diff options
author | AnotherTest <ali.mpfard@gmail.com> | 2020-09-13 15:54:33 +0430 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-09-14 17:40:18 +0200 |
commit | d1550ea64f0d2abf86b4bedd34ae7f7f71ccfc59 (patch) | |
tree | bad8f03044a3880923712b38e4261af8f9dbc326 /Shell/Parser.cpp | |
parent | 519aa2048ad9ca3f5d2a56906ff9feb3743bf746 (diff) | |
download | serenity-d1550ea64f0d2abf86b4bedd34ae7f7f71ccfc59.zip |
Shell: Add support for functions
This implementation does not have support for 'return' yet.
Diffstat (limited to 'Shell/Parser.cpp')
-rw-r--r-- | Shell/Parser.cpp | 89 |
1 files changed, 88 insertions, 1 deletions
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<AST::Node> 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<AST::Node> Parser::parse_variable_decls() return create<AST::VariableDeclarations>(move(variables)); } +RefPtr<AST::Node> 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<AST::FunctionDeclaration::NameWithPosition> 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<AST::Node> syntax_error; + { + auto obrace_error_start = push_start(); + syntax_error = create<AST::SyntaxError>("Expected an open brace '{' to start a function body"); + } + if (!expect('{')) { + return create<AST::FunctionDeclaration>( + AST::FunctionDeclaration::NameWithPosition { + move(function_name), + { offset_before_name, offset_after_name } }, + move(arguments), + move(syntax_error)); + } + } + + auto body = parse_toplevel(); + + { + RefPtr<AST::SyntaxError> syntax_error; + { + auto cbrace_error_start = push_start(); + syntax_error = create<AST::SyntaxError>("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>( + AST::FunctionDeclaration::NameWithPosition { + move(function_name), + { offset_before_name, offset_after_name } }, + move(arguments), + move(body)); + } + } + + return create<AST::FunctionDeclaration>( + AST::FunctionDeclaration::NameWithPosition { + move(function_name), + { offset_before_name, offset_after_name } }, + move(arguments), + move(body)); +} + RefPtr<AST::Node> Parser::parse_or_logical_sequence() { consume_while(is_whitespace); |