#include "Parser.hpp" namespace jk { /*explicit*/ Parser::Parser(Logger& logger, std::shared_ptr lexer) : m_logger { logger } , m_lexer { lexer } { } /*virtual*/ Parser::~Parser() { } std::shared_ptr Parser::parse(std::string const& source) { std::shared_ptr 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_PROG, "", Loc {m_lexer->loc().path(), 1, 1}); } return parse_prog(); } std::shared_ptr Parser::current() const { assert(m_cursor < m_tokens.size()); return m_tokens[m_cursor]; } Loc Parser::loc() const { return current()->loc(); } std::shared_ptr Parser::consume() { assert(m_cursor < m_tokens.size()); auto tok = m_tokens[m_cursor]; m_cursor++; return tok; } std::shared_ptr 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(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 Parser::parse_prog() { auto root = std::make_shared(NODE_PROG, "", loc()); while (m_cursor < m_tokens.size()) { root->add_child(parse_expr()); } return root; } std::shared_ptr Parser::parse_expr() { if (type_is(NODE_OPAR) && type_is(NODE_DECL, 1) && type_is(NODE_OPAR, 2)) { return parse_fundecl(); } if (type_is(NODE_OPAR) && type_is(NODE_IDENT, 1)) { return parse_funcall(); } 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(); } return parse_literal(); } std::shared_ptr Parser::parse_vardecl() { auto root = std::make_shared(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 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_VARDECL, "", ident->loc()); vardecl->add_child(ident); auto lambda = std::make_shared(NODE_LAMBDA, "", ident->loc()); lambda->add_child(params); lambda->add_child(body); vardecl->add_child(lambda); return vardecl; } std::shared_ptr Parser::parse_lambda() { auto root = std::make_shared(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 Parser::parse_params() { auto root = std::make_shared(NODE_PARAMS, "", loc()); while (!type_is(NODE_CPAR)) { root->add_child(consume(NODE_IDENT)); } return root; } std::shared_ptr Parser::parse_body() { auto root = std::make_shared(NODE_BODY, "", loc()); while (!type_is(NODE_CPAR)) { root->add_child(parse_expr()); } return root; } std::shared_ptr Parser::parse_funcall() { auto root = std::make_shared(NODE_FUNCALL, "", loc()); consume(NODE_OPAR); while (!type_is(NODE_CPAR)) { root->add_child(parse_expr()); } consume(NODE_CPAR); return root; } std::shared_ptr Parser::parse_literal() { if (type_is(NODE_INT) || type_is(NODE_BOOL) || type_is(NODE_IDENT)) { return consume(); } m_logger.log(LOG_ERROR, loc(), std::string() + "unexpected token '" + NodeTypeStr[current()->type()] + "' ('" + current()->repr() + "')"); abort(); } }