/********************************************************************** Java CUP specification for a parser for C-- programs **********************************************************************/ import java_cup.runtime.*; import java.util.*; /* Redefine method syntax_error to give better error messages than just * "Syntax error" */ parser code {: public void syntax_error(Symbol currToken) { if (currToken.value == null) { Errors.fatal(0,0, "Syntax error at end of file"); } else { Errors.fatal(((TokenVal)currToken.value).linenum, ((TokenVal)currToken.value).charnum, "Syntax error"); } System.exit(-1); } :}; /* Terminals (tokens returned by the scanner) */ terminal INT; terminal BOOL; terminal VOID; terminal TokenVal TRUE; terminal TokenVal FALSE; terminal IF; terminal ELSE; terminal WHILE; terminal CIN; terminal COUT; terminal RETURN; terminal IdTokenVal ID; terminal IntLitTokenVal INTLITERAL; terminal StrLitTokenVal STRINGLITERAL; terminal LCURLY; terminal RCURLY; terminal LPAREN; terminal RPAREN; terminal LSQBRACKET; terminal RSQBRACKET; terminal COMMA; terminal ASSIGN; terminal SEMICOLON; terminal PLUS; terminal MINUS; terminal TIMES; terminal DIVIDE; terminal NOT; terminal AND; terminal OR; terminal EQUALS; terminal NOTEQUALS; terminal LESS; terminal GREATER; terminal LESSEQ; terminal GREATEREQ; terminal READ; terminal WRITE; /* Non-terminals */ non terminal ProgramNode program; non terminal LinkedList declList; non terminal LinkedList varDeclList; non terminal DeclNode decl; non terminal VarDeclNode varDecl; non terminal FnDeclNode fnDecl; non terminal FormalsListNode formals; non terminal LinkedList formalsList; non terminal FormalDeclNode formalDecl; non terminal FnBodyNode fnBody; non terminal LinkedList stmtList; non terminal StmtNode stmt; non terminal ExpNode exp; non terminal ExpNode term; non terminal CallExpNode fncall; non terminal LinkedList actualList; non terminal TypeNode type; non terminal ExpNode loc; non terminal IdNode id; /* precedences and associativities of operators */ precedence left OR, AND; precedence nonassoc EQUALS, NOTEQUALS, LESS, GREATER, LESSEQ, GREATEREQ; precedence left PLUS, MINUS; precedence left TIMES, DIVIDE; precedence nonassoc NOT; start with program; /* grammar with actions */ program ::= declList: d {: RESULT = new ProgramNode(new DeclListNode(d)); :} ; declList ::= declList:dl decl:d {: dl.addLast(d); RESULT = dl; :} | /* epsilon */ {: RESULT = new LinkedList(); :} ; varDeclList ::= varDeclList:dl varDecl:d {: dl.addLast(d); RESULT = dl; :} | /* epsilon */ {: RESULT = new LinkedList(); :} ; decl ::= varDecl:v {: RESULT = v; :} | fnDecl:f {: RESULT = f; :} ; varDecl ::= type: t id: i SEMICOLON {: RESULT = new VarDeclNode(t, i, VarDeclNode.NOT_ARRAY); :} | type: t id: i LSQBRACKET INTLITERAL: k RSQBRACKET SEMICOLON {: RESULT = new VarDeclNode(t, i, k.intVal); :} ; fnDecl ::= type:t id:i formals:f fnBody:b {: RESULT = new FnDeclNode(t, i, f, b); :} ; formals ::= LPAREN RPAREN {: RESULT = new FormalsListNode(new LinkedList()); :} | LPAREN formalsList:f RPAREN {: RESULT = new FormalsListNode(f); :} ; formalsList ::= formalDecl:v {: LinkedList L = new LinkedList(); L.addLast(v); RESULT = L; :} | formalDecl:v COMMA formalsList:L {: L.addFirst(v); RESULT = L; :} ; formalDecl ::= type:t id:i {: RESULT = new FormalDeclNode(t, i); :} ; fnBody ::= LCURLY varDeclList:d stmtList:s RCURLY {: RESULT = new FnBodyNode(new DeclListNode(d), new StmtListNode(s)); :} ; stmtList ::= stmtList:L stmt:s {: L.addLast(s); RESULT = L; :} | /* epsilon */ {: RESULT = new LinkedList(); :} ; stmt ::= CIN READ id:i SEMICOLON {: RESULT = new ReadStmtNode(i); :} | CIN READ id:i LSQBRACKET exp: e RSQBRACKET SEMICOLON {: RESULT = new ReadStmtNode(new ArrayExpNode(i, e)); :} | COUT WRITE exp:e SEMICOLON {: RESULT = new WriteStmtNode(e); :} | loc:l ASSIGN exp:e SEMICOLON {: RESULT = new AssignStmtNode(l, e); :} | IF LPAREN exp:e RPAREN LCURLY varDeclList:d stmtList:s RCURLY {: RESULT = new IfStmtNode(e, new DeclListNode(d), new StmtListNode(s)); :} | IF LPAREN exp:e RPAREN LCURLY varDeclList:td stmtList:ts RCURLY ELSE LCURLY varDeclList:ed stmtList:es RCURLY {: RESULT = new IfElseStmtNode(e, new DeclListNode(td), new StmtListNode(ts), new DeclListNode(ed), new StmtListNode(es)); :} | WHILE LPAREN exp:e RPAREN LCURLY varDeclList:d stmtList:l RCURLY {: RESULT = new WhileStmtNode(e, new DeclListNode(d), new StmtListNode(l)); :} | RETURN exp:e SEMICOLON {: RESULT = new ReturnStmtNode(e); :} | RETURN SEMICOLON {: RESULT = new ReturnStmtNode(null); :} | fncall:f SEMICOLON {: RESULT = new CallStmtNode(f); :} ; fncall ::= id:i LPAREN RPAREN // fn call with no args {: RESULT = new CallExpNode(i, new ExpListNode(new LinkedList())); :} | id:i LPAREN actualList:L RPAREN // with args {: RESULT = new CallExpNode(i, new ExpListNode(L)); :} ; exp ::= exp:e1 PLUS exp:e2 {: RESULT = new PlusNode(e1, e2); :} | exp:e1 MINUS exp:e2 {: RESULT = new MinusNode(e1, e2); :} | exp:e1 TIMES exp:e2 {: RESULT = new TimesNode(e1, e2); :} | exp:e1 DIVIDE exp:e2 {: RESULT = new DivideNode(e1, e2); :} | NOT exp:e {: RESULT = new NotNode(e); :} | exp:e1 AND exp:e2 {: RESULT = new AndNode(e1, e2); :} | exp:e1 OR exp:e2 {: RESULT = new OrNode(e1, e2); :} | exp:e1 EQUALS exp:e2 {: RESULT = new EqualsNode(e1, e2); :} | exp:e1 NOTEQUALS exp:e2 {: RESULT = new NotEqualsNode(e1, e2); :} | exp:e1 LESS exp:e2 {: RESULT = new LessNode(e1, e2); :} | exp:e1 GREATER exp:e2 {: RESULT = new GreaterNode(e1, e2); :} | exp:e1 LESSEQ exp:e2 {: RESULT = new LessEqNode(e1, e2); :} | exp:e1 GREATEREQ exp:e2 {: RESULT = new GreaterEqNode(e1, e2); :} | MINUS term:t {: RESULT = new UnaryMinusNode(t); :} | term: t {: RESULT = t; :} ; term ::= loc:l {: RESULT = l; :} | INTLITERAL:i {: RESULT = new IntLitNode(i.linenum, i.charnum, i.intVal); :} | STRINGLITERAL:s {: RESULT = new StringLitNode(s.linenum, s.charnum, s.strVal); :} | TRUE:t {: RESULT = new TrueNode(t.linenum, t.charnum); :} | FALSE:f {: RESULT = new FalseNode(f.linenum, f.charnum); :} | LPAREN exp:e RPAREN {: RESULT = e; :} | fncall:f {: RESULT = f; :} ; actualList ::= exp:e {: LinkedList L = new LinkedList(); L.addLast(e); RESULT = L; :} | actualList:L COMMA exp:e {: L.addLast(e); RESULT = L; :} ; type ::= INT {: RESULT = new IntNode(); :} | BOOL {: RESULT = new BoolNode(); :} | VOID {: RESULT = new VoidNode(); :} ; loc ::= id:i {: RESULT = i; :} | id:i LSQBRACKET exp:e RSQBRACKET {: RESULT = new ArrayExpNode(i, e); :} ; id ::= ID:i {: RESULT = new IdNode(i.linenum, i.charnum, i.idVal); :} ;