User Tools

Site Tools


Compiler minimal sample with Re/flex and bison

lexer.l
%top{
#include "parser.hh"
%}
 
%option bison-cc
%option bison-locations
%option noyywrap
%option namespace="compiler"
%option lexer="lexer"
%option lex="yylex"
%option header-file="lexer.hh"
%option bison-cc-namespace="compiler"
 
NUMBER          [[:digit:]]+
WORD            [[:alnum:]]+
LET             =
DELIM           ;
NL              .|\n
SPACE           [\t ]
%%
 
{NUMBER}        { yylval.num = atoi(text());   return compiler::parser::token::NUMBER; }
{WORD}          { yylval.str = strdup(text()); return compiler::parser::token::STRING; }
{DELIM}          { return compiler::parser::token::DELIM; }
{LET}              { return compiler::parser::token::LET; }
{SPACE}         {}
NL                 {}
%%
parser.y
%skeleton "lalr1.cc"
%require  "3.2"
%language "c++"
 
%defines "parser.hh"
%output "parser.cc"
%define api.namespace { compiler }
 
%code requires{
    #include <sstream>
 
    namespace compiler {
            class lexer;
    }
    namespace compiler {
            class driver;
    }
}
 
%code{
    #include "lexer.hh"
 
    #undef yylex
    #define yylex lexer.yylex
 
    namespace compiler {
        class driver {
            private:
                compiler::lexer lexer;
                compiler::parser *parser;
            public:
                driver(reflex::Input in) : lexer(in), parser(new compiler::parser(lexer, *this)) { }
                ~driver() { 
                    delete parser; 
                }
                int parse() { 
                    return parser->parse(); 
                }
        };
    }
}
 
%locations
%parse-param { compiler::lexer &lexer }
%parse-param { compiler::driver &driver }
 
%union {
    int   num;
    char *str;
}
 
%token <str> STRING
%token <num> NUMBER
%token LET
%token DELIM
 
%%
assignments : assignment
            | assignment assignments
            ;
assignment  : STRING LET NUMBER delims { std::cout << "(setf " << $1 << " " << $3 << ")\n"; }
            ;
delims  : DELIM
        | DELIM delims
        ;
%%
 
int main() {
    std::stringstream iss;
    iss << "a = 12;\n";
    iss << "b = 32;;  c =\n 18;\n";
    iss << "b - 32;\n";
 
    std::stringstream oss;
 
    reflex::Input i(iss);
    compiler::driver driver(i);
    return driver.parse();
}
 
void compiler::parser::error(const location_type& loc, const std::string& msg) {
    std::cerr << msg << " at " << loc << std::endl;
}
Makefile
CXX=	c++
 
all: compiler
 
OBJS+= parser.o lexer.o
LOCALBASE= /usr/local
CFLAGS+= -Wall -I${LOCALBASE}/include
LDFLAGS+= -L${LOCALBASE}/lib -lreflex
 
compiler: ${OBJS}
	${CXX} -o $@ ${OBJS} ${LDFLAGS}
 
lexer.o: lexer.cc parser.cc
	${CXX} ${CFLAGS} -c -o $@ $<
 
lexer.cc: lexer.l
	reflex -o $@ $<
 
parser.o: parser.cc lexer.cc
	${CXX} ${CFLAGS} -c -o $@ $<
 
parser.cc: parser.y
	bison -o $@ $<
 
clean:
	rm -f lexer.cc lexer.hh 
	rm -f parser.cc parser.hh location.hh position.hh stack.hh
	rm -f compiler *.o *~

build and run

input as

    iss << "a = 12;\n";
    iss << "b = 32;;  c =\n 18;\n";
    iss << "b - 32;\n";
$ make
bison -o parser.cc parser.y
reflex -o lexer.cc lexer.l
c++ -Wall -I/usr/local/include -c -o parser.o parser.cc
c++ -Wall -I/usr/local/include -c -o lexer.o lexer.cc
c++ -o compiler parser.o lexer.o -L/usr/local/lib -lreflex

$ ./compiler
(setf a 12)
(setf b 32)
(setf c 18)

First PagePrevious PageBack to overviewNext PageLast Page