我尝试翻译表达式时出现UnsupportedOperationException

时间:2014-04-15 18:32:00

标签: rascal

我为表达式语言定义了一个语法,实际上它更复杂,但我简化了这里,我定义了一些函数来为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)

1 个答案:

答案 0 :(得分:0)

错误消息是一个错误,因为它应该报告更清楚的内容,但似乎您的语法定义仍然存在歧义。运行时正在尝试为Tree$Amborg.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;

由于!>>\绑定比并置更强,\关键字预留仅适用于Ident的尾部,而不是整个。{1}}。请添加括号(序列运算符)以消除歧义:

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,因此没有直接递归。下一个将支持间接递归,但对于这个语法,这是不必要的。

另外,我补充说+-通过将它们放在一个组中而相互保留递归,否则1+1-1将保持不明确。