制作一个程序,接收包含算术表达式和注释的文本文件作为输入,并返回一个包含每个找到的标记的表,按照它们被发现的顺序并指示它们的类型。
代币类型
算术表达式只能包含以下类型的标记:
整数 花车(真实) 运营商: 任务 添加 减法 乘法 分配 力量 身份标识: 变量 特殊符号: ( ) 评论: // 接着是字符,直到该行用完
主要功能
程序可能由它需要的函数组成,但主要函数将具有以下签名(格式可能因使用的编程语言而异,但必须保留函数名称及其参数):
void lexerArithmetic(字符串文件);
其中 file 是包含要解析的表达式的文件的名称(名称必须包含扩展名,例如 expressions.txt)。
入口
包含一个或多个算术表达式的文本文件,每行一个。 令牌不一定必须由空格分隔,或者可以由多个空格分隔 例如:
b=7
a = 32.4 *(-8.6 - b)/ 6.1E-8
d = a ^ b // 这是评论
退出
它应该提供以下输出:
代币
家伙
b
变量
=
作业
7
整个
到
变量
=
作业
32.4
真实
*
乘法
(
打开的括号
-8.6
真实
-
减法
b
变量
)
右括号
/
师
6.1E-8
真实
d
变量
=
作业
^
电源
b
变量
// 这是评论
评论
部分代币的形成规则
变量: 它们必须以字母(大写或小写)开头。 它们仅由字母、数字和下划线('_')组成。 实数(浮点数): 它们可以是正面的或负面的 它们可能有也可能没有小数部分,但必须包含小数点(例如 10. 或 10.0) 他们可以使用带有字母 E 的指数表示法,大写或小写,但字母 E 后只能有正整数或负整数(例如 2.3E3、6.345e-5、-0.001E-3、.467E9)。 评论: 它们以 // 开头,然后直到该行结束的所有内容都是注释。
算法
令牌识别必须通过有限确定自动机的转换表来完成。 自动机的设计必须是文档的基础部分(使用一些计算工具来绘制它,不要手工绘制)。
我试图像这样实现它:
def lexerAritmetico(存档): # Definir la tabla de transición del AFD tabla_transicion = { 0:{ '字母':1, '数字':2, '-':3, '+':4, '*': 5, '/': 6, '^': 7, '=': 8, '(':9, ')': 10, '/': 11, '其他':12 }, 1:{ '字母':1, '数字':1, '_':1, '其他':-1 }, 2:{ '数字':2, '.': 13, 'e':15, '其他':-1 }, 3:{ '数字':2, '.': 13, '-': 18, '其他':-1 }, 4:{ '数字':2, '.': 13, '-': 18, '其他':-1 }, 5:{ '数字':2, '.': 13, '-': 18, '其他':-1 }, 6:{ '数字':2, '.': 13, '-': 18, '其他':-1 }, 7:{ '数字':2, '.': 13, '-': 18, '其他':-1 }, 8:{ '其他':-1 }, 9:{ '其他':-1 }, 10:{ '其他':-1 }, 11:{ '/': 12, '其他':-1 }, 12:{ '其他':-1 }, 13:{ 'digito':14, '其他':-1 }, 14:{ 'digito':14, 'e':15, '其他':-1 }, 15:{ 'digito':17, '-': 16, '+':16, '其他':-1 }, 16:{ 'digito':17, '其他':-1 }, 17:{ 'digito':17, '其他':-1 }, 18:{ '数字':2, '.': 13, '其他':-1 } }
# Definir los estados finales del AFD
estados_finales = {1: 'Variable', 2: 'Entero', 14: 'Real', 8: 'Operador', 9: 'Paréntesis'}
# Leer el archivo
with open(archivo, "r") as file:
lineas = file.readlines()
# Procesar cada línea del archivo
for linea in lineas:
linea = linea.strip() # Eliminar espacios en blanco al inicio y final de la línea
# Ignorar líneas vacías o comentarios completos
if not linea or linea.startswith("//"):
continue
estado_actual = 0
i = 0 # Índice para recorrer la línea
while i < len(linea):
c = linea[i] # Carácter actual
# Determinar la categoría del carácter
if c.isalpha():
categoria = 'letra'
elif c.isdigit():
categoria = 'digito'
elif c == '_':
categoria = '_'
else:
categoria = 'otros'
if estado_actual == -1:
print("Error: token no válido")
break
# Verificar si hay una transición válida desde el estado actual
if categoria in tabla_transicion[estado_actual]:
estado_actual = tabla_transicion[estado_actual][categoria]
i += 1 # Avanzar al siguiente carácter
else:
# No hay transición válida, se ha encontrado un token
if estado_actual in estados_finales:
tipo = estados_finales[estado_actual]
token = linea[:i]
print(token)
print(tipo)
print()
# Recortar la línea y reiniciar el análisis desde el principio
linea = linea[i:]
i = 0
estado_actual = 0
else:
# No se ha encontrado un token válido, se ignora el carácter
i += 1
estado_actual = 0
# Comprobar si queda algún token pendiente al final de la línea
if estado_actual in estados_finales:
tipo = estados_finales[estado_actual]
token = linea
print(token)
print(tipo)
print()
lexerAritmetico("test.txt")