00001
00002
00003
00004
00005
00006
00007
00008 #ifndef CEKLA_H
00009 #define CEKLA_H
00010
00087 #include <stdexcept>
00088 #include <string>
00089 #include <iomanip>
00090 #include <sstream>
00091 #include <iostream>
00092 #include <cassert>
00093 #include <cstring>
00094 #include <cassert>
00095 #include <algorithm>
00096 #include <new>
00097 #ifdef ENABLE_INITIALIZER_LIST // __GXX_EXPERIMENTAL_CXX0X__
00098 # include <initializer_list>
00099 #endif
00100
00101
00102
00103
00104
00105
00106
00107
00134 class list {
00135
00136 public:
00137
00158 list(const char *S) throw (std::logic_error);
00159
00160 #ifdef ENABLE_INITIALIZER_LIST
00161
00175 list(std::initializer_list<int> S);
00176 #endif
00177
00189 bool operator==(const list & Rhs) const;
00203 bool operator!=(const list & Rhs) const;
00204
00205 #ifdef ENABLE_SHARED_PTR
00206 ~list();
00207 #endif
00208
00209
00210
00211 list(int, const list);
00212 int head() const;
00213 list tail() const;
00214 private:
00215
00216
00217
00218
00219
00220 struct elem;
00221
00222 #ifndef ENABLE_SHARED_PTR
00223
00224 typedef const elem * shared_ptr;
00225 #else
00226
00227
00228 struct shared_ptr {
00229 const elem * p;
00230 void inc() { if (p) p->refcount++; }
00231 void dec() { if (p) if (0 == --(p->refcount)) delete p; }
00232 shared_ptr(const elem *p = NULL) : p(p) { inc(); }
00233 shared_ptr(const shared_ptr & o) : p(NULL) { *this = o; }
00234 shared_ptr & operator=(const shared_ptr & o) { dec(); p = o.p; inc(); return *this; }
00235 const elem* operator->() const { return p; }
00236 operator const elem* const & () const { return p; }
00237
00238 ~shared_ptr() { dec(); }
00239 };
00240 #endif
00241
00242 struct elem {
00243
00244 int data;
00245
00246 shared_ptr next;
00247
00248 elem(int data, shared_ptr next = 0) : data(data), next(next)
00249 #ifdef ENABLE_SHARED_PTR
00250 , refcount(0)
00251 #endif
00252 {}
00253
00254 #ifdef ENABLE_SHARED_PTR
00255
00256 mutable int refcount;
00257 private:
00258 void operator=(const elem&);
00259 elem(const elem&);
00260 #endif
00261 };
00262
00263
00264 shared_ptr first;
00265
00266 };
00267
00292 list cons(int Head, const list Tail);
00293
00314 int hd(const list L);
00315
00336 list tl(const list L);
00337
00354 extern const list nil;
00355
00356
00357
00374 template <typename any_type>
00375 void write(const any_type & X);
00376
00377 #ifdef NDEBUG
00378
00388 template <typename any_type>
00389 void writeln(const any_type & X);
00390 #else
00391
00400 #define writeln(X) detail::_writeln(X, __FILE__, __LINE__)
00401 #endif
00402
00404 list l() { return nil; }
00406 list l(int E) { return cons(E, nil); }
00408 list l(int E1,int E2) { return cons(E1,l(E2)); }
00410 list l(int E1,int E2,int E3) { return cons(E1,l(E2,E3)); }
00412 list l(int E1,int E2,int E3,int E4) { return cons(E1,l(E2,E3,E4)); }
00414 list l(int E1,int E2,int E3,int E4,int E5) { return cons(E1,l(E2,E3,E4,E5)); }
00416 list l(int E1,int E2,int E3,int E4,int E5,int E6) { return cons(E1,l(E2,E3,E4,E5,E6)); }
00418 list l(int E1,int E2,int E3,int E4,int E5,int E6,int E7) { return cons(E1,l(E2,E3,E4,E5,E6,E7)); }
00420 list l(int E1,int E2,int E3,int E4,int E5,int E6,int E7,int E8) { return cons(E1,l(E2,E3,E4,E5,E6,E7,E8)); }
00422 list l(int E1,int E2,int E3,int E4,int E5,int E6,int E7,int E8,int E9) { return cons(E1,l(E2,E3,E4,E5,E6,E7,E8,E9)); }
00435 list l(int E1,int E2,int E3,int E4,int E5,int E6,int E7,int E8,int E9,int E10) { return cons(E1,l(E2,E3,E4,E5,E6,E7,E8,E9,E10)); }
00436
00474 typedef int (*fun1)(int);
00484 typedef int (*fun2)(int, int);
00486
00487
00488
00489 namespace detail {
00490
00491
00492 extern volatile int Tab;
00493
00494
00495 template <typename any_type>
00496 void _writeln(const any_type & X, const char * Source_file, int Source_line);
00497
00498
00499 void error(const char *Errmsg) throw (std::logic_error);
00500
00501
00502 std::ostream & operator<<(std::ostream & Os, const list & L);
00503
00504 }
00505
00506
00507
00508
00509
00510
00511
00512 const list nil = "";
00513
00514 template <typename any_type>
00515 void write(const any_type & X) {
00516 using namespace detail;
00517 std::stringstream S;
00518 S << X;
00519 detail::Tab += (int)S.str().length();
00520 std::cout << X;
00521 }
00522
00523 #ifdef NDEBUG
00524 template <typename any_type>
00525 void writeln(const any_type & X) {
00526 write(X);
00527 std::cout << std::endl;
00528 }
00529 #else
00530 namespace detail {
00531 template <typename any_type>
00532 void _writeln(const any_type & X, const char * Source_file, int Source_line) {
00533 write(X);
00534 using namespace std;
00535 cout << setw(60 - Tab) << ' ' << setw(0);
00536 cout << " // " << Source_file << ":" << Source_line;
00537 Tab = 0;
00538 cout << endl;
00539 }
00540 }
00541 #endif
00542
00543 list::list(const char *S) throw (std::logic_error) : first() {
00544 if (!S) detail::error("ERROR in list(char*): null pointer given");
00545 *this = nil;
00546 for (const char * P = S + strlen(S) - 1; P >= S; P--)
00547 *this = cons(*P, *this);
00548 }
00549
00550 #ifdef ENABLE_INITIALIZER_LIST
00551 list::list(std::initializer_list<int> S) : first() {
00552 for (auto P = S.begin(); P != S.end(); ++P)
00553 *this = cons(*P, *this);
00554 }
00555 #endif
00556
00557 bool list::operator==(const list & Rhs) const {
00558 shared_ptr p1, p2;
00559 for (p1 = first, p2 = Rhs.first; p1 && p2; p1 = p1->next, p2 = p2->next)
00560 if (p1->data != p2->data)
00561 return false;
00562 return !p1 && !p2;
00563 }
00564
00565 bool list::operator!=(const list & Rhs) const {
00566 return ! (*this == Rhs);
00567 }
00568
00569 #ifdef ENABLE_SHARED_PTR
00570 list::~list() {
00571
00572
00573
00574
00575 for (const elem * p = first; p && p->refcount == 1; p = first) {
00576 first.p = NULL;
00577 first = p->next;
00578 delete p;
00579 }
00580 }
00581 #endif
00582
00583 inline
00584 list::list(int Head, const list Tail) : first() {
00585 first = new list::elem(Head, Tail.first);
00586 }
00587
00588 list cons(int Head, const list Tail) {
00589 return list(Head, Tail);
00590 }
00591
00592 inline
00593 int list::head() const {
00594 if (first==NULL)
00595 detail::error("ERROR in head(): list is empty");
00596 return first->data;
00597 }
00598
00599 int hd(const list L) {
00600 return L.head();
00601 }
00602
00603 inline
00604 list list::tail() const {
00605 if (first==NULL)
00606 detail::error("ERROR in tail(): list is empty");
00607 list L0 = nil;
00608 L0.first = first->next;
00609 return L0;
00610 }
00611
00612 list tl(const list L) {
00613
00614
00615
00616
00617
00618 return L.tail();
00619 }
00620
00621 namespace detail {
00622
00623 void memory_error() {
00624 std::cerr << "ERROR: out of memory" << std::endl;
00625 throw std::bad_alloc();
00626 }
00627
00628
00629 struct bootstrap {
00630 bootstrap() {
00631 std::set_new_handler(memory_error);
00632 }
00633 } _startup;
00634
00635 volatile int Tab = 0;
00636
00637 void error(const char *errmsg) throw (std::logic_error) {
00638 std::logic_error e(errmsg);
00639 std::cerr << e.what() << std::endl;
00640 throw e;
00641 }
00642
00643 std::ostream & operator<<(std::ostream & Os, const list & L) {
00644 bool Is_szoveg = true;
00645 for (list L0 = L; L0 != nil; L0 = tl(L0)) {
00646 if (hd(L0) < 32 || 126 < hd(L0)) {
00647 Is_szoveg = false;
00648 break;
00649 }
00650 }
00651 if (Is_szoveg && L != nil) {
00652
00653 for (list L0 = L; L0 != nil; L0 = tl(L0))
00654 Os << (char) hd(L0);
00655
00656 }
00657 else {
00658 Os << "[";
00659 bool First = true;
00660 for (list L0 = L; L0 != nil; L0 = tl(L0)) {
00661 if (!First) Os << ",";
00662 Os << hd(L0);
00663 First = false;
00664 }
00665 Os << "]";
00666 }
00667 return Os;
00668 }
00669
00670 }
00671
00672 #endif