Hi!
Let's assume the following grammar:
SimpleRule:
name = ID (indexList = IndexList)?;
IndexList: ('[' args+=LogicalExpr (',' args+=LogicalExpr)* ']');
LogicalExpr: LogExprAtom;
LogExprAtom returns LogicalExpr:
{LogicalAtom} someref = [AnotherType] |
{BooleanAtom} bool = 'true' |
"(" LogicalExpr ")";
AnotherType: ...
QualifiedRule: // we are looking at this
"Rule_nonLL" (s1=SimpleRule '.')? s2=SimpleRule;
QualifiedRule is non-LL(*), since SimpleRule leads to a theoretically infinite recursion on LogicalExpr and it's not possible with ANTLR to decide which rule we consumed, the first SimpleRule or the second SimpleRule. We can force the parser in two ways:
Way 1: Introduce a syntactic predicate
QualifiedRule:
"Rule_nonLL_hacked" (s1=SimpleRule '.')? s2=SimpleRule;
Ways 2: Make the optional statement on the right, since we parse from left to right:
QualifiedRule:
"Rule_Working" s1=SimpleRule ('.' s2=SimpleRule)?;
The problem now is, that an introduction of syntactic predicates makes it hard to follow the grammar locally, meaning, that we have to know exactly, what the grammar does globally. Way 2 helps here, but consider the following type cross-reference problem:
QualifiedRuleTypeA:
"Rule_TypeA" (s1=SimpleRule '.')? s2=SimpleRuleTypeA;
QualifiedRuleTypeB:
"Rule_TypeB" (s1=SimpleRule '.')? s2=SimpleRuleTypeB;
SimpleRuleTypeA:
name = [TypeA|ID] (indexList = IndexList)?;
SimpleRuleTypeB:
name = [TypeB|ID] (indexList = IndexList)?;
TypeA: name="TypeA";
TypeB: name="TypeB";
If we want here to enable "Way 2", we have to declare a supertype for TypeA and TypeB for references, since both consume an ID.
Is there an alternative way to solve this problem without introducing syntactic predicates or an artificial supertype (which makes the generated ecore model unnecessary enhanced)?
Greetings,
Alex.