grammar CMinus; options { output=AST; } tokens { GLOBALS; FUNCTIONS; FUNCTION; PARAMS; PARAM; BLOCK; LOCALS; STATEMENTS; FOR; INIT; COND; STMT; VAR; } program: (declaration)+ ; declaration: variable -> ^(GLOBALS variable) | function -> ^(FUNCTIONS function) ; variable: type declarator SEMI -> ^(VAR type declarator) ; function: type ID LPAREN (formalParameter (COMMA formalParameter)* )? RPAREN block -> ^(FUNCTION type ID ^(PARAMS formalParameter+) ^(BLOCK block)) ; formalParameter: type declarator -> ^(PARAM type declarator) ; block: LCURLY (variable)* (stat)* RCURLY -> ^(LOCALS variable*) ^(STATEMENTS stat*) ; stat: forStat | expr SEMI! | block | assignStat SEMI! | SEMI! ; forStat: 'for' LPAREN e1=assignStat SEMI e2=expr SEMI e3=assignStat RPAREN block -> ^(FOR ^(INIT $e1) ^(COND $e2) ^(STMT $e3) ^(BLOCK block)) ; assignStat: ID ASSIGN^ expr ; expr: condExpr ; condExpr: aexpr ( (EQUALS | LT)^ aexpr )? ; aexpr: atom ( PLUS^ atom )* ; atom: ID | INT | LPAREN expr RPAREN ; type: 'int' | 'char' | ID ; declarator: ID ; PLUS: '+' ; SEMI: ';' ; EQUALS: '==' ; LT: '<' ; LPAREN: '(' ; RPAREN: ')' ; COMMA: ',' ; LCURLY: '{' ; RCURLY: '}' ; ASSIGN: '=' ; ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* ; INT: ('0'..'9')+ ; WS: ( ' ' | '\t' | '\n' | '\r')+ {$channel=HIDDEN;} ;