Antlr4使用相同符号的不同词法规则

时间:2016-10-27 18:41:12

标签: antlr antlr4

我有以下语法:

grammar Test2;

my_rule: 'start' L_PAREN dummy R_PAREN DOT;
dummy: upper_word|lower_word|single_quoted|distinct_object|dollar_word|dollar_dollar_word;

single_quoted               : SINGLE_QUOTE single_quoted_entry SINGLE_QUOTE;
single_quoted_entry         : SQ_CHAR+;

distinct_object             : DOUBLE_QUOTE distinct_object_entry DOUBLE_QUOTE ;
distinct_object_entry       : DO_CHAR+;

dollar_dollar_word          : DOLLAR DOLLAR lower_word; // make lower word token for the word
dollar_word                 : DOLLAR lower_word; // make lower word token for the word
upper_word                  : UPPER_WORD; // necessary since it should be one token
UPPER_WORD                  : UPPER_ALPHA ALPHA_NUMERIC*;
lower_word                  : LOWER_WORD; // necessary since it should be one token
LOWER_WORD                  : LOWER_ALPHA ALPHA_NUMERIC*;

DOLLAR                      : '$';
L_PAREN                     : '(';
R_PAREN                     : ')';
L_SQUARE_BRACKET            : '[';
R_SQUARE_BRACKET            : ']';
COMMA                       : ',';
VLINE                       : '|';
STAR                        : '*';
PLUS                        : '+';
ARROW                       : '>';
LESS_SIGN                   : '<';
DOT                         : '.';
UNDERSCORE                  : '_';

NUMERIC                     : [0-9];
LOWER_ALPHA                 : [a-z];
UPPER_ALPHA                 : [A-Z];
ALPHA_NUMERIC               : LOWER_ALPHA
                            | UPPER_ALPHA
                            | NUMERIC
                            | UNDERSCORE;

DOUBLE_QUOTE                : '"';
DO_CHAR                     : [\u0028-\u0029\u002B-\u0085\u0087-\u00B0]; // for double_quoted
SINGLE_QUOTE                : '\'' ;
SQ_CHAR                     : [\u0028-\u002E\u0032-\u0085\u0087-\u00B0]; // for single_quoted

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

从my_rule开始,虚拟规则可以输入upper_word,lower_word,dollar_word,dollar_dollar_word。 但是single_quoted和distinct_object不会起作用,因为它们期望SQ_CHAR +或DO_CHAR +也覆盖已经定义的标记,例如UPPER_ALPHA等许多其他标记。

解决方案是将带有管道的所有已定义标记添加到使用SQ_CHAR / DO_CHAR的位置。这可能看起来与此类似,但管道更多:

single_quoted               : SINGLE_QUOTE single_quoted_entry SINGLE_QUOTE;
single_quoted_entry         : (SQ_CHAR|UPPER_ALPHA|...way more tokens here...)+;

double_quoted再次相同。由于这是一项繁琐的任务,需要检查所有已定义为令牌的ascii代码,并且在更改语法时容易出错,因此更简单的解决方案将是有利的。

有没有简单的解决方案?

1 个答案:

答案 0 :(得分:0)

我找到了另一个适用的解决方案,因为我没有在语法中的其他地方使用单引号和双引号。

创建包含引号的词法分析器标记有效:

grammar Test2;

my_rule: 'start' L_PAREN dummy R_PAREN DOT;
dummy: upper_word|lower_word|single_quoted|distinct_object|dollar_word|dollar_dollar_word;

single_quoted               : SINGLE_QUOTED;
SINGLE_QUOTED               : SINGLE_QUOTE SQ_CHAR+ SINGLE_QUOTE;
distinct_object             : DISTINCT_OBJECT;
DISTINCT_OBJECT             : DOUBLE_QUOTE DO_CHAR+ DOUBLE_QUOTE;

dollar_dollar_word          : DOLLAR DOLLAR lower_word; // make lower word token for the word
dollar_word                 : DOLLAR lower_word; // make lower word token for the word
upper_word                  : UPPER_WORD; // necessary since it should be one token
UPPER_WORD                  : UPPER_ALPHA ALPHA_NUMERIC*;
lower_word                  : LOWER_WORD; // necessary since it should be one token
LOWER_WORD                  : LOWER_ALPHA ALPHA_NUMERIC*;

DOLLAR                      : '$';
L_PAREN                     : '(';
R_PAREN                     : ')';
L_SQUARE_BRACKET            : '[';
R_SQUARE_BRACKET            : ']';
COMMA                       : ',';
VLINE                       : '|';
STAR                        : '*';
PLUS                        : '+';
ARROW                       : '>';
LESS_SIGN                   : '<';
DOT                         : '.';
UNDERSCORE                  : '_';

NUMERIC                     : [0-9];
LOWER_ALPHA                 : [a-z];
UPPER_ALPHA                 : [A-Z];
ALPHA_NUMERIC               : LOWER_ALPHA
                            | UPPER_ALPHA
                            | NUMERIC
                            | UNDERSCORE;

DOUBLE_QUOTE                : '"';
DO_CHAR                     : [\u0028-\u0029\u002B-\u0085\u0087-\u00B0]; // for double_quoted
SINGLE_QUOTE                : '\'' ;
SQ_CHAR                     : [\u0028-\u002E\u0032-\u0085\u0087-\u00B0]; // for single_quoted

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

SINGLE_QUOTED,DISTINCT_OBJECT,UPPER_WORD和LOWER_WORD的位置无关紧要(已测试)。

请注意,此解决方案不会为引号创建额外的叶子。