#include "Parser.hpp" #include "src/Loc.hpp" namespace fk { /*explicit*/ Parser::Parser(Lexer& lexer) : m_lexer { lexer } { } /*virtual*/ Parser::~Parser() { } std::shared_ptr Parser::parse(std::string const& source) { m_lexer.scan(source); std::shared_ptr tok; m_tokens.clear(); m_cursor = 0; while ( (tok=m_lexer.next()) ) { m_tokens.push_back(tok); } if (m_tokens.empty()) { Loc loc {"???"}; auto node = std::make_shared(NODE_MODULE, "", loc); return node; } return parse_module(); } std::shared_ptr Parser::parse_module() { auto node = make_node(NODE_MODULE); while (m_cursor < m_tokens.size()) { node->add_child(parse_expr()); } return node; } std::shared_ptr Parser::parse_expr() { if (type_any({NODE_INT, NODE_FLOAT, NODE_BOOL, NODE_STRING})) { return consume(); } std::stringstream ss; ss << "unknown expression '" << (NodeTypeStr[m_tokens[m_cursor]->type()] + strlen("NODE_")) << "'"; loc().error(LOG_ERROR, ss.str()); return nullptr; } std::shared_ptr Parser::make_node(NodeType type) { return std::make_shared(type, "", loc()); } Loc Parser::loc() const { if (m_cursor < m_tokens.size()) { return m_tokens[m_cursor]->loc(); } else if (m_tokens.empty() == false) { return m_tokens.back()->loc(); } else { Loc loc {"???"}; return loc; } } bool Parser::type_is(NodeType type) const { return type_all({type}); } bool Parser::type_isnt(NodeType type) const { return !type_is(type); } bool Parser::type_all(std::vector types) const { for (size_t i=0; i= m_tokens.size() || m_tokens[m_cursor + i]->type() != types[i]) { return false; } } return true; } bool Parser::type_any(std::vector types) const { for (size_t i=0; itype() == types[i]) { return true; } } return false; } std::shared_ptr Parser::consume() { assert(m_cursor < m_tokens.size()); auto node = m_tokens[m_cursor]; m_cursor++; return node; } std::shared_ptr Parser::consume(NodeType type) { if (type_isnt(type)) { std::stringstream ss; ss << "expected '" << (NodeTypeStr[type] + strlen("NODE_")) << "', got '" << (NodeTypeStr[m_tokens[m_cursor]->type()] + strlen("NODE_")) << "'"; loc().error(LOG_ERROR, ss.str()); } return consume(); } }