I would like to set a rule that I can have an expression that starts with a non-reserved word, but it can contain a path that can contain a reserved word. Examples would be:
myFunc().select
table.select.select.myFunc().array[0].select
new.select.test
My thinking was to use a rule like this:
exprWithoutReservedKeyword (DOT exprWithReservedKeyword)*
However, this seems like it would be incredibly repetitious, if for example the expr
rule had 30 alternatives, such as:
expr:
OPEN_PAREN expr CLOSE_PAREN
| selectStatement
| ...
So then how would I accomplish that, would I have to re-write (i.e., copy-paste) the entire expression two times and then one time I would add in the reservedKeyword
rule? And if both are recursive, wouldn't there be incredible ambiguity competing between those two rules? What would be a good way to handle it?
Or would I need to basically make each of the sub-expressions non-recursive and handle that in the parent, such as:
expr:
exprWithoutReservedKeyword (DOT exprWithReservedKeyword)*
| expr
;
CodePudding user response:
I suppose that somewhere in your expr
rule (perhaps buried inside subrules), there will be something like:
path : IDENTIFIER
| path '.' IDENTIFIER
You'll want to change that to
path : IDENTIFIER
| path '.' (IDENTIFIER | reserved_word)
where reserved_word
is defined somewhere as a conjunction of reserved word tokens, which is probably a long list.
In languages with "semi-reserved" words, you'll find other contexts in which some reserved words are possible, but not all of them; to handle those, you'll need other sets as well as reserved_word
. That can get tedious, but fortunately you only need to do it once.
Note that reserved_word
must be a non-terminal, not a token; if it were a token, it would be recognised unconditionally, but you only want it to be recognised in this particular context.