2 scanner
2.1 scanner classes structure
scanner类是一个符号流扫描器,提供对输入符号流的读取,迭代,是否末尾的判断。
scanner提供的方法:
operator* (读取当前符号)
operator++ (移动到下一个符号)
at_end (是否到了当前符号流的末尾?)
scanner本身并不实现这些方法,而是将其委托给策略类来实现。策略类作为一个被继承的模板参数。
scanner的成员:
IteratorT first (迭代指示器:指向符号流的当前符号位置)
IteratorT end (迭代指示器:指向符号流的最末位置)
scanner模板类包含两个参数:
IteratorT:输入符号流的迭代器类型,默认为char const*,输入为字符串。
PoliciesT:策略类,scanner类从此类继承。
2.2 scanner_policies
scanner 策略类:scanner功能具体实现类;策略被横切为三种:迭代策略(iteration_policy),匹配策略(match_policy)和动作策略(action_policy)。
2.2.1 迭代策略(iteration_policy)
scanner所提供的最主要功能,符号流的读取和迭代,都由此类完成。
方法实现概述:
at_end(scanner):判断是否到了符号流末尾;通过比较scanner的两个迭代指示器成员first和end是否相等。
advance(scanner):到符号流的下一个位置;++scanner.first。
get(scanner):取当前符号;*scanner.first。
filter(T):过滤当前符号;实际上,scanner::operator*()方法就是调用iteration_policy::filter(iteration_policy::get(scanner));将get()方法得到的符号经过filter的过滤,这个方法的作用用于改变符号,比如想把输入的字符串全部改为大写再进行解析,就可以从iteration_policy类派生一个子类,重写filter方法,将字符to_upper就可以了。
2.2.1.1 upper_iteration_policy
upper_iteration_policy是一个自定义的迭代策略类,用于示范filter的用法。
// 模板类upper_iteration_policy,是为了把符号流中的所有字符都转为大写字符
// 这个类继承自BaseT (默认为iteration_policy),只改写filter方法,其他方法仍维持原语义。
template <typename BaseT = iteration_policy>
struct upper_iteration_policy : public BaseT
{
typedef BaseT base_t;
upper_iteration_policy() : BaseT() {}
//因为scanner_policies的copy ctor是调用各个基类的copy ctor,包括iteration_policy的;如果要用upper_iteration_policy代替默认的iteration_policy,那么需要提供一个copy ctor。以便有人在写下scanner_policies< upper_iteration_policy, …> policy(scanner)时候不会出错。
template <typename PolicyT>
upper_iteration_policy(PolicyT const& other) : BaseT(other) {}
// 提供一个filter方法,将所有读取出来的字符转为大写。
template <typename T>
T filter(T ch) const
{
printf("run this char:%c, and filter to:%c/n", ch, toupper(ch));
return toupper(ch);
}
};
template <typename DerivedT, typename ScannerT>
bool upper_parse(parser<DerivedT> const& p, ScannerT const & scan)
{
// 替换scanner_policies的默认迭代策略类为自定义的upper_iteration_policy
typedef scanner_policies<
upper_iteration_policy<
BOOST_DEDUCED_TYPENAME ScannerT::iteration_policy_t>,
BOOST_DEDUCED_TYPENAME ScannerT::match_policy_t,
BOOST_DEDUCED_TYPENAME ScannerT::action_policy_t
> policies_t;
/* 这是构造scanner的第一种方法,直接调用scanner的构造方法,注意这里的policies对象是通过scanner 对象构造的,实际上这是不必要的。
scanner<BOOST_DEDUCED_TYPENAME ScannerT::iterator_t, policies_t>
scan2(scan.first, scan.last, policies_t(scan));
*/
// 或者无须重新构造一个新的scanner对象,直接在默认的scanner对象上调用change_policies方法,给他一个新的policies(前面替换的自定义policies)。实际上第2种方法使用比较广泛。
match<nil_t> hit = p.derived().parse(scan.change_policies(policies_t()));
cout << "hit:" << hit << endl;
cout << "length:" << hit.length() << endl;
return hit;
}
bool test_upper_parse(const char* str)
{
char const* last = str;
while (*last) last++;
scanner<char const*, scanner_policies<> > scan(str, last);
return upper_parse(str_p("HEEL"), scan);
}
2.2.1.2 skipper_iteration_policy
skipper_iteration_policy :跳过空格的迭代策略(系统提供)
这个策略重写了iteration_policy的大部分方法,包括advance,at_end。
方法实现概述:
skip:跳过所有空格,一直到符号流末尾。
advance:调用基类的advance,然后skip。
at_end:先skip,然后调用基类的at_end判断是否到了末尾。
2.2.1.3 skip_parser_iteration_policy
与skipper_iteration_policy策略类一样,也是跳过某些符号,只不过这些需要跳过的符号是由一个parser来解析的。
这个模板类有两个参数:ParserT,跳过字符的解析类;BaseT,继承基类。
该类继承自skipper_iteration_policy类,是为了继承其advance和at_end方法。
值得注意的是该类重写了基类的skip方法。这个方法是要来识别要跳过的字符。该方法调用skipper_skip(ParserT, scanner, scanner),该方法有三个重载,通过最后一个参数来区别实际的scanner类型;如果原来的scanner类中的迭代策略就是一个skipper_iteration_policy,那么这个函数需要把原来scanner中的skipper_iteration_policy去掉。
2.2.2 match_policy
匹配策略类,用来创建解析的结果类。
这个类首先要提供一个模板类result,用来推演parser的解析结果类。从meta function [1.2.3match_result]中得知,该函数需要一个MatchPolicyT参数,一般来说,该参数传入ScannerT,也就是match_policy(因为ScannerT从match_policy派生而来)。这样,根据match_result的结果,应该为match_policy::template result<T>。
方法概述:
no_match:错误match对象match<nil_t>()
empty_match:空的match对象match<nil_t>(0, nil_t())
create_match:创建一个match对象
group_match:未实现
concat_match:连接两个match对象
2.2.3 action_policy
动作策略类,这个类是为action对象提供的。