Implementación en Python de las funciones PRIMERO y SIGUIENTE para gramáticas libres de contexto, como parte del análisis sintáctico de compiladores.
📁 proyecto/
├── main.py # Menú principal y punto de entrada
├── grammar.py # Clase Grammar (estructura de datos)
├── first_follow.py # Algoritmos PRIMERO y SIGUIENTE
├── predefined_grammars.py # Gramáticas de ejemplo listas para usar
└── grammar_input.py # Ingreso interactivo de gramáticas
- Python 3.10 o superior
- No requiere librerías externas
python main.pyAl iniciar, se muestra un menú con dos opciones:
1. Usar una gramática predefinida
2. Ingresar una gramática manualmente
3. Salir
| # | Nombre |
|---|---|
| 1 | Expresiones aritméticas (LL(1)) |
| 2 | Sentencias if-then-else |
| 3 | Listas y asignaciones (con recursión izquierda) |
| 4 | Declaraciones simples |
| 5 | Paréntesis balanceados |
Al elegir la opción 2, el programa solicita los datos paso a paso:
- Nombre de la gramática (opcional).
- No terminales separados por comas. El primero será el símbolo inicial.
- Producciones para cada no terminal, usando
|para separar alternativas.
Nombre: mi gramatica
No terminales: E, T, F
E → E + T | T
T → T * F | F
F → ( E ) | id
Para representar épsilon use:
eps,epsilonoε
Las gramáticas se representan como diccionarios de Python:
Grammar(
productions={
'E' : [['E', '+', 'T'], ['T']],
'T' : [['T', '*', 'F'], ['F']],
'F' : [['(', 'E', ')'], ['id']],
},
start_symbol='E',
name='Expresiones aritméticas'
)==================================================
Gramática: Expresiones aritméticas
==================================================
Símbolo inicial : E
No terminales : { E, F, T }
Terminales : { (, ), *, +, id }
Producciones:
E → E + T | T
T → T * F | F
F → ( E ) | id
==================================================
──────────────────────────────────────────────────
CONJUNTOS PRIMERO y SIGUIENTE
──────────────────────────────────────────────────
No Terminal PRIMERO SIGUIENTE
─────────── ──────────────────── ────────────────────
E { (, id } { $, ), + }
T { (, id } { $, ), *, + }
F { (, id } { $, ), *, + }
──────────────────────────────────────────────────
- Si
Xes terminal →PRIMERO(X) = { X } - Si
X → ε→ε ∈ PRIMERO(X) - Si
X → Y1 Y2 … Yk→ se agregan los PRIMERO de cadaYimientras el anterior pueda derivarε - Implementado con recursión + memoización para manejar gramáticas con recursión mutua.
$ ∈ SIGUIENTE(S)(símbolo inicial)- Si
A → α B β→PRIMERO(β) − {ε} ⊆ SIGUIENTE(B) - Si
ε ∈ PRIMERO(β)oBestá al final →SIGUIENTE(A) ⊆ SIGUIENTE(B) - Implementado con iteración de punto fijo hasta que ningún conjunto cambie.
Para agregar una nueva gramática al catálogo, editar predefined_grammars.py:
GRAMMAR_NUEVA = Grammar(
productions={
'S': [['a', 'S', 'b'], ['ε']],
},
start_symbol='S',
name='Mi nueva gramática'
)
# Agregar al catálogo
PREDEFINED['6'] = GRAMMAR_NUEVA