aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--compilador/nanoiter.py30
-rw-r--r--compilador/parse/base.py9
-rw-r--r--compilador/parse/decl.py12
-rw-r--r--compilador/parse/expr.py2
-rw-r--r--compilador/parse/type.py38
-rw-r--r--compilador/parser.py2
-rw-r--r--compilador/tabla.py6
-rw-r--r--pruebas/sintaxis2.es6
9 files changed, 71 insertions, 38 deletions
diff --git a/.gitignore b/.gitignore
index 36608c4..c2d12e7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
__pycache__/
-*.tab \ No newline at end of file
+*.tab
+*.gv
+*.gv.pdf
diff --git a/compilador/nanoiter.py b/compilador/nanoiter.py
new file mode 100644
index 0000000..928522f
--- /dev/null
+++ b/compilador/nanoiter.py
@@ -0,0 +1,30 @@
+from typing import Optional, NoReturn, List, TypeVar
+
+T = TypeVar('T')
+
+class NanoIter:
+ def __init__(self, l: List[T]):
+ self.i = -1
+ self.l: List[T] = l
+
+ def next(self) -> T:
+ if self.i == len(self.l):
+ raise StopIteration()
+ else:
+ self.i += 1
+ return self.l[self.i]
+
+ def get(self, i = None):
+ return self.l[self.i] if not i else self.l[i]
+
+ def back(self) -> NoReturn:
+ if self.i <= 0:
+ self.i = -1
+ else:
+ self.i -= 1
+
+ def peek(self) -> T:
+ if self.i == len(self.l):
+ raise StopIteration()
+ else:
+ return self.l[self.i + 1]
diff --git a/compilador/parse/base.py b/compilador/parse/base.py
index a8f6f8a..49742e6 100644
--- a/compilador/parse/base.py
+++ b/compilador/parse/base.py
@@ -7,12 +7,13 @@ from errors import Error
from typing import NoReturn
from more_itertools import seekable
+from nanoiter import NanoIter
from tabla import TablaLex, Token
from errors import Error
class BaseParser:
- def __init__(self, iterador: seekable):
- self.iterador: seekable = iterador
+ def __init__(self, iterador: NanoIter):
+ self.iterador: NanoIter = iterador
''' Requires the next token to have a matching ltok. Returns that
token, or an error. '''
@@ -49,10 +50,10 @@ class BaseParser:
return tok
def lex(self):
- return next(self.iterador)
+ return self.iterador.next()
def unlex(self):
- self.iterador.seek(-1)
+ self.iterador.back()
''' Returns a syntax error if cond is false and void otherwise '''
def synassert(self, cond: bool, msg: str) -> (Error | NoReturn):
diff --git a/compilador/parse/decl.py b/compilador/parse/decl.py
index 73f8580..4a752f0 100644
--- a/compilador/parse/decl.py
+++ b/compilador/parse/decl.py
@@ -54,7 +54,7 @@ class ParseDecl:
return ident
# Prototipo
- proto = ParseType(self.parser).prototype()
+ proto = ParseType(self.parser).prototype(_type)
if type(proto) is Error:
return proto
@@ -70,12 +70,16 @@ class ParseDecl:
# Parses a declaration.
def decl(self) -> (Decl | Error):
- toks = [Token.BOOLEAN, Token.CHAR, Token.INT, Token.STRING, Token.VOID]
- _next = self.parser.peek(*toks)
+ toks = [Token.BOOLEAN, Token.CHAR, Token.INT, Token.STRING, Token.VOID, Token.FUNCTION]
+ _next = self.parser.want(*toks)
decl: Optional[Decl] = None
- if not _next:
+ if type(_next) is Error:
+ return _next
+ elif _next.tipo is Token.FUNCTION:
+ self.parser.unlex()
decl = self.decl_func()
else:
+ self.parser.unlex()
decl = self.decl_global()
if type(decl) is Error:
diff --git a/compilador/parse/expr.py b/compilador/parse/expr.py
index a00f3d5..23b1a61 100644
--- a/compilador/parse/expr.py
+++ b/compilador/parse/expr.py
@@ -7,6 +7,6 @@ class ParseExpr:
self.parser = parser
def expr(self) -> Expr | Error:
- next(self.parser.iterador)
+ self.parser.iterador.next()
return
diff --git a/compilador/parse/type.py b/compilador/parse/type.py
index 27b83d3..06c68d0 100644
--- a/compilador/parse/type.py
+++ b/compilador/parse/type.py
@@ -16,48 +16,36 @@ class ParseType:
return tok
return BuiltinType(tok.tipo)
- def prototype(self) -> (FuncType | Error):
+ def prototype(self, _type: Type) -> (FuncType | Error):
params: List[FuncParam] = []
- # Tipo
- tok = ParseType(self.parser)._type()
- if type(tok) is Error:
- return tok
- _type = tok
-
# (
tok = self.parser.want(Token.L_PAREN)
if type(tok) is Error:
return tok
- while True:
- tok = self.parser._try(Token.R_PAREN)
- if not tok:
- break
-
+
+ while not self.parser._try(Token.R_PAREN):
+
# Tipo
- tok = ParseType(self.parser)._type()
- if type(tok) is Error:
- return tok
- __type: Type = tok
+ __type = ParseType(self.parser)._type()
+ if type(__type) is Error:
+ return __type
# Identificador
- tok = self.parser.want(Token.IDENT)
- if type(tok) is Error:
- return tok
- name: str = tok
+ name = self.parser.want(Token.IDENT)
+ if type(name) is Error:
+ return name
params.append(FuncParam(name = name,
_type = __type))
# ,
- tok = self.parser._try(Token.COMMA)
- if not tok:
+ if self.parser._try(Token.COMMA):
continue
# )
- tok = self.parser.want(Token.R_PAREN)
- if type(tok) is Error:
- return tok
+ if self.parser._try(Token.R_PAREN):
+ break
return FuncType(result = _type,
params = params)
diff --git a/compilador/parser.py b/compilador/parser.py
index 82ee3c8..99cabe7 100644
--- a/compilador/parser.py
+++ b/compilador/parser.py
@@ -19,5 +19,5 @@ class Parser:
print (unit.message, file=sys.stderr)
return 1
- pprint(self.unit)
+ pprint(unit)
return 0
diff --git a/compilador/tabla.py b/compilador/tabla.py
index d0a8ffe..fb76e08 100644
--- a/compilador/tabla.py
+++ b/compilador/tabla.py
@@ -2,7 +2,9 @@ import json, os
from enum import Enum, auto
from dataclasses import dataclass
from typing import Any
-from more_itertools import seekable
+# from more_itertools import seekable
+
+from nanoiter import NanoIter
reservadas = [
'BOOLEAN',
@@ -101,7 +103,7 @@ class TablaLex:
return [t for t in self.tabla if t.nombre == nombre][0]
def iterar(self):
- return seekable(self.tabla)
+ return NanoIter(self.tabla)
def actualizar(self, nombre: str, tok: LexToken):
for i, t in enumerate(self.tabla):
diff --git a/pruebas/sintaxis2.es b/pruebas/sintaxis2.es
new file mode 100644
index 0000000..c89bee0
--- /dev/null
+++ b/pruebas/sintaxis2.es
@@ -0,0 +1,6 @@
+entero a = 10;
+entero b = 20;
+booleano c = verdadero;
+caracter d;
+funcion entero a (entero a, cadena b);
+funcion caracter b (booleano a); \ No newline at end of file