152 lines
2.9 KiB
C++
152 lines
2.9 KiB
C++
#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();
|
|
}
|
|
}
|