#include <pgs/pgs.hpp>
#include <gtest/gtest.h>
#include <string>
#include <iostream>
#include <list>
#include <algorithm>
#include <iterator>
#include <sstream>
namespace {
struct atom_unit
{};
struct atom_bool {
bool val;
explicit atom_bool (bool val) : val {val}
{}
};
struct atom_int {
int val;
explicit atom_int (int val) : val {val}
{}
};
struct atom_float {
double val;
explicit atom_float (double val) : val {val}
{}
};
struct atom_string {
template <class S>
explicit atom_string (S&& val) : val {std::forward<S> (val)}
{}
};
atom_unit
, atom_bool
, atom_int
, atom_float
, atom_string
>;
, [](atom_bool
const& b) ->
std::string {
return b.val ?
"#t" :
"#f"; }
, [](atom_string
const& s) ->
std::string {
return s.val; }
);
}
struct expr_atom {
atom val;
template <class A>
explicit expr_atom (A&& val) : val {std::forward<A> (val)}
{}
};
struct expr_list;
expr_atom
>;
struct expr_list {
template <class L>
explicit expr_list (L&& l) : val { std::forward<L> (l)}
{}
};
[](expr_atom
const& a) ->
std::string {
return string_of_atom (a.val); }
os << "(";
if (begin != l.val.
begin ())
os << " ";
os << string_of_expr (*begin);
++begin;
}
os << ")";
}
);
}
struct sexpr {
private:
expr impl_;
public:
sexpr ()
{}
explicit sexpr (bool b)
{}
explicit sexpr (int i)
{}
explicit sexpr (double d)
{}
explicit sexpr (char const* s)
{}
{}
{}
{
, [](sexpr const& s) -> expr const& { return s.impl_; });
}
bool is_unit () const {
return impl_.match<bool>(
[](expr_atom const& e) {
return e.val.match<bool>(
[](atom_unit const&) -> bool { return true; },
); },
);
}
bool is_bool () const {
return impl_.match<bool>(
[](expr_atom const& e) {
return e.val.match<bool>(
[](atom_bool const&) -> bool { return true; },
); },
);
}
bool is_int () const {
return impl_.match<bool>(
[](expr_atom const& e) { return e.val.is<atom_int> (); },
);
}
bool is_float () const {
return impl_.match<bool>(
[](expr_atom const& e) { return e.val.is<atom_float> (); },
);
}
bool is_string () const {
return impl_.match<bool>(
[](expr_atom const& e) { return e.val.is<atom_string> (); },
);
}
bool is_list () const {
return impl_.match<bool>(
[](expr_list const& e) { return true; },
);
}
expr const& get_expr () const {
return impl_;
}
expr_atom const& get_atom () const {
return pgs::get<expr_atom> (impl_);
}
expr_list const& get_list () const {
return pgs::get<expr_list> (impl_);
}
};
}
sexpr s_unit;
sexpr s_bool{true};
sexpr s_int{1};
sexpr s_float{1.0};
sexpr s_list{sexpr_list{s_unit, s_int, s_float, s_string}};
ASSERT_TRUE (s_bool.is_bool ());
ASSERT_FALSE (s_int.is_bool ());
sexpr xpr{sexpr_list{
sexpr{"+"}, sexpr{5}, sexpr{sexpr_list{sexpr{"+"}, sexpr{3}, sexpr{5}}}}
};
ASSERT_EQ (xpr.to_string (),
std::string{
"(+ 5 (+ 3 5))"});
}