当前位置: 首页 > 知识库问答 >
问题:

ANTLR4中来自列表的令牌的非贪婪匹配

柳英豪
2023-03-14
grammar Hello;

file     : ( fixedSentence )* EOF ;
sentence : KEYWORD1 ID+ KEYWORD2 ID+ PERIOD
         | KEYWORD3 ID+ KEYWORD4 ID+ PERIOD;

KEYWORD1 : 'hello' | 'howdy' | 'hi' ;
KEYWORD2 : 'bye' | 'goodbye' | 'adios' ;
KEYWORD3 : 'dear' | 'dearest' ;
KEYWORD4 : 'love' | 'yours' ;
PERIOD  : '.' ;
ID      : [a-z]+ ;
WS      : [ \t\r\n]+ -> skip ;
hello snickers bar goodbye mars bar.
dear peter this is fun yours james.

效果很好。但是我也想匹配包含关键字的句子,这些关键字不会被期望终止ID+块。例如

hello hello kitty goodbye my dearest raggedy ann and andy.

hellofist显示为keyword1,然后作为第一个ID+的一部分。按照上面链接的问题的例子,我可以这样修复它:

// ugly solution:
fixedSentence : KEYWORD1 a=(ID|KEYWORD1|KEYWORD3|KEYWORD4)+ KEYWORD2 b=(ID|KEYWORD1|KEYWORD2|KEYWORD3|KEYWORD4)+ PERIOD
              | KEYWORD3 a=(ID|KEYWORD1|KEYWORD2|KEYWORD3)+ KEYWORD4 b=(ID|KEYWORD1|KEYWORD2|KEYWORD3|KEYWORD4)+ PERIOD;

它起作用了,而且做的正是我想要的。在我的真实语言中,我有数百个关键字列表,用于不同类型的句子,所以如果我尝试这种方法,我肯定会犯错误,当我在我的语言中创建新的结构时,我必须返回并编辑所有其他结构。

最好是从列表中进行非贪婪匹配,遵循ANTLR4书中的示例进行注释。所以我试了这个

// non-greedy matching concept:
KEYWORD : KEYWORD1 | KEYWORD2 | KEYWORD3 | KEYWORD4 ;
niceID : ( ID | KEYWORD ) ;
niceSentence : KEYWORD1 niceID+? KEYWORD2 niceID+? PERIOD
             | KEYWORD2 niceID+? KEYWORD3 niceID+? PERIOD;

我认为它遵循了评论的模式(例如在书的第81页中给出的):

COMMENT : '/*' .*? '*/' -> skip ;

通过使用来表示不贪婪。(尽管示例是lexer规则,但这是否改变了这里的含义?)FixedStrence有效,但NiceSentence失败。从这里我要去哪里?

line 1:6 extraneous input 'hello' expecting ID
line 1:29 extraneous input 'dearest' expecting {'.', ID}
line 1:6 extraneous input 'hello' expecting {ID, KEYWORD}
line 1:29 extraneous input 'dearest' expecting {KEYWORD2, ID, KEYWORD}
line 1:57 extraneous input '.' expecting {KEYWORD2, ID, KEYWORD}

如果查看解析树有帮助,这里是它们。

共有1个答案

夹谷成龙
2023-03-14

认识到解析器最适合处理语法,即结构,而不是语义区别。关键字在一个上下文中是否是ID终止符,而在另一个上下文中是否是ID终止符,这两者在语法上是等价的,这是本质上的语义问题。

处理语义歧义的典型ANTLR方法是创建一个解析树,识别尽可能多的结构差异,然后遍历树,分析每个节点与周围节点的关系(在本例中),以解决歧义。

如果解析器为

sentences : ( ID+ PERIOD )* EOF ;

那么你的句子基本上是自由形式的。更合适的工具可能是NLP库--斯坦福有一个很好的工具。

附加

如果将lexer规则定义为

KEYWORD1 : 'hello' | 'howdy' | 'hi' ;
KEYWORD2 : 'bye' | 'goodbye' | 'adios' ;
KEYWORD3 : 'dear' | 'dearest' ;
KEYWORD4 : 'love' | 'yours' ;
. . . .
KEYWORD : KEYWORD1 | KEYWORD2 | KEYWORD3 | KEYWORD4 ;
hello    hello    kitty goodbye  my dearest  ...
KEYWORD1 KEYWORD1 ID    KEYWORD2 ID KEYWORD3 ...
niceID : ( ID | keyword ) ;
keyword : KEYWORD1 | KEYWORD2 | KEYWORD3 | KEYWORD4 ;
 类似资料:
  • 基本上,我试图为lexer指定尝试匹配(LOWCHARHIGHCHAR)的非贪婪方式,因此它停止在关键字lookahead。到目前为止,我所读到的关于ANTLR lexer的内容是,应该有某种lexer规则的优先级。如果我在lexer语法中首先指定关键字lexer规则,那么后面的任何lexer规则都不能匹配所使用的字符。 经过一番搜索,我明白了这里的问题是它不能以正确的方式标记输入,因为例如对于输

  • 据我所知,非贪婪匹配不是基本正则表达式(BRE)和扩展正则表达式(ERE)的一部分。然而,不同版本的(BSD和GNU)上的行为似乎表明了另一种明智的做法。 举个例子,我们来看下面这个例子。我有一串话要说: 以下是从字符串中提取< code>hello的一些尝试。 BRE尝试(失败): 输出产生整个字符串,这表明非贪婪量词在 BRE 上不起作用。请注意,我只是转义,因为不会失去它的意义,也不需要转义

  • 本文向大家介绍python re模块匹配贪婪和非贪婪模式详解,包括了python re模块匹配贪婪和非贪婪模式详解的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了python re模块匹配贪婪和非贪婪模式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 python贪婪和非贪婪 正则表达式通常用于在文本中查找匹配的字符串。Pytho

  • 本文向大家介绍php正则表达式中贪婪与非贪婪介绍,包括了php正则表达式中贪婪与非贪婪介绍的使用技巧和注意事项,需要的朋友参考一下 一、贪婪与非贪婪 什么叫贪婪,比如说要从字符串中<td>面包一</td><td>面包二</td>吃面包,本来你只可以吃面包一,可是你贪心,于是就把第一个<td>到最后一个</td>里面的两个面包取出来了,你想多吃点,非贪婪也就是你不贪吃了,就只吃面包一。 我们来看看正

  • 问题内容: 我有下一个代码: 并具有下一个输出: 但我认为它必须是: 有人请解释为什么。 问题答案: 由于您的模式是非贪婪的,因此它们在仍由匹配项组成的情况下,匹配的文本越少越好。 去除 ?在第二组中,您会得到 单词 word word big small

  • 我是一个Antlr4新手,有一个相对简单的语法问题。语法在末尾的底部给出。(这是一个语法片段,用于分析生物序列变体的描述)。 在下面的单元测试中,我试图解析字符串。 这里出了什么问题?我在哪里可以学习如何解决这个问题?