From d1550ea64f0d2abf86b4bedd34ae7f7f71ccfc59 Mon Sep 17 00:00:00 2001 From: AnotherTest Date: Sun, 13 Sep 2020 15:54:33 +0430 Subject: Shell: Add support for functions This implementation does not have support for 'return' yet. --- Shell/Parser.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) (limited to 'Shell/Parser.cpp') diff --git a/Shell/Parser.cpp b/Shell/Parser.cpp index 98ea06f5f7..3b101619e8 100644 --- a/Shell/Parser.cpp +++ b/Shell/Parser.cpp @@ -167,7 +167,10 @@ RefPtr Parser::parse_sequence() break; } - auto first = parse_or_logical_sequence(); + auto first = parse_function_decl(); + + if (!first) + first = parse_or_logical_sequence(); if (!first) return var_decls; @@ -259,6 +262,90 @@ RefPtr Parser::parse_variable_decls() return create(move(variables)); } +RefPtr Parser::parse_function_decl() +{ + auto rule_start = push_start(); + + auto restore = [&] { + m_offset = rule_start->offset; + return nullptr; + }; + + consume_while(is_whitespace); + auto offset_before_name = m_offset; + auto function_name = consume_while(is_word_character); + auto offset_after_name = m_offset; + if (function_name.is_empty()) + return restore(); + + if (!expect('(')) + return restore(); + + Vector arguments; + for (;;) { + consume_while(is_whitespace); + + if (expect(')')) + break; + + auto name_offset = m_offset; + auto arg_name = consume_while(is_word_character); + if (arg_name.is_empty()) { + // FIXME: Should this be a syntax error, or just return? + return restore(); + } + arguments.append({ arg_name, { name_offset, m_offset } }); + } + + consume_while(is_whitespace); + + { + RefPtr syntax_error; + { + auto obrace_error_start = push_start(); + syntax_error = create("Expected an open brace '{' to start a function body"); + } + if (!expect('{')) { + return create( + AST::FunctionDeclaration::NameWithPosition { + move(function_name), + { offset_before_name, offset_after_name } }, + move(arguments), + move(syntax_error)); + } + } + + auto body = parse_toplevel(); + + { + RefPtr syntax_error; + { + auto cbrace_error_start = push_start(); + syntax_error = create("Expected a close brace '}' to end a function body"); + } + if (!expect('}')) { + if (body) + body->set_is_syntax_error(*syntax_error); + else + body = move(syntax_error); + + return create( + AST::FunctionDeclaration::NameWithPosition { + move(function_name), + { offset_before_name, offset_after_name } }, + move(arguments), + move(body)); + } + } + + return create( + AST::FunctionDeclaration::NameWithPosition { + move(function_name), + { offset_before_name, offset_after_name } }, + move(arguments), + move(body)); +} + RefPtr Parser::parse_or_logical_sequence() { consume_while(is_whitespace); -- cgit v1.2.3