00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
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
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
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;
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;
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
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
00338 return lex;
00339 }
00340
00341
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
00362
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
00375 SReference modifier = parts.Car().Cdr().Cdr();
00376
00377 if(lex.GetPtr() == closer.GetPtr()) {
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
00408 res.Append(DoFinishParts());
00409 }
00410 }
00411 }
00412
00414
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) {
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
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
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 {}