我想设置一个规则,即我可以有一个以非保留字开头的表达式,但它可以包含一个可以包含保留字的路径。例如:
myFunc().select
table.select.select.myFunc().array[0].select
new.select.test
我的想法是使用这样一条规则:
exprWithoutReservedKeyword (DOT exprWithReservedKeyword)*
然而,这似乎是令人难以置信的重复,例如,如果expr
规则有30个替代方案,例如:
expr:
OPEN_PAREN expr CLOSE_PAREN
| selectStatement
| ...
那么,我该如何实现这一点,我是否必须重写(即复制粘贴(整个表达式两次,然后再添加一次reservedKeyword
规则?如果两者都是递归的,那么这两个规则之间难道不会有令人难以置信的模糊性竞争吗?什么是处理它的好方法?
或者,我需要基本上使每个子表达式都是非递归的,并在父表达式中处理它,例如:
expr:
exprWithoutReservedKeyword (DOT exprWithReservedKeyword)*
| expr
;
我想在expr
规则的某个地方(可能隐藏在子规则中(,会有这样的东西:
path : IDENTIFIER
| path '.' IDENTIFIER
你会想把它改成
path : IDENTIFIER
| path '.' (IDENTIFIER | reserved_word)
其中reserved_word
在某个地方被定义为保留字标记的连词,这可能是一个长列表。
在带有"的语言中;半保留的";单词,你会发现在其他上下文中,一些保留单词是可能的,但不是全部;要处理这些问题,您需要其他集合以及reserved_word
。这可能会很乏味,但幸运的是,你只需要做一次。
注意,reserved_word
必须是非终端,而不是令牌;如果它是一个代币,它将被无条件地认可,但你只希望它在这种特定的背景下被认可。