From c78465010691d45f5e5bfa6a36a96800d30962ac Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Tue, 15 Nov 2022 08:08:06 -0600 Subject: Se elimina código de interfaz y se reorganizan directorios MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- arbol.py | 26 --- automata_cadenas.py | 43 ----- automata_caracteres.py | 51 ----- automata_enteros.py | 58 ------ automata_flotantes.py | 78 -------- automata_identificadores.py | 36 ---- automata_operadores.py | 96 ---------- compilador/arbol.py | 26 +++ compilador/automatas/automata_cadenas.py | 43 +++++ compilador/automatas/automata_caracteres.py | 51 +++++ compilador/automatas/automata_enteros.py | 58 ++++++ compilador/automatas/automata_flotantes.py | 78 ++++++++ compilador/automatas/automata_identificadores.py | 36 ++++ compilador/automatas/automata_operadores.py | 96 ++++++++++ compilador/lexer.py | 205 ++++++++++++++++++++ compilador/main.py | 38 ++++ compilador/parser.py | 230 +++++++++++++++++++++++ compilador/shared.py | 7 + compilador/tabla.py | 70 +++++++ lexer.py | 205 -------------------- main.py | 92 --------- parser.py | 230 ----------------------- shared.py | 7 - tabla.py | 70 ------- 24 files changed, 938 insertions(+), 992 deletions(-) delete mode 100644 arbol.py delete mode 100644 automata_cadenas.py delete mode 100644 automata_caracteres.py delete mode 100644 automata_enteros.py delete mode 100644 automata_flotantes.py delete mode 100644 automata_identificadores.py delete mode 100644 automata_operadores.py create mode 100644 compilador/arbol.py create mode 100644 compilador/automatas/automata_cadenas.py create mode 100644 compilador/automatas/automata_caracteres.py create mode 100644 compilador/automatas/automata_enteros.py create mode 100644 compilador/automatas/automata_flotantes.py create mode 100644 compilador/automatas/automata_identificadores.py create mode 100644 compilador/automatas/automata_operadores.py create mode 100644 compilador/lexer.py create mode 100644 compilador/main.py create mode 100644 compilador/parser.py create mode 100644 compilador/shared.py create mode 100644 compilador/tabla.py delete mode 100644 lexer.py delete mode 100644 main.py delete mode 100644 parser.py delete mode 100644 shared.py delete mode 100644 tabla.py diff --git a/arbol.py b/arbol.py deleted file mode 100644 index 7abcbe0..0000000 --- a/arbol.py +++ /dev/null @@ -1,26 +0,0 @@ -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/automata_cadenas.py b/automata_cadenas.py deleted file mode 100644 index 7170d4b..0000000 --- a/automata_cadenas.py +++ /dev/null @@ -1,43 +0,0 @@ -class automata_cad: - stateN = 0 - - def isAccepted(self, _str): - i = len(_str) - _len = len(_str) - - for i in range(len): - if self.stateN == 0: - self.start(_str[i]) - if self.stateN == 1: - self.state1(_str[i]) - if self.stateN == 2: - self.state2(str[i]) - else: - return 0 - if self.stateN == 2 - return 1 - else: - return 0 - - def start(self, c): - if (c == '\"'): - self.stateN = 1 - else: - self.stateN = -1 - - def state1(self,c): - if (c != '\"'): - self.stateN = 1 - else: - self.stateN = 2 - - def state2(self,c): - self.stateN = -1 - - def verified(self,token) - { - if isAccepted(token): - return true - else: - return false - } \ No newline at end of file diff --git a/automata_caracteres.py b/automata_caracteres.py deleted file mode 100644 index 341100a..0000000 --- a/automata_caracteres.py +++ /dev/null @@ -1,51 +0,0 @@ -class automata_car: - stateN = 0 - - - def isAccepted(self, _str): - i = len(_str) - _len = len(_str) - - for i in range(len): - if self.stateN == 0: - self.start(_str[i]) - if self.stateN == 1: - self.state1(_str[i]) - if self.stateN == 2: - self.state2(_str[i]) - if self.stateN == 3: - self.state3(_str[i]) - else: - return 0 - if self.stateN == 3: - return 1 - else: - return 0 - - def start(self,c): - if (c == '\''): - self.stateN = 1 - else: - self.stateN = -1 - - def state1(self,c): - if (c != '\''): - self.stateN = 2 - else: - self.stateN = 3 - - def state2(self,c): - if (c == '\''): - self.stateN = 3 - else: - self.stateN = -1 - - def state3(self,c): - self.stateN = -1 - - def verified(self,token){ - if isAccepted(token): - return true - else: - return false - } diff --git a/automata_enteros.py b/automata_enteros.py deleted file mode 100644 index 1b5fcb8..0000000 --- a/automata_enteros.py +++ /dev/null @@ -1,58 +0,0 @@ -class automata_ent: - stateN = 0 - - def isAccepted(self, _str): - i = len(_str) - _len = len(_str) - - for i in range(len): - if self.stateN == 0: - self.start(_str[i]) - if self.stateN == 1: - self.state1(_str[i]) - if self.stateN == 2: - self.state2(_str[i]) - if self.stateN == 3: - self.state3(_str[i]) - else: - return 0 - if self.stateN == 2 or self.stateN == 3: - return 1 - else: - return 0 - - - def start(self,c): - if(c == '1' or c == '2' or c == '3' or c == '4' or c == '5' or c == '6' or c == '7' or c == '8' or c == '9'): - self.stateN = 3 - else if (c == '0'): - self.stateN = 2 - else if (c == '-'): - self.stateN = 1 - else - self.stateN = -1 - - def state1(self,c): - if (c == '1' or c == '2' or c == '3' or c == '4' or c == '5' or c == '6' or c == '7' or c == '8' or c == '9'): - self.stateN = 3 - else: - self.stateN = -1 - - def state2(self,c): - self.stateN = -1 - - def state3(self,c) - { - if c.isdigit(): - self.stateN = 3 - else: - self.stateN = -1 - } - - def verified(self,token) - { - if isAccepted(token): - return true - else: - return false - } \ No newline at end of file diff --git a/automata_flotantes.py b/automata_flotantes.py deleted file mode 100644 index 5ba2b7d..0000000 --- a/automata_flotantes.py +++ /dev/null @@ -1,78 +0,0 @@ -class automata_flot: - stateN = 0 - def isAccepted(self, _str): - i = len(_str) - _len = len(_str) - - for i in range(len): - if self.stateN == 0: - self.start(_str[i]) - if self.stateN == 1: - self.state1(_str[i]) - if self.stateN == 2: - self.state2(_str[i]) - if self.stateN == 3: - self.state3(_str[i]) - if self.stateN == 4: - self.state4(_str[i]) - if self.stateN == 5: - self.state5(_str[i]) - else: - return 0 - - if self.stateN == 5: - return 1 - else: - return 0 - - def start(self, c): - if (c == '0'): - self.stateN = 1 - else if(c == '-'): - self.stateN = 2 - else if(c == '1' or c == '2' or c == '3' or c == '4' or c == '5' or - c == '6' or c == '7' or c == '8' or c == '9'): - self.stateN = 3 - else: - self.stateN = -1 - - def state1(self,c): - if (c == '.'): - self.stateN = 4 - else: - self.stateN = -1 - - def state2(self,c): - if(c == '0'): - self.stateN = 1 - else if(c == '1' or c == '2' or c == '3' or c == '4' or c == '5' or - c == '6' or c == '7' or c == '8' or c == '9'): - self.stateN = 3 - else: - self.stateN = -1 - - def state3(self,c): - if(c == '.'): - self.stateN = 4 - else if c.isdigit(): - stateN = 3 - else: - self.stateN = -1 - - def state4(self,c): - if c.isdigit(): - self.stateN = 5 - else: - self.stateN = -1 - - def state5(self,c): - if c.isdigit(): - self.stateN = 5 - else: - self.stateN = -1 - - def verified(self,token): - if isAccepted(token) - return true - else: - return false \ No newline at end of file diff --git a/automata_identificadores.py b/automata_identificadores.py deleted file mode 100644 index 7955616..0000000 --- a/automata_identificadores.py +++ /dev/null @@ -1,36 +0,0 @@ -class automata_ident: - stateN = 0 - - def isAccepted(self, _str): - i = len(_str) - _len = len(_str) - - for i in range(len): - if self.stateN == 0: - self.start(_str[i]) - if self.stateN == 1: - self.state1(_str[i]) - else: - return 0 - if self.stateN == 1: - return 1 - else: - return 0 - - def start(self, c): - if (c.isalpha() or c == '_'): - self.stateN = 1 - else: - self.stateN = -1 - - def state1(self, c): - if (c.isalpha() or c == '_' or c.isdigit()): - self.stateN = 1 - else: - self.stateN = -1 - - def no_es_main(self,token): - if isAccepted(token): - return true - else: - return false \ No newline at end of file diff --git a/automata_operadores.py b/automata_operadores.py deleted file mode 100644 index 354bfe8..0000000 --- a/automata_operadores.py +++ /dev/null @@ -1,96 +0,0 @@ - -class automata_ope: - stateN = 0 - - def isAccepted(self, _str): - i = len(_str) - _len = len(_str) - - for i in range(len): - if self.stateN == 0: - self.start(_str[i]) - if self.stateN == 1: - self.state1(_str[i]) - if self.stateN == 2: - self.state2(_str[i]) - if self.stateN == 3: - self.state3(_str[i]) - if self.stateN == 4: - self.start4(_str[i]) - if self.stateN == 5: - self.state5(_str[i]) - if self.stateN == 6: - self.state6(_str[i]) - if self.stateN == 7: - self.state7(_str[i]) - if self.stateN == 8: - self.state8(_str[i]) - else: - return 0 - if (self.stateN == 1 or self.stateN == 7 or self.stateN == 8 or self.stateN == 2 or self.stateN == 3 or self.stateN == 6): - return 1 - else: - return 0 - - def start(self,c): - if(c == '=' or c == '>' or c == '<' or c == '/' or c == '*' or c == '%' or c == '!'): - self.stateN = 1 - else if(c == '&'): - self.stateN = 4 - else if(c == '|'): - self.stateN = 5 - else if(c == '-'): - selfstateN = 6 - else if(c == '+'): - selfstateN = 3 - else: - self.stateN = -1 - - def state1(self,c): - if(c == '='): - self.stateN = 2 - else: - self.stateN = -1 - - def state2(self,c): - self.stateN = -1 - - def state3(self,c): - if(c == '+'): - self.stateN = 7 - else if(c == '='): - self.stateN = 2 - else: - self.stateN = -1 - - def state4(self,c): - if(c == '&'): - self.stateN = 2 - else: - self.stateN = -1 - - def state5(self,c): - if(c == '|'): - self.stateN = 2 - else: - self.stateN = -1 - - def state6(self,c): - if(c == '-'): - self.stateN = 8 - else if(c == '='): - self.stateN = 2 - else: - self.stateN = -1 - - def state7(self,c): - self.stateN = -1 - - def state8(self,c): - self.stateN = -1 - - def verified(self,token): - if isAccepted(token): - return true - else: - return false \ No newline at end of file diff --git a/compilador/arbol.py b/compilador/arbol.py new file mode 100644 index 0000000..7abcbe0 --- /dev/null +++ b/compilador/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/compilador/automatas/automata_cadenas.py b/compilador/automatas/automata_cadenas.py new file mode 100644 index 0000000..dc15a98 --- /dev/null +++ b/compilador/automatas/automata_cadenas.py @@ -0,0 +1,43 @@ +class automata_cad: + stateN = 0 + + def isAccepted(self, _str): + i = len(_str) + _len = len(_str) + + for i in range(len): + if self.stateN == 0: + self.start(_str[i]) + if self.stateN == 1: + self.state1(_str[i]) + if self.stateN == 2: + self.state2(str[i]) + else: + return 0 + if self.stateN == 2 + return 1 + else: + return 0 + + def start(self, c): + if (c == '\"'): + self.stateN = 1 + else: + self.stateN = -1 + + def state1(self,c): + if (c != '\"'): + self.stateN = 1 + else: + self.stateN = 2 + + def state2(self,c): + self.stateN = -1 + + def verified(self,token) + { + if isAccepted(token): + return true + else: + return false + } \ No newline at end of file diff --git a/compilador/automatas/automata_caracteres.py b/compilador/automatas/automata_caracteres.py new file mode 100644 index 0000000..139f86b --- /dev/null +++ b/compilador/automatas/automata_caracteres.py @@ -0,0 +1,51 @@ +class automata_car: + stateN = 0 + + + def isAccepted(self, _str): + i = len(_str) + _len = len(_str) + + for i in range(len): + if self.stateN == 0: + self.start(_str[i]) + if self.stateN == 1: + self.state1(_str[i]) + if self.stateN == 2: + self.state2(_str[i]) + if self.stateN == 3: + self.state3(_str[i]) + else: + return 0 + if self.stateN == 3: + return 1 + else: + return 0 + + def start(self,c): + if (c == '\''): + self.stateN = 1 + else: + self.stateN = -1 + + def state1(self,c): + if (c != '\''): + self.stateN = 2 + else: + self.stateN = 3 + + def state2(self,c): + if (c == '\''): + self.stateN = 3 + else: + self.stateN = -1 + + def state3(self,c): + self.stateN = -1 + + def verified(self,token){ + if isAccepted(token): + return true + else: + return false + } diff --git a/compilador/automatas/automata_enteros.py b/compilador/automatas/automata_enteros.py new file mode 100644 index 0000000..c97659e --- /dev/null +++ b/compilador/automatas/automata_enteros.py @@ -0,0 +1,58 @@ +class automata_ent: + stateN = 0 + + def isAccepted(self, _str): + i = len(_str) + _len = len(_str) + + for i in range(len): + if self.stateN == 0: + self.start(_str[i]) + if self.stateN == 1: + self.state1(_str[i]) + if self.stateN == 2: + self.state2(_str[i]) + if self.stateN == 3: + self.state3(_str[i]) + else: + return 0 + if self.stateN == 2 or self.stateN == 3: + return 1 + else: + return 0 + + + def start(self,c): + if(c == '1' or c == '2' or c == '3' or c == '4' or c == '5' or c == '6' or c == '7' or c == '8' or c == '9'): + self.stateN = 3 + else if (c == '0'): + self.stateN = 2 + else if (c == '-'): + self.stateN = 1 + else + self.stateN = -1 + + def state1(self,c): + if (c == '1' or c == '2' or c == '3' or c == '4' or c == '5' or c == '6' or c == '7' or c == '8' or c == '9'): + self.stateN = 3 + else: + self.stateN = -1 + + def state2(self,c): + self.stateN = -1 + + def state3(self,c) + { + if c.isdigit(): + self.stateN = 3 + else: + self.stateN = -1 + } + + def verified(self,token) + { + if isAccepted(token): + return true + else: + return false + } \ No newline at end of file diff --git a/compilador/automatas/automata_flotantes.py b/compilador/automatas/automata_flotantes.py new file mode 100644 index 0000000..b7be7d8 --- /dev/null +++ b/compilador/automatas/automata_flotantes.py @@ -0,0 +1,78 @@ +class automata_flot: + stateN = 0 + def isAccepted(self, _str): + i = len(_str) + _len = len(_str) + + for i in range(len): + if self.stateN == 0: + self.start(_str[i]) + if self.stateN == 1: + self.state1(_str[i]) + if self.stateN == 2: + self.state2(_str[i]) + if self.stateN == 3: + self.state3(_str[i]) + if self.stateN == 4: + self.state4(_str[i]) + if self.stateN == 5: + self.state5(_str[i]) + else: + return 0 + + if self.stateN == 5: + return 1 + else: + return 0 + + def start(self, c): + if (c == '0'): + self.stateN = 1 + else if(c == '-'): + self.stateN = 2 + else if(c == '1' or c == '2' or c == '3' or c == '4' or c == '5' or + c == '6' or c == '7' or c == '8' or c == '9'): + self.stateN = 3 + else: + self.stateN = -1 + + def state1(self,c): + if (c == '.'): + self.stateN = 4 + else: + self.stateN = -1 + + def state2(self,c): + if(c == '0'): + self.stateN = 1 + else if(c == '1' or c == '2' or c == '3' or c == '4' or c == '5' or + c == '6' or c == '7' or c == '8' or c == '9'): + self.stateN = 3 + else: + self.stateN = -1 + + def state3(self,c): + if(c == '.'): + self.stateN = 4 + else if c.isdigit(): + stateN = 3 + else: + self.stateN = -1 + + def state4(self,c): + if c.isdigit(): + self.stateN = 5 + else: + self.stateN = -1 + + def state5(self,c): + if c.isdigit(): + self.stateN = 5 + else: + self.stateN = -1 + + def verified(self,token): + if isAccepted(token) + return true + else: + return false \ No newline at end of file diff --git a/compilador/automatas/automata_identificadores.py b/compilador/automatas/automata_identificadores.py new file mode 100644 index 0000000..c26adfb --- /dev/null +++ b/compilador/automatas/automata_identificadores.py @@ -0,0 +1,36 @@ +class automata_ident: + stateN = 0 + + def isAccepted(self, _str): + i = len(_str) + _len = len(_str) + + for i in range(len): + if self.stateN == 0: + self.start(_str[i]) + if self.stateN == 1: + self.state1(_str[i]) + else: + return 0 + if self.stateN == 1: + return 1 + else: + return 0 + + def start(self, c): + if (c.isalpha() or c == '_'): + self.stateN = 1 + else: + self.stateN = -1 + + def state1(self, c): + if (c.isalpha() or c == '_' or c.isdigit()): + self.stateN = 1 + else: + self.stateN = -1 + + def no_es_main(self,token): + if isAccepted(token): + return true + else: + return false \ No newline at end of file diff --git a/compilador/automatas/automata_operadores.py b/compilador/automatas/automata_operadores.py new file mode 100644 index 0000000..af10e61 --- /dev/null +++ b/compilador/automatas/automata_operadores.py @@ -0,0 +1,96 @@ + +class automata_ope: + stateN = 0 + + def isAccepted(self, _str): + i = len(_str) + _len = len(_str) + + for i in range(len): + if self.stateN == 0: + self.start(_str[i]) + if self.stateN == 1: + self.state1(_str[i]) + if self.stateN == 2: + self.state2(_str[i]) + if self.stateN == 3: + self.state3(_str[i]) + if self.stateN == 4: + self.start4(_str[i]) + if self.stateN == 5: + self.state5(_str[i]) + if self.stateN == 6: + self.state6(_str[i]) + if self.stateN == 7: + self.state7(_str[i]) + if self.stateN == 8: + self.state8(_str[i]) + else: + return 0 + if (self.stateN == 1 or self.stateN == 7 or self.stateN == 8 or self.stateN == 2 or self.stateN == 3 or self.stateN == 6): + return 1 + else: + return 0 + + def start(self,c): + if(c == '=' or c == '>' or c == '<' or c == '/' or c == '*' or c == '%' or c == '!'): + self.stateN = 1 + else if(c == '&'): + self.stateN = 4 + else if(c == '|'): + self.stateN = 5 + else if(c == '-'): + selfstateN = 6 + else if(c == '+'): + selfstateN = 3 + else: + self.stateN = -1 + + def state1(self,c): + if(c == '='): + self.stateN = 2 + else: + self.stateN = -1 + + def state2(self,c): + self.stateN = -1 + + def state3(self,c): + if(c == '+'): + self.stateN = 7 + else if(c == '='): + self.stateN = 2 + else: + self.stateN = -1 + + def state4(self,c): + if(c == '&'): + self.stateN = 2 + else: + self.stateN = -1 + + def state5(self,c): + if(c == '|'): + self.stateN = 2 + else: + self.stateN = -1 + + def state6(self,c): + if(c == '-'): + self.stateN = 8 + else if(c == '='): + self.stateN = 2 + else: + self.stateN = -1 + + def state7(self,c): + self.stateN = -1 + + def state8(self,c): + self.stateN = -1 + + def verified(self,token): + if isAccepted(token): + return true + else: + return false \ No newline at end of file diff --git a/compilador/lexer.py b/compilador/lexer.py new file mode 100644 index 0000000..1952a16 --- /dev/null +++ b/compilador/lexer.py @@ -0,0 +1,205 @@ +from enum import Enum +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', + 'cadena': 'STRING', + 'caracter': 'CHAR', + 'sino': 'ELSE', + 'porcada': 'FOR', + 'si': 'IF', + 'entero': 'INT', + 'imprimir': 'PRINT', + 'leer': 'READ', + 'retorna': 'RETURN', + 'vacio': 'VOID', + 'mientras': 'WHILE' +} + +class Selector(Enum): + NINGUNO = 0 + STRING_LIT = 1 + CHAR_LIT = 2 + ID_RESERVADA = 3 + COMMENT = 4 + ENTERO = 5 + +class Lexer: + 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 + while r != Control.SIGUIENTE: + r = self.procesar(c) + if r == Control.ERROR: return + self.numlinea += 1 + + # 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 self.selector == Selector.NINGUNO: + # Entrada a string + if c == '"': + self.selector = Selector.STRING_LIT + return Control.SIGUIENTE + # Entrada a caracter + elif c == '\'': + self.selector = Selector.CHAR_LIT + return Control.SIGUIENTE + # Entrada a id o palabra reservada + elif c.isalpha() or c == '_': + self.selector = Selector.ID_RESERVADA + # Entrada a entero + elif c.isdigit(): + self.selector = Selector.ENTERO + # Entrada a comentario + elif c == '/': + self.recol_comentario = '/' + # Entrada a operador (simple o compuesto) + elif c in op_simples_a and self.recol_operador == '': + self.recol_operador = c + return Control.SIGUIENTE + # Entrada a operador (simple) + elif c in op_simples_b: + self.recol_operador = c + return Control.SIGUIENTE + # Entrada a tokens simples + elif c in otros_tokens or (c == '*' and self.recol_comentario == ''): + self.insertar_tabla(c, None, None) + return Control.SIGUIENTE + + # Apertura de comentario + if self.recol_comentario == '/' and c == '*': + self.selector = Selector.COMMENT + self.recol_comentario = '' + return Control.SIGUIENTE + + # Apertura de operador compuesto + if len(self.recol_operador) > 0: + rc = self.recol_operador + c + if rc in op_compuestos: + # Operador compuesto + self.insertar_tabla(rc, None, None) + self.recol_operador = '' + return Control.SIGUIENTE + else: + # Operador simple + self.insertar_tabla(self.recol_operador, None, None) + if c in op_simples: + self.insertar_tabla(c, None, None) + self.recol_operador = '' + return Control.SIGUIENTE + + # Cadenas de texto + if self.selector == Selector.STRING_LIT: + return self.procesar_cadena(c) + + # Caracteres + if self.selector == Selector.CHAR_LIT: + return self.procesar_caracter(c) + + # Comentarios + if self.selector == Selector.COMMENT: + return self.procesar_comentario(c) + + # Identificador o palabra reservada + if self.selector == Selector.ID_RESERVADA: + return self.procesar_identificador(c) + + # Enteros + if self.selector == Selector.ENTERO: + return self.procesar_entero(c) + + return Control.SIGUIENTE + + def procesar_cadena(self, c): + if c == '"': + self.insertar_tabla('STRING_LIT', None, self.recol_string) + self.selector = Selector.NINGUNO + self.recol_string = '' + else: + self.recol_string += c + return Control.SIGUIENTE + + def procesar_caracter(self, c): + if len(self.recol_caracter) > 1: + print ('Error: más de un caracter en una literal de caracter') + return Control.ERROR + if c == '\'': + if len(self.recol_caracter) == 0: + print ('Error: literal de caracter vacía') + return Control.ERROR + self.insertar_tabla('CHAR_LIT', None, self.recol_caracter) + self.selector = Selector.NINGUNO + self.recol_caracter = '' + else: + self.recol_caracter += c + return Control.SIGUIENTE + + def procesar_comentario(self, c): + if c == '*': + self.recol_comentario = c + elif self.recol_comentario == '*': + if c == '/': + self.selector = Selector.NINGUNO + self.recol_comentario = '' + else: + self.recol_comentario = '' + return Control.SIGUIENTE + + def procesar_identificador(self, c): + if c.isalnum() or c == '_': + self.recol_ident += c + else: + if self.recol_ident in reservadas.keys(): + self.insertar_tabla(reservadas[self.recol_ident], None, None) + elif self.recol_ident == 'verdadero': + self.insertar_tabla('BOOLEAN_LIT', None, True) + elif self.recol_ident == 'falso': + self.insertar_tabla('BOOLEAN_LIT', None, False) + else: + self.insertar_tabla('IDENT', self.recol_ident, None) + self.recol_ident = '' + self.selector = Selector.NINGUNO + return Control.REPETIR + return Control.SIGUIENTE + + def procesar_entero(self, c): + if c.isdigit(): + self.recol_entero += c + else: + self.insertar_tabla('INT_LIT', None, int(self.recol_entero)) + self.recol_entero = '' + self.selector = Selector.NINGUNO + return Control.REPETIR + return Control.SIGUIENTE + + def insertar_tabla(self, token, nombre, valor): + self.tabla.insertar(LexToken(token, nombre, valor, self.numlinea)) diff --git a/compilador/main.py b/compilador/main.py new file mode 100644 index 0000000..c27c107 --- /dev/null +++ b/compilador/main.py @@ -0,0 +1,38 @@ +import sys, getopt +from tkinter import * +from tkinter import ttk, filedialog +from lexer import * + +class Main: + input_file = None + output_file = None + + def print_help (self, arg0): + print("Uso: % s -i entrada.ñ -o salida.ñ" % arg0) + print(" % s -h" % arg0) + + def main(self, argv): + try: + opts, args = getopt.getopt(argv[1:], "hi:o:", ["input=", "output="]) + except getopt.GetoptError as err: + print(err) + print_help(argv[0]); + sys.exit(2) + + for o, a in opts: + if o == "-h": + self.print_help (argv[0]) + elif o in ("-i", "--input"): + self.input_file = a + elif o in ("-o", "--output"): + self.output_file = a + else: + assert False, "opción desconocida" + + if self.input_file and self.output_file: + with open(self.input_file) as f: + data = f.read() + Lexer(data).inicio() + +if __name__ == "__main__": + Main().main(sys.argv) diff --git a/compilador/parser.py b/compilador/parser.py new file mode 100644 index 0000000..61ab21a --- /dev/null +++ b/compilador/parser.py @@ -0,0 +1,230 @@ +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', 'STRING_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() + self.pila_selector.append([Selector.NINGUNO, []]) + 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): + recol = self.pila_selector[-1][1] + + # directiva + if len(recol) == 1: + 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 + + # directiva + expr + if len(recol) == 2: + if t.tipo == ';': + self.pila_arbol[-1].hijos.append(Nodo({ + 'selector': Selector.DIRECTIVA, + 'expresion': 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_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.tipo in operadores: + recol.append(t) + elif tipo_ultimo in operadores and t.tipo in valores: + recol.append(t) + elif tipo_ultimo in valores and t.tipo in valores: + print('Error: se esperaba un operador') + return Control.ERROR + elif tipo_ultimo in operadores and t.tipo in operadores: + print('Error: se esperaba un identificador o una literal') + return Control.ERROR + else: + self.expresion = recol[1:] + 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/compilador/shared.py b/compilador/shared.py new file mode 100644 index 0000000..e356255 --- /dev/null +++ b/compilador/shared.py @@ -0,0 +1,7 @@ +from enum import Enum + +class Control(Enum): + ERROR = -1 + SIGUIENTE = 0 + REPETIR = 1 + TERMINAR = 2 diff --git a/compilador/tabla.py b/compilador/tabla.py new file mode 100644 index 0000000..c8ca424 --- /dev/null +++ b/compilador/tabla.py @@ -0,0 +1,70 @@ +from enum import Enum +from dataclasses import dataclass +from typing import Any + +reservadas = [ + 'BOOLEAN', + 'BREAK', + 'CHAR', + 'DOUBLE', + 'ELSE', + 'FOR' + 'IDENT', + 'IF', + 'INT', + 'PRINT', + 'READ', + 'RETURN', + 'STRING', + 'VOID', + 'WHILE' +] + +literales = [ + 'BOOLEAN_LIT', + 'CHAR_LIT', + 'DOUBLE_LIT', + 'INT_LIT', + 'STRING_LIT' +] + +tokens = reservadas + literales + [ + '{', '}', '(', ')', ',', '\'', + '"', ';', '=', '*', '/', '+', + '-', '>', '<', '>=', '<=', '&&', + '||', '==', '!=', '++', '--', '//' +] + +@dataclass +class LexToken: + tipo: str + nombre: str + valor: Any + numlinea: int + + def __str__(self): + return "LexToken(%s,%s,%s,%i)" % ( + self.tipo, self.nombre, self.valor, self.numlinea + ) + +class TablaLex: + def __init__(self): + self.tabla = [] + + def insertar(self, tok: LexToken): + self.tabla.append(tok) + + def buscar(self, nombre: str): + return [t for t in self.tabla if t.nombre == nombre][0] + + def actualizar(self, nombre: str, tok: LexToken): + for i, t in enumerate(self.tabla): + if t.nombre == nombre: + self.tabla[i] = tok + return + + def __str__(self): + output = "" + for t in self.tabla: + output += str(t) + "\n" + return output diff --git a/lexer.py b/lexer.py deleted file mode 100644 index 1952a16..0000000 --- a/lexer.py +++ /dev/null @@ -1,205 +0,0 @@ -from enum import Enum -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', - 'cadena': 'STRING', - 'caracter': 'CHAR', - 'sino': 'ELSE', - 'porcada': 'FOR', - 'si': 'IF', - 'entero': 'INT', - 'imprimir': 'PRINT', - 'leer': 'READ', - 'retorna': 'RETURN', - 'vacio': 'VOID', - 'mientras': 'WHILE' -} - -class Selector(Enum): - NINGUNO = 0 - STRING_LIT = 1 - CHAR_LIT = 2 - ID_RESERVADA = 3 - COMMENT = 4 - ENTERO = 5 - -class Lexer: - 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 - while r != Control.SIGUIENTE: - r = self.procesar(c) - if r == Control.ERROR: return - self.numlinea += 1 - - # 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 self.selector == Selector.NINGUNO: - # Entrada a string - if c == '"': - self.selector = Selector.STRING_LIT - return Control.SIGUIENTE - # Entrada a caracter - elif c == '\'': - self.selector = Selector.CHAR_LIT - return Control.SIGUIENTE - # Entrada a id o palabra reservada - elif c.isalpha() or c == '_': - self.selector = Selector.ID_RESERVADA - # Entrada a entero - elif c.isdigit(): - self.selector = Selector.ENTERO - # Entrada a comentario - elif c == '/': - self.recol_comentario = '/' - # Entrada a operador (simple o compuesto) - elif c in op_simples_a and self.recol_operador == '': - self.recol_operador = c - return Control.SIGUIENTE - # Entrada a operador (simple) - elif c in op_simples_b: - self.recol_operador = c - return Control.SIGUIENTE - # Entrada a tokens simples - elif c in otros_tokens or (c == '*' and self.recol_comentario == ''): - self.insertar_tabla(c, None, None) - return Control.SIGUIENTE - - # Apertura de comentario - if self.recol_comentario == '/' and c == '*': - self.selector = Selector.COMMENT - self.recol_comentario = '' - return Control.SIGUIENTE - - # Apertura de operador compuesto - if len(self.recol_operador) > 0: - rc = self.recol_operador + c - if rc in op_compuestos: - # Operador compuesto - self.insertar_tabla(rc, None, None) - self.recol_operador = '' - return Control.SIGUIENTE - else: - # Operador simple - self.insertar_tabla(self.recol_operador, None, None) - if c in op_simples: - self.insertar_tabla(c, None, None) - self.recol_operador = '' - return Control.SIGUIENTE - - # Cadenas de texto - if self.selector == Selector.STRING_LIT: - return self.procesar_cadena(c) - - # Caracteres - if self.selector == Selector.CHAR_LIT: - return self.procesar_caracter(c) - - # Comentarios - if self.selector == Selector.COMMENT: - return self.procesar_comentario(c) - - # Identificador o palabra reservada - if self.selector == Selector.ID_RESERVADA: - return self.procesar_identificador(c) - - # Enteros - if self.selector == Selector.ENTERO: - return self.procesar_entero(c) - - return Control.SIGUIENTE - - def procesar_cadena(self, c): - if c == '"': - self.insertar_tabla('STRING_LIT', None, self.recol_string) - self.selector = Selector.NINGUNO - self.recol_string = '' - else: - self.recol_string += c - return Control.SIGUIENTE - - def procesar_caracter(self, c): - if len(self.recol_caracter) > 1: - print ('Error: más de un caracter en una literal de caracter') - return Control.ERROR - if c == '\'': - if len(self.recol_caracter) == 0: - print ('Error: literal de caracter vacía') - return Control.ERROR - self.insertar_tabla('CHAR_LIT', None, self.recol_caracter) - self.selector = Selector.NINGUNO - self.recol_caracter = '' - else: - self.recol_caracter += c - return Control.SIGUIENTE - - def procesar_comentario(self, c): - if c == '*': - self.recol_comentario = c - elif self.recol_comentario == '*': - if c == '/': - self.selector = Selector.NINGUNO - self.recol_comentario = '' - else: - self.recol_comentario = '' - return Control.SIGUIENTE - - def procesar_identificador(self, c): - if c.isalnum() or c == '_': - self.recol_ident += c - else: - if self.recol_ident in reservadas.keys(): - self.insertar_tabla(reservadas[self.recol_ident], None, None) - elif self.recol_ident == 'verdadero': - self.insertar_tabla('BOOLEAN_LIT', None, True) - elif self.recol_ident == 'falso': - self.insertar_tabla('BOOLEAN_LIT', None, False) - else: - self.insertar_tabla('IDENT', self.recol_ident, None) - self.recol_ident = '' - self.selector = Selector.NINGUNO - return Control.REPETIR - return Control.SIGUIENTE - - def procesar_entero(self, c): - if c.isdigit(): - self.recol_entero += c - else: - self.insertar_tabla('INT_LIT', None, int(self.recol_entero)) - self.recol_entero = '' - self.selector = Selector.NINGUNO - return Control.REPETIR - return Control.SIGUIENTE - - def insertar_tabla(self, token, nombre, valor): - self.tabla.insertar(LexToken(token, nombre, valor, self.numlinea)) diff --git a/main.py b/main.py deleted file mode 100644 index c541b16..0000000 --- a/main.py +++ /dev/null @@ -1,92 +0,0 @@ -import sys, getopt -from tkinter import * -from tkinter import ttk, filedialog -from lexer import * - -class Main: - input_file = None - output_file = None - - # GUI widgets - text = None - msgarea = None - symbols = None - - def abrir_archivo(self): - self.input_file = filedialog.askopenfilename() - with open(self.input_file) as f: - data = f.read() - self.text.insert(END, data) - - def guardar_archivo(self): - data = self.text.get('1.0', 'end-1c') - with open(self.input_file, "r+") as f: - f.truncate(0) - f.write(data) - - def compilar_programa(self): - self.output_file = filedialog.asksaveasfilename() - data = self.text.get('1.0', 'end-1c') - Lexer(data).inicio() - - def ejecutar_programa(self): - print('ejecutar_programa()') - - def salir(self): - exit(0) - - def main_gui(self, argv): - root = Tk() - root.title ("Javañol") - root.columnconfigure(0, weight=1) - root.rowconfigure(0, weight=1) - root.option_add('*tearOff', FALSE) - - mainframe = ttk.Frame(root, padding="3 3 12 12") - mainframe.grid(column=0, row=0, sticky=(N, W, E, S)) - mainframe.columnconfigure(0, weight=1) - mainframe.rowconfigure(0, weight=1) - mainframe.rowconfigure(1, weight=0) - - # Menú - menubar = Menu(root) - root['menu'] = menubar - - menu_file = Menu(menubar) - menubar.add_cascade(menu=menu_file, label='Archivo') - menu_file.add_command(label='Abrir', command=self.abrir_archivo) - menu_file.add_command(label='Guardar', command=self.guardar_archivo) - menu_file.add_command(label='Salir', command=self.salir) - - menu_program = Menu(menubar) - menubar.add_cascade(menu=menu_program, label='Programa') - menu_program.add_command(label='Compilar', command=self.compilar_programa) - menu_program.add_command(label='Ejecutar', command=self.ejecutar_programa) - - # Editor de código - self.text = Text(mainframe) - self.text.grid(column=0, row=0, sticky=(N, W, E, S)) - - # Área de mensajes - msgarealf = LabelFrame(mainframe, text='Área de mensajes', height=10) - msgarealf.grid(column=0, row=1, sticky=(W, E, S)) - - self.msgarea = Text(msgarealf, height=10) - self.msgarea.grid(column=0, row=0, sticky=(N, W, E, S)) - self.msgarea.rowconfigure(0, weight=1) - self.msgarea.columnconfigure(0, weight=1) - - # Tabla de símbolos - symbolslf = LabelFrame(mainframe, text='Símbolos', width=100) - symbolslf.grid(column=1, row=0, rowspan=2, sticky=(N, W, E, S)) - - self.symbols = Text(symbolslf, width=20) - self.symbols.grid(column=0, row=0, sticky=(N, W, E, S)) - self.msgarea.rowconfigure(0, weight=1) - self.msgarea.columnconfigure(0, weight=1) - - root.mainloop() - -if __name__ == "__main__": - main = Main() - main.main_gui(sys.argv) diff --git a/parser.py b/parser.py deleted file mode 100644 index 61ab21a..0000000 --- a/parser.py +++ /dev/null @@ -1,230 +0,0 @@ -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', 'STRING_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() - self.pila_selector.append([Selector.NINGUNO, []]) - 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): - recol = self.pila_selector[-1][1] - - # directiva - if len(recol) == 1: - 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 - - # directiva + expr - if len(recol) == 2: - if t.tipo == ';': - self.pila_arbol[-1].hijos.append(Nodo({ - 'selector': Selector.DIRECTIVA, - 'expresion': 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_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.tipo in operadores: - recol.append(t) - elif tipo_ultimo in operadores and t.tipo in valores: - recol.append(t) - elif tipo_ultimo in valores and t.tipo in valores: - print('Error: se esperaba un operador') - return Control.ERROR - elif tipo_ultimo in operadores and t.tipo in operadores: - print('Error: se esperaba un identificador o una literal') - return Control.ERROR - else: - self.expresion = recol[1:] - 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 deleted file mode 100644 index e356255..0000000 --- a/shared.py +++ /dev/null @@ -1,7 +0,0 @@ -from enum import Enum - -class Control(Enum): - ERROR = -1 - SIGUIENTE = 0 - REPETIR = 1 - TERMINAR = 2 diff --git a/tabla.py b/tabla.py deleted file mode 100644 index c8ca424..0000000 --- a/tabla.py +++ /dev/null @@ -1,70 +0,0 @@ -from enum import Enum -from dataclasses import dataclass -from typing import Any - -reservadas = [ - 'BOOLEAN', - 'BREAK', - 'CHAR', - 'DOUBLE', - 'ELSE', - 'FOR' - 'IDENT', - 'IF', - 'INT', - 'PRINT', - 'READ', - 'RETURN', - 'STRING', - 'VOID', - 'WHILE' -] - -literales = [ - 'BOOLEAN_LIT', - 'CHAR_LIT', - 'DOUBLE_LIT', - 'INT_LIT', - 'STRING_LIT' -] - -tokens = reservadas + literales + [ - '{', '}', '(', ')', ',', '\'', - '"', ';', '=', '*', '/', '+', - '-', '>', '<', '>=', '<=', '&&', - '||', '==', '!=', '++', '--', '//' -] - -@dataclass -class LexToken: - tipo: str - nombre: str - valor: Any - numlinea: int - - def __str__(self): - return "LexToken(%s,%s,%s,%i)" % ( - self.tipo, self.nombre, self.valor, self.numlinea - ) - -class TablaLex: - def __init__(self): - self.tabla = [] - - def insertar(self, tok: LexToken): - self.tabla.append(tok) - - def buscar(self, nombre: str): - return [t for t in self.tabla if t.nombre == nombre][0] - - def actualizar(self, nombre: str, tok: LexToken): - for i, t in enumerate(self.tabla): - if t.nombre == nombre: - self.tabla[i] = tok - return - - def __str__(self): - output = "" - for t in self.tabla: - output += str(t) + "\n" - return output -- cgit v1.2.3