import java_cup.runtime.*; import java.io.FileInputStream; parser code {: private Lexer L; :}; init with {: L = new Lexer(new FileInputStream(Main.filename)); :}; scan with {: Token T = L.next(); return new java_cup.runtime.Symbol(T.type, T.first, T.last, T.spelling); :}; terminal CLASS, ELSE, IF, INT, BOOLEAN, RETURN, STATIC, WHILE; terminal String NUM, BOOL, ID; terminal GETS, PLUS, MINUS, TIMES, DIV, MOD; terminal SEMICOLON, COMMA, LPAREN, RPAREN, LBRACE, RBRACE; terminal EQUALS, NOTEQUAL, OR, AND; terminal UNINIT; non terminal ClassDecl, MethodDecls, MethodDecl, Type, FormalParams; non terminal Block, Statements, Statement; start with ClassDecl; /******************** High-level structures *********************/ ClassDecl ::= CLASS ID:name LBRACE MethodDecls:mds RBRACE {:RESULT = new ClassDecl(new Id(name), (MethodDecls)mds); :}; MethodDecls ::= MethodDecls:mds MethodDecl:md {: ((MethodDecls)mds).append((MethodDecl)md); RESULT = mds; :} | /* empty */ {: RESULT = new MethodDecls(); :}; MethodDecl ::= STATIC Type:type ID:name LPAREN FormalParams:fps RPAREN Block:block {: RESULT = new MethodDecl((Id)type, new Id(name), (FormalParams)fps, (Block)block); :}; FormalParams ::= /* empty */ {: RESULT = new FormalParams(); :}; Type ::= INT:i {: RESULT = new Id("int"); :}; /******************** Statements *********************/ Block ::= LBRACE Statements:ss RBRACE {: RESULT = new Block((Statements)ss); :}; Statements ::= Statements:ss Statement:s {: ((Statements)ss).append((Statement)s); RESULT = ss; :} | /* empty */ {: RESULT = new Statements(); :}; Statement ::= SEMICOLON {: RESULT = null; :}; /* Making Statement empty leads to shift-reduce conflict. See Levine,Mason,Brown, p. 232.*/ /******************** Expressions *********************/