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

241 lines
5.0 KiB
C++
Raw Normal View History

2023-09-09 13:09:43 +00:00
#include "Parser.hpp"
namespace jk
{
/*explicit*/ Parser::Parser(Logger& logger, std::shared_ptr<Lexer> lexer)
: m_logger { logger }
, m_lexer { lexer }
{
}
/*virtual*/ Parser::~Parser()
{
}
2023-09-09 22:03:28 +00:00
std::shared_ptr<Node> Parser::parse(std::string const& source)
2023-09-09 13:09:43 +00:00
{
2023-09-09 22:03:28 +00:00
std::shared_ptr<Node> tok;
m_cursor = 0;
m_lexer->scan(source);
while ( (tok=m_lexer->next()) )
{
m_tokens.push_back(tok);
}
if (m_tokens.empty())
{
return std::make_shared<Node>(NODE_PROG, "",
Loc {m_lexer->loc().path(), 1, 1});
}
return parse_prog();
}
std::shared_ptr<Node> Parser::current() const
{
assert(m_cursor < m_tokens.size());
return m_tokens[m_cursor];
}
Loc Parser::loc() const
{
return current()->loc();
}
std::shared_ptr<Node> Parser::consume()
{
assert(m_cursor < m_tokens.size());
auto tok = m_tokens[m_cursor];
m_cursor++;
return tok;
}
std::shared_ptr<Node> Parser::consume(NodeType type)
{
assert(m_cursor < m_tokens.size());
if (m_tokens[m_cursor]->type() != type)
{
std::stringstream ss;
ss << "expected '"
<< std::string(NodeTypeStr[type])
.substr(std::string("NODE_").size())
<< "', got '"
<< std::string(NodeTypeStr[m_tokens[m_cursor]->type()])
.substr(std::string("NODE_").size())
<< "'";
m_logger.log<syntax_error>(LOG_ERROR,
m_tokens[m_cursor]->loc(),
ss.str());
}
return consume();
}
bool Parser::type_is(NodeType type, int lookahead) const
{
if (m_cursor + lookahead >= m_tokens.size())
{
return false;
}
return m_tokens[m_cursor + lookahead]->type() == type;
}
std::shared_ptr<Node> Parser::parse_prog()
{
auto root = std::make_shared<Node>(NODE_PROG, "", loc());
while (m_cursor < m_tokens.size())
{
2023-09-10 06:06:34 +00:00
root->add_child(parse_expr());
2023-09-09 22:03:28 +00:00
}
return root;
}
std::shared_ptr<Node> Parser::parse_expr()
{
if (type_is(NODE_OPAR)
&& type_is(NODE_DECL, 1)
&& type_is(NODE_OPAR, 2))
{
return parse_fundecl();
}
2023-09-10 06:06:34 +00:00
if (type_is(NODE_OPAR)
&& type_is(NODE_IDENT, 1))
2023-09-09 22:03:28 +00:00
{
return parse_funcall();
}
2023-09-10 06:06:34 +00:00
if (type_is(NODE_OPAR)
&& type_is(NODE_DECL, 1))
{
return parse_vardecl();
}
if (type_is(NODE_OPAR)
&& type_is(NODE_RARROW, 1))
{
return parse_lambda();
}
2023-09-09 22:03:28 +00:00
return parse_literal();
}
2023-09-10 06:06:34 +00:00
std::shared_ptr<Node> Parser::parse_vardecl()
{
auto root = std::make_shared<Node>(NODE_VARDECL, "", loc());
consume(NODE_OPAR);
consume(NODE_DECL);
root->add_child(consume(NODE_IDENT));
root->add_child(parse_expr());
consume(NODE_CPAR);
return root;
}
std::shared_ptr<Node> Parser::parse_fundecl()
{
consume(NODE_OPAR);
consume(NODE_DECL);
consume(NODE_OPAR);
auto ident = consume(NODE_IDENT);
auto params = parse_params();
consume(NODE_CPAR);
auto body = parse_body();
consume(NODE_CPAR);
auto vardecl = std::make_shared<Node>(NODE_VARDECL, "", ident->loc());
vardecl->add_child(ident);
auto lambda = std::make_shared<Node>(NODE_LAMBDA, "", ident->loc());
lambda->add_child(params);
lambda->add_child(body);
vardecl->add_child(lambda);
return vardecl;
}
std::shared_ptr<Node> Parser::parse_lambda()
{
auto root = std::make_shared<Node>(NODE_LAMBDA, "", loc());
consume(NODE_OPAR);
consume(NODE_RARROW);
consume(NODE_OPAR);
root->add_child(parse_params());
consume(NODE_CPAR);
root->add_child(parse_body());
consume(NODE_CPAR);
return root;
}
std::shared_ptr<Node> Parser::parse_params()
{
auto root = std::make_shared<Node>(NODE_PARAMS, "", loc());
while (!type_is(NODE_CPAR))
{
root->add_child(consume(NODE_IDENT));
}
return root;
}
std::shared_ptr<Node> Parser::parse_body()
{
auto root = std::make_shared<Node>(NODE_BODY, "", loc());
while (!type_is(NODE_CPAR))
{
root->add_child(parse_expr());
}
return root;
}
2023-09-09 22:03:28 +00:00
std::shared_ptr<Node> Parser::parse_funcall()
{
auto root = std::make_shared<Node>(NODE_FUNCALL, "", loc());
consume(NODE_OPAR);
while (!type_is(NODE_CPAR))
{
root->add_child(parse_expr());
}
consume(NODE_CPAR);
return root;
}
std::shared_ptr<Node> Parser::parse_literal()
{
if (type_is(NODE_INT)
2023-09-10 12:39:23 +00:00
|| type_is(NODE_BOOL)
2023-09-09 22:03:28 +00:00
|| type_is(NODE_IDENT))
{
return consume();
}
m_logger.log<syntax_error>(LOG_ERROR,
loc(),
std::string()
+ "unexpected token '"
2023-09-10 06:06:34 +00:00
+ NodeTypeStr[current()->type()]
+ "' ('"
2023-09-09 22:03:28 +00:00
+ current()->repr()
2023-09-10 06:06:34 +00:00
+ "')");
2023-09-09 22:03:28 +00:00
abort();
2023-09-09 13:09:43 +00:00
}
}