本文內(nèi)容:
1、給出文法如下:
G[E]
E->T|E+T;
T->F|T*F;
F->i|(E);
可以構(gòu)造算符優(yōu)先表如下:
+ | * | ( | ) | i | |
+ | > | < | < | > | < |
* | > | > | < | > | < |
( | < | < | < | = | < |
) | > | > | > | ||
i | > | > | > |
2、計算機(jī)中表示上述優(yōu)先關(guān)系,優(yōu)先關(guān)系的機(jī)內(nèi)存放方式有兩種1)直接存放,2)為優(yōu)先關(guān)系建立優(yōu)先函數(shù),這里由學(xué)生自己選擇一種方式;
3、給出算符優(yōu)先分析算法如下:
k:=1;S[k]:='#';
REPEAT
????????把下一個輸入符號讀進(jìn)a中;
????????IF S[k]屬于Vt?THEN j:=k ELSE j:=k-1;????????WHILE S[j]>a DO
????????BEGIN
????????????????REPEAT????????????????????????Q:=S[j];
????????????????????????IF S[j-1]屬于Vt?THEN j:=j-1 ELSE j:=j-2????????????????UNTIL s[j]<Q
????????????????把S[j+1]...S[k]歸約為某個N;????????????????k:=j+1;
????????????????S[k]:=N;
????????END OF WHILE;
????????IF S[j]<a OR S[j]=a THEN????????BEGIN
????????????????k:=k+1;????????????????S[k]:=a
????????END
????????ELSE ERRORUNTIL a=‘#'
樣例:
文章來源:http://www.zghlxwxcb.cn/news/detail-467119.html
?代碼如下:
# 輸出結(jié)果
def output(str, a, b, type):
global program
program.append([type, str[a:b + 1]])
# 判斷字符串一部分是否屬于關(guān)鍵字
# 是返回1不是返回2
def iskeywords(str, a, b):
# 關(guān)鍵字
keywords = {"if", "int", "for", "while", "do", "return", "break", "continue"}
s = str[a:a + b + 1] # 拷貝字符
if s in keywords: # 判斷是否存在,存在返回1,否則返回2
return 1
else:
return 2
# 判斷字符是否屬于運(yùn)算符或分隔符的一部分。
# 不是返回0,是返回1,是且后面能跟=號返回2
def belong_to(str, type):
if type == 4: # 選擇運(yùn)算符
library = "+-*/=><!" # 運(yùn)算符
else: # 選擇分隔符
library = ",;{}()" # 分隔符
if str in library: # 存在
# 是可能后面跟=號的幾個符號
if type == 4 and library.index(str) >= 4:
return 2
else:
return 1
return 0
# 遞歸的詞法分析函數(shù),讀入一行str字符串,初始位置 n = 0
# 分離+判斷,打印輸出類型
# 由之前的c語言版本改寫而成
def scan(str, n):
# 7 種類型(最后輸出1 - 5)
# -1
# 0: 初始
# 1: 關(guān)鍵字, 在keywords中
# 2: 標(biāo)識符
# 3: 常數(shù)(無符號整型)
# 4: 運(yùn)算符和界符:+ - * / = > < >= <= !=
# 5: 分隔符:, ; {}()
i = n
type = 0
while i < len(str):
if type == 0: # 初始態(tài)
if str[i] == ' ': # 空格跳過
n += 1
i += 1
continue
elif str[i] == '\0' or str[i] == '\n': # 是結(jié)束
return
elif ('a' <= str[i] <= 'z') or ('A' <= str[i] <= 'Z'):
type = 1 # 是字母,
elif '0' <= str[i] <= '9':
type = 3 # 是數(shù)字,常數(shù)
else:
type = belong_to(str[i], 4)
if type > 0: # 是運(yùn)算符
# 是能跟=號的運(yùn)算符,后面是=號
if type == 2 and str[i + 1] == '=':
i = i + 1 # 結(jié)束位置后移
output(str, n, i, 4) # 輸出 + 遞歸 + 結(jié)束
scan(str, i + 1)
return
elif belong_to(str[i], 5): # 是分隔符
output(str, n, i, 5) # 輸出 + 遞歸 + 結(jié)束
scan(str, i + 1)
return
else:
print("失敗:", str[i])
return
elif type == 1: # 關(guān)鍵字或標(biāo)識符
if not (('a' <= str[i] <= 'z') or ('A' <= str[i] <= 'Z')): # 不是字母了
if '0' <= str[i] <= '9': # 是數(shù)字,只能是標(biāo)識符
type = 2
else: # 非字母數(shù)字
type = iskeywords(str, n, i - 1)
output(str, n, i - 1, type) # 輸出 + 遞歸 + 結(jié)束
scan(str, i)
return
elif type == 2: # 標(biāo)識符
if not (('a' <= str[i] <= 'z') or ('A' <= str[i] <= 'Z')):
# 不是字母了
if not ('0' <= str[i] <= '9'):
# 不是數(shù)字
output(str, n, i - 1, type) # 輸出 + 遞歸 + 結(jié)束
scan(str, i)
return
elif type == 3:
if not ('0' <= str[i] <= '9'):
# 不是數(shù)字
output(str, n, i - 1, type) # 輸出 + 遞歸 + 結(jié)束
scan(str, i)
return
else:
print("%d失敗" % type)
i += 1
# 添加S->;E;,形成句子括號
# S->;E; ; ;
# E->T|E+T +,*,i,( +,*,i,)
# T->F|T*F *,i,( *,i,)
# F->i|(E) i,( i,)
# A-> ···aB··· b∈FIRSTVT(B) a<b
# A-> ···Bb··· a∈LASTVT(B) a>b
# + * ( ) i ;
# + > < < > < >
# * > > < > < >
# ( < < < = <
# ) > > > >
# i > > > >
# ; < < < < =
# 算符分析函數(shù)
def Operator_Analysis():
priority_relationship = { # 優(yōu)先關(guān)系
'+': {'+': '>', '*': '<', '(': '<', ')': '>', 'i': '<', ';': '>'},
'*': {'+': '>', '*': '>', '(': '<', ')': '>', 'i': '<', ';': '>'},
'(': {'+': '<', '*': '<', '(': '<', ')': '=', 'i': '<', ';': None},
')': {'+': '>', '*': '>', '(': None, ')': '>', 'i': None, ';': '>'},
'i': {'+': '>', '*': '>', '(': None, ')': '>', 'i': None, ';': '>'},
';': {'+': '<', '*': '<', '(': '<', ')': None, 'i': '<', ';': '='}}
p = program.copy() # 剩余輸入串
s = [';'] # 棧
a = None # 當(dāng)前符號
k = 0
j = 0
while 1:
# 讀入下一個符號
a = p.pop(0)
if a[0] == 2 or a[0] == 3:
a = 'i'
else:
a = a[1]
if not s[k] == 'F': # 找找終結(jié)符
j = k
else:
j = k - 1
while priority_relationship[s[j]][a] == '>': # 規(guī)約
while 1:
Q = s[j]
if not s[j - 1] == 'F':
j = j - 1
else:
j = j - 2
if priority_relationship[s[j]][Q] == '<': # 找到左括號結(jié)束
break
if len(s[j + 1:k + 1]) % 2 == 0: # 如果不是奇數(shù)就不是 a op b,a,(a),這幾種形式,
print("錯誤")
return -1
s = s[0:j + 1]
s.append('F')
k = j + 1
if priority_relationship[s[j]][a] == '<' or priority_relationship[s[j]][a] == '=':
s.append(a) # 入棧
k = k + 1
else:
print("錯誤")
return -1
if a == ';':
break
print("正確")
return 1
file = "program.txt"
file = open(file) # 讀取文件
while i := file.readline():
program = [] # 記錄讀到的句子
scan(i, 0)
print(i, end='')
Operator_Analysis()
file.close()
結(jié)果:文章來源地址http://www.zghlxwxcb.cn/news/detail-467119.html
10;
正確
1+2;
正確
(1+2)*3+(5+6*7);
正確
((1+2)*3+4;
錯誤
1+2+3+(*4+5);
錯誤
(a+b)*(c+d);
正確
((ab3+de4)**5)+1;錯誤
到了這里,關(guān)于python 算符優(yōu)先分析法的設(shè)計實(shí)現(xiàn) 編譯原理的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!