Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

sexpress.cpp

Go to the documentation of this file.
00001 // +-------------------------------------------------------------------------+
00002 // |               I__n__t__e__L__i__b           0.6.10 development          |
00003 // | Copyright (c) Andrey Vikt. Stolyarov <crocodil_AT_croco.net> 2000-2007. |
00004 // |                                                                         |
00005 // | This is free software. The library part is available under              |
00006 // |                               GNU LESSER GENERAL PUBLIC LICENSE v.2.1.  |
00007 // | GNU LGPL v2.1 is found in docs/gnu_gpl2.txt,  or at  http://www.gnu.org |
00008 // |     Please see also docs/readme.txt and visit http://www.intelib.org    |
00009 // |                                                                         |
00010 // | !!! THERE IS NO WARRANTY OF ANY KIND, NEITHER EXPRESSED NOR IMPLIED !!! |
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 /* Version identification and copyright information. DON'T REMOVE !!!     */
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 // IntelibTypeId implementation
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 // SExpression class
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 // SExpressionInt class
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     //snprintf(buf, sizeof(buf), INTELIB_INTEGER_FORMAT, data);
00118     sprintf(buf, INTELIB_INTEGER_FORMAT, data);
00119     return SString(buf);
00120 }
00121 #endif
00122 
00123 // SExpressionFloat class
00124 
00125 IntelibTypeId SExpressionFloat::TypeId(&SExpression::TypeId);
00126 
00127 bool SExpressionFloat::SpecificEql(const SExpression *expr) const
00128 {
00129     /*INTELIB_ASSERT(ref->TermType() == TypeId, LispX_bug());*/
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     //snprintf(buf, sizeof(buf), INTELIB_FLOAT_FORMAT, data);
00138     sprintf(buf, INTELIB_FLOAT_FORMAT, data);
00139     return SString(buf);
00140 }
00141 #endif
00142 
00143 // SExpressionChar class
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     // names taken from CLISP
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 // SExpressionString class
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]) {  // in accordance to B.Stroustroup, 3rd ed., C.3.2
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                 //case '\?': res+="\\?"; break; //senseless
00253                 //case '\'': res+="\\'"; break; //senseless
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 // Single character object bank
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 // SExpressionClassicAtom class
00290 
00291 IntelibTypeId SExpressionClassicAtom::TypeId(&SExpressionString::TypeId);
00292 
00293 SString SExpressionClassicAtom::TextRepresentation() const 
00294 {
00295     return SString(this->GetValue());
00296 }
00297 
00298 // SExpressionCons class
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         // end of list
00324     } else {
00325         SExpressionCons *dp = cdr.DynamicCastGetPtr<SExpressionCons>();
00326         if(dp) {
00327             // Print as a list, without a dot...
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 // SExpressionLabel class
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 //SString SExpressionLabel::GetName() const
00373 //{
00374 //  return name;
00375 //}
00376 #endif
00377 
00378 // Some useful label terms
00379 
00380 static SLabel STheEmptyListLabelRef("()");
00381 SReference *PTheEmptyList = &STheEmptyListLabelRef;
00382 
00383 // SReference class
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     // for compatibility, let's consider a string of one char as a char
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 

Generated on Tue Dec 18 00:39:45 2007 for InteLib by  doxygen 1.4.1