推送模式、弹出模式示例

Pushmode, popMode example

我正在尝试学习 ANTLR 并遇到了 pushMode 和 popMode 词法模式。

我在 google 上浏览了很多 material 的内容(包括大型教程),但无法使用 pushMode 和 popMode。

我的 Lexer 语法是

lexer grammar MyLexer;
OPEN_QUOTE: '"' -> pushMode(STRING);
TEXT: [a-zA-Z]+ ;
NUMBER: [0-9]+;
mode STRING;
CLOSE_QUOTE: '"' -> popMode;
WORD: [a-zA-Z]+ ;
NUM: [0-9]+;

我的解析器是

parser grammar MyParser;
options {tokenVocab=MyLexer;}
test: sentence string ;
sentence: (TEXT|NUMBER)+;
string: OPEN_QUOTE (WORD NUM) CLOSE_QUOTE;

我的输入是

this is sentence 
"this is string"

我不相信对于第一次输入我使用的是在 pushMode 和模式中定义的词法分析器。而对于第二条语句,我使用的是 pushMode 和 popMode 之外的词法分析器。 我的印象是这应该是相反的方式,如下所示

parser grammar MyParser;
options {tokenVocab=MyLexer;}
test: sentence string ;
sentence: (WORD|NUM)+;
string: OPEN_QUOTE (TEXT|NUMBER) CLOSE_QUOTE;

有人能帮我理解一下吗?

您没有在词法分析器规则中处理空格。

通用规则是:

WS: [ \t\r\n]+ -> skip;

但是您不想跳过字符串中的空格。事实上你真的不想跳过任何东西。

尝试:

lexer grammar MyLexer;
OPEN_QUOTE: '"' -> pushMode(STRING);
TEXT: [a-zA-Z]+ ;
NUMBER: [0-9]+;
mode STRING;
CLOSE_QUOTE: '"' -> popMode;
STRING_CONTENT: ~["]* ;

~["]* 表示匹配任何不是 " 的东西。

在您的 Lexer 规则中,OPEN_QUOTETEXTNUMBER 都是默认规则,或 top-level Lexer 模式。当您遇到 OPEN_QUOTE 时,您将 Lexer“推”到 STRING 模式,它只会查看 CLOSE_QUOTEWORDNUMBER 规则. (当然,CLOSE_QUOTE 上的 popMode 将词法分析器弹回 top-level 默认词法分析器模式。您应该考虑使用 grun 工具转储令牌流(-tokens 选项),因为它可能会使这一点更清楚。

注意:一般STRING Lexer规则比这更复杂(建议查看其他语法中的STRING规则)。但是,这应该可以处理您理解 Lexer 模式的测试。