算符优先分析+属性文法 简单计算器的实现
写在前面
这是本人编译原理的课程作业,仅提供参考作用,不建议直接拷贝作为作业进行提交,如果文章或者代码中出现错误,欢迎指正
参考文章
构造简单的算符优先文法
G(E)
E-> E+T|E-T|T
T-> T*F|T/F|F
F-> (E)|i
因为使用规约的方式,所以不用考虑左递归产生的影响
实现步骤
- 计算出各个非终结符的FIRSTVT和LASTVT
- 根据FIRSTVT和LASTVT构造优先关系表
- 根据优先关系表进行移进归约
计算各个非终结符的FIRSTVT和LASTVT集合
FIRSTVT
如果存在文法 A->aB... 或者 A->Ba... 则 a ∈ FIRSTVT(A)
如果存在文法 A->B... 则FIRSTVT(B) ∈ FIRSTVT(A)
所以文法中G(E)中的所有非终结符的FIRSTVT为
FIRSTVT(E) = {+,-,*,/,(,i}
FIRSTVT(T) = {*,/,(,i}
FIRSTVT(F) = {(,i}
LASTVT
如果存在文法 A->...aB 或者 A->...a 则 a ∈ LASTVT(A)
如果存在文法 a ∈ LASTVT(B) 且 A->...B 则 a ∈ LASTVT(A)
所以文法中G(E)中的所有非终结符的LASTVT为
LASTVT(E) = {+,-,*,/,),i}
LASTVT(T) = {*,/,),i}
LASTVT(F) = {),i}
根据FIRSTVT和LASTVT构造优先关系表
| + | - | * | / | ( | ) | i | # | |
|---|---|---|---|---|---|---|---|---|
| + | > | > | < | < | < | > | < | > |
| - | > | > | < | < | < | > | < | > |
| * | > | > | > | > | < | > | < | > |
| / | > | > | > | > | < | > | < | > |
| ( | < | < | < | < | < | = | < | |
| ) | > | > | > | > | > | > | ||
| i | > | > | > | > | > | > | ||
| # | < | < | < | < | < | < | = |
根据算符优先文法的规则构建算符优先文法的代码,就是判断什么时候规约,什么时候移进
注!!!算符优先文法的规约只判断终结符,跳过非终结符进行比较

这里算符优先文法的实现依赖于词法分析的实现,所以这里先贴上词法分析的代码
文件名:lab1.py
'''
@Author: wentaoStudy
@Date: 2020-05-13 10:44:03
@LastEditTime: 2020-06-30 17:57:24
@LastEditors: wentaoStudy
@Email: 2335844083@qq.com
'''
class NormalFunctions:
def __init__(self , strInput):
self.ch = ''
self.strToken = ""
self.strInput = strInput
self.index = 0
# self.reserve = ["const", "var", "procedure", "call", "begin", "end", "if", "then", "while", "do", "odd", ".", ",", "=", ";", ":=", "#", "<", ">", "+", "-", "*", "/", "(", ")"]
self.word_reserve = ["begin" , "end" , "if" , "then" , "while" , "do" , "const" , "var" , "call" , "procedure"]
self.compute_reserve = ["+" , "-" , "*" , "/" , "odd" , "=" , "<>" , "<" , ">" , "<=" , ">=" , ":=" ]
self.boder_reserve = ["(" , ")" , "," , "." , ";"]
self.Id = []
self.Const = []
def GetChar(self):
if self.index < len(self.strInput):
self.ch = self.strInput[self.index]
self.index += 1
else:
self.ch = ''
self.index += 1
def GetBC(self):
while(self.ch == " "):
self.GetChar()
def Concat(self):
self.strToken += self.ch
def IsLetter(self):
Char = self.ch
if((Char>='a' and Char<='z') or( Char>='A' and Char<='Z')):
return True
else:
return False
def IsDigit(self):
try:
int(self.ch)
return True
except:
return False
def Reserve(self):
try:
index = self.reserve.index(self.strToken)
return index + 1
except:
return 0
def Word_Reserve(self):
try:
index = self.word_reserve.index(self.strToken)
return index + 1
except:
return 0
def Compute_Reserve(self):
try:
index = self.compute_reserve.index(self.strToken)
return index + 1
except:
return 0
def Boder_Reserve(self):
try:
index = self.boder_reserve.index(self.strToken)
return index + 1
except:
return 0
def Retract(self):
# if self.index > 0 and self.index < len(self.strInput):
if self.index > 0:
self.index -= 1
def InsertId(self):
self.Id.append(self.strToken)
return len(self.Id)
def InsertConst(self):
self.Concat.append(self.strToken)
return len(self.Id)
#实现类内自己编译
def Self_Compile(self):
while(self.index < len(self.strInput)):
self.Compile_Str()
self.strToken = ""
def Compile_Str(self):
self.GetChar()
self.GetBC()
if(self.IsLetter()):
while((self.IsLetter() or self.IsDigit()) ):
self.Concat()
self.GetChar()
self.Retract()
# self.Retract()
word_code = self.Word_Reserve()
compute_code = self.Compute_Reserve()
if word_code == 0 and compute_code == 0:
value = self.InsertId()
print("< 标识符" , self.strToken , "-" ">")
else :
if word_code > 0 :
print("< 保留字" , self.strToken , word_code , ">")
if compute_code > 0:
print("< 算符" , self.strToken , compute_code , ">")
elif(self.IsDigit()):
while(self.IsDigit()):
self.Concat()
self.GetChar()
self.Retract()
# self.Retract()
value = self.InsertId()
print("< 常数" ,self.strToken , value , ">")
else:
#这里描述界符和运算符
self.Concat()
compute_code = self.Compute_Reserve()
boder_code = self.Boder_Reserve()
if compute_code == 0 and boder_code == 0:
self.GetChar()
self.Concat()
if self.Compute_Reserve() > 0:
print("< 算符" , self.strToken , self.Compute_Reserve() , ">")
else:
self.Retract()
#异常处理
pass
elif boder_code > 0:
print("< 界符" , self.strToken , self.Boder_Reserve() , ">")
elif compute_code > 0:
if compute_code > 6:
self.GetChar()
self.Concat()
if self.Compute_Reserve() > 0:
print("< 算符" , self.strToken , self.Compute_Reserve() , ">")
else:
self.Retract()
#异常处理
pass
else:
print("< 算符" , self.strToken , self.Compute_Reserve() , ">")
else:
self.Retract()
#异常处理
pass
#进行测试的代码
#strInput = "1*i+1 )("
#func = NormalFunctions(strInput)
#func.Self_Compile()
算符优先文法+属性文法实现简单的4则计算器
文件名:lab3.py
'''
@Author: wentaoStudy
@Date: 2020-06-29 08:47:51
@LastEditTime: 2020-06-30 18:07:25
@LastEditors: wentaoStudy
@Email: 2335844083@qq.com
'''
from lab1 import NormalFunctions
PRT = [
['>','>','<','<','<','>','<','>'],
['>','>','<','<','<','>','<','>'],
['>','>','>','>','<','>','<','>'],
['>','>','>','>','<','>','<','>'],
['<','<','<','<','<','=','<',' '],
['>','>','>','>',' ','>',' ','>'],
['>','>','>','>',' ','>',' ','>'],
['<','<','<','<','<',' ','>','=']
]
Terminators = ['+','-','*','/','(',')','i','#']
# G(E)
# E-> E+T|E-T|T
# T-> T*F|T/F|F
# F-> (E)|i
rules = {
"N":["N+N" , "N-N" , "N*N" , "N/N" , "(N)" , "i"]
}
from enum import Enum
class proprity_type(Enum):
ntm = 1
tm = 2
class property():
def __init__(self , i_type , i_name , i_val):
self.i_type = i_type
self.i_name = i_name
self.i_val = i_val
NTM = ["N"]
TM = ["(" , ")" , "+" , "-" , "*" , "/" , "i"]
class move_into_reduction_proprity():
def if_number(self , str):
rt = False
try:
int(str)
rt = True
except:
rt = False
return rt
def tindex(self , char):
return Terminators.index(char)
def __init__(self , input_str):
self.input_list = []
#调用词法分析
self.nf = NormalFunctions(input_str)
while(self.nf.index < len(self.nf.strInput)):
self.nf.Compile_Str()
self.input_list.append(self.nf.strToken)
self.nf.strToken = ""
print(self.input_list)
self.reduction_stack = []
self.proprity_stack = []
self.proprity_stack.append(property(proprity_type.tm , "#" , "#"))
for i in self.input_list:
if i in NTM:
self.proprity_stack.append(property(proprity_type.ntm , i , 0))
elif self.if_number(i):
self.proprity_stack.append(property(proprity_type.tm , "i" , int(i)))
elif i in TM:
self.proprity_stack.append(property(proprity_type.tm , i , i))
else:
print("类型错误")
self.proprity_stack.append(property(proprity_type.tm , "#" , "#"))
self.input_list = self.proprity_stack[1:]
self.reduction_stack = []
self.reduction_stack.append((self.proprity_stack[0]))
def move_into(self):
if len(self.input_list )!= 0:
self.reduction_stack.append(self.input_list[0])
self.input_list.pop(0)
def self_reduction(self , left , right):
tempstr = ""
for i in range(left , right+1):
tempstr += self.reduction_stack[i].i_name
temp_val = 0
if tempstr == "i":
temp_val = int(self.reduction_stack[left].i_val)
elif tempstr == "N+N":
val1 = self.reduction_stack[left].i_val
val2 = self.reduction_stack[left+2].i_val
temp_val = val1 + val2
elif tempstr == "N-N":
val1 = self.reduction_stack[left].i_val
val2 = self.reduction_stack[left+2].i_val
temp_val = val1 - val2
elif tempstr == "N*N":
val1 = self.reduction_stack[left].i_val
val2 = self.reduction_stack[left+2].i_val
temp_val = val1 * val2
elif tempstr == "N/N":
val1 = self.reduction_stack[left].i_val
val2 = self.reduction_stack[left+2].i_val
temp_val = val1 / val2
elif tempstr == "(N)":
temp_val = self.reduction_stack[left+1].i_val
print(tempstr + " -> N")
for i in range(left , right+1).__reversed__():
self.reduction_stack.pop(i)
self.reduction_stack.append(property(proprity_type.ntm , "N" , temp_val))
def judge_can_reduction(self , left , right):
tempstr = ""
for i in range(left , right+1):
tempstr += self.reduction_stack[i].i_name
if tempstr in rules["N"]:
return True
else:
return False
def lmp_d(self):
l = 0
r = 0
lr_list = ["#"]
lasti = 0
for i , value in enumerate(self.reduction_stack):
if value.i_name in TM:
lr_list.append(value.i_name)
row = self.tindex(lr_list[len(lr_list) - 2])
col = self.tindex(lr_list[len(lr_list) - 1])
if PRT[row][col] == "<":
l = lasti
elif PRT[row][col] == ">":
r = i - 1
lasti = i
if self.input_list[0].i_name in Terminators:
row = self.tindex(lr_list[len(lr_list) - 1])
col = self.tindex(self.input_list[0].i_name)
if PRT[row][col] == ">":
r = len(self.reduction_stack) - 1
if r > 0:
if self.judge_can_reduction(l+1 , r):
self.self_reduction(l+1 , r)
self.lmp_d()
else:
print("不可归约")
def statue(self):
while(len(self.input_list) != 0):
if(self.input_list[0].i_name == "#"):
print("归约结束")
break
self.move_into()
self.lmp_d()
for i in self.reduction_stack:
print(i.i_name , i.i_val)
if len(self.reduction_stack) != 2:
print("归约错误")
# print(self.reduction_stack)
mir = move_into_reduction_proprity("(3*(1+2)*100)")
mir.statue()
运行结果

浙公网安备 33010602011771号