0

Я работаю над парсером для языка LiveScript, и у меня возникают проблемы с разбором форм определения свойств объекта - key: value и (+|-)key - вместе. Например:Избегание левой рекурсии при разборе определения объектов LiveScript

prop: "val" 
+boolProp 
-boolProp 
prop2: val2 

У меня есть key: value форма работы с этим:

Expression ::= TestExpression 
    | ParenExpression 
    | OpExpression 
    | ObjDefExpression 
    | PropDefExpression 
    | LiteralExpression 
    | ReferenceExpression 

PropDefExpression ::= Expression COLON Expression 

ObjDefExpression ::= PropDefExpression (NEWLINE PropDefExpression)* 

// ... other expressions 

Но тем не менее я пытаюсь добавить ("+"|"-") IDENTIFIER к PropDefExpression или ObjDefExpression, я получаю сообщения об ошибках, используя левую рекурсию. Каков (правильный) способ сделать это?

+0

Что парсер-генератор вы используете (и, если вы заботитесь чтобы комментировать, почему вы выбрали тот, а не тот, который создает анализатор снизу вверх)? – rici

+0

Я работаю над плагином LiveScript для IDE IntelliJ IDEA и в соответствии с их [учебником] (https://confluence.jetbrains.com/display/IntelliJIDEA/Grammar+and+Parser) Я использую [JFlex lexer] (http://jflex.de/) + [GrammarKit parser plugin] (https://github.com/JetBrains/Grammar-Kit). И я слишком мало знаю о парсерах и разработке плагинов IntelliJ в целом, чтобы искать альтернативы. –

+0

Справедливо. По-видимому, GrammarKit строит рекурсивную грамматику спуска, хотя ее документация немного дезорганизована, поэтому я могу что-то упустить. Я также не очень разбираюсь в сценариях lifecript, но это не похоже на синтаксический анализ LL (1), и его синтаксический анализатор построен с помощью Jison, который строит парные анализаторы LALR (1) снизу вверх. (Https://github.com/gkz/LiveScript/blob/master/src/grammar.ls). Короче говоря, я не думаю, что могу вам помочь. Сожалею. – rici

ответ

0

фрагмент грамматики вы вывесили уже покинул рекурсию, т.е. даже без добавления (+ | -) boolprop, нетерминальный «выражения» выводит форму, в которой «Expression» появляется снова, как крайний левый символ:

Expression -> PropDefExpression -> Expression COLON Expression 

И это не только леворекурсивное, это неоднозначно. Например.

Expression COLON Expression COLON Expression 

могут быть получены двумя различными способами (примерно, левый ассоциативно против правого ассоциативной).

Вы можете устранить обе эти проблемы, используя что-то более ограниченный слева от двоеточия, например .:

PropDefExpression ::= Identifier COLON Expression 

Кроме того, другой двусмысленность: Выражение происходит PropDefExpression двумя различными способами, непосредственно и через ObjDefExpression. Я предполагаю, что вы можете отказаться от прямого вывода.

После того как вы позаботились об этих вещах, мне кажется, вы должны иметь возможность добавлять (+ | -) boolprop без ошибок (если это не противоречит одному из других выражений, которые вы не показывали).

Помните, что, глядя на примеры в http://livescript.net, я сомневаюсь, сколько из них вы сможете уловить в обычной грамматике. Но если вы просто собираетесь подмножество, вы можете быть в порядке.

+0

Grammar-Kit допускает некоторую (псевдо?) Рекурсию через своего рода OO-подобный механизм расширения, так что это не совсем проблема. Но я решил это, переписав файл с более ограниченными/конкретными выражениями, поэтому я принимаю это как ответ. –

0

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

Тем не менее, мне кажется, что

PropDefExpression ::= Expression COLON Expression 

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

name : expression 
parenthesized_expression : expression 

(Который должен сказать, выражения должны начинаться с ()

Это означает, что логическое определение свойства, начиная с + или - распознается с первого токена, что является именно условием, необходимым для успешного рекурсивного анализа спуска.Есть несколько других Синтаксисов определения собственности, в том числе имен и parenthesized_expressions не следовавшие по :

Это легко разобрать с LR (1) синтаксическим анализатором, как и производит один Jison, но разобрать его с рекурсивным -дессальный парсер вам нужен левый фактор. (Вполне возможно, что GrammarKit может сделать это для вас, кстати.) В принципе, вам нужно что-то вроде (это не полный):

PropertyDefinition ::= PropertyPrefix PropertySuffix? | BooleanProperty 
PropertyPrefix ::= NAME | ParenthesizedExpression 
PropertySuffix ::= COLON Expression | DOT NAME