Learning Spirit 2Phase level vs. character levelparse函数有4种形式的重载。
template <typename IteratorT, typename DerivedT>
parse_info<IteratorT>
parse
(
IteratorT const& first,
IteratorT const& last,
parser<DerivedT> const& p
);
template <typename CharT, typename DerivedT>
parse_info<CharT const*>
parse
(
CharT const* str,
parser<DerivedT> const& p
);
以上两种是字符层次的parse。
template <typename IteratorT, typename ParserT, typename SkipT>
parse_info<IteratorT>
parse
(
IteratorT const& first,
IteratorT const& last,
parser<ParserT> const& p,
parser<SkipT> const& skip
);
template <typename CharT, typename ParserT, typename SkipT>
parse_info<CharT const*>
parse
(
CharT const* str,
parser<ParserT> const& p,
parser<SkipT> const& skip
);
以上是短语层次的parse。
短语层次使用一个skip parser参数来过滤输入中的“空白”符号(这里空白的意思由skip参数决定,可以是空格、回车、甚至是“/*...*/”这样的c语言注释)。而字符层次则严格的分析每一个字符。
例如:
parse(“a 123”,ch_p(‘a’)>>int_p,space_p)==true;//phase level
parse(“a123”,ch_p(‘a’)>>int_p)==true;//character level
parse(“a 123”,ch_p(‘a’)>>int_p)==false;
Semantic Action语义动作是指在分析的过程中执行的动作。每个parser可以附带一个或多个语义动作,当这个parser匹配了一段输入后,就会调用这个动作。
语义动作可以是一个函数:
template<typename Iterator>
void func(Iterator first, Iterator last);
也可以是仿函数:
struct myfunctor
{
template<typename Iterator>
void operator()(Iterator first, Iterator last) const;
}
注意()重载的const不能去掉。
可以这样使用:
rule<> r = (a>>b)[&func];
rule<> s= (a[myfunctor()] | b[&func])[&func];
特殊的语义动作:
对于一些特殊的parser,例如:int_p,ch_p。除了可以使用上述的语义动作外,还提供了与其类型有关的语义动作。
对于int_p:void func(int val); 对于ch_p:void func(char c)。
那么,现在我们就可以完成我们上一篇教程的题目了。
#include<iostream>
#include<string>
#include<boost/spirit.hpp>//spirit的头文件
using namespace std;
using namespace boost::spirit;
struct Assign
{
int & var;
Assign(int & v):var(v){}
void operator()(int val) const
{
var=val;
}
};
struct Increase
{
int & var;
Increase(int & v):var(v){}
void operator()(int val) const
{
var+=val;
}
};
int main()
{
int count;
rule<phrase_scanner_t> s
=int_p[Assign(count)]
>> *( ch_p(',')
>>int_p[Increase(count)]);
string str;
while(getline(cin,str))
{
parse_info<> info = parse(str.c_str(),s,space_p);
if (info.full)
{
cout<<"Parse successful."<<endl;
cout<<"Result is "<<count<<endl;
}
else
{
cout<<"Parse fail."<<endl;
}
}
return 0;
}