问题是因为 - addExpression((EQ | NE | GT | LT | LE | GE)addExpression)+ ---。 通过这样做,我想过滤数学表达式从单独处理,除非后面跟一个关系使其整体逻辑...我不希望我的解析器解析数学表达式,如果单独...
expression
:
logicalExpression
;
primitive
:
DECIMAL
| UNSIGNED_INTEGER
| SIGNED_INTEGER
| VARIABLE
| '(' logicalExpression ')'
| '{' logicalExpression '}'
| '[' logicalExpression ']'
;
notExpression
:
(NOT)* primitive
;
signExpression
:
( '-' | '+' )* notExpression
;
mulExpression
:
signExpression ( ( '*' | '/' ) signExpression)*
;
addExpression
:
mulExpression ( ( '+' | '-' ) mulExpression)*
;
relationalExpression
:
addExpression ((EQ | NE | GT | LT | LE | GE) addExpression)+
| '(' VARIABLE ')'
| '{' VARIABLE '}'
| '[' VARIABLE ']'
| VARIABLE
;
试验:
Input string: (5) --> Expected: to fail -- Current:failed
Input string: 5*6 --> Expected: to fail -- Current:failed
Input string: A-B --> Expected: to fail -- Current:failed
Input string: A/B --> Expected: to fail -- Current:failed
Input string: 5/A --> Expected: to fail -- Current:failed
Input string: --2 --> Expected: to fail -- Current:failed
Input string: 5++ --> Expected: to fail -- Current:failed
Input string: A-B and B-A --> Expected: to fail -- Current:failed
Input string: (A and B)--> Expected: to pass {AND(A,B)} -- Current:failed
Input string: A and B--> Expected: to pass AND(A,B) -- Current:failed
Input string: (5)>6 --> Expected: to pass {GT(5,6)} -- Current:failed
Input string: 5>6 --> Expected: to pass {GT(5,6)} -- Current:pass
Input string: 5*6 < 6-5 --> Expected: to pass GT(MUL(5,6),SUB(5,6)) --Current:pass
Input string: A/B == B/A --> Expected: to pass -- Current:pass
Input string: (A/B)=B/A --> Expected: to pass -- Current:failed
Input string: 5 /= 5 --> Expected: to pass -- Current:pass
答案 0 :(得分:1)
下面是两个简单的ANTLR语法,演示了两种评估逻辑和算术表达式混合的方法,然后是测试类及其输出。第一个语法采用您请求的形式,使用ANTLR确定表达式类型并确保表达式值兼容。另一种形式使用语法中的动作确定表达式类型。我在这里提供它进行比较。
我在两种语法中对表达式评估进行了硬编码,以使示例更有用,并证明它们按预期工作。请注意,除了您在下面的测试代码中看到的内容之外,我还没有测试过这些语法。此外,我只包括展示感兴趣的概念所必需的操作员。添加其他内容应该很容易。
要求ANTLR保持表达式类型不同需要告诉ANTLR当运算符对多种表达式类型有效时该怎么做。例如,在下面的语法LogicRules
中,词法分析器标记LPAR
标记从规则compExpr
开始的逻辑表达式或从primaryExpr
开始的算术表达式的开头。默认情况下,ANTLR无法知道输入"(3..."
是标记逻辑表达式分组("(3 + 3 == 6)"
)的开头还是算术/数值表达式分组("(3 + 3) == 6"
)的开头。规则compExpr
中的句法谓词用于帮助ANTLR通过告诉它实际上等待和看到来区分这两个选择。
grammar LogicRules;
statement returns [boolean result]
: logicalExpr {$result = $logicalExpr.result;} EOF
;
logicalExpr returns [boolean result]
@init { $result = true;}
: lhs=compExpr {$result = $lhs.result;}
(AND rhs=compExpr
{$result = $result && $rhs.result;}
)*
;
compExpr returns [boolean result]
@init { $result = true;}
: (eqExpr) => eqExpr {$result = $eqExpr.result;}
//^^ Needs a syntactic predicate to differentiate between logical grouping and arithmetic grouping
| LPAR logicalExpr {$result = $logicalExpr.result;} RPAR
//^^ Only group logical expressions at this level.
;
eqExpr returns [boolean result]
@init {$result = true;}
: lhs=arithmeticExpr
(EQ rhs=arithmeticExpr
{$result = $result && $lhs.result == $rhs.result;}
)+
//^^ use +: a logical expression of arithmetic expressions
// requires a logical operation to produce a boolean value
;
arithmeticExpr returns [int result]
@init {$result = 0;}
: lhs=primaryExpr {$result += $lhs.result;}
(PLUS rhs=primaryExpr
{$result += $rhs.result;}
)*
;
primaryExpr returns [int result]
@init {$result = 0;}
: INT {$result = $INT.int;}
| LPAR arithmeticExpr RPAR {$result = $arithmeticExpr.result;}
//^^ Only group other numeric/arithmetic expressions at this level.
;
INT : ('0'..'9')+;
AND : '&&';
EQ : '==';
LPAR : '(';
RPAR : ')';
PLUS : '+';
WS : (' '|'\t'|'\r'|'\n')+ {skip();};
使用代码而不是ANTLR规则评估表达式的结果类型会产生如下语法。请注意,分组仅在一个级别完成,不需要语法谓词。语法整体保持相对简单。与之前的语法一样,此语法在遇到无效的类型转换时会产生错误。
grammar LogicEval;
@parser::members {
private static boolean toBoolean(Object obj){
if (obj instanceof Boolean){
return (Boolean)obj;
} else {
throw new RuntimeException("Cannot convert " + obj + " to boolean");
}
}
private static int toInt(Object obj){
if (obj instanceof Integer){
return (Integer)obj;
} else {
throw new RuntimeException("Cannot convert " + obj + " to integer");
}
}
}
statement returns [Object result]
: expr {$result = $expr.result;} EOF
;
expr returns [Object result]
: lhs=compExpr {$result = $lhs.result;}
(AND rhs=compExpr
{$result = toBoolean($result) && toBoolean($rhs.result);}
)*
;
compExpr returns [Object result]
@init {Object lhsResult = null;}
: lhs=arithmeticExpr {$result = lhsResult = $lhs.result;}
(EQ rhs=arithmeticExpr
{$result = toInt(lhsResult) == toInt($rhs.result);}
)*
;
arithmeticExpr returns [Object result]
: lhs=primaryExpr {$result = $lhs.result;}
(PLUS rhs=primaryExpr
{$result = toInt($result) + toInt($rhs.result);}
)*
;
primaryExpr returns [Object result]
: INT {$result = $INT.int;}
| LPAR expr RPAR {$result = $expr.result;}
;
INT : ('0'..'9')+;
AND : '&&';
EQ : '==';
LPAR : '(';
RPAR : ')';
PLUS : '+';
WS : (' '|'\t'|'\r'|'\n')+ {skip();};
public class LogicTest {
public static void main(String[] args) {
test("1 + 2 == 3", Result.True);
test("1 + 2 == 4", Result.False);
test("1 + 2 == 3 && 1 + 2 == 4", Result.False);
test("1 + 2 == 3 && 4 + 5 == 9", Result.True);
test("(1 + 2) == 3 && (4 + 5 == 9)", Result.True);
test("1 + 2 == (3 && 4 + 5 == 9)", Result.Failure);
test("1 && 2", Result.Failure);
test("1 + 2", Result.Failure);
}
private static void test(String rawInput, Result expectedResult){
Result rulesResult = runRules(rawInput);
Result evalResult = runEval(rawInput);
System.out.println("---\n");
System.out.printf("**Input:** %s%n%n", rawInput);
System.out.printf("**Expected Result:** %s%n%n", expectedResult);
System.out.printf("**LogicRules Result:** %s%n%n", rulesResult);
System.out.printf("**LogicRules Passed?** %s%n%n", (rulesResult == expectedResult));
System.out.printf("**LogicEval Result:** %s%n%n", evalResult);
System.out.printf("**LogicEval Passed?** %s%n%n", (evalResult == expectedResult));
}
private static Result runRules(String rawInput){
CharStream input = new ANTLRStringStream(rawInput);
LogicRulesLexer lexer = new LogicRulesLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
LogicRulesParser parser = new LogicRulesParser(tokens);
boolean result;
try {
result = parser.statement();
} catch (Exception e) {
return Result.Failure;
}
if (lexer.getNumberOfSyntaxErrors() > 0 || parser.getNumberOfSyntaxErrors() > 0){
return Result.Failure;
}
return result ? Result.True : Result.False;
}
private static Result runEval(String rawInput){
CharStream input = new ANTLRStringStream(rawInput);
LogicEvalLexer lexer = new LogicEvalLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
LogicEvalParser parser = new LogicEvalParser(tokens);
Object result;
try {
result = parser.statement();
} catch (Exception e) {
return Result.Failure;
}
if (lexer.getNumberOfSyntaxErrors() > 0 || parser.getNumberOfSyntaxErrors() > 0){
return Result.Failure;
}
if (result instanceof Boolean){
return ((Boolean)result) ? Result.True : Result.False;
} else {
return Result.Failure; //Produced a valid result, but it wasn't a boolean.
}
}
private static enum Result {
True, False, Failure;
}
}
输入: 1 + 2 == 3
预期结果: True
LogicRules结果: True
通过LogicRules? true
LogicEval结果: True
LogicEval通过了吗?是真的
输入: 1 + 2 == 4
预期结果:错误
LogicRules结果:错误
通过LogicRules? true
LogicEval结果:错误
LogicEval通过了吗?是真的
输入 1 + 2 == 3&amp;&amp; 1 + 2 == 4
预期结果:错误
LogicRules结果:错误
通过LogicRules? true
LogicEval结果:错误
LogicEval通过了吗?是真的
输入 1 + 2 == 3&amp;&amp; 4 + 5 == 9
预期结果: True
LogicRules结果: True
通过LogicRules? true
LogicEval结果: True
LogicEval通过了吗?是真的
输入(1 + 2)== 3&amp;&amp; (4 + 5 == 9)
预期结果: True
LogicRules结果: True
通过LogicRules? true
LogicEval结果: True
LogicEval通过了吗?是真的
输入: 1 + 2 ==(3&amp; 4 + 5 == 9)
预期结果:失败
LogicRules结果:失败
通过LogicRules? true
LogicEval结果:失败
LogicEval通过了吗?是真的
输入: 1&amp;&amp; 2
预期结果:失败
LogicRules结果:失败
通过LogicRules? true
LogicEval结果:失败
LogicEval通过了吗?是真的
输入: 1 + 2
预期结果:失败
LogicRules结果:失败
通过LogicRules? true
LogicEval结果:失败
LogicEval通过了吗?是真的