我目前正在编写一个扩展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
// ...
}
}
答案 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