Как я заставляю Bison/YACC не распознавать команду, пока он не анализирует целую строку?

У меня есть некоторая грамматика бизона:

input: /* empty */
       | input command
;

command:
        builtin
        | external
;

builtin:
        CD { printf("Changing to home directory...\n"); }
        | CD WORD { printf("Changing to directory %s\n", $2); }
;

Я задаюсь вопросом, как я заставляю Бизона не принимать (YYACCEPT?) что-то как a command пока это не читает ВЕСЬ вход. Таким образом, у меня могут быть все эти правила ниже той рекурсии использования или безотносительно создавать вещи, который или приводит к допустимой команде или чему-то, что это не собирается работать.

Один простой тест, который я делаю с кодом выше, просто вводит "CD mydir mydir". Синтаксические анализы бизона CD и WORD и идет "эй! это - команда, поместите ее в вершину!". Затем следующий маркер это находки справедливо WORD, который не имеет никакого правила, и затем это сообщает об ошибке.

Я хочу, чтобы это считало целую строку и поняло CD WORD WORD не правило, и затем сообщите об ошибке. Я думаю, что пропускаю что-то очевидное и был бы очень признателен за любую справку - Спасибо!

Также - я попытался использовать input command NEWLINE или что-то подобное, но это все еще продвигает CD WORD к вершине как команда и затем анализирует дополнительное WORD отдельно.

5
задан chucknelson 10 April 2010 в 12:57
поделиться

3 ответа

Иногда я работаю с этими случаями, выравнивая свои грамматики.

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

sep:   NEWLINE | SEMICOLON
   ;

command:  CD  sep
   |  CD WORD sep
   ;

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

args:
    /* empty */
  | args WORD
  ;

command:
      CD args sep
   ;
2
ответ дан 15 December 2019 в 06:21
поделиться

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

0
ответ дан 15 December 2019 в 06:21
поделиться

Обычно все делается не так, как вы описываете.

С Bison / Yakk / Lex обычно тщательно разрабатывают синтаксис, чтобы делать именно то, что им нужно. Поскольку Bison / Yakk / Lex от природы жадные свои регулярные выражения, это должно вам помочь.

А как насчет этого?

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

input : /* empty */
      | line


command-break : command-break semi-colon
              | semi-colon

line : commands new-line

commands : commands command-break command
         | commands command-break command command-break
         | command
         | command command-break

...

Где новая строка , точка с запятой определена в исходном тексте lex как что-то вроде \ n , \ t `. Это должно дать вам синтаксис в стиле UNIX для команд, которые вы ищете. Возможны всевозможные вещи, и он немного раздут, допускает использование нескольких точек с запятой и не принимает во внимание пробелы, но вы должны уловить идею.

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

0
ответ дан 15 December 2019 в 06:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: