2013-11-17 2 views
4

Я пытаюсь разработать грамматику острова, используя Rascal MPL, но я столкнулся с проблемой:Как использовать SDF в {избегает} в мошеннике MPL

При реализации Island грамматики в SDF очень распространенный подход состоит в определении «добыча» всей воды с использованием атрибута {avoid}. Это не позволяет парсеру использовать эту продукцию, если другие применимы. Это позволяет определить поведение в по умолчанию, который может быть преодолен с помощью других производств whitout порождающих abiguities. Очень простой пример:

context free syntax 
    Chunk*   -> Input 
    Water   -> Chunk 
lexical syntax 
    ~[\t\n\ ]+ -> Water {avoid} // avoid the Water production 

Я пробовал воспроизвести это поведение с помощью Rascal MPL. Моя цель - создать островную грамматику, которая собирает все условные препроцессорные директивы внутри куска кода C/C++ и пропускает остальную часть ввода, используя Water production.

layout LAYOUT = [\t\n\ ]; 
lexical WATER = ![\t\n\ ]+; 

start syntax Program = Line*;  // program consists of lines 

syntax Line = ConditionalDirective // preprocessor directives 
      > WATER;    // catch-all option 

syntax ConditionalDirective = "#ifdef" 
          | "#ifndef" 
          | "#if" 
          | "#elif"; 

Я попытался создать {} ИЗБЕЖАТЬ эффект, давая по производству ConditionalDirective более высокий приоритет, с помощью «>» оператора, но это не работает, по-видимому. Дерево разбора все еще содержит неоднозначности.

#ifdef asd 

Если я разобрать приведенный выше код, например, я получаю дерево разбора, которое выглядит следующим образом:

ambiguous parse tree

Насколько я могу сказать от Rascal Documentation, используя «приоритет» -оператор, возможно, не подходит для моего случая, но я не вижу других возможностей. Я предполагаю, что есть способ, потому что авторы негодяя ясно заявляют, что каждая грамматика SDF может быть преобразована в грамматику мошенничества.

Есть ли способ воспроизвести функциональные возможности SDF с функцией неконтролируемого MPL? Или можно каким-то образом отфильтровать разведывательный лес, повторно применяя приоритеты?

+0

Одна из возможностей заключалась бы в том, чтобы исключить условные директивы явно из WATER-Production с использованием RegEx, но вряд ли это вариант при попытке создать поведение по умолчанию ... – silflow

+0

Существует sdf2. грамматика для языка cpp: https: // github.com/cwi-swat/sdf-library/tree/master/src/languages ​​/ cpp/syntax – jurgenv

ответ

2

Короткий ответ: избегать в sdf2 фильтра синтаксического анализа. В негодяи вы можете определить их сами, см. https://github.com/cwi-swat/rascal/blob/master/src/org/rascalmpl/library/lang/sdf2/filters/PreferAvoid.rsc для примера, который имитирует sdf2, избегая поведения, не игнорируя цепочки инъекций и не подсчитывая. Вы можете импортировать его в грамматику и использовать теги @avoid и @prefer, как в sdf2, или написать собственные фильтры.

Предостережение: избегать, как правило, недостаточно для определения поведения воды в sdf2, и оно также не является подлым. Причина в том, что вода может стать больше, чем ее альтернатива. Предпочитают и избегают выбирать только альтернативы равной длины в терминах длины подписи. Один верный способ, но медленный способ справиться с водой в негодяи, состоит в том, чтобы подсчитать его в каждой альтернативе и выбрать деривации с меньшим количеством воды.

Другая проблема с предпочтением и недопущением заключалась в том, что использование начнет вмешиваться, особенно когда они будут учтены. Этого можно избежать у мошенников, специализируясь на фильтрах для определенных нетерминалов или даже альтернативных правил.

Другой вариант - использовать \ и! операторы-нарушители. См. Руководство. Тем не менее, все, и все Я считаю, что вариант фильтрации после синтаксического анализа в настоящее время является лучшим способом справиться с острова грамматик, потому что вы контролируете то, что происходит.

+0

Спасибо за ваш ответ и ваши объяснения :) – silflow

+0

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