fakir/src/Parser.cpp

152 lines
2.9 KiB
C++
Raw Normal View History

#include "Parser.hpp"
#include "src/Loc.hpp"
namespace fk
{
/*explicit*/ Parser::Parser(Lexer& lexer)
: m_lexer { lexer }
{
}
/*virtual*/ Parser::~Parser()
{
}
std::shared_ptr<Node> Parser::parse(std::string const& source)
{
m_lexer.scan(source);
std::shared_ptr<Node> tok;
m_tokens.clear();
m_cursor = 0;
while ( (tok=m_lexer.next()) )
{
m_tokens.push_back(tok);
}
if (m_tokens.empty())
{
Loc loc {"???"};
auto node = std::make_shared<Node>(NODE_MODULE, "", loc);
return node;
}
return parse_module();
}
std::shared_ptr<Node> Parser::parse_module()
{
auto node = make_node(NODE_MODULE);
while (m_cursor < m_tokens.size())
{
node->add_child(parse_expr());
}
return node;
}
std::shared_ptr<Node> Parser::parse_expr()
{
if (type_any({NODE_INT, NODE_FLOAT, NODE_BOOL, NODE_STRING}))
{
return consume();
}
std::stringstream ss;
ss << "unknown expression '"
<< (NodeTypeStr[m_tokens[m_cursor]->type()] + strlen("NODE_"))
<< "'";
loc().error<syntax_error>(LOG_ERROR, ss.str());
return nullptr;
}
std::shared_ptr<Node> Parser::make_node(NodeType type)
{
return std::make_shared<Node>(type, "", loc());
}
Loc Parser::loc() const
{
if (m_cursor < m_tokens.size())
{
return m_tokens[m_cursor]->loc();
}
else if (m_tokens.empty() == false)
{
return m_tokens.back()->loc();
}
else
{
Loc loc {"???"};
return loc;
}
}
bool Parser::type_is(NodeType type) const
{
return type_all({type});
}
bool Parser::type_isnt(NodeType type) const
{
return !type_is(type);
}
bool Parser::type_all(std::vector<NodeType> types) const
{
for (size_t i=0; i<types.size(); i++)
{
if (m_cursor + i >= m_tokens.size()
|| m_tokens[m_cursor + i]->type() != types[i])
{
return false;
}
}
return true;
}
bool Parser::type_any(std::vector<NodeType> types) const
{
for (size_t i=0; i<types.size(); i++)
{
if (m_cursor < m_tokens.size()
&& m_tokens[m_cursor]->type() == types[i])
{
return true;
}
}
return false;
}
std::shared_ptr<Node> Parser::consume()
{
assert(m_cursor < m_tokens.size());
auto node = m_tokens[m_cursor];
m_cursor++;
return node;
}
std::shared_ptr<Node> Parser::consume(NodeType type)
{
if (type_isnt(type))
{
std::stringstream ss;
ss << "expected '"
<< (NodeTypeStr[type] + strlen("NODE_"))
<< "', got '"
<< (NodeTypeStr[m_tokens[m_cursor]->type()] + strlen("NODE_"))
<< "'";
loc().error<syntax_error>(LOG_ERROR, ss.str());
}
return consume();
}
}