ANTLR如何区分两条相似的评论
ANTLR how to discriminate two similar comments
在 Antlr 中,如果我有一个规则,例如:
> someRule : COMM TYPE arg EQUAL COMMENT_TEXT;
其中:
- 'COMM' : 是'|'
- 'TYPE' : 是 ('C'|'I'|'U')
- 'arg' :可以是 'number,number'(1,0) 或只是一个数字 (1)
- 等于:'='
- COMMENT_TEXT : 字符串
它将接受:
- | C10,1 = comment
- | U10 = comment
在我的语法中,这条规则是一个定义。
即使缺少其中一个“令牌”,我也想要一个通用的评论:
|C1 comment -> Generic Comment (EQUAL is missing)
|1 = comment -> Generic comment ('type' is missing)
|C = Comment -> Generic comment ('arg' is missing)
|comment ....
语法:
currLine : commentType | .....;
commentType: COMM (defComm | genComm);
defComm: TYPE arg EQUAL COMMENT_TEXT #defcom;
我怎么能说其他都是 genComm?
genComm:....
编辑:
一个可能的解决方案是:
genComment:
: TYPE arg? EQUAL? COMMENT_TEXT?
| arg EQUAL? COMMENT_TEXT?
| EQUAL COMMENT_TEXT?
| COMMENT_TEXT
;
我的解析器语法:
parser grammar ParserComments;
options {
tokenVocab = LexerComments;
}
prog : (line? EOL)+;
line : comment;
comment: SINGLE_COMMENT (defComm | genericComment);
defComm: TYPE arg EQUAL COMMENT_TEXT;
arg : (argument1) (VIRGOLA argument2)?;
argument1 : numbers ;
argument2 : numbers ;
numbers : NUMBER+ ;
genericComment
: TYPE arg? EQUAL? COMMENT_TEXT?
| arg EQUAL? COMMENT_TEXT?
| EQUAL COMMENT_TEXT?
| COMMENT_TEXT
;
// ------ general ------
ignored : . ;
我的 Lexer 语法:
lexer grammar LexerComments;
SINGLE_COMMENT : '|' -> pushMode(COMMENT);
NUMBER : [0-9];
VIRGOLA : ',';
WS : [ \t] -> skip ;
EOL : [\r\n]+;
// ------------ Everything INSIDE a COMMENT ------------
mode COMMENT;
COMMENT_NUMBER : NUMBER -> type(NUMBER);
COMMENT_VIRGOLA : VIRGOLA -> type(VIRGOLA);
TYPE : 'I'| 'U'| 'Q';
EQUAL : '=';
COMMENT_TEXT: ('a'..'z' | 'A'..'Z')+;
WS_1 : [ \t] -> skip ;
COMMENT_EOL : EOL -> type(EOL);
但正在解析:
- | Q1,0 = 文字
我在 BaseErrorListener 中收到完整的上下文和歧义错误。
一些更改似乎可以为您提供所需的结果:
1 - 当您遇到 EOL 时,您需要 popMode
退出 COMMENT
模式:
COMMENT_EOL: EOL -> type(EOL),popMode;
2 - 您可以将以下内容用于 genericComment
规则:
genericComment: .*?;
基本上说,匹配任何东西(但不要贪心),所以它不会匹配 EOL
标记。因此,它会将任何令牌带到下一个 EOL
令牌。
顺便说一句...您的 ignored
规则完全无关。解析器规则通过递归下降调用结构进行评估。如果一条规则不是起始规则,则只能通过被另一条规则引用来访问。
(有一个匹配 .
(即任何东西)的最终词法分析器规则来捕捉任何先前的词法分析器规则不匹配的东西并不少见。但这是有效的,因为词法分析器规则不是通过递归下降评估的算法)
回复:词法分析器规则
ANTLR 解析输入的第一步是将输入的字符流转换为标记流。此过程使用 Lexer 规则(以大写字母开头的规则)。此时,解析器规则无关紧要,解析器规则作用于 Lexer 产生的标记流。
当 Lexer(又名分词器)对您的输入字符进行分词时,它将根据您的所有 Lexer 规则评估您的输入。当超过 1 条规则可以匹配您的输入时,则有两种“tie-breaker”策略:
匹配最长输入字符流的Lexer规则具有最高优先级。
如果有多个规则匹配相同(最长)的字符序列,则第一个出现的规则“获胜”
在 Antlr 中,如果我有一个规则,例如:
> someRule : COMM TYPE arg EQUAL COMMENT_TEXT;
其中:
- 'COMM' : 是'|'
- 'TYPE' : 是 ('C'|'I'|'U')
- 'arg' :可以是 'number,number'(1,0) 或只是一个数字 (1)
- 等于:'='
- COMMENT_TEXT : 字符串
它将接受:
- | C10,1 = comment
- | U10 = comment
在我的语法中,这条规则是一个定义。
即使缺少其中一个“令牌”,我也想要一个通用的评论:
|C1 comment -> Generic Comment (EQUAL is missing)
|1 = comment -> Generic comment ('type' is missing)
|C = Comment -> Generic comment ('arg' is missing)
|comment ....
语法:
currLine : commentType | .....;
commentType: COMM (defComm | genComm);
defComm: TYPE arg EQUAL COMMENT_TEXT #defcom;
我怎么能说其他都是 genComm?
genComm:....
编辑:
一个可能的解决方案是:
genComment:
: TYPE arg? EQUAL? COMMENT_TEXT?
| arg EQUAL? COMMENT_TEXT?
| EQUAL COMMENT_TEXT?
| COMMENT_TEXT
;
我的解析器语法:
parser grammar ParserComments;
options {
tokenVocab = LexerComments;
}
prog : (line? EOL)+;
line : comment;
comment: SINGLE_COMMENT (defComm | genericComment);
defComm: TYPE arg EQUAL COMMENT_TEXT;
arg : (argument1) (VIRGOLA argument2)?;
argument1 : numbers ;
argument2 : numbers ;
numbers : NUMBER+ ;
genericComment
: TYPE arg? EQUAL? COMMENT_TEXT?
| arg EQUAL? COMMENT_TEXT?
| EQUAL COMMENT_TEXT?
| COMMENT_TEXT
;
// ------ general ------
ignored : . ;
我的 Lexer 语法:
lexer grammar LexerComments;
SINGLE_COMMENT : '|' -> pushMode(COMMENT);
NUMBER : [0-9];
VIRGOLA : ',';
WS : [ \t] -> skip ;
EOL : [\r\n]+;
// ------------ Everything INSIDE a COMMENT ------------
mode COMMENT;
COMMENT_NUMBER : NUMBER -> type(NUMBER);
COMMENT_VIRGOLA : VIRGOLA -> type(VIRGOLA);
TYPE : 'I'| 'U'| 'Q';
EQUAL : '=';
COMMENT_TEXT: ('a'..'z' | 'A'..'Z')+;
WS_1 : [ \t] -> skip ;
COMMENT_EOL : EOL -> type(EOL);
但正在解析:
- | Q1,0 = 文字
我在 BaseErrorListener 中收到完整的上下文和歧义错误。
一些更改似乎可以为您提供所需的结果:
1 - 当您遇到 EOL 时,您需要 popMode
退出 COMMENT
模式:
COMMENT_EOL: EOL -> type(EOL),popMode;
2 - 您可以将以下内容用于 genericComment
规则:
genericComment: .*?;
基本上说,匹配任何东西(但不要贪心),所以它不会匹配 EOL
标记。因此,它会将任何令牌带到下一个 EOL
令牌。
顺便说一句...您的 ignored
规则完全无关。解析器规则通过递归下降调用结构进行评估。如果一条规则不是起始规则,则只能通过被另一条规则引用来访问。
(有一个匹配 .
(即任何东西)的最终词法分析器规则来捕捉任何先前的词法分析器规则不匹配的东西并不少见。但这是有效的,因为词法分析器规则不是通过递归下降评估的算法)
回复:词法分析器规则
ANTLR 解析输入的第一步是将输入的字符流转换为标记流。此过程使用 Lexer 规则(以大写字母开头的规则)。此时,解析器规则无关紧要,解析器规则作用于 Lexer 产生的标记流。
当 Lexer(又名分词器)对您的输入字符进行分词时,它将根据您的所有 Lexer 规则评估您的输入。当超过 1 条规则可以匹配您的输入时,则有两种“tie-breaker”策略:
匹配最长输入字符流的Lexer规则具有最高优先级。 如果有多个规则匹配相同(最长)的字符序列,则第一个出现的规则“获胜”