La maggior parte degli esempi che trovo di creare un parser di espressioni aritmetiche con ANTLR li ha inseriti quasi tutti nel file di grammatica.
Tuttavia, ho bisogno di analizzare l'espressione senza inserire tutto nel file .g4.
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')+)?;
Quando il parser vede una dichiarazione, esegue questo codice:
@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())));
}
}
Ogni volta che ha bisogno di analizzare un'espressione, chiama mau.expr(ExprContext, MauModule)
Quindi .. la domanda è:
Come si usa un ciclo for sui figli di ExprContext?
Non posso usare ctx.children
perché non so se si tratta di un numero in quanto NumberContext ha un campo value
in esso.
Questa domanda è stata fatta così male.