Грамматика не терминальная? - PullRequest
0 голосов
/ 27 января 2020

В настоящее время я разрабатываю свою собственную оболочку для C, Bison & Flex.

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

Моя проблема находится в грамматике argList (я думаю). arg argList { $1->next = $2; $$ = $1; } используется, чтобы позволить мне позже передать более одного аргумента в список.

Без этого скомпилированный парсер работает так, как задумано: он позволяет мне вводить токен MOS и выполняет эту функцию, позволяя после этого продолжать вводить токен MOS с другим (но ограниченным одним) аргументом.

С этим фрагментом грамматики парсер позволяет мне вводить токен MOS, но выполняет эту функцию только тогда, когда я нажимаю Ctrl + D из него. Почему?

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

Приветствия.

код ЗИЗНА


commandList
  : command                { $$ = $1; }
  | command commandList  { $1->next = $2; $$ = $1; }
  ;


command
  : MOS argList             { $$ = insert_Mostra( NULL, $2 ); ExecuteCommands($$); }
  ;

argList
  : arg           { $$ = $1; }
  | arg argList   { $1->next = $2; $$ = $1; }
  ;

arg
  : VAR_VALUE { $$ = insert_Args(NULL, $1); }
  ;

1 Ответ

0 голосов
/ 30 января 2020

С этим фрагментом грамматики парсер позволяет мне вводить токен MOS, но выполняет эту функцию только тогда, когда я нажимаю Ctrl + D из него. Почему?

В двух словах, потому что парсеры lex и ya cc не подходят для интерактивного ввода.

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

Если вы используете lex, это означает изменение сканер, так что он может принимать входные данные из буфера в памяти, а не только из потока.

Вы не можете иметь интерактивную оболочку, вызывая yyparse, который вызывает yylex, который извлекает символы из stdin. Если вы запускаете его из-за различных проблем.

Во-первых, ввод будет буферизован строкой (в ядре, на уровне TTY). lex не видит ничего, что вы вводите, пока не нажмете Enter.

Во-вторых, бот лексера и анализатор используют «lookahead». Чтобы распознать токен, лексер, управляемый регулярным выражением, использует N символов. Парсер LALR (1) использует один токен упреждения. Lookahead добавляет в заблуждение пользователя, потому что машина продолжает ожидать большего ввода, даже если пользователю уже дана полная фраза.

Пользователь думает: "почему Разве машина не вычисляет только полное введенное синтаксически правильное выражение? ".

Машина считает: " согласно моей грамматике, это выражение (хотя и неоспоримо допустимое) может быть просто префикс более длинного; мне нужно посмотреть, что, если что-нибудь, последует за ним! Мне нужно больше ввода или EOF! ".

(Зачем лексеру требуется N символов например, предположим, что у нас есть лексическая грамматика с тремя фиксированными токенами: aaaaab, a и x. Предположим, что введено значение aaax. Сканер должен подозревать, что он может смотреть на aaaaab токен, поэтому он читает все символы a, пока не достигнет x. В этот момент автомат регулярных выражений понимает, что aaaaab не может совпадать. И так как токен делает не начинайте с x, он должен смотреть на a токен. Так что токен a возвращается анализатору. Таким образом, входная позиция должна возвращаться назад до второй a. Другими словами, машина должна была смотреть за пределы первого a на aax, чтобы разрешить токен: она использовала три символа предвкушения.)

Синтаксический анализ Lookahead по вводу в свободном формате может привести к путанице -пользователь с неисправимыми ошибками; это пользовательский интерфейс без стартера.

...