Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

About Tokens and Token Values

Boost , Spirit 2.5.2 , Lexer Primitives

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Как уже говорилось, лексическое сканирование — это процесс анализа потока входных символов и разделения его на строки, называемые токенами, большую часть времени разделенные белым пространством. Различные типы токенов, распознаваемые лексическим анализатором, часто получают уникальные целые идентификаторы токенов (идентификаторы токенов). Эти идентификаторы токенов обычно используются парсером для идентификации текущего токена без необходимости снова смотреть на соответствующую строку.Дух.ЛексБиблиотека не отличается в этом отношении, поскольку она использует идентификаторы токенов в качестве основного средства идентификации различных типов токенов, определенных для конкретного лексического анализатора. Однако он отличается от обычно используемых лексических анализаторов в том смысле, что он возвращает (ссылки на) экземпляры (определяемого пользователем) класса токенов пользователю. Единственное ограничение этого класса токенов заключается в том, что он должен нести по крайней мере идентификатор токена, который он представляет. Для получения дополнительной информации об интерфейсе, который пользователь определил как тип токена, пожалуйста, посмотрите ссылку на класс токенов. Библиотека предоставляет тип токена по умолчанию на основе библиотекиLexertl, которого должно быть достаточно в большинстве случаев: тип<lex::lexertl::token<>>. В этом разделе основное внимание уделяется описанию общих функций, которые может реализовать класс токенов, и тому, как он интегрируется с другими частями.Spirit.LexБиблиотека.

The Anatomy of a Token

Очень важно понимать разницу между определением токена (представленным шаблоном<lex::token_def<>>) и самим токеном (например, представленным шаблоном<lex::lexertl::token<>>).

Определение токена используется для описания основных особенностей конкретного типа токена, особенно:

  • для упрощения определения типа токена с использованием обычного шаблона выражения, применяемого при сопоставлении этого типа токена,
  • ассоциировать тип токена с конкретным состоянием лексера;
  • необязательно назначать идентификатор токена типу токена,
  • необязательно ассоциировать некоторый код для выполнения, когда экземпляр этого типа токена был сопоставлен,
  • и необязательно указать тип атрибута значения токена.

Сам токен представляет собой структуру данных, возвращаемую итераторами лексера. Ссылка на итератор лексера возвращает ссылку на последний совпадающий экземпляр токена. Он инкапсулирует часть базовой входной последовательности, соответствующую регулярному выражению, используемому во время определения этого типа токенов. Увеличение итератора лексера вызывает лексический анализатор, чтобы соответствовать следующему токену, продвигая основной входной поток. Структура данных токена содержит по меньшей мере идентификатор токена соответствующего типа токена, что позволяет идентифицировать согласованную последовательность символов. Необязательно, экземпляр токена может содержать значение токена и/или состояние лексера, в котором этот экземпляр токена был сопоставлен. Следующийрисунокпоказывает схематическую структуру токена.

Figure 8. The structure of a token

The structure of a token


Значение токена и состояние лексера, в котором был распознан токен, могут быть опущены по причинам оптимизации, что позволяет избежать необходимости того, чтобы токен переносил больше данных, чем фактически требуется. Эта конфигурация может быть достигнута путем предоставления соответствующих параметров шаблона для<lex::lexertl::token<>>шаблона при определении типа токена.

Итератор лексера возвращает один и тот же тип токена для каждого из различных согласованных определений токена. Чтобы учесть возможные различные типы токенов, представленные различными типами токенов (определения токенов), общий тип значения токенов являетсяBoost.Variant. Как минимум (для конфигурации по умолчанию) этот вариант значения токена будет сконфигурирован так, чтобы всегда держать.<boost::iterator_range>содержит пару итераторов, указывающих на соответствующую входную последовательность для этого экземпляра токена.

[Note]Note

Если лексический анализатор используется в сочетании с парсеромSpirit.Qi, сохраненное значение токена<boost::iterator_range>будет преобразовано в запрашиваемый тип токена (атрибут парсера) ровно один раз. Это происходит во время первого доступа к значению токена, требующего соответствующего преобразования типа. Преобразованное значение токена будет храниться вBoost. Вариантзамены первоначально хранимого диапазона итераторов. Это позволяет избежать необходимости конвертировать входную последовательность в значение токена более одного раза, тем самым оптимизируя интеграцию лексера сSpirit.Qi, даже во время парсерного обратного трекинга.

Вот прототип шаблона<lex::lexertl::token<>>:

template <
    typename Iterator = char const*,
    typename AttributeTypes = mpl::vector0<>,
    typename HasState = mpl::true_
>
struct lexertl_token;

where:

Iterator

Это тип итератора, используемого для доступа к основному входному потоку. В этом есть доля истины<char const*>.

AttributeTypes

Это либо последовательность mpl, содержащая все типы атрибутов, используемые для определений токенов, либо тип<omit>. Если последовательность mpl пуста (что является по умолчанию), все экземпляры токенов будут хранить<boost::iterator_range><<Iterator>>, указывающие на начало и конец совпадающего раздела во входном потоке. Если тип<omit>, то генерируемые токены вообще не будут содержать значения токена (атрибута).

HasState

Это либо<mpl::true_>, либо<mpl::false_>, что позволяет контролировать, будут ли генерируемые экземпляры токенов содержать состояние лексера, в котором они были созданы. По умолчанию mpl::true_, поэтому все экземпляры токенов будут содержать состояние лексера.

Обычно во время строительства экземпляр токена всегда содержит<boost::iterator_range>в качестве значения токена, если он не был определен с использованием типа значения токена<omit>. Затем этот диапазон итераторов преобразуется в запрашиваемый тип значения токена (атрибут), когда он запрашивается впервые.

The Physiognomy of a Token Definition

Определения токенов (представленные шаблоном<lex::token_def<>>) обычно используются как часть определения лексического анализатора. В то же время экземпляр определения токена может использоваться в качестве парсерного компонента.Дух.Qi.

Прототип шаблона этого класса показан здесь:

template<
    typename Attribute = unused_type,
    typename Char = char
>
class token_def;

where:

Attribute

Это тип значения токена (атрибута), поддерживаемый экземплярами токена, представляющими этот тип токена. Этот тип атрибута подвергается воздействиюБиблиотека Spirit.Qi, когда это определение токена используется в качестве парсерного компонента. Тип атрибута по умолчанию<unused_type>, что означает, что экземпляр токена содержит<boost::iterator_range>, указывающий на начало и конец сопоставленного раздела во входном потоке. Если<omit>, то [[<omit>], то [[[[[]]], [[[[]]]], [[[[[]]]], [[[[[]]]]], [[[[[[]]]]], [[[[[[]]]]]], [[[[[[]]]]]], [[[[[[[]]]]]][[[[[[[]]]]]][[[[[[]]]]]][[[[[]]]]]][[[[[[]]]]]][[[[[[]]]]]][[[[[]]]]]][[[[[[]]]]]][[[[[[[]]]]]]][[[[[[]]]]]][[[[[[[]]]]]]][[[[[[]]]]]]]][[[[[[[[]]]]]]] Любой другой тип будет использоваться непосредственно как тип значения токена.

Char

Это тип значения итератора для базовой входной последовательности. Недостаток<char>.

Семантика параметров шаблона для типа токена и типа определения токена очень похожи и взаимозависимы. Как правило, вы можете думать о типе определения токена как о средстве определения всего, что связано с одним конкретным типом токена (например,<identifier>или<integer>). С другой стороны, тип токена используется для определения общих свойств всех экземпляров токенов, генерируемых библиотекойSpirit.Lex.

[Important]Important

Если вы не перечислите какие-либо типы значений токена в декларации определения типа токена (что приводит к использованию по умолчанию<boost::iterator_range>типа токена), все будет компилироваться и работать просто отлично, немного менее эффективно. Это связано с тем, что значение токена будет конвертироваться из согласованной последовательности ввода каждый раз, когда он запрашивается.

Но как только вы укажете хотя бы один тип значения токена при определении типа токена, вам нужно будет перечислить все типы значений, используемые для<lex::token_def<>>деклараций в классе определения токена, иначе будут возникать ошибки компиляции.

Examples of using lex::lexertl::token<>

Начнем с некоторых примеров. Мы ссылаемся на один из примеровSpirit.Lex(для полного исходного кода этого примера см.example4.cpp).

Первый фрагмент кода показывает выдержку из класса определения токена, определение пары типов токенов. Некоторые из типов токенов не выставляют специального значения токена<if_>,<else_>и<while_>. Их значение токена всегда будет удерживать диапазон итератора согласованной входной последовательности. Определения токенов для<identifier>и целого числа<constant>специализированы для раскрытия явного типа токена каждый:<std::string>и<unsigned int>.

// these tokens expose the iterator_range of the matched input sequence
lex::token_def<> if_, else_, while_;
// The following two tokens have an associated attribute type, 'identifier'
// carries a string (the identifier name) and 'constant' carries the 
// matched integer value.
//
// Note: any token attribute type explicitly specified in a token_def<>
//       declaration needs to be listed during token type definition as 
//       well (see the typedef for the token_type below).
//
// The conversion of the matched input to an instance of this type occurs
// once (on first access), which makes token attributes as efficient as 
// possible. Moreover, token instances are constructed once by the lexer
// library. From this point on tokens are passed by reference only, 
// avoiding them being copied around.
lex::token_def<std::string> identifier;
lex::token_def<unsigned int> constant;

Поскольку парсеры, генерируемыеSpirit.Qi, полностью приписываются, любойSpirit.Qiпарсерный компонент должен выставлять определенный тип в качестве своего парсерного атрибута. Естественно, что<lex::token_def<>>раскрывает тип значения токена в качестве своего атрибута парсера, обеспечивая плавную интеграцию сSpirit.Qi.

Следующий фрагмент кода показывает, как задаются требуемые типы значений токенов при определении типа токена для использования. Все типы значений токена, используемые по меньшей мере для одного из определений токена, также должны быть повторно повторены для определения токена.

// This is the lexer token type to use. The second template parameter lists 
// all attribute types used for token_def's during token definition (see 
// calculator_tokens<> above). Here we use the predefined lexertl token 
// type, but any compatible token type may be used instead.
//
// If you don't list any token attribute types in the following declaration 
// (or just use the default token type: lexertl_token<base_iterator_type>)  
// it will compile and work just fine, just a bit less efficient. This is  
// because the token attribute will be generated from the matched input  
// sequence every time it is requested. But as soon as you specify at 
// least one token attribute type you'll have to list all attribute types 
// used for token_def<> declarations in the token definition class above, 
// otherwise compilation errors will occur.
typedef lex::lexertl::token<
    base_iterator_type, boost::mpl::vector<unsigned int, std::string>
> token_type;

Чтобы избежать токена, чтобы иметь значение токена вообще, можно использовать специальный тег<omit>:<token_def<omit>>и<lexertl_token<base_iterator_type,omit>>.


PrevUpHomeNext

Статья About Tokens and Token Values раздела Spirit 2.5.2 Lexer Primitives может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Lexer Primitives ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 19:35:38/0.029397010803223/1