实习题:构造一个小(Mini)语言的词法分析程序。 设计一个包含简单算术表达式、赋值语句、IF语句的小语 言的文法。 根据此文法,构造一词法分析程序。输入以“#”为结束符 的源程序,输出为各类单词表和单词串文件。 要求:源程序和输出的单词串均以文件的形式存放。单词 的自身值均为其对应的表的指针,如标识符表的指针、常数表 的指针等。 词法错误类型:词法中未定义的字符及任何不符合词法单元定义的字符。请给出详细代码
时间: 2024-02-15 18:03:21 浏览: 165
好的,我可以给你写一个基于Python的Mini语言词法分析程序,实现词法单元的识别、单词表的构建以及单词串文件的输出。代码如下:
```python
# coding: utf-8
# 定义关键字和操作符
keywords = ['if', 'then', 'else']
operators = ['+', '-', '*', '/', '=', '<', '>', '<=', '>=', '==', '!=']
# 定义单词类型的枚举
class TokenType:
IDENTIFIER = 1
NUMBER = 2
KEYWORD = 3
OPERATOR = 4
DELIMITER = 5
ERROR = 6
# 定义Token类,表示一个单词
class Token:
def __init__(self, value, token_type, position):
self.value = value # 单词的字符串值
self.token_type = token_type # 单词的类型
self.position = position # 单词在源文件中的位置
# 定义符号表类
class SymbolTable:
def __init__(self):
self.table = [] # 符号表列表
self.next_index = 0 # 下一个可用的索引
# 向符号表中添加一个新的符号,并返回其索引
def add(self, symbol):
if symbol not in self.table:
self.table.append(symbol)
return self.table.index(symbol)
# 根据索引从符号表中获取一个符号
def get(self, index):
return self.table[index]
# 定义词法分析器类
class Lexer:
def __init__(self):
self.symbol_table = SymbolTable() # 符号表实例
self.tokens = [] # 单词列表
# 执行词法分析,生成单词列表和符号表
def analyze(self, filename):
with open(filename, 'r') as f:
# 逐个字符读入源文件
source = f.read()
# 记录当前位置和行号
position = 0
line = 1
while position < len(source):
# 跳过空格和换行符
if source[position] in [' ', '\t', '\r', '\n']:
if source[position] == '\n':
line += 1
position += 1
continue
# 判断是否为关键字或标识符
if source[position].isalpha():
start = position
while position < len(source) and (source[position].isalnum() or source[position] == '_'):
position += 1
word = source[start:position]
if word in keywords:
token_type = TokenType.KEYWORD
else:
token_type = TokenType.IDENTIFIER
token = Token(word, token_type, (start, position, line))
self.tokens.append(token)
index = self.symbol_table.add(word)
token.value = index
continue
# 判断是否为数字常量
if source[position].isdigit():
start = position
while position < len(source) and source[position].isdigit():
position += 1
if position < len(source) and source[position] == '.':
position += 1
while position < len(source) and source[position].isdigit():
position += 1
word = source[start:position]
token = Token(word, TokenType.NUMBER, (start, position, line))
self.tokens.append(token)
index = self.symbol_table.add(word)
token.value = index
continue
# 判断是否为操作符
if source[position] in operators:
start = position
position += 1
while position < len(source) and source[position-1:position+1] in operators:
position += 1
word = source[start:position]
token = Token(word, TokenType.OPERATOR, (start, position, line))
self.tokens.append(token)
continue
# 判断是否为分隔符
if source[position] in ['(', ')', ';', ',']:
start = position
position += 1
word = source[start:position]
token = Token(word, TokenType.DELIMITER, (start, position, line))
self.tokens.append(token)
continue
# 未定义的字符,输出错误信息
token = Token(source[position], TokenType.ERROR, (position, position+1, line))
self.tokens.append(token)
position += 1
# 输出单词串文件
with open('tokens.txt', 'w') as f:
for token in self.tokens:
f.write(str(token.token_type) + ' ' + str(token.value) + ' ' + str(token.position) + '\n')
# 输出标识符表文件
with open('identifiers.txt', 'w') as f:
for symbol in self.symbol_table.table:
f.write(symbol + '\n')
# 测试代码
if __name__ == '__main__':
lexer = Lexer()
lexer.analyze('source.txt')
```
以上代码实现了一个Mini语言的词法分析程序,包括单词类型的定义、Token类的定义、SymbolTable类的定义、Lexer类的定义以及词法分析的实现。在执行程序时,需要将源文件名传入`analyze`函数中。程序会输出单词串文件`tokens.txt`和标识符表文件`identifiers.txt`。你可以根据需要修改输出文件的格式和路径。
希望这个代码对你有帮助!
阅读全文