rendered paste body/* * This is based on: * Example grammar written 11/1/96 by Chuck McManisoptions { MULTI=true; VISITOR=true; NODE_DEFAULT_VOID=true;}/* MULTI=true; *//* #LOOKAHEAD=1; */PARSER_BEGIN(PRM)public class PRM { public static void main(String args[]) { PRM parser = new PRM(System.in); ASTProgram n = null; try { n = parser.program(); n.dump(""); System.out.println("Successfully parsed!\n"); } catch (Exception e) { System.out.println("Error."); System.out.println(e.getMessage()); e.printStackTrace(); } /* Check variable declarations */ System.out.println("\nChecking variable declarations"); PRMDeclarationCheckVisitor dcv = new PRMDeclarationCheckVisitor(); dcv.visit(n, null); }}PARSER_END(PRM)SKIP : /* WHITESPACE */{ " " | "\t" | "\r" | "\n" | < "//" (~["\n","\r"])* ("\n" | "\r" | "\r\n") > }/* The next few TOKEN definitions are the binary operators of our language in decreasing order of precedence */TOKEN : /* The end of line token (a semicolon) */{ < EOL: ";" >}TOKEN : /* Block begin and block end markers */{ < BB: "{" > | < BE: "}" >}TOKEN : /* The left subscript and right subscript operators */{ < LSUB: "[" > | < RSUB: "]" >}TOKEN : /* Left and right parentheses */{ < LPAREN: "(" > | < RPAREN: ")" >}TOKEN : /* The list separator */{ < LISTSEP: "," >}TOKEN : /* Exponentiation operator */{ < EXP: "^" >}TOKEN : /* Multiplication and division */{ < MULTIPLY: "*" > | < DIVIDE: "/"> | < MOD: "%" >}TOKEN : /* Addition and subtraction */{ < PLUS: "+" > | < MINUS: "-">}TOKEN : /* Comparison operators */{ < EQ: "=" > | < GT: ">" > | < GE: ">=" > | < LT: "<" > | < LE: "<=" > | < NE: "<>" | "!=" >}TOKEN : /* Logical operators (AND/OR) */{ < AND: "&" > | < OR: "|" >}TOKEN : /* The assignment operator */{ < GETS: ":=" >}TOKEN : /* Keywords */{ < DO: "do" > | < WHILE: "while" > | < IF: "if" > | < ELSIF: "elsif" > | < ELSE: "else" > | < NUMBER_TYPE: "number" > | < STRING_TYPE: "string" > | < BOOLEAN_TYPE: "boolean" > | < RETURN: "return" >}TOKEN : /* Numeric Constants */{ < NUMBER: <FLOAT> | <INTEGER> "r" <SPECINTEGER> | <FLOAT> ( ["e","E"] ([ "-","+"])? <INTEGER> )? > | < #FLOAT: <INTEGER> | <INTEGER> ( "." <INTEGER> )? | "." <INTEGER> > | < #INTEGER: ( <DIGIT> )+ > | < #SPECINTEGER: (["a"-"t", "A"-"T", "0"-"9"])+ | < #DIGIT: ["0" - "9"] >}TOKEN : /* String constants */{ < STRING: "\"" ( <CHAR> )* "\"" > | < #CHAR: ["!", "#"-"~", " ", "\t"] >}TOKEN : /* Boolean constants */{ < BOOLEAN: "true" | "false" >}TOKEN : /* Identifiers (variables and function calls) */{ < ID: ( <LETTER> )+ ( <DIGIT> | <LETTER> )* > | < #LETTER: ["a"-"z", "A"-"Z", "_"] > } /* That's it for TOKEN definitions, now we start with the grammar */ASTProgram program() #Program :{ }{ (( functionDefinition() )* <EOF> ) { return jjtThis; }}void functionDefinition() :{ }{ ( type() identifier() <LPAREN> parameterList() <RPAREN> block() ) #Function}void parameterList() :{ }{ ( ( parameter() ( <LISTSEP> parameter() )* )? ) #ParameterList}void parameter() :{ }{ ( type() identifier() ) #Parameter}void block() :{ }{ ( <BB> expressionList() <BE> ) #Block}void expressionList() :{ }{ ( statement() )* }void statement() :{ }{ declaration() | returnStatement() | whileLoop() | doLoop() | ifStatement() | simpleStatement()}void declaration() :{ }{ ( type() identifier() (<LISTSEP> identifier())* <EOL> ) #Declaration}void type() #MyType : { Token t;}{ ( <NUMBER_TYPE> | <STRING_TYPE> | <BOOLEAN_TYPE> ) { t = getToken(0); jjtThis.setName(t.image); } }void identifier() #MyIdentifier :{ Token t;}{ t=<ID> { jjtThis.setName(t.image); }}void returnStatement() :{ }{ ( <RETURN> logical() <EOL> ) #Return}void whileLoop() :{ }{ ( <WHILE> condition() block() ) #WhileLoop}void doLoop() :{ }{ ( <DO> block() <WHILE> condition() ) #DoLoop}void ifStatement() :{ }{ ( <IF> condition() block() ( <ELSIF> condition() block() )* ( <ELSE> block() )? ) #IfStatement}void condition() :{ }{ ( <LPAREN> assignment() <RPAREN> ) #Condition}void simpleStatement() :{ }{ ( assignment() <EOL> ) #SimpleStatement}void assignment() :{ }{ // The first solution requires a lookahead, but spots invalid // assignments during parsing. The second solution doesn't require // lookahead, but allows invalid assignments during parsing // LOOKAHEAD( <ID> <GETS> ) <ID> <GETS> logical() | logical() ( logical() ( <GETS> logical() )* ) #Assign(>1)}void logical() :{ }{ ( comparison() (logicalOp() comparison())* ) #OperatorList(>1)}void logicalOp() #MyOperator :{ Token t;}{ ( <AND> | <OR> ) { t = getToken(0); jjtThis.setName(t.image); }}void comparison() :{ }{ ( sum() (comparisonOp() sum())* ) #OperatorList(>1)}void comparisonOp() #MyOperator :{ Token t;}{ ( <GT> | <GE> | <LT> | <LE> | <EQ> | <NE> ) { t = getToken(0); jjtThis.setName(t.image); }}void sum() :{ }{ ( term() (sumOp() term())* ) #OperatorList(>1)}void sumOp() #MyOperator :{ Token t;}{ ( <PLUS> | <MINUS> ) { t = getToken(0); jjtThis.setName(t.image); }}void term() :{ }{ ( exp() (termOp() exp())* ) #OperatorList(>1)}void termOp() #MyOperator :{ Token t;}{ ( <MULTIPLY> | <DIVIDE> | <MOD> ) { t = getToken(0); jjtThis.setName(t.image); }}void exp() :{ }{ // Notice: x^x^x^x = x^(x^(x^(x))) ( unary() ( expOp() exp() )? ) #OperatorList(>1)}void expOp() #MyOperator :{ Token t;}{ t=<EXP> { jjtThis.setName(t.image); }}void unary() :{ }{ negation() | element()}void negation() #MyUnaryOp :{ Token t;}{ t=<MINUS> element() { jjtThis.setName(t.image); }}void element() :{ }{ constant() | idOrFunctionCall() | <LPAREN> assignment() <RPAREN>}void idOrFunctionCall() :{ }{ ( identifier() (argumentList())? ) #IDOrFunctionCall}void constant() : { }{ ( stringConstant() | booleanConstant() | numberConstant() )}void stringConstant() #MyStringConstant :{ Token t;}{ t=<STRING> { jjtThis.setValue(t.image.substring(1,t.image.length()-1)); }}void booleanConstant() #MyBooleanConstant :{ Token t;}{ t=<BOOLEAN> { jjtThis.setValue(t.image.compareTo("true")==0); } }void numberConstant() #MyNumberConstant :{ Token t;}{ t=<NUMBER> { String parsed[]; if ((t.image.indexOf("r") == 1)||(t.image.indexOf("r") == 2)) { parsed = t.image.split("r"); jjtThis.setValue(new Double(Integer.valueOf(parsed[1], (new Integer(parsed[0])).intValue())).doubleValue()); } else { jjtThis.setValue(new Double(t.image).doubleValue()); } } }void variableOrFunctionCall() #MyIdentifier :{ Token t; }{ t=<ID> ( argumentList() )? { jjtThis.setName(t.image); }}void argumentList() :{ }{ ( <LPAREN> assignment() ( <LISTSEP> assignment() )* <RPAREN> ) #ArgumentList}