header { package nl.tue.win.riaca.gap.parser; import antlr.collections.*; } class GapOMParser extends Parser; options { k = 2; codeGenMakeSwitchThreshold = 3; codeGenBitsetTestThreshold = 4; buildAST=true; ASTLabelType = "antlr.CommonAST"; // change default of "AST" } tokens { AST_TOP; /* imaginary token */ AST_LIST; /* imaginary token */ AST_FUNCTION; /* imaginary token */ UNARY_MINUS; /* helper token to match unary minus. */ UNARY_PLUS; /* helper token to match unary plus. */ } expr : assignExpr SEMI! { #expr = #([AST_TOP, "AST_TOP"], expr); } ; assignExpr : equalityExpression ( ASSIGN^ assignExpr )? ; /** * Matches equality expressions.

* * @since 1.0 */ equalityExpression : relationalExpression ( ( EQ^ | NEQ^ ) relationalExpression )* ; /** * Matches relational expressions.

* * @since 1.0 */ relationalExpression : additiveExpression ( ( LT^ | GT^ | LE^ | GE^ ) additiveExpression )* ; /** * Matches additive expressions.

* * @since 1.0 */ additiveExpression : multiplicativeExpression ( ( PLUS^ | MINUS^ ) multiplicativeExpression )* ; /** * Matches multiplicative expressions.

* * @since 1.0 */ multiplicativeExpression : powerExpression ( ( STAR^ | DIV^ ) powerExpression )* ; /** * Matches power expressions.

* * @since 1.0 */ powerExpression : unaryExpression ( POWER^ unaryExpression )* ; /** * Matches the unary expressions.

* * @since 1.0 */ unaryExpression : MINUS^ { #MINUS.setType( UNARY_MINUS ); } unaryExpression | PLUS^ { #PLUS.setType( UNARY_PLUS ); } unaryExpression | unaryExpressionRest ; /** * Matches the rest of the unary expressions.

* * @since 1.0 */ unaryExpressionRest : postFixExpression ; /** * Matches a postfix expression, either * function call or an atom.

* * @since 1.0 */ postFixExpression : ( id:ID LPAREN )=> /* * Matches function call syntax like "id( arg,arg )" */ id2:ID^ ( parenArgs )? { #postFixExpression = #([AST_FUNCTION, "AST_FUNCTION"], postFixExpression); } | atom ; parenArgs : LPAREN! ( assignExpr ( COMMA! assignExpr )* )? RPAREN! ; atom : ID | INT | CHAR_LITERAL | STRING_LITERAL | LPAREN! assignExpr RPAREN! | LBRACK! ( additiveExpression ( COMMA! additiveExpression )* )? RBRACK! { #atom = #([AST_LIST, "AST_LIST"], #atom); } ; /** * The Gap Lexer.

* * It reads in the input that is said to be GAP input. It tries * to read the tokens that valid GAP input should have. If it * succeeds it generates a sequence of tokens, which in turn can * be read by the Gap parser.

* * @author Manfred Riem (mriem@win.tue.nl). * @version 1.0 */ class GapOMLexer extends Lexer; options { k = 2; } /** * Reads whitespace and throws it away.

* * @since 1.0 */ WS : (' ' | '\t' | '\n' | '\r') { _ttype = Token.SKIP; } ; /** * Reads the last semi-colon.

* * @since 1.0 */ SEMI : ';' ; /** * Reads the left parenthesis.

* * @since 1.0 */ LPAREN : '(' ; /** * Reads the right parenthesis.

* * @since 1.0 */ RPAREN : ')' ; /** * Reads the left bracket.

* * @since 1.0 */ LBRACK : '[' ; /** * Reads the right bracket.

* * @since 1.0 */ RBRACK : ']' ; /** * Reads the plus operator.

* * @since 1.0 */ PLUS : '+'; /** * Reads the minus operator.

* * @since 1.0 */ MINUS : '-'; /** * Reads the star operator.

* * @since 1.0 */ STAR : '*'; /** * Reads the divide operator.

* * @since 1.0 */ DIV : '/'; /* * Reads the power operator.

* * @since 1.0 */ POWER : '^'; /** * Reads the assignment operator.

* * @since 1.0 */ ASSIGN : ":=" ; /** * Reads the comma operator.

* * @since 1.0 */ COMMA : ',' ; /** * Reads the '<' operator.

* * @since 1.0 */ LT : '<'; /** * Reads the '>' operator.

* * @since 1.0 */ GT : '>'; /** * Reads the "<=" operator.

* * @since 1.0 */ LE : "<="; /** * Reads the ">=" operator.

* * @since 1.0 */ GE : ">="; /** * Reads the '=' operator.

* * @since 1.0 */ EQ : '='; /** * Reads the "<>" operator.

* * @since 1.0 */ NEQ : "<>"; /** * Reads a simple character-literal.

* * @since 1.0 */ CHAR_LITERAL : '\'' (ESC|~'\'') '\'' ; /** * Reads a string literal.

* * @since 1.0 */ STRING_LITERAL : '"' (ESC|~'"')* '"' ; /** * Reads an escape-sequence.

* * @since 1.0 */ protected ESC : '\\' ( 'n' | 'r' | 't' | 'b' | 'f' | '"' | '\'' | '\\' | ('0'..'3') ( options { warnWhenFollowAmbig = false; } : ('0'..'9') ( options { warnWhenFollowAmbig = false; } : '0'..'9' )? )? | ('4'..'7') ( options { warnWhenFollowAmbig = false; } : ('0'..'9') )? ) ; protected DIGIT : '0'..'9' ; INT : (DIGIT)+ ; ID options { testLiterals = true; } : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')* ; /** * Tree walker.

* * Transform the AST-tree to an XML-encoded OpenMath object. It does * NOT use any of the libraries for OpenMath to make it possible to * run without any of those libraries.

* * @author Manfred Riem (mriem@win.tue.nl) * @version 1.0 */ class GapOMTreeWalker extends TreeParser; expr returns [String tResult] { String tLeft,tRight; tResult = ""; } : tTop : AST_TOP { AST tChild = tTop.getFirstChild(); tResult = "\n"; if ( tChild != null ) { tResult += this.expr( tChild ); } tResult += "\n"; } | #( tMinus:MINUS tLeft=expr tRight=expr ) { tResult = "\n" + "\n" + tLeft + tRight + "\n" ; } | tUnaryMinus:UNARY_MINUS { AST tAST = tUnaryMinus.getFirstChild(); if ( tAST.getType() == INT ) tResult = "-" + tAST + "\n"; else tResult = "\n" + "\n" + this.expr( tAST ) + ""; } | #( tPlus:PLUS tLeft=expr tRight=expr ) { tResult = "\n" + "\n" + tLeft + tRight + "\n" ; } | #( tLess:LT tLeft=expr tRight=expr ) { tResult = "\n" + "\n" + tLeft + tRight + "\n"; } | #( tGreater:GT tLeft=expr tRight=expr ) { tResult = "\n" + "\n" + tLeft + tRight + "\n"; } | #( tLessEqual:LE tLeft=expr tRight=expr ) { tResult = "\n" + "\n" + tLeft + tRight + "\n"; } | #( tGreaterEqual:GE tLeft=expr tRight=expr ) { tResult = "\n" + "\n" + tLeft + tRight + "\n"; } | tUnaryPlus:UNARY_PLUS { AST tAST = tUnaryPlus.getFirstChild(); if ( tAST.getType() == INT ) tResult = "" + tAST + "\n"; else tResult = this.expr( tAST ); } | #( tStar:STAR tLeft=expr tRight=expr ) { tResult = "\n" + "\n" + tLeft + tRight + "\n"; } | #( tDiv:DIV tLeft=expr tRight=expr ) { tResult = "\n" + "\n" + tLeft + tRight + "\n"; } | #( tPower:POWER tLeft=expr tRight=expr ) { tResult = "\n" + "\n" + tLeft + tRight + "\n"; } | #( tEqual:EQ tLeft=expr tRight=expr ) { tResult = "\n" + "\n" + tLeft + tRight + "\n"; } | #( tNotEqual:NEQ tLeft=expr tRight=expr ) { tResult = "\n" + "\n" + tLeft + tRight + "\n"; } | tInteger : INT { tResult = "" + tInteger.getText() + "\n"; } | tList : AST_LIST { /* * Add each child to the list.

*/ AST tChild = tList.getFirstChild(); tResult = "\n" + " \n"; if ( tChild != null ) { tResult += this.expr( tChild ); tChild = tChild.getNextSibling(); while( tChild != null ) { tResult += this.expr( tChild ); tChild = tChild.getNextSibling(); } } tResult += "\n"; } | tFunction : AST_FUNCTION { /* * A function call. */ AST tChild = tFunction.getFirstChild(); tResult = "\n" + "\n"; tChild = tChild.getFirstChild(); while( tChild != null ) { tResult += this.expr( tChild ); tChild = tChild.getNextSibling(); } tResult += "\n"; } | tIdentifier : ID { if ( tIdentifier.getText().equals( "true" ) || tIdentifier.getText().equals( "false" ) ) { tResult = "\n"; } else { tResult = "\n"; } } ;