This repository has been archived on 2023-09-09. You can view files and clone it, but cannot push or open issues/pull-requests.
skemla/lib/Parser.cpp

100 lines
2.0 KiB
C++

#include "Parser.hpp"
#include "lib/Node.hpp"
namespace sk
{
/*explicit*/ Parser::Parser(std::shared_ptr<Lexer> lexer, Logger& logger)
: m_lexer { lexer }
, m_logger { logger }
{
}
/*virtual*/ Parser::~Parser()
{
}
std::shared_ptr<Node> Parser::parse(std::string const& source)
{
m_lexer->scan(source);
std::shared_ptr<Node> node;
while ( (node = m_lexer->next()) )
{
m_tokens.push_back(node);
}
return parse_prog();
}
std::shared_ptr<Node> Parser::consume()
{
assert(m_cursor < m_tokens.size());
auto root = m_tokens[m_cursor];
m_cursor++;
return root;
}
std::shared_ptr<Node> Parser::consume(NodeType type)
{
if (type != m_tokens[m_cursor]->type())
{
std::stringstream ss;
ss << "expected '"
<< NodeTypeStr[type]
<< "' node, got '"
<< NodeTypeStr[m_tokens[m_cursor]->type()]
<< "'";
m_logger.log<syntax_error>(m_tokens[m_cursor]->loc(),
LOGGER_ERROR,
ss);
}
return consume();
}
bool Parser::type_is(NodeType type)
{
return m_cursor < m_tokens.size()
&& m_tokens[m_cursor]->type() == type;
}
Loc Parser::loc() const
{
assert(m_cursor < m_tokens.size());
return m_tokens[m_cursor]->loc();
}
std::shared_ptr<Node> Parser::parse_prog()
{
auto root = std::make_shared<Node>(NODE_PROG, "", m_lexer->loc());
while (m_cursor < m_tokens.size())
{
root->add_child(parse_builtins());
}
return root;
}
std::shared_ptr<Node> Parser::parse_builtins()
{
if (type_is(NODE_INT)
|| type_is(NODE_FLOAT)
|| type_is(NODE_BOOL)
|| type_is(NODE_STRING))
{
return consume();
}
std::stringstream ss;
ss << "unknown node of type '"
<< NodeTypeStr[m_tokens[m_cursor]->type()]
<< "'";
m_logger.log<syntax_error>(loc(), LOGGER_ERROR, ss);
return nullptr;
}
}