Допустимо ли хранить предыдущее состояние как глобальную переменную?

Одной из самых больших проблем при проектировании комбинации лексический анализатор/парсер является чрезмерное усердие при проектировании анализатора. (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-символьных записях), я не смогу использовать силу гибкости для токенизации структурированных данных, находящихся в .{71}.

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

  1. Entering a CODE1 state from the <INITIAL> start condition results in calls to:
    • 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.


person kmore    schedule 05.01.2012    source источник


Ответы (1)


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

person Saijanai    schedule 05.01.2012