00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <stdio.h>
00037 #include <string.h>
00038 #include <stdarg.h>
00039 #if !defined(_MSC_VER)
00040 #include <sys/time.h>
00041 #endif
00042 #include "ptree.h"
00043 #include "token.h"
00044 #include "mop.h"
00045
00046 #if (defined(sun) && defined(SUNOS4)) || defined(SUNOS5)
00047 extern "C" {
00048 int gettimeofday(struct timeval*, void*);
00049 };
00050 #endif
00051
00052 const int MAX = 32;
00053
00054 static Ptree** resultsArgs[MAX];
00055 static int resultsIndex;
00056
00057 static int CountArgs(char* pat);
00058 static char* SkipSpaces(char* pat);
00059
00060 bool Ptree::Match(Ptree* list, char* pattern, ...)
00061 {
00062 va_list args;
00063 int n = CountArgs(pattern);
00064 if(n >= MAX)
00065 MopErrorMessage("Ptree::Match()", "bomb! too many arguments");
00066
00067 va_start(args, pattern);
00068 for(int i = 0; i < n; ++i)
00069 resultsArgs[i] = va_arg(args, Ptree**);
00070
00071 va_end(args);
00072
00073 char* pat = pattern;
00074 resultsIndex = 0;
00075 pat = SkipSpaces(pat);
00076 pat = MatchPat(list, pat);
00077 if(pat == nil)
00078 return FALSE;
00079 else{
00080 pat = SkipSpaces(pat);
00081 if(*pat == '\0')
00082 return TRUE;
00083 else{
00084 MopWarningMessage("Ptree::Match()", "[ ] are forgot?");
00085 MopMoreWarningMessage(pattern);
00086 return FALSE;
00087 }
00088 }
00089 }
00090
00091 static int CountArgs(char* pat)
00092 {
00093 int n = 0;
00094
00095 for(char c = *pat; c != '\0'; c = *++pat)
00096 if(c == '%'){
00097 c = *++pat;
00098 if(c == '?' || c == 'r')
00099 ++n;
00100 }
00101
00102 return n;
00103 }
00104
00105 char* Ptree::MatchPat(Ptree* list, char* pat)
00106 {
00107 switch(*pat){
00108 case '[' :
00109 if(list != nil && list->IsLeaf())
00110 return nil;
00111 else
00112 return MatchList(list, pat + 1);
00113 case '%' :
00114 switch(pat[1]){
00115 case '?' :
00116 *resultsArgs[resultsIndex++] = list;
00117 return(pat + 2);
00118 case '*' :
00119 return(pat + 2);
00120 case '_' :
00121 case 'r' :
00122 return nil;
00123 default :
00124 break;
00125 }
00126 }
00127
00128 if(list != nil && list->IsLeaf())
00129 return MatchWord(list, pat);
00130 else
00131 return nil;
00132 }
00133
00134 char* Ptree::MatchList(Ptree* list, char* pat)
00135 {
00136 char c, d;
00137 pat = SkipSpaces(pat);
00138 while((c = *pat) != '\0'){
00139 if(c == ']')
00140 if(list == nil)
00141 return(pat + 1);
00142 else
00143 return nil;
00144 else if(c == '%' && (d = pat[1], (d == 'r' || d == '_'))){
00145
00146 if(d == 'r')
00147 *resultsArgs[resultsIndex++] = list;
00148
00149 list = nil;
00150 pat = pat + 2;
00151 }
00152 else if(list == nil)
00153 return nil;
00154 else{
00155 pat = MatchPat(list->Car(), pat);
00156 if(pat == nil)
00157 return nil;
00158
00159 list = list->Cdr();
00160 }
00161
00162 pat = SkipSpaces(pat);
00163 }
00164
00165 MopErrorMessage("Ptree::Match()", "unmatched bracket");
00166 return nil;
00167 }
00168
00169 char* Ptree::MatchWord(Ptree* list, char* pat)
00170 {
00171 char* str = list->GetPosition();
00172 int str_len = list->GetLength();
00173
00174 for(int j = 0; ; ++pat){
00175 char c = *pat;
00176 switch(c){
00177 case '\0' :
00178 case ' ' :
00179 case '\t' :
00180 case '[' :
00181 case ']' :
00182 if(j == str_len)
00183 return pat;
00184 else
00185 return nil;
00186 case '%' :
00187 c = *++pat;
00188 switch(c){
00189 case '[' :
00190 case ']' :
00191 case '%' :
00192 if(j >= str_len || c != str[j++])
00193 return nil;
00194
00195 break;
00196 default :
00197 if(j == str_len)
00198 return pat;
00199 else
00200 return nil;
00201 }
00202 break;
00203 default :
00204 if(j >= str_len || c != str[j++])
00205 return nil;
00206 }
00207 }
00208 }
00209
00210 static char* SkipSpaces(char* pat)
00211 {
00212 while(*pat == ' ' || *pat == '\t')
00213 ++pat;
00214
00215 return pat;
00216 }
00217
00218 Ptree* Ptree::GenSym()
00219 {
00220 #if !defined(_MSC_VER)
00221 struct timeval time;
00222 #endif
00223 static char head[] = "_sym";
00224 static int seed = 1;
00225 int len1, len2;
00226
00227 IntegerToString(seed, len1);
00228
00229 #if !defined(_MSC_VER)
00230 gettimeofday(&time, NULL);
00231 uint rnum = (time.tv_sec * 10 + time.tv_usec / 100) & 0xffff;
00232 #else
00233 static uint time = 0;
00234 time++;
00235 uint rnum = time & 0xffff;
00236 #endif
00237 char* num = IntegerToString(rnum, len2);
00238
00239 int size = len1 + len2 + sizeof(head) - 1 + 1;
00240 char* name = new (GC) char[size];
00241 memmove(name, head, sizeof(head) - 1);
00242 memmove(&name[sizeof(head) - 1], num, len2);
00243 name[sizeof(head) - 1 + len2] = '_';
00244 num = IntegerToString(seed++, len1);
00245 memmove(&name[sizeof(head) - 1 + len2 + 1], num, len1);
00246 return new Leaf(name, size);
00247 }
00248
00249
00250
00251 Ptree* Ptree::Make(const char* pat, ...)
00252 {
00253 va_list args;
00254 const int N = 4096;
00255 static char buf[N];
00256 char c;
00257 int len;
00258 char* ptr;
00259 Ptree* p;
00260 Ptree* q;
00261 int i = 0, j = 0;
00262 Ptree* result = nil;
00263
00264 va_start(args, pat);
00265 while((c = pat[i++]) != '\0')
00266 if(c == '%'){
00267 c = pat[i++];
00268 if(c == '%')
00269 buf[j++] = c;
00270 else if(c == 'd'){
00271 ptr = IntegerToString(va_arg(args, int), len);
00272 memmove(&buf[j], ptr, len);
00273 j += len;
00274 }
00275 else if(c == 's'){
00276 ptr = va_arg(args, char*);
00277 len = strlen(ptr);
00278 memmove(&buf[j], ptr, len);
00279 j += len;
00280 }
00281 else if(c == 'c')
00282 buf[j++] = va_arg(args, int);
00283 else if(c == 'p'){
00284 p = va_arg(args, Ptree*);
00285 if(p == nil)
00286 ;
00287 else if(p->IsLeaf()){
00288 memmove(&buf[j], p->GetPosition(), p->GetLength());
00289 j += p->GetLength();
00290 }
00291 else{
00292 if(j > 0)
00293 q = List(new DupLeaf(buf, j), p);
00294 else
00295 q = List(p);
00296
00297 j = 0;
00298 result = Nconc(result, q);
00299 }
00300 }
00301 else
00302 MopErrorMessage("Ptree::Make()", "invalid format");
00303 }
00304 else
00305 buf[j++] = c;
00306
00307 va_end(args);
00308
00309 if(j > 0)
00310 if(result == nil)
00311 result = new DupLeaf(buf, j);
00312 else
00313 result = Snoc(result, new DupLeaf(buf, j));
00314
00315 return result;
00316 }
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 Ptree* Ptree::MakeStatement(const char* pat, ...)
00327 {
00328 va_list args;
00329 const int N = 4096;
00330 static char buf[N];
00331 char c;
00332 int len;
00333 char* ptr;
00334 Ptree* p;
00335 Ptree* q;
00336 int i = 0, j = 0;
00337 Ptree* result = nil;
00338
00339 va_start(args, pat);
00340
00341 Class::WarnObsoleteness("Ptree::MakeStatement()", "Ptree::Make()");
00342
00343 while((c = pat[i++]) != '\0')
00344 if(c == '%'){
00345 c = pat[i++];
00346 if(c == '%')
00347 buf[j++] = c;
00348 else if(c == 'd'){
00349 ptr = IntegerToString(va_arg(args, int), len);
00350 memmove(&buf[j], ptr, len);
00351 j += len;
00352 }
00353 else if(c == 's'){
00354 ptr = va_arg(args, char*);
00355 len = strlen(ptr);
00356 memmove(&buf[j], ptr, len);
00357 j += len;
00358 }
00359 else if(c == 'c')
00360 buf[j++] = va_arg(args, int);
00361 else if(c == 'p'){
00362 p = va_arg(args, Ptree*);
00363 if(p == nil)
00364 ;
00365 else if(p->IsLeaf()){
00366 memmove(&buf[j], p->GetPosition(), p->GetLength());
00367 j += p->GetLength();
00368 }
00369 else{
00370 if(j > 0)
00371 q = new DupLeaf(buf, j);
00372 else
00373 q = nil;
00374
00375 j = 0;
00376 result = Nconc(result, List(q, p));
00377 }
00378 }
00379 else
00380 MopErrorMessage("Ptree::MakeStatement()", "invalid format");
00381 }
00382 else
00383 buf[j++] = c;
00384
00385 va_end(args);
00386
00387 if(j > 0)
00388 if(result == nil)
00389 result = new DupLeaf(buf, j);
00390 else
00391 result = Snoc(result, new DupLeaf(buf, j));
00392
00393 return result;
00394 }
00395
00396 bool Ptree::Reify(unsigned int& value)
00397 {
00398 return Lex::Reify(this, value);
00399 }
00400
00401 bool Ptree::Reify(char*& str)
00402 {
00403 return Lex::Reify(this, str);
00404 }
00405
00406 char* Ptree::IntegerToString(sint num, int& length)
00407 {
00408 const int N = 16;
00409 static char buf[N];
00410 bool minus;
00411
00412 int i = N - 1;
00413 if(num >= 0)
00414 minus = FALSE;
00415 else{
00416 minus = TRUE;
00417 num = -num;
00418 }
00419
00420 buf[i--] = '\0';
00421 if(num == 0){
00422 buf[i] = '0';
00423 length = 1;
00424 return &buf[i];
00425 }
00426 else{
00427 while(num > 0){
00428 buf[i--] = '0' + char(num % 10);
00429 num /= 10;
00430 }
00431
00432 if(minus)
00433 buf[i--] = '-';
00434
00435 length = N - 2 - i;
00436 return &buf[i + 1];
00437 }
00438 }
00439
00440 Ptree* Ptree::qMake(char*)
00441 {
00442 MopErrorMessage("Ptree::qMake()",
00443 "the metaclass must be compiled by OpenC++.");
00444 return nil;
00445 }
00446
00447 Ptree* Ptree::qMakeStatement(char*)
00448 {
00449 MopErrorMessage("Ptree::qMakeStatement()",
00450 "the metaclass must be compiled by OpenC++.");
00451 return nil;
00452 }
00453
00454
00455
00456 PtreeHead& PtreeHead::operator + (Ptree* p)
00457 {
00458 ptree = Append(ptree, p);
00459 return *this;
00460 }
00461
00462 PtreeHead& PtreeHead::operator + (const char* str)
00463 {
00464 if(*str != '\0')
00465 ptree = Append(ptree, (char*)str, strlen(str));
00466
00467 return *this;
00468 }
00469
00470 PtreeHead& PtreeHead::operator + (char* str)
00471 {
00472 if(*str != '\0')
00473 ptree = Append(ptree, str, strlen(str));
00474
00475 return *this;
00476 }
00477
00478 PtreeHead& PtreeHead::operator + (char c)
00479 {
00480 ptree = Append(ptree, &c, 1);
00481 return *this;
00482 }
00483
00484 PtreeHead& PtreeHead::operator + (int n)
00485 {
00486 int len;
00487 char* str = Ptree::IntegerToString(n, len);
00488 ptree = Append(ptree, str, len);
00489 return *this;
00490 }
00491
00492 Ptree* PtreeHead::Append(Ptree* lst, Ptree* tail)
00493 {
00494 Ptree* last;
00495 Ptree* p;
00496 Ptree* q;
00497
00498 if(tail == nil)
00499 return lst;
00500
00501 if(!tail->IsLeaf() && tail->Length() == 1){
00502 tail = tail->Car();
00503 if(tail == nil)
00504 return lst;
00505 }
00506
00507 if(tail->IsLeaf() && lst != nil){
00508 last = Ptree::Last(lst);
00509 if(last != nil){
00510 p = last->Car();
00511 if(p != nil && p->IsLeaf()){
00512 q = new DupLeaf(p->GetPosition(), p->GetLength(),
00513 tail->GetPosition(), tail->GetLength());
00514 last->SetCar(q);
00515 return lst;
00516 }
00517 }
00518 }
00519
00520 return Ptree::Snoc(lst, tail);
00521 }
00522
00523 Ptree* PtreeHead::Append(Ptree* lst, char* str, int len)
00524 {
00525 Ptree* last;
00526 Ptree* p;
00527 Ptree* q;
00528
00529 if(lst != nil){
00530 last = Ptree::Last(lst);
00531 if(last != nil){
00532 p = last->Car();
00533 if(p != nil && p->IsLeaf()){
00534 q = new DupLeaf(p->GetPosition(), p->GetLength(),
00535 str, len);
00536 last->SetCar(q);
00537 return lst;
00538 }
00539 }
00540 }
00541
00542 return Ptree::Snoc(lst, new DupLeaf(str, len));
00543 }