词法分析器 (编程实现)
前言:
程序的输入:为txt文件中的c语言的代码,通过python的第三库将txt文件的c语言代码存在asr[]字符变量里。
程序输出的格式为(符号,内码值)
通过之前的状态转换图。可以看到存在许多个判断分支,整体上我分为了4个大的处理模块。
- 处理标识符
if asr[t] != '\n' and asr[t] != ' ': # 去除换行符号
# 处理标识符
if asr[t].isalpha() or asr[t] == '.' and len(temAsr) == 0: # 临时字符串为空且当前指针读到的是字母
for i in asr[t:]:
temAsr = temAsr + i
t = t + 1
if t == len(asr):
t = t - 1
break
if bool(1 - asr[t].isalpha()) and bool(1 - asr[t].isdigit()) and asr[t] != '.':
break
finalStr(temAsr)
temAsr = ''
思路:就是设置一个变量去标记当前扫描的字符。通过总结得出当前指针指到是字母且临时字符串是空就将当前字符存在临时字符串中去。结束的条件:当前读到的字符不是字母也不是数字。且指针要回退一个
- 处理常数
if asr[t].isdigit() and len(temAsr) == 0:
for i in asr[t:]:
temAsr = temAsr + i
t = t + 1
if t == len(asr):
t = t - 1
break
if bool(1 - asr[t].isdigit()):
break
finalStr(temAsr)
temAsr = ''
思路:遇上个字符串的处理方式几乎相同,结束的条件结束当前读到的字符不是数字 就导致结束。且指针要回退一个。
- 处理限界符和特殊运算符号
Once_out = [',', '.', '%', '#', ';', '[', ']', '{', '}', '(', ')', '\'']
for i in Once_out:
if asr[t] == i:
finalStr(asr[t])
break
思路:这些字符读到就可以跳到终态(查表)。所以我事先将这些字符存在一个数组了,判断如果当前读到的字符是其中的一个,就执行查表的函数 finalStr()
- 其他情况
if t != len(asr):
if asr[t] == '+':
t = t + 1
if t == len(asr): # 越界检查
finalStr(asr[t - 1])
break
if asr[t] == '+' or asr[t] == '=':
finalStr('+' + asr[t])
else:
if asr[t - 2] != '+':
finalStr('+')
t = t - 1
if t != len(asr):
if asr[t] == '*':
t = t + 1
if t == len(asr):
finalStr(asr[t - 1])
break
if asr[t] == '*' or asr[t] == '/' or asr[t] == '=':
finalStr('*' + asr[t])
else:
if asr[t - 2] != '*' and asr[t - 2] != '/':
finalStr('*')
t = t - 1
思路:这里举例了两个其他情况在类似。因为这些字符存在一些组合的问题,所以要去判断属于那种字符。例如+号 存在++,+= 这写表达,要判断这些读到这个字符时下一个字符是不是可以组成这些情况。
结束语
通过不断的调试终于将正确的输出得到了,整体代码还是很冗余的。但是目的是得到正确的输出结果,有时间可以将代码更加的简洁。
txt文件内容
#include <stdio.h>
int main(){
int i = 0;
int sum = 0;
for(i=1; i<=100; i++){
sum+=i;
}
return sum;
}
输出结果
(#,70)
(include, )
(<,53)
(stdio.h, )
(>,52)
(int,14)
(main,1)
((,37)
(),38)
({,33)
(int,14)
(i,0b0)
(=,54)
(0,0b0)
(;,69)
(int,14)
(sum,0b0)
(=,54)
(0,0b0)
(;,69)
(for,7)
((,37)
(i,0b0)
(=,54)
(1,0b1)
(;,69)
(i,0b0)
(<=,56)
(100,0b1100100)
(;,69)
(i,0b0)
(++,40)
(),38)
({,33)
(sum,0b0)
(+=,58)
(i,0b0)
(;,69)
(},34)
(return,11)
(sum,0b0)
(;,69)
(},34)