// gcom.gr // parser for guarded command example language verbatim { #include "str.h" // stringf #include "ast.h" // AST declarations #include // getenv, atoi, putenv #include // printf } // the parser context class is useful in large examples; // an empty one will suffice here context_class GComContext : public UserActions { public: // given a lexer-allocated string, make a 'string', and // deallocate the lexer-created copy static inline string copyAndFree(char *x) { string ret(x); delete x; return ret; } }; // pull in the tokens generated from lexer.h terminals { include("tokens.tok") // declare token sval types token(int) TOK_LITERAL; token(char*) TOK_IDENTIFIER; precedence { // high precedence left 60 "*"; left 50 "+" "-"; left 40 "!"; // ! has higher precedence than /\ and \/ left 30 TOK_AND; // /\ has higher precedence than \/ left 20 TOK_OR; left 10 ";" "#"; // precedence is irrelvant // low precedence } } // now the grammar; the first symbol is the start symbol nonterm(Stmt*) Start { -> s:Stmt { return s; } } nonterm(AExp*) AExp { -> n:TOK_LITERAL { return new A_lit(n); } -> x:TOK_IDENTIFIER { return new A_var(copyAndFree(x)); } -> a1:AExp "+" a2:AExp { return new A_bin(a1, AO_PLUS, a2); } -> a1:AExp "-" a2:AExp { return new A_bin(a1, AO_MINUS, a2); } -> a1:AExp "*" a2:AExp { return new A_bin(a1, AO_TIMES, a2); } -> "(" a:AExp ")" { return a; } } nonterm(BExp*) BExp { -> "true" { return new B_lit(true); } -> "false" { return new B_lit(false); } -> a1:AExp "=" a2:AExp { return new B_pred(a1, BP_EQUAL, a2); } -> a1:AExp "<" a2:AExp { return new B_pred(a1, BP_LESS, a2); } -> "!" b:BExp { return new B_not(b); } -> b1:BExp TOK_AND b2:BExp { return new B_bin(b1, BO_AND, b2); } -> b1:BExp TOK_OR b2:BExp { return new B_bin(b1, BO_OR, b2); } -> "(" b:BExp ")" { return b; } } nonterm(Stmt*) Stmt { -> "skip" { return new S_skip; } -> "abort" { return new S_abort; } -> "print" x:TOK_IDENTIFIER { return new S_print(copyAndFree(x)); } -> x:TOK_IDENTIFIER ":=" a:AExp { return new S_assign(copyAndFree(x), a); } -> s1:Stmt ";" s2:Stmt { return new S_seq(s1, s2); } -> "if" g:GCom "fi" { return new S_if(g); } -> "do" g:GCom "od" { return new S_do(g); } } nonterm(GCom*) GCom { -> b:BExp "->" s:Stmt { return new G_stmt(b, s); } -> g1:GCom "#" g2:GCom { return new G_seq(g1, g2); } }