执行扩展XBase解释器会导致运行时异常



我当前正在为扩展xbase的Xtext语言写一个解释器。

这样做是从XBaseInterPreter继承,添加自己的run方法,并使用我的新抽象概念覆盖调度方法doEvaluateProgram

问题出现在CondStmt的解释中。它的语义是评估EXP XExpression并仅在评估EXP返回true时才调用STMTS语句。

当调用解释器时(从下面的测试案例中说(,exp XExpression的评估会在 java.lang.IllegalArgumentException: Segment cannot be null异常中失败。

==语句的两面,例如_inPortinSide应该是使用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)
...  

这是一个没有parsehelper

加载模型的示例
@RunWith(XtextRunner)
@InjectWith(DomainmodelInjectorProvider)
class DullyTest{
    @Inject Provider<XtextResourceSet> rsp
    @Inject ValidationTestHelper helper
    @Test
    def void xxxxx() {
        val rs = rsp.get
        rs.classpathURIContext = DullyTest
        val r = rs.createResource(URI.createURI("dummy.dmodel"))
        val text = '''
        entity Person {
            op xxxx() {
                1==1
            }
        }
        '''
        r.load(new StringInputStream(text), null)
        helper.assertNoIssues(r)
        val m = r.contents.head as DomainModel

最新更新