Нетерминалы хорошо известны из парсеров, где они используются в качестве основного средства построения более сложных парсеров из более простых. Нетерминалы в парсерном мире очень похожи на функции в императивном языке программирования. Они могут быть использованы для инкапсуляции выражений парсера для конкретной входной последовательности. После определения нетерминалы могут использоваться в качестве «нормальных» парсеров в более сложных выражениях, когда инкапсулированный вход должен быть распознан. Парсер нетерминалов вДух.Qiможет принятьпараметры(унаследованные атрибуты) и обычно возвращают значение (синтезированный атрибут).
Оба типа наследственных и синтезированных атрибутов должны быть четко определены при определении конкретнойграмматики
или правила
(ДухРепозиторийдополнительно имеетподправила
, которые соответствуют аналогичному интерфейсу). В качестве примера, следующий код объявляетSpirit.Qiправило
, разоблачающееint
как его синтезированный атрибут, ожидая при этом единственногодвойного
как его унаследованный атрибут (см. раздел оДух.QiПравило для получения дополнительной информации):
qi::rule<Iterator, int(double)> r;
В мире генераторов нетерминалы так же полезны, как и в мире парсеров. Нетерминалы генератора инкапсулируют описание формата для конкретного типа данных, и всякий раз, когда нам нужно излучать выход для этого типа данных, соответствующий нетерминал вызывается таким же образом, как и предопределенныйДух. Кармагенератор примитивных.Дух. Карманетерминалов очень похожа наSpirit.Qiнетерминалов. Генераторные нетерминалы также могут приниматьпараметры, и мы называем эти наследственные атрибуты также. Главное отличие состоит в том, что они не выставляют синтезированного атрибута (как это делают парсеры), а требуют специальногопотребляемого атрибута. Обычно потребляемым атрибутом является значение, из которого генератор создает свой выход. Даже если потребленный атрибут не «возвращен» из генератора, мы решили использовать тот же синтаксис декларации функционального стиля, что и вSpirit.Qi. Приведенный ниже пример говорит о духе. Кармаправило
потребляетдвойной
, не ожидая никаких дополнительных наследственных признаков.
karma::rule<OutputIterator, double()> r;
Унаследованные атрибуты не терминальных парсеров и генераторов обычно передаются компоненту во время его вызова. Это параметры, которые может принять парсер или генератор, и они могут использоваться для параметризации компонента в зависимости от контекста, из которого они вызваны.