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