#include "Parser.hpp" namespace wg { /*explicit*/ Parser::Parser() { } /*virtual*/ Parser::~Parser() { } std::shared_ptr Parser::parse(std::vector> const& tokens) { m_cursor = 0; m_tokens = tokens; return parse_prog(); } Loc Parser::loc() const { if (m_cursor >= m_tokens.size()) { return Loc {}; } return m_tokens[m_cursor]->loc(); } std::shared_ptr Parser::consume(NodeType type) { if (m_cursor >= m_tokens.size()) { std::stringstream ss; ss << "type mismatch, expected '" << (NodeTypeStr[type] + strlen("NODE_")) << "', got nothing."; loc().error(ss); } auto current = m_tokens[m_cursor]; if (current->type() != type) { std::stringstream ss; ss << "type mismatch, expected '" << (NodeTypeStr[type] + strlen("NODE_")) << "', got '" << (NodeTypeStr[current->type()] + strlen("NODE_")) << "'"; loc().error(ss); } else { return consume(); } return nullptr; } std::shared_ptr Parser::consume() { WG_ASSERT(m_cursor < m_tokens.size(), "cannot consume"); auto node = m_tokens[m_cursor]; m_cursor++; return node; } bool Parser::type_is(NodeType type, int lookahead) { if (m_cursor + lookahead >= m_tokens.size()) { return false; } return m_tokens[m_cursor + lookahead]->type() == type; } bool Parser::type_isnt(NodeType type, int lookahead) { return !type_is(type, lookahead); } std::shared_ptr Parser::make_node(NodeType type) const { return std::make_shared(type, "", loc()); } std::shared_ptr Parser::parse_prog() { auto node = std::make_shared(NODE_PROG, "", Loc {}); while (m_cursor < m_tokens.size()) { node->add_child(parse_instr()); } return node; } std::shared_ptr Parser::parse_instr() { if (type_is(NODE_HASH)) { return parse_dir(); } auto expr = parse_expr(); consume(NODE_SEMICOLON); return expr; } std::shared_ptr Parser::parse_dir() { auto node = make_node(NODE_DIR); consume(NODE_HASH); node->add_child(consume(NODE_IDENT)); node->add_child(parse_expr()); return node; } std::shared_ptr Parser::parse_expr() { return parse_addsub(); } std::shared_ptr Parser::parse_addsub() { auto lhs = parse_muldivmod(); while (type_is(NODE_ADD) || type_is(NODE_SUB)) { auto node = consume(); node->add_child(lhs); node->add_child(parse_muldivmod()); lhs = node; } return lhs; } std::shared_ptr Parser::parse_muldivmod() { auto lhs = parse_literal(); while (type_is(NODE_MUL) || type_is(NODE_DIV) || type_is(NODE_MOD)) { auto node = consume(); node->add_child(lhs); node->add_child(parse_literal()); lhs = node; } return lhs; } std::shared_ptr Parser::parse_literal() { if (type_is(NODE_INT) || type_is(NODE_IDENT)) { return consume(); } // Groups if (type_is(NODE_OPAR)) { consume(NODE_OPAR); auto expr = parse_expr(); consume(NODE_CPAR); return expr; } loc().error(std::string() + "unknown literal '" + (NodeTypeStr[m_tokens[m_cursor]->type()] + strlen("NODE_")) + "'"); return nullptr; } }