Makefile
all:
flex -o lex.yy.cpp scanner.lpp && bison -do parser.tab.cpp parser.ypp && g++ lex.yy.cpp parser.tab.cpp && echo 2 + 2 | ./a.out # Should print 4
parser.ypp
%skeleton "glr.cc"
%define parse.error verbose
%code provides
{
#define YY_DECL int yylex (yy::parser::semantic_type *yylval)
YY_DECL;
}
%code top
{
#include <iostream>
}
%define api.value.type union
%token <int> NUMBER
%%
_start:
expr
{
std::cout << $1 << "\n";
}
%type <int> expr;
expr:
product
{
$$ = $1;
}
| expr '+' product
{
$$ = $1 + $3;
}
| expr '-' product
{
$$ = $1 - $3;
}
%type <int> product;
product:
prim
{
$$ = $1;
}
| product '*' prim
{
$$ = $1 * $3;
}
| product '/' prim
{
$$ = $1 / $3;
}
%type <int> prim;
prim:
NUMBER
{
$$ = $1;
}
| '(' expr ')'
{
$$ = $2;
}
%%
void
yy::parser::error (const std::string &m)
{
std::cerr << m << "\n";
}
int
main (void)
{
try
{
yy::parser p;
if (p.parse () != 0)
{
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
catch (const std::exception &e)
{
std::cerr << "Exception from main: " << e.what () << "\n";
return EXIT_FAILURE;
}
catch (...)
{
std::cerr << "Exception from main\n";
return EXIT_FAILURE;
}
}
scanner.lpp
%option noyywrap
%option warn nodefault
%{
#include <stdlib.h>
#include <string>
#include "parser.tab.hpp"
%}
%%
[-+*/()]* {
return yytext[0];
}
[0-9][0-9]* {
yylval->NUMBER = atoi (yytext);
return yy::parser::token::NUMBER;
}
[ \t\n]+ {
}
. {
throw yy::parser::syntax_error ("Invalid character: " + std::string (yytext));
}
%%