ANTLR试图创建一个词法规则,但不包括某些符号

时间:2017-07-17 04:17:07

标签: antlr antlr4 lexer

我使用ANTLR4来解析用Yarn编写的文本冒险游戏对话文件,所以大部分都是自由格式的文本和大量的孤岛语法,而且大部分内容都很顺利但是我有一个问题排除Shortcut模式中的某些文字(当呈现供玩家选择的选项时)。

基本上我需要编写规则来匹配除#,换行符或<<之外的任何内容。当它到达<<时,它需要进入一种新模式来处理各种表达式,或者只是离开当前模式,以便<<将被现有规则选中。

我的词法分析器的缩减版本(忽略表达式规则):

lexer grammar YarnLexer;

NEWLINE : ('\n') -> skip;

CMD : '<<' -> pushMode(Command);
SHORTCUT : '->' -> pushMode(Shortcut);

HASHTAG : '#' ;

LINE_GOBBLE : . -> more, pushMode(Line);

mode Line;
LINE : ~('\n'|'#')* -> popMode;

mode Shortcut ;
TEXT : CHAR+ -> popMode;
fragment CHAR : ~('#'|'\n'|'<');

mode Command ;
CMD_EXIT : '>>' -> popMode;

// RULES FOR OPERATORS/IDs/NUMBERS/KEYWORDS/etc
CMD_TEXT : ~('>')+ ;

解析器语法(再次忽略表达式的所有规则):

parser grammar YarnParser;

options { tokenVocab=YarnLexer; }

dialogue: statement+ EOF;

statement : line_statement | shortcut_statement | command_statement ;

hashtag : HASHTAG LINE ;

line_statement : LINE hashtag? ;

shortcut_statement : SHORTCUT TEXT command_statement? hashtag?;

command_statement : CMD expression CMD_EXIT;
expression : CMD_TEXT ;

我已经测试了命令模式,当它本身和内部的所有内容都正常工作时,但是当我尝试解析我的示例输入时:

Where should we go?
-> the park
-> the zoo
-> Peter's house <<if $metPeter == true >>

ok shall we take the bus?
-> :<
-> ok

<<set $daySpent = true>>

我的问题是这一行:

-> Peter's house <<if $metPeter == true >>

完全匹配为TEXT,并且CMD规则被更长的TEXT忽略了。

我的第一个想法是将<添加到集合中,但之后我无法使用以下文字:

-> :<

应该是完全有效的。知道怎么做吗?

1 个答案:

答案 0 :(得分:0)

将单个左尖括号添加到排除列表会创建一个易于处理的单角案例:

TEXT : CHAR+ ;
CMD  : '<<' -> pushMode(Command);
LAB  : '<'  -> type(TEXT) ;

fragment CHAR : ~('\n' | '#' | '<') ;