gpt4 book ai didi

java - ANTLR:以编程方式运行解析器时忽略语法错误

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:23:01 26 4
gpt4 key购买 nike

我目前正在使用 ANTLR 创建一个或多或少简单的表达式求值器。

我的语法很简单(至少我希望如此)并且看起来像这样:

grammar SXLGrammar;

options {
language = Java;
output = AST;
}

tokens {
OR = 'OR';
AND = 'AND';
NOT = 'NOT';
GT = '>'; //greater then
GE = '>='; //greater then or equal
LT = '<'; //lower then
LE = '<='; //lower then or equal
EQ = '=';
NEQ = '!='; //Not equal
PLUS = '+';
MINUS = '-';
MULTIPLY = '*';
DIVISION = '/';
CALL;
}

@header {
package somepackage;
}

@members {

}


@lexer::header {
package rise.spics.sxl;
}

rule
: ('='|':')! expression
;

expression
: booleanOrExpression
;

booleanOrExpression
:
booleanAndExpression ('OR'^ booleanAndExpression)*
;

booleanAndExpression
:
booleanNotExpression ('AND'^ booleanNotExpression)*
;

booleanNotExpression
:
('NOT'^)? booleanAtom
;

booleanAtom
:
| compareExpression
;

compareExpression
:
commonExpression (('<' | '>' | '=' | '<=' | '>=' | '!=' )^ commonExpression)?
;

commonExpression
:
multExpr
(
(
'+'^
| '-'^
)
multExpr
)*
| DATE
;

multExpr
:
atom (('*'|'/')^ atom)*
| '-'^ atom
;

atom
:
INTEGER
| DECIMAL
| BOOLEAN
| ID
| '(' expression ')' -> expression
| functionCall
;

functionCall
:
ID '(' arguments ')' -> ^(CALL ID arguments?)
;

arguments
:
(expression) (','! expression)*
| WS
;

BOOLEAN
:
'true'
| 'false'
;

ID
:
(
'a'..'z'
| 'A'..'Z'
)+
;

INTEGER
:
('0'..'9')+
;

DECIMAL
:
('0'..'9')+ ('.' ('0'..'9')*)?
;

DATE
:
'!' '0'..'9' '0'..'9' '0'..'9' '0'..'9' '-' '0'..'9' '0'..'9' '-' '0'..'9' '0'..'9' (' ' '0'..'9' '0'..'9' ':''0'..'9' '0'..'9' (':''0'..'9' '0'..'9')?)?
;

WS
: (' '|'\t' | '\n' | '\r' | '\f')+ { $channel = HIDDEN; };

现在,如果我尝试解析一个无效的表达式,如“= true NOT true”,eclipse 插件的图形测试工具会抛出一个 NoViableAltException:第 1:6 行在输入“NOT”时没有可行的替代方案,这是正确的并且假设。

现在,如果我尝试在 Java 程序中解析表达式,什么也不会发生。程序

    String expression = "=true NOT false";

CharStream input = new ANTLRStringStream(expression);
SXLGrammarLexer lexer = new SXLGrammarLexer(input);
TokenStream tokenStream = new CommonTokenStream(lexer);
SXLGrammarParser parser = new SXLGrammarParser(tokenStream);
CommonTree tree = (CommonTree) parser.rule().getTree();
System.out.println(tree.toStringTree());
System.out.println(parser.getNumberOfSyntaxErrors());

会输出:

true
0

这意味着,解析器创建的 AST 只存在一个节点,而忽略其余节点。我想处理我的应用程序中的语法错误,但如果生成的解析器没有发现任何错误,那是不可能的。

我还尝试通过使用如下内容覆盖 displayRecognitionError() 方法来更改解析器:

public void displayRecognitionError(String[] tokenNames,
RecognitionException e) {
String msg = getErrorMessage(e, tokenNames);
throw new RuntimeException("Error at position "+e.index+" " + msg);
}

但 displayRecognitionError 从未被调用。

如果我尝试类似“=1+”的操作,则会显示错误。我想我的语法有问题,但为什么 eclipse 插件会抛出该错误,而生成的解析器却不会?

最佳答案

如果您希望 rule 消耗整个 token 流,您必须指定您希望输入结束的位置。像这样:

rule
: ('='|':')! expression EOF
;

如果没有 EOF,您的解析器会将 true 读取为 boolean 值并忽略其余部分。

关于java - ANTLR:以编程方式运行解析器时忽略语法错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6678257/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com