【问题标题】:Why doesn't linking work in my Xtext-based DSL?为什么链接在我的基于 Xtext 的 DSL 中不起作用?
【发布时间】:2011-06-17 08:37:23
【问题描述】:

以下是我的 DSL 的 Xtext 语法。

Model:
  variableTypes=VariableTypes predicateTypes=PredicateTypes variableDeclarations=
  VariableDeclarations rules=Rules;

VariableType:
  name=ID;

VariableTypes:
  'var types' (variableTypes+=VariableType)+;

PredicateTypes:
  'predicate types' (predicateTypes+=PredicateType)+;

PredicateType:
  name=ID '(' (variableTypes+=[VariableType|ID])+ ')';

VariableDeclarations:
  'vars' (variableDeclarations+=VariableDeclaration)+;

VariableDeclaration:
  name=ID ':' type=[VariableType|ID];

Rules:
  'rules' (rules+=Rule)+;

Rule:
  head=Head ':-' body=Body;

Head:
  predicate=Predicate;

Body:
  (predicates+=Predicate)+;

Predicate:
  predicateType=[PredicateType|ID] '(' (terms+=Term)+ ')';

Term:
  variable=Variable;

Variable:
  variableDeclaration=[VariableDeclaration|ID];

terminal WS:
  (' ' | '\t' | '\r' | '\n' | ',')+;

而且,下面是上述DSL中的一个程序。

var types
  Node

predicate types
  Edge(Node, Node)
  Path(Node, Node)

vars
  x : Node
  y : Node
  z : Node

rules
  Path(x, y) :- Edge(x, y)
  Path(x, y) :- Path(x, z) Path(z, y)

以下是我生成的 Switch 类的子类,它演示了 getPredicateType()Predicate 节点上返回 null。

public class ModelPrinter extends MyDSLSwitch<Object> {

    protected Object visitChildren(EObject object) {
        for (EObject eobj : object.eContents()) {
            doSwitch(eobj);
        }   
        return object;
    }

    @Override
    public Object casePredicate(Predicate object) {
        System.out.println(object.getPredicateType());
        return object;
    }

    @Override
    public Object defaultCase(EObject object) {
        return visitChildren(object);
    }

}

当我使用ModelPrinter类遍历上述程序对应的EMF对象模型时,我意识到节点没有正确链接在一起。例如,Predicate 节点上的 getPredicateType() 方法返回 null。阅读了 Xtext 用户指南后,我的印象是 Xtext 默认链接语义应该适用于我的 DSL。但是,由于某种原因,我的 DSL 的 AST 节点没有正确链接在一起。谁能帮我诊断这个问题?

【问题讨论】:

    标签: java eclipse dsl eclipse-emf xtext


    【解决方案1】:

    最后,我发现了问题所在。链接设置不正确,因为我没有正确加载模型。我刚刚使用解析器加载模型。所以,我没有得到链接。因此,我使用Xtext FAQ 中的以下代码 sn-p 来正确加载模型。然后,我将返回的模型传递给我的 switch 类。

    // "workspace" is a string that contains the path to the workspace containing the DSL program.
    new org.eclipse.emf.mwe.utils.StandaloneSetup().setPlatformUri(workspace);
    
    Injector injector = new MyDslStandaloneSetup().createInjectorAndDoEMFRegistration();
    XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
    resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
    
    // "DSLProgram" is a string that contains the path to the file of the DSL program relative to the workspace set above.
    Resource resource = resourceSet.getResource(URI.createURI("platform:/resource/" + DSLProgram), true);
    Model model = (Model) resource.getContents().get(0);
    

    【讨论】:

      【解决方案2】:

      我试过了,但是我对 Switch 不熟悉,我宁愿使用 Xpand/Xtend 从 Predicate 中访问 predicateTypes 并生成它们的名字。

      模板.xpt:

      «导入我的 Dsl»; «DEFINE main FOR Model-» «文件“输出.txt”-» «FOREACH this.rules.rules.body.last().predicates AS p-» «p.predicateType.name» «ENDFOREACH-» «ENDFILE-» «ENDDEFINE»

      和 output.txt:

      小路 小路

      我猜这是预期的行为。

      【讨论】:

      • @Gabriel Ščerbák,我不想从我的 DSL 生成代码。相反,我想将输入 DSL 程序的语义模型转换为其他领域模型。我已经通过演示链接设置不正确的代码更新了我的问题。
      • @reprogrammer 正如我在回答您的其他问题时提到的,可以进行模型转换(从模型到模型,无论它们是否共享相同的元模型,只要支持元元模型。 ..) 使用 Xtend(现在显然是 Xpand 的一部分 ..),它比您通过 Java 的方法具有一定的优势。但是,要对您的确切问题有一个很好的回答,请听听 Sebastian Zarnekow,他是 Xtext AFAIK 的核心开发人员。
      猜你喜欢
      • 2013-05-25
      • 1970-01-01
      • 2015-06-24
      • 2015-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-10
      相关资源
      最近更新 更多