2015-05-28 4 views
1

Я работаю над грамматикой Delphi в Rascal, и у меня возникают проблемы с разбором своего типа записи. Соответствующий раздел Delphi код может выглядеть следующим образом:Как удалить неоднозначность из этого фрагмента грамматики Delphi

record 

private 
a,b,c : Integer; 
x : Cardinal; 

end 

Где «частный» может быть необязательным, и переменные строки декларации также могут быть необязательными.

Я попытался интерпретировать этот раздел, используя правила ниже:

syntax FieldDecl = IdentList ":" Type 
     | IdentList ":" Type ";" 
     ; 

syntax FieldSection = FieldDecl 
     | "var" FieldDecl 
     | "class" "var" FieldDecl 
     ; 

syntax Visibility = "private" | "protected" | "public"| "published" ; 

syntax VisibilitySectionContent = FieldSection 
      | MethodOrProperty 
      | ConstSection 
      | TypeSection 
      ; 

syntax VisibilitySection = Visibility? VisibilitySectionContent+  
     ; 

syntax RecordType = "record" "end" 
     | "record" VisibilitySection+ "end" 
     ; 

Проблема неоднозначности. Весь текст между «записью» и «концом» можно разобрать в одном окне VisibilitySection, но каждая строка сама по себе также может быть отдельной визуализацией.

Я не могу изменить правила VisibilitySection к

syntax VisibilitySection = Visibility 
     | VisibilitySectionContent 
     ; 

Тогда грамматика больше не неоднозначная, но VisibilitySection становится плоская, нет вложенности больше вариабельных линий под необязательным «частным» узлом, который я бы предпочел.

Любые предложения по решению этой проблемы? То, что я хотел бы сделать, - потребовать самый длинный/жадный матч на символе VisibilitySectionContent + VisibilitySection.

Но изменение

syntax VisibilitySection = Visibility? VisibilitySectionContent+  

в

syntax VisibilitySection = Visibility? VisibilitySectionContent+ !>> VisibilitySectionContent 

не похоже на работу для этого.

Я также запустил инструмент отчета о неоднозначности на Rascal, но он не дает мне никаких сведений.

Любые мысли?

Благодаря

+0

привет. Я не могу воспроизвести двусмысленность, потому что грамматика неполна. есть ли у вас ссылка на полное определение? – jurgenv

+0

Обозначение '! >>' работает только с терминалами с правой стороны, например '! >>« private »' – jurgenv

+0

Грамматика до сих пор находится по адресу: http://www.ilsmoija.nl/download/DelphiGrammar. rsc – Martijn

ответ

0

я не могу проверить, так как вы не предоставили полную грамматику, но я считаю, что это должно работать, чтобы получить свой «самый длинный матч» поведение:

syntax VisibilitySection 
    = Visibility? VisibilitySectionContent+() 
    >> "public" 
    >> "private" 
    >> "published" 
    >> "protected" 
    >> "end" 
    ; 

На мой взгляд, это должно удалить интерпретацию, где ваш вложенные VisibilitySections сокращаются. Теперь мы принимаем только такие разделы, если за ними сразу следует либо конец записи, либо следующий раздел.Мне любопытно узнать, действительно ли это работает, потому что всегда сложно предсказать поведение грамматики :-)

() в конце правила (пустой не терминал), мы можем пропустить начало следующей части перед применением ограничения. Это работает только в том случае, если у вас есть самое длинное правило соответствия в макете уже где-то в грамматике.

+0

Это работает почти отлично, хотя каждый оператор «следует» должен быть в своем собственном правиле производства. Проблема в том, что макет, похоже, не рассматривается между секцией VisibilitySectionContent и «частной» частью? Когда между ними нет частей макета, он отлично разбирается, но когда макет добавляется, он генерирует ошибку синтаксического анализа. Когда элементы макета, которые следует ожидать, явно добавляются к правилу, это двусмысленно в двойной пробельной части. – Martijn

+0

ах да, действительно. Я изменю решение с другим обходным решением для этого. Если он затем работает, пожалуйста, примите ответ :-) – jurgenv

+0

Он работает, отлично. Спасибо за ответ: ^) – Martijn

0

VisibilitySectionContent+ в VisibilitySection должна быть VisibilitySectionContent (без Клини плюс).

Я предполагаю здесь, но ваше намерение, вероятно, разрешить несколько разделов/деклараций в типе записи, и любой из них может иметь или не иметь модификатор Visibility. Чтобы не помещать этот необязательный Visibility в каждый раздел, вы создали 0терминал VisibilitySectionContent, который в основном моделирует «вещи, которые могут произойти в определении типа записи», одна вещь для нетерминала, не беспокоясь о модификаторах видимости. В этом случае у вас все нормально с одним VisibilitySectionContent за VisibilitySection, так как есть явное повторение, когда вы ссылаетесь на VisibilitySection от RecordType в любом случае.

+0

Спасибо за идею, но когда я использую этот метод, внутренняя структура записи становится «плоской», и мне нравится сохранять вложенность переменных под «частными» и «общедоступными» тегами. – Martijn