137 lines
2.8 KiB
C++
137 lines
2.8 KiB
C++
#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);
|
|
}
|
|
}
|