Boost.Spirit用户手册翻译(16):深入:分析器

22 篇文章 0 订阅
 

In-depth: The Parsers

深入:分析器


 

What makes Spirit tick? Now on to some details... The parser class is the most fundamental entity in the framework. A parser accepts a scanner comprised of a first-last iterator pair and returns a match object as its result. The iterators delimit the data currently being parsed. The match object evaluates to true if the parse succeeds, in which case the input is advanced accordingly. Each parser can represent a specific pattern or algorithm, or it can be a more complex parser formed as a composition of other parsers.

什么使Spirit运行?现在来看些细节……分析器类是框架中最基础的实体。分析器接受一个包含first-last分析器对的扫描器并返回一个匹配对象作为分析结果。迭代器界定了当前要分析的数据。如果分析成功则匹配对象为真,在这种情况下输入产生相应的步进。每个分析器都代表了特定的模式或者算法,或者可以作为一个更复杂的分析器的构成物。

All parsers inherit from the base template class, parser:

所有的分析器都派生自模板基类,parser:

template <typename DerivedT>
struct parser
{
/*...*/

DerivedT& derived();
DerivedT const& derived() const;
};

This class is a protocol base class for all parsers. The parser class does not really know how to parse anything but instead relies on the template parameter DerivedT to do the actual parsing. This technique is known as the "Curiously Recurring Template Pattern" in template meta-programming circles. This inheritance strategy gives us the power of polymorphism without the virtual function overhead. In essence this is a way to implement compile time polymorphism.

该类是针对所有分析器的基于协议的类。parser类并不真正知道如何分析,而是依赖于它的模板参数DerivedT来做真正的分析。这种技术在模板元编程圈子里被称为“神奇递归模板模式(Curiously Recurring Template Pattern)”。这种继承策略使我们拥有了多态的威力而不必承担虚函数的代价。本质上这是一个实现编译多态的方法。

parser_category_t

Each derived parser has a typedef parser_category_t that defines its category. By default, if one is not specified, it will inherit from the base parser class which typedefs its parser_category_t as plain_parser_category. Some template classes are provided to distinguish different types of parsers. The following categories are the most generic. More specific types may inherit from these.

每个派生的分析器都有一个名为定义其种类的typedef parser_category_t。默认情况下,如果某个分析器没有指定,它将从把parser_category_t定义为plain_parser_category的基类继承这个typedef。提供了一些模板类以区分分析器的种类。下面的种类是最粗泛的。更特定的种类将派生自这些类。

Parser categories
plain_parser_category

Your plain vanilla parser

纯分析器

binary_parser_categoryA parser that has subject a and b (e.g. alternative)
有a项和b项的分析器(比如选择分析器)
unary_parser_categoryA parser that has single subject (e.g. kleene star)
只有单项的分析器(比如克林星)
action_parser_categoryA parser with an attached semantic action
挂接了语义动作的分析器
    struct plain_parser_category {};
struct binary_parser_category : plain_parser_category {};
struct unary_parser_category : plain_parser_category {};
struct action_parser_category : unary_parser_category {};

embed_t

Each parser has a typedef embed_t. This typedef specifies how a parser is embedded in a composite. By default, if one is not specified, the parser will be embedded by value. That is, a copy of the parser is placed as a member variable of the composite. Most parsers are embedded by value. In certain situations however, this is not desirable or possible. One particular example is the rule. The rule, unlike other parsers is embedded by reference.

每个分析器都有一个typedef embed_t。这个typedef指定了分析器是如何被嵌入合成物的。默认情况下,如果某个分析器未指定的话,它将以值内嵌。然而在特定的情况下,这可能不是我们想要的或者是不可能的。特定的例子就是rule。规则,与其他分析器不同,是以引用内嵌。

The match

匹配

The match holds the result of a parser. A match object evaluates to true when a succesful match is found, otherwise false. The length of the match is the number of characters (or tokens) that is successfully matched. This can be queried through its length() member function. A negative value means that the match is unsucessful.

匹配持有分析器的分析结果。一个匹配对象的值在产生成功匹配时为true,否则为false。匹配的长度即被成功匹配的字符(记号)的长度。这可以用成员函数length()获得。负数意味着匹配失败。

Each parser may have an associated attribute. This attribute is also returned back to the client on a successful parse through the match object. We can get this attribute via the match's value() member function. Be warned though that the match's attribute may be invalid, in which case, getting the attribute will result in an exception. The member function has_valid_attribute() can be queried to know if it is safe to get the match's attribute. The attribute may be set anytime through the member function value(v)where v is the new attribute value.

所有分析器都有一个相关联的属性。这个属性在成功分析后也会通过匹配对象返回给客户程序。我们可以通过匹配对象的value()成员函数获得这个属性。注意匹配的属性有可能无效,在这种情况下,试图取得这个属性将导致一个异常。has_valid_attribute()成员函数可以用来探知是否可以安全地取得匹配的属性。可以在任意时间通过value(v)成员函数给匹配的属性设定新的属性值。

A match attribute is valid:

一个匹配属性是有效的:

  • on a successful match
  • 在成功匹配时
  • when its value is set through the value(val) member function
  • 当它的值通过value(val)成员函数设置时
  • if it is assigned or copied from a compatible match object (e.g. match<double> from match<int>) with a valid attribute. A match object A is compatible with another match object B if the attribute type of A can be assigned from the attribute type of B (i.e. a = b; must compile).
  • 如果它是一个兼容的带有有效属性的匹配对象(比如从match<int>到match<float>)的赋值或者拷贝时。一个匹配对象A与另一个匹配对象B是兼容的如果A的属性可以被从B的属性赋值(比如a=b必须兼容)。

The match attribute is undefined:

匹配属性为未定义的:

  • on an unsuccessful match
  • 当没有成功匹配时 
  • when an attempt to copy or assign from another match object with an incompatible attribute type (e.g. match<std::string> from match<int>).
  • 当试图从不兼容的另外的匹配对象拷贝或赋值匹配属性时(比如从match<int>到match<string>) 

The match class:

match类:

    template <typename T>
class match
{
public:

/*...*/

typedef T attr_t;
operator safe_bool() const; // convertible to a bool int length() const;
bool has_valid_attribute() const; void value(T const&) const;
T const& value();
};

match_result

It has been mentioned repeatedly that the parser returns a match object as its result. This is a simplification. Actually, for the sake of genericity, parsers are really not hard-coded to return a match object. More accurately, a parser returns an object that adheres to a conceptual interface, of which the match is an example. Nevertheless, we shall call the result type of a parser a match object regardless if it is actually a match class, a derivative or a totally unrelated type.

前面反复提到过分析器返回一个匹配对象作为结果。这只是简略的说法。事实上,为了通用性,并不要求分析器一定要返回匹配对象。更准确的说,分析器返回的是与某个概念接口一致的对象,而匹配只是一个例子。不过,不管实际类型是什么,我们都把分析器的结果的类型称为匹配对象。

Meta-functions

元函数

What are meta-functions? We all know how functions look like. In simplest terms, a function accepts some arguments and returns a result. Here is the function we all love so much:


什么是元函数?我们都知道函数长什么样。用最简单的话说,一个函数接受某些参数并返回一个结果。这里是我们亲爱的函数:

int identity_func(int arg)
{ return arg; } // return the argument arg

Meta-functions are essentially the same. These beasts also accept arguments and return a result. However, while functions work at runtime on values, meta-functions work at compile time on types (or constants, but we shall deal only with types). The meta-function is a template class (or struct). The template parameters are the arguments to the meta-function and a typedef within the class is the meta-function's return type. Here is the corresponding meta-function:

元函数本质上是一样的。这些怪兽同样接受参数并返回结果。然而,函数在运行时针对值工作,而元函数在编译期针对类工作(或者常数,但我们只和类型打交道)。元函数是一个模板类(或者结构)。模板参数即为元函数的参数而模板类内的一个typdef则为元函数的返回类型。这里是对应的元函数:

template <typename ArgT>
struct identity_meta_func
{ typedef ArgT type; } // return the argument ArgT

The meta-function above is invoked as:

上面的元函数这么被激活:

typename identity_meta_func<ArgT>::type

By convention, meta-functions return the result through the typedef type. Take note that typename is only required within templates.

按照习惯,元函数通过typedef type返回结果。注意typename 只有在模板中才是必须的。

The actual match type used by the parser depends on two types: the parser's attribute type and the scanner type. match_result is the meta-function that returns the desired match type given an attribute type and a scanner type.
分析器所使用的实际的匹配类型取决于两个类:分析器的属性类型和扫描器的类型。match_result是一个被给予一个属性类和扫描器类并返回所希望的匹配类型的元函数。

Usage:
使用:

    typename match_result<ScannerT, T>::type

The meta-function basically answers the question "given a scanner type ScannerT and an attribute type T, what is the desired match type?" [ typename is only required within templates ].

这个元函数基本上回答了“给定一个分析器类ScannerT和一个属性类T,所期望的匹配类型为何”这个问题。[ typename 只在模板中才是必须的 ]。

The parse member function

parse成员函数

Concrete sub-classes inheriting from parser must have a corresponding member function parse(...) compatible with the conceptual Interface:

从parser派生的实际子类必须相应地有与概念接口一致的parse(...)成员函数:

    template <typename ScannerT>
RT
parse(ScannerT const& scan) const;

where RT is the desired return type of the parser.

这里RT是分析器所要返回的类型。

The parser result

分析器结果

Concrete sub-classes inheriting from parser in most cases need to have a nested meta-function result that returns the result type of the parser's parse member function, given a scanner type. The meta-function has the form:

从parse派生的实际子类在大多数情况下需要一个嵌套的元函数result ,给定一个分析器类,它将返回分析器parse成员函数的结果类型。该元函数有如下形式:

    template <typename ScannerT>
struct result
{
typedef RT type;
};

where RT is the desired return type of the parser. This is usually, but not always, dependent on the template parameter ScannerT. For example, given an attribute type int, we can use the match_result metafunction:

这里RT是分析器要返回的类型。通常是这样的,但并非总是如此,这取决与模板参数ScannerT。举例来说,给定属性类 int,我们可以使用match_result元函数:

    template <typename ScannerT>
struct result
{
typedef typename match_result<ScannerT, int>::type type;
};

If a parser does not supply a result metafunction, a default is provided by the base parser class. The default is declared as:

如果一个分析器没有提供result元函数,则由parser基类提供一个默认的。默认元函数声明如下:

    template <typename ScannerT>
struct result
{
typedef typename match_result<ScannerT, nil_t>::type type;
};

Without a result metafunction, notice that the parser's default attribute is nil_t (i.e. the parser has no attribute).

除去了result成员函数后,注意到分析器的默认属性为int_t(比如分析器没有属性)。

parser_result

Given a a scanner type ScannerT and a parser type ParserT, what will be the actual result of the parser? The answer to this question is provided to by the parser_result meta-function.

给定一个扫描器类ScannerT和一个分析器类ParserT,分析器的真正结果类型为何?这个问题的答案有parser_result元函数提供。

Usage:

使用:

    typename parser_result<ParserT, ScannerT>::type

In general, the meta-function just forwards the invocation to the parser's result meta-function:

同样,这个成员函数通过与分析器的result元函数一致的方式被激活:

    template <typename ParserT, typename ScannerT>
struct parser_result
{
typedef typename ParserT::template result<ScannerT>::type type;
};

This is similar to a global function calling a member function. Most of the time, the usage above is equivalent to:

这和通过全局函数调用成员函数类似。大多数时候,上面的使用等同于:

    typename ParserT::template result<ScannerT>::type

Yet, this should not be relied upon to be true all the time because the parser_result metafunction might be specialized for specific parser and/or scanner types.

但是,并不是在所有的情况下都是如此,因为parse_result元函数有可能针对特定的分析器和/或特定的扫描器而特化。

The parser_result metafunction makes the signature of the required parse member function almost canonical:

parse_result元函数使得其所需要的parse成员函数的签名总是规范的:

    template <typename ScannerT>
typename parser_result<self_t, ScannerT>::type
parse(ScannerT const& scan) const;

where self_t is a typedef to the parser.

这里self_t是对分析器的一个typedef。

parser class declaration

parser类声明

    template <typename DerivedT>
struct parser
{
typedef DerivedT embed_t;
typedef DerivedT derived_t;
typedef plain_parser_category parser_category_t;

template <typename ScannerT>
struct result
{
typedef typename match_result<ScannerT, nil_t>::type type;
};

DerivedT& derived();
DerivedT const& derived() const;

template <typename ActionT>
action<DerivedT, ActionT>
operator[](ActionT const& actor) const;
};
 


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值