#include "Parser.hpp" #include "Node.hpp" namespace muz { /*explicit*/ Parser::Parser() { } /*virtual*/ Parser::~Parser() { } std::shared_ptr Parser::parse(Lexer& lexer) { m_tokens = lexer.all(); m_cursor = 0; return parse_prog(); } std::shared_ptr Parser::consume(std::optional type) { if (m_cursor >= m_tokens.size()) { std::string ty_desired = NodeTypeStr[*type] + strlen("NODE_"); throw syntax_error {"unexpected end: expected <" + ty_desired + ">, got nothing."}; } auto node = m_tokens[m_cursor]; if (type && node->type() != *type) { std::string ty_got = NodeTypeStr[node->type()] + strlen("NODE_"); std::string ty_desired = NodeTypeStr[*type] + strlen("NODE_"); throw syntax_error {"expected <" + ty_desired + ">, got <" + ty_got + ">."}; } m_cursor++; return node; } NodeType Parser::peek(size_t lookahead) const { return m_tokens[m_cursor + lookahead]->type(); } bool Parser::next_is(NodeType type, size_t lookahead) const { if (m_cursor + lookahead >= m_tokens.size()) { return false; } return peek(lookahead) == type; } std::shared_ptr Parser::parse_prog() { auto node = std::make_shared(NODE_PROG); while (m_cursor < m_tokens.size()) { node->add_child(parse_instr()); } return node; } std::shared_ptr Parser::parse_instr() { if (next_is(NODE_DIR_IDENT)) { return parse_dir(); } return parse_cmd(); } std::shared_ptr Parser::parse_dir() { auto node = std::make_shared(NODE_DIR); node->add_child(consume(NODE_DIR_IDENT)); node->add_child(parse_cmd()); return node; } std::shared_ptr Parser::parse_cmd() { consume(NODE_OSQUARE); auto node = std::make_shared(NODE_CMD); node->add_child(consume(NODE_IDENT)); while (!next_is(NODE_CSQUARE)) { node->add_child(parse_arg()); } consume(NODE_CSQUARE); return node; } std::shared_ptr Parser::parse_arg() { if (next_is(NODE_OSQUARE)) { return parse_cmd(); } return parse_literal(); } std::shared_ptr Parser::parse_literal() { return consume(NODE_NUM); } }