from typing import Optional, Any, List from jortsc.parser.lexer import Token, TokenType class ParseError(Exception): """Represents a parse error.""" pass class Reader: """Main reader class""" def __init__(self, tokens: List[Token]): self.tokens = tokens self.cur = 0 def next(self) -> Optional[Token]: """Fetch the current token then skip to the next one.""" try: token = self.tokens[self.cur] except IndexError: return None self.cur += 1 return token def _fn_read_args(reader: Reader, cur: List = None) -> List: """Recursively read the arguments of the function.""" if cur is None: cur = [] token = reader.next() if token.value == ')': return cur argtype, argname = reader.next(), reader.next() cur.append((argtype, argname)) return _fn_read_args(reader, cur) def read_function(reader: Reader): """Read a function block.""" token = reader.next() if token.type_ == TokenType.whitespace: pass else: raise ParseError('Expected whitespace') token = reader.next() fn_name = '_anonymous' fn_args = [] if token.type_ == TokenType.identifier: fn_name = token.value fn_args = _fn_read_args(reader) block = read_start(reader) elif token.value == '(': fn_args = _fn_read_args(reader) block = read_start(reader) return (fn_name, fn_args, block) def read_reserved(token: Token, reader: Reader): """Read reserved statements.""" if token.value == 'fn': return read_function(reader) def read_start(reader: Reader): """Read the start of a program.""" token = reader.next() ast = [] res = [] print('cur', token) if token.type_ == TokenType.reserved: res = read_reserved(token, reader) ast.extend(res) return ast def syntatic(tokens: List[Token]): """Create an AST out of the tokens.""" return read_start(Reader(tokens))