muzgen/lib/Parser.cpp

137 lines
2.8 KiB
C++
Raw Permalink Normal View History

#include "Parser.hpp"
#include "Node.hpp"
namespace muz
{
/*explicit*/ Parser::Parser()
{
}
/*virtual*/ Parser::~Parser()
{
}
std::shared_ptr<Node> Parser::parse(Lexer& lexer)
{
m_tokens = lexer.all();
m_cursor = 0;
return parse_prog();
}
int Parser::current_line()
{
if (m_cursor < m_tokens.size())
{
return m_tokens[m_cursor]->line();
}
return 0;
}
std::shared_ptr<Node> Parser::consume(std::optional<NodeType> type)
{
if (m_cursor >= m_tokens.size())
{
std::string ty_desired = NodeTypeStr[*type] + strlen("NODE_");
format_error<syntax_error>(current_line(),
"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_");
format_error<syntax_error>(current_line(),
"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<Node> Parser::parse_prog()
{
auto node = std::make_shared<Node>(NODE_PROG, current_line());
while (m_cursor < m_tokens.size())
{
node->add_child(parse_instr());
}
return node;
}
std::shared_ptr<Node> Parser::parse_instr()
{
if (next_is(NODE_DIR_IDENT))
{
return parse_dir();
}
return parse_cmd();
}
std::shared_ptr<Node> Parser::parse_dir()
{
auto node = std::make_shared<Node>(NODE_DIR, current_line());
node->add_child(consume(NODE_DIR_IDENT));
node->add_child(parse_cmd());
return node;
}
std::shared_ptr<Node> Parser::parse_cmd()
{
consume(NODE_OSQUARE);
auto node = std::make_shared<Node>(NODE_CMD, current_line());
node->add_child(consume(NODE_IDENT));
while (!next_is(NODE_CSQUARE))
{
node->add_child(parse_arg());
}
consume(NODE_CSQUARE);
return node;
}
std::shared_ptr<Node> Parser::parse_arg()
{
if (next_is(NODE_OSQUARE))
{
return parse_cmd();
}
return parse_literal();
}
std::shared_ptr<Node> Parser::parse_literal()
{
return consume(NODE_NUM);
}
}