-- 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;