00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <string.h>
00017 #include <stdlib.h>
00018
00019 #include "../version.h"
00020
00021 #include "sexpress.hpp"
00022 #include "iexcept.hpp"
00023 #if INTELIB_TEXT_REPRESENTATIONS == 1
00024 #include <stdio.h>
00025 #include "sstring.hpp"
00026 #endif
00027
00028
00029
00030
00031
00032 #ifndef INTELIB_VERSION
00033 # error The symbol INTELIB_VERSION must be defined
00034 #endif
00035
00036 const char *the_intelib_title =
00037 "I n t e L i b library version " INTELIB_VERSION;
00038
00039 const char *the_intelib_copyright =
00040 "Copyright (c) Andrey V. Stolyarov <crocodil_AT_croco.net> 1999 - 2007. "
00041 "This is free software. You may copy and distribute it as well as any "
00042 "software developed using it under the terms and conditions of the "
00043 "GNU General Public License, version 2. "
00044 "The files which the library consist of are also available under the "
00045 "terms and conditions of GNI Lesser General Public License, vers. 2.1. "
00046 "See the file COPYING for details. "
00047 " !!! WARNING: There's NO WARRANTY of any kind !!!";
00048
00049 const int the_intelib_numberic_version = INTELIB_NUMVERSION;
00050
00051
00052
00053
00054
00055 bool IntelibTypeId::IsSubtypeOf(const IntelibTypeId &op) const
00056 {
00057 if(&op == this) {
00058 return true;
00059 } else if (!prev) {
00060 return false;
00061 } else {
00062 return prev->IsSubtypeOf(op);
00063 }
00064 }
00065
00066
00067
00068 IntelibTypeId SExpression::TypeId;
00069
00070
00071 SExpression::SExpression(const IntelibTypeId &the_type)
00072 {
00073 term_type_id = &the_type;
00074 #if INTELIB_DEBUG_COUNTERS == 1
00075 object_counter++;
00076 term_type_id->object_counter++;
00077 #endif
00078 }
00079
00080 SExpression::~SExpression()
00081 {
00082 #if INTELIB_DEBUG_COUNTERS == 1
00083 object_counter--;
00084 term_type_id->object_counter--;
00085 #endif
00086 }
00087
00088
00089 #if INTELIB_TEXT_REPRESENTATIONS == 1
00090 SString SExpression::TextRepresentation() const
00091 {
00092 return SString("#<UNKNOWN_TERM>");
00093 }
00094 #endif
00095
00096
00097
00098
00099 #if INTELIB_DEBUG_COUNTERS == 1
00100 long SExpression::object_counter = 0;
00101 #endif
00102
00103
00104
00105
00106 IntelibTypeId SExpressionInt::TypeId(&SExpression::TypeId);
00107
00108 bool SExpressionInt::SpecificEql(const SExpression *expr) const
00109 {
00110 return data == static_cast<const SExpressionInt*>(expr)->data;
00111 }
00112
00113 #if INTELIB_TEXT_REPRESENTATIONS == 1
00114 SString SExpressionInt::TextRepresentation() const
00115 {
00116 static char buf[40];
00117
00118 sprintf(buf, INTELIB_INTEGER_FORMAT, data);
00119 return SString(buf);
00120 }
00121 #endif
00122
00123
00124
00125 IntelibTypeId SExpressionFloat::TypeId(&SExpression::TypeId);
00126
00127 bool SExpressionFloat::SpecificEql(const SExpression *expr) const
00128 {
00129
00130 return data == static_cast<const SExpressionFloat*>(expr)->data;
00131 }
00132
00133 #if INTELIB_TEXT_REPRESENTATIONS == 1
00134 SString SExpressionFloat::TextRepresentation() const
00135 {
00136 char buf[30];
00137
00138 sprintf(buf, INTELIB_FLOAT_FORMAT, data);
00139 return SString(buf);
00140 }
00141 #endif
00142
00143
00144
00145 IntelibTypeId SExpressionChar::TypeId(&SExpression::TypeId);
00146
00147 bool SExpressionChar::SpecificEql(const SExpression *ref) const
00148 {
00149 INTELIB_ASSERT(TermType() == ref->TermType(), IntelibX_bug());
00150 return s[0] == static_cast<const SExpressionChar*>(ref)->s[0];
00151 }
00152
00153 #if INTELIB_TEXT_REPRESENTATIONS == 1
00154 SString SExpressionChar::TextRepresentation() const
00155 {
00156
00157 static const char *charnames[] = {
00158 "#\\Null", "#\\Soh", "#\\Stx", "#\\Etx",
00159 "#\\Eot", "#\\Enq", "#\\Ack", "#\\Bell",
00160 "#\\Backspace", "#\\Tab", "#\\Newline", "#\\Vt",
00161 "#\\Page", "#\\Return", "#\\So", "#\\Si",
00162 "#\\Dle", "#\\Dc1", "#\\Dc2", "#\\Dc3",
00163 "#\\Dc4", "#\\Nak", "#\\Syn", "#\\Etb",
00164 "#\\Can", "#\\Em", "#\\Sub", "#\\Escape",
00165 "#\\Fs", "#\\Gs", "#\\Rs", "#\\Us",
00166 "#\\Space"
00167 };
00168 if(s[0] < 33 && s[0] >= 0) return charnames[(int)(s[0])];
00169 if(s[0] == 127) return "#\\Rubout";
00170 char res[] = "#\\.";
00171 res[2] = s[0];
00172 return res;
00173 }
00174 #endif
00175
00176
00177
00178
00179 IntelibTypeId SExpressionString::TypeId(&SExpression::TypeId);
00180
00181 SExpressionString::SExpressionString(const char *s)
00182 : SExpression(TypeId)
00183 {
00184 StringSetup(s);
00185 }
00186
00187 SExpressionString::
00188 SExpressionString(const IntelibTypeId &tid, const char *s)
00189 : SExpression(tid)
00190 {
00191 StringSetup(s);
00192 }
00193
00194 SExpressionString::SExpressionString(const char *s1,
00195 const char *s2)
00196 : SExpression(TypeId)
00197 {
00198 unsigned int len1 = strlen(s1);
00199 unsigned int lensum = len1 + strlen(s2);
00200 char *p;
00201 is_indirect = (lensum + 1 >= intelib_simple_string_limit);
00202 if(is_indirect) {
00203 p = str.p = new char[lensum+1];
00204 } else {
00205 p = str.s;
00206 }
00207 strncpy(p, s1, len1+1);
00208 strncpy(p+len1, s2, lensum+1-len1);
00209 }
00210
00211 void SExpressionString::StringSetup(const char *s)
00212 {
00213 unsigned int len = strlen(s);
00214 is_indirect = (len+1 >= intelib_simple_string_limit);
00215 if(is_indirect) {
00216 str.p = new char[len+1];
00217 strncpy(str.p, s, len+1);
00218 } else {
00219 strncpy(str.s, s, len+1);
00220 }
00221 }
00222
00223 SExpressionString::~SExpressionString() {
00224 if(is_indirect)
00225 delete [] str.p;
00226 }
00227
00228 bool SExpressionString::SpecificEql(const SExpression *ref) const
00229 {
00230 INTELIB_ASSERT(TermType() == ref->TermType(), IntelibX_bug());
00231 return
00232 strcmp(GetValue(), ((const SExpressionString*)(ref))->GetValue()) == 0;
00233 }
00234
00235 #if INTELIB_TEXT_REPRESENTATIONS == 1
00236 SString SExpressionString::TextRepresentation() const
00237 {
00238 SString res;
00239 const char *src = is_indirect ? str.p : str.s;
00240 int len = strlen(src);
00241 res="\"";
00242 for(int i = 0; i< len; i++) {
00243 switch(src[i]) {
00244 case '\n': res+="\\n"; break;
00245 case '\t': res+="\\t"; break;
00246 case '\v': res+="\\v"; break;
00247 case '\b': res+="\\b"; break;
00248 case '\r': res+="\\r"; break;
00249 case '\f': res+="\\f"; break;
00250 case '\a': res+="\\a"; break;
00251 case '\\': res+="\\\\"; break;
00252
00253
00254 case '\"': res+="\\\""; break;
00255 default: {
00256 char tmp[2];
00257 tmp[0] = src[i];
00258 tmp[1] = 0;
00259 res+=tmp;
00260 }
00261 }
00262 }
00263 res+="\"";
00264 return res;
00265 }
00266 #endif
00267
00268
00269
00270 class IntelibSingleCharBank {
00271 SReference refs[256];
00272 public:
00273 IntelibSingleCharBank() {
00274 for(int i=0; i<256; i++) {
00275 refs[i] = ::new SExpressionChar(i);
00276 }
00277 }
00278 ~IntelibSingleCharBank() {}
00279 const SReference& operator[](int ch) { return refs[ch % 256]; }
00280 };
00281
00282 static IntelibSingleCharBank TheSingleCharBank;
00283
00284 const SReference& GetSingleCharExpression(int ch)
00285 {
00286 return TheSingleCharBank[ch];
00287 }
00288
00289
00290
00291 IntelibTypeId SExpressionClassicAtom::TypeId(&SExpressionString::TypeId);
00292
00293 SString SExpressionClassicAtom::TextRepresentation() const
00294 {
00295 return SString(this->GetValue());
00296 }
00297
00298
00299
00300 IntelibTypeId SExpressionCons::TypeId(&SExpression::TypeId, true);
00301
00302 SExpression* SExpressionCons::Clone() const
00303 {
00304 return new SExpressionCons(car.Clone(), cdr.Clone());
00305 }
00306
00307 #if INTELIB_TEXT_REPRESENTATIONS == 1
00308 static SString SafeTextRepresentation(const SReference &ref)
00309 {
00310 if(ref.GetPtr())
00311 return ref->TextRepresentation();
00312 else
00313 return "#<UNBOUND>";
00314 }
00315
00316 SString SExpressionCons::
00317 CoreTextRepresentation(const char *delim,
00318 const char *dot_delim,
00319 SString (*repfun)(const SReference &)) const
00320 {
00321 SString res = repfun ? repfun(car) : SafeTextRepresentation(car);
00322 if(cdr.IsEmptyList()) {
00323
00324 } else {
00325 SExpressionCons *dp = cdr.DynamicCastGetPtr<SExpressionCons>();
00326 if(dp) {
00327
00328 res += delim;
00329 res += dp->CoreTextRepresentation(delim, dot_delim, repfun);
00330 } else {
00331 res += dot_delim;
00332 res += repfun ? repfun(cdr) : SafeTextRepresentation(cdr);
00333 }
00334 }
00335 return res;
00336 }
00337 SString SExpressionCons::TextRepresentation() const
00338 {
00339 SString res("(");
00340 res+= CoreTextRepresentation(" ", " . ");
00341 res+= ")";
00342 return res;
00343 }
00344 #endif
00345
00346
00347
00348
00349 IntelibTypeId SExpressionLabel::TypeId(&SExpression::TypeId);
00350
00351
00352 #if INTELIB_TEXT_REPRESENTATIONS == 1
00353 SExpressionLabel::SExpressionLabel(const IntelibTypeId &the_type,
00354 const char *a_name)
00355 : SExpression(the_type)
00356 {
00357 name = strdup(a_name);
00358 }
00359 SExpressionLabel::SExpressionLabel(const char *a_name)
00360 : SExpression(TypeId)
00361 {
00362 name = strdup(a_name);
00363 }
00364 SExpressionLabel::~SExpressionLabel()
00365 {
00366 free(name);
00367 }
00368 SString SExpressionLabel::TextRepresentation() const
00369 {
00370 return name;
00371 }
00372
00373
00374
00375
00376 #endif
00377
00378
00379
00380 static SLabel STheEmptyListLabelRef("()");
00381 SReference *PTheEmptyList = &STheEmptyListLabelRef;
00382
00383
00384
00385 SReference::SReference(char c)
00386 {
00387 (*this) = TheSingleCharBank[c];
00388 }
00389
00390 SReference::SReference(signed char c)
00391 {
00392 (*this) = TheSingleCharBank[c];
00393 }
00394
00395 SReference::SReference(unsigned char c)
00396 {
00397 (*this) = TheSingleCharBank[c];
00398 }
00399
00400 SReference::SReference(signed short i)
00401 : GenericReference<SExpression>(new SExpressionInt(i))
00402 {}
00403
00404 SReference::SReference(unsigned short i)
00405 : GenericReference<SExpression>(new SExpressionInt(i))
00406 {}
00407
00408 SReference::SReference(signed int i)
00409 : GenericReference<SExpression>(new SExpressionInt(i))
00410 {}
00411
00412 SReference::SReference(unsigned int i)
00413 : GenericReference<SExpression>(new SExpressionInt(i))
00414 {}
00415
00416 SReference::SReference(signed long i)
00417 : GenericReference<SExpression>(new SExpressionInt(i))
00418 {}
00419
00420 SReference::SReference(unsigned long i)
00421 : GenericReference<SExpression>(new SExpressionInt(i))
00422 {}
00423
00424 SReference::SReference(signed long long i)
00425 : GenericReference<SExpression>(new SExpressionInt(i))
00426 {}
00427
00428 SReference::SReference(unsigned long long i)
00429 : GenericReference<SExpression>(new SExpressionInt(i))
00430 {}
00431
00432 SReference::SReference(float f)
00433 : GenericReference<SExpression>(new SExpressionFloat(f))
00434 {}
00435
00436 SReference::SReference(double f)
00437 : GenericReference<SExpression>(new SExpressionFloat(f))
00438 {}
00439
00440 SReference::SReference(long double f)
00441 : GenericReference<SExpression>(new SExpressionFloat(f))
00442 {}
00443
00444 SReference::SReference(const char *s)
00445 {
00446 (*this) = new SExpressionString(s);
00447 }
00448
00449 SReference::SReference(const unsigned char *s)
00450 {
00451 (*this) = new SExpressionString(reinterpret_cast<const char*>(s));
00452 }
00453
00454 SReference::SReference(const class SListConstructor &)
00455 : GenericReference<SExpression>(*PTheEmptyList)
00456 {}
00457
00458 SReference::SReference(const SReference &rcar, const SReference &rcdr)
00459 : GenericReference<SExpression>(new SExpressionCons(rcar, rcdr))
00460 {}
00461
00462
00463 SReference& SReference::AddAnotherItemToList(const SReference &right)
00464 {
00465 if(GetPtr() && (*this)->TermType() == SExpressionCons::TypeId) {
00466 (((SExpressionCons*)GetPtr())->Cdr()).AddAnotherItemToList(right);
00467 } else {
00468 (*this) = new SExpressionCons(right, *PTheEmptyList);
00469 }
00470 return *this;
00471 }
00472
00473 SReference& SReference::ChangeListEnd(const SReference &new_last)
00474 {
00475 if(GetPtr() && (*this)->TermType() == SExpressionCons::TypeId) {
00476 (((SExpressionCons*)GetPtr())->Cdr()).ChangeListEnd(new_last);
00477 } else {
00478 (*this) = new_last;
00479 }
00480 return *this;
00481 }
00482
00483 SReference SReference::MakeCons(const SReference &a_cdr) const
00484 {
00485 return SReference(new SExpressionCons(*this, a_cdr));
00486 }
00487
00488 SReference& SReference::Car() const
00489 {
00490 INTELIB_ASSERT(GetPtr(), IntelibX_unexpected_unbound_value());
00491 SExpressionCons *tp = DynamicCastGetPtr<SExpressionCons>();
00492 INTELIB_ASSERT(tp, IntelibX_not_a_cons(*this));
00493 return tp->Car();
00494 }
00495
00496 SReference& SReference::Cdr() const
00497 {
00498 INTELIB_ASSERT(GetPtr(), IntelibX_unexpected_unbound_value());
00499 SExpressionCons *tp = DynamicCastGetPtr<SExpressionCons>();
00500 INTELIB_ASSERT(tp, IntelibX_not_a_cons(*this));
00501 return tp->Cdr();
00502 }
00503
00504 SReference& SReference::CCar() const
00505 {
00506 if((*this)==*PTheEmptyList) {
00507 return *PTheEmptyList;
00508 } else {
00509 return Car();
00510 }
00511 }
00512
00513 SReference& SReference::CCdr() const
00514 {
00515 if((*this)==*PTheEmptyList) {
00516 return *PTheEmptyList;
00517 } else {
00518 return Cdr();
00519 }
00520 }
00521
00522 intelib_float_t SReference::GetFloat() const
00523 {
00524 INTELIB_ASSERT(GetPtr(), IntelibX_unexpected_unbound_value());
00525 SExpressionFloat *sf = DynamicCastGetPtr<SExpressionFloat>();
00526 if(sf) return sf->GetValue();
00527 SExpressionInt *si = DynamicCastGetPtr<SExpressionInt>();
00528 if(si) return si->GetValue();
00529 throw IntelibX_not_a_number(*this);
00530 }
00531
00532 intelib_integer_t SReference::GetInt() const
00533 {
00534 INTELIB_ASSERT(GetPtr(), IntelibX_unexpected_unbound_value());
00535 SExpressionInt *si = DynamicCastGetPtr<SExpressionInt>();
00536 if(si) return si->GetValue();
00537 SExpressionFloat *sf = DynamicCastGetPtr<SExpressionFloat>();
00538 if(sf) return (intelib_integer_t) (sf->GetValue());
00539 throw IntelibX_not_a_number(*this);
00540 }
00541
00542 const char* SReference::GetString() const
00543 {
00544 INTELIB_ASSERT(GetPtr(), IntelibX_unexpected_unbound_value());
00545 SExpressionString *ss = DynamicCastGetPtr<SExpressionString>();
00546 if(ss) return ss->GetValue();
00547 SExpressionChar *ch = DynamicCastGetPtr<SExpressionChar>();
00548 if(ch) return ch->GetString();
00549 throw IntelibX_not_a_string(*this);
00550 }
00551
00552 char SReference::GetSingleChar() const
00553 {
00554 SExpressionChar *ch = DynamicCastGetPtr<SExpressionChar>();
00555 if(ch) return ch->GetValue();
00556
00557 const char *p = GetString();
00558 if(p && *p && (*(p+1)==0)) return *p;
00559 throw IntelibX_not_a_char(*this);
00560 }
00561
00562 SReference SReference::Clone() const
00563 {
00564 if(!GetPtr()) return *this;
00565 if(!GetPtr()->IsChangeable()) return *this;
00566 return SReference(GetPtr()->Clone());
00567 }
00568
00569 SReference SReference::CopyList() const
00570 {
00571 if(!GetPtr()) return *this;
00572 SExpressionCons *cons = DynamicCastGetPtr<SExpressionCons>();
00573 if(cons)
00574 return SReference(cons->Car(), cons->Cdr().CopyList());
00575 else
00576 return *this;
00577 }
00578
00579 SReference SReference::CopyTree() const
00580 {
00581 if(!GetPtr()) return *this;
00582 SExpressionCons *cons = DynamicCastGetPtr<SExpressionCons>();
00583 if(cons)
00584 return SReference(cons->Car().CopyTree(), cons->Cdr().CopyTree());
00585 else
00586 return *this;
00587 }
00588
00589 bool SReference::IsEql(const SReference& other) const
00590 {
00591 if(GetPtr() == other.GetPtr()) {
00592 return true;
00593 }
00594 if(GetPtr()->TermType() == other->TermType()) {
00595 return GetPtr()->SpecificEql(other.GetPtr());
00596 }
00597 return false;
00598 }
00599
00600 bool SReference::IsEqual(const SReference& other) const
00601 {
00602 if(IsEql(other)) return true;
00603 SExpressionCons *dp = DynamicCastGetPtr<SExpressionCons>();
00604 if(dp) {
00605 SExpressionCons *dp2 = other.DynamicCastGetPtr<SExpressionCons>();
00606 if(dp2) {
00607 return
00608 dp->Car().IsEqual(dp2->Car()) &&
00609 dp->Cdr().IsEqual(dp2->Cdr());
00610 }
00611 }
00612 return false;
00613 }
00614
00615 bool SReference::IsEmptyList() const
00616 {
00617 return GetPtr() == PTheEmptyList->GetPtr();
00618 }
00619