class P extends Parser; options { buildAST=true; } prog : "begin"! stmts "end"! ; stmts : ((stmt SEMI!)*) { #stmts = #([BLOCK,"block"], #stmts);} ; stmt : id ASSIGN^ expr |! "if"! e:expr "then"! s:stmts "end"! "if"! { #stmt = #([IFTHEN,"ifthen"], #e, #s);} | "read"^ LPAREN! id (COMMA! id)* RPAREN! | "write"^ LPAREN! expr (COMMA! expr)* RPAREN! ; expr : term ( (EQ^ | NEQ^) term)* ; term : factor ((PLUS^ | MINUS^) factor)* ; factor: primary ((TIMES^ | DIVIDE^) primary)* ; primary : MINUS^ (primary) | LPAREN! expr RPAREN! // {#primary = #expr ;} | id | NUM ; id : ID ; class L extends Lexer; tokens { PROGRAM; IFTHEN; BLOCK; } ID : ('a'..'z')+ ; ASSIGN : ":=" ; EQ : '=' ; NEQ : "<>" ; TIMES : '*' ; DIVIDE : '/' ; PLUS : '+' ; MINUS : '-' ; LPAREN : '(' ; RPAREN : ')' ; SEMI : ';' ; COMMA : ',' ; NUM : ( '0'..'9' )+ ; WS : (' ' | ('\r' '\n' | '\n') { newline(); } | '\t') {$setType(Token.SKIP);} //ignore this token ;