支持ANTLR语法中的二进制运算符和引号



我们尝试以以下形式解析查询:

Taiwan OR China
Taiwan OR "Republic of China"

本质上,像OR/AND/NOT这样的二元运算符将用于构造此类查询,引号用于标记包含多个单词的术语。然后,我们的目标是在此处提取各个名称:

  • 第一种情况下的台湾和中国
  • 第二种情况下的台湾中华民国

(问题更复杂,但这是第一个里程碑(

从基础知识开始,对于第一个用例,我们将提供以下内容

grammar Query;
parse : expr EOF ;
expr : name binop name ;
binop : 'AND' | 'OR' | 'NOT' ;
name
:  WORD
;
WORD              : ('a' .. 'z' | 'A' .. 'Z')+ ;
WS : [ trn]+ -> skip ;

当试图扩展它以捕获引号并处理引号内术语的空格时,我们有点挣扎。

我们尝试了这样的事情:

grammar Query;
parse : expr EOF ;
expr : name binop name ;
binop : 'AND' | 'OR' | 'NOT' ;
name
:  WORD
| '"' NAME_WITH_SPACES '"'
;
WORD              : ('a' .. 'z' | 'A' .. 'Z')+ ;
NAME_WITH_SPACES  : ('a' .. 'z' | 'A' .. 'Z' | ' ')+ ;
WS : [ trn]+ -> skip ;

更具体地说,输出是:

line 1:0 mismatched input 'TAIWAN OR CHINA' expecting {'"', WORD}

分别:

line 1:0 extraneous input 'TAIWAN OR ' expecting {'"', WORD}
line 1:29 mismatched input '<EOF>' expecting {'AND', 'OR', 'NOT'}

我们理解在尝试在引号内包含空格时可能会有摩擦,同时跳过引号外的空格。

任何想法都会受到欢迎 - 作为新的两个,很难说如何适应这些围绕空白的冲突要求。

不,这个:

name
:  WORD
| '"' NAME_WITH_SPACES '"'
;
...
NAME_WITH_SPACES  : ('a' .. 'z' | 'A' .. 'Z' | ' ')+ ;

与以下不同:

name
: WORD
| NAME_WITH_SPACES
;
...
NAME_WITH_SPACES  : '"' ('a' .. 'z' | 'A' .. 'Z' | ' ')+ '"' ;

在第一种情况下,像Taiwan OR "Republic of China"这样的输入被标记如下:

  • Taiwan OR(类型:NAME_WITH_SPACES(
  • "
  • Republic of China(类型:NAME_WITH_SPACES(
  • "

因为 ANTLR 的词法分析器规则试图匹配尽可能多的字符。因此,如果您让引号包含在NAME_WITH_SPACES词法分析器规则中:

NAME_WITH_SPACES  : '"' ('a' .. 'z' | 'A' .. 'Z' | ' ')+ '"' ;

然后将输入Taiwan OR "Republic of China"标记为:

  • Taiwan(类型:单词(
  • OR(类型:或(
  • "Republic of China"(类型:NAME_WITH_SPACES(

并且正确跳过带引号的标记之外的空格。

请注意,您可以这样编写它:

WORD              : [a-zA-Z]+ ;
NAME_WITH_SPACES  : '"' [a-zA-Z ]+ '"' ;

另请参阅此相关问答:ANTLR中解析器规则和词法分析器规则之间的实际区别?

进一步,我们尝试了以下内容:

grammar Query;
parse : expr EOF ;
expr : name binop name ;
binop : 'AND' | 'OR' | 'NOT' ;
name
: WORD
| NAME_WITH_SPACES
;
WORD              : ('a' .. 'z' | 'A' .. 'Z')+ ;
NAME_WITH_SPACES  : '"' ('a' .. 'z' | 'A' .. 'Z' | ' ')+ '"' ;
WS : [ trn]+ -> skip ;

这似乎工作得很好,即使对我来说它似乎与我们第一次尝试没有奏效的语义相同:

grammar Query;
parse : expr EOF ;
expr : name binop name ;
binop : 'AND' | 'OR' | 'NOT' ;
name
:  WORD
| '"' NAME_WITH_SPACES '"'
;
WORD              : ('a' .. 'z' | 'A' .. 'Z')+ ;
NAME_WITH_SPACES  : ('a' .. 'z' | 'A' .. 'Z' | ' ')+ ;
WS : [ trn]+ -> skip ;

相关内容

  • 没有找到相关文章

最新更新