使用 Antlr 防止 "Antlr4.Runtime.NoViableAltException"
Prevent "Antlr4.Runtime.NoViableAltException" with Antlr
我正在使用 Antlr 4(C# 实现),每当要解析的字符串很复杂时,我都会收到以下异常。
A first chance exception of type 'Antlr4.Runtime.NoViableAltException' occurred in DataImportClassLibrary.dll
这个有效:
[Pitch Angle] > 5
这个产生错误:
[Pitch Angle] > 5 AND [Pressure Altitude] < 10000
语法:
grammar EventDetection;
AND : 'AND' ;
OR : 'OR' ;
GT : '>' ;
GE : '>=' ;
LT : '<' ;
LE : '<=' ;
EQ : '=' ;
LPAREN : '(' ;
RPAREN : ')' ;
DECIMAL : '-'?[0-9]+('.'[0-9]+)? ;
IDENTIFIER : '[' [a-zA-Z_][a-zA-Z_0-9 ]* ']';
SEMI : ';' ;
COMMENT : '//' .+? ('\n'|EOF);// -> skip ;
WS : [ \r\t\u000C\n]+;// -> skip ;
rule_set : single_rule* ;
single_rule : logical_expr ;
logical_expr : logical_expr AND logical_expr # LogicalExpressionAnd
| logical_expr OR logical_expr # LogicalExpressionOr
| comparison_expr # ComparisonExpression
| LPAREN logical_expr RPAREN # LogicalExpressionInParen
;
comparison_expr : IDENTIFIER comp_operator DECIMAL # ComparisonExpressionWithOperator
;
comp_operator : GT
| GE
| LT
| LE
| EQ
;
- 有没有办法强制词法分析器对规则进行优先排序?例如。如果它只是先选择 OR,我认为我不会遇到这个问题。
- 我需要在代码中处理这个吗?
由于您将 AND
定义为 logical_expr
中的第一个替代项,因此生成的解析器将首先解析 5 AND [Pressure Altitude]
,而不是 [Pitch Angle] > 5
。
您可能需要在 AND
和 OR
之前定义 comparison_expr
:
logical_expr : comparison_expr # ComparisonExpression
| logical_expr AND logical_expr # LogicalExpressionAnd
| logical_expr OR logical_expr # LogicalExpressionOr
| LPAREN logical_expr RPAREN # LogicalExpressionInParen
;
我使用了您的语法文件并且能够解析您提供的两个输入字符串。
为了使其正常工作,我取消了对“-> skip;”的注释。你有你的规则。你能试试看吗?
COMMENT : '//' .+? ('\n'|EOF) -> skip ;
WS : [ \r\t\u000C\n]+ -> skip ;
事实证明问题出在空格上。如果我将输入字符串更改为:
[Pitch Angle]>5AND[Pressure Altitude]<10000
它起作用了,尽管我有处理空格的规则。
解决方案是将其更改为以下内容:
WS : [ \r\t\u000C\n]+ -> channel(HIDDEN);
感谢调查此问题的人。
我正在使用 Antlr 4(C# 实现),每当要解析的字符串很复杂时,我都会收到以下异常。
A first chance exception of type 'Antlr4.Runtime.NoViableAltException' occurred in DataImportClassLibrary.dll
这个有效:
[Pitch Angle] > 5
这个产生错误:
[Pitch Angle] > 5 AND [Pressure Altitude] < 10000
语法:
grammar EventDetection;
AND : 'AND' ;
OR : 'OR' ;
GT : '>' ;
GE : '>=' ;
LT : '<' ;
LE : '<=' ;
EQ : '=' ;
LPAREN : '(' ;
RPAREN : ')' ;
DECIMAL : '-'?[0-9]+('.'[0-9]+)? ;
IDENTIFIER : '[' [a-zA-Z_][a-zA-Z_0-9 ]* ']';
SEMI : ';' ;
COMMENT : '//' .+? ('\n'|EOF);// -> skip ;
WS : [ \r\t\u000C\n]+;// -> skip ;
rule_set : single_rule* ;
single_rule : logical_expr ;
logical_expr : logical_expr AND logical_expr # LogicalExpressionAnd
| logical_expr OR logical_expr # LogicalExpressionOr
| comparison_expr # ComparisonExpression
| LPAREN logical_expr RPAREN # LogicalExpressionInParen
;
comparison_expr : IDENTIFIER comp_operator DECIMAL # ComparisonExpressionWithOperator
;
comp_operator : GT
| GE
| LT
| LE
| EQ
;
- 有没有办法强制词法分析器对规则进行优先排序?例如。如果它只是先选择 OR,我认为我不会遇到这个问题。
- 我需要在代码中处理这个吗?
由于您将 AND
定义为 logical_expr
中的第一个替代项,因此生成的解析器将首先解析 5 AND [Pressure Altitude]
,而不是 [Pitch Angle] > 5
。
您可能需要在 AND
和 OR
之前定义 comparison_expr
:
logical_expr : comparison_expr # ComparisonExpression
| logical_expr AND logical_expr # LogicalExpressionAnd
| logical_expr OR logical_expr # LogicalExpressionOr
| LPAREN logical_expr RPAREN # LogicalExpressionInParen
;
我使用了您的语法文件并且能够解析您提供的两个输入字符串。
为了使其正常工作,我取消了对“-> skip;”的注释。你有你的规则。你能试试看吗?
COMMENT : '//' .+? ('\n'|EOF) -> skip ;
WS : [ \r\t\u000C\n]+ -> skip ;
事实证明问题出在空格上。如果我将输入字符串更改为:
[Pitch Angle]>5AND[Pressure Altitude]<10000
它起作用了,尽管我有处理空格的规则。
解决方案是将其更改为以下内容:
WS : [ \r\t\u000C\n]+ -> channel(HIDDEN);
感谢调查此问题的人。