继
《面向组合子的一些测试》 进一步完善代码,制作出词法分析器.
我们首先需要一个Fail基类,他有一个纯虚函数Parser.
1 class Fail
2 {
3 public:
4 virtual NWString Parser(NWString& input)=0;
5 };
Parser的输入为要分析的字符串,输出为分析完成后剩余的字符串.
然后我们需要一个Ch和一个Str分别用来分析单个字符和一个字符串.
1 class Ch : public Fail
2 {
3 public:
4 Ch(WCHAR _value) : value(_value){}
5
6 NWString Parser(NWString& input);
7
8 WCHAR Value();
9 protected:
10 WCHAR value; // 待匹配串
11 };
12
13 class Str : public Fail
14 {
15 public:
16 Str(NWString _value) : value(_value){}
17
18 NWString Parser(NWString& input);
19 protected:
20 NWString value; // 待匹配串
21 };
然后是Seq,Alt和Any,分别表示组合,选择和循环.
1 class Seq : public Fail
2 {
3 public:
4 Seq(const NAutoPtr<Fail>& _left,const NAutoPtr<Fail>& _right) : left(_left),right(_right){}
5
6 NWString Parser(NWString& input);
7 protected:
8 NAutoPtr<Fail> left;
9 NAutoPtr<Fail> right;
10 };
11
12 class Alt : public Fail
13 {
14 public:
15 Alt(const NAutoPtr<Fail>& _left,const NAutoPtr<Fail>& _right) : left(_left),right(_right){}
16
17 NWString Parser(NWString& input);
18 protected:
19 NAutoPtr<Fail> left;
20 NAutoPtr<Fail> right;
21 };
22
23 class Any : public Fail
24 {
25 public:
26 Any(const NAutoPtr<Fail>& _left,const int _count) : left(_left),count(_count){}
27
28 NWString Parser(NWString& input);
29 protected:
30 NAutoPtr<Fail> left;
31 int count;
32 };
最后我们需要一个Node类型来存放以上这几类对象.
1 class Node
2 {
3 public:
4 Node(){}
5 Node(const NAutoPtr<Fail>& _left) : left(_left){}
6
7 friend NAutoPtr<Node> operator+(const NAutoPtr<Node>& left,const NAutoPtr<Node>& right);
8 friend NAutoPtr<Node> operator|(const NAutoPtr<Node>& left,const NAutoPtr<Node>& right);
9 friend NAutoPtr<Node> operator-(const NAutoPtr<Node>& left,const NAutoPtr<Node>& right);
10
11 static NAutoPtr<Node> OnceMore(NAutoPtr<Node> node);
12 static NAutoPtr<Node> More(NAutoPtr<Node> node);
13 static NAutoPtr<Node> NewCh(WCHAR input);
14 static NAutoPtr<Node> NewStr(NWString input);
15
16 NWString Parser(NWString& input);
17
18 NAutoPtr<Fail>& Value();
19 protected:
20 NAutoPtr<Fail> left;
21 };
下面来分析一下Node里的函数:
+:对应于Seq,用于将两个Node连接起来.
|:对应与Alt,用于选择两个Node.
-:只有left和right的Value()都是NAutoPtr<Ch>时才可使用,内部有类型转换,表示从哪个字符到哪个字符.
OnceMore:重复1次及以上.
More:重复0次以上.
NewCh:生成一个NAutoPtr<Ch>的Node对象.
NewStr:生成一个NAutoPtr<Str>的Node对象.
下面我们需要4个宏.
1 #define ONCEMORE(N) Node::OnceMore(N)
2 #define MORE(N) Node::More(N)
3 #define NEWCH(N) Node::NewCh(N)
4 #define NEWSTR(N) Node::NewStr(N)
这4个宏仅为了输入方便
然后我们来测试一下:
1 NAutoPtr<Node> Symbol = ONCEMORE(NEWCH('_') | NEWCH('a') - NEWCH('z')) | (NEWCH('A') - NEWCH('Z'))
2 + MORE(NEWCH('_') | (NEWCH('0') - NEWCH('9')) | (NEWCH('a') - NEWCH('z')) | (NEWCH('A') - NEWCH('Z')));
3 NAutoPtr<Node> Number = ONCEMORE(NEWCH('0') - NEWCH('9'));
4 NAutoPtr<Node> Real = Number + NEWCH('.') + Number;
相信对正则表达式有一定认识的同学已经知道这3条语句分别对应于什么正则表达式.
Symbol->[_a-zA-Z]+[_0-9a-zA-Z]*
Number->[0-9]+
Real->[0-9]+.[0-9]+
定义一个待分析的字符串.
1 NWString str = L"abcce_fg123.459agetr";
对其分析.
1 wprintf(L"%s\n",str);
2 wprintf(L"%s\n",Symbol->Parser(str));
3 wprintf(L"%s\n",Real->Parser(str));
4 wprintf(L"%s\n",Symbol->Parser(str));
分析结果.
1 abcce_fg123.459agetr
2 123.459agetr
3 agetr
4
因为没有考虑分析效率问题,所以使用NWString作为输入和输出,在实际使用中可用LPTSTR来代替NWString,同时修改响应代码.
最后给出
源代码
posted on 2011-01-26 22:11
lwch 阅读(2399)
评论(9) 编辑 收藏 引用 所属分类:
NScript