untitled paste

unlisted ⁨3⁩ ⁨files⁩ 2018-12-08 15:15:27 UTC

Makefile

Raw
# Public domain
# Tested with Bison) 3.2.2 and Flex 2.6.4
# Note that our scanner.ll contains C++ code fragments, but we run Flex in C mode anyway. I. e. we pass C++ code to Flex, but trick it to think it processes C code. Then Flex generates code, which (at its optinion) is C code, but in fact this is C++ code (because it contains unmodified C++ code fragments, written by us), so we write it to file with .cc extension and pass to C++ compiler
 
all: a.out
 
lex.yy.cc lex.yy.hh: scanner.ll
	flex --header-file=lex.yy.hh -o lex.yy.cc scanner.ll
 
parser.tab.cc parser.tab.hh: parser.yy
	bison -do parser.tab.cc parser.yy
 
a.out: lex.yy.cc parser.tab.cc
	c++ lex.yy.cc parser.tab.cc
 
clean:
	rm -f lex.yy.* parser.tab.* stack.hh a.out

parser.yy

Raw
%skeleton "lalr1.cc"
 
%code requires{
// Here you should insert declarations for types you will use in AST, if you will build AST. This will ensure that they will go both to generated parser and to file parser.tab.hh. Then you will include parser.tab.hh everywhere you need this declarations
}
 
%{
#include <iostream>
 
#include "parser.tab.hh"
 
int
yylex (yy::parser::semantic_type *yylval);
 
void
yy::parser::error (const std::string &m)
{
  std::cerr << m << std::endl;
}
%}
 
%define api.value.type variant
 
%start document
 
%token <int> NUMBER
 
%%
 
%left '+' '-';
%left '*' '/';
 
%type <int> expr;
 
expr:
  NUMBER
    { $$ = $1; }
| expr '+' expr
    { $$ = $1 + $3; }
| expr '-' expr
    { $$ = $1 - $3; }
| expr '*' expr
    { $$ = $1 * $3; }
| expr '/' expr
    { $$ = $1 / $3; }
| '(' expr ')'
    { $$ = $2; }
 
document:
  expr
    { std::cout << $1 << std::endl; }
 
%%
 
int
main ()
{
  yy::parser p;
 
  if (p.parse () != 0)
    {
      return EXIT_FAILURE;
    }
 
  return EXIT_SUCCESS;
}

scanner.ll

Raw
%option noyywrap
%option warn nodefault
 
%{
#include <stdlib.h>
 
#include <stdexcept>
 
#include "parser.tab.hh"
 
#define YY_DECL int \
  yylex (yy::parser::semantic_type *yylval)
%}
 
%%
 
[-+*/()] {
  return yytext[0];
}
 
[0-9]+ {
  yylval->build (atoi (yytext));
  return yy::parser::token::NUMBER;
}
 
[ \t\n]+ {
}
 
. {
  throw std::runtime_error ("Unknown character");
}
 
%%