[содержание] [назад] [пред] [вверх] [след] [вперед] 8. обработка контекстных зависимостейосновной принцип bison в том, чтобы сначала разбираются лексемы, а затем они группируются в более крупные синтаксические единицы. во многих языках значение лексемы зависит от её контекста. хотя это и нарушает принципы bison, существуют определённые приёмы (известные как кладжи), которые дают вам возможность писать анализаторы bison для таких языков. (на самом деле, "кладж" -- это всякий приём, который решает поставленную задачу, но не является ни чистым, ни надёжным.) 8.1 семантическая информация в типах лексемязык c содержит контекстную зависимость -- способ использования идентификаторов зависит от его текущего смысла. например, рассмотрим: foo (x);
это выглядит как оператор вызова функции, но если
в gnu c используется метод, состоящий в том, чтобы иметь два разных типа
лексем:
правила грамматики могут затем выражать контекстную зависимость выбором
типа лексемы при распознавании. этот приём просто использовать, если решение, какой тип идентификаторов допустим, принимается в месте, близком к тому, где разбирается этот идентификатор. но в c это не всегда так: c допускает, чтобы объявление переопределяло имя определения типа, при условии, что явный тип был задан ранее: typedef int foo, bar, lose; static foo (bar); /* переопределить к сожалению, объявляемое имя отделено от самой объявляющей конструкции сложной синтаксической структурой -- "объявлятелем". в результате часть анализатора bison для c должна быть продублирована с изменением имён всех нетерминалов: одно для разбора объявления, в котором имя определения типа может быть переопределено, и другое для разбора объявлений, в которых это невозможно. приведём часть такого дублирования, действия в котором опущены для краткости: initdcl: declarator maybeasm '=' init | declarator maybeasm ; notype_initdcl: notype_declarator maybeasm '=' init | notype_declarator maybeasm ;
здесь есть нечто общее между этим приёмом и лексической увязкой (описанной ниже), в том, что информация, изменяющая ход лексического анализа, изменяется во время разбора другим частями программы. различие в том, что здесь эта информация глобальна, и используется в программе для других целей. истинная лексическая увязка имеет флаг специального назначения, управляемый синтаксическим контекстом. 8.2 лексическая увязкаодним из способов обработки контекстной зависимости является лексическая увязка -- флаг, устанавливаемый действиями bison, предназначенный для изменения способа разбора лексем.
например, предположим, что у нас есть язык, смутно похожий на c, но со
специальной конструкцией `hex (шестнадцатеричное_выражение)'.
после ключевого слова %{ int hexflag; %} %% ... expr: identifier | constant | hex '(' { hexflag = 1; } expr ')' { hexflag = 0; $$ = $4; } | expr '+' expr { $$ = make_sum ($1, $3); } ... ; constant: integer | string ;
здесь мы полагаем, что
объявление 8.3 лексическая увязка и восстановление после ошибоклексическая увязка предъявляет строгие требования ко всем имеющимся у вас правилам восстановления после ошибок. см. раздел 7. восстановление после ошибок. причина этого в том, что целью правил восстановления после ошибок является прервать анализ одной конструкии и возобновить анализ более крупных конструкций. например, в языках типа c типичное правило восстановления после ошибки пропускает лексемы до следующей точки с запятой, и затем начинает разбор нового оператора, как здесь: stmt: expr ';' | if '(' expr ')' stmt { ... } ... error ';' { hexflag = 0; } ;
если внутри конструкции `hex (выражение)' есть синтаксическая
ошибка, будет применено это правило обработки ошибок, и тогда действия для
законченного `hex (выражение)' никогда не будут выполнены. поэтому
чтобы избежать этой проблемы, правило восстановления после ошибки само
сбрасывает также могут существовать правила восстановления после ошибок, работающие внутри выражений. например, может быть правило, применяющееся внутри скобок и пропускающее всё до закрывающей скобки: expr: ... | '(' expr ')' { $$ = $2; } | '(' error ')' ...
если это правило действует внутри конструкции
что если существует правило восстановления после ошибок, которое может прервать
или не прерывать разбор конструкции [содержание] [назад] [пред] [вверх] [след] [вперед] |