Допустимо ли хранить предыдущее состояние в качестве глобальной переменной? - PullRequest
2 голосов
/ 05 января 2012

Одной из самых больших проблем при разработке комбинации лексического анализатора / анализатора является чрезмерная усердие в разработке анализатора.(f) lex не имеет логики парсера, которая иногда может мешать разработке мини-парсеров (с помощью yy_push_state(), yy_pop_state() и yy_top_state().

Моя цель -для анализа документа вида:

CODE1 this is the text that might appear for a 'CODE' entry
SUBCODE1 the CODE group will have several subcodes, which
      may extend onto subsequent lines.
SUBCODE2 however, not all SUBCODEs span multiple lines
SUBCODE3 still, however, there are some SUBCODES that span
      not only one or two lines, but any number of lines.
      this makes it a challenge to use something like \r\n
      as a record delimiter.
CODE2 Moreover, it's not guaranteed that a SUBCODE is the
      only way to exit another SUBCODE's scope. There may
      be CODE blocks that accomplish this.

В конце концов, я решил, что этот раздел проекта лучше оставить лексическому анализатору, поскольку я не хочу создавать шаблон, которыйсоответствует каждой строке (и идентифицирует записи продолжения). Частично причина в том, что я хочу, чтобы лексический синтаксический анализатор знал содержание каждой строки, не включая свою собственную логику токенизации. То есть, если я соответствую ^SUBCODE[ ][ ].{71}\r\n (все записи заблокированы в 80-символьных записях) Я не смог бы использовать возможности flex для токенизации структурированных данных, находящихся в .{71}.

Учитывая эти ограничения, я думаю сделать следующее:

  1. Вход в состояние CODE1 из условия запуска <INITIAL> приводит к вызовам:
    • yy_push_state(CODE_STATE)
    • yy_push_state(CODE_CODE1_STATE)
    • (сделать что-то сСодержимое идентификатора состояния CODE1, если такое содержимое существует)
    • yy_push_state(SUBCODE_STATE) (чтобы сообщить анализатору ожидать SUBCODE состояний, принадлежащих CODE_CODE1_STATE. Здесь анализатор начинает маскироваться под синтаксический анализатор.
  2. Условие запуска <SUBCODE1_STATE> вложено следующим образом: <CODE_STATE>{ <CODE_CODE1_STATE> { <SUBCODE_STATE>{ <SUBCODE1_STATE> { (perform actions based on the matching patterns) } } }.Он также устанавливает глобальную переменную previous_state на yy_top_state(), то есть SUBCODE1_STATE.
  3. В пределах <SUBCODE1_STATE>, \r\n вызовет yy_pop_state().Если имеется запись продолжения (которая является шаблоном в самой высокой области видимости, с которой сопоставляется весь текст), вызывается yy_push_state(continuation_record_states[previous_state]), что возвращает нас к области действия в 2 .continuation_record_states[] сопоставляет каждое состояние с его состоянием записи продолжения, которое используется синтаксическим анализатором.

Как видите, это довольно сложно, что приводит меня к выводу, что я чрезмерно перегруженусложняет задачу.

Вопросы

  1. Для государств, в которых отсутствует чрезвычайно четкий токен, обозначающий конец его области действия, приемлемо ли мое предлагаемое решение?
  2. Учитывая, что я хочуЧтобы токенизировать ввод с помощью flex, есть ли способ сделать это без условий запуска?

Самая большая проблема у меня заключается в том, что каждая запись (начиная с префикса (SUB)CODE) уникальна,но информация, появляющаяся после префикса (SUB)CODE, отсутствует.Поэтому почти кажется обязательным иметь несколько таких состояний, и абстрактные состояния CODE_STATE и SUBCODE_STATE будут действовать как группировки для каждого из конкретных состояний SUBCODE[0-9]+_STATE и CODE[0-9]+_STATE.

1 Ответ

1 голос
/ 05 января 2012

Я бы посмотрел, как парсер OMeta обрабатывает эти вещи.

...