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

sreader.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 <ctype.h>
00018 
00019 #include "slexer.hpp"
00020 #include "sreader.hpp"
00021 
00022 static SLabel LexemaQuote("#'#");
00023 SLabel& IntelibGenericReader::EofMarker = LexemaEof;
00024 
00025 IntelibGenericReader::IntelibGenericReader()
00026 { 
00027     the_package = &TheDummyPackage;
00028     uppercase = true;
00029     lexer = new IntelibSLexAnalyser;
00030     first_sl = 0;
00031     unclosed_brackets = 0;
00032 }
00033 
00034 IntelibGenericReader::~IntelibGenericReader()
00035 {
00036     while(first_sl) {
00037         SpecialLexic *tmp = first_sl->next;
00038         delete first_sl;
00039         first_sl = tmp;
00040     }
00041     delete lexer;
00042 }
00043 
00044 IntelibGenericReader::SpecialLexic*
00045 IntelibGenericReader::AddSpecialLexic(const char *str,
00046                                       SpecialLexic::sl_type t,
00047                                       process_function proc)
00048 {
00049     SpecialLexic *tmp = new SpecialLexic;
00050     tmp->id = new SExpressionString(str);
00051     tmp->t = t;
00052     tmp->process = proc;
00053     tmp->next = first_sl;
00054     first_sl = tmp;
00055     return tmp;
00056 }
00057 
00058 #if 0
00059 void IntelibGenericReader::AddInvalidLexem(const char *str)
00060 {
00061     AddSpecialLexic(str, SpecialLexic::invalid, 0, false);
00062 }
00063 #endif
00064 
00065 void IntelibGenericReader::
00066 AddDelimiter(const char *str, const SReference &tok)
00067 {
00068     bool res = lexer->AddDelimiter(str, tok);
00069     INTELIB_ASSERT(res, IntelibX_reader_error(lexer->GetErrorMessage(), -1));
00070 }
00071 
00072 void IntelibGenericReader::
00073 AddToken(const char *str, const SReference &tok)
00074 {
00075     bool res = lexer->AddNonDelimiter(str, tok);
00076     INTELIB_ASSERT(res, IntelibX_reader_error(lexer->GetErrorMessage(), -1));
00077 }
00078 
00079 void IntelibGenericReader::
00080 AddTokenType(const char *str, SReference (*fun)(const char*))
00081 {
00082     bool res = lexer->AddTokenStarter(str, fun);
00083     INTELIB_ASSERT(res, IntelibX_reader_error(lexer->GetErrorMessage(), -1));
00084 }
00085 
00086 void IntelibGenericReader::
00087 AddStringLiteral(const char *str, int closing_char,
00088                  SReference (*fun)(const char*))
00089 {
00090     bool res = lexer->AddStringStarter(str, closing_char, fun);
00091     INTELIB_ASSERT(res, IntelibX_reader_error(lexer->GetErrorMessage(), -1));
00092 }
00093 
00094 void IntelibGenericReader::AddQuoter(const char *str, process_function proc)
00095 {
00096     SpecialLexic *sl = AddSpecialLexic(str, SpecialLexic::quoter, proc);
00097     bool res = lexer->AddDelimiter(str, sl->id);
00098     INTELIB_ASSERT(res, IntelibX_reader_error(lexer->GetErrorMessage(), -1));
00099 }
00100 
00101 void IntelibGenericReader::AddSequenceOpener(const char *str,
00102                                              process_function proc,
00103                                              const char *closer,
00104                                              const char *cons_sign,
00105                                              bool cons_sign_delimiter)
00106 {
00107     SReference closer_id;
00108     // first, check if the closer is already there
00109     for(SpecialLexic *p = first_sl; p; p = p->next) {
00110         if(p->id == closer) {
00111             closer_id = p->id;
00112             break;
00113         }
00114     }
00115     if(!closer_id.GetPtr()) {
00116         SpecialLexic *cls =
00117             AddSpecialLexic(closer, SpecialLexic::seq_closer, 0);
00118         lexer->AddDelimiter(closer, cls->id);
00119         closer_id = cls->id;
00120     }
00121 
00122     // next, if there's a cons_sign...
00123     SReference cons_sign_id;
00124     if(cons_sign) {
00125         for(SpecialLexic *p = first_sl; p; p = p->next) {
00126             if(p->id == cons_sign) {
00127                 cons_sign_id = p->id;
00128                 break;
00129             }
00130         }
00131         if(!cons_sign_id.GetPtr()) {
00132             SpecialLexic *cls =
00133                 AddSpecialLexic(cons_sign, SpecialLexic::cons_sign, 0);
00134             if(cons_sign_delimiter)
00135                 lexer->AddDelimiter(cons_sign, cls->id);
00136             else
00137                 lexer->AddNonDelimiter(cons_sign, cls->id);
00138             cons_sign_id = cls->id;
00139         }
00140     }
00141 
00142     // now add the opener
00143     SpecialLexic *sl = AddSpecialLexic(str, SpecialLexic::sequence, proc);
00144     lexer->AddDelimiter(str, sl->id);
00145     sl->the_closer = closer_id;
00146     sl->the_cons_sign = cons_sign_id;
00147 }
00148 
00149 void IntelibGenericReader::AddComment(const char *starter, const char *closer)
00150 {
00151     lexer->AddCommentStarter(starter, closer);
00152 }
00153 
00154 void IntelibGenericReader::SetLine(int l, const SString &afn)
00155 {
00156     lexer->SetLine(l);
00157     file_name = afn;
00158 }
00159 
00160 int IntelibGenericReader::GetLine() const
00161 {
00162     return lexer->GetLine();
00163 }
00164 
00165 void IntelibGenericReader::FeedChar(int c)
00166 {
00167     SListConstructor L;
00168     switch(lexer->FeedChar(c)) {
00169         case IntelibSLexAnalyser::res_empty: 
00170         case IntelibSLexAnalyser::res_continue:
00171             break; /* nothing to do */
00172         case IntelibSLexAnalyser::res_ready:
00173             HandleLexema(lexer->Get());
00174             break;
00175         case IntelibSLexAnalyser::res_eof:
00176             HandleEof();
00177             break;
00178         case IntelibSLexAnalyser::res_error:
00179             throw IntelibX_reader_error(
00180                 SString("lexical error: ") + lexer->GetErrorMessage(),
00181                 lexer->GetLine(),
00182                 -1,
00183                 file_name
00184             );
00185     }
00186 }
00187 
00188 void IntelibGenericReader::FeedString(const char *s)
00189 {
00190     while(*s) FeedChar(*s++);
00191 }
00192 
00193 SReference IntelibGenericReader::Get()
00194 {
00195     INTELIB_ASSERT(IsReady(), IntelibX_reader_not_ready());
00196     SReference res = ready.Car();
00197     ready.RemoveFirst();
00198     return res;
00199 }
00200 
00201 void IntelibGenericReader::Drop()
00202 {
00203     lexer->Drop();
00204     while(ready.RemoveFirst()) {}
00205     while(parts.RemoveFirst()) {}
00206     unclosed_brackets = 0;
00207 }
00208 
00209 SReference IntelibGenericReader::Read(const SStreamRef& stream)
00210 {
00211     SExpressionStreamTextInput *sti =
00212         stream.DynamicCastGetPtr<SExpressionStreamTextInput>();
00213     if(sti)
00214         lexer->SetLine(sti->TellLine());
00215     int c;
00216     do {
00217         c = stream->Getc();
00218         FeedChar(c);
00219     } while(!IsReady() && c != EOF);
00220     if(IsReady())
00221         return Get();
00222     else
00223         return EofMarker;
00224 }
00225 
00226 #if 0
00227 static bool is_prefix(const char *pr, const char *w)
00228 {
00229     for(;;pr++,w++) {
00230         if(!*pr) return true;
00231         if(*pr != *w) return false; // this covers w shorter that pr
00232     }
00233 }
00234 #endif
00235 
00236 static SLabel special_modifier("#<SM>");
00237 
00238 void IntelibGenericReader::HandleSpecialLex(SpecialLexic *sp, int line)
00239 {
00240     SListConstructor L;
00241     switch(sp->t) {
00242         case SpecialLexic::quoter:
00243             parts.Append((L|sp->id, line)||special_modifier);
00244             return;
00245         case SpecialLexic::sequence:
00246             parts.Append((L|sp->id, line)||special_modifier);
00247             unclosed_brackets++;
00248             return;
00249         case SpecialLexic::seq_closer:
00250             if(parts.IsEmpty() || unclosed_brackets<1) {
00251                 throw IntelibX_reader_error("unexpected sequence closer",
00252                                             line, -1, file_name);
00253             }
00254             parts.Append((L|sp->id, line)||special_modifier);
00255             unclosed_brackets--;
00256             if(unclosed_brackets == 0) 
00257                 FinishParts();
00258             return;
00259         case SpecialLexic::cons_sign:
00260             if(parts.IsEmpty() || unclosed_brackets<1) {
00261                 throw IntelibX_reader_error("unexpected pair constructor",
00262                                             line, -1, file_name);
00263             }
00264             parts.Append((L|sp->id, line)||special_modifier);
00265             return;
00266     }
00267 }
00268 
00269 void IntelibGenericReader::HandleLexema(const SReference &lexpair)
00270 {
00271     SListConstructor L;
00272     SReference lex = lexpair.Car();
00273     int line = lexpair.Cdr().GetInt();
00274 
00275     // first of all, determine whether it is special
00276     for(SpecialLexic *p = first_sl; p; p = p->next) {
00277         if(p->id.GetPtr() == lex.GetPtr()) {
00278             HandleSpecialLex(p, line);
00279             return;
00280         }
00281     }
00282 
00283    SExpressionClassicAtom *ca = 
00284        lex.SimpleCastGetPtr<SExpressionClassicAtom>();
00285    if(ca) { 
00286        lex = DoMakeSymbol(ca->GetValue());
00287    }
00288    if(parts.IsEmpty()) {
00289        ready.Append(lex);
00290    } else {
00291        parts.Append((L|lex, lexpair.Cdr()));
00292        if(unclosed_brackets == 0) FinishParts();
00293    }
00294 }
00295 
00296 SReference IntelibGenericReader::DoMakeSymbol(const char *s) const
00297 {
00298     if(uppercase) {
00299         char *str = new char[strlen(s)+1];
00300         int i;
00301         for(i = 0; s[i]!='\0'; i++) str[i] = toupper(s[i]);
00302         str[i] = 0;
00303         SReference tmp = the_package->MakeSymbol(str);
00304         delete[] str;
00305         return tmp;
00306     } else {
00307         return the_package->MakeSymbol(s);
00308     }
00309 }
00310 
00311 void IntelibGenericReader::HandleEof()
00312 {
00313     if(!parts.IsEmpty()) {
00314         throw IntelibX_reader_error("unexpected eof", 
00315                                     lexer->GetLine(),
00316                                     parts.Car().Cdr().Car().GetInt(),
00317                                     file_name);
00318     }
00319     ready.Append(EofMarker);
00320 }
00321 
00322 void IntelibGenericReader::FinishParts()
00323 {
00324     ready.Append(DoFinishParts());
00325     while(parts.RemoveFirst()) {}
00326     unclosed_brackets = 0;
00327 }
00328 
00329 SReference IntelibGenericReader::DoFinishParts()
00330 {
00331     SReference lex = parts.Car().Car();
00332     int line = parts.Car().Cdr().Car().GetInt();
00333     SReference modifier = parts.Car().Cdr().Cdr();
00334     parts.RemoveFirst();
00335 
00336     if(modifier.IsEmptyList()) {
00337         // nothing special...
00338         return lex;
00339     }
00340 
00341     // okay, it's definitely something special
00342     for(SpecialLexic *p = first_sl; p; p = p->next) {
00343         if(p->id.GetPtr() == lex.GetPtr()) {
00344             switch(p->t) {
00345                 case SpecialLexic::quoter:
00346                     return p->process(DoFinishParts());
00347                 case SpecialLexic::sequence:
00348                     return p->process(
00349                         DoFinishPartsSeq(p->the_closer,
00350                                          p->the_cons_sign, line));
00351                 case SpecialLexic::seq_closer:
00352                     throw IntelibX_reader_error("unexpected sequence closer", 
00353                                     line, -1, file_name);
00354                 case SpecialLexic::cons_sign:
00355                     throw IntelibX_reader_error("unexpected pair constructor", 
00356                                     line, -1, file_name);
00357             }
00358         }
00359     }
00360 
00361     // being here means the lex is marked as special but not found in the
00362     // list of special lexems
00363     throw IntelibX_bug();
00364 }
00365 
00366 SReference IntelibGenericReader::
00367 DoFinishPartsSeq(const SReference& closer,
00368                  const SReference& conser,
00369                  int begline)
00370 {
00371     SQueue res;
00372     for(;;) {
00373         SReference lex = parts.Car().Car();
00374         //int line = parts.Car().Cdr().Car().GetInt();
00375         SReference modifier = parts.Car().Cdr().Cdr();
00376 
00377         if(lex.GetPtr() == closer.GetPtr()) { // end of the seq
00378             parts.RemoveFirst();
00379             if(res.IsEmpty()) {
00380                 return *PTheEmptyList;
00381             } else {
00382                 return SReference(res);
00383             }
00384         } else 
00385         if(conser.GetPtr() && (lex.GetPtr() == conser.GetPtr())) { 
00386             parts.RemoveFirst();
00387             SReference last = DoFinishParts();
00388             if(parts.Car().Car().GetPtr() != closer.GetPtr()) {
00389                 throw IntelibX_reader_error("sequence closer expected",
00390                                      parts.Car().Cdr().Car().GetInt(),
00391                                      begline, file_name);
00392             }
00393             parts.RemoveFirst();
00394             if(res.IsEmpty()) {
00395                 throw IntelibX_reader_error("incorrect dotted sequence",
00396                                      parts.Car().Cdr().Car().GetInt(),
00397                                      begline, file_name);
00398             }
00399             SReference res_r(res);
00400             res_r||last;
00401             return res_r;
00402         } else 
00403         if(modifier.IsEmptyList()) {
00404             res.Append(lex); 
00405             parts.RemoveFirst();
00406         } else {
00407             // this is in turn something special
00408             res.Append(DoFinishParts());   
00409         }
00410     }    
00411 }
00412 
00414 // IntelibReader 
00415 
00416 static SReference process_char_escape(const char *name)
00417 {
00418     static const struct {
00419         const char *name;
00420         char val;
00421     } charnames[] = {
00422         { "NEWLINE", '\n' },
00423         { "SPACE", ' ' },
00424         { "TAB", '\t' },
00425         { "BACKSPACE", '\010' },
00426         { "LINEFEED", '\012' },
00427         { "PAGE", '\014' },
00428         { "RETURN", '\015' },
00429         { "RUBOUT", '\177' },
00430         { 0, 0 }
00431     };
00432     if(name[1] == 0) { // single char
00433         return SReference((char)(name[0]));
00434     }
00435     int i;
00436     for(i = 0; charnames[i].name; i++) {
00437         if(strcasecmp(name, charnames[i].name) == 0)
00438             return SReference(charnames[i].val);
00439     }
00440     throw IntelibX_reader_error("unknown_char_name", -1, -1, "");
00441 }
00442 
00443 static SReference process_plain_list(const SReference &a)
00444 {
00445     return a;
00446 }
00447 
00448 IntelibReader::IntelibReader()
00449 {
00450     AddTokenType("#\\", process_char_escape);
00451     AddStringLiteral("\"", '\"');
00452     AddSequenceOpener("(", process_plain_list, ")", ".", false);
00453     AddComment(";");
00454 }
00455 
00457 // Dummy package
00458 
00459 SReference IntelibDummyPackage::MakeSymbol(const char *s)
00460 {
00461     return SReference(new SExpressionClassicAtom(s));
00462 }
00463 
00464 IntelibDummyPackage TheDummyPackage;
00465 
00466 
00468 //
00469 
00470 IntelibGenericReader *PTheIntelibReader = 0;
00471 
00473 // exceptions
00474 
00475 
00476 IntelibX_reader_error::
00477 IntelibX_reader_error(SReference a_param, int a_line, int a_b_line,
00478                       const SString &afn) 
00479     : IntelibX("Reader encountered an error", a_param), fname(afn)
00480  
00481 { line = a_line; beg_line = a_b_line; }
00482 
00483 IntelibX_reader_not_ready::
00484 IntelibX_reader_not_ready() 
00485     : IntelibX("IntelibGenericReader::Get() called when IsReady() is false") 
00486 {}
00487 
00488 IntelibX_read_eof::
00489 IntelibX_read_eof(SReference a_param) 
00490     : IntelibX("Unexpected end of file", a_param) 
00491 {}

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