为什么链接在我的基于 Xtext 的 DSL 中不起作用?

发布于 2024-08-31 04:23:08 字数 2018 浏览 13 评论 0原文

以下是我的 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 节点没有正确链接在一起。谁能帮我诊断这个问题?

The following is the Xtext grammar for my DSL.

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' | ',')+;

And, the following is a program in the above 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)

The following is my subclass of the generated Switch class that demonstrates the getPredicateType() returns null on a Predicate node.

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);
    }

}

When I used the ModelPrinter class to traverse the EMF object model corresponding to the above program, I realized that the nodes are not linked together properly. For example, the getPredicateType() method on a Predicate node returns null. Having read the Xtext user's guide, my impression is that the Xtext default linking semantics should work for my DSL. But, for some reason, the AST nodes of my DSL don't get linked together properly. Can anyone help me in diagnosing this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

泅人 2024-09-07 04:23:08

最后,我找到了问题所在。由于我没有正确加载模型,因此链接设置不正确。我刚刚使用解析器加载模型。所以,我没有得到链接。因此,我使用 Xtext FAQ 中的以下代码片段来正确加载模型。然后,我将返回的模型传递给我的 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);

Finally, I figured out the problem. The links were not set properly because I wasn't loading the model properly. I had just used the parser to load the model. So, I didn't get the links. Therefore, I used the following code snippet from Xtext FAQ to load the model correctly. Then, I passed the returned model to my switch class.

// "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);
橘和柠 2024-09-07 04:23:08

我已经尝试过,但我对 Switch 不熟悉,我宁愿使用 Xpand/Xtend 从 Predicate 访问 predicateTypes 并生成它们的名称。

Template.xpt:

«IMPORT myDsl»;

«DEFINE main FOR Model-»
«FILE "output.txt"-»
«FOREACH this.rules.rules.body.last().predicates AS p-»
«p.predicateType.name»
«ENDFOREACH-»
«ENDFILE-»
«ENDDEFINE»

和output.txt:

Path
Path

我想这是预期的行为。

I have tried it out, but I am not familiar with the Switch, I rather used Xpand/Xtend to access predicateTypes from Predicate and generated their names.

Template.xpt:

«IMPORT myDsl»;

«DEFINE main FOR Model-»
«FILE "output.txt"-»
«FOREACH this.rules.rules.body.last().predicates AS p-»
«p.predicateType.name»
«ENDFOREACH-»
«ENDFILE-»
«ENDDEFINE»

and the output.txt:

Path
Path

I guess this is the expected behaviour.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文