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

时间:2018-02-07 13:11:24

标签: interpreter xtext xtend xbase

我目前正在编写一个扩展Xbase的Xtext语言的解释器。

为此,我继承了XbaseInterpreter,添加了我自己的run方法,并用我的新抽象概念覆盖了调度方法doEvaluateProgram

问题出现在CondStmt的解释中。它的语义是评估exp XExpression并仅在exp的求值返回true时调用stmts语句。

当调用解释器时(让我们从下面的测试用例中说),exp [{1}}的评估失败并带有XExpression异常。

java.lang.IllegalArgumentException: Segment cannot be null声明的双方,例如==_inPort应该是使用inSide方法在解释上下文中定义的变量。

我猜测运行时错误与无法识别变量的类型和/或值有关,但我无法弄清楚如何解决这个问题。

PS:下面的完整堆栈跟踪。

语法:

newValue

口译员

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

        // ...
    }
}

1 个答案:

答案 0 :(得分:0)

这是一个没有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