For-loop over an ANTLR context

35 views
Skip to first unread message

Sylvestr Lozynskyy

unread,
Sep 2, 2016, 9:21:14 AM9/2/16
to antlr-discussion

Most examples I find of creating an arithmetic expression parser with ANTLR have them put almost everything in the grammar file.

I however need to parse the expression without putting everything in the .g4 file.

grammar Mau;

program
    :   statement*
    ;

statement
    :(  moduleDeclaration
    |   whileStatement
    |   loopStatement
    |   ifStatement
    |   varStatement
    |   funcStatement
    |   expr
    )   ';'
    ;

funcStatement
    :   'func' IDENTIFIER '(' ( IDENTIFIER (',' IDENTIFIER)* )? ')' block
    ;

moduleDeclaration
    :   'module' IDENTIFIER
    ;

varStatement
    :   IDENTIFIER? IDENTIFIER '=' expr
    ;

whileStatement
    :   'while' expr block
    ;

ifStatement
    :   'if' expr block
    ;

loopStatement
    :   'loop' block
    ;

block
    :   '{' statement* '}'
    ;

expr
    :   multiplyMath (('+' | '-') multiplyMath)*
    ;

multiplyMath
    :   mathAtom (('*' | '/') mathAtom)*
    ;

mathAtom
    :   number
    |   STRING
    |   IDENTIFIER
    |   '(' expr ')'
    |   IDENTIFIER '(' expr (',' expr)+ ')'
    ;

number returns [double value]
    :   num=NUMBER { $value = Double.parseDouble($num.getText()); }
    ;

STRING: '"' (~["])* '"';
WHITESPACE: ('\t' | ' ' | '\r' | '\n' | '\u000C')+ -> skip;
IDENTIFIER: ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*;
NUMBER: ('0' .. '9') + ('.' ('0' .. '9')+)?;

When ever the parser sees a statement, it runs this code:

@Override
public void enterStatement(MauParser.StatementContext ctx) {
    if (ctx.moduleDeclaration() != null) {
        ModuleDeclarationContext statement = ctx.moduleDeclaration();
        Mau.modules.put(statement.IDENTIFIER().getText(), mau);
    } else if (ctx.varStatement() != null) {
        VarStatementContext statement = ctx.varStatement();
        mau.vars.put(statement.IDENTIFIER(1).getText(), mau.expr(statement.expr(), Mau.modules.get(statement.IDENTIFIER(0).getText())));
    }
}

Whenever it needs to parse an expression, it calls mau.expr(ExprContext, MauModule)

So.. the question is:
How do I use a for-loop over the children of the ExprContext?

I cannot use ctx.children as I do not know whether or not it's a number as NumberContext has a value field in it.

 

This question is so poor-ly made.


Mike Lischke

unread,
Sep 2, 2016, 9:59:30 AM9/2/16
to antlr-di...@googlegroups.com
Hi Sylvestr,

Most examples I find of creating an arithmetic expression parser with ANTLR have them put almost everything in the grammar file.

I however need to parse the expression without putting everything in the .g4 file.



I don't understand what you mean by "putting everything in the .g4 file". What is "everything"? What I see below seems to be exactly what should be there.
This is a bad approach in several aspects. First it uses enterStatement(). At this point in the parse process there is nothing in the given ctx. enterXXX is called before a rule is actually parsed. So instead use exitStatement(). Then all the subrules are handled in this single function, which makes this a lot more complicated than necessary. Instead override the individual sub contexts, e.g. public void exitVarStatement(MauParser.VarStatementContext ctx); which will be called only if there is really a var statement in the input. This frees you from checking all the subcontexts manually.

Whenever it needs to parse an expression, it calls mau.expr(ExprContext, MauModule)

So.. the question is:
How do I use a for-loop over the children of the ExprContext?

I cannot use ctx.children as I do not know whether or not it's a number as NumberContext has a value field in it.



Don't use the children directly unless you want to operate on them in more generic way (e.g. for walking/dumping the tree). Many of the fields in a context are simply a convenience view into the child list, to simplify parser writer's life.


Sylvestr Lozynskyy

unread,
Sep 2, 2016, 10:42:30 AM9/2/16
to antlr-discussion
Thank you for the advice, however It does not answer my original question.
How would I loop over ExprContext's children to efficiently parse a mathematical expression?
Reply all
Reply to author
Forward
0 new messages