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

时间:2015-01-21 07:20:13

标签: java parsing grammar freemarker xtext

我正在尝试为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。如何更改语法以按预期工作?

2 个答案:

答案 0 :(得分:2)

如果我生成你的语法我得

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+=ANY_OTHER+;

然后有更高等级的其他终端被列为ANY_OTHER 例如ID

你也必须尊重

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

答案 1 :(得分:1)

你为什么用你的方式写你的语法?无论如何,这是你的语法。

我花了一些时间来弄清楚你的语法问题,但是我找到了解决问题的方法。

第一个问题: Text规则:由于它是一个可以匹配的无限长输入,因此您必须注意Text是不可能的}规则后跟Text规则。

第二个问题: Text规则它似乎是没有qoute标志的字符串。

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

我完全重建了你的语法,但是在我的工作台上它有效。也许它能满足您的需求:

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类型的元素。

Text元素以ID开头,后跟.ID,后跟...我认为您可以通过任何其他符号扩展此元素,但你必须尝试。

然后,对于我的反对,最好有更多属性而不是任何东西。这使得使用该模型变得更加容易。


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

fragment = parser.antlr.DebugAntlrGeneratorFragment {}