#include <assert.h>
namespace ln {
struct Cell;
struct Obj {
unsigned _ref = 0;
Obj* retain() { return ++_ref, this; }
Obj* release() {
if (0 != --_ref) return this;
return delete this, nullptr;
}
virtual ~Obj() {}
virtual operator int() { return 0; }
virtual Obj* eval(Cell* args) { return this->retain(); }
template<class Node> static Obj* parse(const char** p);
static Obj* parse(const char* s) { return parse<Cell>(&s); }
};
struct Nil : Obj {};
struct Cell : Obj {
Obj *_a, *_b;
Cell(Obj *a = nullptr, Obj *b = nullptr) : _a(a ? a->retain() : a), _b(b ? b->retain() : b) {}
virtual ~Cell() { if (_a) _a->release(); if (_b) _b->release(); }
void push(Obj* v) {
if (!_a) { _a = v->retain(); return; }
if (_b) return static_cast<Cell*>(_b)->push(v);
(_b = new Cell{v, nullptr})->retain();
}
virtual Obj* eval(Cell* args) { return _a ? _a->eval(static_cast<Cell*>(_b)) : (new Nil{})->retain(); }
};
struct Ary : Cell {
virtual Obj* eval(Cell* args) {
Cell *r = new Ary{};
Cell *b = this;
while (b && b->_a) {
auto v = b->_a->eval(nullptr);
r->push(v);
v->release();
b = static_cast<Cell*>(b->_b);
}
return r->retain();
}
};
struct Num : Obj {
int _v;
Num(int v) : _v{v} {}
virtual operator int() { return _v; }
virtual Obj* eval(Cell* args) { return (new Num{_v})->retain(); }
static Obj* parse(const char **p) {
auto isdigit = [](auto c) { return '0' <= c && '9' >= c; };
if (!isdigit(**p)) return nullptr;
auto v = new Num{**p - '0'};
while (isdigit(*(*p + 1))) v->_v = v->_v * 10 + (*++*p - '0');
return v;
}
};
template<class T = void, char C = ' '> struct Calc : Obj {
static Obj* parse(const char** p);
virtual Obj* eval(Cell* args);
};
struct Add : Calc<Add, '+'> {
Obj* binary(Obj* a, Obj* b) { return new Num{int(*a) + int(*b)}; }
Obj* unary(Obj* a) { if (auto v = dynamic_cast<Cell*>(a)) return v->_b ? static_cast<Obj*>(v->_b) : new Nil{}; return a; } };
struct Sub : Calc<Sub, '-'> {
Obj* binary(Obj* a, Obj* b) { return new Num{int(*a) - int(*b)}; }
Obj* unary(Obj* a) { return new Num{-int(*a)}; } };
struct Mul : Calc<Mul, '*'> {
Obj* binary(Obj* a, Obj* b) { return new Num{int(*a) * int(*b)}; }
Obj* unary(Obj* a) { if (auto v = dynamic_cast<Cell*>(a)) { return v->_a ? v->_a : new Nil{}; } return a; } };
struct Div : Calc<Div, '/'> {
Obj* binary(Obj* a, Obj* b) { return new Num{int(*a) / int(*b)}; }
Obj* unary(Obj* a) { return a; } };
template<class T, char C> Obj* Calc<T, C>::parse(const char** p) {
if ('+' == **p) { auto x = new Add{}; return x; }
if ('-' == **p) { auto x = new Sub{}; return x; }
if ('*' == **p) { auto x = new Mul{}; return x; }
if ('/' == **p) { auto x = new Div{}; return x; } return nullptr;
}
template<class T, char C> Obj* Calc<T, C>::eval(Cell* args) {
if (!args) return this->retain();
auto a = args->_a;
auto b = static_cast<Cell*>(args->_b);
if (!b) {
auto t = a->eval(nullptr);
auto r = static_cast<T*>(this)->unary(t)->retain();
t->release();
return r;
}
auto r = a;
do {
auto x = r->eval(nullptr);
auto y = b->_a->eval(nullptr);
if (r != a) r->release();
r = static_cast<T*>(this)->binary(x, y)->retain();
x->release();
y->release();
b = static_cast<Cell*>(b->_b);
} while (nullptr != b);
return r;
}
template<class Node> Obj* Obj::parse(const char **p) {
auto a = new Node{};
do {
if (' ' == **p) continue;
if ('(' == **p) { a->push(Obj::parse<Cell>(&++*p)); continue; }
if ('[' == **p) { a->push(Obj::parse<Ary >(&++*p)); continue; }
if (')' == **p) break;
if (']' == **p) break;
if (auto v = Num::parse(p)) { a->push(v); continue; }
if (auto v = Calc<>::parse(p)) { a->push(v); continue; }
} while (*++*p);
return a;
}
int ling(const char* s) {
auto t = Obj::parse(s)->retain();
auto r = t->eval(nullptr);
int i = static_cast<int>(*r);
r->release();
t->release();
return i;
}
}
int main() {
assert( 2 == ln::ling("2") );
assert( -2 == ln::ling("- 2") );
assert( 3 == ln::ling("+ 1 2") );
assert( 6 == ln::ling("+ 1 2 3") );
assert( -3 == ln::ling("- (+ 1 2)") );
assert( 2 == ln::ling("+ 1 2 (- 1)") );
assert( 6 == ln::ling("* (- 2) (- 3)") );
assert( -3 == ln::ling("- (* (+ [2 3]))") );
}