101 lines
2 KiB
Plaintext
101 lines
2 KiB
Plaintext
// At least 3.2 to get rid of `stack.hh`
|
|
%require "3.2"
|
|
// Let's be modern
|
|
%language "C++"
|
|
|
|
// LALR is fine for our purposes
|
|
%skeleton "lalr1.cc"
|
|
|
|
// Write a header with our parser-related declarations
|
|
%defines
|
|
|
|
// Safer than unions...
|
|
%define api.value.type variant
|
|
// Define constructors for each token
|
|
%define api.token.constructor
|
|
|
|
// Ambiguity is forbidden
|
|
%expect 0
|
|
|
|
// Prefix all the tokens with TOK_ to avoid colisions.
|
|
%define api.token.prefix {TOK_}
|
|
// Track locations
|
|
%locations
|
|
|
|
// Enable parse tracing
|
|
%define parse.trace
|
|
// Give detailled error messages
|
|
%define parse.error detailed
|
|
// Correct look-ahead to avoid erroneous error messages
|
|
%define parse.lac full
|
|
|
|
// Code that should be in the header
|
|
%code requires {
|
|
// Forward declare our driver
|
|
namespace abacus::parser {
|
|
class ParserDriver;
|
|
} // namespace abacus::parser
|
|
|
|
#include "bignum.hh" // FIXME: I would like `bignum/bignum.hh` path instead...
|
|
}
|
|
|
|
%code provides {
|
|
// Forward ParserDriver to scanner
|
|
#define YY_DECL \
|
|
yy::parser::symbol_type yylex(::abacus::parser::ParserDriver& drv)
|
|
YY_DECL;
|
|
}
|
|
|
|
// Only include the actual ParserDriver class declaration in source code
|
|
%code {
|
|
#include "parser-driver.hh"
|
|
}
|
|
|
|
// Use the driver to carry context back-and-forth
|
|
%param { abacus::parser::ParserDriver& drv }
|
|
|
|
%token EOF 0 "end-of-file"
|
|
|
|
%token <abacus::bignum::BigNum> NUM "number"
|
|
|
|
// Use `<<` to print everything
|
|
%printer { yyo << $$; } <*>;
|
|
|
|
%token
|
|
PLUS "+"
|
|
MINUS "-"
|
|
TIMES "*"
|
|
DIVIDE "/"
|
|
LPAREN "("
|
|
RPAREN ")"
|
|
|
|
// Let's define the usual PEMDAS rules
|
|
%left PLUS MINUS
|
|
%left TIMES DIVIDE
|
|
%precedence UNARY
|
|
|
|
%type <abacus::bignum::BigNum> input exp
|
|
|
|
%%
|
|
|
|
input:
|
|
exp EOF
|
|
;
|
|
|
|
exp:
|
|
NUM { $$ = $1; }
|
|
| exp PLUS exp { $$ = $1 + $3; }
|
|
| exp MINUS exp { $$ = $1 - $3; }
|
|
| exp TIMES exp { $$ = $1 * $3; }
|
|
| exp DIVIDE exp { $$ = $1 / $3; }
|
|
| PLUS exp %prec UNARY { $$ = $2; }
|
|
| MINUS exp %prec UNARY { $$ = -$2; }
|
|
| LPAREN exp RPAREN { $$ = $2; }
|
|
;
|
|
|
|
%%
|
|
|
|
void yy::parser::error(location_type const& l, std::string const& m) {
|
|
std::cerr << l << ": " << m << '\n';
|
|
}
|