![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Semantic ActionsBoost , ,
Семантические действия имеют форму:выражение[действие] В конечном счете, после того, как мы определили нашу грамматику и создали соответствующий парсер, нам нужно будет произвести некоторый вывод и выполнить некоторую работу, помимо синтаксического анализа; если, конечно, мы не хотим просто проверить соответствие ввода нашей грамматике, что очень редко бывает. Семантические действия могут быть прикреплены к любому выражению на любом уровне иерархии парсера. Действие - это функция или объект функции C/C++, который будет называться, если совпадение найдено в конкретном контексте, где оно прикреплено. Функция действия служит крюком в парсере и может использоваться, например:
Generic Semantic Actions (Transduction Interface)Общим семантическим действием может быть любая свободная функция или объект функции, совместимый с интерфейсом:
гдеИтератор- тип используемого итератора,первыйуказывает на текущий вход ипоследнийуказывает на один после окончания входа (идентичный диапазонам итератора STL). Объект функции (функционер) должен иметь участникаоператора().с той же подписью, что и выше:
Итераторы, указывающие на соответствующую часть входа, передаются в функцию/функтор. В общем, семантические действия принимают пару первого итератора. Это интерфейс трансдукции. Функции действия или функторы получают необработанные данные, представляющие соответствующую продукцию непосредственно с входа. Во многих случаях этого достаточно. Примерами являются исходный перевод, предварительная обработка и т.д. Example:
Функцияmy_actionбудет называться всякий раз, когда выражение(a | b | * (c >>d)соответствует части входного потока при разборе. Два итератора,первыйипоследний, переходят в функцию. Эти итераторы указывают на начало и конец, соответственно, части входного потока, где находится совпадение. Const-ness:С помощью функторов обратите внимание, что оператордолжен бытьconst. Это означает, что функторы неизменны. Можно захотеть иметь некоторые переменные, которые изменяются при вызове действия. Это не очень хорошая идея. В первую очередь, функторы предпочтительно легкие. Функторы часто проходят вокруг, и это повлечет за собой много накладных расходов, если функторы сильно нагружены. Во-вторых, функторы передаются по стоимости. Таким образом, фактический объект функтора, который, наконец, прикрепляется к парсеру, не будет оригинальным экземпляром, предоставленным клиентом. Это означает, что изменения в состоянии функтора не повлияют на исходный функтор, который прошел клиент, поскольку они являются отдельными копиями. Если функтору необходимо обновить некоторые переменные состояния, что часто бывает, то лучше использовать ссылки на внешние данные. Следующий пример показывает, как это можно сделать:
Full Example:Вот наш калькулятор, усиленный семантическими действиями:
Мы дополняем нашу грамматику смысловыми действиями:
Кормление в выражении(-1 + 2) * (3 + -4), например, по правилувыражениедаст ожидаемый выход:
Что, кстати, и есть Обратная польская нотация (РПН) данного выражения, напоминающая некоторые примитивные калькуляторы и язык Форт.
Specialized ActionsВ общем, семантические действия принимают пару первого итератора. Существуют ситуации, когда мы можем захотеть передать данные в обработанной форме. Конкретным примером является числовой парсер. Неразумно передавать необработанные данные в семантическое действие, прикрепленное к числовому парсеру, и просто выбрасывать то, что было проанализировано парсером. Мы хотим передать фактический парсированный номер. Функция и подпись функтора семантического действия варьируется в зависимости от парсера, к которому он прикреплен. В следующей таблице перечислены парсеры, которые принимают уникальные подписи.
Numeric ActionsПрименяется к:
Подпись для функций:
Подпись для функторов:
ГдеNumT- любой примитивный числовой тип, такой какint,long,float,doubleи т.д., или пользователь, определенный числовой тип, такой как big_int.NumT- это тот же тип параметра шаблона, который используется дляuint_p,int_p,ureal_pилиreal_p. Парсируемое число передается в функцию/функтор. Character ActionsПрименяется к:
Подпись для функций:
Подпись для функторов:
гдеCharT- значение_тип итератора, используемого при парсинге. Например, итераторchar const*имеетзначение_типchar. Соответствующий символ передается в функцию/функтор. Cascading ActionsДействия могут быть каскадными. Каскадные действия также наследуют функциональный интерфейс оригинала. Например:
Здесь функторыfa,fbиfcвсе ожидают подписиvoid operator()(неподписанный n) const. Directives and ActionsДирективы наследуют функциональный/функциональный интерфейс субъекта, который они охватывают. Пример:
Здесь функторfожидает подписьvoid operator()(char ch) const, предполагая, что используемый итератор являетсяchar const*.
Copyright © 1998-2003 Joel de Guzman
Статья Semantic Actions раздела может быть полезна для разработчиков на c++ и boost. Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта. :: Главная :: ::
|
||||||||||||||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |