一个简单的语义分析算法:单步算法——Python实现
2014-04-05 20:57
1101 查看
以前 曾经有一个人教会我一件事
要学会相信一些看似不可能的事
当你真的相信的时候
或许 没有什么事情是不可能的
——《秦时明月•与子同归》
在编译原理的众多书籍中,陈述了很多生成语法树的经典算法,它们大多是基于递归的方式进行工作的。在本文中,将与大家分享一种基于迭代方式的、易于理解的语法树生成算法,由于其一次成功迭代仅生成一个语法“树枝”的处理特点,可称之为单步算法。
我们将通过对中缀表达式的语法树生成实验进行算法细节的初步阐述与验证。
第一阶段:简单模型
我们第一阶段的中缀表达式语法规定如下:
该语法的等价描述:
对于这种简单的中缀表达式,我们的算法处理过程如下:(先大概看一遍处理过程,不要阻塞在这儿)
为了接下来讨论方便,我们做一些类似正则表达式的符号约定:
算法处理过程:
下面我们故意给中缀表达式加入一语法错误,看一看处理过程:
如果语法正确,是不可能上图情况的,所以,如果出现上图情况,可断定所给中缀表达式中有语法错误出现。
下面我们给出此算法的Python实现代码:
运算符'-'规则:
运算符'+'规则:
运算符'*'规则:
运算符'/'规则:
运算符'%'规则:
语义分析函数:
实验结果:
第二阶段:为我们的中缀表达式加入括号 :)
新的文法规则如下:
算法处理大概过程:
寻找出表达式中第一对'('')'位置的方法:
处理包含有'('')'功能的中缀表达式的方法:
实验结果:
附录:
在接下来的文章中,将会逐步增加其他的语义分析功能,如参与表达式运算的函数、条件语句的语法树生成等。
如有问题或者建议,欢迎留言讨论 :)
要学会相信一些看似不可能的事
当你真的相信的时候
或许 没有什么事情是不可能的
——《秦时明月•与子同归》
在编译原理的众多书籍中,陈述了很多生成语法树的经典算法,它们大多是基于递归的方式进行工作的。在本文中,将与大家分享一种基于迭代方式的、易于理解的语法树生成算法,由于其一次成功迭代仅生成一个语法“树枝”的处理特点,可称之为单步算法。
我们将通过对中缀表达式的语法树生成实验进行算法细节的初步阐述与验证。
第一阶段:简单模型
我们第一阶段的中缀表达式语法规定如下:
expr -> expr addop term | term addop -> + | - term -> term mulop factor | factor mulop -> * | / | % factor -> var | num | function
该语法的等价描述:
运算符优先级:(从高到低) —————————————————————————— * / % 二元操作符 - + 二元操作符 —————————————————————————— 参与运算的可以是: —————————————————————————— num:常数 var:变量 function:函数 expr:表达式 ——————————————————————————
对于这种简单的中缀表达式,我们的算法处理过程如下:(先大概看一遍处理过程,不要阻塞在这儿)
#例子1: 90-565*235/31+6756+45/312-321%12 90-A/31+6756+45/312-321%12 90-A+6756+45/312-321%12 A+6756+45/312-321%12 A+45/312-321%12 A+A-321%12 A-321%12 A-A A
为了接下来讨论方便,我们做一些类似正则表达式的符号约定:
# ^ 行首锚定 # $ 行尾锚定 # ... 与正则的(.*)意义相同,表示任意多字符 # A 参与运算的单位 可以是num、var、function或者expr # 下面便是我们算法的合并规则 ^A-A$ ^A-A+... ^A-A-... ^A+A$ ^A+A-... ^A+A+... ...A*A... ...A/A... ...A%A...
算法处理过程:
下面我们故意给中缀表达式加入一语法错误,看一看处理过程:
如果语法正确,是不可能上图情况的,所以,如果出现上图情况,可断定所给中缀表达式中有语法错误出现。
下面我们给出此算法的Python实现代码:
# 数据结构 """ list structure : - + * / % ( ) @var @num @expr @func ["-",None] ["+",None] ["*",None] ["/",None] ["%",None] ["(",None] [")",None] ["@var","varName"] ["@num","num_string"] ["@expr","-"|"+"|"*"|"/"|"%",listPtr,...] ["@func","funcName",listPtr1,...] """ ''' 31 + 8 * 9 ''' listToParse=[ ['@num','31'] , ['+',None] , ['@num','8'] , ['*',None] , ['@num','9'] ]
运算符'-'规则:
########### return value : ############# 0 parsed some expresions ############# 1 done nothing but no errors happene def module_minus(lis,i): # left i right are both indexes :) left=i-1 right=i+1 # process: ^A-A$ if i==1 and len(lis)==3: if lis[left][0]=="@var" or lis[left][0]=="@num" or \ lis[left][0]=="@expr" or lis[left][0]=="@func" : if lis[right][0]=="@var" or lis[right][0]=="@num" or \ lis[right][0]=="@expr" or lis[right][0]=="@func" : leftPtr=lis[left] rightPtr=lis[right] del lis[left:left+3] lis.insert(left,["@expr","-",leftPtr,rightPtr]) return 0 # process: ^A-A+... | ^A-A-... if i==1 and len(lis)>3: if lis[left][0]=="@var" or lis[left][0]=="@num" or \ lis[left][0]=="@expr" or lis[left][0]=="@func" : if lis[right][0]=="@var" or lis[right][0]=="@num" or \ lis[right][0]=="@expr" or lis[right][0]=="@func" : if lis[right+1][0] in "-+" : leftPtr=lis[left] rightPtr=lis[right] del lis[left:left+3] lis.insert(left,["@expr","-",leftPtr,rightPtr]) return 0 return 1
运算符'+'规则:
########### return value : ############# 0 parsed some expresions ############# 1 done nothing but no errors happene def module_plus(lis,i): # left i right are both indexes :) left=i-1 right=i+1 # process ^A+A$ if i==1 and len(lis)==3: if lis[left][0]=="@var" or lis[left][0]=="@num" or \ lis[left][0]=="@expr" or lis[left][0]=="@func" : if lis[right][0]=="@var" or lis[right][0]=="@num" or \ lis[right][0]=="@expr" or lis[right][0]=="@func" : leftPtr=lis[left] rightPtr=lis[right] del lis[left:left+3] lis.insert(left,["@expr","+",leftPtr,rightPtr]) return 0 # process ^A+A-... | ^A+A+... if i==1 and len(lis)>3: if lis[left][0]=="@var" or lis[left][0]=="@num" or \ lis[left][0]=="@expr" or lis[left][0]=="@func" : if lis[right][0]=="@var" or lis[right][0]=="@num" or \ lis[right][0]=="@expr" or lis[right][0]=="@func" : if lis[right+1][0] in "-+" : leftPtr=lis[left] rightPtr=lis[right] del lis[left:left+3] lis.insert(left,["@expr","+",leftPtr,rightPtr]) return 0 return 1
运算符'*'规则:
########### return value : ############# 0 parsed some expresions ############# 1 done nothing but no errors happene def module_multiply(lis,i): # left i right are both indexes :) left=i-1 right=i+1 # i is not at head and end # process ...A*A... if i<len(lis)-1 and i>0 : if lis[left][0]=="@var" or lis[left][0]=="@num" or \ lis[left][0]=="@expr" or lis[left][0]=="@func" : if lis[right][0]=="@var" or lis[right][0]=="@num" or \ lis[right][0]=="@expr" or lis[right][0]=="@func" : leftPtr=lis[left] rightPtr=lis[right] del lis[left:left+3] lis.insert(left,["@expr","*",leftPtr,rightPtr]) return 0 return 1
运算符'/'规则:
########### return value : ############# 0 parsed some expresions ############# 1 done nothing but no errors happene def module_division(lis,i): # left i right are both indexes :) left=i-1 right=i+1 # i is not at head and end # process ...A/A... if i<len(lis)-1 and i>0 : if lis[left][0]=="@var" or lis[left][0]=="@num" or \ lis[left][0]=="@expr" or lis[left][0]=="@func" : if lis[right][0]=="@var" or lis[right][0]=="@num" or \ lis[right][0]=="@expr" or lis[right][0]=="@func" : leftPtr=lis[left] rightPtr=lis[right] del lis[left:left+3] lis.insert(left,["@expr","/",leftPtr,rightPtr]) return 0 return 1
运算符'%'规则:
########### return value : ############# 0 parsed some expresions ############# 1 done nothing but no errors happene def module_mod(lis,i): # left i right are both indexes :) left=i-1 right=i+1 # i is not at head and end # process ...A%A... if i<len(lis)-1 and i>0 : if lis[left][0]=="@var" or lis[left][0]=="@num" or \ lis[left][0]=="@expr" or lis[left][0]=="@func" : if lis[right][0]=="@var" or lis[right][0]=="@num" or \ lis[right][0]=="@expr" or lis[right][0]=="@func" : leftPtr=lis[left] rightPtr=lis[right] del lis[left:left+3] lis.insert(left,["@expr","%",leftPtr,rightPtr]) return 0 return 1
语义分析函数:
########### return value : ############# 0 parsed sucessfully ############# 1 syntax error ############# 2 list is null :( def parse_simple_expr(lis): while 1: if len(lis)==0 : return 2 if len(lis)==1 : if lis[0][0]=="@var" or lis[0][0]=="@num" or \ lis[0][0]=="@expr" or lis[0][0]=="@func" : return 0 else: return 1 if len(lis)==2 : return 1 i=0 while 1: if i<0 or i>=len(lis): return 1 if lis[i][0] in "-+*/%": if lis[i][0]=="-": if module_minus(lis,i)==0: break else: i=i+1 continue elif lis[i][0]=="+": if module_plus(lis,i)==0: break else: i=i+1 continue elif lis[i][0]=="*": if module_multiply(lis,i)==0: break else: i=i+1 continue elif lis[i][0]=="/": if module_division(lis,i)==0: break else: i=i+1 continue elif lis[i][0]=="%": if module_mod(lis,i)==0: break else: i=i+1 continue else : return 1 else: i=i+1 return 0
实验结果:
第二阶段:为我们的中缀表达式加入括号 :)
新的文法规则如下:
expr -> expr addop term | term addop -> + | - term -> term mulop factor | factor mulop -> * | / | % factor -> ( expr )| var | num | function
算法处理大概过程:
寻找出表达式中第一对'('')'位置的方法:
########### return value :[intStatusCode,indexOf'(',indexOf')'] ############# intStatusCode ############# 0 sucessfully ############# 1 no parenthesis matched ############# 2 list is null :( def module_parenthesis_place(lis): length=len(lis) err=0 x=0 y=0 if length==0: return [2,None,None] try: x=lis.index([")",None]) except: err=1 lis.reverse() try: y=lis.index(["(",None],length-x-1) except: err=1 lis.reverse() y=length-y-1 if err==1: return [1,None,None] else: return [0,y,x]
处理包含有'('')'功能的中缀表达式的方法:
########### return value : ############# 0 parsed sucessfully ############# 1 syntax error ############# 2 list is null :( def parse_parenthesis_expr(lis): while 1: if len(lis)==0 : return 2 if len(lis)==1 : if lis[0][0]=="@var" or lis[0][0]=="@num" or \ lis[0][0]=="@expr" or lis[0][0]=="@func" : return 0 else: return 1 if len(lis)==2 : return 1 place=module_parenthesis_place(lis) if place[0]==0: mirror=lis[(place[1]+1):place[2]] if parse_simple_expr(mirror)==0: del lis[place[1]:(place[2]+1)] lis.insert(place[1],mirror[0]) else: return 1 else: return parse_simple_expr(lis) return 0
实验结果:
附录:
在接下来的文章中,将会逐步增加其他的语义分析功能,如参与表达式运算的函数、条件语句的语法树生成等。
如有问题或者建议,欢迎留言讨论 :)
相关文章推荐
- Python中使用中文
- python-Modules--已阅
- python 黄图机的爬虫脚本
- 静态方法 分类: python基础学习 2014-04-05 19:34 228人阅读 评论(0) 收藏
- 005_010 Python 选择序列中最小的第n个元素
- python 判断控制符 unicode str
- numpy的基本操作(矩阵、文件)
- Selenium入门(三)如何获取京东的商品列表
- python list(列表)赋值与复制
- Python基础函数
- 入坑python,写个黄土鸡试试水
- 005_009 Python 在排序已经完成的序列中查找元素
- 005_008 Python 获取序列中最小的几个元素
- 005_007 Python 插入元素并保持顺序,取得最小的元素
- Python学习笔记
- Windows XP搭建virtualenv
- 005_006 Python 随机访问列表的元素
- python对文件进行读写操作
- python之字符串处理 2014-4-5
- python 的file 用法