简单词法分析器

本文详细介绍了如何使用Python构建一个简单的词法分析器,涉及文件读写、字符串操作、循环控制和逻辑判断。实验要求包括处理源程序、删除注释和换行、识别单词及错误提示。通过创建运算符、关键字和界符表,遍历字符流以输出单词表和错误信息,强调了编程时保持核心思路的重要性。

写在实验之前

首先感谢有缘点进来的同道们,本文将介绍使用Python语言来构建一个比较简单的词法分析程序的构建思路和过程,希望能带来一些启发和借鉴。
这个程序不算长,如果精简一下关键词等词表,不到100行。但无论程序是长是短,核心的思路都是不能忘记的。
我在自己尝试写这个程序的过程中,好几次沉浸在细节的实现上调试,以至于逐渐模糊了核心思路,极大地影响了编写程序的进度,希望大家引以为戒。

实验目标

掌握词法分析程序的工作流程

实验内容

编写一个面向高级程序设计语言的简单词法分析程序,能够识别出标识符、关键字、十进制整数和运算符

实验要求

一、在一个txt文件中输入一段有意义的高级程序设计语言(用例为C语言)的源程序,要求:
1.不少于50字符(不计空格)
2.程序中需包括合法的标识符、关键字、十进制整数和运算符
3.必须有回车换行和注释,允许//和//…两种注释,且前者可跨行
4.至少含有一个非法的标识符
二、词法分析器读入程序,并进行预处理:删除回车换行和注释,要求:
1.将预处理后的源程序以字符流的形式显示出来
2.写入新的txt中
三、词法分析器扫描预处理后的源程序,识别各单词,要求:
1.识别出的单词以<序号,类型,值>显示
2.对非法标识符,跳过不予显示,但在最后给出出错信息

对实验的分析——核心思路

我们来看一看需要用到哪些知识点:
1.文件读写操作
2.字符串操作
3.循环控制
想要自己动手写程序可以先温习一下相关方法

我们可以先从产出的角度来分析:
程序需要实现哪些功能?
输出删除注释&换行的字符流
输出识别出的单词表
提示非法标识符
不难发现,首当其冲的就是要让计算机认识需要用到的标识符、关键字、十进制整数和运算符
因此先建立一些字符串表,以备识别时使用
注意!在分析实验的时候不建议立刻去实现字符串表的代码,以防偏离重点
之后我们需要打开文件并逐行进行处理,删去回车换行
再对每一行逐字符遍历,找到注释内容并删去
此时就能够得到第一项产出——删除了注释&换行的字符流
接下来,遍历字符流,结合字符串表去识别标识符、关键字、十进制整数和运算符,同时收集可能的错误信息
最后输出单词表和错误提示信息

程序实现

字符串表

# 创建运算符表
dict_op = [
    '+',
    '-',
    '*',
    '/',
    '=',
    '<',
    '>',
    '<=',
    '>=',
    '<>'
]


# 创建关键字表
dict_key = [
    'int',
    'if',
    'then',
    'else',
    'for',
    'return',
    'void'
]


# 创建界符表
dict_dl = [
    '(',
    ')',
    '"',
    ';',
    ",",
    '{',
    '}'
]

涉及文件读写的操作

txt = open('D:\Projects\LATXT\TXT.txt', 'r+')
result = open('D:\Projects\LATXT\RESULT.txt', 'w+')
result.write(string)
txt.close()
result.close()

不要忘记文件有开就要有关哦

判断方法

# 判断当前char是否是数字
def IsNum(char):
    if(char >= '0') and (char <= '9'):
        return True
    else:
        return False


# 判断当前char是否是大小写字母
def IsChr(char):
    if((char >= 'A') and (char <= 'Z')) or ((char >= 'a') and (char <= 'z')):
        return True
    else:
        return False


# 判断当前char是否是空格
def IsSp(char):
    if char == ' ':
        return True
    else:
        return False

预处理

# 预处理文件,删去注释内容,在RESULT文件中写入单行程序流
result = open('D:\Projects\LATXT\RESULT.txt', 'w+')
string = ''
temp = ''
s = False  # s真表示现在在注释中
ss = False  # ss表示重置s标志
for line in txt.readlines():
    index = 0
    temp = ''
    if ss:
        s = False
    for char in line.strip():
        if index < len(line.strip()) - 1:
            index += 1
        if not s and char == '/' and line.strip()[index] == '/':
            s = True
            ss = True
        elif not s and char == '/' and line.strip()[index] == '*':
            s = True
        if s and index >= 2 and line.strip()[index-2] == '/' and line.strip()[index-3] == '*':
            s = False
        if not s:
            temp += char
    string += temp
result.write(string)

遍历字符流并输出单词表、错误提示信息

# 逐字扫描string,输出单词
print("单词识别如下:")
Word = ''
index = 0
count = 1
ErrorStr = ''
for char in string:
    if index < len(string) - 1:
        index += 1
    if IsSp(char):
        continue
    elif char in dict_dl:
        print("< No.{}  界符  ".format(count) + char + " >")
        count += 1
    elif char in dict_op:
        Word += char
        if string[index] in dict_op:
            continue
        else:
            print("< No.{}  运算符  ".format(count) + Word + " >")
            count += 1
            Word = ''
    elif IsNum(char) or IsChr(char):
        Word += char
        if not(IsNum(string[index]) or IsChr(string[index])):
            if Word in dict_key:
                print("< No.{}  关键字  ".format(count) + Word + " >")
                count += 1
            elif Word[0].isalpha() or Word.isdigit():
                print("< No.{}  标识符  " .format(count) + Word + " >")
                count += 1
            else:
                ErrorStr += "第" + str(count) + "个单词" + Word + "是非法标识符!\n"
                count += 1
            Word = ''
print(ErrorStr)

判别逻辑

对于这道实验来说,for指针只会遇到这四种类型的字符:字母、数字、界符、运算符,因此我们可以特别地构建判别逻辑:
请原谅我敷衍的示意图233

总结

一、核心思路是至关重要的
就像词法分析器的转换图一样,编程时一定要牢记核心思路,紧跟思路去铺开程序。
二、分清主次
编程时要先写好框架主干,后完善细节,不要急着去实现一些细枝末节的小函数,以防扰乱了思路,因小失大。
三、小单元检错
如果等到全部代码写完再调试用例,一旦出错,很难厘清出错位置。因此需要在编程时对每个函数、每个功能都要进行检错,从底层排除错误,扼杀在萌芽阶段。
四、勤写注释
本次实验的代码只有100行左右,但在后续调试中已经出现遗忘程序段实现功能的情况;在以后越来越复杂的代码中,更需要详尽的注释,提高程序的可读性。

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值