#include "Parser.hpp" #include "lib/Node.hpp" namespace roza { /*explicit*/ Parser::Parser(Lexer& lexer, StatusLog& log) : m_lexer { lexer } , m_log { log } { } /*virtual*/ Parser::~Parser() { } std::shared_ptr Parser::parse() { m_cursor = 0; auto root = parse_prog(); if (m_cursor < m_lexer.size()) { m_log.fatal(m_lexer.loc(), "unexpected end."); } return root; } std::shared_ptr Parser::node(size_t offset) const { return m_lexer.get_or_nullptr(m_cursor + offset); } NodeType Parser::type(size_t offset) const { auto tok = m_lexer.get_or_nullptr(m_cursor + offset); assert(tok); return tok->type(); } bool Parser::type_is(NodeType type, size_t offset) const { auto tok = m_lexer.get_or_nullptr(m_cursor + offset); if (!tok) { return false; } return tok->type() == type; } std::shared_ptr Parser::consume(NodeType ty) { if (!type_is(ty)) { m_log.fatal(node()->loc(), std::string() + "syntax error, expected '" + NodeTypeStr[ty] + "', got '" + NodeTypeStr[type()] + "'"); return nullptr; } auto ret = node(); next(); return ret; } void Parser::next() { m_cursor++; } std::shared_ptr Parser::parse_prog() { if (m_lexer.size() == 0) { return std::make_shared(NODE_PROG, "", m_lexer.loc()); } auto root = std::make_shared(NODE_PROG, "", node()->loc()); root->add_child(parse_instr()); while (type_is(NODE_EOI)) { next(); root->add_child(parse_instr()); } return root; } std::shared_ptr Parser::parse_instr() { auto lhs = parse_expr(); auto root = std::make_shared(NODE_INSTR, "", lhs->loc()); root->add_child(lhs); return root; } std::shared_ptr Parser::parse_expr() { return parse_base(); } std::shared_ptr Parser::parse_base() { return parse_int(); } std::shared_ptr Parser::parse_int() { auto root = consume(NODE_INT); return root; } }