From e7a5aa34608dfac769c648027d46c0591282fd41 Mon Sep 17 00:00:00 2001 From: John Doe Date: Mon, 17 Nov 2014 15:41:27 +0100 Subject: [PATCH] moved parser into sources (thus dramatically speeding up compilation) --- CMakeLists.txt | 3 +- include/aqua.h | 1041 +------------------------------------------------ src/interp.cpp | 5 +- src/ops.statement.cpp | 5 +- src/parser.cpp | 996 ++++++++++++++++++++++++++++++++++++++++++++++ src/parser.h | 144 +++++++ 6 files changed, 1152 insertions(+), 1042 deletions(-) create mode 100644 src/parser.cpp create mode 100644 src/parser.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 91d70b2..5348a2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ set(exename ${name}-exe) set(libname ${name}-library) set(libsources + "src/parser.cpp" "src/ops.cpp" "src/ops.statement.cpp" "src/ops.member.cpp" @@ -52,7 +53,7 @@ if(WIN32) # get rid of the 'lib' prefix on windows set_target_properties(${libname} PROPERTIES CMAKE_SHARED_LIBRARY_PREFIX "") set_target_properties(${libname} PROPERTIES CMAKE_SHARED_MODULE_PREFIX "") -endif +endif() target_link_libraries(${libname}) cotire(${libname}) diff --git a/include/aqua.h b/include/aqua.h index 081c874..fb5c8f7 100644 --- a/include/aqua.h +++ b/include/aqua.h @@ -1218,1042 +1218,7 @@ namespace Aqua } }; - template - class Parser - { - public: - using Iter = std::vector>::iterator; - using return_t = std::shared_ptr>; - - template - return_t operator()(StrIter sbegin, StrIter send) - { - auto source = std::make_shared(sbegin, send); - auto tokens = tokenize(source->begin(), source->end()); - this->begin = tokens->begin(); - this->end = tokens->end(); - i = this->begin; - accepted = this->end; - auto node = statement_list(); - node->source = source; - node->tokens = tokens; - node->root = node; - node->inject_dependencies(); - return node; - } - - template - return_t parse_expression(StrIter sbegin, StrIter send) - { - auto source = std::make_shared(sbegin, send); - auto tokens = tokenize(source->begin(), source->end()); - this->begin = tokens->begin(); - this->end = tokens->end(); - i = this->begin; - accepted = this->end; - auto node = expression(); - node->source = source; - node->tokens = tokens; - node->root = node; - node->inject_dependencies(); - return node; - } - - private: - Iter i; - Iter accepted; - - public: - Iter begin; - Iter end; - - public: - void advance() - { - if(i==end) - { - Iter last = end-1; - auto lc = Utils::LineColumn(begin->begin, last->end); - throw std::runtime_error( - std::to_string(lc.first) + ":" + - std::to_string(lc.second) + ": unexpected end of input at"); - } - else - { - ++i; - } - } - - void rewind(Iter pos) - { - i = pos; - } - - bool peek(TokenType t, int amount = 0) - { - return (((i+amount) != end) && (((i+amount)->type) == t)); - } - - bool accept(TokenType t) - { - if(i != end && i->type == t) - { - accepted = i; - advance(); - return true; - } - else - { - return false; - } - } - - bool end_of_input() - { - return (i == end); - } - - bool expect(TokenType t) - { - if(accept(t)) - { - return true; - } - else - { - i = std::min(i, end-1); - auto lc = Utils::LineColumn(begin->begin, i->begin); - throw std::runtime_error( - std::to_string(lc.first) + ":" + - std::to_string(lc.second) + ": unexpected token '" + - std::string(i->begin, i->end) + "'" - ); - return false; - } - } - - void expect(const std::string &expected) - { - i = std::min(i, end-1); - auto lc = Utils::LineColumn(begin->begin, i->begin); - throw std::runtime_error( - std::to_string(lc.first) + ":" + - std::to_string(lc.second) + ": expected " + - expected+ " but got '" + std::string(i->begin, i->end) + "'" - ); - } - - return_t variable() - { - expect(Tok_Identifier); - auto node = std::make_shared>(); - node->begin = accepted; - node->end = accepted+1; - node->name = Value(accepted->begin, accepted->end); - return std::move(node); - } - - return_t field_name() - { - expect(Tok_Identifier); - auto node = std::make_shared>(); - node->begin = accepted; - node->end = accepted+1; - node->name = Value(accepted->begin, accepted->end); - return std::move(node); - } - - return_t identifier_list() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_LeftParen); - while(!accept(Tok_RightParen)) - { - node->children.push_back(field_name()); - if(!peek(Tok_RightParen)) - { - accept(Tok_Comma); - } - } - node->end = accepted+1; - return std::move(node); - } - - return_t function() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_Function); - node->children[0] = identifier_list(); - node->children[1] = statement(); - node->end = accepted+1; - return std::move(node); - } - - return_t parse_expression() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_ParseExpression); - expect(Tok_LeftParen); - node->children[0] = expression(); - expect(Tok_RightParen); - node->end = accepted+1; - return std::move(node); - } - - return_t parse_statement() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_ParseStatement); - expect(Tok_LeftParen); - node->children[0] = expression(); - expect(Tok_RightParen); - node->end = accepted+1; - return std::move(node); - } - - return_t tree() - { - auto node = std::make_shared>(); - node->begin = i; - if(accept(Tok_Expression)) - { - expect(Tok_LeftParen); - node->children[0] = expression(); - expect(Tok_RightParen); - } - else - { - expect(Tok_Statement); - expect(Tok_LeftParen); - node->children[0] = statement(); - expect(Tok_RightParen); - } - node->end = accepted+1; - return std::move(node); - } - - return_t root() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_Root); - if(accept(Tok_LeftParen)) - { - node->children.push_back(expression()); - expect(Tok_RightParen); - } - node->end = accepted+1; - return std::move(node); - } - - return_t eval() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_Eval); - expect(Tok_LeftParen); - node->children[0] = unary_expression(); - expect(Tok_RightParen); - node->end = accepted+1; - return std::move(node); - } - - return_t type() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_TypeOf); - if(accept(Tok_LeftParen)) - { - node->children[0] = expression(); - expect(Tok_RightParen); - } - node->end = accepted+1; - return std::move(node); - } - - return_t size() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_SizeOf); - if(accept(Tok_LeftParen)) - { - node->children[0] = expression(); - expect(Tok_RightParen); - } - node->end = accepted+1; - return std::move(node); - } - - return_t do_import() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_Import); - if(accept(Tok_LeftParen)) - { - node->children[0] = expression(); - expect(Tok_RightParen); - } - node->end = accepted+1; - return std::move(node); - } - - return_t table_initializer() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_LeftBrace); - while(!accept(Tok_RightBrace)) - { - node->children.push_back(initializer_assignment_expression()); - if(!peek(Tok_RightBrace)) - { - accept(Tok_Comma); - } - } - node->end = accepted+1; - return std::move(node); - } - - return_t array_initializer() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_LeftBracket); - while(!accept(Tok_RightBracket)) - { - node->children.push_back(logical_or_expression()); - if(!peek(Tok_RightBracket)) - { - accept(Tok_Comma); - } - } - node->end = accepted+1; - return std::move(node); - } - - return_t primary_expression() - { - if (peek(Tok_Identifier) || peek(Tok_Global) || peek(Tok_Local)) - { - return variable(); - } - else if (accept(Tok_Number)) - { - auto node = std::make_shared>(); - node->begin = accepted; - node->end = accepted+1; - node->value = Value(std::stod(std::string(accepted->begin, accepted->end))); - return std::move(node); - } - else if (accept(Tok_Nil)) - { - auto node = std::make_shared>(); - node->begin = accepted; - node->end = accepted+1; - return std::move(node); - } - else if (accept(Tok_String)) - { - auto node = std::make_shared>(); - node->begin = accepted; - node->end = accepted+1; - node->value = Value(Utils::Unescape(std::string(accepted->begin+1, accepted->end-1))); - return std::move(node); - } - else if (accept(Tok_LeftParen)) - { - auto node = std::make_shared>(); - node->begin = accepted; - node->children[0] = expression(); - expect(Tok_RightParen); - node->end = accepted+1; - return std::move(node); - } - else if (peek(Tok_LeftBrace)) - { - return table_initializer(); - } - else if (peek(Tok_LeftBracket)) - { - return array_initializer(); - } - else if (peek(Tok_Expression) || peek(Tok_Statement)) - { - return tree(); - } - else if (peek(Tok_Root)) - { - return root(); - } - else if (peek(Tok_TypeOf)) - { - return type(); - } - else if (peek(Tok_Eval)) - { - return eval(); - } - else if (peek(Tok_SizeOf)) - { - return size(); - } - else if(peek(Tok_Import)) - { - return do_import(); - } - else if (peek(Tok_ParseExpression)) - { - return parse_expression(); - } - else if (peek(Tok_ParseStatement)) - { - return parse_statement(); - } - else if (peek(Tok_Function)) - { - return function(); - } - else - { - expect("primary expression"); - return nullptr; - } - } - - return_t postfix_expression() - { - Iter from = i; - return_t left = primary_expression(); - while(true) - { - if(accept(Tok_LeftBracket)) - { - return_t right = expression(); - expect(Tok_RightBracket); - if(peek(Tok_Equal) || peek(Tok_PlusEqual) || peek(Tok_DashEqual) || - peek(Tok_StarEqual) || peek(Tok_SlashEqual) || peek(Tok_PercentEqual)) - { - std::shared_ptr> node; - if(accept(Tok_Equal)) - { - node = std::make_shared>(); - } - else if(accept(Tok_PlusEqual)) - { - node = std::make_shared>(); - } - else if(accept(Tok_DashEqual)) - { - node = std::make_shared>(); - } - else if(accept(Tok_StarEqual)) - { - node = std::make_shared>(); - } - else if(accept(Tok_SlashEqual)) - { - node = std::make_shared>(); - } - else if(accept(Tok_PercentEqual)) - { - node = std::make_shared>(); - } - node->begin = from; - node->children[0] = std::move(left); - node->children[1] = std::move(right); - node->children[2] = expression(); - node->end = accepted+1; - left = std::move(node); - } - else - { - auto node = std::make_shared>(); - node->begin = from; - node->children[0] = std::move(left); - node->children[1] = std::move(right); - node->end = accepted+1; - left = std::move(node); - } - } - else if(accept(Tok_Dot)) - { - return_t right = field_name(); - if(peek(Tok_Equal) || peek(Tok_PlusEqual) || peek(Tok_DashEqual) || - peek(Tok_StarEqual) || peek(Tok_SlashEqual) || peek(Tok_PercentEqual)) - { - std::shared_ptr> node; - if(accept(Tok_Equal)) - { - node = std::make_shared>(); - } - else if(accept(Tok_PlusEqual)) - { - node = std::make_shared>(); - } - else if(accept(Tok_DashEqual)) - { - node = std::make_shared>(); - } - else if(accept(Tok_StarEqual)) - { - node = std::make_shared>(); - } - else if(accept(Tok_SlashEqual)) - { - node = std::make_shared>(); - } - else if(accept(Tok_PercentEqual)) - { - node = std::make_shared>(); - } - node->begin = from; - node->children[0] = std::move(left); - node->children[1] = std::move(right); - node->children[2] = expression(); - node->end = accepted+1; - left = std::move(node); - } - else if(accept(Tok_LeftParen)) - { - auto node = std::make_shared>(); - node->begin = from; - node->children.push_back(std::move(left)); - node->children.push_back(std::move(right)); - while(!accept(Tok_RightParen)) - { - node->children.push_back(expression()); - if(!peek(Tok_RightParen)) - { - accept(Tok_Comma); - } - } - node->end = accepted+1; - left = std::move(node); - } - else - { - auto node = std::make_shared>(); - node->begin = from; - node->children[0] = std::move(left); - node->children[1] = std::move(right); - node->end = accepted+1; - left = std::move(node); - } - } - else if(accept(Tok_LeftParen)) - { - auto node = std::make_shared>(); - node->begin = from; - node->children.push_back(std::move(left)); - while(!accept(Tok_RightParen)) - { - node->children.push_back(expression()); - if(!peek(Tok_RightParen)) - { - accept(Tok_Comma); - } - } - node->end = accepted+1; - left = std::move(node); - } - else - { - return std::move(left); - } - } - } - - return_t unary_expression() - { - if(accept(Tok_Plus) || accept(Tok_Dash) || accept(Tok_Not)) - { - using node_t = std::shared_ptr>; - node_t node; - switch(accepted->type) - { - case Tok_Plus: - node = node_t(new UnaryPlusExpression); - break; - case Tok_Dash: - node = node_t(new UnaryMinusExpression); - break; - case Tok_Not: - node = node_t(new UnaryNotExpression); - break; - default: - break; - } - node->begin = accepted; - node->children[0] = postfix_expression(); - node->end = accepted+1; - return std::move(node); - } - else - { - return postfix_expression(); - } - } - - return_t multiplicative_expression() - { - Iter from = i; - return_t left = unary_expression(); - if(accept(Tok_Star) || accept(Tok_Slash) || accept(Tok_Percent)) - { - using node_t = std::shared_ptr>; - node_t node; - switch(accepted->type) - { - case Tok_Star: - node = node_t(new MultiplyExpression); - break; - case Tok_Slash: - node = node_t(new DivideExpression); - break; - case Tok_Percent: - node = node_t(new ModuloExpression); - break; - default: - break; - } - node->begin = from; - node->children[0] = std::move(left); - node->children[1] = multiplicative_expression(); - node->end = accepted+1; - return std::move(node); - } - else - { - return std::move(left); - } - } - - return_t additive_expression() - { - Iter from = i; - return_t left = multiplicative_expression(); - if(accept(Tok_Plus) || accept(Tok_Dash)) - { - using node_t = std::shared_ptr>; - node_t node; - switch(accepted->type) - { - case Tok_Plus: - node = node_t(new AddExpression); - break; - case Tok_Dash: - node = node_t(new SubtractExpression); - break; - default: - break; - } - node->begin = from; - node->children[0] = std::move(left); - node->children[1] = additive_expression(); - node->end = accepted+1; - return std::move(node); - } - else - { - return std::move(left); - } - } - - return_t relational_expression() - { - Iter from = i; - return_t left = additive_expression(); - if(accept(Tok_Less) || accept(Tok_LessEqual) || accept(Tok_Greater) || accept(Tok_GreaterEqual)) - { - using node_t = std::shared_ptr>; - node_t node; - switch(accepted->type) - { - case Tok_Less: - node = node_t(new LessExpression); - break; - case Tok_LessEqual: - node = node_t(new LessEqualExpression); - break; - case Tok_Greater: - node = node_t(new GreaterExpression); - break; - case Tok_GreaterEqual: - node = node_t(new GreaterEqualExpression); - break; - default: - break; - } - node->begin = from; - node->children[0] = std::move(left); - node->children[1] = relational_expression(); - node->end = accepted+1; - return std::move(node); - } - else - { - return std::move(left); - } - } - - return_t equality_expression() - { - Iter from = i; - return_t left = relational_expression(); - if(accept(Tok_EqOp) || accept(Tok_NotEqual)) - { - using node_t = std::shared_ptr>; - node_t node; - switch(accepted->type) - { - case Tok_EqOp: - node = node_t(new EqualExpression); - break; - case Tok_NotEqual: - node = node_t(new NotEqualExpression); - break; - default: - break; - } - node->begin = from; - node->children[0] = std::move(left); - node->children[1] = relational_expression(); - node->end = accepted+1; - return std::move(node); - } - else - { - return std::move(left); - } - } - - return_t logical_and_expression() - { - Iter from = i; - return_t left = equality_expression(); - if(accept(Tok_LogicalAnd)) - { - auto node = std::make_shared>(); - node->begin = from; - node->children[0] = std::move(left); - node->children[1] = equality_expression(); - node->end = accepted+1; - return std::move(node); - } - else - { - return std::move(left); - } - } - - return_t logical_or_expression() - { - Iter from = i; - return_t left = logical_and_expression(); - if(accept(Tok_LogicalOr)) - { - auto node = std::make_shared>(); - node->begin = from; - node->children[0] = std::move(left); - node->children[1] = logical_and_expression(); - node->end = accepted+1; - return std::move(node); - } - else - { - return std::move(left); - } - } - - return_t assignment_expression() - { - Iter from = i; - if(peek(Tok_Global) || peek(Tok_Local)) - { - bool global = accept(Tok_Global); - bool local = accept(Tok_Local); - return_t left = field_name(); - if(accept(Tok_Equal)) - { - std::shared_ptr> node; - node = - global ? - std::make_shared>() - : - local ? - std::make_shared>() - : - std::make_shared>(); - node->begin = from; - node->children[0] = std::move(left); - node->children[1] = assignment_expression(); - node->end = accepted+1; - return std::move(node); - } - } - else if(peek(Tok_Identifier)) - { - return_t left = field_name(); - std::shared_ptr> node; - if(accept(Tok_Equal)) - { - node = std::make_shared>(); - } - else if(accept(Tok_PlusEqual)) - { - node = std::make_shared>(); - } - else if(accept(Tok_DashEqual)) - { - node = std::make_shared>(); - } - else if(accept(Tok_StarEqual)) - { - node = std::make_shared>(); - } - else if(accept(Tok_SlashEqual)) - { - node = std::make_shared>(); - } - else if(accept(Tok_PercentEqual)) - { - node = std::make_shared>(); - } - else - { - rewind(from); - return logical_or_expression(); - } - node->begin = from; - node->children[0] = std::move(left); - node->children[1] = assignment_expression(); - node->end = accepted+1; - return std::move(node); - } - rewind(from); - return logical_or_expression(); - } - - return_t initializer_assignment_expression() - { - auto node = std::make_shared>(); - node->begin = i; - node->children.push_back(logical_or_expression()); - if(accept(Tok_Equal)) - { - node->children.push_back(logical_or_expression()); - } - node->end = accepted+1; - return std::move(node); - } - - return_t expression() - { - return assignment_expression(); - } - - return_t block() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_LeftBrace); - node->children[0] = statement_list(); - expect(Tok_RightBrace); - node->end = accepted+1; - return std::move(node); - } - - return_t if_statement() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_If); - expect(Tok_LeftParen); - node->children.push_back(expression()); - expect(Tok_RightParen); - node->children.push_back(statement()); - if(accept(Tok_Else)) - { - node->children.push_back(statement()); - } - node->end = accepted+1; - return std::move(node); - } - - return_t while_statement() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_While); - expect(Tok_LeftParen); - node->children[0] = expression(); - expect(Tok_RightParen); - node->children[1] = statement(); - node->end = accepted+1; - return std::move(node); - } - - return_t nop() - { - auto node = std::make_shared>(); - node->begin = i; - node->end = i; - return std::move(node); - } - - return_t for_statement() - { - Iter from = i; - expect(Tok_For); - expect(Tok_LeftParen); - if(peek(Tok_Identifier) && (peek(Tok_Comma, 1) || peek(Tok_Colon, 1))) - { - auto node = std::make_shared>(); - node->begin = from; - node->children.push_back(field_name()); - if(accept(Tok_Comma)) - { - node->children.push_back(field_name()); - } - expect(Tok_Colon); - node->children.push_back(expression()); - expect(Tok_RightParen); - node->children.push_back(statement()); - node->end = accepted+1; - return std::move(node); - } - else - { - auto node = std::make_shared>(); - node->begin = from; - if(accept(Tok_Semicolon)) - { - node->children.push_back(nop()); - } - else - { - node->children.push_back(expression()); - expect(Tok_Semicolon); - } - if(accept(Tok_Semicolon)) - { - node->children.push_back(nop()); - } - else - { - node->children.push_back(expression()); - expect(Tok_Semicolon); - } - if(accept(Tok_RightParen)) - { - node->children.push_back(nop()); - } - else - { - node->children.push_back(expression()); - expect(Tok_RightParen); - } - node->children.push_back(statement()); - node->end = accepted+1; - return std::move(node); - } - } - - return_t break_statement() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_Break); - accept(Tok_Semicolon); - node->end = accepted+1; - return std::move(node); - } - - return_t continue_statement() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_Continue); - accept(Tok_Semicolon); - node->end = accepted+1; - return std::move(node); - } - - return_t return_statement() - { - auto node = std::make_shared>(); - node->begin = i; - expect(Tok_Return); - if(accept(Tok_Semicolon)) - { - node->end = accepted+1; - return std::move(node); - } - node->children.push_back(expression()); - accept(Tok_Semicolon); - node->end = accepted+1; - return std::move(node); - } - - return_t statement() - { - if(peek(Tok_LeftBrace)) - { - return block(); - } - else if (peek(Tok_If)) - { - return if_statement(); - } - else if (peek(Tok_While)) - { - return while_statement(); - } - else if (peek(Tok_For)) - { - return for_statement(); - } - else if (peek(Tok_Return)) - { - return return_statement(); - } - else if (peek(Tok_Continue)) - { - return continue_statement(); - } - else if (peek(Tok_Break)) - { - return break_statement(); - } - else - { - auto node = std::make_shared>(); - node->begin = i; - node->children[0] = expression(); - accept(Tok_Semicolon); - node->end = accepted+1; - return std::move(node); - } - } - return_t statement_list() - { - auto node = std::make_shared>(); - node->begin = i; - while(!end_of_input() && !peek(Tok_RightBrace)) - { - node->children.push_back(statement()); - } - node->end = accepted+1; - return std::move(node); - } - }; + class Parser; } template class Table; @@ -2892,7 +1857,7 @@ namespace Aqua using Environment = std::shared_ptr>; using EnvStack = std::vector; using FunStack = std::vector; - using ParserInstance = Internal::Parser; + using ParserInstance = Internal::Parser; using ModulePath = std::vector; using FuncProto = std::function&)>; @@ -2927,7 +1892,7 @@ namespace Aqua }; private: - ParserInstance m_parser; + ParserInstance* m_parser; std::vector m_function_stack; std::vector> m_scopes; EnvStack m_envstack; diff --git a/src/interp.cpp b/src/interp.cpp index 926d160..7ab9cb9 100644 --- a/src/interp.cpp +++ b/src/interp.cpp @@ -1,6 +1,7 @@ #include "private.h" #include "builtin.h" +#include "parser.h" namespace Aqua { @@ -154,6 +155,7 @@ namespace Aqua Interpreter::Interpreter() { + m_parser = new Internal::Parser; beginFunctionScope(); populate_modpath(*this); setGlobal(Value("true"), Value(Value::NumberType(1))); @@ -180,6 +182,7 @@ namespace Aqua Interpreter::~Interpreter() { endFunctionScope(); + delete m_parser; } Value Interpreter::eval(const std::string &source) @@ -208,7 +211,7 @@ namespace Aqua Value Interpreter::run(const std::string &source) { - auto root = m_parser(source.begin(), source.end()); + auto root = (*m_parser)(source.begin(), source.end()); Value result = root->accept(*this); return result; } diff --git a/src/ops.statement.cpp b/src/ops.statement.cpp index 2a799aa..c5ae63b 100644 --- a/src/ops.statement.cpp +++ b/src/ops.statement.cpp @@ -1,5 +1,6 @@ #include "private.h" +#include "parser.h" namespace Aqua { @@ -52,7 +53,7 @@ namespace Aqua error("parse argument needs to be string.", node); return Interpreter::Value(); } - return Interpreter::Value(Interpreter::Value::Type::Tree, m_parser(val.string().begin(), val.string().end())); + return Interpreter::Value(Interpreter::Value::Type::Tree, (*m_parser)(val.string().begin(), val.string().end())); } Interpreter::Value Interpreter::operator()(ParseExpression &node) @@ -63,7 +64,7 @@ namespace Aqua error("parse argument needs to be string.", node); return Interpreter::Value(); } - return Interpreter::Value(Interpreter::Value::Type::Tree, m_parser.parse_expression( + return Interpreter::Value(Interpreter::Value::Type::Tree, (*m_parser).parse_expression( val.string().begin(), val.string().end())); } diff --git a/src/parser.cpp b/src/parser.cpp new file mode 100644 index 0000000..988d75a --- /dev/null +++ b/src/parser.cpp @@ -0,0 +1,996 @@ + +#include "private.h" +#include "parser.h" + +namespace Aqua +{ + namespace Internal + { + void Parser::advance() + { + if(i==end) + { + Iter last = end-1; + auto lc = Utils::LineColumn(begin->begin, last->end); + throw std::runtime_error( + std::to_string(lc.first) + ":" + + std::to_string(lc.second) + ": unexpected end of input at"); + } + else + { + ++i; + } + } + + void Parser::rewind(Iter pos) + { + i = pos; + } + + bool Parser::peek(TokenType t, int amount) + { + return (((i+amount) != end) && (((i+amount)->type) == t)); + } + + bool Parser::accept(TokenType t) + { + if(i != end && i->type == t) + { + accepted = i; + advance(); + return true; + } + else + { + return false; + } + } + + bool Parser::end_of_input() + { + return (i == end); + } + + bool Parser::expect(TokenType t) + { + if(accept(t)) + { + return true; + } + else + { + i = std::min(i, end-1); + auto lc = Utils::LineColumn(begin->begin, i->begin); + throw std::runtime_error( + std::to_string(lc.first) + ":" + + std::to_string(lc.second) + ": unexpected token '" + + std::string(i->begin, i->end) + "'" + ); + return false; + } + } + + void Parser::expect(const std::string &expected) + { + i = std::min(i, end-1); + auto lc = Utils::LineColumn(begin->begin, i->begin); + throw std::runtime_error( + std::to_string(lc.first) + ":" + + std::to_string(lc.second) + ": expected " + + expected+ " but got '" + std::string(i->begin, i->end) + "'" + ); + } + + Parser::return_t Parser::variable() + { + expect(Tok_Identifier); + auto node = std::make_shared>(); + node->begin = accepted; + node->end = accepted+1; + node->name = Value(accepted->begin, accepted->end); + return std::move(node); + } + + Parser::return_t Parser::field_name() + { + expect(Tok_Identifier); + auto node = std::make_shared>(); + node->begin = accepted; + node->end = accepted+1; + node->name = Value(accepted->begin, accepted->end); + return std::move(node); + } + + Parser::return_t Parser::identifier_list() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_LeftParen); + while(!accept(Tok_RightParen)) + { + node->children.push_back(field_name()); + if(!peek(Tok_RightParen)) + { + accept(Tok_Comma); + } + } + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::function() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_Function); + node->children[0] = identifier_list(); + node->children[1] = statement(); + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::parse_expression() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_ParseExpression); + expect(Tok_LeftParen); + node->children[0] = expression(); + expect(Tok_RightParen); + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::parse_statement() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_ParseStatement); + expect(Tok_LeftParen); + node->children[0] = expression(); + expect(Tok_RightParen); + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::tree() + { + auto node = std::make_shared>(); + node->begin = i; + if(accept(Tok_Expression)) + { + expect(Tok_LeftParen); + node->children[0] = expression(); + expect(Tok_RightParen); + } + else + { + expect(Tok_Statement); + expect(Tok_LeftParen); + node->children[0] = statement(); + expect(Tok_RightParen); + } + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::root() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_Root); + if(accept(Tok_LeftParen)) + { + node->children.push_back(expression()); + expect(Tok_RightParen); + } + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::eval() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_Eval); + expect(Tok_LeftParen); + node->children[0] = unary_expression(); + expect(Tok_RightParen); + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::type() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_TypeOf); + if(accept(Tok_LeftParen)) + { + node->children[0] = expression(); + expect(Tok_RightParen); + } + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::size() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_SizeOf); + if(accept(Tok_LeftParen)) + { + node->children[0] = expression(); + expect(Tok_RightParen); + } + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::do_import() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_Import); + if(accept(Tok_LeftParen)) + { + node->children[0] = expression(); + expect(Tok_RightParen); + } + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::table_initializer() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_LeftBrace); + while(!accept(Tok_RightBrace)) + { + node->children.push_back(initializer_assignment_expression()); + if(!peek(Tok_RightBrace)) + { + accept(Tok_Comma); + } + } + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::array_initializer() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_LeftBracket); + while(!accept(Tok_RightBracket)) + { + node->children.push_back(logical_or_expression()); + if(!peek(Tok_RightBracket)) + { + accept(Tok_Comma); + } + } + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::primary_expression() + { + if (peek(Tok_Identifier) || peek(Tok_Global) || peek(Tok_Local)) + { + return variable(); + } + else if (accept(Tok_Number)) + { + auto node = std::make_shared>(); + node->begin = accepted; + node->end = accepted+1; + node->value = Value(std::stod(std::string(accepted->begin, accepted->end))); + return std::move(node); + } + else if (accept(Tok_Nil)) + { + auto node = std::make_shared>(); + node->begin = accepted; + node->end = accepted+1; + return std::move(node); + } + else if (accept(Tok_String)) + { + auto node = std::make_shared>(); + node->begin = accepted; + node->end = accepted+1; + node->value = Value(Utils::Unescape(std::string(accepted->begin+1, accepted->end-1))); + return std::move(node); + } + else if (accept(Tok_LeftParen)) + { + auto node = std::make_shared>(); + node->begin = accepted; + node->children[0] = expression(); + expect(Tok_RightParen); + node->end = accepted+1; + return std::move(node); + } + else if (peek(Tok_LeftBrace)) + { + return table_initializer(); + } + else if (peek(Tok_LeftBracket)) + { + return array_initializer(); + } + else if (peek(Tok_Expression) || peek(Tok_Statement)) + { + return tree(); + } + else if (peek(Tok_Root)) + { + return root(); + } + else if (peek(Tok_TypeOf)) + { + return type(); + } + else if (peek(Tok_Eval)) + { + return eval(); + } + else if (peek(Tok_SizeOf)) + { + return size(); + } + else if(peek(Tok_Import)) + { + return do_import(); + } + else if (peek(Tok_ParseExpression)) + { + return parse_expression(); + } + else if (peek(Tok_ParseStatement)) + { + return parse_statement(); + } + else if (peek(Tok_Function)) + { + return function(); + } + else + { + expect("primary expression"); + return nullptr; + } + } + + Parser::return_t Parser::postfix_expression() + { + Iter from = i; + Parser::return_t left = primary_expression(); + while(true) + { + if(accept(Tok_LeftBracket)) + { + Parser::return_t right = expression(); + expect(Tok_RightBracket); + if(peek(Tok_Equal) || peek(Tok_PlusEqual) || peek(Tok_DashEqual) || + peek(Tok_StarEqual) || peek(Tok_SlashEqual) || peek(Tok_PercentEqual)) + { + std::shared_ptr> node; + if(accept(Tok_Equal)) + { + node = std::make_shared>(); + } + else if(accept(Tok_PlusEqual)) + { + node = std::make_shared>(); + } + else if(accept(Tok_DashEqual)) + { + node = std::make_shared>(); + } + else if(accept(Tok_StarEqual)) + { + node = std::make_shared>(); + } + else if(accept(Tok_SlashEqual)) + { + node = std::make_shared>(); + } + else if(accept(Tok_PercentEqual)) + { + node = std::make_shared>(); + } + node->begin = from; + node->children[0] = std::move(left); + node->children[1] = std::move(right); + node->children[2] = expression(); + node->end = accepted+1; + left = std::move(node); + } + else + { + auto node = std::make_shared>(); + node->begin = from; + node->children[0] = std::move(left); + node->children[1] = std::move(right); + node->end = accepted+1; + left = std::move(node); + } + } + else if(accept(Tok_Dot)) + { + Parser::return_t right = field_name(); + if(peek(Tok_Equal) || peek(Tok_PlusEqual) || peek(Tok_DashEqual) || + peek(Tok_StarEqual) || peek(Tok_SlashEqual) || peek(Tok_PercentEqual)) + { + std::shared_ptr> node; + if(accept(Tok_Equal)) + { + node = std::make_shared>(); + } + else if(accept(Tok_PlusEqual)) + { + node = std::make_shared>(); + } + else if(accept(Tok_DashEqual)) + { + node = std::make_shared>(); + } + else if(accept(Tok_StarEqual)) + { + node = std::make_shared>(); + } + else if(accept(Tok_SlashEqual)) + { + node = std::make_shared>(); + } + else if(accept(Tok_PercentEqual)) + { + node = std::make_shared>(); + } + node->begin = from; + node->children[0] = std::move(left); + node->children[1] = std::move(right); + node->children[2] = expression(); + node->end = accepted+1; + left = std::move(node); + } + else if(accept(Tok_LeftParen)) + { + auto node = std::make_shared>(); + node->begin = from; + node->children.push_back(std::move(left)); + node->children.push_back(std::move(right)); + while(!accept(Tok_RightParen)) + { + node->children.push_back(expression()); + if(!peek(Tok_RightParen)) + { + accept(Tok_Comma); + } + } + node->end = accepted+1; + left = std::move(node); + } + else + { + auto node = std::make_shared>(); + node->begin = from; + node->children[0] = std::move(left); + node->children[1] = std::move(right); + node->end = accepted+1; + left = std::move(node); + } + } + else if(accept(Tok_LeftParen)) + { + auto node = std::make_shared>(); + node->begin = from; + node->children.push_back(std::move(left)); + while(!accept(Tok_RightParen)) + { + node->children.push_back(expression()); + if(!peek(Tok_RightParen)) + { + accept(Tok_Comma); + } + } + node->end = accepted+1; + left = std::move(node); + } + else + { + return std::move(left); + } + } + } + + Parser::return_t Parser::unary_expression() + { + if(accept(Tok_Plus) || accept(Tok_Dash) || accept(Tok_Not)) + { + using node_t = std::shared_ptr>; + node_t node; + switch(accepted->type) + { + case Tok_Plus: + node = node_t(new UnaryPlusExpression); + break; + case Tok_Dash: + node = node_t(new UnaryMinusExpression); + break; + case Tok_Not: + node = node_t(new UnaryNotExpression); + break; + default: + break; + } + node->begin = accepted; + node->children[0] = postfix_expression(); + node->end = accepted+1; + return std::move(node); + } + else + { + return postfix_expression(); + } + } + + Parser::return_t Parser::multiplicative_expression() + { + Iter from = i; + Parser::return_t left = unary_expression(); + if(accept(Tok_Star) || accept(Tok_Slash) || accept(Tok_Percent)) + { + using node_t = std::shared_ptr>; + node_t node; + switch(accepted->type) + { + case Tok_Star: + node = node_t(new MultiplyExpression); + break; + case Tok_Slash: + node = node_t(new DivideExpression); + break; + case Tok_Percent: + node = node_t(new ModuloExpression); + break; + default: + break; + } + node->begin = from; + node->children[0] = std::move(left); + node->children[1] = multiplicative_expression(); + node->end = accepted+1; + return std::move(node); + } + else + { + return std::move(left); + } + } + + Parser::return_t Parser::additive_expression() + { + Iter from = i; + auto left = multiplicative_expression(); + if(accept(Tok_Plus) || accept(Tok_Dash)) + { + using node_t = std::shared_ptr>; + node_t node; + switch(accepted->type) + { + case Tok_Plus: + node = node_t(new AddExpression); + break; + case Tok_Dash: + node = node_t(new SubtractExpression); + break; + default: + break; + } + node->begin = from; + node->children[0] = std::move(left); + node->children[1] = additive_expression(); + node->end = accepted+1; + return std::move(node); + } + else + { + return std::move(left); + } + } + + Parser::return_t Parser::relational_expression() + { + Iter from = i; + auto left = additive_expression(); + if(accept(Tok_Less) || accept(Tok_LessEqual) || accept(Tok_Greater) || accept(Tok_GreaterEqual)) + { + using node_t = std::shared_ptr>; + node_t node; + switch(accepted->type) + { + case Tok_Less: + node = node_t(new LessExpression); + break; + case Tok_LessEqual: + node = node_t(new LessEqualExpression); + break; + case Tok_Greater: + node = node_t(new GreaterExpression); + break; + case Tok_GreaterEqual: + node = node_t(new GreaterEqualExpression); + break; + default: + break; + } + node->begin = from; + node->children[0] = std::move(left); + node->children[1] = relational_expression(); + node->end = accepted+1; + return std::move(node); + } + else + { + return std::move(left); + } + } + + Parser::return_t Parser::equality_expression() + { + Iter from = i; + auto left = relational_expression(); + if(accept(Tok_EqOp) || accept(Tok_NotEqual)) + { + using node_t = std::shared_ptr>; + node_t node; + switch(accepted->type) + { + case Tok_EqOp: + node = node_t(new EqualExpression); + break; + case Tok_NotEqual: + node = node_t(new NotEqualExpression); + break; + default: + break; + } + node->begin = from; + node->children[0] = std::move(left); + node->children[1] = relational_expression(); + node->end = accepted+1; + return std::move(node); + } + else + { + return std::move(left); + } + } + + Parser::return_t Parser::logical_and_expression() + { + Iter from = i; + auto left = equality_expression(); + if(accept(Tok_LogicalAnd)) + { + auto node = std::make_shared>(); + node->begin = from; + node->children[0] = std::move(left); + node->children[1] = equality_expression(); + node->end = accepted+1; + return std::move(node); + } + else + { + return std::move(left); + } + } + + Parser::return_t Parser::logical_or_expression() + { + Iter from = i; + auto left = logical_and_expression(); + if(accept(Tok_LogicalOr)) + { + auto node = std::make_shared>(); + node->begin = from; + node->children[0] = std::move(left); + node->children[1] = logical_and_expression(); + node->end = accepted+1; + return std::move(node); + } + else + { + return std::move(left); + } + } + + Parser::return_t Parser::assignment_expression() + { + Iter from = i; + if(peek(Tok_Global) || peek(Tok_Local)) + { + bool global = accept(Tok_Global); + bool local = accept(Tok_Local); + auto left = field_name(); + if(accept(Tok_Equal)) + { + std::shared_ptr> node; + node = + global ? + std::make_shared>() + : + local ? + std::make_shared>() + : + std::make_shared>(); + node->begin = from; + node->children[0] = std::move(left); + node->children[1] = assignment_expression(); + node->end = accepted+1; + return std::move(node); + } + } + else if(peek(Tok_Identifier)) + { + auto left = field_name(); + std::shared_ptr> node; + if(accept(Tok_Equal)) + { + node = std::make_shared>(); + } + else if(accept(Tok_PlusEqual)) + { + node = std::make_shared>(); + } + else if(accept(Tok_DashEqual)) + { + node = std::make_shared>(); + } + else if(accept(Tok_StarEqual)) + { + node = std::make_shared>(); + } + else if(accept(Tok_SlashEqual)) + { + node = std::make_shared>(); + } + else if(accept(Tok_PercentEqual)) + { + node = std::make_shared>(); + } + else + { + rewind(from); + return logical_or_expression(); + } + node->begin = from; + node->children[0] = std::move(left); + node->children[1] = assignment_expression(); + node->end = accepted+1; + return std::move(node); + } + rewind(from); + return logical_or_expression(); + } + + Parser::return_t Parser::initializer_assignment_expression() + { + auto node = std::make_shared>(); + node->begin = i; + node->children.push_back(logical_or_expression()); + if(accept(Tok_Equal)) + { + node->children.push_back(logical_or_expression()); + } + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::expression() + { + return assignment_expression(); + } + + Parser::return_t Parser::block() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_LeftBrace); + node->children[0] = statement_list(); + expect(Tok_RightBrace); + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::if_statement() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_If); + expect(Tok_LeftParen); + node->children.push_back(expression()); + expect(Tok_RightParen); + node->children.push_back(statement()); + if(accept(Tok_Else)) + { + node->children.push_back(statement()); + } + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::while_statement() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_While); + expect(Tok_LeftParen); + node->children[0] = expression(); + expect(Tok_RightParen); + node->children[1] = statement(); + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::nop() + { + auto node = std::make_shared>(); + node->begin = i; + node->end = i; + return std::move(node); + } + + Parser::return_t Parser::for_statement() + { + Iter from = i; + expect(Tok_For); + expect(Tok_LeftParen); + if(peek(Tok_Identifier) && (peek(Tok_Comma, 1) || peek(Tok_Colon, 1))) + { + auto node = std::make_shared>(); + node->begin = from; + node->children.push_back(field_name()); + if(accept(Tok_Comma)) + { + node->children.push_back(field_name()); + } + expect(Tok_Colon); + node->children.push_back(expression()); + expect(Tok_RightParen); + node->children.push_back(statement()); + node->end = accepted+1; + return std::move(node); + } + else + { + auto node = std::make_shared>(); + node->begin = from; + if(accept(Tok_Semicolon)) + { + node->children.push_back(nop()); + } + else + { + node->children.push_back(expression()); + expect(Tok_Semicolon); + } + if(accept(Tok_Semicolon)) + { + node->children.push_back(nop()); + } + else + { + node->children.push_back(expression()); + expect(Tok_Semicolon); + } + if(accept(Tok_RightParen)) + { + node->children.push_back(nop()); + } + else + { + node->children.push_back(expression()); + expect(Tok_RightParen); + } + node->children.push_back(statement()); + node->end = accepted+1; + return std::move(node); + } + } + + Parser::return_t Parser::break_statement() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_Break); + accept(Tok_Semicolon); + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::continue_statement() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_Continue); + accept(Tok_Semicolon); + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::return_statement() + { + auto node = std::make_shared>(); + node->begin = i; + expect(Tok_Return); + if(accept(Tok_Semicolon)) + { + node->end = accepted+1; + return std::move(node); + } + node->children.push_back(expression()); + accept(Tok_Semicolon); + node->end = accepted+1; + return std::move(node); + } + + Parser::return_t Parser::statement() + { + if(peek(Tok_LeftBrace)) + { + return block(); + } + else if (peek(Tok_If)) + { + return if_statement(); + } + else if (peek(Tok_While)) + { + return while_statement(); + } + else if (peek(Tok_For)) + { + return for_statement(); + } + else if (peek(Tok_Return)) + { + return return_statement(); + } + else if (peek(Tok_Continue)) + { + return continue_statement(); + } + else if (peek(Tok_Break)) + { + return break_statement(); + } + else + { + auto node = std::make_shared>(); + node->begin = i; + node->children[0] = expression(); + accept(Tok_Semicolon); + node->end = accepted+1; + return std::move(node); + } + } + + Parser::return_t Parser::statement_list() + { + auto node = std::make_shared>(); + node->begin = i; + while(!end_of_input() && !peek(Tok_RightBrace)) + { + node->children.push_back(statement()); + } + node->end = accepted+1; + return std::move(node); + } + } +} diff --git a/src/parser.h b/src/parser.h new file mode 100644 index 0000000..229aa43 --- /dev/null +++ b/src/parser.h @@ -0,0 +1,144 @@ + +namespace Aqua +{ + namespace Internal + { + class Parser + { + public: + using FuncType = Interpreter; + using Value = Interpreter::Value; + using Iter = std::vector>::iterator; + using return_t = std::shared_ptr>; + + template + return_t operator()(StrIter sbegin, StrIter send) + { + auto source = std::make_shared(sbegin, send); + auto tokens = tokenize(source->begin(), source->end()); + this->begin = tokens->begin(); + this->end = tokens->end(); + i = this->begin; + accepted = this->end; + auto node = statement_list(); + node->source = source; + node->tokens = tokens; + node->root = node; + node->inject_dependencies(); + return node; + } + + template + return_t parse_expression(StrIter sbegin, StrIter send) + { + auto source = std::make_shared(sbegin, send); + auto tokens = tokenize(source->begin(), source->end()); + this->begin = tokens->begin(); + this->end = tokens->end(); + i = this->begin; + accepted = this->end; + auto node = expression(); + node->source = source; + node->tokens = tokens; + node->root = node; + node->inject_dependencies(); + return node; + } + + private: + Iter i; + Iter accepted; + + public: + Iter begin; + Iter end; + + public: + void advance(); + + void rewind(Iter pos); + + bool peek(TokenType t, int amount = 0); + + bool accept(TokenType t); + + bool end_of_input(); + + bool expect(TokenType t); + + void expect(const std::string &expected); + + return_t variable(); + + return_t field_name(); + + return_t identifier_list(); + + return_t function(); + + return_t parse_expression(); + + return_t parse_statement(); + + return_t tree(); + + return_t root(); + + return_t eval(); + + return_t type(); + + return_t size(); + + return_t do_import(); + + return_t table_initializer(); + + return_t array_initializer(); + + return_t primary_expression(); + + return_t postfix_expression(); + + return_t unary_expression(); + + return_t multiplicative_expression(); + + return_t additive_expression(); + + return_t relational_expression(); + + return_t equality_expression(); + + return_t logical_and_expression(); + + return_t logical_or_expression(); + + return_t assignment_expression(); + + return_t initializer_assignment_expression(); + + return_t expression(); + + return_t block(); + + return_t if_statement(); + + return_t while_statement(); + + return_t nop(); + + return_t for_statement(); + + return_t break_statement(); + + return_t continue_statement(); + + return_t return_statement(); + + return_t statement(); + + return_t statement_list(); + }; + } +} -- 2.11.4.GIT