diff options
| author | Andrew <saintruler@gmail.com> | 2021-07-12 16:57:10 +0400 |
|---|---|---|
| committer | Andrew <saintruler@gmail.com> | 2021-07-12 16:59:08 +0400 |
| commit | f078f93ba357c3ede0b109a3b9ea5e79c7a8b777 (patch) | |
| tree | 132c9d46ce508e6f4a0c31300b8d95bec89d4803 /parser.py | |
| parent | 49df60f32aca6428706bc895b7e48ab2d68444b5 (diff) | |
Added ability to call functions as a statement.
Diffstat (limited to 'parser.py')
| -rw-r--r-- | parser.py | 99 |
1 files changed, 90 insertions, 9 deletions
@@ -7,7 +7,7 @@ class ParserError(Exception): class Node: - def __init__(self, node_type, value=None, subtype=None): + def __init__(self, node_type, *, value=None, subtype=None): self.type = node_type self.value = value self.subtype = subtype @@ -50,7 +50,7 @@ def parse_parenthesis(tokens, start): if depth == 0 and token.type == TokenType.RIGHT_PARENTHESIS: break end += 1 - node = parse_expr(tokens[start + 1: end]) + node, _ = parse_expr(tokens[start + 1: end], 0) return node, end @@ -78,7 +78,11 @@ def parse_args(tokens, start): if len(arg) != 0: args.append(arg) - return list(map(parse_expr, args)) + tmp = [] + for arg in args: + node, _ = parse_expr(arg, 0) + tmp.append(node) + return tmp def parse_expr(tokens, start): @@ -91,7 +95,8 @@ def parse_expr(tokens, start): if state == State.OPERATOR and token.type == TokenType.LEFT_PARENTHESIS: args = parse_args(tokens, i) current_node.type = NodeType.FUNCALL - current_node.value = (current_node.value, args) + current_node.left = Node(NodeType.SYMBOL, value=current_node.value) + current_node.right = Node(NodeType.ARGUMENTS, value=args) elif token.type in [TokenType.LEFT_PARENTHESIS, TokenType.NUMBER, TokenType.SYMBOL] or token.subtype == TokenType.UNARY: @@ -146,7 +151,7 @@ def parse_expr(tokens, start): raise ValueError("Not a valid expression") state = State.NAME - elif token.type == TokenType.SEMICOLON: + elif token.type in [TokenType.SEMICOLON, TokenType.COMMA]: break i += 1 @@ -205,18 +210,94 @@ def parse_let_statement(tokens: list[Token], start: int): return root_node, i +def parse_function_call(tokens: list[Token], start: int): + class FuncStates: + (WAIT_SYMBOL, WAIT_LEFT_PAR, PARSING_EXPR, WAIT_SEMICOLON, PARSE_END, *_) = range(100) + + root_node = Node(NodeType.FUNCALL) + state = FuncStates.WAIT_SYMBOL + i = start + args = [] + arg = [] + + while i < len(tokens): + token = tokens[i] + if state == FuncStates.WAIT_SYMBOL: + if token.type == TokenType.SYMBOL: + root_node.left = Node(NodeType.SYMBOL, value=token.value) + state = FuncStates.WAIT_LEFT_PAR + else: + raise ParserError(f"Waited for symbol, got {token}") + + elif state == FuncStates.WAIT_LEFT_PAR: + if token.type == TokenType.LEFT_PARENTHESIS: + state = FuncStates.PARSING_EXPR + else: + raise ParserError(f"Waited for left parenthesis, got {token}") + + elif state == FuncStates.PARSING_EXPR: + if token.type == TokenType.COMMA: + node, _ = parse_expr(arg, 0) + args.append(node) + arg.clear() + elif token.type == TokenType.RIGHT_PARENTHESIS: + node, _ = parse_expr(arg, 0) + args.append(node) + root_node.right = Node(NodeType.ARGUMENTS, value=args) + state = FuncStates.WAIT_SEMICOLON + else: + arg.append(token) + + elif state == FuncStates.WAIT_SEMICOLON: + if token.type == TokenType.SEMICOLON: + state = FuncStates.PARSE_END + break + else: + raise ParserError(f"Waited for semicolon, got {token}") + + i += 1 + + if state != FuncStates.PARSE_END: + raise ParserError("Statement ended unexpectedly") + + return root_node, i + + def parse(tokens: list[Token]): + class ParseState: + (ANY, GOT_SYMBOL, *_) = range(100) + _statements = [ [Keyword.LET, TokenType.SYMBOL, TokenType.EQUALS, "EXPR", TokenType.SEMICOLON], - [Keyword.FN, TokenType.SYMBOL, TokenType.LEFT_PARENTHESIS, "ARGS", TokenType.RIGHT_PARENTHESIS, TokenType.LEFT_BRACE, ["STATEMENTS"], TokenType.RIGHT_BRACE], + [TokenType.SYMBOL, TokenType.EQUALS, "EXPR", TokenType.SEMICOLON], + [TokenType.SYMBOL, TokenType.LEFT_PARENTHESIS, "ARGS", TokenType.RIGHT_PARENTHESIS, TokenType.SEMICOLON], + [Keyword.FN, TokenType.SYMBOL, TokenType.LEFT_PARENTHESIS, "ARGS", TokenType.RIGHT_PARENTHESIS, TokenType.LEFT_BRACE, ["STATEMENT"], TokenType.RIGHT_BRACE], ] + state = ParseState.ANY + statements = [] + symbol = None i = 0 while i < len(tokens): - if tokens[i].type == TokenType.KEYWORD and tokens[i].subtype == Keyword.LET: - node, i = parse_let_statement(tokens, i) - statements.append(node) + token = tokens[i] + + if state == ParseState.ANY: + if token.type == TokenType.KEYWORD: + if token.subtype == Keyword.LET: + node, i = parse_let_statement(tokens, i) + statements.append(node) + elif token.type == TokenType.SYMBOL: + state = ParseState.GOT_SYMBOL + + elif state == ParseState.GOT_SYMBOL: + if token.type == TokenType.LEFT_PARENTHESIS: + node, i = parse_function_call(tokens, i - 1) + statements.append(node) + state = ParseState.ANY + else: + raise ParserError("oops...") + i += 1 return statements |