Можно ли убрать внутренний контроль лексера парсером для разбора heredoc в оболочке? - PullRequest
0 голосов
/ 07 февраля 2019

Чтобы справиться с heredoc в оболочке (например, bash), правило грамматики изменит переменную need_here_doc через push_heredoc().

    |   LESS_LESS WORD
            {
              source.dest = 0;
              redir.filename = $2;
              $$ = make_redirection (source, r_reading_until, redir, 0);
              push_heredoc ($$);
            }

http://git.savannah.gnu.org/cgit/bash.git/tree/parse.y#n539

static void
push_heredoc (r)
     REDIRECT *r;
{
  if (need_here_doc >= HEREDOC_MAX)
    {
      last_command_exit_value = EX_BADUSAGE;
      need_here_doc = 0;
      report_syntax_error (_("maximum here-document count exceeded"));
      reset_parser ();
      exit_shell (last_command_exit_value);
    }
  redir_stack[need_here_doc++] = r;
}

http://git.savannah.gnu.org/cgit/bash.git/tree/parse.y#n2794

need_here_doc используется в read_token(), который вызывается yylex().Это делает поведение yylex() неавтомным.

Нормально ли проектировать синтаксический анализатор, который может изменить поведение yylex()?

Это потому, что язык оболочки не является LALR (1), поэтому нет способа избежать изменения поведения yylex () действиями грамматики?

      if (need_here_doc)
    gather_here_documents ();

http://git.savannah.gnu.org/cgit/bash.git/tree/parse.y#n3285

  current_token = read_token (READ);

http://git.savannah.gnu.org/cgit/bash.git/tree/parse.y#n2761

1 Ответ

0 голосов
/ 07 февраля 2019

Нормально ли проектировать парсер, который может изменить поведение yylex ()?

Конечно.Возможно, он не идеален, но чрезвычайно распространен.

Синтаксис оболочки Posix далек от идеального кандидата для синтаксического анализатора flex / bison и является единственным, что можно сказать о реализации bash с использованием flex и bisonв том, что он демонстрирует, насколько гибкими могут быть эти инструменты, если их толкнуть до соответствующих пределов.Здесь документы - не единственное место, где необходима «лексическая обратная связь».

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

Возможно, самый известный (или наиболее часто комментируемый) лексическийобратная связь - это синтаксический анализ приведенных выражений в стиле C, которые требуют, чтобы лексер знал, является ли foo в (foo) типизированным именем или нет.(Это обычно реализуется с помощью таблицы символов, совместно используемой синтаксическим анализатором и лексером, но точные детали реализации хитры.)

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

  • Python (и Haskell) требуют, чтобы лексический сканер переформулировал ведущий пробел в токены INDENT или DEDENT.Но если в скобках происходит разрыв строки, обработка пробелов подавляется (включая сам токен NEWLINE).

  • Ecmascript (Javascript), а другие языки допускают регулярное выражениелитералы должны быть написаны в окружении / с.Но / также может быть оператором деления или первым символом в /= операторе мутации.Лексическое решение зависит от контекста разбора.(Это можно догадаться по лексическому сканеру из недавней истории токенов, который будет считаться воспроизводящей частью логики синтаксического анализа в лексическом сканере.)

  • Как и выше, во многих языкахперегрузка < способами, которые усложняют логику в лексическом сканере.Использование в качестве скобки шаблона вместо оператора сравнения может рассматриваться в сканере - например, в C ++, это будет зависеть от таких функций, как, например, был ли предыдущий идентификатор шаблоном или нет - но это на самом деле не меняетсялексический контекст.Однако использование угловой скобки для обозначения начала литерала X / HTML (или шаблона) определенно меняет лексический контекст.Как и в приведенном выше примере с регулярным выражением, необходимо знать, будет ли синтаксически допустимым оператор сравнения или нет.

Это потому, что язык оболочки не является LALR(1), поэтому нет способа избежать изменения поведения yylex() с помощью грамматических действий?

Синтаксис оболочки Posix, безусловно, не является LALR (1) или даже не зависит от контекста,Но большинство языков не может быть проанализировано без сканера с помощью синтаксического анализатора LALR (1), и многие языки оказываются лишенными контекстно-грамматической грамматики, если принять во внимание все синтаксические соображения.(См. Приведенные выше выражения в стиле C). Возможно, shell дальше от платонического идеала, чем большинство.Но с годами оно выросло из ядра, предназначенного для простого ввода, а не для формального анализа.(Никаких комментариев от меня о том, можно ли распространить это оправдание на Perl, я не собираюсь здесь обсуждать.)

В общем, я бы сказал, что языки, которые встраивают другие языки (регулярные выражения, фрагменты HTML, семантические действия Flex / Bison, арифметические расширения оболочки и т. Д. И т. Д.), Создают проблемы для упрощенной модели синтаксического анализатора / сканера.Несмотря на множество интересных работ и глубоких экспериментов, я чувствую, что встраивание в язык все еще не имеет хорошей реализуемой формальной структуры.А поскольку большинство языков имеют встроенные подъязыки, в их реализациях синтаксического анализатора есть и будет определенная поддержка.Частично, это то, что делает эту область обучения такой веселой.

...