Learning Spirit 2
Phase level vs. character level
parse函數有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(“a 123” ,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;
}