摘要:
1。符號(hào)查找(對(duì)于函數(shù)此時(shí)只看名字,不看參數(shù)) 大致順序是 (1)如果有限定名( XXX:: )那么就直接在XXX里查找 (2)函數(shù)局部名字空間 (3)(如果是成員)類名字空間 (4)遞歸向上至所有基類的...
閱讀全文
posted @
2006-12-27 11:04 shifan3 閱讀(2119) |
評(píng)論 (8) |
編輯 收藏
發(fā)信人: shifan (學(xué)習(xí)浮云技術(shù)), 板面: C++
標(biāo) 題: 偽typeof
發(fā)信站: 飄渺水云間 (Tue Dec 19 16:38:45 2006), 轉(zhuǎn)信
1 /*
2 用標(biāo)準(zhǔn)C++實(shí)現(xiàn)typeof是不可能的
3 這個(gè)是我寫的一個(gè)approached typeof
4 所有需要被靜態(tài)反射出來(lái)的類型必須先用DECL_TYPE注冊(cè)
5 模板如果僅僅帶有1個(gè)參數(shù)可以用DECL_TEMPLATE_1注冊(cè)
6 多個(gè)參數(shù)的模板還不支持。。
7 主要是沒想好編碼
8
9 總共能注冊(cè)64個(gè)類型
10 可以通過(guò)MAX_TYPE_NUMBER設(shè)置
11
12 支持的模板嵌套層數(shù)大約為32 / log2(MAX_TYPE_NUMBER)
13 MAX_TYPE_NUMBER必須為2的整次數(shù)冪
14 */
15 namespace my_typeof
16 {
17
18 const int MAX_TYPE_NUMBER = 64;
19
20 template <int N>
21 struct dummy
22 {
23 int a[N];
24 };
25
26
27 template <int N, typename Arg1>
28 struct select_by_number_1;
29
30 template <int N>
31 struct select_by_number
32 {
33 typedef typename select_by_number_1<N % MAX_TYPE_NUMBER, typename
34 select_by_number<N / MAX_TYPE_NUMBER>::type>::type type;
35 };
36
37
38 template <typename T>
39 struct number_of
40 {
41 static const int v = sizeof(generic_f(*(T*)0)) / sizeof(int);
42 };
43
44
45 #define DECL_TYPE(T, N) \
46 namespace my_typeof{ \
47 template<>\
48 struct select_by_number<N> \
49 {\
50 typedef T type;\
51 };\
52 dummy <N> generic_f(const T&);}
53
54
55 #define DECL_TEMPLATE_1(T, N) \
56 namespace my_typeof{ \
57 template<typename Arg1>\
58 struct select_by_number_1<N, Arg1>\
59 {\
60 typedef T<Arg1> type;\
61 };\
62 template <typename Arg1>\
63 dummy<N + number_of<Arg1>::v * MAX_TYPE_NUMBER > generic_f(const T<Arg1>&);}
64
65
66
67 #define TYPE_OF(x) my_typeof::select_by_number<sizeof(my_typeof::generic_f(x)) /
68 sizeof (int)>::type
69
70 }
71
72
73 //sample
74 #include <iostream>
75 #include <vector>
76 #include <list>
77
78
79 DECL_TYPE(int, 1);
80 DECL_TEMPLATE_1(std::vector, 2);
81 DECL_TEMPLATE_1(std::list, 3);
82 DECL_TYPE(double, 4)
83
84 using namespace std;
85 int main(int, char*[])
86 {
87 vector<list<vector<list<double> > > > v1;
88 TYPE_OF(v1) v2;
89 v1 = v2;
90 return 0;
91 }
92
93
--
You well 撒法!You well all 撒法!
※ 內(nèi)容修改:·shifan 于 Dec 21 14:21:57 修改本文內(nèi)容·[FROM: shifan]
※ 來(lái)源:·飄渺水云間 freecity.cn·[FROM: shifan]
posted @
2006-12-21 14:29 shifan3 閱讀(2646) |
評(píng)論 (8) |
編輯 收藏
真令人傷感,每過(guò)幾年就是離別時(shí)。
我站在窗前,無(wú)奈的看著朋友們?yōu)榱斯ぷ鞅甲撸?br />而不能幫上哪怕一點(diǎn)忙。
就像十年前,就像六年前,就像三年前
就像每一次與人擦肩而過(guò)卻故意目不斜視。
但這一次也許好一點(diǎn),畢竟我們以后可能還能時(shí)常相聚,
而不像現(xiàn)在只能看著從前的好友的博客獨(dú)自傷感。
那種陌生,令人心碎。
?
posted @
2006-11-01 00:31 shifan3 閱讀(595) |
評(píng)論 (4) |
編輯 收藏
boost的integer/integer_mask.hpp僅僅做了單個(gè)位的bit mask
要多個(gè)位必須寫很多遍high_bit_mask_t
使用low_bits_mask_t也不能完全解決問(wèn)題
所以自己用Typelist的那種寫法寫了一個(gè)
用法舉例
bit_mask<INT_LIST_2(2, 3)>::value返回一個(gè)值,該值的第2、3位被置為1
其余位為0
1
2 namespace multi_bit_mask
3 {
4 namespace details
5 {
6
7 template <typename T>
8 struct get_size
9 {
10 enum {size = sizeof(T)};
11 };
12
13 template <int Bit>
14 struct bit_storage
15 {
16 typedef typename bit_storage<Bit - 1>::storage_type storage_type;
17 };
18
19 //---------platform dependency-----------------------
20
21 typedef unsigned int smallest_storage_type;
22 typedef unsigned long long largest_storage_type;
23
24
25
26 template <>
27 struct bit_storage<0>
28 {
29 typedef smallest_storage_type storage_type;
30 };
31
32 template <>
33 struct bit_storage<get_size<smallest_storage_type>::size * 8>
34 {
35 typedef largest_storage_type storage_type;
36 };
37
38 //disable the 65th bit
39 template <>
40 struct bit_storage<get_size<largest_storage_type>::size * 8>
41 {
42 typedef void storage_type;
43 };
44
45 //---------end of platform dependency----------------
46
47
48 template <unsigned int N, typename Next>
49 struct int_list
50 {
51 typedef typename bit_storage<N>::storage_type storage_type;
52 static const storage_type value = N;
53 typedef Next next;
54 };
55
56 struct null_type{};
57
58 template<typename T1, typename T2, bool is_first>
59 struct selector
60 {
61 typedef T1 type;
62 };
63
64 template<typename T1, typename T2>
65 struct compare_type
66 {
67 const static bool is_larger = sizeof(T1) > sizeof(T2);
68 typedef typename selector<T1, T2, is_larger>::type large_type;
69 typedef typename selector<T1, T2, !is_larger>::type small_type;
70 };
71
72
73
74 template<typename T1, typename T2>
75 struct selector<T1, T2, false>
76 {
77 typedef T2 type;
78 };
79
80 template <typename List>
81 class find_largest_storage
82 {
83 typedef typename find_largest_storage<typename List::next>::storage_type T1;
84 typedef typename bit_storage<List::value>::storage_type T2;
85 public:
86 typedef typename compare_type<T1, T2>::large_type storage_type;
87 };
88
89 template <>
90 class find_largest_storage<null_type>
91 {
92 public:
93 typedef smallest_storage_type storage_type;
94 };
95
96
97 }
98
99
100
101
102
103 template <int N>
104 struct single_bit_mask
105 {
106 typedef typename details::bit_storage<N>::storage_type storage_type;
107 static const storage_type value
108 = static_cast<storage_type>(single_bit_mask<N - 1>::value) * 2;
109 };
110
111 template <>
112 struct single_bit_mask<0>
113 {
114 typedef details::bit_storage<0>::storage_type storage_type;
115 static const storage_type value = 1;
116 };
117
118
119 typedef details::null_type null_type;
120
121 template <int N, typename Next>
122 struct int_list_t : public details::int_list<N, Next> {};
123
124 template <typename List>
125 struct bit_mask
126 {
127 public:
128
129 typedef typename details::find_largest_storage<List>::storage_type storage_type;
130
131 static const storage_type value
132 = static_cast<storage_type>(single_bit_mask<List::value>::value)
133 | static_cast<storage_type>(bit_mask<typename List::next>::value);
134 };
135
136 template <>
137 struct bit_mask<null_type>
138 {
139 typedef details::bit_storage<0>::storage_type storage_type;
140 static const storage_type value = 0;
141 };
142
143
144
145
146
147 #define INT_LIST_1(n1) multi_bit_mask::int_list_t<n1, multi_bit_mask::null_type>
148 #define INT_LIST_2(n1, n2) multi_bit_mask::int_list_t<n1, INT_LIST_1(n2) >
149 #define INT_LIST_3(n1, n2, n3) multi_bit_mask::int_list_t<n1, INT_LIST_2(n2, n3) >
150 #define INT_LIST_4(n1, n2, n3, n4) multi_bit_mask::int_list_t<n1, INT_LIST_3(n2, n3, n4) >
151 #define INT_LIST_5(n1, n2, n3, n4, n5) multi_bit_mask::int_list_t<n1, INT_LIST_4(n2, n3, n4, n5) >
152 #define INT_LIST_6(n1, n2, n3, n4, n5, n6) multi_bit_mask::int_list_t<n1, INT_LIST_5(n2, n3, n4, n5, n6) >
153 #define INT_LIST_7(n1, n2, n3, n4, n5, n6, n7) multi_bit_mask::int_list_t<n1, INT_LIST_6(n2, n3, n4, n5, n6, n7) >
154 #define INT_LIST_8(n1, n2, n3, n4, n5, n6, n7, n8) multi_bit_mask::int_list_t<n1, INT_LIST_7(n2, n3, n4, n5, n6, n7, n8) >
155
156 }
157
158
159
sample
#include < iostream >
#include " multi_bit_mask.h "
using namespace std;
int main()

{
cout << multi_bit_mask::bit_mask < INT_LIST_1( 1 ) > ::value << endl;
cout << multi_bit_mask::bit_mask < INT_LIST_5( 0 , 1 , 2 , 3 , 4 ) > ::value << endl;
cout << multi_bit_mask::bit_mask < INT_LIST_7( 0 , 1 , 2 , 3 , 4 , 4 , 2 ) > ::value << endl;
posted @
2006-10-26 23:37 shifan3 閱讀(1453) |
評(píng)論 (2) |
編輯 收藏
近日在學(xué)校bbs上與人討論C++的typeid關(guān)鍵字的實(shí)現(xiàn)問(wèn)題,有人提到type_info的地址是存放在虛表的第一個(gè)位置上,頗覺得不妥,于是我在vc2003下實(shí)驗(yàn)了一番
在vc下,使用typeid的時(shí)候,如果typeid施加給的類型是沒有vptr的class或者根本不是class
那么匯編是
mov dword ptr [addr],offset A `RTTI Type Descriptor' (42AD40h)
也就是編譯器生成一個(gè)簡(jiǎn)單的type_info對(duì)象的表,并且在編譯期靜態(tài)決定下標(biāo),做一個(gè)簡(jiǎn)單查表操作。
如果typeid的操作對(duì)象是具有vptr的class,但是并不是一個(gè)引用或者指針的解引用形式,例如
A a;
typeid(a);
那么仍然僅僅會(huì)做查表操作
如果typeid的操作對(duì)象是具有vptr的class,并且是引用或者指針的解引用形式,例如
A * p = new A;
A & r = * p;
typeid( * p);
typeid(r);
那么就會(huì)調(diào)用一個(gè)叫___RTtypeid的函數(shù),并通過(guò)某種方法來(lái)獲取type_info對(duì)象
下面是___RTtypeid的反匯編,這里只列出關(guān)鍵的幾條指令
0041213E mov ecx,dword ptr [inptr] ;inptr是對(duì)象的地址
00412141 mov edx,dword ptr [ecx]
00412143 mov eax,dword ptr [edx - 4 ]
0041215F mov ecx,dword ptr [eax + 0Ch]
00412162 mov dword ptr [ebp - 48h],ecx
0041216C mov eax,dword ptr [ebp - 48h]
基本上等價(jià)于C語(yǔ)言的
int a1 = ( int )p; // p是對(duì)象的地址
int a2 = * ( int * )a1 - 4 ;
int a3 = * ( int * )a2 + 12 ;
int a4 = * ( int * )a3;
那么從這段代碼可以看出vc下type_info對(duì)象的存放位置[如下圖]
也就虛表下標(biāo)為-1的位置上存放了一個(gè)指向一個(gè)未知的表的指針(暫且將此表命名為runtime_info_table)
runtime_info_table的第4格上存放了type_info對(duì)象的地址
至于runtime_info_table里前3格上存放的是什么, 還需要再研究研究
一般來(lái)說(shuō)它們?nèi)?, 但是對(duì)于多重虛繼承的類, 第二格上會(huì)是4, 可能和指針的偏移量有關(guān).
posted @
2006-10-26 10:46 shifan3 閱讀(3350) |
評(píng)論 (5) |
編輯 收藏
Xpressive是一個(gè)C++的正則表達(dá)式庫(kù),目前是Boost的候選庫(kù)。
Xpressive和Boost.Regex的區(qū)別很大。首先,Xpressive是一個(gè)純頭文件的庫(kù),也是說(shuō),在使用之前不需要預(yù)先編譯。其次,Xpressive支持類似于Spirit的靜態(tài)語(yǔ)義定義。
我們先來(lái)看一個(gè)例子:
#include <iostream>
#include <boost/xpressive/xpressive.hpp>
using namespace boost::xpressive;
int main()
{
std::string hello( "hello world!" );
sregex rex = sregex::compile( "(\\w+) (\\w+)!" );
smatch what;
if( regex_match( hello, what, rex ) )
{
std::cout << what[0] << '\n'; // whole match
std::cout << what[1] << '\n'; // first capture
std::cout << what[2] << '\n'; // second capture
}
return 0;
}
這是使用Xpressive動(dòng)態(tài)語(yǔ)義定義的例子,其中sregex::compile函數(shù)編譯一個(gè)表示正則文法的串,并返回一個(gè)正則對(duì)象sregex
使用regex_match來(lái)使用這個(gè)正則對(duì)象匹配一個(gè)串。結(jié)果儲(chǔ)存在what內(nèi)
其中what[0]返回整個(gè)串,what[1]~what[n]返回文法中用于標(biāo)記的部分(用小括號(hào)括起來(lái)的部分)
最后將輸出
hello world!
hello
world
如果想在一個(gè)串中查找符合該文法的子串,可以使用regex_search,用法和regex_match一樣,此外還可以用regex_replace來(lái)進(jìn)行替換。
靜態(tài)文法:
Xpressive除了可以用compile來(lái)分析一個(gè)文法串之外,還可以用類似于Spirit的方式來(lái)靜態(tài)的指定文法:
sregex re = '$' >> +_d >> '.' >> _d >> _d;
這將定義一個(gè)表示金額的串,其中_d表示一個(gè)數(shù)字,相當(dāng)于串 $\d+.\d\d
這樣定義文法將比之前的動(dòng)態(tài)定義更加高效,并且還有一個(gè)附加的好處:
分級(jí)定義:
sregex re = '$' >> +_d >> '.' >> _d >> _d;
sregex s = '(' >> re >> ')';
這樣s表示為用括號(hào)括起來(lái)的re
通過(guò)分級(jí)定義,文法能被表示的更加清楚。
更加棒的是,分級(jí)定義還可以向后引用,因此能夠分析EBNF
sregex group, factor, term, expression;
group = '(' >> by_ref(expression) >> ')';
factor = +_d | group;
term = factor >> *(('*' >> factor) | ('/' >> factor));
expression = term >> *(('+' >> term) | ('-' >> term));
expression定義了一個(gè)四則表達(dá)式,注意其中g(shù)roup的定義。
這里必須使用by_ref是因?yàn)閄pressive默認(rèn)是值拷貝,如果這里使用默認(rèn)的方式,那么會(huì)造成一個(gè)無(wú)限循環(huán)。
Xpressive可以在這里下載
http://boost-consulting.com/vault/index.php?PHPSESSID=f1d4af8b742cfa7adae7aab373cfc535&direction=0&order=&directory=Strings%20-%20Text%20Processing&PHPSESSID=f1d4af8b742cfa7adae7aab373cfc535
內(nèi)有詳細(xì)的文檔
posted @
2006-07-27 16:27 shifan3 閱讀(3116) |
評(píng)論 (4) |
編輯 收藏
看了546@C++@Freecity之后,發(fā)覺非常有意思,由此產(chǎn)生一些想法
很多時(shí)候?qū)懸粋€(gè)類的時(shí)候,需要多個(gè)模版參數(shù),例如一個(gè)遺傳算法的算法類,需要一個(gè)模版參數(shù)來(lái)指定交配方式,另一個(gè)模版參數(shù)來(lái)指定子代選擇的方式,還要一個(gè)參數(shù)來(lái)指定變異的方式。那么一般來(lái)說(shuō),這個(gè)類會(huì)寫成:
template<class T //描述問(wèn)題的一個(gè)類
, class CrossPolicy = AvgCrossPolicy //雜交方式
, class SelectPolicy = DefaultSelectPolicy //子代選擇的方式
, class VariationPolicy = ReverseVariationPolicy> //變異方式
class Gene
: private AvgCrossPolicy
, private SelectPolicy
, private VariationPolicy
{
....
};
這樣用戶要使用該類的時(shí)候,可以直接指定T,就行了,然而如果要指定變異方式,那么就必須把所有的參數(shù)都顯式的寫出來(lái),很不方便
546提供了一種有效的方法,可以讓我們僅僅指定變異參數(shù),而不用寫出另兩個(gè)Policy
甚至允許我們以任意的順序書寫幾個(gè)Policy參數(shù),都不會(huì)有問(wèn)題
預(yù)備知識(shí):
TypeList
一個(gè)TypeList是一個(gè)類型的容器
template <typename Type_, typename Next_>
struct TypeList
{
typedef Type_ Type;
typedef Next_ Next;
};
這就是一個(gè)TypeList。
看這個(gè)寫法,是不是像一個(gè)鏈表?
首先定義一個(gè)類型來(lái)表示鏈表尾:class NullType{};
現(xiàn)在一個(gè)包含了2個(gè)類型的TypeList就可以寫為:
TypeList<T1, TypeList<T2, NullType> >
如何在一個(gè)TypeList中查找一個(gè)類型的子類?
首先要有一個(gè)IsDerivedFrom<Base, T>
這個(gè)比較簡(jiǎn)單
template<class Base, class T>
class IsDerivedFrom
{
struct large{char a[2];};
static char pred(Base*);
static large pred(...);
public:
enum {Is = sizeof(pred((T*)0)) == sizeof(char)};
};
然后FindChild就容易了
template <class List, class Base>
struct FindChild
{
template <bool IsChild>
struct Select
{
typedef typename List::Type Type;
};
template <>
struct Select<false>
{
typedef typename FindChild<typename List::Next, Base>::Type Type;
};
typedef typename Select<IsDerivedFrom<Base, typename List::Type> >::Type Type;
};
當(dāng)然還要對(duì)一些特殊情況進(jìn)行特化,例如NullType
template <class Base>
struct FindChild<NullType, Base>
{
typedef NullType Type;
};
這里使用NullType來(lái)表明沒找到
實(shí)際操作:
首先需要給3個(gè)Policy3個(gè)基類,分別叫
class AvgCrossPolicyBase{};
class SelectPolicyBase{};
class VariationPolicyBase{};
內(nèi)容為空就行了,這樣也沒有虛函數(shù)調(diào)用的開銷
然后聲明一個(gè)類來(lái)表示默認(rèn)情況:
class DefaultPolicy{};
定義一個(gè)宏
#define TYPELIST_3_N(a, b, c) TypeList<a, TypeList<b, TypeList<c, NullType> > >
下面要寫一些選擇器,用于把合適的類型選擇出來(lái),如果沒找到,則要使用默認(rèn)的類型
template <class List, class Base, class DefaultType>
struct Selector
{
template <class RetType>
struct Judge
{
typedef RetType Type;
};
template<>
struct Judge<NullType>
{
typedef DefaultType Type;
};
typedef typename Judge<typename FindChild<List, Base>::Type >::Type Type;
};
好啦,現(xiàn)在整個(gè)類的聲明可以寫為
template<class T
, class CrossPolicy_ = DefaultPolicy
, class SelectPolicy_ = DefaultPolicy
, class VariationPolicy_ = DefaultPolicy //其后的參數(shù)用戶不可指定
, class List = TYPELIST_3_N(CrossPolicy_, SelectPolicy_, VariationPolicy_)
, class CrossPolicy = typename Selector<List, CrossPolicyBase, AvgCrossPolicy>::Type
, class SelectPolicy = typename Selector<List, SelectPolicyBase, DefaultSelectPolicy>::Type
, class VariationPolicy = typename Selector<List, VariationPolicyBase, ReverseVariationPolicy>::Type
>
class Gene
: private CrossPolicy
, private SelectPolicy
, private VariationPolicy
{
....
};
其中第4-7個(gè)參數(shù)(List,CrossPolicy,SelectPolicy和VariationPolicy)是不由用戶指定的,僅僅是為了起一個(gè)別名
第一個(gè)參數(shù)T必須指定,然后2,3,4這3個(gè)參數(shù)就可以任意的改變順序了
例如,可以寫Gene<T, DefaultSelectPolicy, AvgCrossPolicy>而不會(huì)有任何問(wèn)題
如果不想要最后面幾個(gè)參數(shù)的話也行,但是代碼就要稍微長(zhǎng)一點(diǎn)
而且最好在類里面進(jìn)行3個(gè)typedef
typedef typename Selector<List, CrossPolicyBase, AvgCrossPolicy>::Type CrossPolicy;
等,以便在實(shí)現(xiàn)的時(shí)候使用
posted @
2006-07-24 01:06 shifan3 閱讀(1012) |
評(píng)論 (9) |
編輯 收藏
摘要: 發(fā)信人: shifan (家沒有豚豚 T.T), 板面: C++標(biāo) 題: 如何實(shí)現(xiàn)Lambda[第二部分]發(fā)信站: 飄渺水云間 (Thu Jun 8 23:30:20 2006), 轉(zhuǎn)信
章節(jié):八:第一部分的小結(jié)九:簡(jiǎn)化,如何減少Lambda代碼的冗余和依賴性十:bind的實(shí)現(xiàn)十一:實(shí)現(xiàn)phoenix
八. 中期總結(jié)目前的結(jié)果是這樣的...
閱讀全文
posted @
2006-07-15 15:32 shifan3 閱讀(992) |
評(píng)論 (0) |
編輯 收藏
摘要: 一. 什么是Lambda所謂Lambda,簡(jiǎn)單的說(shuō)就是快速的小函數(shù)生成。在C++中,STL的很多算法都要求使用者提供一個(gè)函數(shù)對(duì)象。例如for_each函數(shù),會(huì)要求用戶提供一個(gè)表明“行為”的函數(shù)對(duì)象。以vector<bool>為例,如果想使用for_each對(duì)其中的各元素全部賦值為true,一般需要這么一個(gè)函數(shù)對(duì)象,
c...
閱讀全文
posted @
2006-06-09 13:23 shifan3 閱讀(2993) |
評(píng)論 (7) |
編輯 收藏
最近為了解析SQL語(yǔ)法,懷著試一試的心態(tài)去翻了翻boost的spirit庫(kù),因?yàn)樵搸?kù)的文檔的簡(jiǎn)介里寫著LL parser framework represents parsers directly as EBNF grammars in inlined C++。看著framework這個(gè)詞自然覺得這個(gè)庫(kù)很牛B,試用了一下果然如此。
所謂EBNF即擴(kuò)展巴克斯范式,是一種描述Context-Free Language的文法。在目前常見的非自然語(yǔ)言中,大部分都可以用EBNF表示。例如:
group ::='('exp ')'
factor ::=integer| group
term ::=factor(('*'factor)|('/'factor ))*
exp ::=term(('+'term)|('-'term ))*
這是一個(gè)整數(shù)表達(dá)式的EBNF。該段描述用spirit在C++中的實(shí)現(xiàn)則是:
rule<> group, factor, term, exp;
group = '(' >> exp >> ')';
factor = int_p | group;
term = factor >> *(('*' >> factor) | ('/' >> factor));
exp = term >> *(('+' >> term) | ('-' >> term));
這里使用=代替::=, 用>>代替空格連接。并且由于C++語(yǔ)法所限,EBNF中后置的*在spirit中改為前置。
等式左邊的單詞被稱為一個(gè)rule,等式右邊為rule的定義。我們可以看出一個(gè)group是一個(gè)exp加上一對(duì)括號(hào),一個(gè)factor是一個(gè)整數(shù)或者一個(gè)group,一個(gè)term是一個(gè)或多個(gè)factor用*/連接,一個(gè)exp是一個(gè)或多個(gè)term用+-連接。處于最頂端的exp可以據(jù)此識(shí)別出以下表達(dá)式
12345
-12345
+12345
1 + 2
1 * 2
1/2 + 3/4
1 + 2 + 3 + 4
1 * 2 * 3 * 4
(1 + 2) * (3 + 4)
(-1 + 2) * (3 + -4)
1 + ((6 * 200) - 20) / 6
(1 + (2 + (3 + (4 + 5))))
得到一個(gè)rule之后,我們就可以用 parse函數(shù)對(duì)一個(gè)串進(jìn)行識(shí)別了。例如
parse( " (1 + (2 + (3 + (4 + 5)))) " , exp);
該函數(shù)返回一個(gè)結(jié)構(gòu)parse_info,可以通過(guò)訪問(wèn)其中的full成員來(lái)判斷是否成功識(shí)別,也可以訪問(wèn)stop成員來(lái)獲知失敗的位置。這里要特別提一點(diǎn),關(guān)于各個(gè)符號(hào)之間的空格,spirit的文檔的正文說(shuō)的是給parse再傳一個(gè)參數(shù)space_p,通知parse跳過(guò)所有的空格,然而在FAQ中又提到,如果使用以上方法定義rule,第三個(gè)參數(shù)傳space_p會(huì)失敗。原因是使用rule默認(rèn)定義的規(guī)則被稱為character level parsing,即字符級(jí)別解析,而parse的第3個(gè)參數(shù)僅適用于phrase level parsing,即語(yǔ)法級(jí)別解析。要使用第3個(gè)參數(shù)可以有幾種方法。
1。在parse的第二個(gè)參數(shù)直接傳入一個(gè)EBNF表達(dá)式,不創(chuàng)建rule對(duì)象。
parse( " hello world " , * anychar_p, space_p);
2。以rule<phrase_scanner_t>創(chuàng)建rule。
rule < phrase_scanner_t > exp;
注意雖然可以用這兩個(gè)辦法屏蔽空格,但是這樣可能完全改變EBNF文法的語(yǔ)義,尤其是在語(yǔ)言本身需要識(shí)別空格的時(shí)候。對(duì)于這種情況,可以不使用第三個(gè)參數(shù),并在需要出現(xiàn)空格的地方加上space_p,或者+space_p及*space_p,其中+和*分別表示后面的符號(hào)連續(xù)出現(xiàn)一次以上和0次以上。例如一個(gè)以空格分隔的整數(shù)列表可以寫成int_p >> *(+space_p >> int_p)
如上使用parse可以識(shí)別一個(gè)串,但并不能做更多的操作,例如將語(yǔ)法里的各個(gè)成分提取出來(lái)。對(duì)于這樣的需求,可以通過(guò)actor實(shí)現(xiàn)。下面是使用actor的一個(gè)簡(jiǎn)單例子
bool
parse_numbers(char const* str, vector<double>& v)

{
return parse(str,

// Begin grammar
(
real_p[push_back_a(v)] >> *(',' >> real_p[push_back_a(v)])
)
,
// End grammar
space_p).full;
}
注意到real_p后面的[],中括號(hào)里面是一個(gè)仿函數(shù)(函數(shù)指針或者函數(shù)對(duì)象),該仿函數(shù)具有如下調(diào)用型別
void operator()(IterT first, IterT last) const;
void operator()(NumT val) const;
void operator()(CharT ch) const;
一旦spase發(fā)現(xiàn)了匹配real_p的子串,就會(huì)調(diào)用該functor。不同的rule可能會(huì)對(duì)應(yīng)不同的調(diào)用型別。
第一個(gè)型別針對(duì)一般規(guī)則,first和last為兩個(gè)指向字符的迭代器(一般為char*),匹配的子串為[first, last)
第二個(gè)型別針對(duì)數(shù)字型規(guī)則,如real_p和int_p, 參數(shù)val是一個(gè)數(shù)字類型。
第三個(gè)性別針對(duì)單字符型規(guī)則,如space_p, 參數(shù)ch是一個(gè)字符類型。
real_p[push_back_a(v)]中的push_back_a是一個(gè)spirit已經(jīng)定義好的functor,它會(huì)將匹配好的內(nèi)容依照匹配到的時(shí)間順序調(diào)用v的push_back函數(shù)加入到v中。
到此spirit的常用功能就都介紹完了。要詳細(xì)深入了解可以參考spirit的文檔。
最后在題一個(gè)注意要點(diǎn)。spirit的各種EBNF連接都是指針連接,因此才能在expression被賦值前就在group的定義里面使用。所以在使用EBNF的時(shí)候一定要小心不要將局部變量的rule提供給全局或者類成員變量使用,例如:
class A

{
rule<> s;
A()

{
rule<> r = int_p | hex_p;

s = r >> *(+space_p >> r); //error, r destructed after return
}
};

如果真想使用局部作用域,可以在局部的rule前面加上static.
posted @
2005-12-18 12:02 shifan3 閱讀(7122) |
評(píng)論 (5) |
編輯 收藏