LALR грамматика, запятая и многострочный список - PullRequest
3 голосов
/ 14 марта 2012

Я пытаюсь создать грамматику LALR для очень простого языка, состоящего из заданий.Например:

foo = "bar"
bar = 42

Язык также должен обрабатывать список значений, например:

foo = 1, 2, 3

Но я также хочу обрабатывать список в несколько строк:

foo = 1, 2
      3, 4

Завершающая запятая (для синглетонов и гибкости языка):

foo = 1,
foo = 1, 2,

И, очевидно, оба одновременно:

foo = 1,
      2,
      3,

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

Моя грамматика выглядит следующим образом:

content : content '\n'
        : content assignment
        | <empty>

assignment : NAME '=' value
           | NAME '=' list

value : TEXT
      | NUMBER

list : ???

Примечание: мне нужен '\ n' в грамматике, чтобыЗапретите этот код:

foo
=
"bar"

Заранее спасибо,

Антуан.

Ответы [ 2 ]

2 голосов
/ 15 марта 2012

Похоже, что ваш язык конфигурации является по сути свободной формой. Я бы забыл о том, чтобы сделать перевод строки символом грамматики. Если вы хотите ограничения новой строки, вы можете взломать его как некоторые лексические правила встраивания, в результате чего анализатор вызывает небольшой API, добавленный к лексеру, чтобы проинформировать лексера о том, где он находится в грамматике, и лексер может решить, принимать ли его. переводить строки или отклонять их с ошибкой.

Попробуйте эту грамматику.

%token NAME NUMBER TEXT

%%

config_file : assignments
            | /* empty */
            ;

assignments : assignment
            | assignments assignment
            ;

assignment : NAME '=' values comma_opt

comma_opt : ',' | /* empty */;

values : value
       | values ',' value
       ;

value : NUMBER | TEXT ;

Он строит для меня без конфликтов. Я не запускал его, но случайное чтение y.output выглядит так, как будто переходы нормальны.

Эта грамматика, конечно, позволяет

foo = 1, 2, 3, bar = 4, 5, 6 xyzzy = 7 answer = 42

без дополнительной связи с лексером.

Ваши ограничения означают, что переводы строки разрешены только в значениях. Два токена NAME никогда не должны появляться в одной строке, а символ = должен появляться в той же строке, что и предыдущее NAME (и, вероятно, первое значение также должно быть).

Обычно, когда анализатор сканирует первое значение, он может сказать лексеру: «значения сейчас сканируются, включите допуск новых строк». И затем, когда comma_opt уменьшится, это можно снова отключить. Когда значение comma_opt уменьшается, лексер, возможно, уже прочитал токен NAME следующего назначения, но он может проверить, что это происходит в строке, отличной от предыдущего NAME. Вы хотите, чтобы ваш лексер все равно отслеживал точное количество строк.

0 голосов
/ 14 марта 2012

У меня нет особого опыта с этим, но будет ли это работать?

listvalue : value ,
          | value '\n'
          | value , '\n'

list : listvalue list
...