Finally, I follow the advices provided by sepp2k like this:
grammar minimal;
value:
'(' val = value ')' # Parenthesis
| b = BOOLEAN # Boolean
| 'non' not = value # Boolean
| l = value '=' r = value # Boolean
| i = INTEGER # Numeric
| '|' abs = value '|' # Numeric
| '-' opposite = value # Numeric
;
condition:
'(' condition ')'
| cond = value
;
ifStmnt:
'IF' condition 'THEN' ( actionsThen += action )+
( 'ELSE' ( actionsElse += action )+ )?
;
system:
( actions += action )+
EOF
;
print:
'print' val = value
;
action:
ifs = ifStmnt
| pr = print
;
BOOLEAN:
'false'
| 'true'
;
INTEGER:
[0-9]+
;
WS:
[ \n\t\r]+ -> skip
;
The labels create classes which extends ValueContext, I use them like this:
package com.thalesgroup.dms.stimulus.factories;
import minimal.minimalParser.BooleanContext;
import minimal.minimalParser.ConditionContext;
import minimal.minimalParser.NumericContext;
import minimal.minimalParser.ParenthesisContext;
import minimal.minimalParser.ValueContext;
public class Sample {
void analyze( ValueContext ctxt ) {
if( ctxt instanceof ParenthesisContext ) {
analyze(((ParenthesisContext)ctxt).val );
}
else if( ctxt instanceof BooleanContext ) {
final BooleanContext bc = (BooleanContext)ctxt;
analyze( bc );
}
else if( ctxt instanceof NumericContext ) {
final NumericContext nc = (NumericContext)ctxt;
analyze( nc );
}
}
void analyze( ConditionContext ctxt ) {
if( ctxt.cond instanceof BooleanContext ) {
final BooleanContext boolCtxt = (BooleanContext)ctxt.cond;
// build a condition from a BooleanContext
analyze( boolCtxt );
}
else {
throw new IllegalStateException();
}
}
void analyze( BooleanContext ctxt ) {
if( ctxt.b != null ) {
final String literal = ctxt.b.getText();
if( literal.equals( "true" )) {
// deal with a boolean literal 'true'
}
else if( literal.equals( "false" )) {
// deal with a boolean literal 'false'
}
}
else if( ctxt.not != null ) {
final BooleanContext bCtxt = (BooleanContext)ctxt.not;
// deal with a 'not' operation
}
else if( ctxt.l != null ) {
final ValueContext left = ctxt.l;
final ValueContext right = ctxt.r;
// deal with 'equals'
}
else {
// ???
}
}
void analyze( NumericContext ctxt ) {
if( ctxt.abs != null ) {
// deal with abs( x )
}
else if( ctxt.opposite != null ) {
// deal with - x
}
else if( ctxt.i != null ) {
// deal with literal integer
}
}
}
valeurBooleene
andvaleur
into one rule and leave the type checking to the type checker (or the interpreter or runtime system if your language is dynamically typed). – sepp2kcondition
usevaleur
instead and leave it to the type checker to make sure that only Boolean expressions are used as conditions. – sepp2k