类似谷歌查询的antlr4学习示例.如何获取值字符串?为什么要提前停止使用定义的值



只是,作为一个学习过程,我想模拟一个较短版本的谷歌高级搜索查询[1]。在这种情况下,仅使用";站点";以及";文件类型";关键字。因此,我需要:

  1. 将除关键字之外的所有内容:值解释为文本查询(语法中的query_string(
  2. 解释定义的关键字:值(语法中的binary_op(

输入:";文本搜索网站:foo">

当前结果

当前语法(发布在下面(和定义的输入失败:

line 1:0 extraneous input 'text' expecting {'(', SITE, FILETYPE, STRING}
(start (logic_expr text (expr (query_string  ))))

预期结果

有了定义的语法,我会期待另一个结果:

(start (logic_expr (expr (query_string t e x t   t o   s e a r c h  )) (expr (binary_op (varname site) : (value foo)))))

问题

  1. 为什么语法在文本的第一个元素处失败?

  2. 如果我改变";值";rule到STRING并注释VALUE lexer规则,它几乎可以工作,但它不遵循请求。当然,它只是作为非贪婪来消耗价值。

    2.1现在,在语法中,我可以评论或不评论VALUE规则。为什么即使我没有使用VALUE规则,行为也会发生如此大的变化?,我尝试交换STRING和VALUE规则,但这不会影响结果。

GRAMMAR

grammar Google;
// Fragments (not tokens)
fragment A: ('a' | 'A'); // match either an 'a' or 'A'
fragment B: ('b' | 'B');
fragment C: ('c' | 'C');
fragment D: ('d' | 'D');
fragment E: ('e' | 'E');
fragment F: ('f' | 'F');
fragment G: ('g' | 'G');
fragment H: ('h' | 'H');
fragment I: ('i' | 'I');
fragment J: ('j' | 'J');
fragment K: ('k' | 'K');
fragment L: ('l' | 'L');
fragment M: ('m' | 'M');
fragment N: ('n' | 'N');
fragment O: ('o' | 'O');
fragment P: ('p' | 'P');
fragment Q: ('q' | 'Q');
fragment R: ('r' | 'R');
fragment S: ('s' | 'S');
fragment T: ('t' | 'T');
fragment U: ('u' | 'U');
fragment V: ('v' | 'V');
fragment W: ('w' | 'W');
fragment X: ('x' | 'X');
fragment Y: ('y' | 'Y');
fragment Z: ('z' | 'Z');
// Lexer rules (tokens)
WHITE_SPACE: [trn] -> skip;  // Every space like except the space properly
AND : A N D;
OR  : O R;
SITE: S I T E;
FILETYPE: F I L E T Y P E;
// ... other keywords ...
VALUE: (~[ ])+;  // Everything except space. Fails if enabled. Why ?
STRING: .+?;  // Non-greedy comsumption

// Grammar
start: logic_expr ;
logic_expr
: '(' logic_expr+ ')'           # parenthesis_logic_expr_operator
| logic_expr (AND logic_expr)+  # and_logic_expr_operator
| logic_expr (OR logic_expr)+   # or_logic_expr_operator
| expr+                         # terminal_logic_expr_operator
;

expr
: (query_string | binary_op) ;
query_string: STRING+;
varname
: SITE
| FILETYPE
// others ..
;
value: VALUE;
binary_op
: varname ':' value;

[1] -https://support.google.com/websearch/answer/2466433?hl=en

默认情况下,ANTLR的lexer规则是贪婪的。因此,如果执行VALUE: (~[ ])+;,它将匹配site:foo(并且将不匹配解析器规则binary_op : varname ':' value;!(。此外,当执行STRING : .+?;时,将只匹配1个字符。只有在后面跟有终止字符的情况下,才应使用.+?

WHITE_SPACE: [trn] -> skip; // Every space like except the space properly

为什么?在您的用例中,您确实需要跳过空格AFAIK。

我(稍微(编辑了你的语法,以便它能与你的输入一起工作:

grammar Google;
// Grammar
start: logic_expr EOF;
logic_expr
: '(' logic_expr+ ')'           # parenthesis_logic_expr_operator
| logic_expr (AND logic_expr)+  # and_logic_expr_operator
| logic_expr (OR logic_expr)+   # or_logic_expr_operator
| expr+                         # terminal_logic_expr_operator
;

expr
: (query_string | binary_op) ;
query_string: STRING+;
varname
: SITE
| FILETYPE
// others ..
;
value: STRING;
binary_op
: varname ':' value;
// Lexer rules (tokens)
WHITE_SPACE: [ trn] -> skip;
AND : A N D;
OR  : O R;
SITE: S I T E;
FILETYPE: F I L E T Y P E;
// ... other keywords ...
STRING: ~[ :]+;
// Fragments (not tokens)
fragment A: [aA];
fragment B: [bB];
fragment C: [cC];
fragment D: [dD];
fragment E: [eE];
fragment F: [fF];
fragment G: [gG];
fragment H: [hH];
fragment I: [iI];
fragment J: [jJ];
fragment K: [kK];
fragment L: [lL];
fragment M: [mM];
fragment N: [nN];
fragment O: [oO];
fragment P: [pP];
fragment Q: [qQ];
fragment R: [rR];
fragment S: [sS];
fragment T: [tT];
fragment U: [uU];
fragment V: [vV];
fragment W: [wW];
fragment X: [xX];
fragment Y: [yY];
fragment Z: [zZ];

主要变化有:

  • 删除VALUE
  • STRING : .+?;更改为STRING: ~[ :]+;
  • WHITE_SPACE: [trn] -> skip;更改为WHITE_SPACE: [ trn] -> skip;

如果你想支持site:site这样的语法(请参阅Antlr4如何构建语法允许的关键字作为标识符(,你需要更改:

value: STRING;

进入:

value: STRING | varname;

相关内容

  • 没有找到相关文章

最新更新