Antlr 无法匹配 [a-z]+
Antlr failing to match [a-z]+
尝试拆分输入的第一个单词,这样 apple a type of fruit
将拆分为 apple
和 a type of fruit
。
grammar Hello;
entry
: headword definition
;
headword
: HEADWORD
;
definition
: ANYTHING
;
HEADWORD : [a-z]+ ;
SPACE : [ \t]+ -> skip ;
ANYTHING : .+;
使用 Getting Started 演练:
C:\Code\antlr\hello>java org.antlr.v4.Tool Hello.g4
warning(131): Hello.g4:17:12: greedy block ()+ contains wildcard; the non-greedy syntax ()+? may be preferred
C:\Code\antlr\hello>javac Hello*.java
C:\Code\antlr\hello>grun Hello entry -tree
C:\Code\antlr\hello>java org.antlr.v4.gui.TestRig Hello entry -tree
asdf asdf
^Z
line 1:0 missing HEADWORD at 'asdf asdf\r\n'
(entry (headword <missing HEADWORD>) (definition asdf asdf\r\n))
为什么无法匹配 HEADWORD?
即使尝试直接匹配 HEADWORD 也不起作用:
C:\Code\antlr\hello>grun Hello HEADWORD -tree
asdf^Z
Terminate batch job (Y/N)? y
它似乎永远循环,所以我不得不用 Ctrl-C 杀死它。
ANTLR 词法分析器规则使用尽可能多的字符。所以你的规则 ANYTHING : .+;
消耗了整个输入,导致它成为唯一要创建的标记。这就是 HEADWORD
未创建的原因。
是的,ANTLR 的词法分析器规则是从上到下匹配的,但是只有当 2 个(或更多)词法分析器规则匹配相同数量的字符时,从上到下才有意义。然后首先定义的规则“获胜”,但前提是(多个)规则匹配相同数量的字符。在您的情况下,ANYTHING
将(几乎)总是匹配最多的字符,因此将是要创建的唯一标记。
如果您的输入只是 "apple"
,则会创建一个 HEADWORD
标记,因为 HEADWORD
和 ANYTHING
都匹配输入,但是 HEADWORD
首先定义,因此优先。
并且将 .+
更改为 .+?
只会导致 ANYTHING
永远不会与您的输入 apple a type of fruit
匹配。只会创建 5 HEADWORD
个代币。
根据经验,让词法分析器规则以 .*
或 .+
(或 .*?
或 .+?
)结尾绝不是一个好主意。
尝试拆分输入的第一个单词,这样 apple a type of fruit
将拆分为 apple
和 a type of fruit
。
grammar Hello;
entry
: headword definition
;
headword
: HEADWORD
;
definition
: ANYTHING
;
HEADWORD : [a-z]+ ;
SPACE : [ \t]+ -> skip ;
ANYTHING : .+;
使用 Getting Started 演练:
C:\Code\antlr\hello>java org.antlr.v4.Tool Hello.g4
warning(131): Hello.g4:17:12: greedy block ()+ contains wildcard; the non-greedy syntax ()+? may be preferred
C:\Code\antlr\hello>javac Hello*.java
C:\Code\antlr\hello>grun Hello entry -tree
C:\Code\antlr\hello>java org.antlr.v4.gui.TestRig Hello entry -tree
asdf asdf
^Z
line 1:0 missing HEADWORD at 'asdf asdf\r\n'
(entry (headword <missing HEADWORD>) (definition asdf asdf\r\n))
为什么无法匹配 HEADWORD?
即使尝试直接匹配 HEADWORD 也不起作用:
C:\Code\antlr\hello>grun Hello HEADWORD -tree
asdf^Z
Terminate batch job (Y/N)? y
它似乎永远循环,所以我不得不用 Ctrl-C 杀死它。
ANTLR 词法分析器规则使用尽可能多的字符。所以你的规则 ANYTHING : .+;
消耗了整个输入,导致它成为唯一要创建的标记。这就是 HEADWORD
未创建的原因。
是的,ANTLR 的词法分析器规则是从上到下匹配的,但是只有当 2 个(或更多)词法分析器规则匹配相同数量的字符时,从上到下才有意义。然后首先定义的规则“获胜”,但前提是(多个)规则匹配相同数量的字符。在您的情况下,ANYTHING
将(几乎)总是匹配最多的字符,因此将是要创建的唯一标记。
如果您的输入只是 "apple"
,则会创建一个 HEADWORD
标记,因为 HEADWORD
和 ANYTHING
都匹配输入,但是 HEADWORD
首先定义,因此优先。
并且将 .+
更改为 .+?
只会导致 ANYTHING
永远不会与您的输入 apple a type of fruit
匹配。只会创建 5 HEADWORD
个代币。
根据经验,让词法分析器规则以 .*
或 .+
(或 .*?
或 .+?
)结尾绝不是一个好主意。