Rodhos Soft

備忘録を兼ねた技術的なメモです。Rofhos SoftではiOSアプリ開発を中心としてAndroid, Webサービス等の開発を承っております。まずはご相談下さい。

木構造的なもの

LISPのようなものを作ろうとしたら単に文字列の結合を木構造でやるということになっていた。でもクラスについてだいぶ勉強になった。

//
//  RDLisp.hpp
//  RDLisp
//
//  Created by KatagiriSo on 2017/09/26.
//  Copyright © 2017年 RodhosSoft. All rights reserved.
//

#ifndef RDLisp_hpp
#define RDLisp_hpp

#include <iostream>
#include <stdio.h>

namespace RDLisp {
    
    template<class T>
    using Share = std::shared_ptr<T>;

    
    class Printable {
    public:
        virtual std::string description() = 0;
    };
    
    
    class S : public Printable{
    public:
    };
    
    class Value;
    
    class Pair : public S {
    public:
        Share<S> car;
        Share<S> cdr;
        Pair(Share<S> car, Share<S> cdr) {
            this->car = car;
            this->cdr = cdr;
        }
        
        std::string description();
        bool isFunc();
        bool isValue();
    };
    
    
    class Nil : public S {
    public:
        Nil();
        std::string description();
    };
    
    class Symbol;
    class Value;
    
    class Atom  : public S {
    public:
        std::string value;
        Atom(std::string value) {
            this->value = value;
        };
        std::string description();
    };
    
    
    class Value : public Atom {
    public:
        Value(std::string value) : Atom(value) {
            
        };
    };
    
    /// symbol is function
    class Symbol : public Atom {
    public:
        Symbol(std::string value) : Atom(value) {
            
        };
    };
    

    Share<S> eval(Share<S> s);
    Share<S> apply(Share<Symbol> sy, Share<S> target);
}



#endif /* RDLisp_hpp */
//
//  RDLisp.cpp
//  RDLisp
//
//  Created by KatagiriSo on 2017/09/26.
//  Copyright © 2017年 RodhosSoft. All rights reserved.
//

#include "RDLisp.hpp"

#include <vector>
#include <string>

namespace RDLisp {
    
    template <class T>
    Share<T> scast(Share <S> s) {
        return std::dynamic_pointer_cast<T>(s);
    }
    
    Share<Value> add(Share<S> target, int n) {
        std::cout <<std::string(n, ' ') << "+"<< "\n";

        if (auto v = scast<Value>(target)) {
            std::cout << std::string(n, ' ')<< v->description() << "\n";
            return v;
        }
        
        if (auto p = scast<Pair>(target)) {
            
            if (auto s = scast<Symbol>(p->car)) {
                auto cdr_after = apply(s, p->cdr);
                if (auto v = scast<Value>(cdr_after)) {
                    return v;

                } else {
                    return nullptr;
                }
            }
            
            if (auto f = scast<Value>(p->car)) {
                auto l = add(p->cdr, n+1);
                if (f&&l) {
                    auto v = std::make_shared<Value>(f->value + l->value);
                    
                    std::cout <<std::string(n, ' ')<< "["<< v->description() << "]"<< "\n";
                    return v;
                } else {
                    return nullptr;
                }
            }
            
            if (auto l = scast<Value>(p->cdr)) {
                auto f = add(p->car, n+1);
                if (f&&l) {
                    auto v = std::make_shared<Value>(f->value + l->value);
                    
                    std::cout <<std::string(n, ' ')<< "["<< v->description() << "]"<< "\n";
                    return v;
                } else {
                    return nullptr;
                }
            }
            
            
            auto f = add(p->car, n+1);
            auto l = add(p->cdr, n+1);
            if (f&&l) {
                auto v = std::make_shared<Value>(f->value + l->value);
                
                std::cout <<std::string(n, ' ')<< "["<< v->description() << "]"<< "\n";
                return v;
            } else {
                return nullptr;
            }
        }
        
        std::cout <<std::string(n, ' ')<< "nullptr"<< "\n";
        return nullptr;
    }
    

    
    Share<S> eval(Share<S> exp) {
        auto pair = scast<Pair>(exp);
        if (pair) {
            if (pair->isFunc()) {
                auto sy = std::dynamic_pointer_cast<Symbol>(pair->car);
//                auto crd_after = eval(pair->cdr);
//                std::cout << "crd_after" + crd_after->description() + "\n";
                return apply(sy, pair->cdr);
//                return apply(sy, crd_after);

            }
        }
        
        return exp;
    }
    
    Share<S> apply(Share<Symbol> sy, Share<S> target) {
        
        if (sy->value == "+") {
            if (auto v = scast<Value>(target)) {
                return target;
            }
            
            if (auto p = scast<Pair>(target)) {
                auto exp = add(target, 0);
                if (exp) {
                    return exp;
                }
            }
            
        }
        
        return std::make_shared<Pair>(sy,target);
    }

    
    bool Pair::isFunc() {
        auto sy = std::dynamic_pointer_cast<Symbol>(this->car);
        if (sy) {
            return true;
        }
        return false;
    }
    


    
    std::string Pair::description() {
        return "(" + this->car->description() + " " + this->cdr->description() + ")";  
    }
    
    std::string Atom::description() {
        return this->value;
    }

    std::string Nil::description() {
        return "";
    }

    

}

実行は次のようにする。面倒。

//
//  main.cpp
//  RDLisp
//
//  Created by KatagiriSo on 2017/09/26.
//  Copyright © 2017年 RodhosSoft. All rights reserved.
//

#include <iostream>
#include "RDLisp.hpp"

int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    
    using namespace RDLisp;
    using namespace std;
    
    auto a1 = make_shared<Value>("a1");
    auto a2 = make_shared<Value>("a2");
    auto pair_a = make_shared<Pair>(a1,a2);
    auto b = make_shared<Value>("b");
    auto c = make_shared<Value>("c");
    auto d = make_shared<Value>("d");
    auto add = make_shared<Symbol>("+");
    auto add2 = make_shared<Symbol>("+");
    auto pair_ab = make_shared<Pair>(pair_a,b);
    auto pair_cd = make_shared<Pair>(c,d);
    auto pair = make_shared<Pair>(add, pair_ab);
    auto pair2 = make_shared<Pair>(add, pair_cd);
    auto pair3 = make_shared<Pair>(pair, pair2);
    auto pair4 = make_shared<Pair>(add2, pair3);
    
    std::cout << pair4->description() << "\n";
    
    auto res = eval(pair4);
    
    std::cout << res->description() << "\n";

    
    return 0;
}

結果は

Hello, World!
(+ ((+ ((a1 a2) b)) (+ (c d))))
+
 +
+
 +
  +
  a2
 [a1a2]
[a1a2b]
 +
+
 +
 d
[cd]
[a1a2bcd]
a1a2bcd
Program ended with exit code: 0