summaryrefslogtreecommitdiff
path: root/parser.py
diff options
context:
space:
mode:
authorAndrew <saintruler@gmail.com>2021-07-12 16:57:10 +0400
committerAndrew <saintruler@gmail.com>2021-07-12 16:59:08 +0400
commitf078f93ba357c3ede0b109a3b9ea5e79c7a8b777 (patch)
tree132c9d46ce508e6f4a0c31300b8d95bec89d4803 /parser.py
parent49df60f32aca6428706bc895b7e48ab2d68444b5 (diff)
Added ability to call functions as a statement.
Diffstat (limited to 'parser.py')
-rw-r--r--parser.py99
1 files changed, 90 insertions, 9 deletions
diff --git a/parser.py b/parser.py
index 19fa952..f780e57 100644
--- a/parser.py
+++ b/parser.py
@@ -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