基于其他令牌更改 Antlr 令牌

Change Antlr Token based on other tokens

是否可以根据令牌是否存在于字符串中来使令牌类型成为一种类型?

例如:

Hello 100
and:
100 Hello

WORD 会是你好

AMOUNT 将是 100

但是对于这个:

100 3543
and:
3543 100

WORD 将是 100

AMOUNT 将是 3543

基本上,只有WORD。问题是定义哪个数字是 WORD.

或者 Antlr 这根本不可能吗?

最佳答案是 'no'('no' 因为这是个坏主意,'no' 因为它可以做到,但只能使用可怕的拼凑)。

识别明确定义的标记类型的相对 syntactic/structural 定位完全是一个解析器问题。如果标记类型没有明确定义,那么语法就会有歧义——正确的解释依赖于语义。在这种情况下,标记先前是否已在语义上用作 WORD

语义问题最好在树遍历器中处理,因为存在完整的解析树以供分析。

考虑:

phrase : a=ID b=ID ;

ID : WORD | NUMB ;
WS : [ \r\n\t] -> skip ;

fragment WORD : .... ;
fragment NUMB : .... ;

现在,在遍历解析树时,可以检查每个 PhraseContext 节点。 ID 的标签使得确定相对顺序变得简单:每个 PhraseContext 节点将有变量

TerminalNode a; // the first ID in the node
TerminalNode b; // the second

在暂存器中记录第一次遇到 ID 的顺序。在随后的遭遇中,暂存器可用于一致地定义哪些 ID 应被视为 WORDNUMB

有一个解决方案,如果您始终保持 WORD 和 NUMBER 的顺序相同。例如:

phase: id NUMBER;

id: WORD | NUMBER;
WORD: ...;
NUMBER ...;

第一个标记应该 return id,无论它是数字还是单词,第二个标记始终 return 是一个数字。

单独使用解析器不可能允许任意排序两者。如果必须使用任意顺序,您只能按照@GRosenberg 的建议将两者都解析为 ID,然后再进行语义检查,其中哪个是更合理的 WORD,哪个是 NUMBER。

更新id 规则更改为解析器规则,以避免 Jiri 提到的麻烦。

因为你所说的 WORD 可以是数字以及 NUMBER,这是一个解析器决定,而不是词法分析器决定:

line: id NUMBER | NUMBER WORD;
id: WORD | NUMBER;
WORD: [a-zA-Z];
NUMBER: [0-9];