diff options
-rw-r--r-- | libraries/README | 2 | ||||
-rw-r--r-- | libraries/lemon/lemon.c | 378 |
2 files changed, 264 insertions, 116 deletions
diff --git a/libraries/README b/libraries/README index 57f81b3..8ef38d3 100644 --- a/libraries/README +++ b/libraries/README | |||
@@ -13,6 +13,8 @@ Irrlicht has been slightly modified to get it to use externally created | |||
13 | GL stuff, and not use their internal copies of bzip, jpeglib, libpng, | 13 | GL stuff, and not use their internal copies of bzip, jpeglib, libpng, |
14 | and zlib. | 14 | and zlib. |
15 | 15 | ||
16 | Lemon is from http://www.hwaci.com/sw/lemon/. | ||
17 | |||
16 | LuaJIT 2.0 has been released for Ubuntu 13.04 and later, try using | 18 | LuaJIT 2.0 has been released for Ubuntu 13.04 and later, try using |
17 | https://launchpad.net/~mwild1/+archive/ppa for 12.04. Not including | 19 | https://launchpad.net/~mwild1/+archive/ppa for 12.04. Not including |
18 | that anymore. | 20 | that anymore. |
diff --git a/libraries/lemon/lemon.c b/libraries/lemon/lemon.c index c3e612b..8dca20c 100644 --- a/libraries/lemon/lemon.c +++ b/libraries/lemon/lemon.c | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | #ifndef __WIN32__ | 16 | #ifndef __WIN32__ |
17 | # if defined(_WIN32) || defined(WIN32) | 17 | # if defined(_WIN32) || defined(WIN32) |
18 | # define __WIN32__ | 18 | # define __WIN32__ |
19 | # endif | 19 | # endif |
20 | #endif | 20 | #endif |
21 | 21 | ||
@@ -50,6 +50,107 @@ static char *msort(char*,char**,int(*)(const char*,const char*)); | |||
50 | */ | 50 | */ |
51 | #define lemonStrlen(X) ((int)strlen(X)) | 51 | #define lemonStrlen(X) ((int)strlen(X)) |
52 | 52 | ||
53 | /* | ||
54 | ** Compilers are starting to complain about the use of sprintf() and strcpy(), | ||
55 | ** saying they are unsafe. So we define our own versions of those routines too. | ||
56 | ** | ||
57 | ** There are three routines here: lemon_sprintf(), lemon_vsprintf(), and | ||
58 | ** lemon_addtext(). The first two are replacements for sprintf() and vsprintf(). | ||
59 | ** The third is a helper routine for vsnprintf() that adds texts to the end of a | ||
60 | ** buffer, making sure the buffer is always zero-terminated. | ||
61 | ** | ||
62 | ** The string formatter is a minimal subset of stdlib sprintf() supporting only | ||
63 | ** a few simply conversions: | ||
64 | ** | ||
65 | ** %d | ||
66 | ** %s | ||
67 | ** %.*s | ||
68 | ** | ||
69 | */ | ||
70 | static void lemon_addtext( | ||
71 | char *zBuf, /* The buffer to which text is added */ | ||
72 | int *pnUsed, /* Slots of the buffer used so far */ | ||
73 | const char *zIn, /* Text to add */ | ||
74 | int nIn, /* Bytes of text to add. -1 to use strlen() */ | ||
75 | int iWidth /* Field width. Negative to left justify */ | ||
76 | ){ | ||
77 | if( nIn<0 ) for(nIn=0; zIn[nIn]; nIn++){} | ||
78 | while( iWidth>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth--; } | ||
79 | if( nIn==0 ) return; | ||
80 | memcpy(&zBuf[*pnUsed], zIn, nIn); | ||
81 | *pnUsed += nIn; | ||
82 | while( (-iWidth)>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth++; } | ||
83 | zBuf[*pnUsed] = 0; | ||
84 | } | ||
85 | static int lemon_vsprintf(char *str, const char *zFormat, va_list ap){ | ||
86 | int i, j, k, c, size; | ||
87 | int nUsed = 0; | ||
88 | const char *z; | ||
89 | char zTemp[50]; | ||
90 | str[0] = 0; | ||
91 | for(i=j=0; (c = zFormat[i])!=0; i++){ | ||
92 | if( c=='%' ){ | ||
93 | int iWidth = 0; | ||
94 | lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0); | ||
95 | c = zFormat[++i]; | ||
96 | if( isdigit(c) || (c=='-' && isdigit(zFormat[i+1])) ){ | ||
97 | if( c=='-' ) i++; | ||
98 | while( isdigit(zFormat[i]) ) iWidth = iWidth*10 + zFormat[i++] - '0'; | ||
99 | if( c=='-' ) iWidth = -iWidth; | ||
100 | c = zFormat[i]; | ||
101 | } | ||
102 | if( c=='d' ){ | ||
103 | int v = va_arg(ap, int); | ||
104 | if( v<0 ){ | ||
105 | lemon_addtext(str, &nUsed, "-", 1, iWidth); | ||
106 | v = -v; | ||
107 | }else if( v==0 ){ | ||
108 | lemon_addtext(str, &nUsed, "0", 1, iWidth); | ||
109 | } | ||
110 | k = 0; | ||
111 | while( v>0 ){ | ||
112 | k++; | ||
113 | zTemp[sizeof(zTemp)-k] = (v%10) + '0'; | ||
114 | v /= 10; | ||
115 | } | ||
116 | lemon_addtext(str, &nUsed, &zTemp[sizeof(zTemp)-k], k, iWidth); | ||
117 | }else if( c=='s' ){ | ||
118 | z = va_arg(ap, const char*); | ||
119 | lemon_addtext(str, &nUsed, z, -1, iWidth); | ||
120 | }else if( c=='.' && memcmp(&zFormat[i], ".*s", 3)==0 ){ | ||
121 | i += 2; | ||
122 | k = va_arg(ap, int); | ||
123 | z = va_arg(ap, const char*); | ||
124 | lemon_addtext(str, &nUsed, z, k, iWidth); | ||
125 | }else if( c=='%' ){ | ||
126 | lemon_addtext(str, &nUsed, "%", 1, 0); | ||
127 | }else{ | ||
128 | fprintf(stderr, "illegal format\n"); | ||
129 | exit(1); | ||
130 | } | ||
131 | j = i+1; | ||
132 | } | ||
133 | } | ||
134 | lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0); | ||
135 | return nUsed; | ||
136 | } | ||
137 | static int lemon_sprintf(char *str, const char *format, ...){ | ||
138 | va_list ap; | ||
139 | int rc; | ||
140 | va_start(ap, format); | ||
141 | rc = lemon_vsprintf(str, format, ap); | ||
142 | va_end(ap); | ||
143 | return rc; | ||
144 | } | ||
145 | static void lemon_strcpy(char *dest, const char *src){ | ||
146 | while( (*(dest++) = *(src++))!=0 ){} | ||
147 | } | ||
148 | static void lemon_strcat(char *dest, const char *src){ | ||
149 | while( *dest ) dest++; | ||
150 | lemon_strcpy(dest, src); | ||
151 | } | ||
152 | |||
153 | |||
53 | /* a few forward declarations... */ | 154 | /* a few forward declarations... */ |
54 | struct rule; | 155 | struct rule; |
55 | struct lemon; | 156 | struct lemon; |
@@ -653,7 +754,7 @@ void FindRulePrecedences(struct lemon *xp) | |||
653 | } | 754 | } |
654 | }else if( sp->prec>=0 ){ | 755 | }else if( sp->prec>=0 ){ |
655 | rp->precsym = rp->rhs[i]; | 756 | rp->precsym = rp->rhs[i]; |
656 | } | 757 | } |
657 | } | 758 | } |
658 | } | 759 | } |
659 | } | 760 | } |
@@ -711,12 +812,12 @@ void FindFirstSets(struct lemon *lemp) | |||
711 | progress += SetAdd(s1->firstset,s2->subsym[j]->index); | 812 | progress += SetAdd(s1->firstset,s2->subsym[j]->index); |
712 | } | 813 | } |
713 | break; | 814 | break; |
714 | }else if( s1==s2 ){ | 815 | }else if( s1==s2 ){ |
715 | if( s1->lambda==LEMON_FALSE ) break; | 816 | if( s1->lambda==LEMON_FALSE ) break; |
716 | }else{ | 817 | }else{ |
717 | progress += SetUnion(s1->firstset,s2->firstset); | 818 | progress += SetUnion(s1->firstset,s2->firstset); |
718 | if( s2->lambda==LEMON_FALSE ) break; | 819 | if( s2->lambda==LEMON_FALSE ) break; |
719 | } | 820 | } |
720 | } | 821 | } |
721 | } | 822 | } |
722 | }while( progress ); | 823 | }while( progress ); |
@@ -959,8 +1060,8 @@ void FindFollowSets(struct lemon *lemp) | |||
959 | if( change ){ | 1060 | if( change ){ |
960 | plp->cfp->status = INCOMPLETE; | 1061 | plp->cfp->status = INCOMPLETE; |
961 | progress = 1; | 1062 | progress = 1; |
962 | } | 1063 | } |
963 | } | 1064 | } |
964 | cfp->status = COMPLETE; | 1065 | cfp->status = COMPLETE; |
965 | } | 1066 | } |
966 | } | 1067 | } |
@@ -993,7 +1094,7 @@ void FindActions(struct lemon *lemp) | |||
993 | ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */ | 1094 | ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */ |
994 | Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp); | 1095 | Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp); |
995 | } | 1096 | } |
996 | } | 1097 | } |
997 | } | 1098 | } |
998 | } | 1099 | } |
999 | } | 1100 | } |
@@ -1262,11 +1363,11 @@ void Configlist_closure(struct lemon *lemp) | |||
1262 | SetAdd(newcfp->fws, xsp->subsym[k]->index); | 1363 | SetAdd(newcfp->fws, xsp->subsym[k]->index); |
1263 | } | 1364 | } |
1264 | break; | 1365 | break; |
1265 | }else{ | 1366 | }else{ |
1266 | SetUnion(newcfp->fws,xsp->firstset); | 1367 | SetUnion(newcfp->fws,xsp->firstset); |
1267 | if( xsp->lambda==LEMON_FALSE ) break; | 1368 | if( xsp->lambda==LEMON_FALSE ) break; |
1268 | } | 1369 | } |
1269 | } | 1370 | } |
1270 | if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); | 1371 | if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); |
1271 | } | 1372 | } |
1272 | } | 1373 | } |
@@ -1367,7 +1468,7 @@ static void handle_D_option(char *z){ | |||
1367 | fprintf(stderr,"out of memory\n"); | 1468 | fprintf(stderr,"out of memory\n"); |
1368 | exit(1); | 1469 | exit(1); |
1369 | } | 1470 | } |
1370 | strcpy(*paz, z); | 1471 | lemon_strcpy(*paz, z); |
1371 | for(z=*paz; *z && *z!='='; z++){} | 1472 | for(z=*paz; *z && *z!='='; z++){} |
1372 | *z = 0; | 1473 | *z = 0; |
1373 | } | 1474 | } |
@@ -1378,7 +1479,7 @@ static void handle_T_option(char *z){ | |||
1378 | if( user_templatename==0 ){ | 1479 | if( user_templatename==0 ){ |
1379 | memory_error(); | 1480 | memory_error(); |
1380 | } | 1481 | } |
1381 | strcpy(user_templatename, z); | 1482 | lemon_strcpy(user_templatename, z); |
1382 | } | 1483 | } |
1383 | 1484 | ||
1384 | /* The main program. Parse the command line and do it... */ | 1485 | /* The main program. Parse the command line and do it... */ |
@@ -1447,12 +1548,15 @@ int main(int argc, char **argv) | |||
1447 | } | 1548 | } |
1448 | 1549 | ||
1449 | /* Count and index the symbols of the grammar */ | 1550 | /* Count and index the symbols of the grammar */ |
1450 | lem.nsymbol = Symbol_count(); | ||
1451 | Symbol_new("{default}"); | 1551 | Symbol_new("{default}"); |
1552 | lem.nsymbol = Symbol_count(); | ||
1452 | lem.symbols = Symbol_arrayof(); | 1553 | lem.symbols = Symbol_arrayof(); |
1453 | for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i; | 1554 | for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; |
1454 | qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*), Symbolcmpp); | 1555 | qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp); |
1455 | for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i; | 1556 | for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; |
1557 | while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; } | ||
1558 | assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 ); | ||
1559 | lem.nsymbol = i - 1; | ||
1456 | for(i=1; isupper(lem.symbols[i]->name[0]); i++); | 1560 | for(i=1; isupper(lem.symbols[i]->name[0]); i++); |
1457 | lem.nterminal = i; | 1561 | lem.nterminal = i; |
1458 | 1562 | ||
@@ -1546,7 +1650,7 @@ int main(int argc, char **argv) | |||
1546 | /* | 1650 | /* |
1547 | ** Return a pointer to the next structure in the linked list. | 1651 | ** Return a pointer to the next structure in the linked list. |
1548 | */ | 1652 | */ |
1549 | #define NEXT(A) (*(char**)(((unsigned long)A)+offset)) | 1653 | #define NEXT(A) (*(char**)(((char*)A)+offset)) |
1550 | 1654 | ||
1551 | /* | 1655 | /* |
1552 | ** Inputs: | 1656 | ** Inputs: |
@@ -1940,7 +2044,9 @@ enum e_state { | |||
1940 | WAITING_FOR_DESTRUCTOR_SYMBOL, | 2044 | WAITING_FOR_DESTRUCTOR_SYMBOL, |
1941 | WAITING_FOR_DATATYPE_SYMBOL, | 2045 | WAITING_FOR_DATATYPE_SYMBOL, |
1942 | WAITING_FOR_FALLBACK_ID, | 2046 | WAITING_FOR_FALLBACK_ID, |
1943 | WAITING_FOR_WILDCARD_ID | 2047 | WAITING_FOR_WILDCARD_ID, |
2048 | WAITING_FOR_CLASS_ID, | ||
2049 | WAITING_FOR_CLASS_TOKEN | ||
1944 | }; | 2050 | }; |
1945 | struct pstate { | 2051 | struct pstate { |
1946 | char *filename; /* Name of the input file */ | 2052 | char *filename; /* Name of the input file */ |
@@ -1950,6 +2056,7 @@ struct pstate { | |||
1950 | struct lemon *gp; /* Global state vector */ | 2056 | struct lemon *gp; /* Global state vector */ |
1951 | enum e_state state; /* The state of the parser */ | 2057 | enum e_state state; /* The state of the parser */ |
1952 | struct symbol *fallback; /* The fallback token */ | 2058 | struct symbol *fallback; /* The fallback token */ |
2059 | struct symbol *tkclass; /* Token class symbol */ | ||
1953 | struct symbol *lhs; /* Left-hand side of current rule */ | 2060 | struct symbol *lhs; /* Left-hand side of current rule */ |
1954 | const char *lhsalias; /* Alias for the LHS */ | 2061 | const char *lhsalias; /* Alias for the LHS */ |
1955 | int nrhs; /* Number of right-hand side symbols seen */ | 2062 | int nrhs; /* Number of right-hand side symbols seen */ |
@@ -1996,7 +2103,7 @@ static void parseonetoken(struct pstate *psp) | |||
1996 | "There is no prior rule upon which to attach the code \ | 2103 | "There is no prior rule upon which to attach the code \ |
1997 | fragment which begins on this line."); | 2104 | fragment which begins on this line."); |
1998 | psp->errorcnt++; | 2105 | psp->errorcnt++; |
1999 | }else if( psp->prevrule->code!=0 ){ | 2106 | }else if( psp->prevrule->code!=0 ){ |
2000 | ErrorMsg(psp->filename,psp->tokenlineno, | 2107 | ErrorMsg(psp->filename,psp->tokenlineno, |
2001 | "Code fragment beginning on this line is not the first \ | 2108 | "Code fragment beginning on this line is not the first \ |
2002 | to follow the previous rule."); | 2109 | to follow the previous rule."); |
@@ -2004,7 +2111,7 @@ to follow the previous rule."); | |||
2004 | }else{ | 2111 | }else{ |
2005 | psp->prevrule->line = psp->tokenlineno; | 2112 | psp->prevrule->line = psp->tokenlineno; |
2006 | psp->prevrule->code = &x[1]; | 2113 | psp->prevrule->code = &x[1]; |
2007 | } | 2114 | } |
2008 | }else if( x[0]=='[' ){ | 2115 | }else if( x[0]=='[' ){ |
2009 | psp->state = PRECEDENCE_MARK_1; | 2116 | psp->state = PRECEDENCE_MARK_1; |
2010 | }else{ | 2117 | }else{ |
@@ -2097,7 +2204,7 @@ to follow the previous rule."); | |||
2097 | "Can't allocate enough memory for this rule."); | 2204 | "Can't allocate enough memory for this rule."); |
2098 | psp->errorcnt++; | 2205 | psp->errorcnt++; |
2099 | psp->prevrule = 0; | 2206 | psp->prevrule = 0; |
2100 | }else{ | 2207 | }else{ |
2101 | int i; | 2208 | int i; |
2102 | rp->ruleline = psp->tokenlineno; | 2209 | rp->ruleline = psp->tokenlineno; |
2103 | rp->rhs = (struct symbol**)&rp[1]; | 2210 | rp->rhs = (struct symbol**)&rp[1]; |
@@ -2105,7 +2212,7 @@ to follow the previous rule."); | |||
2105 | for(i=0; i<psp->nrhs; i++){ | 2212 | for(i=0; i<psp->nrhs; i++){ |
2106 | rp->rhs[i] = psp->rhs[i]; | 2213 | rp->rhs[i] = psp->rhs[i]; |
2107 | rp->rhsalias[i] = psp->alias[i]; | 2214 | rp->rhsalias[i] = psp->alias[i]; |
2108 | } | 2215 | } |
2109 | rp->lhs = psp->lhs; | 2216 | rp->lhs = psp->lhs; |
2110 | rp->lhsalias = psp->lhsalias; | 2217 | rp->lhsalias = psp->lhsalias; |
2111 | rp->nrhs = psp->nrhs; | 2218 | rp->nrhs = psp->nrhs; |
@@ -2117,12 +2224,12 @@ to follow the previous rule."); | |||
2117 | rp->next = 0; | 2224 | rp->next = 0; |
2118 | if( psp->firstrule==0 ){ | 2225 | if( psp->firstrule==0 ){ |
2119 | psp->firstrule = psp->lastrule = rp; | 2226 | psp->firstrule = psp->lastrule = rp; |
2120 | }else{ | 2227 | }else{ |
2121 | psp->lastrule->next = rp; | 2228 | psp->lastrule->next = rp; |
2122 | psp->lastrule = rp; | 2229 | psp->lastrule = rp; |
2123 | } | 2230 | } |
2124 | psp->prevrule = rp; | 2231 | psp->prevrule = rp; |
2125 | } | 2232 | } |
2126 | psp->state = WAITING_FOR_DECL_OR_RULE; | 2233 | psp->state = WAITING_FOR_DECL_OR_RULE; |
2127 | }else if( isalpha(x[0]) ){ | 2234 | }else if( isalpha(x[0]) ){ |
2128 | if( psp->nrhs>=MAXRHS ){ | 2235 | if( psp->nrhs>=MAXRHS ){ |
@@ -2131,11 +2238,11 @@ to follow the previous rule."); | |||
2131 | x); | 2238 | x); |
2132 | psp->errorcnt++; | 2239 | psp->errorcnt++; |
2133 | psp->state = RESYNC_AFTER_RULE_ERROR; | 2240 | psp->state = RESYNC_AFTER_RULE_ERROR; |
2134 | }else{ | 2241 | }else{ |
2135 | psp->rhs[psp->nrhs] = Symbol_new(x); | 2242 | psp->rhs[psp->nrhs] = Symbol_new(x); |
2136 | psp->alias[psp->nrhs] = 0; | 2243 | psp->alias[psp->nrhs] = 0; |
2137 | psp->nrhs++; | 2244 | psp->nrhs++; |
2138 | } | 2245 | } |
2139 | }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){ | 2246 | }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){ |
2140 | struct symbol *msp = psp->rhs[psp->nrhs-1]; | 2247 | struct symbol *msp = psp->rhs[psp->nrhs-1]; |
2141 | if( msp->type!=MULTITERMINAL ){ | 2248 | if( msp->type!=MULTITERMINAL ){ |
@@ -2199,24 +2306,24 @@ to follow the previous rule."); | |||
2199 | if( strcmp(x,"name")==0 ){ | 2306 | if( strcmp(x,"name")==0 ){ |
2200 | psp->declargslot = &(psp->gp->name); | 2307 | psp->declargslot = &(psp->gp->name); |
2201 | psp->insertLineMacro = 0; | 2308 | psp->insertLineMacro = 0; |
2202 | }else if( strcmp(x,"include")==0 ){ | 2309 | }else if( strcmp(x,"include")==0 ){ |
2203 | psp->declargslot = &(psp->gp->include); | 2310 | psp->declargslot = &(psp->gp->include); |
2204 | }else if( strcmp(x,"code")==0 ){ | 2311 | }else if( strcmp(x,"code")==0 ){ |
2205 | psp->declargslot = &(psp->gp->extracode); | 2312 | psp->declargslot = &(psp->gp->extracode); |
2206 | }else if( strcmp(x,"token_destructor")==0 ){ | 2313 | }else if( strcmp(x,"token_destructor")==0 ){ |
2207 | psp->declargslot = &psp->gp->tokendest; | 2314 | psp->declargslot = &psp->gp->tokendest; |
2208 | }else if( strcmp(x,"default_destructor")==0 ){ | 2315 | }else if( strcmp(x,"default_destructor")==0 ){ |
2209 | psp->declargslot = &psp->gp->vardest; | 2316 | psp->declargslot = &psp->gp->vardest; |
2210 | }else if( strcmp(x,"token_prefix")==0 ){ | 2317 | }else if( strcmp(x,"token_prefix")==0 ){ |
2211 | psp->declargslot = &psp->gp->tokenprefix; | 2318 | psp->declargslot = &psp->gp->tokenprefix; |
2212 | psp->insertLineMacro = 0; | 2319 | psp->insertLineMacro = 0; |
2213 | }else if( strcmp(x,"syntax_error")==0 ){ | 2320 | }else if( strcmp(x,"syntax_error")==0 ){ |
2214 | psp->declargslot = &(psp->gp->error); | 2321 | psp->declargslot = &(psp->gp->error); |
2215 | }else if( strcmp(x,"parse_accept")==0 ){ | 2322 | }else if( strcmp(x,"parse_accept")==0 ){ |
2216 | psp->declargslot = &(psp->gp->accept); | 2323 | psp->declargslot = &(psp->gp->accept); |
2217 | }else if( strcmp(x,"parse_failure")==0 ){ | 2324 | }else if( strcmp(x,"parse_failure")==0 ){ |
2218 | psp->declargslot = &(psp->gp->failure); | 2325 | psp->declargslot = &(psp->gp->failure); |
2219 | }else if( strcmp(x,"stack_overflow")==0 ){ | 2326 | }else if( strcmp(x,"stack_overflow")==0 ){ |
2220 | psp->declargslot = &(psp->gp->overflow); | 2327 | psp->declargslot = &(psp->gp->overflow); |
2221 | }else if( strcmp(x,"extra_argument")==0 ){ | 2328 | }else if( strcmp(x,"extra_argument")==0 ){ |
2222 | psp->declargslot = &(psp->gp->arg); | 2329 | psp->declargslot = &(psp->gp->arg); |
@@ -2245,21 +2352,23 @@ to follow the previous rule."); | |||
2245 | psp->preccounter++; | 2352 | psp->preccounter++; |
2246 | psp->declassoc = NONE; | 2353 | psp->declassoc = NONE; |
2247 | psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; | 2354 | psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; |
2248 | }else if( strcmp(x,"destructor")==0 ){ | 2355 | }else if( strcmp(x,"destructor")==0 ){ |
2249 | psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL; | 2356 | psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL; |
2250 | }else if( strcmp(x,"type")==0 ){ | 2357 | }else if( strcmp(x,"type")==0 ){ |
2251 | psp->state = WAITING_FOR_DATATYPE_SYMBOL; | 2358 | psp->state = WAITING_FOR_DATATYPE_SYMBOL; |
2252 | }else if( strcmp(x,"fallback")==0 ){ | 2359 | }else if( strcmp(x,"fallback")==0 ){ |
2253 | psp->fallback = 0; | 2360 | psp->fallback = 0; |
2254 | psp->state = WAITING_FOR_FALLBACK_ID; | 2361 | psp->state = WAITING_FOR_FALLBACK_ID; |
2255 | }else if( strcmp(x,"wildcard")==0 ){ | 2362 | }else if( strcmp(x,"wildcard")==0 ){ |
2256 | psp->state = WAITING_FOR_WILDCARD_ID; | 2363 | psp->state = WAITING_FOR_WILDCARD_ID; |
2364 | }else if( strcmp(x,"token_class")==0 ){ | ||
2365 | psp->state = WAITING_FOR_CLASS_ID; | ||
2257 | }else{ | 2366 | }else{ |
2258 | ErrorMsg(psp->filename,psp->tokenlineno, | 2367 | ErrorMsg(psp->filename,psp->tokenlineno, |
2259 | "Unknown declaration keyword: \"%%%s\".",x); | 2368 | "Unknown declaration keyword: \"%%%s\".",x); |
2260 | psp->errorcnt++; | 2369 | psp->errorcnt++; |
2261 | psp->state = RESYNC_AFTER_DECL_ERROR; | 2370 | psp->state = RESYNC_AFTER_DECL_ERROR; |
2262 | } | 2371 | } |
2263 | }else{ | 2372 | }else{ |
2264 | ErrorMsg(psp->filename,psp->tokenlineno, | 2373 | ErrorMsg(psp->filename,psp->tokenlineno, |
2265 | "Illegal declaration keyword: \"%s\".",x); | 2374 | "Illegal declaration keyword: \"%s\".",x); |
@@ -2314,10 +2423,10 @@ to follow the previous rule."); | |||
2314 | ErrorMsg(psp->filename,psp->tokenlineno, | 2423 | ErrorMsg(psp->filename,psp->tokenlineno, |
2315 | "Symbol \"%s\" has already be given a precedence.",x); | 2424 | "Symbol \"%s\" has already be given a precedence.",x); |
2316 | psp->errorcnt++; | 2425 | psp->errorcnt++; |
2317 | }else{ | 2426 | }else{ |
2318 | sp->prec = psp->preccounter; | 2427 | sp->prec = psp->preccounter; |
2319 | sp->assoc = psp->declassoc; | 2428 | sp->assoc = psp->declassoc; |
2320 | } | 2429 | } |
2321 | }else{ | 2430 | }else{ |
2322 | ErrorMsg(psp->filename,psp->tokenlineno, | 2431 | ErrorMsg(psp->filename,psp->tokenlineno, |
2323 | "Can't assign a precedence to \"%s\".",x); | 2432 | "Can't assign a precedence to \"%s\".",x); |
@@ -2347,7 +2456,7 @@ to follow the previous rule."); | |||
2347 | for(z=psp->filename, nBack=0; *z; z++){ | 2456 | for(z=psp->filename, nBack=0; *z; z++){ |
2348 | if( *z=='\\' ) nBack++; | 2457 | if( *z=='\\' ) nBack++; |
2349 | } | 2458 | } |
2350 | sprintf(zLine, "#line %d ", psp->tokenlineno); | 2459 | lemon_sprintf(zLine, "#line %d ", psp->tokenlineno); |
2351 | nLine = lemonStrlen(zLine); | 2460 | nLine = lemonStrlen(zLine); |
2352 | n += nLine + lemonStrlen(psp->filename) + nBack; | 2461 | n += nLine + lemonStrlen(psp->filename) + nBack; |
2353 | } | 2462 | } |
@@ -2422,6 +2531,40 @@ to follow the previous rule."); | |||
2422 | } | 2531 | } |
2423 | } | 2532 | } |
2424 | break; | 2533 | break; |
2534 | case WAITING_FOR_CLASS_ID: | ||
2535 | if( !islower(x[0]) ){ | ||
2536 | ErrorMsg(psp->filename, psp->tokenlineno, | ||
2537 | "%%token_class must be followed by an identifier: ", x); | ||
2538 | psp->errorcnt++; | ||
2539 | psp->state = RESYNC_AFTER_DECL_ERROR; | ||
2540 | }else if( Symbol_find(x) ){ | ||
2541 | ErrorMsg(psp->filename, psp->tokenlineno, | ||
2542 | "Symbol \"%s\" already used", x); | ||
2543 | psp->errorcnt++; | ||
2544 | psp->state = RESYNC_AFTER_DECL_ERROR; | ||
2545 | }else{ | ||
2546 | psp->tkclass = Symbol_new(x); | ||
2547 | psp->tkclass->type = MULTITERMINAL; | ||
2548 | psp->state = WAITING_FOR_CLASS_TOKEN; | ||
2549 | } | ||
2550 | break; | ||
2551 | case WAITING_FOR_CLASS_TOKEN: | ||
2552 | if( x[0]=='.' ){ | ||
2553 | psp->state = WAITING_FOR_DECL_OR_RULE; | ||
2554 | }else if( isupper(x[0]) || ((x[0]=='|' || x[0]=='/') && isupper(x[1])) ){ | ||
2555 | struct symbol *msp = psp->tkclass; | ||
2556 | msp->nsubsym++; | ||
2557 | msp->subsym = (struct symbol **) realloc(msp->subsym, | ||
2558 | sizeof(struct symbol*)*msp->nsubsym); | ||
2559 | if( !isupper(x[0]) ) x++; | ||
2560 | msp->subsym[msp->nsubsym-1] = Symbol_new(x); | ||
2561 | }else{ | ||
2562 | ErrorMsg(psp->filename, psp->tokenlineno, | ||
2563 | "%%token_class argument \"%s\" should be a token", x); | ||
2564 | psp->errorcnt++; | ||
2565 | psp->state = RESYNC_AFTER_DECL_ERROR; | ||
2566 | } | ||
2567 | break; | ||
2425 | case RESYNC_AFTER_RULE_ERROR: | 2568 | case RESYNC_AFTER_RULE_ERROR: |
2426 | /* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; | 2569 | /* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; |
2427 | ** break; */ | 2570 | ** break; */ |
@@ -2516,9 +2659,8 @@ void Parse(struct lemon *gp) | |||
2516 | filesize = ftell(fp); | 2659 | filesize = ftell(fp); |
2517 | rewind(fp); | 2660 | rewind(fp); |
2518 | filebuf = (char *)malloc( filesize+1 ); | 2661 | filebuf = (char *)malloc( filesize+1 ); |
2519 | if( filebuf==0 ){ | 2662 | if( filesize>100000000 || filebuf==0 ){ |
2520 | ErrorMsg(ps.filename,0,"Can't allocate %d of memory to hold this file.", | 2663 | ErrorMsg(ps.filename,0,"Input file too large."); |
2521 | filesize+1); | ||
2522 | gp->errorcnt++; | 2664 | gp->errorcnt++; |
2523 | fclose(fp); | 2665 | fclose(fp); |
2524 | return; | 2666 | return; |
@@ -2587,12 +2729,12 @@ void Parse(struct lemon *gp) | |||
2587 | if( c=='\n' ) lineno++; | 2729 | if( c=='\n' ) lineno++; |
2588 | prevc = c; | 2730 | prevc = c; |
2589 | cp++; | 2731 | cp++; |
2590 | } | 2732 | } |
2591 | }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */ | 2733 | }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */ |
2592 | cp = &cp[2]; | 2734 | cp = &cp[2]; |
2593 | while( (c= *cp)!=0 && c!='\n' ) cp++; | 2735 | while( (c= *cp)!=0 && c!='\n' ) cp++; |
2594 | if( c ) lineno++; | 2736 | if( c ) lineno++; |
2595 | }else if( c=='\'' || c=='\"' ){ /* String a character literals */ | 2737 | }else if( c=='\'' || c=='\"' ){ /* String a character literals */ |
2596 | int startchar, prevc; | 2738 | int startchar, prevc; |
2597 | startchar = c; | 2739 | startchar = c; |
2598 | prevc = 0; | 2740 | prevc = 0; |
@@ -2600,8 +2742,8 @@ void Parse(struct lemon *gp) | |||
2600 | if( c=='\n' ) lineno++; | 2742 | if( c=='\n' ) lineno++; |
2601 | if( prevc=='\\' ) prevc = 0; | 2743 | if( prevc=='\\' ) prevc = 0; |
2602 | else prevc = c; | 2744 | else prevc = c; |
2603 | } | 2745 | } |
2604 | } | 2746 | } |
2605 | } | 2747 | } |
2606 | if( c==0 ){ | 2748 | if( c==0 ){ |
2607 | ErrorMsg(ps.filename,ps.tokenlineno, | 2749 | ErrorMsg(ps.filename,ps.tokenlineno, |
@@ -2716,10 +2858,10 @@ PRIVATE char *file_makename(struct lemon *lemp, const char *suffix) | |||
2716 | fprintf(stderr,"Can't allocate space for a filename.\n"); | 2858 | fprintf(stderr,"Can't allocate space for a filename.\n"); |
2717 | exit(1); | 2859 | exit(1); |
2718 | } | 2860 | } |
2719 | strcpy(name,lemp->filename); | 2861 | lemon_strcpy(name,lemp->filename); |
2720 | cp = strrchr(name,'.'); | 2862 | cp = strrchr(name,'.'); |
2721 | if( cp ) *cp = 0; | 2863 | if( cp ) *cp = 0; |
2722 | strcat(name,suffix); | 2864 | lemon_strcat(name,suffix); |
2723 | return name; | 2865 | return name; |
2724 | } | 2866 | } |
2725 | 2867 | ||
@@ -2776,11 +2918,13 @@ void Reprint(struct lemon *lemp) | |||
2776 | printf(" ::="); | 2918 | printf(" ::="); |
2777 | for(i=0; i<rp->nrhs; i++){ | 2919 | for(i=0; i<rp->nrhs; i++){ |
2778 | sp = rp->rhs[i]; | 2920 | sp = rp->rhs[i]; |
2779 | printf(" %s", sp->name); | ||
2780 | if( sp->type==MULTITERMINAL ){ | 2921 | if( sp->type==MULTITERMINAL ){ |
2922 | printf(" %s", sp->subsym[0]->name); | ||
2781 | for(j=1; j<sp->nsubsym; j++){ | 2923 | for(j=1; j<sp->nsubsym; j++){ |
2782 | printf("|%s", sp->subsym[j]->name); | 2924 | printf("|%s", sp->subsym[j]->name); |
2783 | } | 2925 | } |
2926 | }else{ | ||
2927 | printf(" %s", sp->name); | ||
2784 | } | 2928 | } |
2785 | /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */ | 2929 | /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */ |
2786 | } | 2930 | } |
@@ -2802,11 +2946,13 @@ void ConfigPrint(FILE *fp, struct config *cfp) | |||
2802 | if( i==cfp->dot ) fprintf(fp," *"); | 2946 | if( i==cfp->dot ) fprintf(fp," *"); |
2803 | if( i==rp->nrhs ) break; | 2947 | if( i==rp->nrhs ) break; |
2804 | sp = rp->rhs[i]; | 2948 | sp = rp->rhs[i]; |
2805 | fprintf(fp," %s", sp->name); | ||
2806 | if( sp->type==MULTITERMINAL ){ | 2949 | if( sp->type==MULTITERMINAL ){ |
2950 | fprintf(fp," %s", sp->subsym[0]->name); | ||
2807 | for(j=1; j<sp->nsubsym; j++){ | 2951 | for(j=1; j<sp->nsubsym; j++){ |
2808 | fprintf(fp,"|%s",sp->subsym[j]->name); | 2952 | fprintf(fp,"|%s",sp->subsym[j]->name); |
2809 | } | 2953 | } |
2954 | }else{ | ||
2955 | fprintf(fp," %s", sp->name); | ||
2810 | } | 2956 | } |
2811 | } | 2957 | } |
2812 | } | 2958 | } |
@@ -2916,7 +3062,7 @@ void ReportOutput(struct lemon *lemp) | |||
2916 | while( cfp ){ | 3062 | while( cfp ){ |
2917 | char buf[20]; | 3063 | char buf[20]; |
2918 | if( cfp->dot==cfp->rp->nrhs ){ | 3064 | if( cfp->dot==cfp->rp->nrhs ){ |
2919 | sprintf(buf,"(%d)",cfp->rp->index); | 3065 | lemon_sprintf(buf,"(%d)",cfp->rp->index); |
2920 | fprintf(fp," %5s ",buf); | 3066 | fprintf(fp," %5s ",buf); |
2921 | }else{ | 3067 | }else{ |
2922 | fprintf(fp," "); | 3068 | fprintf(fp," "); |
@@ -2981,7 +3127,7 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask) | |||
2981 | c = *cp; | 3127 | c = *cp; |
2982 | *cp = 0; | 3128 | *cp = 0; |
2983 | path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 ); | 3129 | path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 ); |
2984 | if( path ) sprintf(path,"%s/%s",argv0,name); | 3130 | if( path ) lemon_sprintf(path,"%s/%s",argv0,name); |
2985 | *cp = c; | 3131 | *cp = c; |
2986 | }else{ | 3132 | }else{ |
2987 | pathlist = getenv("PATH"); | 3133 | pathlist = getenv("PATH"); |
@@ -2990,13 +3136,13 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask) | |||
2990 | path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 ); | 3136 | path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 ); |
2991 | if( (pathbuf != 0) && (path!=0) ){ | 3137 | if( (pathbuf != 0) && (path!=0) ){ |
2992 | pathbufptr = pathbuf; | 3138 | pathbufptr = pathbuf; |
2993 | strcpy(pathbuf, pathlist); | 3139 | lemon_strcpy(pathbuf, pathlist); |
2994 | while( *pathbuf ){ | 3140 | while( *pathbuf ){ |
2995 | cp = strchr(pathbuf,':'); | 3141 | cp = strchr(pathbuf,':'); |
2996 | if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)]; | 3142 | if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)]; |
2997 | c = *cp; | 3143 | c = *cp; |
2998 | *cp = 0; | 3144 | *cp = 0; |
2999 | sprintf(path,"%s/%s",pathbuf,name); | 3145 | lemon_sprintf(path,"%s/%s",pathbuf,name); |
3000 | *cp = c; | 3146 | *cp = c; |
3001 | if( c==0 ) pathbuf[0] = 0; | 3147 | if( c==0 ) pathbuf[0] = 0; |
3002 | else pathbuf = &cp[1]; | 3148 | else pathbuf = &cp[1]; |
@@ -3087,9 +3233,9 @@ PRIVATE FILE *tplt_open(struct lemon *lemp) | |||
3087 | 3233 | ||
3088 | cp = strrchr(lemp->filename,'.'); | 3234 | cp = strrchr(lemp->filename,'.'); |
3089 | if( cp ){ | 3235 | if( cp ){ |
3090 | sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename); | 3236 | lemon_sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename); |
3091 | }else{ | 3237 | }else{ |
3092 | sprintf(buf,"%s.lt",lemp->filename); | 3238 | lemon_sprintf(buf,"%s.lt",lemp->filename); |
3093 | } | 3239 | } |
3094 | if( access(buf,004)==0 ){ | 3240 | if( access(buf,004)==0 ){ |
3095 | tpltname = buf; | 3241 | tpltname = buf; |
@@ -3240,9 +3386,9 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2){ | |||
3240 | while( n-- > 0 ){ | 3386 | while( n-- > 0 ){ |
3241 | c = *(zText++); | 3387 | c = *(zText++); |
3242 | if( c=='%' && n>0 && zText[0]=='d' ){ | 3388 | if( c=='%' && n>0 && zText[0]=='d' ){ |
3243 | sprintf(zInt, "%d", p1); | 3389 | lemon_sprintf(zInt, "%d", p1); |
3244 | p1 = p2; | 3390 | p1 = p2; |
3245 | strcpy(&z[used], zInt); | 3391 | lemon_strcpy(&z[used], zInt); |
3246 | used += lemonStrlen(&z[used]); | 3392 | used += lemonStrlen(&z[used]); |
3247 | zText++; | 3393 | zText++; |
3248 | n--; | 3394 | n--; |
@@ -3391,7 +3537,7 @@ void print_stack_union( | |||
3391 | int maxdtlength; /* Maximum length of any ".datatype" field. */ | 3537 | int maxdtlength; /* Maximum length of any ".datatype" field. */ |
3392 | char *stddt; /* Standardized name for a datatype */ | 3538 | char *stddt; /* Standardized name for a datatype */ |
3393 | int i,j; /* Loop counters */ | 3539 | int i,j; /* Loop counters */ |
3394 | int hash; /* For hashing the name of a type */ | 3540 | unsigned hash; /* For hashing the name of a type */ |
3395 | const char *name; /* Name of the parser */ | 3541 | const char *name; /* Name of the parser */ |
3396 | 3542 | ||
3397 | /* Allocate and initialize types[] and allocate stddt[] */ | 3543 | /* Allocate and initialize types[] and allocate stddt[] */ |
@@ -3458,7 +3604,7 @@ void print_stack_union( | |||
3458 | break; | 3604 | break; |
3459 | } | 3605 | } |
3460 | hash++; | 3606 | hash++; |
3461 | if( hash>=arraysize ) hash = 0; | 3607 | if( hash>=(unsigned)arraysize ) hash = 0; |
3462 | } | 3608 | } |
3463 | if( types[hash]==0 ){ | 3609 | if( types[hash]==0 ){ |
3464 | sp->dtnum = hash + 1; | 3610 | sp->dtnum = hash + 1; |
@@ -3467,7 +3613,7 @@ void print_stack_union( | |||
3467 | fprintf(stderr,"Out of memory.\n"); | 3613 | fprintf(stderr,"Out of memory.\n"); |
3468 | exit(1); | 3614 | exit(1); |
3469 | } | 3615 | } |
3470 | strcpy(types[hash],stddt); | 3616 | lemon_strcpy(types[hash],stddt); |
3471 | } | 3617 | } |
3472 | } | 3618 | } |
3473 | 3619 | ||
@@ -3553,9 +3699,11 @@ static void writeRuleText(FILE *out, struct rule *rp){ | |||
3553 | fprintf(out,"%s ::=", rp->lhs->name); | 3699 | fprintf(out,"%s ::=", rp->lhs->name); |
3554 | for(j=0; j<rp->nrhs; j++){ | 3700 | for(j=0; j<rp->nrhs; j++){ |
3555 | struct symbol *sp = rp->rhs[j]; | 3701 | struct symbol *sp = rp->rhs[j]; |
3556 | fprintf(out," %s", sp->name); | 3702 | if( sp->type!=MULTITERMINAL ){ |
3557 | if( sp->type==MULTITERMINAL ){ | 3703 | fprintf(out," %s", sp->name); |
3704 | }else{ | ||
3558 | int k; | 3705 | int k; |
3706 | fprintf(out," %s", sp->subsym[0]->name); | ||
3559 | for(k=1; k<sp->nsubsym; k++){ | 3707 | for(k=1; k<sp->nsubsym; k++){ |
3560 | fprintf(out,"|%s",sp->subsym[k]->name); | 3708 | fprintf(out,"|%s",sp->subsym[k]->name); |
3561 | } | 3709 | } |
@@ -3856,7 +4004,7 @@ void ReportTable( | |||
3856 | /* Generate a table containing the symbolic name of every symbol | 4004 | /* Generate a table containing the symbolic name of every symbol |
3857 | */ | 4005 | */ |
3858 | for(i=0; i<lemp->nsymbol; i++){ | 4006 | for(i=0; i<lemp->nsymbol; i++){ |
3859 | sprintf(line,"\"%s\",",lemp->symbols[i]->name); | 4007 | lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name); |
3860 | fprintf(out," %-15s",line); | 4008 | fprintf(out," %-15s",line); |
3861 | if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; } | 4009 | if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; } |
3862 | } | 4010 | } |
@@ -4021,12 +4169,15 @@ void ReportHeader(struct lemon *lemp) | |||
4021 | else prefix = ""; | 4169 | else prefix = ""; |
4022 | in = file_open(lemp,".h","rb"); | 4170 | in = file_open(lemp,".h","rb"); |
4023 | if( in ){ | 4171 | if( in ){ |
4172 | int nextChar; | ||
4024 | for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){ | 4173 | for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){ |
4025 | sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); | 4174 | lemon_sprintf(pattern,"#define %s%-30s %3d\n", |
4175 | prefix,lemp->symbols[i]->name,i); | ||
4026 | if( strcmp(line,pattern) ) break; | 4176 | if( strcmp(line,pattern) ) break; |
4027 | } | 4177 | } |
4178 | nextChar = fgetc(in); | ||
4028 | fclose(in); | 4179 | fclose(in); |
4029 | if( i==lemp->nterminal ){ | 4180 | if( i==lemp->nterminal && nextChar==EOF ){ |
4030 | /* No change in the file. Don't rewrite it. */ | 4181 | /* No change in the file. Don't rewrite it. */ |
4031 | return; | 4182 | return; |
4032 | } | 4183 | } |
@@ -4034,7 +4185,7 @@ void ReportHeader(struct lemon *lemp) | |||
4034 | out = file_open(lemp,".h","wb"); | 4185 | out = file_open(lemp,".h","wb"); |
4035 | if( out ){ | 4186 | if( out ){ |
4036 | for(i=1; i<lemp->nterminal; i++){ | 4187 | for(i=1; i<lemp->nterminal; i++){ |
4037 | fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); | 4188 | fprintf(out,"#define %s%-30s %3d\n",prefix,lemp->symbols[i]->name,i); |
4038 | } | 4189 | } |
4039 | fclose(out); | 4190 | fclose(out); |
4040 | } | 4191 | } |
@@ -4232,10 +4383,10 @@ int SetUnion(char *s1, char *s2) | |||
4232 | ** Code for processing tables in the LEMON parser generator. | 4383 | ** Code for processing tables in the LEMON parser generator. |
4233 | */ | 4384 | */ |
4234 | 4385 | ||
4235 | PRIVATE int strhash(const char *x) | 4386 | PRIVATE unsigned strhash(const char *x) |
4236 | { | 4387 | { |
4237 | int h = 0; | 4388 | unsigned h = 0; |
4238 | while( *x) h = h*13 + *(x++); | 4389 | while( *x ) h = h*13 + *(x++); |
4239 | return h; | 4390 | return h; |
4240 | } | 4391 | } |
4241 | 4392 | ||
@@ -4251,7 +4402,7 @@ const char *Strsafe(const char *y) | |||
4251 | if( y==0 ) return 0; | 4402 | if( y==0 ) return 0; |
4252 | z = Strsafe_find(y); | 4403 | z = Strsafe_find(y); |
4253 | if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){ | 4404 | if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){ |
4254 | strcpy(cpy,y); | 4405 | lemon_strcpy(cpy,y); |
4255 | z = cpy; | 4406 | z = cpy; |
4256 | Strsafe_insert(z); | 4407 | Strsafe_insert(z); |
4257 | } | 4408 | } |
@@ -4290,8 +4441,7 @@ void Strsafe_init(){ | |||
4290 | if( x1a ){ | 4441 | if( x1a ){ |
4291 | x1a->size = 1024; | 4442 | x1a->size = 1024; |
4292 | x1a->count = 0; | 4443 | x1a->count = 0; |
4293 | x1a->tbl = (x1node*)malloc( | 4444 | x1a->tbl = (x1node*)calloc(1024, sizeof(x1node) + sizeof(x1node*)); |
4294 | (sizeof(x1node) + sizeof(x1node*))*1024 ); | ||
4295 | if( x1a->tbl==0 ){ | 4445 | if( x1a->tbl==0 ){ |
4296 | free(x1a); | 4446 | free(x1a); |
4297 | x1a = 0; | 4447 | x1a = 0; |
@@ -4307,8 +4457,8 @@ void Strsafe_init(){ | |||
4307 | int Strsafe_insert(const char *data) | 4457 | int Strsafe_insert(const char *data) |
4308 | { | 4458 | { |
4309 | x1node *np; | 4459 | x1node *np; |
4310 | int h; | 4460 | unsigned h; |
4311 | int ph; | 4461 | unsigned ph; |
4312 | 4462 | ||
4313 | if( x1a==0 ) return 0; | 4463 | if( x1a==0 ) return 0; |
4314 | ph = strhash(data); | 4464 | ph = strhash(data); |
@@ -4328,8 +4478,7 @@ int Strsafe_insert(const char *data) | |||
4328 | struct s_x1 array; | 4478 | struct s_x1 array; |
4329 | array.size = size = x1a->size*2; | 4479 | array.size = size = x1a->size*2; |
4330 | array.count = x1a->count; | 4480 | array.count = x1a->count; |
4331 | array.tbl = (x1node*)malloc( | 4481 | array.tbl = (x1node*)calloc(size, sizeof(x1node) + sizeof(x1node*)); |
4332 | (sizeof(x1node) + sizeof(x1node*))*size ); | ||
4333 | if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 4482 | if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
4334 | array.ht = (x1node**)&(array.tbl[size]); | 4483 | array.ht = (x1node**)&(array.tbl[size]); |
4335 | for(i=0; i<size; i++) array.ht[i] = 0; | 4484 | for(i=0; i<size; i++) array.ht[i] = 0; |
@@ -4362,7 +4511,7 @@ int Strsafe_insert(const char *data) | |||
4362 | ** if no such key. */ | 4511 | ** if no such key. */ |
4363 | const char *Strsafe_find(const char *key) | 4512 | const char *Strsafe_find(const char *key) |
4364 | { | 4513 | { |
4365 | int h; | 4514 | unsigned h; |
4366 | x1node *np; | 4515 | x1node *np; |
4367 | 4516 | ||
4368 | if( x1a==0 ) return 0; | 4517 | if( x1a==0 ) return 0; |
@@ -4404,11 +4553,15 @@ struct symbol *Symbol_new(const char *x) | |||
4404 | return sp; | 4553 | return sp; |
4405 | } | 4554 | } |
4406 | 4555 | ||
4407 | /* Compare two symbols for working purposes | 4556 | /* Compare two symbols for sorting purposes. Return negative, |
4557 | ** zero, or positive if a is less then, equal to, or greater | ||
4558 | ** than b. | ||
4408 | ** | 4559 | ** |
4409 | ** Symbols that begin with upper case letters (terminals or tokens) | 4560 | ** Symbols that begin with upper case letters (terminals or tokens) |
4410 | ** must sort before symbols that begin with lower case letters | 4561 | ** must sort before symbols that begin with lower case letters |
4411 | ** (non-terminals). Other than that, the order does not matter. | 4562 | ** (non-terminals). And MULTITERMINAL symbols (created using the |
4563 | ** %token_class directive) must sort at the very end. Other than | ||
4564 | ** that, the order does not matter. | ||
4412 | ** | 4565 | ** |
4413 | ** We find experimentally that leaving the symbols in their original | 4566 | ** We find experimentally that leaving the symbols in their original |
4414 | ** order (the order they appeared in the grammar file) gives the | 4567 | ** order (the order they appeared in the grammar file) gives the |
@@ -4416,12 +4569,11 @@ struct symbol *Symbol_new(const char *x) | |||
4416 | */ | 4569 | */ |
4417 | int Symbolcmpp(const void *_a, const void *_b) | 4570 | int Symbolcmpp(const void *_a, const void *_b) |
4418 | { | 4571 | { |
4419 | const struct symbol **a = (const struct symbol **) _a; | 4572 | const struct symbol *a = *(const struct symbol **) _a; |
4420 | const struct symbol **b = (const struct symbol **) _b; | 4573 | const struct symbol *b = *(const struct symbol **) _b; |
4421 | int i1 = (**a).index + 10000000*((**a).name[0]>'Z'); | 4574 | int i1 = a->type==MULTITERMINAL ? 3 : a->name[0]>'Z' ? 2 : 1; |
4422 | int i2 = (**b).index + 10000000*((**b).name[0]>'Z'); | 4575 | int i2 = b->type==MULTITERMINAL ? 3 : b->name[0]>'Z' ? 2 : 1; |
4423 | assert( i1!=i2 || strcmp((**a).name,(**b).name)==0 ); | 4576 | return i1==i2 ? a->index - b->index : i1 - i2; |
4424 | return i1-i2; | ||
4425 | } | 4577 | } |
4426 | 4578 | ||
4427 | /* There is one instance of the following structure for each | 4579 | /* There is one instance of the following structure for each |
@@ -4456,8 +4608,7 @@ void Symbol_init(){ | |||
4456 | if( x2a ){ | 4608 | if( x2a ){ |
4457 | x2a->size = 128; | 4609 | x2a->size = 128; |
4458 | x2a->count = 0; | 4610 | x2a->count = 0; |
4459 | x2a->tbl = (x2node*)malloc( | 4611 | x2a->tbl = (x2node*)calloc(128, sizeof(x2node) + sizeof(x2node*)); |
4460 | (sizeof(x2node) + sizeof(x2node*))*128 ); | ||
4461 | if( x2a->tbl==0 ){ | 4612 | if( x2a->tbl==0 ){ |
4462 | free(x2a); | 4613 | free(x2a); |
4463 | x2a = 0; | 4614 | x2a = 0; |
@@ -4473,8 +4624,8 @@ void Symbol_init(){ | |||
4473 | int Symbol_insert(struct symbol *data, const char *key) | 4624 | int Symbol_insert(struct symbol *data, const char *key) |
4474 | { | 4625 | { |
4475 | x2node *np; | 4626 | x2node *np; |
4476 | int h; | 4627 | unsigned h; |
4477 | int ph; | 4628 | unsigned ph; |
4478 | 4629 | ||
4479 | if( x2a==0 ) return 0; | 4630 | if( x2a==0 ) return 0; |
4480 | ph = strhash(key); | 4631 | ph = strhash(key); |
@@ -4494,8 +4645,7 @@ int Symbol_insert(struct symbol *data, const char *key) | |||
4494 | struct s_x2 array; | 4645 | struct s_x2 array; |
4495 | array.size = size = x2a->size*2; | 4646 | array.size = size = x2a->size*2; |
4496 | array.count = x2a->count; | 4647 | array.count = x2a->count; |
4497 | array.tbl = (x2node*)malloc( | 4648 | array.tbl = (x2node*)calloc(size, sizeof(x2node) + sizeof(x2node*)); |
4498 | (sizeof(x2node) + sizeof(x2node*))*size ); | ||
4499 | if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 4649 | if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
4500 | array.ht = (x2node**)&(array.tbl[size]); | 4650 | array.ht = (x2node**)&(array.tbl[size]); |
4501 | for(i=0; i<size; i++) array.ht[i] = 0; | 4651 | for(i=0; i<size; i++) array.ht[i] = 0; |
@@ -4530,7 +4680,7 @@ int Symbol_insert(struct symbol *data, const char *key) | |||
4530 | ** if no such key. */ | 4680 | ** if no such key. */ |
4531 | struct symbol *Symbol_find(const char *key) | 4681 | struct symbol *Symbol_find(const char *key) |
4532 | { | 4682 | { |
4533 | int h; | 4683 | unsigned h; |
4534 | x2node *np; | 4684 | x2node *np; |
4535 | 4685 | ||
4536 | if( x2a==0 ) return 0; | 4686 | if( x2a==0 ) return 0; |
@@ -4604,9 +4754,9 @@ PRIVATE int statecmp(struct config *a, struct config *b) | |||
4604 | } | 4754 | } |
4605 | 4755 | ||
4606 | /* Hash a state */ | 4756 | /* Hash a state */ |
4607 | PRIVATE int statehash(struct config *a) | 4757 | PRIVATE unsigned statehash(struct config *a) |
4608 | { | 4758 | { |
4609 | int h=0; | 4759 | unsigned h=0; |
4610 | while( a ){ | 4760 | while( a ){ |
4611 | h = h*571 + a->rp->index*37 + a->dot; | 4761 | h = h*571 + a->rp->index*37 + a->dot; |
4612 | a = a->bp; | 4762 | a = a->bp; |
@@ -4655,8 +4805,7 @@ void State_init(){ | |||
4655 | if( x3a ){ | 4805 | if( x3a ){ |
4656 | x3a->size = 128; | 4806 | x3a->size = 128; |
4657 | x3a->count = 0; | 4807 | x3a->count = 0; |
4658 | x3a->tbl = (x3node*)malloc( | 4808 | x3a->tbl = (x3node*)calloc(128, sizeof(x3node) + sizeof(x3node*)); |
4659 | (sizeof(x3node) + sizeof(x3node*))*128 ); | ||
4660 | if( x3a->tbl==0 ){ | 4809 | if( x3a->tbl==0 ){ |
4661 | free(x3a); | 4810 | free(x3a); |
4662 | x3a = 0; | 4811 | x3a = 0; |
@@ -4672,8 +4821,8 @@ void State_init(){ | |||
4672 | int State_insert(struct state *data, struct config *key) | 4821 | int State_insert(struct state *data, struct config *key) |
4673 | { | 4822 | { |
4674 | x3node *np; | 4823 | x3node *np; |
4675 | int h; | 4824 | unsigned h; |
4676 | int ph; | 4825 | unsigned ph; |
4677 | 4826 | ||
4678 | if( x3a==0 ) return 0; | 4827 | if( x3a==0 ) return 0; |
4679 | ph = statehash(key); | 4828 | ph = statehash(key); |
@@ -4693,8 +4842,7 @@ int State_insert(struct state *data, struct config *key) | |||
4693 | struct s_x3 array; | 4842 | struct s_x3 array; |
4694 | array.size = size = x3a->size*2; | 4843 | array.size = size = x3a->size*2; |
4695 | array.count = x3a->count; | 4844 | array.count = x3a->count; |
4696 | array.tbl = (x3node*)malloc( | 4845 | array.tbl = (x3node*)calloc(size, sizeof(x3node) + sizeof(x3node*)); |
4697 | (sizeof(x3node) + sizeof(x3node*))*size ); | ||
4698 | if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 4846 | if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
4699 | array.ht = (x3node**)&(array.tbl[size]); | 4847 | array.ht = (x3node**)&(array.tbl[size]); |
4700 | for(i=0; i<size; i++) array.ht[i] = 0; | 4848 | for(i=0; i<size; i++) array.ht[i] = 0; |
@@ -4729,7 +4877,7 @@ int State_insert(struct state *data, struct config *key) | |||
4729 | ** if no such key. */ | 4877 | ** if no such key. */ |
4730 | struct state *State_find(struct config *key) | 4878 | struct state *State_find(struct config *key) |
4731 | { | 4879 | { |
4732 | int h; | 4880 | unsigned h; |
4733 | x3node *np; | 4881 | x3node *np; |
4734 | 4882 | ||
4735 | if( x3a==0 ) return 0; | 4883 | if( x3a==0 ) return 0; |
@@ -4751,7 +4899,7 @@ struct state **State_arrayof() | |||
4751 | int i,size; | 4899 | int i,size; |
4752 | if( x3a==0 ) return 0; | 4900 | if( x3a==0 ) return 0; |
4753 | size = x3a->count; | 4901 | size = x3a->count; |
4754 | array = (struct state **)malloc( sizeof(struct state *)*size ); | 4902 | array = (struct state **)calloc(size, sizeof(struct state *)); |
4755 | if( array ){ | 4903 | if( array ){ |
4756 | for(i=0; i<size; i++) array[i] = x3a->tbl[i].data; | 4904 | for(i=0; i<size; i++) array[i] = x3a->tbl[i].data; |
4757 | } | 4905 | } |
@@ -4759,9 +4907,9 @@ struct state **State_arrayof() | |||
4759 | } | 4907 | } |
4760 | 4908 | ||
4761 | /* Hash a configuration */ | 4909 | /* Hash a configuration */ |
4762 | PRIVATE int confighash(struct config *a) | 4910 | PRIVATE unsigned confighash(struct config *a) |
4763 | { | 4911 | { |
4764 | int h=0; | 4912 | unsigned h=0; |
4765 | h = h*571 + a->rp->index*37 + a->dot; | 4913 | h = h*571 + a->rp->index*37 + a->dot; |
4766 | return h; | 4914 | return h; |
4767 | } | 4915 | } |
@@ -4797,8 +4945,7 @@ void Configtable_init(){ | |||
4797 | if( x4a ){ | 4945 | if( x4a ){ |
4798 | x4a->size = 64; | 4946 | x4a->size = 64; |
4799 | x4a->count = 0; | 4947 | x4a->count = 0; |
4800 | x4a->tbl = (x4node*)malloc( | 4948 | x4a->tbl = (x4node*)calloc(64, sizeof(x4node) + sizeof(x4node*)); |
4801 | (sizeof(x4node) + sizeof(x4node*))*64 ); | ||
4802 | if( x4a->tbl==0 ){ | 4949 | if( x4a->tbl==0 ){ |
4803 | free(x4a); | 4950 | free(x4a); |
4804 | x4a = 0; | 4951 | x4a = 0; |
@@ -4814,8 +4961,8 @@ void Configtable_init(){ | |||
4814 | int Configtable_insert(struct config *data) | 4961 | int Configtable_insert(struct config *data) |
4815 | { | 4962 | { |
4816 | x4node *np; | 4963 | x4node *np; |
4817 | int h; | 4964 | unsigned h; |
4818 | int ph; | 4965 | unsigned ph; |
4819 | 4966 | ||
4820 | if( x4a==0 ) return 0; | 4967 | if( x4a==0 ) return 0; |
4821 | ph = confighash(data); | 4968 | ph = confighash(data); |
@@ -4835,8 +4982,7 @@ int Configtable_insert(struct config *data) | |||
4835 | struct s_x4 array; | 4982 | struct s_x4 array; |
4836 | array.size = size = x4a->size*2; | 4983 | array.size = size = x4a->size*2; |
4837 | array.count = x4a->count; | 4984 | array.count = x4a->count; |
4838 | array.tbl = (x4node*)malloc( | 4985 | array.tbl = (x4node*)calloc(size, sizeof(x4node) + sizeof(x4node*)); |
4839 | (sizeof(x4node) + sizeof(x4node*))*size ); | ||
4840 | if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 4986 | if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
4841 | array.ht = (x4node**)&(array.tbl[size]); | 4987 | array.ht = (x4node**)&(array.tbl[size]); |
4842 | for(i=0; i<size; i++) array.ht[i] = 0; | 4988 | for(i=0; i<size; i++) array.ht[i] = 0; |