Implementación del analizador léxico mediante un DFA para analizar expresiones aritméticas,[关闭]

问题描述 投票:0回答:0

制作一个程序,接收包含算术表达式和注释的文本文件作为输入,并返回一个包含每个找到的标记的表,按照它们被发现的顺序并指示它们的类型。

代币类型

算术表达式只能包含以下类型的标记:

整数 花车(真实) 运营商: 任务 添加 减法 乘法 分配 力量 身份标识: 变量 特殊符号: ( ) 评论: // 接着是字符,直到该行用完

主要功能

程序可能由它需要的函数组成,但主要函数将具有以下签名(格式可能因使用的编程语言而异,但必须保留函数名称及其参数):

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()

Prueba del programa

lexerAritmetico("test.txt")

computer-science automata dfa
© www.soinside.com 2019 - 2024. All rights reserved.