您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 
 订阅
一个简单的语义分析算法:单步算法——Python实现
 
作者:燕云
   次浏览      
 2023-9-19
 
编辑推荐:
本文主要分享了一种基于迭代方式的、易于理解的语法树生成算法。
本文来自于燕云,由火龙果软件Linda编辑,推荐。

以前 曾经有一个人教会我一件事

要学会相信一些看似不可能的事

当你真的相信的时候

或许 没有什么事情是不可能的

——《秦时明月•与子同归》

在编译原理的众多书籍中,陈述了很多生成语法树的经典算法,它们大多是基于递归的方式进行工作的。在本文中,将与大家分享一种基于迭代方式的、易于理解的语法树生成算法,由于其一次成功迭代仅生成一个语法“树枝”的处理特点,可称之为单步算法。

我们将通过对中缀表达式的语法树生成实验进行算法细节的初步阐述与验证。

第一阶段:简单模型

我们第一阶段的中缀表达式语法规定如下:

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实现代码:

 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 i<len(lis)-1 and i>0 :
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 i<len(lis)-1 and i>0 :
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<0 or i>=len(lis):
20                 return 1
21             if lis[i][0] in "-+*/%":
22                 if lis[i][0]=="-":
23                     if module_minus(lis,i)==0:
24                         break
25                     else:
26                         i=i+1
27                         continue
28                 elif lis[i][0]=="+":
29                     if module_plus(lis,i)==0:
30                         break
31                     else:
32                         i=i+1
33                         continue
34                 elif lis[i][0]=="*":
35                     if module_multiply(lis,i)==0:
36                         break
37                     else:
38                         i=i+1
39                         continue
40                 elif lis[i][0]=="/":
41                     if module_division(lis,i)==0:
42                         break
43                     else:
44                         i=i+1
45                         continue
46                 elif lis[i][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

 

实验结果:

第二阶段:为我们的中缀表达式加入括号 :)

新的文法规则如下:

expr   -> expr addop term | term
addop  -> + | -
term   -> term mulop factor | factor
mulop  -> * | / | %
factor -> ( expr )| var | num | function

 

算法处理大概过程:

寻找出表达式中第一对'('')'位置的方法:

 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

 

实验结果:

 

 

 
   
次浏览       
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试

最新活动计划
C++高级编程 12-25 [线上]
白盒测试技术与工具实践 12-24[线上]
LLM大模型应用与项目构建 12-26[特惠]
需求分析最佳实践与沙盘演练 1-6[线上]
SysML建模专家 1-16[北京]
UAF架构体系与实践 1-22[北京]
 
 
最新文章
简述Matplotlib
Python三维绘图--Matplotlib
Python数据清洗实践
PyTorch实战指南
Python爬虫与数据可视化
最新课程
Python应用开发最佳实践
Python+数据分析+tensorflow
Python 编程方法和应用开发
人工智能+Python+大数据
Python及数据分析
更多...   
成功案例
某通信设备企业 Python数据分析与挖掘
某银行 人工智能+Python+大数据
某领先数字地图提供商 Python数据分析与机器学习
北京 Python及数据分析
某金融公司 Python编程方法与实践培训
更多...