2015-01-21 1 views
0

Я пытаюсь написать очень простую грамматику Xtext для языка freemarker. Я не могу совместить любой текст между известными тегами.Xtext-грамматика, которая соответствует любому входу между определенными тегами xml

Моя грамматика до сих пор:

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 типа элементов, которые могут возникнуть в любом порядке и количестве в документе. Теги Freemarker, которые всегда начинаются с <#tag some text and functions called></#tag>, которые могут содержать любые элементы. Комментарии, которые должны содержать весь текст между игнорированием чего-либо там: <#-- Comment -->. Существуют также простые операторы печати, которые выглядят следующим образом: ${some variable or method call}. Все остальное, даже обычные теги xml или фигурные скобки, должны быть непроверенным текстом.

Проблема в моей грамматике, по-видимому, в том, что она не может соответствовать тексту где угодно. Пример ввод

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

показывает ошибку при mhh о том, что EOF отсутствует. Как мне изменить грамматику для работы, как ожидалось?

ответ

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)+; 
+0

В этом была проблема. Похоже, потому, что у него была возможность создать столько текстовых элементов, сколько захотелось, это не соответствовало. Благодарю. Теперь я могу создать более чистую версию грамматики. – user1264614

1

Почему вы написали грамматики, как вы делаете? Во всяком случае, это ваша грамматика.

Мне потребовалось некоторое время, чтобы выяснить проблемы вашей грамматики, однако я нашел решение проблемы.

Первая проблема: Text правило: Поскольку это бесконечный длинный вход, который может быть подобран в него, вы должны позаботиться о том, что невозможно для Text правила с последующим Text правилом.

Вторая проблема: Правило Text Кажется, что это строка без знаков qoute.

Третья проблема: Правила, касающиеся ->: Это слишком неоднозначно.

Я полностью перестроил вашу грамматику, но в моем верстаке это работает. Может быть, это то, что вы хотите:

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 правило, но элемент является его супером типа. И любой элемент Text должен сопровождаться элементом, который не имеет типа Text.

Text элемент начинается с ID, с последующим . или ID, а затем ... Я думаю, вы можете продлить это любой другой знак, но вы должны попробовать.

Затем, для моего оппониона лучше иметь больше атрибутов вместо всего. Это упрощает работу с моделью.


Если у вас есть какие-либо проблемы с рекурсией или какой-либо двусмысленности, есть очень полезный инструмент, доступный, называется ANTLRWorks. Он может визуализировать проблемы вашей грамматики. Для использования этого инструмента есть дополнительный фрагмент, который может быть включен в рабочий процесс MWE2, который строит чистый файл грамматики ANTLR:

fragment = parser.antlr.DebugAntlrGeneratorFragment {} 
+0

Это решение очень сильно ограничивает возможные входные значения. Вся проблема в том, что MyString должен допускать все, кроме символов, которые открывают/закрывают что-либо, например. в тексте должны быть разрешены фигурные скобки. – user1264614

+0

вы должны заручиться их всеми или не наследовать от терминалов –