自作言語:プログラムのツリー構造を構築

アバター
いわん
記事: 30
登録日時: 8年前

自作言語:プログラムのツリー構造を構築

投稿記事 by いわん » 5ヶ月前

一旦全てのコードを解析して要素(文や式)のツリー構造を形成してから実行します。
今回のバージョンアップで要素間の接続に用いるポインタを全て shared_ptr に変更しているのですが
this ポインタを使用する必要がある所が出てきて躓きました。二重に開放してはいけないからといって
shared_ptr<T>(this, [](T*){})
という風に何もしないデリーターを渡してもダメな気がします。
同じオブジェクトを二重に参照管理することになりますし。
これは設計からやり直さないとだめかなーと思ったら、ちゃんとあるんですね this ポインタを shared_ptr にする方法が。

this ポインタを shared_ptr に変換するインタフェースクラスを継承して
class T : public std::enable_shared_from_this<T>

shared_from_this() を呼び出すだけ。助かりしました(^^;


実験プログラムソースコード

CODE:

// compiler Visual C++ 2019
// 木構造実験プログラム
#include <iostream>
#include <vector>
#include <string>

// 木構造基底アイテム
struct tree_item : public std::enable_shared_from_this<tree_item>
{
    using ptr_type = typename std::shared_ptr<tree_item>;   // ポインタタイプ
    using ctr_type = typename std::vector<ptr_type>;        // コンテナタイプ

    virtual ~tree_item() {}
    virtual ctr_type& Branch() { throw "未実装例外"; }
    virtual bool parse(std::istream& is, ptr_type parent) = 0;
    virtual void print(const size_t level = 0) = 0;
};

// 葉アイテム
struct tree_leaf : public tree_item
{
    std::string text;

    virtual ~tree_leaf() {}
    virtual bool parse(std::istream& is, ptr_type parent) override
    {
        text.clear();
        while (is)
        {
            auto c = is.get();
            if (c == std::istream::traits_type::eof())
            {
                break;
            }
            if ((c == '{') || (c == '}'))
            {
                is.unget();
                break;
            }
            if (c == ';' || c == '\n')
            {
                break;
            }
            text += c;
        }
        if (text.size() > 0)
        {
            parent->Branch().push_back(shared_from_this());
            return true;
        }
        return false;
    }
    virtual void print(const size_t level = 0) override
    {
        for (size_t i = 0; i < level; ++i)  std::cout << '\t';
        std::cout << typeid(this).name() << std::endl;
    }
};

// 節アイテム
struct tree_node : public tree_item
{
    ctr_type branch;

    virtual ~tree_node() {}
    virtual ctr_type& Branch() { return branch; }
    virtual bool parse(std::istream& is, ptr_type parent) override
    {
        if (is.peek() != '{')
        {
            return false;
        }
        is.get();
        while (is)
        {
            if (ptr_type(new tree_node)->parse(is, shared_from_this()))
            {
                continue;
            }
            if (ptr_type(new tree_leaf)->parse(is, shared_from_this()))
            {
                continue;
            }
            if (is.peek() == '}')
            {
                is.get();
                parent->Branch().push_back(shared_from_this());
                return true;
            }
        }
        return false;
    }
    virtual void print(const size_t level = 0) override
    {
        for (size_t i = 0; i < level; ++i)  std::cout << '\t';
        std::cout << typeid(this).name() << std::endl;
        for (auto n : branch)
        {
            n->print(level + 1);
        }
    }
};

// 根アイテム
struct tree_root : public tree_node
{
    virtual ~tree_root() {}
    virtual bool parse(std::istream& is, ptr_type parent) override
    {
        while (is)
        {
            if (ptr_type(new tree_node)->parse(is, shared_from_this()))
            {
                continue;
            }
            if (ptr_type(new tree_leaf)->parse(is, shared_from_this()))
            {
                continue;
            }
        }
        return true;
    }
    virtual void print(const size_t level = 0) override
    {
        for (size_t i = 0; i < level; ++i)  std::cout << '\t';
        std::cout << typeid(this).name() << std::endl;
        for (auto n : branch)
        {
            n->print(level + 1);
        }
    }
};

int main()
{
    auto root = tree_item::ptr_type( new tree_root );
    std::cout << "*** input" << std::endl;
    root->parse(std::cin, nullptr);
    std::cout << "*** print" << std::endl;
    root->print();
}
実行結果
iprg_test4.png
ツリー構造構築実験
iprg_test4.png (11.27 KiB) 閲覧数: 13 回
最後に編集したユーザー いわん on 2023年11月16日(木) 17:50 [ 編集 1 回目 ]

コメントはまだありません。