随笔-341  评论-2670  文章-0  trackbacks-0

除了错误处理文件还没有定义好以外,现在语法定义跟语法树的数据结构定义以及分析器都完成了!有了这两个文件,我的工具就可以替你生成一个函数和一堆类,让你使用这个函数就可以将一份代码转换为一颗语法树啦。娃哈哈……

 

现在让我们来看一个例子,这个例子展示了一个科学计算器的表达式的结构定义以及语法定义。首先是数据结构的定义:

enum BinopType

{

  Plus

  Minus

  Mul

  Div

}

enum SinopType

{

  Negative

}

 

class Expression

{

}

class Number Expression

{

  double                              Number

}

class Binop Expression

{

  BinopType                      Operator

  Expression^                   LeftOp

  Expression^                   RightOp

}

class Sinop Expression

{

  SinopType                       Operator

  Expression^                   Operand

}

class Invoke Expression

{

  string                               Name;

  list<Expression^>         Parameters;

}

 

Type^的意思是autoptr<Type>。因为语义已经决定了这玩意儿是生成树的,所以我们不需要考虑循环引用的问题。如果你不改动这个树的话,你可以不必删除,autoptr自己会将这些问题处理掉的。内存管理是一件多么麻烦的事情啊,于是我解决掉了。class后面的第一个名称是类名,如果第二个名称存在的话则代表父类的类名,可以用来表达继承关系。

 

那么现在看看语法的定义:

num                   ="\d+(.\d+)?"            ;

ident                  ="[a-zA-Z_]\w*"       ;

plus                    ="\+"                           ;

minus                ="\-"                                     ;

mul                    ="\*"                           ;

div                      ="/"                             ;

leftbrace           ="\("                                     ;

rightbrace        ="\)"                                     ;

comma              =","                             ;

discard              ="\s+"                         ;

 

Number^                    factor=num{Number};

Sinop^                         factor=minus{Operator=Negative} factor{Operand};

Expression^               factor=leftbrace exp{#result} rightbrace;

Invoke^                       factor=ident{Name}[leftbrace param_list{Parameters} rightbrace];

Expression^               term =factor{#result};

Binop^                       term=term{LeftOp} (mul{Operator=Mul}|div{Operator=Div}) factor{RightOp};

Expression^               exp=term{#result};

Binop^                        exp=exp{LeftOp} (plus{Operator=Plus}|minus{Operator=Minus}) term{RightOp};

list<Expression^>    param_list=exp{#insert} [comma param_list{#result}];

Expression^               program=exp{#result};

 

我们来看其中的两条文法。第一条文法:list<Expression^>param_list=exp{#insert}[comma param_list{#result}];。文法推导式子返回list<Expression^>类型的对象。如果param_list存在那么将param_list当成当前的列表,否则创建一个新列表。然后将exp使用insert方法插入列表的头部。最后返回列表。

 

第二条文法:Binop^ exp=exp{LeftOp} (plus{Operator=Plus}|minus{Operator=Minus}) term{RightOp};。文法推导式子返回Binop^类型的对象。将exp放入成员LeftOp,将term放入成员RightOp,如果遇到plus则将Operator设置为BinopType::Plus,否则设置为BinopType::Minus。参考一下前面对于类Binop以及枚举类型BinopType的定义就知道了。

 

文法从program开始,分析器检查输入的字符串,得到一个正确的推倒之后,就是用这些语义命令来构造所需的数据结构。当整个过程被生成为C++代码之后,一切都变得非常的方便。等代码生成部分完成之后(这一部分由于将产生基于我半年前做的Syngram库的代码,由于Syngram支持在C++里面直接写文法,所以代码生成是没有什么难度的,而且做起来很快)就算不会处理字符串也可以写文法分析器啦!

posted on 2008-09-14 00:53 陈梓瀚(vczh) 阅读(1415) 评论(3)  编辑 收藏 引用 所属分类: 脚本技术

评论:
# re: 语法分析器定义接近完成! 2008-09-14 00:56 | Real
博主辛苦了,那么多作品。  回复  更多评论
  
# re: 语法分析器定义接近完成! 2008-09-14 02:23 | jx
您可真是个强人,不知道你考研不?  回复  更多评论
  
# re: 语法分析器定义接近完成! 2008-09-14 03:14 | 陈梓瀚(vczh)
不考  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理