package MCC; import MCC.IR.ParseNode; import MCC.IR.ParseNodeVector; import java.util.*; action code {: public static boolean errors; public static boolean debug; // debugMessage: writes debug production message only if debug = true void debugMessage (String production) { if (debug) { System.out.println("Applying production: " + production); } } String unescape (String str) { StringBuffer sb = new StringBuffer(); int i; // Note that we skip the first and last characters (they're "'s) for (i = 1; i < str.length() - 1; i++) { if (str.charAt(i) == '\\') { i++; switch (str.charAt(i)) { case '\"': sb.append('\"'); break; case '\'': sb.append('\''); break; case '\\': sb.append('\\'); break; case 't': sb.append('\t'); break; case 'n': sb.append('\n'); break; default: System.err.print("Error in string literal: "); System.err.println(str.charAt(i)); System.err.println("Aborting..."); break; } } else { sb.append(str.charAt(i)); } } return sb.toString(); } :} init with {: :} parser code {: public String filename; public void syntax_error (java_cup.runtime.Symbol current) { CUP$MDLParser$actions.errors = true; Symbol symbol = (Symbol) current; //System.out.println("current.value = "+current.value + " " + current.value.equals("true")); //System.out.println("current = " + current); boolean isInteger = true; try{ Integer.parseInt(current.value.toString()); } catch(NumberFormatException e) { isInteger = false;} report_error(filename+":"+(symbol.line+1)+": Syntax error at column " + (LineCount.getColumn(symbol.left)+1) +": " + current.value, current); /* if (current.value.equals("true") || isInteger) System.out.println("Did you mean literal("+current.value+")?"); */ if (LineCount.getColumn(symbol.left) == 0) System.out.println("Did you forget a semicolon on the previous line?"); System.out.println(); System.exit(0); } public void report_fatal_error (String message, Object info) { done_parsing(); report_error(message, info); CUP$MDLParser$actions.errors = true; } public int curPos () { return cur_token.left; } public int curLine (int back) { Stack st = new Stack(); int i; for (i = 0; i < back; i++) { st.push(stack.pop()); } java_cup.runtime.Symbol s; s = (java_cup.runtime.Symbol) st.peek(); for (i = 0; i < back; i++) { stack.push(st.pop()); } return LineCount.getLine(s.left); } :} // TERMINALS ///////////////////////////////////////////////////////////// terminal BAD; terminal String ID; terminal String DECIMAL; terminal String CHAR; terminal String STRING; terminal OPENBRACE; terminal CLOSEBRACE; terminal OPENPAREN; terminal CLOSEPAREN; terminal OPENBRACKET; terminal CLOSEBRACKET; terminal ADD; terminal SUB; terminal MULT; terminal DIV; terminal SUM; terminal NOT; terminal LT; terminal GT; terminal LE; terminal GE; terminal EQ; terminal NE; terminal FORALL; terminal IN; terminal INTEST; terminal COMMA; terminal SIZEOF; terminal DOT; terminal DOTINV; terminal AND; terminal OR; terminal LITERAL; terminal IMPLIES; terminal TRUE; terminal FALSE; terminal ISVALID; terminal FOR; terminal TO; terminal CAST; terminal PARAM; terminal STRUCTURE; terminal RESERVED; terminal BIT; terminal BYTE; terminal SHORT; terminal LABEL; terminal INT; terminal SUBTYPE; terminal SUBCLASS; terminal OF; terminal SEMICOLON; terminal COLON; terminal SET; terminal ARROW; terminal MANY; terminal BAR; terminal PARTITION; terminal ELEMENT; terminal DELAY; terminal STATIC; terminal NULL; terminal CRASH; // NON-TERMINALS ///////////////////////////////////////////////////////// /* TYPE NAME ------------------------------------------------------------------------*/ nonterminal ParseNode rules; nonterminal ParseNode rule; nonterminal ParseNode ruletype; nonterminal ParseNode optquantifiers; nonterminal ParseNode quantifiers; nonterminal ParseNode quantifier; nonterminal ParseNode inclusion; nonterminal ParseNode expr; nonterminal ParseNode literal; nonterminal ParseNode simple_expr; nonterminal ParseNode location; nonterminal ParseNode set; nonterminal ParseNode listofliterals; precedence nonassoc OR; precedence nonassoc AND; precedence nonassoc EQ, NE; precedence nonassoc LT, LE, GE, GT; precedence left INTEST; precedence left ADD, SUB; precedence left MULT, DIV; precedence left NOT; precedence left DOT; // PRODUCTION RULES ///////////////////////////////////////////////////// start with rules; rules ::= rules:rules rule:rule {: debugMessage(PRODSTRING); rules.addChild(rule); RESULT = rules; :} | rule:rule {: debugMessage(PRODSTRING); ParseNode rules = new ParseNode("rules", parser.curLine(1)); rules.addChild(rule); RESULT = rules; :} ; rule ::= ruletype:ruletype OPENBRACKET optquantifiers:quantifiers CLOSEBRACKET COMMA expr:guard IMPLIES inclusion:inclusion SEMICOLON {: debugMessage(PRODSTRING); ParseNode rule = new ParseNode("rule", parser.curLine(9)); if (ruletype != null) { rule.addChild(ruletype); } if (quantifiers != null) { rule.addChild(quantifiers); } rule.addChild(guard); rule.addChild(inclusion); RESULT = rule; :} ; ruletype ::= STATIC {: debugMessage(PRODSTRING); RESULT = new ParseNode("static", parser.curLine(1)); :} | DELAY {: debugMessage(PRODSTRING); RESULT = new ParseNode("delay", parser.curLine(1)); :} | /* nothing */ {: debugMessage(PRODSTRING); RESULT = null; :} ; optquantifiers ::= quantifiers:quantifiers {: debugMessage(PRODSTRING); RESULT = quantifiers; :} | /* nothing */ {: debugMessage(PRODSTRING); RESULT = null; :} ; quantifiers ::= quantifiers:quantifiers COMMA quantifier:quantifier {: debugMessage(PRODSTRING); quantifiers.addChild(quantifier); RESULT = quantifiers; :} | quantifier:quantifier {: debugMessage(PRODSTRING); ParseNode quantifiers = new ParseNode("quantifiers", parser.curLine(1)); quantifiers.addChild(quantifier); RESULT = quantifiers; :} ; quantifier ::= FORALL ID:var IN set:set {: debugMessage(PRODSTRING); ParseNode q = new ParseNode("quantifier", parser.curLine(4)); q.addChild("forall", parser.curLine(4)); q.addChild("var", parser.curLine(3)).addChild(var); q.addChild(set); RESULT = q; :} | FORALL LT ID:r1 COMMA ID:r2 GT IN ID:relation {: debugMessage(PRODSTRING); ParseNode q = new ParseNode("quantifier", parser.curLine(7)); q.addChild("relation", parser.curLine(1)).addChild(relation); q.addChild("left", parser.curLine(5)).addChild(r1); q.addChild("right", parser.curLine(3)).addChild(r2); RESULT = q; :} | FOR ID:var EQ expr:lower TO expr:upper {: debugMessage(PRODSTRING); ParseNode q = new ParseNode("quantifier", parser.curLine(5)); q.addChild("for"); q.addChild("var", parser.curLine(4)).addChild(var); q.addChild("lower", parser.curLine(3)).addChild(lower); q.addChild("upper", parser.curLine(1)).addChild(upper); RESULT = q; :} ; inclusion ::= expr:expr IN ID:setname {: debugMessage(PRODSTRING); ParseNode set = (new ParseNode("inclusion", parser.curLine(3))).addChild("set"); set.addChild(expr); set.addChild("name", parser.curLine(1)).addChild(setname); RESULT = set.getRoot(); :} | LT expr:r1 COMMA expr:r2 GT IN ID:relationname {: debugMessage(PRODSTRING); ParseNode relation = (new ParseNode("inclusion", parser.curLine(7))).addChild("relation"); relation.addChild("left").addChild(r1); relation.addChild("right").addChild(r2); relation.addChild("name", parser.curLine(1)).addChild(relationname); RESULT = relation.getRoot(); :} ; simple_expr ::= location:location {: debugMessage(PRODSTRING); ParseNode se = new ParseNode("simple_expr", parser.curLine(1)); se.addChild(location); RESULT = se; :} ; location ::= ID:var {: debugMessage(PRODSTRING); ParseNode loc = new ParseNode("location", parser.curLine(1)); loc.addChild("var").addChild(var); RESULT = loc; :} | simple_expr:dotexpr DOT ID:field {: debugMessage(PRODSTRING); ParseNode dot = (new ParseNode("location", parser.curLine(3))).addChild("dot"); dot.addChild(dotexpr); dot.addChild("field", parser.curLine(1)).addChild(field); RESULT = dot.getRoot(); :} | simple_expr:dotexpr DOT ID:field OPENBRACKET expr:index CLOSEBRACKET {: debugMessage(PRODSTRING); ParseNode dot = (new ParseNode("location", parser.curLine(6))).addChild("dot"); dot.addChild(dotexpr); dot.addChild("field", parser.curLine(4)).addChild(field); dot.addChild("index", parser.curLine(2)).addChild(index); RESULT = dot.getRoot(); :} | CAST OPENPAREN ID:type COMMA simple_expr:expr CLOSEPAREN {: debugMessage(PRODSTRING); ParseNode cast = (new ParseNode("location", parser.curLine(6))).addChild("cast"); cast.addChild("type").addChild(type); cast.addChild(expr); RESULT = cast.getRoot(); :} ; expr ::= simple_expr:se {: debugMessage(PRODSTRING); ParseNode expr = new ParseNode("expr", parser.curLine(1)); expr.addChild(se); RESULT = expr; :} | expr:expr INTEST ID:setname {: debugMessage(PRODSTRING); ParseNode elementof = (new ParseNode("expr", parser.curLine(3))).addChild("elementof"); elementof.addChild(expr); elementof.addChild("name").addChild(setname); RESULT = elementof.getRoot(); :} | LT expr:r1 COMMA expr:r2 GT INTEST ID:relationname {: debugMessage(PRODSTRING); ParseNode tupleof = (new ParseNode("expr", parser.curLine(7))).addChild("tupleof"); tupleof.addChild("left").addChild(r1); tupleof.addChild("right").addChild(r2); tupleof.addChild("name").addChild(relationname); RESULT = tupleof.getRoot(); :} | OPENPAREN expr:expr CLOSEPAREN {: debugMessage(PRODSTRING); RESULT = expr; :} | literal:literal {: debugMessage(PRODSTRING); ParseNode expr = new ParseNode("expr", parser.curLine(4)); expr.addChild(literal); RESULT = expr; :} | expr:leftexpr LT expr:rightexpr {: debugMessage(PRODSTRING); ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator"); bool.addChild("op").addChild("lt"); bool.addChild("left", parser.curLine(3)).addChild(leftexpr); bool.addChild("right", parser.curLine(1)).addChild(rightexpr); RESULT = bool.getRoot(); :} | expr:leftexpr LE expr:rightexpr {: debugMessage(PRODSTRING); ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator"); bool.addChild("op").addChild("le"); bool.addChild("left", parser.curLine(3)).addChild(leftexpr); bool.addChild("right", parser.curLine(1)).addChild(rightexpr); RESULT = bool.getRoot(); :} | expr:leftexpr GT expr:rightexpr {: debugMessage(PRODSTRING); ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator"); bool.addChild("op").addChild("gt"); bool.addChild("left", parser.curLine(3)).addChild(leftexpr); bool.addChild("right", parser.curLine(1)).addChild(rightexpr); RESULT = bool.getRoot(); :} | expr:leftexpr GE expr:rightexpr {: debugMessage(PRODSTRING); ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator"); bool.addChild("op").addChild("ge"); bool.addChild("left", parser.curLine(3)).addChild(leftexpr); bool.addChild("right", parser.curLine(1)).addChild(rightexpr); RESULT = bool.getRoot(); :} | expr:leftexpr EQ expr:rightexpr {: debugMessage(PRODSTRING); ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator"); bool.addChild("op").addChild("eq"); bool.addChild("left", parser.curLine(3)).addChild(leftexpr); bool.addChild("right", parser.curLine(1)).addChild(rightexpr); RESULT = bool.getRoot(); :} | expr:leftexpr NE expr:rightexpr {: debugMessage(PRODSTRING); ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator"); bool.addChild("op").addChild("ne"); bool.addChild("left", parser.curLine(3)).addChild(leftexpr); bool.addChild("right", parser.curLine(1)).addChild(rightexpr); RESULT = bool.getRoot(); :} | expr:leftexpr ADD expr:rightexpr {: debugMessage(PRODSTRING); ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator"); bool.addChild("op").addChild("add"); bool.addChild("left", parser.curLine(3)).addChild(leftexpr); bool.addChild("right", parser.curLine(1)).addChild(rightexpr); RESULT = bool.getRoot(); :} | expr:leftexpr SUB expr:rightexpr {: debugMessage(PRODSTRING); ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator"); bool.addChild("op").addChild("sub"); bool.addChild("left", parser.curLine(3)).addChild(leftexpr); bool.addChild("right", parser.curLine(1)).addChild(rightexpr); RESULT = bool.getRoot(); :} | expr:leftexpr DIV expr:rightexpr {: debugMessage(PRODSTRING); ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator"); bool.addChild("op").addChild("div"); bool.addChild("left", parser.curLine(3)).addChild(leftexpr); bool.addChild("right", parser.curLine(1)).addChild(rightexpr); RESULT = bool.getRoot(); :} | expr:leftexpr MULT expr:rightexpr {: debugMessage(PRODSTRING); ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator"); bool.addChild("op").addChild("mult"); bool.addChild("left", parser.curLine(3)).addChild(leftexpr); bool.addChild("right", parser.curLine(1)).addChild(rightexpr); RESULT = bool.getRoot(); :} | expr:leftexpr AND expr:rightexpr {: debugMessage(PRODSTRING); ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator"); bool.addChild("op").addChild("and"); bool.addChild("left", parser.curLine(3)).addChild(leftexpr); bool.addChild("right", parser.curLine(1)).addChild(rightexpr); RESULT = bool.getRoot(); :} | expr:leftexpr OR expr:rightexpr {: debugMessage(PRODSTRING); ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator"); bool.addChild("op").addChild("or"); bool.addChild("left", parser.curLine(3)).addChild(leftexpr); bool.addChild("right", parser.curLine(1)).addChild(rightexpr); RESULT = bool.getRoot(); :} | NOT expr:expr {: debugMessage(PRODSTRING); ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator"); bool.addChild("op").addChild("not"); bool.addChild("left").addChild(expr); RESULT = bool.getRoot(); :} | ISVALID OPENPAREN expr:innerexpr CLOSEPAREN {: debugMessage(PRODSTRING); ParseNode expr = new ParseNode("expr", parser.curLine(4)); expr.addChild("isvalid").addChild(innerexpr); RESULT = expr; :} | ISVALID OPENPAREN expr:innerexpr COMMA ID:type CLOSEPAREN {: debugMessage(PRODSTRING); ParseNode isvalid = (new ParseNode("expr", parser.curLine(6))).addChild("isvalid"); isvalid.addChild(innerexpr); isvalid.addChild("type", parser.curLine(2)).addChild(type); RESULT = isvalid.getRoot(); :} ; /** standard *********************************/ literal ::= TRUE {: debugMessage(PRODSTRING); RESULT = (new ParseNode("literal", parser.curLine(1))).addChild("boolean").addChild("true").getRoot(); :} | FALSE {: debugMessage(PRODSTRING); RESULT = (new ParseNode("literal", parser.curLine(1))).addChild("boolean").addChild("false").getRoot(); :} | NULL {: debugMessage(PRODSTRING); RESULT = (new ParseNode("literal", parser.curLine(1))).addChild("decimal").addChild("0").getRoot(); :} | DECIMAL:dec {: debugMessage(PRODSTRING); RESULT = (new ParseNode("literal", parser.curLine(1))).addChild("decimal").addChild(dec).getRoot(); :} | SUB DECIMAL:dec {: debugMessage(PRODSTRING); RESULT = (new ParseNode("literal", parser.curLine(1))).addChild("decimal").addChild("-"+dec).getRoot(); :} | STRING:str {: debugMessage(PRODSTRING); RESULT = (new ParseNode("literal", parser.curLine(1))).addChild("string").addChild(str).getRoot(); :} | CHAR:chr {: debugMessage(PRODSTRING); RESULT = (new ParseNode("literal", parser.curLine(1))).addChild("char").addChild(chr).getRoot(); :} | LITERAL OPENPAREN ID:literal CLOSEPAREN {: debugMessage(PRODSTRING); RESULT = (new ParseNode("literal", parser.curLine(1))).addChild("token").addChild(literal).getRoot(); :} ; set ::= ID:setname {: debugMessage(PRODSTRING); ParseNode set = new ParseNode("set", parser.curLine(1)); set.addChild("name").addChild(setname); RESULT = set; :} | OPENBRACE listofliterals:list CLOSEBRACE {: debugMessage(PRODSTRING); ParseNode set = new ParseNode("set", parser.curLine(3)); set.addChild(list); RESULT = set; :} ; listofliterals ::= listofliterals:list COMMA literal:literal {: debugMessage(PRODSTRING); list.addChild(literal); RESULT = list; :} | literal:literal {: debugMessage(PRODSTRING); ParseNode list = new ParseNode("listofliterals", parser.curLine(1)); list.addChild(literal); RESULT = list; :} ;