#-*- coding=utf-8 -*-
letter = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
number = '0123456789'
operater = '+-*/()'
dic = {} #符号表
table = [] #单词栈
wenfa = [] #字符串文法
siyuan = [] #四元式
##################################### 词法分析 ######################################
def cifa(string): #词法分析
print ''
m = 0
state = 0 #1:为标识符 2:为数字串 3:为运算符
for i in range ( len (string)):
if string[i] in operater : #如果是运算符
if state = = 1 : #state=1表明其前面的为标识符
print string[m:i], '是标识符,类型码:1'
dic[string[m:i]] = 1
table.append(string[m:i])
elif state = = 2 : #state=2表明其前面的为数字
print string[m:i], '是数字,类型码:2'
dic[string[m:i]] = 2
table.append(string[m:i])
m = i + 1
state = 3
print string[i], '是运算符,类型码:3'
dic[string[i]] = 3
table.append(string[i])
elif string[i] in number: #如果是数字
if i = = m: #判断此时的数字是否为整数的第一个数字,若是则改变状态为无符号整数
state = 2
elif string[i] in letter: #如果是字母
if state = = 2 : #判断此时的状态,若state=2表明状态为无符号整数,而整数内不能包含字母,故报错
print '词法分析检测到错误,数字串中不能包含字母'
exit( 0 )
if i = = m: #判断此时的字母是否为标识符的第一个字母,若是则改变状态为标识符
state = 1
else : #当输入的字符均不符合以上判断,则说明为非法字符,故报错
print '词法分析检测到非法字符'
exit( 0 )
if state = = 1 : #当字符串检查完后,若字符串最后部分为标识符,应将其print出来
print string[m:], '是标识符,类型码:3'
dic[string[m:]] = 1
table.append(string[m:])
elif state = = 2 : #若字符串最后部分为无符号整数,应将其print出来
print string[m:], '是无符号整数,类型码:2'
dic[string[m:]] = 2
table.append(string[m:])
table.append( '#' )
print '字符栈:' ,table, '\n词法正确'
################################### 语法分析 #####################################
'''
基本文法:
M -> +E|-E|E
E -> TE~
E~ -> +TE~|-TE~|&
T -> FT~
T~ -> *FT~|/FT~|&
F -> (E)|indentifer|digit
'''
class yufa(): #语法分析程序
def __init__( self ):
self .i = 0 #栈指针
try : #用异常处理程序捕获程序的错误,出现异常则报错
self .m()
except :
print '\n语法分析程序检查到错误'
exit( 0 )
def m( self ): #PM程序
if (table[ self .i] = = '+' ):
self .i + = 1
wenfa.append( 'M -> +E' )
self .e()
elif (table[ self .i] = = '-' ):
self .i + = 1
wenfa.append( 'M -> -E' )
self .e()
else :
wenfa.append( 'M -> E' )
self .e()
if ( self .i is not len (table) - 1 ): #语法分析结束时,若单词栈指针与单词表长度不相等,报错
print "\n语法分析程序检查到错误,'('前应该有运算符"
exit( 0 )
else :
print '\n字符串语法是:' #若一切正确,则输出语法树文法
for i in wenfa:
print i
print '语法正确'
def e( self ): #PE程序
wenfa.append( 'E -> TE1' )
self .t()
self .e1()
def e1( self ): #PE1程序
if (table[ self .i] = = '+' ):
self .i + = 1
wenfa.append( 'E1 -> +TE1' )
self .t()
self .e1()
elif (table[ self .i] = = '-' ):
self .i + = 1
wenfa.append( 'E1 -> -TE1' )
self .t()
self .e1()
else :
wenfa.append( 'E1 -> &' )
def t( self ): #PT程序
wenfa.append( 'T -> FT1' )
self .f()
self .t1()
def t1( self ): #PT1程序
if (table[ self .i] = = '*' ):
self .i + = 1
wenfa.append( 'T1 -> *FT1' )
self .f()
self .t1()
elif (table[ self .i] = = '/' ):
self .i + = 1
wenfa.append( 'T1 -> /FT1' )
self .f()
self .t1()
else :
wenfa.append( 'T1 -> &' )
def f( self ): #PF程序
if (table[ self .i] = = '(' ):
wenfa.append( 'F -> (E)' )
self .i + = 1
self .e()
if (table[ self .i]! = ')' ):
raise Exception
self .i + = 1
elif (dic[table[ self .i]] = = 1 ):
wenfa.append( 'F -> Indentifer ' + str (table[ self .i]))
self .i + = 1
elif (dic[table[ self .i]] = = 2 ):
wenfa.append( 'F -> Digit ' + str (table[ self .i]))
self .i + = 1
else :
raise Exception #若均不符合,则引出异常
####################################### 语义分析 #######################################
class yuyi:
def __init__( self ):
print '\n语义分析结果(四元式):'
self .i = 0 #栈指针
self .flag = 0 #记录临时变量T数目
self .m()
for i in siyuan: #输出四元式结果
print i
def m( self ): #PM程序
if (table[ self .i] = = '+' ):
self .i + = 1
ret1 = self .e()
siyuan.append( '(+,0,' + ret1 + ',out)' )
self .flag + = 1
elif (table[ self .i] = = '-' ):
self .i + = 1
ret2 = self .e()
siyuan.append( '(-,0,' + ret2 + ',out)' )
self .flag + = 1
else :
ret3 = self .e()
siyuan.append( '(=,' + ret3 + ',0,out)' )
def e( self ): #PE程序
ret1 = self .t()
ret2,ret3 = self .e1()
if (ret2! = '&' ): #若ret2不为&,则可以产生四元式,否则将变量传递给父项
self .flag + = 1
siyuan.append( '(' + ret2 + ',' + ret1 + ',' + ret3 + ',T' + str ( self .flag) + ')' )
return 'T' + str ( self .flag)
else :
return ret1
def e1( self ): #PE1程序
if (table[ self .i] = = '+' ):
self .i + = 1
ret1 = self .t()
ret2,ret3 = self .e1()
if (ret2 = = '&' ):
return '+' ,ret1
else :
self .flag + = 1
siyuan.append( '(' + ret2 + ',' + ret1 + ',' + ret3 + ',T' + str ( self .flag) + ')' )
return '+' , 'T' + str ( self .flag)
elif (table[ self .i] = = '-' ):
self .i + = 1
ret1 = self .t()
ret2,ret3 = self .e1()
if (ret2 = = '&' ):
return '-' ,ret1
else :
self .flag + = 1
siyuan.append( '(' + ret2 + ',' + ret1 + ',' + ret3 + ',T' + str ( self .flag) + ')' )
return '-' , 'T' + str ( self .flag)
else :
return '&' , '&'
def t( self ): #PT程序
ret1 = self .f()
ret2,ret3 = self .t1()
if (ret2! = '&' ):
self .flag + = 1
siyuan.append( '(' + ret2 + ',' + ret1 + ',' + ret3 + ',T' + str ( self .flag) + ')' )
return 'T' + str ( self .flag)
else :
return ret1
def t1( self ): #PT1程序
if (table[ self .i] = = '*' ):
self .i + = 1
ret1 = self .f()
ret2,ret3 = self .t1()
if (ret2 = = '&' ):
return '*' ,ret1
else :
self .flag + = 1
siyuan.append( '(' + ret2 + ',' + ret1 + ',' + ret3 + ',T' + str ( self .flag) + ')' )
return '*' , 'T' + str ( self .flag)
elif (table[ self .i] = = '/' ):
self .i + = 1
ret1 = self .f()
ret2,ret3 = self .t1()
if (ret2 = = '&' ): #若ret2不为&,则可以产生四元式,否则将变量传递给父项
return '/' ,ret1
else :
self .flag + = 1
siyuan.append( '(' + ret2 + ',' + ret1 + ',' + ret3 + ',T' + str ( self .flag) + ')' )
return '/' , 'T' + str ( self .flag)
else :
return '&' , '&'
def f( self ): #PF程序
if (table[ self .i] = = '(' ):
self .i + = 1
ret1 = self .e()
self .i + = 1
return str (ret1)
elif (dic[table[ self .i]] = = 1 ): #当为标识符时,传递给父项
temp = self .i
self .i + = 1
return table[temp]
elif (dic[table[ self .i]] = = 2 ): #当为整数时,传递给父项
temp = self .i
self .i + = 1
return table[temp]
####################################### 主程序 #######################################
if __name__ = = '__main__' :
string = raw_input ( '请输入表达式:' )
cifa(string)
yufa()
yuyi()
|