【发布时间】:2018-02-07 13:11:23
【问题描述】:
我目前正在为扩展 Xbase 的 Xtext 语言编写解释器。
为此,我从 XbaseInterpreter 继承,添加我自己的 run 方法并用我的新抽象概念覆盖调度方法 doEvaluateProgram。
问题出现在CondStmt 的解释中。它的语义是评估 exp XExpression,只有当 exp 的评估返回 true 时才调用 stmts 语句。
当调用解释器时(让我们从下面的测试用例中说),exp XExpression 的评估失败并出现 java.lang.IllegalArgumentException: Segment cannot be null 异常。
== 语句的两边,例如_inPort 和 inSide 应该是使用 newValue 方法在解释上下文中定义的变量。
我猜测运行时错误与未能识别变量的类型和/或值有关,但我不知道如何解决此问题。
PS:下面是完整的堆栈跟踪。
语法:
grammar MyLang with org.eclipse.xtext.xbase.Xbase
generate mylang "http://MyLang"
import "http://www.eclipse.org/xtext/xbase/Xbase" as xbase
// ...
CondStmt returns xbase::XExpression:
{CondStmt} "cond" "(" exp=XExpression "," stmts+=Stmt* ")";
// ...
口译员
class MyLangInterpreter extends XbaseInterpreter {
val indicator = CancelIndicator.NullImpl
def run(MyProgram program) {
// ...
val context = this.createContext
// ...
val newContext = context.fork
newContext.newValue(QualifiedName.create("_inPort"), "something"))
myElement.doEvaluate(newContext, indicator)
// ...
}
def dispatch doEvaluateProgram(MyElem elem, IEvaluationContext context, CancelIndicator indicator) {
// ...
}
def dispatch doEvaluateProgram(CondStmt condStmt, IEvaluationContext context, CancelIndicator indicator) {
val exp = this.evaluate(condStmt.exp, context, indicator)
if (Boolean.TRUE == exp) {
condStmt.stmts.map [
this.internalEvaluate(it, context, indicator)
].last
}
}
}
测试用例
@RunWith(XtextRunner)
@InjectWith(GpflInjectorProvider)
class GpflInterpreterTest {
@Inject private extension ParseHelper<Program> parseHelper
@Inject private extension GpflInterpreter
@Test
def test1() {
val program = '''
// ...
cond(_inPort == inSide,
// ...
)
// ....
'''.parse
val res = program.run
// ...
}
}
堆栈跟踪
java.lang.IllegalArgumentException: Segment cannot be null
at org.eclipse.xtext.naming.QualifiedName.create(QualifiedName.java:203)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1008)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:993)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:901)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:864)
at mylang.MyLangInterpreter.doEvaluate(GpflInterpreter.java:414)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:900)
at mylang.MyLangInterpreter.doEvaluate(GpflInterpreter.java:450)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:189)
at mylang.MyLangInterpreter._doEvaluate(GpflInterpreter.java:314)
at mylang.MyLangInterpreter.doEvaluate(GpflInterpreter.java:430)
at mylang.MyLangInterpreter.lambda$3(GpflInterpreter.java:263)
at mylang.MyLangInterpreter$$Lambda$13/974320615.accept(Unknown Source)
at java.lang.Iterable.forEach(Iterable.java:75)
at mylang.MyLangInterpreter.run(GpflInterpreter.java:265)
at fr.mleduc.gpfl.tests.MyLangInterpreterTest.test1(GpflInterpreterTest.java:113)
...
【问题讨论】:
-
如果特性是代理,你调试了吗?
-
public /* @Nullable */ String getSimpleName(JvmIdentifiableElement element) { if (element == null || element.eIsProxy()) { return null; } -
如果是,代理是哪个功能? ==
-
除此之外,我不会使用解析助手进行解析,因为它可能与 xbase 结合使用
-
该功能确实是 JvmVoidImplCustom 类型的代理(toString: JvmVoid: (eProxyURI: __synthetic0.mylang#|9))。因此,您的 getSimpleName 实现在使用此功能执行时返回 null。另外,如何避免使用解析助手?
标签: interpreter xtext xtend xbase