antlr - 匹配带有空格的单词作为一个标记,但不允许某些关键字标记
问题描述
我有以下令牌规则:
IF: 'IF' | 'if';
THEN: 'THEN' | 'then';
ELSE: 'ELSE' | 'else';
BINARYOPERATOR: 'AND' | 'and' | 'OR' | 'or';
NOT: 'NOT' | 'not';
WORD: (DIGIT* (LOWERCASE | UPPERCASE | WORDSYMBOL)) (LOWERCASE | UPPERCASE | DIGIT | WORDSYMBOL)*;
这有效,类似的东西my variable
出现在WORD WORD
. 我希望能够只拥有一个代表整个事物的令牌。
我把它挂在:
IF: 'IF' | 'if';
THEN: 'THEN' | 'then';
ELSE: 'ELSE' | 'else';
BINARYOPERATOR: 'AND' | 'and' | 'OR' | 'or';
NOT: 'NOT' | 'not';
WORD: (LOWERCASE | UPPERCASE | WORDSYMBOL)+ (' '* (LOWERCASE | UPPERCASE | WORDSYMBOL))*;
这解决了这个问题,但是它也捕获了我想分类为上述关键字标记的字符串。
例如if my variable then something
不应该只是一个WORD
令牌,它应该是IF WORD THEN WORD
.
我理解为什么要按原样对其进行标记(首选消耗更多输入的标记),但不确定如何更改行为。
解决方案
不幸的是(对于您想做的事情),ANTLR 的标记化不是这样工作的。
(这更像是一个“合乎逻辑”的解释,而不是实际的实现)
当 ANTLR 评估 Lexer 规则时,它会尝试将每个规则与输入流中的字符匹配,从输入流中的当前位置开始。
一旦它拥有所有匹配的输入序列,如果有一个序列比其他序列长,它将选择产生最长标记的 Token 类型。这是您的WORD
规则将使用输入的地方,直到 if 找到与 a 中的字符不匹配的内容WORD
(如果它们与模式匹配,这将包括“slurping”关键字WORD
)。
(为了完整性)如果 Tokenizer 发现多个等长匹配,则在您的语法中匹配的第一个规则将是分配的 Token 类型。
您可能会通过以下方法获得成功:
假设:WORD
不能是您的语言关键字之一
- 确保该
WORD
规则位于所有关键字规则之后,以便它们具有优先权。 - 添加解析器规则
word: WORD+;
- 现在在您使用令牌
word
的任何地方使用解析器规则。RULE
enterWord()
编写一个侦听器,将所有s覆盖并合并WORD
为一个“单词”。(您可以通过多种方式处理此步骤,但这是一种相当简单的方法)
警告:
- 语言通常不允许这样做是有原因的。我怀疑你会在路上遇到其他并发症/模棱两可。
- 性能可能会受到影响,因为 ANTLR 必须做更多的预测才能知道何时回溯。
推荐阅读
- swift - 在 ARSCNView 上放置一个对象
- fluent-bit - FluentBit - 如果日志太长,有没有办法截断日志?
- git - 如何在 git 更改选项卡的 [GIT] [Visual-Studio] 中不显示 git 忽略的文件
- rdl - 使用 Free 3 of 9 字体无法扫描带有条码的 SSRS 报告
- python - 在 Windows 10 中激活 python 的虚拟环境时出错
- html - 悬停时折叠 Django NavBar(鼠标移出)
- android - AndroidTV 纵向
- fluid-framework - 获取流体服务器中所有现有文档的名称
- java - 如何通过编程改变指针速度 - Android
- python - nfcpy python脚本打印UID