diff --git a/examples/hello.jt b/examples/hello.jt index efed740..4bc50f6 100644 --- a/examples/hello.jt +++ b/examples/hello.jt @@ -5,6 +5,7 @@ import io // main can return int or void, void mains are handled by jortsc fn main () -> int { - io.puts("pants") + // todo: put it back to io.puts + ioputs("pants") 0 } diff --git a/jortsc/parser/ast_nodes.py b/jortsc/parser/ast_nodes.py index 18c4d7f..bff1c05 100644 --- a/jortsc/parser/ast_nodes.py +++ b/jortsc/parser/ast_nodes.py @@ -27,3 +27,19 @@ class Identifier: @dataclass class Import: module: str + + +@dataclass +class String: + value: str + + +@dataclass +class Number: + value: str + + +@dataclass +class FunctionCall: + function: str + args: list diff --git a/jortsc/parser/lexer.py b/jortsc/parser/lexer.py index 9405713..7d61ff7 100644 --- a/jortsc/parser/lexer.py +++ b/jortsc/parser/lexer.py @@ -13,6 +13,7 @@ class TokenType(Enum): comment_end = auto() whitespace = auto() number = auto() + string = auto() @dataclass @@ -50,7 +51,7 @@ TOKENS = [ (r'\-\>', TokenType.reserved), (r'\.', TokenType.reserved), - (r'\"[^\n]*\"', TokenType.reserved), + (r'\"[^\n]*\"', TokenType.string), # basic math ops (r'[\+\-\/\*]', TokenType.reserved), diff --git a/jortsc/parser/syntatic.py b/jortsc/parser/syntatic.py index f6d118a..7e9bc62 100644 --- a/jortsc/parser/syntatic.py +++ b/jortsc/parser/syntatic.py @@ -2,7 +2,8 @@ from typing import Optional, Any, List from jortsc.parser.lexer import Token, TokenType from jortsc.parser.ast_nodes import ( - Function, TypedVar, Identifier, Import, ReturnType + Function, TypedVar, Identifier, Import, ReturnType, String, Number, + FunctionCall ) @@ -18,7 +19,8 @@ class Reader: self.cur = 0 def __repr__(self): - return f'' + return (f'') def peek(self) -> Optional[Token]: """Peek at the current token.""" @@ -168,6 +170,34 @@ def read_reserved(token: Token, reader: Reader): return handler(reader) +def read_value(token: Token, _reader: Reader): + """Read a given value""" + if token.type_ == TokenType.string: + return String(token.value) + elif token.type_ == TokenType.number: + return Number(token.value) + + +def read_statement(token: Token, reader: Reader): + """Read a statement""" + # token is an identifier, so first check for a function call + + # TODO: handle more things than a function call + call_fn_name = token.value + token = reader.expect_val('(') + res = [] + + while True: + token = reader.next_safe() + + if token.value == ')': + break + + res.append(read_value(token, reader)) + + return FunctionCall(call_fn_name, res) + + def read_start(reader: Reader): """Read the start of a program.""" print('reader', reader) @@ -181,8 +211,6 @@ def read_start(reader: Reader): ast = [] res = [] - print('cur', token) - # handle blocks if token.value == '{': # next can be a whitespace, or a } @@ -193,10 +221,12 @@ def read_start(reader: Reader): if token.type_ == TokenType.whitespace: # keep going on reading while True: - token = reader.next() - print(token) + token = reader.peek() + print('block append', token) if token.value == '}': + print('block end') + reader.next() break res.extend(read_start(reader)) @@ -211,7 +241,9 @@ def read_start(reader: Reader): return [] elif token.type_ == TokenType.identifier: - res = [Identifier(token.value)] + res = read_statement(token, reader) + else: + res = read_value(token, reader) ast.append(res) return ast @@ -228,13 +260,9 @@ def read_loop(reader: Reader): if ast is None: break - try: - inner = ast[0] - except IndexError: - inner = None + # TODO: better ast cleanup - if ast and not inner: - final_ast.append(ast) + final_ast.append(ast) return final_ast