Newer
Older
libj / modules / parser / src / parser.cpp
#include <iostream>
#include <tokenizer.hpp>
#include <parser.hpp>

namespace parser
{
    Parser::Parser(const std::vector<xtokenizer::Token> &tokens)
        : tokens(tokens), tokenIndex(0)
    {
        // NOP
    }

    Parser::~Parser()
    {
        // NOP
    }

    std::unique_ptr<Node> Parser::parse()
    {
        std::unique_ptr<Node> node = expr();
        return node;
    }

    // expr = mul ("+" mul | "-" mul)*
    std::unique_ptr<Node> Parser::expr()
    {
        std::unique_ptr<Node> node = mul();

        std::cout << "expr() : "
                  << xtokenizer::toTokenTypeSymbol(node->token.type) << ", "
                  << node->token.value.i << std::endl;

        for (;;)
        {
            if (tokens.size() <= tokenIndex)
            {
                break;
            }
            xtokenizer::Token token = tokens[tokenIndex];
            if (token.type == xtokenizer::TokenType::T_ADD)
            { // +
                tokenIndex++;
                node = Node::create(token, std::move(node), mul());
            }
            else if (token.type == xtokenizer::TokenType::T_SUB)
            { // -
                tokenIndex++;
                node = Node::create(token, std::move(node), mul());
            }
            else if (token.type == xtokenizer::TokenType::T_SPACE)
            { // 空白なら次へ
                continue;
            }
            else
            {
                break;
            }
        }
        return node;
    }

    // mul  = primary ("*" primary | "/" primary)*
    std::unique_ptr<Node> Parser::mul()
    {
        std::cout << "mul() START:" << std::endl;
        std::unique_ptr<Node> node = primary();

        std::cout << "mul() : GET "
                  << xtokenizer::toTokenTypeSymbol(node->token.type) << ", "
                  << node->token.value.i << std::endl;

        for (;;)
        {
            if (tokens.size() <= tokenIndex)
            {
                break;
            }
            xtokenizer::Token token = tokens[tokenIndex];
            if (token.type == xtokenizer::TokenType::T_MUL)
            { // *
                tokenIndex++;
                node = Node::create(token, std::move(node), primary());
            }
            else if (token.type == xtokenizer::TokenType::T_DIV)
            { // /
                tokenIndex++;
                node = Node::create(token, std::move(node), primary());
            }
            else if (token.type == xtokenizer::TokenType::T_SPACE)
            { // 空白なら次へ
                continue;
            }
            else
            {
                break;
            }
        }

        std::cout << "mul() : loop : "
                  << xtokenizer::toTokenTypeSymbol(node->token.type) << ", "
                  << node->token.value.i << std::endl;
        return node;
    }

    // primary = num | "(" expr ")"
    std::unique_ptr<Node> Parser::primary()
    {
        xtokenizer::Token token = tokens[tokenIndex];
        for (; tokenIndex < tokens.size() && token.type == xtokenizer::TokenType::T_SPACE; tokenIndex++)
        {
            token = tokens[tokenIndex];
        }

        if (token.type == xtokenizer::TokenType::T_L_PAREN)
        { // (
            tokenIndex++;
            std::unique_ptr<Node> node = expr();
            token = tokens[tokenIndex];
            if (token.type == xtokenizer::TokenType::T_R_PAREN)
            { // )
                tokenIndex++;
                return node;
            }
            else
            {
                throw xtokenizer::ParseException("not found block end", token);
            }
        }
        // 数値
        std::unique_ptr<Node> node = Node::create(token, nullptr, nullptr);
        tokenIndex++;

        std::cout << "primary() : number :"
                  << node.get()
                  << xtokenizer::toTokenTypeSymbol(node->token.type) << ", "
                  << node->token.value.i << std::endl;
        return node;
    }

} // namespace parser