首页 > 解决方案 > 如何解析无法转换为解析器规则的长词法规则的标记?

问题描述

我正在尝试用 ANTLR4 解析这个:

> A Request [AR]
Commments might have many lines here
Line 2
 
- A Response [A]
- The other response [B]
Response can also have lines here.

> Request [A]
- Responce

下面的代码很好地解析了它:

grammar Response;

prog: (request | response)+ EOF;

request: REQUEST TEXT*;
response: RESPONSE TEXT*;
 
REQUEST: '>' TEXT '[' ID ']';
RESPONSE: '-' TEXT ('[' ID ']')?;
 
ID: [a-zA-Z] [a-zA-Z0-9._]*;
TEXT: ~[\r\n]+;
 
EMPTY: [ \t\r\n]+ -> skip;

这是一个很好的结果。但是我想分别解析 ID 和 TEXT。因为这些是长词法分析器规则中的标记,所以似乎不支持。

据我了解,通常在这种情况下,您可以将词法分析器规则 REQUEST 和 RESPONSE 替换为解析器规则,如 request_rule 和 response_rule。

但这在这里不起作用,因为 TEXT 词法分析器规则将匹配每一行。例如,如果我将 REQUEST 和 RESPONSE 替换为 ruleREQUEST 和 ruleRESPONSE:

我正试图弄清楚如何继续......似乎唯一的方法是使用一些popMode和pushMode使代码更加复杂,如下所述:

https://github.com/antlr/antlr4/issues/2229(不正确的词法分析器规则优先级与“非”规则)

有没有什么简单的方法,根据antlr4的原始代码来获取C#Antlr4.Runtime.Standard中的TEXT和ID值?除此之外,代码完美运行。

标签: antlr4

解决方案


TEXT 是贪婪的,因此它最匹配所有其他词法分析器规则。您需要通过添加“?”来使其不贪心。'+' 后的运算符。

但是,一旦您这样做了,就需要更改解析器规则以允许使用不同的令牌。

这是一个可以代替的语法。它适用于您的输入,但您可能需要进行进一步的更改。

grammar Response;

prog: (request | response)+ EOF;
request: request_rule text*;
response: response_rule text*;
request_rule: '>' text '[' ID ']';
response_rule: '-' text ('[' ID ']')?;
text: (ID | TEXT)+;
ID: [a-zA-Z] [a-zA-Z0-9._]*;
GT: '>';
LP: '[';
RP: ']';
DS: '-';
TEXT: ~[\r\n]+?;
EMPTY: [ \t\r\n]+ -> skip;

推荐阅读