1

我为表达式语言定义了一种语法,实际上它更复杂,但我简化了放在这里,我定义了一些函数来为 Java 翻译这个表达式(我没有使用 Java 语法,我只是翻译成字符串)。我在调用“MAXINT”和“MININT”的语法中定义了一些常量(我不知道它是否是正确的名称),以及一些调用 translateExp 以将我在语法中定义的每个表达式转换为字符串的函数. 我尝试翻译的大多数表达式都有效,但是当表达式中出现“MAXINT”或“MININT”时不起作用并抛出 UnsupportedOperationException 我不知道为什么,例如“MAXINT - 1”。有人知道为什么并且可以帮助我吗?另一个引发 UnsupportedOperationException 的问题是,当我尝试翻译一些具有多个加号 (+) 或减号 (-) 的表达式时,例如“1+1+1”,有人知道为什么吗?

我的模块的语法和功能:

module ExpSyntax

import String;
import ParseTree;

layout Whitespaces = [\t\n\ \r\f]*;

lexical Ident = [a-z A-Z 0-9 _] !<< [a-z A-Z][a-z A-Z 0-9 _]* !>> [a-z A-Z 0-9 _] \ Keywords;
lexical Integer_literal = [0-9]+;

keyword Keywords = "MAXINT" | "MININT";

start syntax Expression
= Expressions_primary
| Expressions_arithmetical;

syntax Expressions_primary
= Data: Ident+ id
| bracket Expr_bracketed: "(" Expression e ")"
;

syntax Expressions_arithmetical
= Integer_lit
| left Addition: Expression e1 "+" Expression e2
| left Difference: Expression e1 "-" Expression e2 
;

syntax Integer_lit
= Integer_literal il
| MAX_INT: "MAXINT"
| MIN_INT: "MININT"
;

public str translate(str txt) = translateExp(parse(#Expression, txt));

public str translateExp((Expression) `<Integer_literal i>`) = "<i>";
public str translateExp((Expression) `MAXINT`) = "java.lang.Integer.MAX_VALUE";
public str translateExp((Expression) `MININT`) = "java.lang.Integer.MIN_VALUE";
public str translateExp((Expression) `<Expression e1>+<Expression e2>`) = "<translateExp(e1)> + <translateExp(e2)>";
public str translateExp((Expression) `<Expression e1>-<Expression e2>`) = "<translateExp(e1)> - <translateExp(e2)>";
public str translateExp((Expression) `<Ident id>`) = "<id>";
public str translateExp((Expression) `(<Expression e>)`) = "(<translateExp(e)>)";

这就是发生的事情:

rascal>import ExpSyntax;

ok

rascal>translate("(test + 1) - test2");

str: "(test + 1) - test2"

rascal>translate("MAXINT - 1");

java.lang.UnsupportedOperationException(internal error) at $shell$(|main://$shell$|)
java.lang.UnsupportedOperationException
    at org.rascalmpl.ast.Expression.getKeywordArguments(Expression.java:214)
    at org.rascalmpl.interpreter.matching.NodePattern.<init>(NodePattern.java:84)
    at org.rascalmpl.semantics.dynamic.Tree$Amb.buildMatcher(Tree.java:351)
    at org.rascalmpl.ast.AbstractAST.getMatcher(AbstractAST.java:173)
    at org.rascalmpl.interpreter.result.RascalFunction.prepareFormals(RascalFunction.java:503)
    at org.rascalmpl.interpreter.result.RascalFunction.call(RascalFunction.java:365)
    at org.rascalmpl.interpreter.result.OverloadedFunction.callWith(OverloadedFunction.java:327)
    at org.rascalmpl.interpreter.result.OverloadedFunction.call(OverloadedFunction.java:305)
    at org.rascalmpl.semantics.dynamic.Expression$CallOrTree.interpret(Expression.java:486)
    at org.rascalmpl.semantics.dynamic.Statement$Expression.interpret(Statement.java:355)
    at org.rascalmpl.semantics.dynamic.Statement$Return.interpret(Statement.java:773)
    at org.rascalmpl.interpreter.result.RascalFunction.runBody(RascalFunction.java:467)
    at org.rascalmpl.interpreter.result.RascalFunction.call(RascalFunction.java:413)
    at org.rascalmpl.interpreter.result.OverloadedFunction.callWith(OverloadedFunction.java:327)
    at org.rascalmpl.interpreter.result.OverloadedFunction.call(OverloadedFunction.java:305)
    at org.rascalmpl.semantics.dynamic.Expression$CallOrTree.interpret(Expression.java:486)
    at org.rascalmpl.semantics.dynamic.Statement$Expression.interpret(Statement.java:355)
    at org.rascalmpl.interpreter.Evaluator.eval(Evaluator.java:936)
    at org.rascalmpl.semantics.dynamic.Command$Statement.interpret(Command.java:115)
    at org.rascalmpl.interpreter.Evaluator.eval(Evaluator.java:1147)
    at org.rascalmpl.interpreter.Evaluator.eval(Evaluator.java:1107)
    at org.rascalmpl.eclipse.console.RascalScriptInterpreter.execCommand(RascalScriptInterpreter.java:446)
    at org.rascalmpl.eclipse.console.RascalScriptInterpreter.run(RascalScriptInterpreter.java:239)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:53)

rascal>translate("1+1+1");

java.lang.UnsupportedOperationException(internal error) at $shell$(|main://$shell$|)
java.lang.UnsupportedOperationException
    at org.rascalmpl.ast.Expression.getKeywordArguments(Expression.java:214)
    at org.rascalmpl.interpreter.matching.NodePattern.<init>(NodePattern.java:84)
    at org.rascalmpl.semantics.dynamic.Tree$Amb.buildMatcher(Tree.java:351)
    at org.rascalmpl.ast.AbstractAST.getMatcher(AbstractAST.java:173)
    at org.rascalmpl.interpreter.result.RascalFunction.prepareFormals(RascalFunction.java:503)
    at org.rascalmpl.interpreter.result.RascalFunction.call(RascalFunction.java:365)
    at org.rascalmpl.interpreter.result.OverloadedFunction.callWith(OverloadedFunction.java:327)
    at org.rascalmpl.interpreter.result.OverloadedFunction.call(OverloadedFunction.java:305)
    at org.rascalmpl.semantics.dynamic.Expression$CallOrTree.interpret(Expression.java:486)
    at org.rascalmpl.semantics.dynamic.Statement$Expression.interpret(Statement.java:355)
    at org.rascalmpl.semantics.dynamic.Statement$Return.interpret(Statement.java:773)
    at org.rascalmpl.interpreter.result.RascalFunction.runBody(RascalFunction.java:467)
    at org.rascalmpl.interpreter.result.RascalFunction.call(RascalFunction.java:413)
    at org.rascalmpl.interpreter.result.OverloadedFunction.callWith(OverloadedFunction.java:327)
    at org.rascalmpl.interpreter.result.OverloadedFunction.call(OverloadedFunction.java:305)
    at org.rascalmpl.semantics.dynamic.Expression$CallOrTree.interpret(Expression.java:486)
    at org.rascalmpl.semantics.dynamic.Statement$Expression.interpret(Statement.java:355)
    at org.rascalmpl.interpreter.Evaluator.eval(Evaluator.java:936)
    at org.rascalmpl.semantics.dynamic.Command$Statement.interpret(Command.java:115)
    at org.rascalmpl.interpreter.Evaluator.eval(Evaluator.java:1147)
    at org.rascalmpl.interpreter.Evaluator.eval(Evaluator.java:1107)
    at org.rascalmpl.eclipse.console.RascalScriptInterpreter.execCommand(RascalScriptInterpreter.java:446)
    at org.rascalmpl.eclipse.console.RascalScriptInterpreter.run(RascalScriptInterpreter.java:239)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:53)
4

1 回答 1

0

该错误消息是一个错误,因为它应该报告更清楚的内容,但您的语法定义似乎仍然存在歧义。运行时正在尝试为Tree$Amb( org.rascalmpl.semantics.dynamic.Tree$Amb.buildMatcher) 构建一个模式匹配器,我们没有实现也不会实现。

从定义看(我没试过),似乎原因是这个规则:

lexical Ident = [a-z A-Z 0-9 _] !<< [a-z A-Z][a-z A-Z 0-9 _]* !>> [a-z A-Z 0-9 _] \ Keywords;

因为!>>and \bind 比并置强,所以\关键字 reservation 只应用于 an 的尾部Ident而不是整个。请添加括号(序列运算符)以消除歧义:

lexical Ident = [a-z A-Z 0-9 _] !<< ([a-z A-Z][a-z A-Z 0-9 _]*) !>> [a-z A-Z 0-9 _] \ Keywords; 

这应该让你更进一步。

那么你的表达式语法仍然是模棱两可的,可以简化为:

start syntax Expression
  = Data: Ident+ id
  | Integer: Integer_lit
  | bracket bracketed: "(" Expression e ")"
  > left
      ( Addition: Expression e1 "+" Expression e2
      | Difference: Expression e1 "-" Expression e2 
      )
  ;

syntax Integer_lit
  = Integer_literal il
  | MAX_INT: "MAXINT"
  | MIN_INT: "MININT"
  ;

简短说明:left仅适用于直接递归的非终结符。由于您根据定义Expressions_arithmatical没有Expression直接递归。next 将支持间接递归,但对于这种语法,这将是不必要的。

另外,我补充说,+并且-通过将它们放在一个组中来相互递归,否则1+1-1会保持模棱两可。

于 2014-04-15T20:55:00.817 回答