Code snippets‎ > ‎C++‎ > ‎

Bison and Flex

A simple calculator parser that uses Bison and Flex

main.cc
#include <generic.h>
#include <assert.h>

int main(int argc, char *argv[]) {
  if ( argc > 1 ) {
    vex_in = fopen( argv[1], "r" );
    assert(vex_in != NULL);
  }

  return vex_parse ();
}

generic.h
#ifndef GENERIC_H
#define GENERIC_H

#define YYSTYPE double
#include <parser.tab.hh>
#include <stdio.h>

extern FILE *vex_in, *vex_out;
int vex_lex();
int vex_parse();
void vex_error (char const *s);

#endif // GENERIC_H


lex.yy
%option noyywrap
%option prefix="vex_"

%{
#include "generic.h"
#include <stdlib.h>
#include <iostream>
%}

DIGIT [0-9]

%%

{DIGIT}+|{DIGIT}+"."{DIGIT}*|"."{DIGIT}* 
{
  vex_lval = atof( yytext );
  return NUM;
}

\+ return PLUS;
- return MINUS;
\* return MULT;
\/ return DIV;
\n return ENDL;
\^ return EXP;
n return NEG;

[ \t]+ /* eat up whitespace */


bison.yy
/* Reverse polish notation calculator. */

%file-prefix="parser"
%name-prefix="vex_"

%defines
%{
#include <math.h>
#include <stdio.h>
#include <iostream>
#include <generic.h>
%}

%token NUM PLUS MINUS MULT DIV ENDL EXP NEG

%{
#include <math.h>
#include <stdio.h>
#include <iostream>
%}

%%

/* Grammar rules and actions follow. */
input: /* empty */ | input line ;
line: ENDL | exp ENDL {
  std::cout << $1 << std::endl;
};
exp: NUM { $ = $1; }
| exp exp PLUS { $ = $1 + $2;}
| exp exp MINUS { $ = $1 - $2; }
| exp exp MULT { $ = $1 * $2; }
| exp exp DIV { $ = $1 / $2; }
/* Exponentiation */
| exp exp EXP { $ = pow ($1, $2); }
/* Unary minus */
| exp NEG { $ = -$1; };

%%

void vex_error (char const *s) {
  fprintf (stderr, "Error: %s\n", s);
}


test.in
3. 4 + .3 4 + 3.0 4 + 2 .5 ^ 2 .5 ^ * 5. .5 + 5. - .5 / 5 n

Makefile
CXXFLAGS += -I.

parser: parser.tab.o scanner.yy.o main.o
    g++ -o parser parser.tab.o scanner.yy.o main.o -ly

main.o: main.cc parser.tab.hh


scanner.yy.cc:
    lex.yy flex --header-file=scanner.yy.h -t $<
 > $@

parser.tab.cc: bison.yy
    bison bison.yy

parser.tab.hh: bison.yy
    bison -d bison.yy


clean:
    rm -f *.o scanner.yy.cc parser.tab.* parser

ċ
bison_flex.tgz
(4k)
Nico Kruithof,
Jul 19, 2011, 6:23 AM
Comments