-- Example of defined rules in bnfc.
-- Ulf Norell, 2006
-- The core statement language. Nothing funny here.
Assign. Stm ::= Ident "=" Exp ;
Block. Stm ::= "{" [Stm] "}" ;
While. Stm ::= "while" "(" Exp ")" Stm ;
If. Stm ::= "if" "(" Exp ")" Stm "else" Stm "endif" ;
-- We now want to have some syntactic sugar. Note that the labels for
-- these rule all start with a lowercase letter, indicating that they
-- correspond to defined functions rather than nodes in the abstract
-- syntax tree.
if. Stm ::= "if" "(" Exp ")" Stm "endif" ;
for. Stm ::= "for" "(" Stm ";" Exp ";" Stm ")" Stm ;
inc. Stm ::= Ident "++" ;
-- Functions are defined using the 'define' keyword. Definitions have
-- the form 'define f x1 .. xn = e' where e is an expression on applicative
-- form using labels, other defined functions, lists and literals.
define if e s = If e s (Block []) ;
define for i c s b = Block [i, While c (Block [b, s])] ;
define inc x = Assign x (EOp (EVar x) Plus (EInt 1)) ;
terminator Stm ";" ;
-- Another use of defined functions to simplify the abstract syntax for
-- binary operators. Instead of one node for each operator we want to have
-- a general node (EOp) for all binary operator applications.
_. Op ::= Op1;
_. Op ::= Op2;
Less. Op1 ::= "<";
Equal. Op1 ::= "==";
Plus. Op2 ::= "+" ;
Minus. Op2 ::= "-" ;
op. Exp ::= Exp1 Op1 Exp1 ;
op. Exp1 ::= Exp1 Op2 Exp2 ;
EInt. Exp2 ::= Integer ;
EVar. Exp2 ::= Ident ;
-- Care has to be taken to make sure that the pretty printer prints enough
-- parenthesis.
internal EOp. Exp ::= Exp1 Op Exp1 ;
define op e1 o e2 = EOp e1 o e2 ;
coercions Exp 2;