使用面向组合子算法写词法分析器

使用面向组合子算法写词法分析器
继 《面向组合子的一些测试》 进一步完善代码,制作出词法分析器.

我们首先需要一个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,同时修改响应代码.
最后给出 源代码

你可能感兴趣的:(使用面向组合子算法写词法分析器)