roza/lib/Parser.cpp

291 lines
5.2 KiB
C++
Raw Normal View History

2023-08-30 18:06:26 +00:00
#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())
{
2023-08-30 22:31:19 +00:00
m_log.fatal(m_lexer.loc(), "unexpected end");
2023-08-30 18:06:26 +00:00
}
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;
}
2023-08-30 22:31:19 +00:00
std::shared_ptr<Node> Parser::consume_or_nullptr(NodeType ty)
{
if (m_cursor >= m_lexer.size())
{
return nullptr;
}
return consume(ty);
}
2023-08-30 18:06:26 +00:00
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;
}
2023-08-30 22:31:19 +00:00
void Parser::consume_all(NodeType ty)
{
while (type_is(ty))
{
next();
}
}
std::shared_ptr<Node> Parser::consume()
{
auto ret = node();
next();
return ret;
}
2023-08-30 18:06:26 +00:00
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());
2023-08-30 22:31:19 +00:00
while (m_cursor < m_lexer.size())
2023-08-30 18:06:26 +00:00
{
root->add_child(parse_instr());
}
return root;
}
std::shared_ptr<Node> Parser::parse_instr()
{
2023-08-30 22:31:19 +00:00
auto root = parse_expr();
consume_or_nullptr(NODE_EOI);
consume_all(NODE_EOI);
2023-08-30 18:06:26 +00:00
return root;
}
std::shared_ptr<Node> Parser::parse_expr()
{
2023-08-31 09:07:03 +00:00
return parse_imp();
}
std::shared_ptr<Node> Parser::parse_imp()
{
auto lhs = parse_or();
if (type_is(NODE_IMP))
{
auto root = consume();
root->add_child(lhs);
root->add_child(parse_or());
lhs = root;
}
return lhs;
}
std::shared_ptr<Node> Parser::parse_or()
{
auto lhs = parse_and();
while (type_is(NODE_OR))
{
auto root = consume();
root->add_child(lhs);
root->add_child(parse_and());
lhs = root;
}
return lhs;
}
std::shared_ptr<Node> Parser::parse_and()
{
auto lhs = parse_term();
while (type_is(NODE_AND))
{
auto root = consume();
root->add_child(lhs);
root->add_child(parse_term());
lhs = root;
}
return lhs;
2023-08-30 22:31:19 +00:00
}
std::shared_ptr<Node> Parser::parse_term()
{
auto lhs = parse_factor();
while (type_is(NODE_ADD) || type_is(NODE_SUB))
{
auto root = consume();
root->add_child(lhs);
root->add_child(parse_factor());
lhs = root;
}
return lhs;
}
std::shared_ptr<Node> Parser::parse_factor()
{
auto lhs = parse_unop();
while (type_is(NODE_MUL)
|| type_is(NODE_DIV)
|| type_is(NODE_MOD))
{
auto root = consume();
root->add_child(lhs);
root->add_child(parse_unop());
lhs = root;
}
return lhs;
}
std::shared_ptr<Node> Parser::parse_unop()
{
if (type_is(NODE_ADD))
{
auto root = std::make_shared<Node>(NODE_UADD, "", m_lexer.loc());
next();
root->add_child(parse_pow());
return root;
}
if (type_is(NODE_SUB))
{
auto root = std::make_shared<Node>(NODE_USUB, "", m_lexer.loc());
next();
root->add_child(parse_pow());
return root;
}
2023-08-31 09:07:03 +00:00
if (type_is(NODE_NOT))
{
auto root = std::make_shared<Node>(NODE_NOT, "", m_lexer.loc());
next();
root->add_child(parse_pow());
return root;
}
2023-08-30 22:31:19 +00:00
return parse_pow();
}
std::shared_ptr<Node> Parser::parse_pow()
{
auto lhs = parse_group();
if (type_is(NODE_POW))
{
auto root = consume();
root->add_child(lhs);
root->add_child(parse_group());
lhs = root;
}
return lhs;
}
std::shared_ptr<Node> Parser::parse_group()
{
if (type_is(NODE_OPAR))
{
consume(NODE_OPAR);
auto root = parse_expr();
consume(NODE_CPAR);
return root;
}
2023-08-30 18:06:26 +00:00
return parse_base();
}
std::shared_ptr<Node> Parser::parse_base()
{
2023-08-31 09:07:03 +00:00
if (type_is(NODE_INT)
|| type_is(NODE_BOOL))
{
return consume();
}
m_log.fatal(node()->loc(),
"unknown node '"
+ node()->string()
+ "'");
return nullptr;
2023-08-30 18:06:26 +00:00
}
std::shared_ptr<Node> Parser::parse_int()
{
auto root = consume(NODE_INT);
return root;
}
}