理解并掌握词法分析的原理与方法,能够使用某种语言实现词法分析程序。
选用某种语言(如 C/C++)实现词法分析程序。词法分析程序的主要任务如下:
1. 识别出输入的源程序中的单词,输出二元组形式的单词序列。
2. 删除无用的空白字符、回车符等没有实质意义的字符。
3. 删除注释。
1. 选定进行词法分析的高级程序设计语言,给出该语言的文法。
<程序>::=<分程序>.
<分程序> ::=[<常量说明>][<变量说明>][<过程说明>]<语句>
<常量说明> ::=<常量定义>;
<常量定义> ::=<标识符>=<无符号整数>
<无符号整数> ::= <数字>{<数字>}
<变量说明> ::=<变量定义> <标识符>;
<变量定义> ::=char | string
<标识符> ::=<字母>{<字母>|<数字>}
<语句> ::=<赋值语句>|<条件语句>|<当循环语句>|<过程调用语句>
|<复合语句>|<读语句><写语句>|<空>
<赋值语句> ::=<标识符>:=<表达式>
<表达式> ::= [+|-]<项>{<加法运算符> <项>}
<项> ::= <因子>{<乘法运算符> <因子>}
<因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’
<加法运算符> ::= +|-
<乘法运算符> ::= *|/
<关系运算符> ::= =|<>|<|<=|>|>=
<条件语句> ::=if <条件> else <语句>
<当循环语句> ::= WHILE <条件> : <语句>
<字母> ::= a|b|…|X|Y|Z
<数字> ::= 0|1|…|8|9
2. 设计单词种别表。
1 基本字 :bool,char ,char[,class,double,false,float,getchar,include,int,long,main,null,open,printf, private,public,put,read,return,short,scanf,signed,static,stdio,string,struct,true, unsigned,void
2 标识符:Letter
3 常数:number
4 运算符 :*,-,/,=,>,<,>=,==,<=,%,+,+=,-=,*=,/=
5 界符:
'(',')',',',';','.','{','}','<','>','"'
__author__ = 'PythonStriker'
Operation=['*','-','/','=','>','<','>=','==','<=','%','+','+=','-=','*=','/='] #词法分析器中分别运算符
Delimiter=['(',')',',',';','.','{','}','<','>','"'] #词法分析器中分别界符
KeyWord=['bool','char' ,'char[','class','double','false','float','getchar','include','int','long','main','null','open','printf',
'private','public','put','read','return','short','scanf','signed','static','stdio','string','struct','true',
'unsigned','void']
LeftNoteFlag=0 #/*注释清除标记
RightNoteFlag=0 #*/注释清除标记
class Complier(): #封装成编译器
def IsLetter(self,Char):
if((Char>='a' and Char<='z') or( Char>='A' and Char<='Z')):
return True
else:
return False
def IsDigit(self,Char):
if(Char<='9' and Char>='0'):
return True
else:
return False
def IsSpace(self,Char):
if(Char==' '):
return True
else:
return False
def RemoveSpace(self,List): #清除字符串中前后的空格
indexInList=0
for String in List:
List[indexInList]=String.strip()
indexInList+=1
return List
def IsNote(self,String): #判断注释类型
global LeftNoteFlag
global RightNoteFlag
index=0
for Char in String:
if(index')
elif(String in Delimiter):
if(String=='<' ):
if(List[indexInList] in KeyWord):
print('< <,分界符>')
elif(String=='>'):
if(List[indexInList-3] in Delimiter or List[indexInList-4] in KeyWord):
print('< >,分界符>')
else:
print('<'+String+',分界符>')
elif(String in Operation):
if(String=='%'):
if(not(List[indexInList].isdigit())):
print('< %,格式符>')
FormatFlag=1
continue
print('<'+String+',运算符>')
else:
if(String.isdigit()):
print('<'+String+',数字>')
elif(String.isalnum()):
if(FormatFlag==0):
print('<'+String+',变量>')
else:
print('<'+String+',格式变量>')
FormatFlag=0
else:
if(String in KeyWord):
print('<'+String+',关键字>')
elif(String in Operation):
print('<'+String+',运算符>')
else:
if(String.isdigit()):
print('<'+String+',数字>')
elif(String.isalnum()):
if(FormatFlag==0):
print('<'+String+',变量>')
else:
print('<'+String+',格式变量>')
FormatFlag=0
def main():
ComPlier=Complier()
SourceProgram=[]
Filepath=input("请输入文件路径:")
for line in open(Filepath,'r',encoding='UTF-8-sig' ):
line=line.replace('\n','')
SourceProgram.append(line)
SourceProgram=ComPlier.DeleteNote(SourceProgram)
SourceProgram=ComPlier.RemoveSpace(SourceProgram)
SourceProgram=ComPlier.Reader(SourceProgram)
ComPlier.JugeMent(SourceProgram)
if __name__ == "__main__":
main()
测试代码文件代码:test.txt内编写C语言
#include
int main(){
int a = 0; //author:pythonstriker
int b = 1;
printf("%d",a+b);
/* just for test
return ;
}
*/
return 0;
}
测试结果:
结果成功删除注释, 同时删除没有用的空格回车,识别出输入的源程序中的单词,输出二元组形式的单词序列,为以后的语法分析器打下基础。
如若输出版本不舒适还可换成如下版本:
__author__='PythonStriker'
KeySimple=['*','-','/','=','>','<','>=','==','<=','%','+','+=','-=','*=','/='] #词法分析器中分别运算符
KeyAmbit=['(',')',',',';','.','{','}','<','>','"'] #词法分析器中分别界符
KeyWord=[ 'bool','char' ,'char[','class','double','false','float','getchar','include','int','long','main','null','open','printf',
'private','public','put','read','return','short','scanf','signed','static','stdio','string','struct','true',
'unsigned','void']
WithoutSpaceKeyWord=['main','printf','scanf','open','read','true','false','getchar','put']
LeftNoteFlag=0 #/*注释清除标记
RightNoteFlag=0 #*/注释清除标记
class Assembly(): #封装成编译器
def IsLetter(self,Char):
if((Char<='z' and Char>='a') or( Char<='Z' and Char>='A')):
return True
else:
return False
def IsNote(self,String): #判断注释类型
global LeftNoteFlag
global RightNoteFlag
NumberInString=0
for Char in String:
if(NumberInString='0'):
return True
else:
return False
def IsSpace(self,Char):
if(Char==' '):
return True
else:
return False
def PassSpace(self,List): #清除字符串中前后的空格
NumberinList=0
for String in List:
List[NumberinList]=String.strip()
NumberinList+=1
return List
def SplitSourceProgram(self,List): #字符串分割
ListSplit = List.split("\\n")
'''
LIST = []
for InIt in ListSplit:
LIST.extend(InIt.split(";"))
return LIST
'''
return ListSplit
def DeleteNote(self,List): #删除列表中的注释『'//'或者'/* */'』
RemoveList=[]
FirstLeftNoteNumber=0
NumberinList=0
LeftNoteNumber=0
global LeftNoteFlag
global RightNoteFlag
for String in List:
Flag=self.IsNote(String)
NumberInString=0
FirstLeftNoteNumber=0
if(Flag):
for Char in String:
if(NumberInString宏定义符号')
elif(String in KeyAmbit):
if(String=='<' ):
if(List[NumberinList] in KeyWord):
print('< ---------->分界符')
elif(String=='>'):
if(List[NumberinList-3] in KeyAmbit or List[NumberinList-4] in KeyWord):
print('> ---------->分界符')
else:
print(String+' ---------->分界符')
elif(String in KeySimple):
if(String=='%'):
if(not(List[NumberinList].isdigit())):
print('% ---------->格式符')
FormatFlag=1
continue
print(String+' ---------->运算符')
else:
if(String.isdigit()):
print(String+' ---------->数字')
elif(String.isalnum()):
if(FormatFlag==0):
print(String+' ---------->变量')
else:
print(String+' ---------->格式变量')
FormatFlag==0
else:
if(String in KeyWord):
print(String+' ---------->关键字')
elif(String in KeySimple):
print(String+' ---------->运算符')
else:
if(String.isdigit()):
print(String+' ---------->数字')
elif(String.isalnum()):
if(FormatFlag==0):
print(String+' ---------->变量')
else:
print(String+' ---------->格式变量')
FormatFlag==0
def main():
AsseMbly=Assembly()
SourceProgram=[]
Filepath=input("请输入文件路径:")
for line in open(Filepath,'r',encoding='UTF-8-sig' ):
line=line.replace('\n','')
SourceProgram.append(line)
print(SourceProgram)
SourceProgram=AsseMbly.DeleteNote(SourceProgram)
print(SourceProgram)
SourceProgram=AsseMbly.PassSpace(SourceProgram)
SourceProgram=AsseMbly.Reader(SourceProgram)
print(SourceProgram)
AsseMbly.JugeMent(SourceProgram)
if __name__ == "__main__":
main()
输出结果如下: