119 lines
2.2 KiB
C++
119 lines
2.2 KiB
C++
|
#include "Parser.hpp"
|
||
|
#include "lib/Node.hpp"
|
||
|
|
||
|
namespace roza
|
||
|
{
|
||
|
/*explicit*/ Parser::Parser(Lexer& lexer, StatusLog& log)
|
||
|
: m_lexer { lexer }
|
||
|
, m_log { log }
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/*virtual*/ Parser::~Parser()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<Node> Parser::parse()
|
||
|
{
|
||
|
m_cursor = 0;
|
||
|
auto root = parse_prog();
|
||
|
|
||
|
if (m_cursor < m_lexer.size())
|
||
|
{
|
||
|
m_log.fatal(m_lexer.loc(), "unexpected end.");
|
||
|
}
|
||
|
|
||
|
return root;
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<Node> Parser::node(size_t offset) const
|
||
|
{
|
||
|
return m_lexer.get_or_nullptr(m_cursor + offset);
|
||
|
}
|
||
|
|
||
|
NodeType Parser::type(size_t offset) const
|
||
|
{
|
||
|
auto tok = m_lexer.get_or_nullptr(m_cursor + offset);
|
||
|
assert(tok);
|
||
|
return tok->type();
|
||
|
}
|
||
|
|
||
|
bool Parser::type_is(NodeType type, size_t offset) const
|
||
|
{
|
||
|
auto tok = m_lexer.get_or_nullptr(m_cursor + offset);
|
||
|
if (!tok) { return false; }
|
||
|
|
||
|
return tok->type() == type;
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<Node> Parser::consume(NodeType ty)
|
||
|
{
|
||
|
if (!type_is(ty))
|
||
|
{
|
||
|
m_log.fatal(node()->loc(),
|
||
|
std::string()
|
||
|
+ "syntax error, expected '"
|
||
|
+ NodeTypeStr[ty]
|
||
|
+ "', got '"
|
||
|
+ NodeTypeStr[type()]
|
||
|
+ "'");
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
auto ret = node();
|
||
|
next();
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void Parser::next()
|
||
|
{
|
||
|
m_cursor++;
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<Node> Parser::parse_prog()
|
||
|
{
|
||
|
if (m_lexer.size() == 0)
|
||
|
{
|
||
|
return std::make_shared<Node>(NODE_PROG, "", m_lexer.loc());
|
||
|
}
|
||
|
|
||
|
auto root = std::make_shared<Node>(NODE_PROG, "", node()->loc());
|
||
|
root->add_child(parse_instr());
|
||
|
|
||
|
while (type_is(NODE_EOI))
|
||
|
{
|
||
|
next();
|
||
|
root->add_child(parse_instr());
|
||
|
}
|
||
|
|
||
|
return root;
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<Node> Parser::parse_instr()
|
||
|
{
|
||
|
auto lhs = parse_expr();
|
||
|
|
||
|
auto root = std::make_shared<Node>(NODE_INSTR, "", lhs->loc());
|
||
|
root->add_child(lhs);
|
||
|
|
||
|
return root;
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<Node> Parser::parse_expr()
|
||
|
{
|
||
|
return parse_base();
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<Node> Parser::parse_base()
|
||
|
{
|
||
|
return parse_int();
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<Node> Parser::parse_int()
|
||
|
{
|
||
|
auto root = consume(NODE_INT);
|
||
|
return root;
|
||
|
}
|
||
|
}
|