Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

pattern.cc

Go to the documentation of this file.
00001 /*
00002   Copyright (C) 1997-2001 Shigeru Chiba, Tokyo Institute of Technology.
00003 
00004   Permission to use, copy, distribute and modify this software and   
00005   its documentation for any purpose is hereby granted without fee,        
00006   provided that the above copyright notice appear in all copies and that 
00007   both that copyright notice and this permission notice appear in 
00008   supporting documentation.
00009 
00010   Shigeru Chiba makes no representations about the suitability of this 
00011   software for any purpose.  It is provided "as is" without express or
00012   implied warranty.
00013 */
00014 
00015 /*
00016   Copyright (c) 1995, 1996 Xerox Corporation.
00017   All Rights Reserved.
00018 
00019   Use and copying of this software and preparation of derivative works
00020   based upon this software are permitted. Any copy of this software or
00021   of any derivative work must include the above copyright notice of
00022   Xerox Corporation, this paragraph and the one after it.  Any
00023   distribution of this software or derivative works must comply with all
00024   applicable United States export control laws.
00025 
00026   This software is made available AS IS, and XEROX CORPORATION DISCLAIMS
00027   ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
00028   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029   PURPOSE, AND NOTWITHSTANDING ANY OTHER PROVISION CONTAINED HEREIN, ANY
00030   LIABILITY FOR DAMAGES RESULTING FROM THE SOFTWARE OR ITS USE IS
00031   EXPRESSLY DISCLAIMED, WHETHER ARISING IN CONTRACT, TORT (INCLUDING
00032   NEGLIGENCE) OR STRICT LIABILITY, EVEN IF XEROX CORPORATION IS ADVISED
00033   OF THE POSSIBILITY OF SUCH DAMAGES.
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 '[' :          /* [] means nil */
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' :      /* %_ and %r must be appear in a list */
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             /* %r or %_ */
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 // If you edit Make(), you should also edit MakeStatement().
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                     /* ignore */;
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   MakeStatement() is identical to Make() except that the generated
00320   code is wrapped by a PtreeNonExpr object.
00321   This helps code-traverse functions such as WalkExpr() distinguish
00322   statements from expressions.
00323 
00324   Note: this version is perfectly identical to Make(). 97/3/26
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                     /* ignore */;
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 // class PtreeHead      --- this is used to implement Ptree::qMake().
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 }

Generated on Mon Feb 10 17:32:54 2003 for VFiasco Semantics Compiler by doxygen1.2.15