基于其他令牌更改 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
应被视为 WORD
或 NUMB
。
有一个解决方案,如果您始终保持 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];
是否可以根据令牌是否存在于字符串中来使令牌类型成为一种类型?
例如:
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
应被视为 WORD
或 NUMB
。
有一个解决方案,如果您始终保持 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];