1

我有一个简单的 DSL,它应该为表达式生成异步代码(这是我能想出的最简单的例子来说明我的观点)。我刚刚在脚本示例中添加了一条新async语句:

grammar org.xtext.scripting.Scripting with org.eclipse.xtext.xbase.Xbase

generate scripting "http://www.xtext.org/scripting/Scripting"
import "http://www.eclipse.org/xtext/xbase/Xbase" as xbase

Script returns xbase::XBlockExpression:
    {Script}
    (expressions+=XExpressionOrVarDeclaration ';'?)*;

XExpression returns xbase::XExpression:
    super | Async
;

Async:
    'async' expression=XExpression
;

这个想法是async代码在另一个线程中执行。

我的问题是,我怎样才能为Async.expression使用生成代码ScriptingJvmModelInferrer

在最简单的情况下,我会Async.expression像这样包装代码?

    AsyncRunner.exec(new Runnable() {
        @Override
        public void run() {
            // the Async.expression would end up here
        }
    })

这样做的钩子在哪里?

4

2 回答 2

1

您必须进行 3 项更改:

  1. 扩展编译器以处理您的语言。关键是处理Async表达式。

    class ScriptingCompiler extends XbaseCompiler {
    
        override protected doInternalToJavaStatement(XExpression expr, ITreeAppendable it, boolean isReferenced) {
            switch expr {
                Async : {
                    newLine
                    append('''
                        AsyncRunner.exec(new Runnable() {
                          @Override
                          public void run() {''')
                    expr.expression.doInternalToJavaStatement(it, false)
                    newLine
                    append('}});')
    
                }
    
                default :
                    super.doInternalToJavaStatement(expr, it, isReferenced)
            }
        }
    
        override protected internalToConvertedExpression(XExpression obj, ITreeAppendable it) {
            if (hasName(obj))
                append(getName(obj))
            else 
                super.internalToConvertedExpression(obj, it) 
        }
    }
    
  2. 必须指定表达式的类型

    class ScriptingTypeComputer extends XbaseWithAnnotationsTypeComputer {
    
        override computeTypes(XExpression expression, ITypeComputationState state) {
            if(expression instanceof Async) {
                super.computeTypes(expression.expression, state);
            } else {
                super.computeTypes(expression, state)
            }
        }
    }
    
  3. 两个扩展都必须注入:

    class ScriptingRuntimeModule extends AbstractScriptingRuntimeModule {
        def Class<? extends XbaseCompiler> bindXbaseCompiler() {
            return ScriptingCompiler
        }
    
        def Class<? extends ITypeComputer> bindITypeComputer() {
            return ScriptingTypeComputer
        }
    }
    
于 2017-01-09T10:59:01.407 回答
0

如果您扩展 Xbase,您通常不会将 JvmModelInferrer 用于编译,但您扩展XbaseTypeComputerXbaseCompiler.doInternalToJavaStatement/internalToConvertedExpression(取决于您实际引入的内容)

于 2017-01-05T08:14:26.350 回答