赞
踩
1、待分析的简单语言的词法
(1)识别关键字(所有关键字都是小写):begin if then while do end main int float for
(2)运算符和界符: + - * / % := < <> <= > >= = == ; ( ) #
(3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:
ID = letter(letter | digit)*
NUM = digit digit*
(4) 过滤空格,空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM、运算符、界符和关键字。
(5) 能识别注释,并将注释从代码段中过滤掉。
注释的规则是:由/* */包括的字符串,(扩展识别以 // 表示的注释)
各种单词符号对应的种别码
单词符号 | 种别码 | 单词符号 | 种别码 | 单词符号 | 种别码 |
---|---|---|---|---|---|
begin | 1 | double | 12 | != | 23 |
if | 2 | char | 13 | < | 24 |
then | 3 | break | 14 | <> | 25 |
while | 4 | continue | 15 | <= | 26 |
do | 5 | letter(letter|digit) | 16 | > | 27 |
end | 6 | digit digit* | 17 | >= | 28 |
main | 7 | + | 18 | = | 29 |
int | 8 | — | 19 | == | 30 |
float | 9 | * | 20 | ; | 31 |
for | 10 | # | 21 | ( | 32 |
else | 11 | % | 22 | ) | 33 |
语法分析程序中待识别的简单语言的语法如下
(1)<程序>→begin <语句串>end
(2)<语句串>→<语句>{;<语句>}
(3)<语句>→<赋值语句>
(4)<赋值语句>→ID=<表达式>
(5)<表达式>∷=[+|-] <项>{(+|-) <项>}
(6)<项>∷=<因子>{(*|/) <因子>}
(7)<因子>∷= id|num| ‘(‘<表达式>‘)’
语法分析程序的输入与输出
输入:所给文法的源程序字符串。
输出:如果语句是文法是别的正确语句输出“success”,否则输出“error”。
# !/usr/bin/env python # -*- encoding: utf-8 -*- # @Author : 寻觅 # @File : 第二次上机.py # @Time : 2020/12/17 13:36 # @Software: PyCharm import re class 编译原理: def __init__(self): self.关键字列表 = ['begin', 'if', 'then', 'while', 'do', 'end', 'main', 'int', 'float', 'for', 'else', 'double', 'char', 'break', 'continue'] self.符号列表 = ['+', '-', '*', '#', '%', '!=', '<', '<>', '<=', '>', '>=', '=', '=='] self.结束符列表 = [';', '(', ')'] self.句尾结束符 = [';', '(', ')', 'end', 'begin', '结束'] self.报错信息 = [] self.语法分析开头字符 = 'begin' self.语法分析结束字符 = 'end' def 识别关键字(self, 输入内容): 已识别关键字 = [] for 角标, 关键字 in enumerate(self.关键字列表): if 输入内容.find(关键字) >= 0: 已识别关键字.append((角标 + 1, 关键字)) return 已识别关键字 def 识别结束符(self, 输入内容): 已识别符号 = [] for 角标, 结束符 in enumerate(self.结束符列表): if 输入内容.find(结束符) >= 0: 已识别符号.append((角标 + len(self.关键字列表) + len(self.符号列表) + 3, 结束符)) return 已识别符号 def 识别变量(self, 输入内容, 已识别符号): 已识别变量 = [] for 角标, 符号 in enumerate(self.符号列表): if 输入内容.find(符号) == -1: continue 已识别符号.append((角标 + len(self.关键字列表) + 3, 符号)) print(符号, 输入内容) 正则匹配 = re.findall(f'\w+/{符号}\w+', 输入内容) # print('正则匹配:', 正则匹配) for 匹配内容 in 正则匹配: # print('测试:', 匹配内容) for 拆分内容 in 匹配内容.split(符号): try: 已识别变量.append((17, int(拆分内容))) except: # 判断开头是否为数字 if re.findall(f'^\d', 拆分内容) != []: print(f'警告:{拆分内容},语法错误') continue 已识别变量.append((16, 拆分内容)) return 已识别变量 @staticmethod def 文件输出(文件内容): for 用户输入 in 文件内容: yield 用户输入 def 用户输入(self, 输出写入代码=True, 启动句尾结束符判断=True, 输出注释=True, 词法分析=True, 语法分析=False, 报错信息=True, 读取文件路径=None): 数字 = 1 输入列表 = [] 注释列表 = [] 输入内容 = False if 读取文件路径: 读取文件 = open(读取文件路径, 'r').readlines() 用户指定的文件内容 = self.文件输出(读取文件) print(f'成功读取文件: {读取文件路径}') while True: if 读取文件路径: try: 用户输入 = next(用户指定的文件内容).rstrip("\n") except: 用户输入 = '结束' else: 用户输入 = input(f'当前为{数字}行: ') if 数字 == 1 and 语法分析: if not re.findall(f'^{self.语法分析开头字符}', 用户输入): self.报错信息.append(f'程序为使用{self.语法分析开头字符}开头') if 用户输入.rfind('结束') != -1: if 语法分析: try: if 输入列表[-1].rfind(self.语法分析结束字符) != -1: 输入内容 = ' '.join(输入列表) elif 用户输入.rfind(f'{self.语法分析结束字符}结束') != -1 or 用户输入.rfind(f'{self.语法分析结束字符} 结束') != -1: 输入内容 = ' '.join(输入列表) + ' ' + 用户输入[0:-2] else: self.报错信息.append(f'请使用{self.语法分析结束字符}结束') except: if 用户输入.rfind(f'{self.语法分析结束字符}结束') != -1 or 用户输入.rfind(f'{self.语法分析结束字符} 结束') != -1: 输入内容 = 用户输入[0:-2] self.报错信息.append(f'请使用{self.语法分析结束字符}结束') if not 输入内容: 输入内容 = ' '.join(输入列表) break if re.findall('/\*.*?\*/', 用户输入): 注释 = re.findall('/\*.*?\*/', 用户输入) 注释列表.append(注释) continue else: if 启动句尾结束符判断: 通过判断 = False for 结束符 in self.句尾结束符: if 用户输入.rfind(结束符) != -1: 通过判断 = True if not 通过判断: self.报错信息.append(f'[错误行{数字}]: 请用`;`结尾') 输入列表.append(用户输入) 数字 += 1 if 输出写入代码: print('==========当前写入的代码===========') for 角标, i in enumerate(输入列表): print(f'[{角标+1}]: {i}') if 注释列表 != [] and 输出注释: print('==========当前写入的注释===========') for i in 注释列表: print(i) if 报错信息 and self.报错信息 != []: print('==========报错信息===========') for 信息 in self.报错信息: print(信息) if 词法分析: 关键字 = self.识别关键字(输入内容) 符号 = self.识别结束符(输入内容) 变量 = self.识别变量(输入内容, 符号) print('==========输出二元组===========') print(关键字 + 符号 + 变量) 编译原理().用户输入(语法分析=True) # 编译原理().用户输入(语法分析=True, 读取文件路径='数据.txt')
如果你的种别码和我不同,只需修改__init__
中对应的列表即可!
用户输入的默认参数为下列,可以根据不同的需求开放或关闭这些功能
输出写入代码=True, 启动句尾结束符判断=True, 输出注释=True, 词法分析=True, 语法分析=False, 报错信息=True, 读取文件路径=None
手动输入时,输入汉字结束
即可结束输入状态!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。