匹配某些 xml 标记之间的任何输入的 Xtext 语法

Xtext grammar that matches any input between certain xml tags

我正在尝试为 freemarker 语言编写一个非常简单的 Xtext 语法。我无法匹配已知标签之间的任何文本。

到目前为止我的语法:

grammar org.github.FreemarkerEditor with org.eclipse.xtext.common.Terminals

generate freemarkerEditor "http://www.github.org/FreemarkerEditor"

Freemarker:
    elements+=Element*;

Element: Tag|Print|Comment|Text;

Print:value=PRINT_CONTENT;
Tag:open=TAG_OPEN elements+=Element* TAG_CLOSE;

Text: text+=ANY_OTHER+;

Comment: text=COMMENT_CONTENT;

terminal PRINT_START_FRAGMENT:'${';
terminal PRINT_CONTENT:PRINT_START_FRAGMENT->'}';
terminal COMMENT_START:'<#--';
terminal COMMENT_CONTENT:COMMENT_START->'-->';
terminal TAG_START_FRAGMENT:'<#';
terminal TAG_OPEN:TAG_START_FRAGMENT->'>';
terminal TAG_CLOSE_START:'</#';
terminal TAG_CLOSE:TAG_CLOSE_START->'>';

它应该是这样工作的:文档中有 4 种元素可以以任何顺序和编号出现。始终以 <#tag some text and functions called> </#tag> 开头的 Freemarker 标签可以再次包含任何元素。应包含忽略其中任何内容的所有文本的注释:<#-- Comment -->。还有一些简单的打印语句,如下所示:${some variable or method call}。其他一切,甚至是普通的 xml 标签或大括号都应该是未解析的文本。

我的语法问题似乎是无法匹配任何地方的文本。示例输入

${hallo.welt} 
mhh
<#list something as somethingElse>${aha haha} some text </#list>

mhh 处显示错误,指出缺少 EOF。我必须如何更改语法才能按预期工作?

如果我生成你的语法,我得到

warning(200): ../org.xtext.example.mydsl4/src-gen/org/xtext/example/mydsl4/parser/antlr/internal/InternalMyDsl.g:297:1: Decision can match input such as "RULE_ANY_OTHER" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input
warning(200): ../org.xtext.example.mydsl4.ui/src-gen/org/xtext/example/mydsl4/ui/contentassist/antlr/internal/InternalMyDsl.g:194:28: Decision can match input such as "RULE_ANY_OTHER" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input

因此你的语法有歧义,你应该修正它,例如通过说 Text 应该尽可能多地吃掉(句法谓词)

Text: => text+=ANY_OTHER+;

然后还有排名更高的其他终端 ANY_OTHER 例如编号

你也必须尊重这一点

Text: => text+=(ID|ANY_OTHER)+;

你为什么要这样写语法?无论如何,这是你的语法。

我花了一段时间才弄清楚你的语法问题,不过我找到了解决你问题的方法。

第一个问题:Text规则:因为它是一个无限长的输入,可以匹配进去,你必须注意它是不可能的Text 规则后跟 Text 规则。

第二个问题:Text规则好像是没有引号的字符串

第三个问题:包含->terminal规则:这个太含糊了

我已经完全重建了你的语法,但在我的 workbench 中它有效。也许它会做你想要的:

Freemarker:
    elements+=Text?
    (elements+=Element
    elements+=Text?)*;

Element:
    Tag | Print | Comment;


Tag:
    '<#' open=ID content=MyString '>' elements=Freemarker '</#' close=ID '>';

MyString:
    ID ('.' | ID)*;

Print:
    '${' content=MyString '}';

Text returns Element:
    text=MyString;

Comment:
    {Comment} '<#--' -> '-->';

如您所见,Text 规则无法通过 Element 规则访问,但 Element 是它的超类型。并且任何 Text 元素都必须后跟一个非 Text.

类型的元素

A Text 元素以 ID 开头,后跟 .ID,然后是 ... 我认为您可以通过任何方式扩展它其他标志,但你必须尝试。

那么,在我看来,多属性比什么都好。这使得使用模型变得更加容易。


如果您对递归有任何问题或有任何歧义,可以使用一个非常有用的工具,称为 ANTLRWorks。它可以可视化您的语法问题。要使用此工具,有一个可选片段可以包含在 MWE2 工作流中,该工作流构建一个干净的 ANTLR 语法文件:

fragment = parser.antlr.DebugAntlrGeneratorFragment {}