设为首页 收藏本站
查看: 1410|回复: 0

[经验分享] 一个简单的语义分析算法:单步算法——Python实现

[复制链接]

尚未签到

发表于 2015-4-20 11:52:49 | 显示全部楼层 |阅读模式
  
  以前 曾经有一个人教会我一件事
  要学会相信一些看似不可能的事
   当你真的相信的时候
   或许 没有什么事情是不可能的
  ——《秦时明月·与子同归》
  
  在编译原理的众多书籍中,陈述了很多生成语法树的经典算法,它们大多是基于递归的方式进行工作的。在本文中,将与大家分享一种基于迭代方式的、易于理解的语法树生成算法,由于其一次成功迭代仅生成一个语法“树枝”的处理特点,可称之为单步算法。
    我们将通过对中缀表达式的语法树生成实验进行算法细节的初步阐述与验证。
  第一阶段:简单模型
  我们第一阶段的中缀表达式语法规定如下:



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...
  算法处理过程:
DSC0000.png
  下面我们故意给中缀表达式加入一语法错误,看一看处理过程:
   DSC0001.png
  如果语法正确,是不可能上图情况的,所以,如果出现上图情况,可断定所给中缀表达式中有语法错误出现。
    下面我们给出此算法的Python实现代码:



1 # 数据结构
2 """
3 list structure :
4 - + * / % ( ) @var @num @expr @func
5
6 ["-",None]
7 ["+",None]
8 ["*",None]
9 ["/",None]
10 ["%",None]
11 ["(",None]
12 [")",None]
13 ["@var","varName"]
14 ["@num","num_string"]
15 ["@expr","-"|"+"|"*"|"/"|"%",listPtr,...]
16 ["@func","funcName",listPtr1,...]
17
18 """
19
20 ''' 31 + 8 * 9 '''
21 listToParse=[ ['@num','31'] , ['+',None] , ['@num','8'] , ['*',None] , ['@num','9'] ]
    运算符'-'规则:



1 ########### return value :
2 ############# 0  parsed some expresions
3 ############# 1  done nothing but no errors happene
4 def module_minus(lis,i):
5
6     # left i right are both indexes :)   
7     left=i-1
8     right=i+1
9
10     # process: ^A-A$
11     if i==1 and len(lis)==3:
12         if lis[left][0]=="@var"  or lis[left][0]=="@num" or \
13            lis[left][0]=="@expr" or lis[left][0]=="@func" :
14             if lis[right][0]=="@var"  or lis[right][0]=="@num" or \
15                lis[right][0]=="@expr" or lis[right][0]=="@func" :
16                 leftPtr=lis[left]
17                 rightPtr=lis[right]
18                 del lis[left:left+3]
19                 lis.insert(left,["@expr","-",leftPtr,rightPtr])
20                 return 0
21     # process: ^A-A+... | ^A-A-...
22     if i==1 and len(lis)>3:
23         if lis[left][0]=="@var"  or lis[left][0]=="@num" or \
24            lis[left][0]=="@expr" or lis[left][0]=="@func" :
25             if lis[right][0]=="@var"  or lis[right][0]=="@num" or \
26                lis[right][0]=="@expr" or lis[right][0]=="@func" :
27                 if lis[right+1][0] in "-+" :
28                     leftPtr=lis[left]
29                     rightPtr=lis[right]
30                     del lis[left:left+3]
31                     lis.insert(left,["@expr","-",leftPtr,rightPtr])
32                     return 0
33                 
34     return 1
    运算符'+'规则:



1 ########### return value :
2 ############# 0  parsed some expresions
3 ############# 1  done nothing but no errors happene
4 def module_plus(lis,i):
5
6     # left i right are both indexes :)   
7     left=i-1
8     right=i+1
9
10     # process ^A+A$
11     if i==1 and len(lis)==3:
12         if lis[left][0]=="@var"  or lis[left][0]=="@num" or \
13            lis[left][0]=="@expr" or lis[left][0]=="@func" :
14             if lis[right][0]=="@var"  or lis[right][0]=="@num" or \
15                lis[right][0]=="@expr" or lis[right][0]=="@func" :
16                 leftPtr=lis[left]
17                 rightPtr=lis[right]
18                 del lis[left:left+3]
19                 lis.insert(left,["@expr","+",leftPtr,rightPtr])
20                 return 0
21     # process ^A+A-... | ^A+A+...
22     if i==1 and len(lis)>3:
23         if lis[left][0]=="@var"  or lis[left][0]=="@num" or \
24            lis[left][0]=="@expr" or lis[left][0]=="@func" :
25             if lis[right][0]=="@var"  or lis[right][0]=="@num" or \
26                lis[right][0]=="@expr" or lis[right][0]=="@func" :
27                 if lis[right+1][0] in "-+" :
28                     leftPtr=lis[left]
29                     rightPtr=lis[right]
30                     del lis[left:left+3]
31                     lis.insert(left,["@expr","+",leftPtr,rightPtr])
32                     return 0
33
34     return 1
    运算符'*'规则:



1 ########### return value :
2 ############# 0  parsed some expresions
3 ############# 1  done nothing but no errors happene
4 def module_multiply(lis,i):
5
6     # left i right are both indexes :)   
7     left=i-1
8     right=i+1
9     
10     # i is not at head and end
11     # process ...A*A...
12     if i0 :
13         if lis[left][0]=="@var"  or lis[left][0]=="@num" or \
14            lis[left][0]=="@expr" or lis[left][0]=="@func" :
15             if lis[right][0]=="@var"  or lis[right][0]=="@num" or \
16                lis[right][0]=="@expr" or lis[right][0]=="@func" :
17                 leftPtr=lis[left]
18                 rightPtr=lis[right]
19                 del lis[left:left+3]
20                 lis.insert(left,["@expr","*",leftPtr,rightPtr])
21                 return 0
22     return 1
    运算符'/'规则:



1 ########### return value :
2 ############# 0  parsed some expresions
3 ############# 1  done nothing but no errors happene
4 def module_division(lis,i):
5
6     # left i right are both indexes :)   
7     left=i-1
8     right=i+1
9     
10     # i is not at head and end
11     # process ...A/A...
12     if i0 :
13         if lis[left][0]=="@var"  or lis[left][0]=="@num" or \
14            lis[left][0]=="@expr" or lis[left][0]=="@func" :
15             if lis[right][0]=="@var"  or lis[right][0]=="@num" or \
16                lis[right][0]=="@expr" or lis[right][0]=="@func" :
17                 leftPtr=lis[left]
18                 rightPtr=lis[right]
19                 del lis[left:left+3]
20                 lis.insert(left,["@expr","/",leftPtr,rightPtr])
21                 return 0
22     return 1     
    运算符'%'规则:



1 ########### return value :
2 ############# 0  parsed some expresions
3 ############# 1  done nothing but no errors happene
4 def module_mod(lis,i):
5
6     # left i right are both indexes :)   
7     left=i-1
8     right=i+1
9     
10     # i is not at head and end
11     # process ...A%A...
12     if i0 :
13         if lis[left][0]=="@var"  or lis[left][0]=="@num" or \
14            lis[left][0]=="@expr" or lis[left][0]=="@func" :
15             if lis[right][0]=="@var"  or lis[right][0]=="@num" or \
16                lis[right][0]=="@expr" or lis[right][0]=="@func" :
17                 leftPtr=lis[left]
18                 rightPtr=lis[right]
19                 del lis[left:left+3]
20                 lis.insert(left,["@expr","%",leftPtr,rightPtr])
21                 return 0
22     return 1     
  语义分析函数:



1 ########### return value :
2 ############# 0  parsed sucessfully
3 ############# 1  syntax error
4 ############# 2  list is null :(
5 def parse_simple_expr(lis):
6     while 1:
7         if len(lis)==0 :
8             return 2
9         if len(lis)==1 :
10             if lis[0][0]=="@var"  or lis[0][0]=="@num" or \
11                lis[0][0]=="@expr" or lis[0][0]=="@func" :
12                 return 0
13             else:
14                 return 1
15         if len(lis)==2 :
16             return 1
17         i=0
18         while 1:
19             if i=len(lis):
20                 return 1
21             if lis[0] in "-+*/%":
22                 if lis[0]=="-":
23                     if module_minus(lis,i)==0:
24                         break
25                     else:
26                         i=i+1
27                         continue
28                 elif lis[0]=="+":
29                     if module_plus(lis,i)==0:
30                         break
31                     else:
32                         i=i+1
33                         continue
34                 elif lis[0]=="*":
35                     if module_multiply(lis,i)==0:
36                         break
37                     else:
38                         i=i+1
39                         continue
40                 elif lis[0]=="/":
41                     if module_division(lis,i)==0:
42                         break
43                     else:
44                         i=i+1
45                         continue
46                 elif lis[0]=="%":
47                     if module_mod(lis,i)==0:
48                         break
49                     else:
50                         i=i+1
51                         continue
52                 else :
53                     return 1
54             else:
55                 i=i+1
56            
57     return 0
  实验结果:
   DSC0002.jpg
DSC0003.jpg
  第二阶段:为我们的中缀表达式加入括号 :)
  新的文法规则如下:



expr   -> expr addop term | term
addop  -> + | -
term   -> term mulop factor | factor
mulop  -> * | / | %
factor -> ( expr )| var | num | function
  算法处理大概过程:
DSC0004.png
  寻找出表达式中第一对'('')'位置的方法:



1 ########### return value :[intStatusCode,indexOf'(',indexOf')']
2 ############# intStatusCode
3 ############# 0  sucessfully
4 ############# 1  no parenthesis matched
5 ############# 2  list is null :(
6 def module_parenthesis_place(lis):
7     length=len(lis)
8     err=0
9     x=0
10     y=0
11     
12     if length==0:
13         return [2,None,None]
14     
15     try:
16         x=lis.index([")",None])
17     except:
18         err=1
19     lis.reverse()
20     try:
21         y=lis.index(["(",None],length-x-1)
22     except:
23         err=1
24     lis.reverse()
25     y=length-y-1
26     
27     if err==1:
28         return [1,None,None]
29     else:
30         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
  实验结果:
   DSC0005.jpg
DSC0006.jpg
  附录:
  在接下来的文章中,将会逐步增加其他的语义分析功能,如参与表达式运算的函数、条件语句的语法树生成等。
  如有问题或者建议,欢迎留言讨论 :)   
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-58837-1-1.html 上篇帖子: selenium webdriver (python) 第一版PDF 下篇帖子: Python dict dictionaries Python 数据结构——字典
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表