[antlr-interest] Help with circular reference in parser?

Christopher Schultz christopher.d.schultz at comcast.net
Thu Mar 2 08:22:32 PST 2006


Sorry, forgot the attachment.

Here is the grammar in all it's glory.

Thanks,
-chris


header {
    package net.christopherschultz.evaluator.parser;

    import net.christopherschultz.evaluator.*;
}

class ExpressionParserImpl extends Parser;

options {
   buildAST = false;
   k=2; // 2-token lookahead: can differentiate between
        // ( MINUS INT ) and ( MINUS FLOAT )
defaultErrorHandler = false;
}

/* We have expr and mexpr separate, with the addition and subtraction
   separate from multiplication in order to enforce order-of-operations. */
expr returns [Expression exp = null] throws EvaluationException
    {
        Expression right;
    }
    :
        exp=relexpr (
            ( AND^ right=relexpr) { exp = new MathExpression(exp, "&&",
right); }
            | (OR^ right=relexpr)  { exp = new MathExpression(exp, "||",
right); }
        )*
        // This (EOF)? seem totally sketchy, but it works!
        (EOF!)?
    ;

// Relational Expression
relexpr returns [Expression exp = null] throws EvaluationException
    {
        Expression right;
    }
    :
        exp=addexpr (
            (EQUALS^ right=addexpr) { exp = new MathExpression(exp, "=",
right); }
            | (NOT_EQUALS^ right=addexpr) { exp = new
MathExpression(exp, "!=", right); }
            | (GREATERTHAN^ right=addexpr) { exp = new
MathExpression(exp, ">", right); }
            | (LESSTHAN^ right=addexpr) { exp = new MathExpression(exp,
"<", right); }
            | (GREATERTHANEQUALTO^ right=addexpr) { exp = new
MathExpression(exp, ">=", right); }
            | (LESSTHANEQUALTO^ right=addexpr) { exp = new
MathExpression(exp, "<=", right); }
        )*
    ;

// Arithmetic Expression
addexpr returns [Expression exp = null] throws EvaluationException
    {
        Expression right;
    }
    :
        exp=multexpr (( PLUS^ right=multexpr { exp = new
MathExpression(exp, "+", right); }
                      | MINUS^ right=multexpr { exp = new
MathExpression(exp, "-", right); } ))*
    ;

// Multiplicative (or divisive) expression
multexpr returns [Expression exp = null] throws EvaluationException
    {
        Expression right;
    }
    :
        exp=unaryExpr (
            ( STAR^ right=unaryExpr { exp = new MathExpression(exp, "*",
right); } )
            |
            ( SLASH right=unaryExpr { exp = new MathExpression(exp, "/",
right); } )
            |
            ( PERCENT right=unaryExpr { exp = new MathExpression(exp,
"%", right); } )

        )*
    ;

// (Logically) negated expression
unaryExpr returns [ Expression exp = null ] throws EvaluationException
    :
        (
         (BANG^ exp=atom { exp = new NegatedExpression(exp); })
         |
         (MINUS^ exp=atom { exp = new UnaryMinusExpression(exp); })
         |
         (PLUS!)? exp=atom
        )
    ;

// Function call expression
functioncall returns [ Expression exp = null ] throws EvaluationException
    {
        java.util.List args = null;
    }
    :
        func:IDENTIFIER^ LPAREN! (args=argumentlist)? RPAREN!
        {
            exp = new FunctionCallExpression(func.getText(), args);
        }
    ;

// Array reference (i.e. a[3])
arrayref returns [ Expression exp = null ] throws EvaluationException
    {
        Expression index; // dynamic index ;)
    }
    :
        array:IDENTIFIER^ LBRACKET! (index=expr) RBRACKET!
        {
            exp = new ArrayReferenceExpression(array.getText(), index);
        }
    ;

// arrayref returns [ Expression exp = null ] throws EvaluationException
//     {
//         Expression array; // dynamic reference ;)
//         Expression index; // dynamic index ;)
//     }
//     :
//         (array=expr)
//         |
//         (array=expr) LBRACKET! (index=expr) RBRACKET!
//         {
//             exp = new ArrayReferenceExpression(array.getText(), index);
//         }
//     ;

// Argument List
argumentlist returns [java.util.List list = new java.util.ArrayList()]
throws EvaluationException
    {
        Expression arg;
    }
    :
        arg=argument { list.add(arg); }
        (COMMA! arg=argument { list.add(arg); })*
    ;

// Argument (i.e. anything)
argument returns [Expression exp = null] throws EvaluationException
    :
        exp=expr
    ;

// Indentifiers (i.e. symbols)
identifier returns [ Expression exp = null ] throws EvaluationException
    :
        id:IDENTIFIER
        {
            exp = new IdentifierExpression(id.getText());
        }
    ;

// Atoms
atom returns [Expression exp = null] throws EvaluationException
    :
        exp=functioncall
        |
        exp=arrayref
        |
        exp=identifier
        |
        hex:HEX_LITERAL {   Object value;
                            String hexStr = hex.getText();
                            int length = hexStr.length();
                            if(length > 10) // 8 hex + leading "0x"
                                value = Long.decode(hexStr);
                            else if(length > 6)
                                value = Integer.decode(hexStr);
                            else if(length > 4)
                                value = Short.decode(hexStr);
                            else
                                value = Byte.decode(hexStr);
                            exp = new ConstantExpression(value);
                        }
        |
        oct:OCTAL_LITERAL { Object value;
                            String octalStr = oct.getText();
                            int length = octalStr.length();
                            if(length > 11) // 10 octal + leading "0"
                                value = Long.decode(octalStr);
                            else if(length > 6)
                                value = Integer.decode(octalStr);
                            else if(length > 3)
                                value = Short.decode(octalStr);
                            else
                                value = Byte.decode(octalStr);
                            exp = new ConstantExpression(value);
                        }
        |
/* TODO: allow larger precision than simply 32-bit integer. Long?
BigInteger? */
/* TODO: How can we use a BigInteger to determine if the value fits into
a certain type of primitive? Just make BigInteger objects out of
Integer.MAX_VALUE, etc? */
        i:INT_LITERAL { exp = new ConstantExpression(new
Integer(i.getText())); }
        |
        f:DECIMAL_LITERAL { exp = new ConstantExpression(new
Double(f.getText())); }
        |
        s:STRING { exp = new ConstantExpression(s.getText()); }
        |
        LPAREN! exp=expr RPAREN!
    ;

class ExpressionLexerImpl extends Lexer;

options {
    k=2; // (2)needed for newline junk, (5) needed for booleans
    charVocabulary = '\3'..'\377';
}

IDENTIFIER: WORDCHAR (WORDCHAR | DIGIT)*;

STRING
    :
        DOUBLEQUOTE!
        (CHAR_ESC | ~('\"' | '\\') )*
        DOUBLEQUOTE!
    ;

protected CHAR_ESC
    :
        '\\'
        ( 'n'  { $setText("\n"); }
        | 'r'  { $setText("\r"); }
        | 't'  { $setText("\t"); }
        | 'b'  { $setText("\b"); }
        | 'f'  { $setText("\f"); }
        | '\"' { $setText("\""); }
        | '\'' { $setText("\'"); }
        | '\\' { $setText("\\"); }
        )
    ;

NUMERIC_LITERAL:
        (ZERO (OCTAL_DIGIT)+) => OCTAL_LITERAL { $setType(OCTAL_LITERAL); }
        |
        (ZERO Xx) => HEX_LITERAL  { $setType(HEX_LITERAL); }
        |
        (DOT DIGITS) => DECIMAL_LITERAL { $setType(DECIMAL_LITERAL); }
        |
        (DIGITS DOT) => DECIMAL_LITERAL { $setType(DECIMAL_LITERAL); }
        |
        (DIGITS)    { $setType(INT_LITERAL); }
        ;

/*
NUMERIC_LITERAL:
        (ZERO (OCTAL_DIGIT)+) => OCTAL_LITERAL { $setType(OCTAL_LITERAL); }
        |
        (ZERO Xx) => HEX_LITERAL  { $setType(HEX_LITERAL); }
        |
        ((
            ( PLUS  { $setType(PLUS); } )
            |
            ( MINUS { $setType(MINUS); } )
         )?
            ( ( DIGITS { $setType(INT_LITERAL); } )
              ( DOT (DIGITS)? { $setType(DECIMAL_LITERAL); } )?
              |
              ( ( DOT DIGITS ) => DECIMAL_LITERAL {
$setType(DECIMAL_LITERAL); } )
            )
        )
        |
        (DIGITS)    { $setType(INT_LITERAL); }
           ((DOT) => DECIMAL_LITERAL { $setType(DECIMAL_LITERAL); } )?
        ;
*/

protected OCTAL_LITERAL: (ZERO (OCTAL_DIGIT)+) ;

protected OCTAL_DIGIT: '0'..'7' ;

protected HEX_LITERAL :  (ZERO Xx (HEX_DIGIT)+) ;

protected ZERO: '0' ;

protected Xx: ('x' | 'X') ;

protected HEX_DIGIT: ( 'a'..'z' | 'A'..'Z' | DIGIT ) ;

protected INT_LITERAL: DIGITS ;

protected DECIMAL_LITERAL: ( ( DIGITS )? DOT ( DIGITS )? ) ;

protected DIGITS : ( DIGIT )+ ;

protected SIGN: ( PLUS | MINUS ) ;

protected
WORDCHAR:   'a'..'z' | 'A'..'Z' | '_' ;

protected
DIGIT: '0'..'9';

protected
DOT: '.' ;

BANG: '!' ;

COMMA: ','
        ;

LBRACKET: '['
        ;

RBRACKET: ']'
        ;

LPAREN: '('
        ;

RPAREN: ')'
        ;

PLUS: '+'
        ;

MINUS: '-'
        ;

STAR: '*'
    ;

PERCENT: '%'
    ;

SLASH: '/'
    ;

AND: '&''&'
        ;

OR: '|''|'
        ;

EQUALS: '='
        ;

NOT_EQUALS
    :
        BANG EQUALS
    ;

GREATERTHAN: '>' ;

LESSTHAN: '<' ;

GREATERTHANEQUALTO: '>' '=' ;

LESSTHANEQUALTO: '<' '=' ;

SINGLEQUOTE: '\'' ;

DOUBLEQUOTE: '\"' ;

/*
protected
TRUE: 't''r''u''e'
        ;

protected
FALSE: 'f''a''l''s''e'
        ;
*/

WS:
        (   ' '
        |   '\t'
        |   '\r' '\n' { newline(); }
        |   '\n'      { newline(); }
        )
        {$setType(Token.SKIP);} //ignore this token
    ;



-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 250 bytes
Desc: OpenPGP digital signature
Url : http://www.antlr.org/pipermail/antlr-interest/attachments/20060302/3ec687ba/signature.bin


More information about the antlr-interest mailing list