untitled paste

unlisted ⁨3⁩ ⁨files⁩ 2018-12-15 20:31:31 UTC

Makefile

Raw
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

Raw
%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

Raw
%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));
}

%%