00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "pent_include.h"
00022
00023
00024
00025 #undef yyFlexLexer
00026 #define yyFlexLexer llcFlexLexer
00027 #include "llcLexer.h"
00028
00029
00030
00031
00032
00033 #include <list>
00034 using std::list;
00035 #include <fstream>
00036 using std::ifstream;
00037 #include <iomanip>
00038 #include <string>
00039 #include <cassert>
00040
00041 #include "llcTokens.h"
00042
00043 #include "CoreApp.h"
00044
00045
00046 #define CTRACE(x) perr << x << std::endl
00047
00048 const char *UNKNOWN_ERR = "Unknown Expression.";
00049
00050 const char * const random_generic_errors[] =
00051 {
00052 "Ugh! That's got to be the sickest thing I've ever seen!\n ...next to that poncy git there.\n\t--Giants: Citizen Kabuto",
00053 "Hark! Is that the sweet song of lamentation I hear?\n\t-- The Guardian, Ultima 8",
00054 "I do so enjoy the cries of torment.\n\t-- The Guardian, Ultima 8",
00055 "Ouch! -That- must have hurt, Avatar!\n\t-- The Guardian, Ultima 8",
00056
00057 ""
00058 };
00059
00060 #ifdef USE_CQUIRKS
00061 #define QUIRK(X, Y) X
00062 #else
00063 #define QURIK(X, Y) Y
00064 #endif
00065
00066 #define ICE_ME(X) { msg(MT_ICE, X, this); return true; }
00067
00068
00069
00070
00071 enum MsgType { MT_MSG, MT_WARN, MT_ERR, MT_ICE };
00072
00073 class CompileUnit;
00074
00075 MsgType msg(const MsgType msgType, const char * const msgDetails, CompileUnit *cu=0);
00076
00077
00078
00079 #include "CompileUnit.h"
00080
00081 CompileUnit::CompileUnit(FileSystem *filesystem) : currclass(0), ifile(0), idatasource(0),
00082 parser(0), filesys(filesystem), _state(CSTATE_NEW), _ccomplete(false),
00083 _expect(LLC_NONE), _warned(false)
00084 #ifdef COMPILER_TEST
00085 , testidx(0)
00086 #endif
00087 {
00088 setState(CSTATE_NEW);
00089 filesys->ListFiles("@work/usecode/src/*", filelist);
00090 for(FileSystem::FileList::iterator i=filelist.begin(); i!=filelist.end(); i++)
00091 pout << "FILE: " << *i << std::endl;
00092
00093 #ifdef COMPILER_TEST
00094
00095
00096 filelist.push_back("@work/usecode/src/nothing.llc");
00097
00098 filelist.push_back("@work/usecode/src/empty-class.llc");
00099 #endif
00100 }
00101
00102
00103 void CompileUnit::debugPrint(std::ostream &o, CompileNode *n) const
00104 {
00105 debugPrintHead(o, n);
00106 n->print_unk(o);
00107 debugPrint(o);
00108 }
00109
00110 void CompileUnit::debugPrint(std::ostream &o) const
00111 {
00112 debugPrintHead(o);
00113 debugPrintBody(o);
00114 }
00115
00116 void CompileUnit::debugPrintHead(std::ostream &o, CompileNode *n) const
00117 {
00118 o << "Compile Stack:" << std::endl;
00119 if(n!=0)
00120 o << std::setw(4) << n->linenum << ": ";
00121 else
00122 if(nodes.size())
00123 o << std::setw(4) << nodes.front()->linenum << ": ";
00124 }
00125
00126 void CompileUnit::debugPrintBody(std::ostream &o) const
00127 {
00128 for(std::list<CompileNode *>::const_iterator i=nodes.begin(); i!=nodes.end(); i++)
00129 {
00130 o << '\t';
00131 (*i)->print_unk(o);
00132 o << std::endl;
00133 }
00134 }
00135
00136 #ifdef COMPILER_TEST
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 #endif
00147
00148 bool CompileUnit::consume(const LLCToken &tok)
00149 {
00150 if(found(tok))
00151 nodes.pop_front();
00152 else
00153 ICE_ME("Errornous token encountered in stream in CompileUnit::consume()");
00154
00155 return false;
00156 }
00157
00158 bool CompileUnit::parse()
00159 {
00160 CTRACE("CompileUnit::parse()");
00161
00162 std::string fname;
00163
00164 if(!parser || state()==CSTATE_FINISHED)
00165 {
00166 #ifdef COMPILER_TEST
00167
00168
00169 #endif
00170 assert(filelist.size());
00171 fname = filelist.back();
00172 filelist.pop_back();
00173 pout << "Opening... " << fname << std::endl;
00174
00175 idatasource = filesys->ReadFile(fname.c_str());
00176 assert(idatasource!=0);
00177 ifile = idatasource->GetRawIfstream();
00178
00179 assert((ifile!=0) && (!ifile->fail()));
00180
00181 parser = new llcFlexLexer(ifile, 0);
00182
00183 }
00184
00185 sint32 token=parser->yylex();
00186 switch(token)
00187 {
00188
00189 case LLC_XFAIL: _expect=LLC_XFAIL; return true; break;
00190 case LLC_XPASS: _expect=LLC_XPASS; return true; break;
00191 case LLC_XWARN: _expect=LLC_XWARN; return true; break;
00192
00193
00194 case LLC_CLASS:
00195 nodes.push_back(new ClassNode(parser->lineno()));
00196 break;
00197 case LLC_IDENT:
00198 nodes.push_back(new VarIdentNode(parser->YYText(), parser->lineno()));
00199 break;
00200 case LLC_OPEN_BRACE:
00201
00202 nodes.push_back(new FencePostNode(LLC_OPEN_BRACE, parser->lineno()));
00203 return parse_openblock();
00204 break;
00205 case LLC_CLOSE_BRACE:
00206 nodes.push_back(new FencePostNode(LLC_CLOSE_BRACE, parser->lineno()));
00207 return parse_closeblock();
00208 break;
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 case LLC_EOF:
00223 if(currclass==0)
00224 msg(MT_WARN, "Encountered end-of-file without encountering a class definition.");
00225 setState(CSTATE_FINISHED);
00226 return true;
00227 break;
00228 default:
00229 con.Printf("\n%d\n", token);
00230 return false;
00231 }
00232
00233 return false;
00234 }
00235
00236 bool CompileUnit::parse_openblock()
00237 {
00238 CTRACE("CompileUnit::parse_openblock()");
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 if(nodes.size()==0)
00252 ICE_ME("Empty nodes stack should not occur within CompileUnit::parse_openblock()");
00253
00254
00255
00256 if(found(LLC_CLASS))
00257 {
00258 if(currclass!=0)
00259 {
00260 msg(MT_ERR, "Class already defined in this file.", this);
00261 return true;
00262 }
00263
00264 currclass = static_cast<ClassNode *>(nodes.front());
00265 nodes.pop_front();
00266
00267
00268
00269 if(!found(LLC_IDENT))
00270 {
00271 nodes.push_front(currclass); currclass=0;
00272 msg(MT_ERR, "Class name not found in declaration.", this);
00273 return true;
00274 }
00275
00276 currclass->name=static_cast<VarIdentNode *>(nodes.front())->str;
00277 nodes.pop_front();
00278
00279 if(!found(LLC_INHERITS) && !found(LLC_OPEN_BRACE))
00280 {
00281 nodes.push_front(currclass); currclass=0;
00282 msg(MT_ERR, "Badly formed class expression: 'inherits' or '{' expected.", this);
00283 return true;
00284 }
00285
00286
00287 if(found(LLC_OPEN_BRACE))
00288 {
00289 consume(LLC_OPEN_BRACE);
00290 return true;
00291 }
00292
00293 if(found(LLC_INHERITS))
00294 {
00295
00296 }
00297
00298 return false;
00299 }
00300
00301 else if(found(LLC_OPEN_BRACE))
00302 {
00303 msg(MT_ERR, "Incorrectly defined block {", this);
00304 return true;
00305 }
00306 else
00307 {
00308 debugPrint(pout); assert(false);
00309 }
00310
00311 return false;
00312 };
00313
00314
00315 bool CompileUnit::parse_closeblock()
00316 {
00317 CTRACE("CompileUnit::parse_openblock()");
00318
00319
00320
00321
00322
00323
00324
00325 if(nodes.size()==0)
00326 ICE_ME("Empty nodes stack should not occur within CompileUnit::parse_closeblock()");
00327
00328
00329 if(nodes.size()>1 || !found(LLC_CLOSE_BRACE))
00330 ICE_ME("Unknown tokens before block terminator.");
00331
00332 consume(LLC_CLOSE_BRACE);
00333
00334 return false;
00335 }
00336
00337 bool CompileUnit::setState(const CState cs)
00338 {
00339 switch(cs)
00340 {
00341
00342 case CSTATE_NEW:
00343
00344 if(_state==CSTATE_FINISHED && nodes.size()!=0)
00345 ICE_ME("Nodes stack should be empty on successful compile, it isn't! CompileUnit::setState()");
00346 nodes.clear();
00347 if(currclass!=0)
00348 tailclasses.push_back(currclass);
00349 currclass=0;
00350 FORGET_OBJECT(idatasource);
00351 ifile=0;
00352 FORGET_OBJECT(parser);
00353 _warned=false;
00354 _expect=LLC_NONE;
00355 _state=cs;
00356 break;
00357 case CSTATE_FINISHED:
00358 case CSTATE_FAIL:
00359 case CSTATE_WORKING:
00360 _state=cs;
00361 break;
00362 case CSTATE_WARNED:
00363 _warned=true;
00364 break;
00365 default:
00366 CANT_HAPPEN();
00367 break;
00368 }
00369 return false;
00370 }
00371
00372
00373
00374
00375 MsgType msg(const MsgType msgType, const char * const msgDetails, CompileUnit *cu)
00376 {
00377 switch(msgType)
00378 {
00379 case MT_MSG:
00380 con.Printf_err("%s\n", msgDetails);
00381 break;
00382 case MT_WARN:
00383 if(cu!=0) cu->debugPrint(pout);
00384 con.Printf_err("Warning: %s\n", msgDetails);
00385 cu->setState(CompileUnit::CSTATE_WARNED);
00386 break;
00387 case MT_ERR:
00388 assert(cu!=0);
00389 cu->debugPrint(pout);
00390 con.Printf_err("Error: %s\n", msgDetails);
00391 cu->setState(CompileUnit::CSTATE_FAIL);
00392 break;
00393 case MT_ICE:
00394 con.Printf_err("Internal Compile Error: %s\n", msgDetails);
00395 con.Printf_err(">> Attempting to dump internal datastacks...\n");
00396 assert(cu!=0);
00397 cu->debugPrint(pout);
00398 cu->setState(CompileUnit::CSTATE_FAIL);
00399 break;
00400 default:
00401 assert(false);
00402 }
00403 return msgType;
00404 }
00405
00406