aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIván Ávalos <avalos@disroot.org>2022-11-15 00:34:55 -0600
committerIván Ávalos <avalos@disroot.org>2022-11-15 00:34:55 -0600
commita55cd744c6dae4bba01ec83c6d3603e4ec0627a3 (patch)
tree70e62cfdc755aa1b97ea9e6eaafec23377e95164
parentde272f939f2ae0266a4ee363a854558ace5a59e2 (diff)
downloadjavanol-a55cd744c6dae4bba01ec83c6d3603e4ec0627a3.tar.gz
javanol-a55cd744c6dae4bba01ec83c6d3603e4ec0627a3.tar.bz2
javanol-a55cd744c6dae4bba01ec83c6d3603e4ec0627a3.zip
Primeras fases de análisis sintáctico
-rw-r--r--arbol.py26
-rw-r--r--lexer.py45
-rw-r--r--main.py2
-rw-r--r--parser.py203
-rw-r--r--shared.py7
-rw-r--r--tabla.py (renamed from symbol.py)0
6 files changed, 260 insertions, 23 deletions
diff --git a/arbol.py b/arbol.py
new file mode 100644
index 0000000..7abcbe0
--- /dev/null
+++ b/arbol.py
@@ -0,0 +1,26 @@
+class Nodo:
+ def __init__(self, dato = None):
+ self.dato = dato
+ self.hijos = []
+
+ def print(self, n = 0):
+ s = ' ' * n + 'Nodo:' + "\n"
+ s += ' ' * n + "dato = " + str(self.dato) + "\n"
+ s += ' ' * n + "hijos =\n"
+ for h in self.hijos:
+ s += h.print(n + 1)
+ s += "\n"
+ return s
+
+ def __str__(self):
+ return self.print()
+
+
+class Arbol:
+ def __init__(self, raiz: Nodo = Nodo()):
+ self.raiz = raiz
+
+ def __str__(self):
+ if self.raiz:
+ return str(self.raiz)
+ return "None"
diff --git a/lexer.py b/lexer.py
index 248dc52..1952a16 100644
--- a/lexer.py
+++ b/lexer.py
@@ -1,10 +1,13 @@
from enum import Enum
-from symbol import LexToken, TablaLex, tokens
+from tabla import LexToken, TablaLex, tokens
+from parser import Parser
+from shared import Control
op_compuestos = ['>=', '<=', '==', '!=', '&&', '||', '++', '--']
op_simples_a = ['=', '+', '-', '&', '|'] # pueden ir al final del op compuesto
op_simples_b = ['!', '<', '>'] # solo pueden ir al inicio del op compuesto
op_simples = op_simples_a + op_simples_b
+otros_tokens = ['{', '}', '(', ')', ',', '.', ';']
reservadas = {
'booleano': 'BOOLEAN',
'detener': 'BREAK',
@@ -29,24 +32,21 @@ class Selector(Enum):
COMMENT = 4
ENTERO = 5
-class Control(Enum):
- SIGUIENTE = 0
- REPETIR = 1
- ERROR = 2
-
class Lexer:
- tabla = TablaLex()
- numlinea = 1
- selector = Selector.NINGUNO
- recol_string = ''
- recol_caracter = ''
- recol_comentario = ''
- recol_operador = ''
- recol_ident = ''
- recol_entero = ''
-
- def inicio_lexer(self, data):
- for l in data.splitlines():
+ def __init__(self, data):
+ self.tabla = TablaLex()
+ self.numlinea = 1
+ self.selector = Selector.NINGUNO
+ self.recol_string = ''
+ self.recol_caracter = ''
+ self.recol_comentario = ''
+ self.recol_operador = ''
+ self.recol_ident = ''
+ self.recol_entero = ''
+ self.data = data
+
+ def inicio(self):
+ for l in self.data.splitlines():
for c in l + "\n":
r = self.procesar(c)
if r == 2: return
@@ -57,10 +57,12 @@ class Lexer:
# Imprimir tabla de símbolos
print (str(self.tabla))
+ Parser(self.tabla).inicio()
+
def procesar(self, c):
- if c != "\t" and c != "\n":
- print (c + ' (' + str(self.selector) + ')')
+ # if c != "\t" and c != "\n":
+ # print (c + ' (' + str(self.selector) + ')')
if self.selector == Selector.NINGUNO:
# Entrada a string
@@ -89,8 +91,7 @@ class Lexer:
self.recol_operador = c
return Control.SIGUIENTE
# Entrada a tokens simples
- elif (c == '{' or c == '}' or c == '(' or c == ')' or
- c == ',' or c == '.' or c == ';' or (c == '*' and self.recol_comentario == '')):
+ elif c in otros_tokens or (c == '*' and self.recol_comentario == ''):
self.insertar_tabla(c, None, None)
return Control.SIGUIENTE
diff --git a/main.py b/main.py
index 119336a..c541b16 100644
--- a/main.py
+++ b/main.py
@@ -27,7 +27,7 @@ class Main:
def compilar_programa(self):
self.output_file = filedialog.asksaveasfilename()
data = self.text.get('1.0', 'end-1c')
- Lexer().inicio_lexer(data)
+ Lexer(data).inicio()
def ejecutar_programa(self):
print('ejecutar_programa()')
diff --git a/parser.py b/parser.py
new file mode 100644
index 0000000..7b48bbd
--- /dev/null
+++ b/parser.py
@@ -0,0 +1,203 @@
+from enum import Enum
+from tabla import LexToken, TablaLex, tokens
+from arbol import Arbol, Nodo
+from shared import Control
+from pprint import pprint
+
+valores = ['IDENT', 'BOOLEAN_LIT', 'CHAR_LIT', 'INT_LIT']
+
+operadores = [
+ '>=', '<=', '==', '!=', '&&', '||', '++', '--',
+ '=', '+', '-', '&', '|', '!', '<', '>'
+]
+
+class Selector(Enum):
+ NINGUNO = 0
+ DEF_VARIABLE = 1
+ DIRECTIVA = 2
+ EXPRESION = 3
+ IF = 4
+ FOR = 5
+ WHILE = 6
+ FUNCION = 7
+
+class Parser:
+ def __init__(self, tabla):
+ self.arbol = Arbol()
+ self.pila_selector = [
+ [Selector.NINGUNO, []] # selector, recolector
+ ]
+ self.pila_arbol = [self.arbol.raiz]
+ self.expresion = None
+ self.tabla = tabla
+
+ def inicio (self):
+ for t in self.tabla.tabla:
+ r = self.procesar(t)
+ if r == 2: return
+ while r != Control.SIGUIENTE:
+ r = self.procesar(t)
+ if r == Control.ERROR: return
+
+ print(str(self.arbol))
+
+ def procesar (self, t: LexToken):
+ if len(self.pila_selector) == 0:
+ return Control.SIGUIENTE
+
+ # pprint (self.pila_selector[-1])
+
+ cima = self.pila_selector[-1]
+
+ if cima[0] == Selector.NINGUNO:
+ # Entrada a definición de variable (o función)
+ if t.tipo in ['BOOLEAN', 'CHAR', 'INT', 'VOID']:
+ self.pila_selector.pop()
+ self.pila_selector.append([Selector.DEF_VARIABLE, [t]])
+ return Control.SIGUIENTE
+ # Entrada a directiva del lenguaje
+ elif t.tipo in ['PRINT', 'READ', 'RETURN']:
+ self.pila_selector.pop()
+ self.pila_selector.append([Selector.DIRECTIVA, [t]])
+ return Control.SIGUIENTE
+ # Entrada a expresión
+ elif t.tipo in valores:
+ self.pila_selector.pop()
+ self.pila_selector.append([Selector.EXPRESION, [t]])
+ return Control.SIGUIENTE
+ # Entrada a if
+ elif t.tipo == 'IF':
+ self.pila_selector.pop()
+ self.pila_selector.append([Selector.IF, []])
+ return Control.SIGUIENTE
+ # Entrada a for
+ elif t.tipo == 'FOR':
+ self.pila_selector.pop()
+ self.pila_selector.append([Selector.FOR, []])
+ return Control.SIGUIENTE
+ # Entrada a while
+ elif t.tipo == 'WHILE':
+ self.pila_selector.pop()
+ self.pila_selector.append([Selector.WHILE, []])
+ return Control.SIGUIENTE
+
+ if cima[0] == Selector.DEF_VARIABLE:
+ return self.procesar_def_variable(t)
+
+ if cima[0] == Selector.DIRECTIVA:
+ return self.procesar_directiva(t)
+
+ if cima[0] == Selector.EXPRESION:
+ return self.procesar_expresion(t)
+
+ if cima[0] == Selector.IF:
+ return self.procesar_if(t)
+
+ if cima[0] == Selector.FOR:
+ return self.procesar_for(t)
+
+ if cima[0] == Selector.WHILE:
+ return self.procesar_while(t)
+
+ if cima[0] == Selector.FUNCION:
+ return self.procesar_funcion(t)
+
+ return Control.SIGUIENTE
+
+ def procesar_def_variable(self, t):
+ recol = self.pila_selector[-1][1]
+
+ # tipo
+ if len(recol) == 1:
+ if t.tipo != 'IDENT':
+ print('Error: se esperaba identificador')
+ return Control.ERROR
+ recol.append(t)
+ return Control.SIGUIENTE
+
+ # tipo + ident
+ if len(recol) == 2:
+ if t.tipo == ';':
+ self.pila_arbol[-1].hijos.append(Nodo({
+ 'selector': Selector.DEF_VARIABLE,
+ 'tipo': recol[0].tipo,
+ 'nombre': recol[1].nombre
+ }))
+ self.pila_selector.pop()
+ elif t.tipo == '=':
+ recol.append(t)
+ else:
+ print('Error: se esperaba `;` o `=`')
+ return Control.ERROR
+ return Control.SIGUIENTE
+
+ # tipo + ident + =
+ if len(recol) == 3:
+ if t.tipo in valores:
+ self.pila_selector.append([Selector.EXPRESION, [t]])
+ recol.append(t)
+ else:
+ print('Error: se esperaba una expresión')
+ return Control.ERROR
+ return Control.SIGUIENTE
+
+ # tipo + ident + = + expr
+ if len(recol) == 4:
+ if t.tipo == ';':
+ self.pila_arbol[-1].hijos.append(Nodo({
+ 'selector': Selector.DEF_VARIABLE,
+ 'tipo': recol[0].tipo,
+ 'nombre': recol[1].nombre,
+ 'valor': self.expresion
+ }))
+ self.expresion = None
+ self.pila_selector.pop()
+ self.pila_selector.append([Selector.NINGUNO, []])
+ else:
+ print('Error: se esperaba `;`')
+ return Control.ERROR
+
+ return Control.SIGUIENTE
+
+ def procesar_directiva(self, t):
+ return
+
+ def procesar_expresion(self, t):
+ recol = self.pila_selector[-1][1]
+ tipo_ultimo = recol[-1].tipo
+
+ if len(recol) == 1:
+ if tipo_ultimo in valores:
+ recol.append(recol[-1])
+ else:
+ print('Error: se esperaba un identificador o una literal')
+ return Control.ERROR
+
+ if tipo_ultimo in valores and t in operadores:
+ recol.append(t)
+ elif tipo_ultimo in operadores and t in valores:
+ recol.append(t)
+ elif tipo_ultimo in valores and t in valores:
+ print('Error: se esperaba un operador')
+ return Control.ERROR
+ elif tipo_ultimo in operadores and t in operadores:
+ print('Error: se esperaba un identificador o una literal')
+ return Control.ERROR
+ else:
+ self.expresion = recol
+ self.pila_selector.pop()
+ return Control.REPETIR
+
+ return Control.SIGUIENTE
+
+ def procesar_if(self, t):
+ return
+
+ def procesar_for(self, t):
+ return
+
+ def procesar_while(self, t):
+ return
+
+ def procesar_funcion(self, t):
+ return
diff --git a/shared.py b/shared.py
new file mode 100644
index 0000000..e356255
--- /dev/null
+++ b/shared.py
@@ -0,0 +1,7 @@
+from enum import Enum
+
+class Control(Enum):
+ ERROR = -1
+ SIGUIENTE = 0
+ REPETIR = 1
+ TERMINAR = 2
diff --git a/symbol.py b/tabla.py
index c8ca424..c8ca424 100644
--- a/symbol.py
+++ b/tabla.py