OLD | NEW |
1 /* | 1 /* |
2 ** This file contains all sources (including headers) to the LEMON | 2 ** This file contains all sources (including headers) to the LEMON |
3 ** LALR(1) parser generator. The sources have been combined into a | 3 ** LALR(1) parser generator. The sources have been combined into a |
4 ** single file to make it easy to include LEMON in the source tree | 4 ** single file to make it easy to include LEMON in the source tree |
5 ** and Makefile of another program. | 5 ** and Makefile of another program. |
6 ** | 6 ** |
7 ** The author of this program disclaims copyright. | 7 ** The author of this program disclaims copyright. |
8 */ | 8 */ |
9 #include <stdio.h> | 9 #include <stdio.h> |
10 #include <stdarg.h> | 10 #include <stdarg.h> |
11 #include <string.h> | 11 #include <string.h> |
12 #include <ctype.h> | 12 #include <ctype.h> |
13 #include <stdlib.h> | 13 #include <stdlib.h> |
14 #include <assert.h> | 14 #include <assert.h> |
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 |
22 #ifdef __WIN32__ | 22 #ifdef __WIN32__ |
23 #ifdef __cplusplus | 23 #ifdef __cplusplus |
24 extern "C" { | 24 extern "C" { |
25 #endif | 25 #endif |
26 extern int access(const char *path, int mode); | 26 extern int access(const char *path, int mode); |
27 #ifdef __cplusplus | 27 #ifdef __cplusplus |
28 } | 28 } |
29 #endif | 29 #endif |
30 #else | 30 #else |
31 #include <unistd.h> | 31 #include <unistd.h> |
32 #endif | 32 #endif |
33 | 33 |
34 /* #define PRIVATE static */ | 34 /* #define PRIVATE static */ |
35 #define PRIVATE | 35 #define PRIVATE |
36 | 36 |
37 #ifdef TEST | 37 #ifdef TEST |
38 #define MAXRHS 5 /* Set low to exercise exception code */ | 38 #define MAXRHS 5 /* Set low to exercise exception code */ |
39 #else | 39 #else |
40 #define MAXRHS 1000 | 40 #define MAXRHS 1000 |
41 #endif | 41 #endif |
42 | 42 |
43 static int showPrecedenceConflict = 0; | 43 static int showPrecedenceConflict = 0; |
44 static const char **made_files = NULL; | |
45 static int made_files_count = 0; | |
46 static int successful_exit = 0; | |
47 static void LemonAtExit(void) | |
48 { | |
49 /* if we failed, delete (most) files we made, to unconfuse build tools. */ | |
50 int i; | |
51 for (i = 0; i < made_files_count; i++) { | |
52 if (!successful_exit) { | |
53 remove(made_files[i]); | |
54 } | |
55 } | |
56 free(made_files); | |
57 made_files_count = 0; | |
58 made_files = NULL; | |
59 } | |
60 | |
61 static char *msort(char*,char**,int(*)(const char*,const char*)); | 44 static char *msort(char*,char**,int(*)(const char*,const char*)); |
62 | 45 |
63 /* | 46 /* |
64 ** Compilers are getting increasingly pedantic about type conversions | 47 ** Compilers are getting increasingly pedantic about type conversions |
65 ** as C evolves ever closer to Ada.... To work around the latest problems | 48 ** as C evolves ever closer to Ada.... To work around the latest problems |
66 ** we have to define the following variant of strlen(). | 49 ** we have to define the following variant of strlen(). |
67 */ | 50 */ |
68 #define lemonStrlen(X) ((int)strlen(X)) | 51 #define lemonStrlen(X) ((int)strlen(X)) |
69 | 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; |
| 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 |
70 /* a few forward declarations... */ | 154 /* a few forward declarations... */ |
71 struct rule; | 155 struct rule; |
72 struct lemon; | 156 struct lemon; |
73 struct action; | 157 struct action; |
74 | 158 |
75 static struct action *Action_new(void); | 159 static struct action *Action_new(void); |
76 static struct action *Action_sort(struct action *); | 160 static struct action *Action_sort(struct action *); |
77 | 161 |
78 /********** From the file "build.h" ************************************/ | 162 /********** From the file "build.h" ************************************/ |
79 void FindRulePrecedences(); | 163 void FindRulePrecedences(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 void ReportOutput(struct lemon *); | 211 void ReportOutput(struct lemon *); |
128 void ReportTable(struct lemon *, int); | 212 void ReportTable(struct lemon *, int); |
129 void ReportHeader(struct lemon *); | 213 void ReportHeader(struct lemon *); |
130 void CompressTables(struct lemon *); | 214 void CompressTables(struct lemon *); |
131 void ResortStates(struct lemon *); | 215 void ResortStates(struct lemon *); |
132 | 216 |
133 /********** From the file "set.h" ****************************************/ | 217 /********** From the file "set.h" ****************************************/ |
134 void SetSize(int); /* All sets will be of size N */ | 218 void SetSize(int); /* All sets will be of size N */ |
135 char *SetNew(void); /* A new set for element 0..N */ | 219 char *SetNew(void); /* A new set for element 0..N */ |
136 void SetFree(char*); /* Deallocate a set */ | 220 void SetFree(char*); /* Deallocate a set */ |
137 | |
138 char *SetNew(void); /* A new set for element 0..N */ | |
139 int SetAdd(char*,int); /* Add element to a set */ | 221 int SetAdd(char*,int); /* Add element to a set */ |
140 int SetUnion(char *,char *); /* A <- A U B, thru element N */ | 222 int SetUnion(char *,char *); /* A <- A U B, thru element N */ |
141 #define SetFind(X,Y) (X[Y]) /* True if Y is in set X */ | 223 #define SetFind(X,Y) (X[Y]) /* True if Y is in set X */ |
142 | 224 |
143 /********** From the file "struct.h" *************************************/ | 225 /********** From the file "struct.h" *************************************/ |
144 /* | 226 /* |
145 ** Principal data structures for the LEMON parser generator. | 227 ** Principal data structures for the LEMON parser generator. |
146 */ | 228 */ |
147 | 229 |
148 typedef enum {LEMON_FALSE=0, LEMON_TRUE} Boolean; | 230 typedef enum {LEMON_FALSE=0, LEMON_TRUE} Boolean; |
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 struct symbol *sp = rp->rhs[i]; | 747 struct symbol *sp = rp->rhs[i]; |
666 if( sp->type==MULTITERMINAL ){ | 748 if( sp->type==MULTITERMINAL ){ |
667 for(j=0; j<sp->nsubsym; j++){ | 749 for(j=0; j<sp->nsubsym; j++){ |
668 if( sp->subsym[j]->prec>=0 ){ | 750 if( sp->subsym[j]->prec>=0 ){ |
669 rp->precsym = sp->subsym[j]; | 751 rp->precsym = sp->subsym[j]; |
670 break; | 752 break; |
671 } | 753 } |
672 } | 754 } |
673 }else if( sp->prec>=0 ){ | 755 }else if( sp->prec>=0 ){ |
674 rp->precsym = rp->rhs[i]; | 756 rp->precsym = rp->rhs[i]; |
675 » } | 757 } |
676 } | 758 } |
677 } | 759 } |
678 } | 760 } |
679 return; | 761 return; |
680 } | 762 } |
681 | 763 |
682 /* Find all nonterminals which will generate the empty string. | 764 /* Find all nonterminals which will generate the empty string. |
683 ** Then go back and compute the first sets of every nonterminal. | 765 ** Then go back and compute the first sets of every nonterminal. |
684 ** The first set is the set of all terminal symbols which can begin | 766 ** The first set is the set of all terminal symbols which can begin |
685 ** a string generated by that nonterminal. | 767 ** a string generated by that nonterminal. |
(...skipping 10 matching lines...) Expand all Loading... |
696 for(i=lemp->nterminal; i<lemp->nsymbol; i++){ | 778 for(i=lemp->nterminal; i<lemp->nsymbol; i++){ |
697 lemp->symbols[i]->firstset = SetNew(); | 779 lemp->symbols[i]->firstset = SetNew(); |
698 } | 780 } |
699 | 781 |
700 /* First compute all lambdas */ | 782 /* First compute all lambdas */ |
701 do{ | 783 do{ |
702 progress = 0; | 784 progress = 0; |
703 for(rp=lemp->rule; rp; rp=rp->next){ | 785 for(rp=lemp->rule; rp; rp=rp->next){ |
704 if( rp->lhs->lambda ) continue; | 786 if( rp->lhs->lambda ) continue; |
705 for(i=0; i<rp->nrhs; i++){ | 787 for(i=0; i<rp->nrhs; i++){ |
706 struct symbol *sp = rp->rhs[i]; | 788 struct symbol *sp = rp->rhs[i]; |
707 if( sp->type!=TERMINAL || sp->lambda==LEMON_FALSE ) break; | 789 assert( sp->type==NONTERMINAL || sp->lambda==LEMON_FALSE ); |
| 790 if( sp->lambda==LEMON_FALSE ) break; |
708 } | 791 } |
709 if( i==rp->nrhs ){ | 792 if( i==rp->nrhs ){ |
710 rp->lhs->lambda = LEMON_TRUE; | 793 rp->lhs->lambda = LEMON_TRUE; |
711 progress = 1; | 794 progress = 1; |
712 } | 795 } |
713 } | 796 } |
714 }while( progress ); | 797 }while( progress ); |
715 | 798 |
716 /* Now compute all first sets */ | 799 /* Now compute all first sets */ |
717 do{ | 800 do{ |
718 struct symbol *s1, *s2; | 801 struct symbol *s1, *s2; |
719 progress = 0; | 802 progress = 0; |
720 for(rp=lemp->rule; rp; rp=rp->next){ | 803 for(rp=lemp->rule; rp; rp=rp->next){ |
721 s1 = rp->lhs; | 804 s1 = rp->lhs; |
722 for(i=0; i<rp->nrhs; i++){ | 805 for(i=0; i<rp->nrhs; i++){ |
723 s2 = rp->rhs[i]; | 806 s2 = rp->rhs[i]; |
724 if( s2->type==TERMINAL ){ | 807 if( s2->type==TERMINAL ){ |
725 progress += SetAdd(s1->firstset,s2->index); | 808 progress += SetAdd(s1->firstset,s2->index); |
726 break; | 809 break; |
727 }else if( s2->type==MULTITERMINAL ){ | 810 }else if( s2->type==MULTITERMINAL ){ |
728 for(j=0; j<s2->nsubsym; j++){ | 811 for(j=0; j<s2->nsubsym; j++){ |
729 progress += SetAdd(s1->firstset,s2->subsym[j]->index); | 812 progress += SetAdd(s1->firstset,s2->subsym[j]->index); |
730 } | 813 } |
731 break; | 814 break; |
732 » }else if( s1==s2 ){ | 815 }else if( s1==s2 ){ |
733 if( s1->lambda==LEMON_FALSE ) break; | 816 if( s1->lambda==LEMON_FALSE ) break; |
734 » }else{ | 817 }else{ |
735 progress += SetUnion(s1->firstset,s2->firstset); | 818 progress += SetUnion(s1->firstset,s2->firstset); |
736 if( s2->lambda==LEMON_FALSE ) break; | 819 if( s2->lambda==LEMON_FALSE ) break; |
737 » } | 820 } |
738 } | 821 } |
739 } | 822 } |
740 }while( progress ); | 823 }while( progress ); |
741 return; | 824 return; |
742 } | 825 } |
743 | 826 |
744 /* Compute all LR(0) states for the grammar. Links | 827 /* Compute all LR(0) states for the grammar. Links |
745 ** are added to between some states so that the LR(1) follow sets | 828 ** are added to between some states so that the LR(1) follow sets |
746 ** can be computed later. | 829 ** can be computed later. |
747 */ | 830 */ |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
970 do{ | 1053 do{ |
971 progress = 0; | 1054 progress = 0; |
972 for(i=0; i<lemp->nstate; i++){ | 1055 for(i=0; i<lemp->nstate; i++){ |
973 for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){ | 1056 for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){ |
974 if( cfp->status==COMPLETE ) continue; | 1057 if( cfp->status==COMPLETE ) continue; |
975 for(plp=cfp->fplp; plp; plp=plp->next){ | 1058 for(plp=cfp->fplp; plp; plp=plp->next){ |
976 change = SetUnion(plp->cfp->fws,cfp->fws); | 1059 change = SetUnion(plp->cfp->fws,cfp->fws); |
977 if( change ){ | 1060 if( change ){ |
978 plp->cfp->status = INCOMPLETE; | 1061 plp->cfp->status = INCOMPLETE; |
979 progress = 1; | 1062 progress = 1; |
980 » } | 1063 } |
981 » } | 1064 } |
982 cfp->status = COMPLETE; | 1065 cfp->status = COMPLETE; |
983 } | 1066 } |
984 } | 1067 } |
985 }while( progress ); | 1068 }while( progress ); |
986 } | 1069 } |
987 | 1070 |
988 static int resolve_conflict(struct action *,struct action *, struct symbol *); | 1071 static int resolve_conflict(struct action *,struct action *); |
989 | 1072 |
990 /* Compute the reduce actions, and resolve conflicts. | 1073 /* Compute the reduce actions, and resolve conflicts. |
991 */ | 1074 */ |
992 void FindActions(struct lemon *lemp) | 1075 void FindActions(struct lemon *lemp) |
993 { | 1076 { |
994 int i,j; | 1077 int i,j; |
995 struct config *cfp; | 1078 struct config *cfp; |
996 struct state *stp; | 1079 struct state *stp; |
997 struct symbol *sp; | 1080 struct symbol *sp; |
998 struct rule *rp; | 1081 struct rule *rp; |
999 | 1082 |
1000 /* Add all of the reduce actions | 1083 /* Add all of the reduce actions |
1001 ** A reduce action is added for each element of the followset of | 1084 ** A reduce action is added for each element of the followset of |
1002 ** a configuration which has its dot at the extreme right. | 1085 ** a configuration which has its dot at the extreme right. |
1003 */ | 1086 */ |
1004 for(i=0; i<lemp->nstate; i++){ /* Loop over all states */ | 1087 for(i=0; i<lemp->nstate; i++){ /* Loop over all states */ |
1005 stp = lemp->sorted[i]; | 1088 stp = lemp->sorted[i]; |
1006 for(cfp=stp->cfp; cfp; cfp=cfp->next){ /* Loop over all configurations */ | 1089 for(cfp=stp->cfp; cfp; cfp=cfp->next){ /* Loop over all configurations */ |
1007 if( cfp->rp->nrhs==cfp->dot ){ /* Is dot at extreme right? */ | 1090 if( cfp->rp->nrhs==cfp->dot ){ /* Is dot at extreme right? */ |
1008 for(j=0; j<lemp->nterminal; j++){ | 1091 for(j=0; j<lemp->nterminal; j++){ |
1009 if( SetFind(cfp->fws,j) ){ | 1092 if( SetFind(cfp->fws,j) ){ |
1010 /* Add a reduce action to the state "stp" which will reduce by the | 1093 /* Add a reduce action to the state "stp" which will reduce by the |
1011 ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */ | 1094 ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */ |
1012 Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp); | 1095 Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp); |
1013 } | 1096 } |
1014 » } | 1097 } |
1015 } | 1098 } |
1016 } | 1099 } |
1017 } | 1100 } |
1018 | 1101 |
1019 /* Add the accepting token */ | 1102 /* Add the accepting token */ |
1020 if( lemp->start ){ | 1103 if( lemp->start ){ |
1021 sp = Symbol_find(lemp->start); | 1104 sp = Symbol_find(lemp->start); |
1022 if( sp==0 ) sp = lemp->rule->lhs; | 1105 if( sp==0 ) sp = lemp->rule->lhs; |
1023 }else{ | 1106 }else{ |
1024 sp = lemp->rule->lhs; | 1107 sp = lemp->rule->lhs; |
1025 } | 1108 } |
1026 /* Add to the first state (which is always the starting state of the | 1109 /* Add to the first state (which is always the starting state of the |
1027 ** finite state machine) an action to ACCEPT if the lookahead is the | 1110 ** finite state machine) an action to ACCEPT if the lookahead is the |
1028 ** start nonterminal. */ | 1111 ** start nonterminal. */ |
1029 Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0); | 1112 Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0); |
1030 | 1113 |
1031 /* Resolve conflicts */ | 1114 /* Resolve conflicts */ |
1032 for(i=0; i<lemp->nstate; i++){ | 1115 for(i=0; i<lemp->nstate; i++){ |
1033 struct action *ap, *nap; | 1116 struct action *ap, *nap; |
1034 struct state *stp; | 1117 struct state *stp; |
1035 stp = lemp->sorted[i]; | 1118 stp = lemp->sorted[i]; |
1036 /* assert( stp->ap ); */ | 1119 /* assert( stp->ap ); */ |
1037 stp->ap = Action_sort(stp->ap); | 1120 stp->ap = Action_sort(stp->ap); |
1038 for(ap=stp->ap; ap && ap->next; ap=ap->next){ | 1121 for(ap=stp->ap; ap && ap->next; ap=ap->next){ |
1039 for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){ | 1122 for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){ |
1040 /* The two actions "ap" and "nap" have the same lookahead. | 1123 /* The two actions "ap" and "nap" have the same lookahead. |
1041 ** Figure out which one should be used */ | 1124 ** Figure out which one should be used */ |
1042 lemp->nconflict += resolve_conflict(ap,nap,lemp->errsym); | 1125 lemp->nconflict += resolve_conflict(ap,nap); |
1043 } | 1126 } |
1044 } | 1127 } |
1045 } | 1128 } |
1046 | 1129 |
1047 /* Report an error for each rule that can never be reduced. */ | 1130 /* Report an error for each rule that can never be reduced. */ |
1048 for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = LEMON_FALSE; | 1131 for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = LEMON_FALSE; |
1049 for(i=0; i<lemp->nstate; i++){ | 1132 for(i=0; i<lemp->nstate; i++){ |
1050 struct action *ap; | 1133 struct action *ap; |
1051 for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){ | 1134 for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){ |
1052 if( ap->type==REDUCE ) ap->x.rp->canReduce = LEMON_TRUE; | 1135 if( ap->type==REDUCE ) ap->x.rp->canReduce = LEMON_TRUE; |
(...skipping 14 matching lines...) Expand all Loading... |
1067 ** is on an error rule. In that case, take the action which | 1150 ** is on an error rule. In that case, take the action which |
1068 ** is not associated with the error rule. If neither or both | 1151 ** is not associated with the error rule. If neither or both |
1069 ** actions are associated with an error rule, then try to | 1152 ** actions are associated with an error rule, then try to |
1070 ** use precedence to resolve the conflict. | 1153 ** use precedence to resolve the conflict. |
1071 ** | 1154 ** |
1072 ** If either action is a SHIFT, then it must be apx. This | 1155 ** If either action is a SHIFT, then it must be apx. This |
1073 ** function won't work if apx->type==REDUCE and apy->type==SHIFT. | 1156 ** function won't work if apx->type==REDUCE and apy->type==SHIFT. |
1074 */ | 1157 */ |
1075 static int resolve_conflict( | 1158 static int resolve_conflict( |
1076 struct action *apx, | 1159 struct action *apx, |
1077 struct action *apy, | 1160 struct action *apy |
1078 struct symbol *errsym /* The error symbol (if defined. NULL otherwise) */ | |
1079 ){ | 1161 ){ |
1080 struct symbol *spx, *spy; | 1162 struct symbol *spx, *spy; |
1081 int errcnt = 0; | 1163 int errcnt = 0; |
1082 assert( apx->sp==apy->sp ); /* Otherwise there would be no conflict */ | 1164 assert( apx->sp==apy->sp ); /* Otherwise there would be no conflict */ |
1083 if( apx->type==SHIFT && apy->type==SHIFT ){ | 1165 if( apx->type==SHIFT && apy->type==SHIFT ){ |
1084 apy->type = SSCONFLICT; | 1166 apy->type = SSCONFLICT; |
1085 errcnt++; | 1167 errcnt++; |
1086 } | 1168 } |
1087 if( apx->type==SHIFT && apy->type==REDUCE ){ | 1169 if( apx->type==SHIFT && apy->type==REDUCE ){ |
1088 spx = apx->sp; | 1170 spx = apx->sp; |
1089 spy = apy->x.rp->precsym; | 1171 spy = apy->x.rp->precsym; |
1090 if( spy==0 || spx->prec<0 || spy->prec<0 ){ | 1172 if( spy==0 || spx->prec<0 || spy->prec<0 ){ |
1091 /* Not enough precedence information. */ | 1173 /* Not enough precedence information. */ |
1092 apy->type = SRCONFLICT; | 1174 apy->type = SRCONFLICT; |
1093 errcnt++; | 1175 errcnt++; |
1094 }else if( spx->prec>spy->prec ){ /* higher precedence wins */ | 1176 }else if( spx->prec>spy->prec ){ /* higher precedence wins */ |
1095 apy->type = RD_RESOLVED; | 1177 apy->type = RD_RESOLVED; |
1096 }else if( spx->prec<spy->prec ){ | 1178 }else if( spx->prec<spy->prec ){ |
1097 apx->type = SH_RESOLVED; | 1179 apx->type = SH_RESOLVED; |
1098 }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */ | 1180 }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */ |
1099 apy->type = RD_RESOLVED; /* associativity */ | 1181 apy->type = RD_RESOLVED; /* associativity */ |
1100 }else if( spx->prec==spy->prec && spx->assoc==LEFT ){ /* to break tie */ | 1182 }else if( spx->prec==spy->prec && spx->assoc==LEFT ){ /* to break tie */ |
1101 apx->type = SH_RESOLVED; | 1183 apx->type = SH_RESOLVED; |
1102 }else{ | 1184 }else{ |
1103 assert( spx->prec==spy->prec && spx->assoc==NONE ); | 1185 assert( spx->prec==spy->prec && spx->assoc==NONE ); |
1104 apy->type = SRCONFLICT; | 1186 apx->type = ERROR; |
1105 errcnt++; | |
1106 } | 1187 } |
1107 }else if( apx->type==REDUCE && apy->type==REDUCE ){ | 1188 }else if( apx->type==REDUCE && apy->type==REDUCE ){ |
1108 spx = apx->x.rp->precsym; | 1189 spx = apx->x.rp->precsym; |
1109 spy = apy->x.rp->precsym; | 1190 spy = apy->x.rp->precsym; |
1110 if( spx==0 || spy==0 || spx->prec<0 || | 1191 if( spx==0 || spy==0 || spx->prec<0 || |
1111 spy->prec<0 || spx->prec==spy->prec ){ | 1192 spy->prec<0 || spx->prec==spy->prec ){ |
1112 apy->type = RRCONFLICT; | 1193 apy->type = RRCONFLICT; |
1113 errcnt++; | 1194 errcnt++; |
1114 }else if( spx->prec>spy->prec ){ | 1195 }else if( spx->prec>spy->prec ){ |
1115 apy->type = RD_RESOLVED; | 1196 apy->type = RD_RESOLVED; |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1274 xsp = rp->rhs[i]; | 1355 xsp = rp->rhs[i]; |
1275 if( xsp->type==TERMINAL ){ | 1356 if( xsp->type==TERMINAL ){ |
1276 SetAdd(newcfp->fws,xsp->index); | 1357 SetAdd(newcfp->fws,xsp->index); |
1277 break; | 1358 break; |
1278 }else if( xsp->type==MULTITERMINAL ){ | 1359 }else if( xsp->type==MULTITERMINAL ){ |
1279 int k; | 1360 int k; |
1280 for(k=0; k<xsp->nsubsym; k++){ | 1361 for(k=0; k<xsp->nsubsym; k++){ |
1281 SetAdd(newcfp->fws, xsp->subsym[k]->index); | 1362 SetAdd(newcfp->fws, xsp->subsym[k]->index); |
1282 } | 1363 } |
1283 break; | 1364 break; |
1284 » }else{ | 1365 }else{ |
1285 SetUnion(newcfp->fws,xsp->firstset); | 1366 SetUnion(newcfp->fws,xsp->firstset); |
1286 if( xsp->lambda==LEMON_FALSE ) break; | 1367 if( xsp->lambda==LEMON_FALSE ) break; |
1287 » } | 1368 } |
1288 » } | 1369 } |
1289 if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); | 1370 if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); |
1290 } | 1371 } |
1291 } | 1372 } |
1292 } | 1373 } |
1293 return; | 1374 return; |
1294 } | 1375 } |
1295 | 1376 |
1296 /* Sort the configuration list */ | 1377 /* Sort the configuration list */ |
1297 void Configlist_sort(){ | 1378 void Configlist_sort(){ |
1298 current = (struct config *)msort((char *)current,(char **)&(current->next),Con
figcmp); | 1379 current = (struct config *)msort((char *)current,(char **)&(current->next),Con
figcmp); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1379 if( azDefine==0 ){ | 1460 if( azDefine==0 ){ |
1380 fprintf(stderr,"out of memory\n"); | 1461 fprintf(stderr,"out of memory\n"); |
1381 exit(1); | 1462 exit(1); |
1382 } | 1463 } |
1383 paz = &azDefine[nDefine-1]; | 1464 paz = &azDefine[nDefine-1]; |
1384 *paz = (char *) malloc( lemonStrlen(z)+1 ); | 1465 *paz = (char *) malloc( lemonStrlen(z)+1 ); |
1385 if( *paz==0 ){ | 1466 if( *paz==0 ){ |
1386 fprintf(stderr,"out of memory\n"); | 1467 fprintf(stderr,"out of memory\n"); |
1387 exit(1); | 1468 exit(1); |
1388 } | 1469 } |
1389 strcpy(*paz, z); | 1470 lemon_strcpy(*paz, z); |
1390 for(z=*paz; *z && *z!='='; z++){} | 1471 for(z=*paz; *z && *z!='='; z++){} |
1391 *z = 0; | 1472 *z = 0; |
1392 } | 1473 } |
1393 | 1474 |
1394 static char *user_templatename = NULL; | 1475 static char *user_templatename = NULL; |
1395 static void handle_T_option(char *z){ | 1476 static void handle_T_option(char *z){ |
1396 user_templatename = (char *) malloc( lemonStrlen(z)+1 ); | 1477 user_templatename = (char *) malloc( lemonStrlen(z)+1 ); |
1397 if( user_templatename==0 ){ | 1478 if( user_templatename==0 ){ |
1398 memory_error(); | 1479 memory_error(); |
1399 } | 1480 } |
1400 strcpy(user_templatename, z); | 1481 lemon_strcpy(user_templatename, z); |
1401 } | 1482 } |
1402 | 1483 |
1403 /* The main program. Parse the command line and do it... */ | 1484 /* The main program. Parse the command line and do it... */ |
1404 int main(int argc, char **argv) | 1485 int main(int argc, char **argv) |
1405 { | 1486 { |
1406 static int version = 0; | 1487 static int version = 0; |
1407 static int rpflag = 0; | 1488 static int rpflag = 0; |
1408 static int basisflag = 0; | 1489 static int basisflag = 0; |
1409 static int compress = 0; | 1490 static int compress = 0; |
1410 static int quiet = 0; | 1491 static int quiet = 0; |
(...skipping 15 matching lines...) Expand all Loading... |
1426 {OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"}, | 1507 {OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"}, |
1427 {OPT_FLAG, "s", (char*)&statistics, | 1508 {OPT_FLAG, "s", (char*)&statistics, |
1428 "Print parser stats to standard output."}, | 1509 "Print parser stats to standard output."}, |
1429 {OPT_FLAG, "x", (char*)&version, "Print the version number."}, | 1510 {OPT_FLAG, "x", (char*)&version, "Print the version number."}, |
1430 {OPT_FLAG,0,0,0} | 1511 {OPT_FLAG,0,0,0} |
1431 }; | 1512 }; |
1432 int i; | 1513 int i; |
1433 int exitcode; | 1514 int exitcode; |
1434 struct lemon lem; | 1515 struct lemon lem; |
1435 | 1516 |
1436 atexit(LemonAtExit); | |
1437 | |
1438 OptInit(argv,options,stderr); | 1517 OptInit(argv,options,stderr); |
1439 if( version ){ | 1518 if( version ){ |
1440 printf("Lemon version 1.0\n"); | 1519 printf("Lemon version 1.0\n"); |
1441 exit(0); | 1520 exit(0); |
1442 } | 1521 } |
1443 if( OptNArgs()!=1 ){ | 1522 if( OptNArgs()!=1 ){ |
1444 fprintf(stderr,"Exactly one filename argument is required.\n"); | 1523 fprintf(stderr,"Exactly one filename argument is required.\n"); |
1445 exit(1); | 1524 exit(1); |
1446 } | 1525 } |
1447 memset(&lem, 0, sizeof(lem)); | 1526 memset(&lem, 0, sizeof(lem)); |
(...skipping 13 matching lines...) Expand all Loading... |
1461 | 1540 |
1462 /* Parse the input file */ | 1541 /* Parse the input file */ |
1463 Parse(&lem); | 1542 Parse(&lem); |
1464 if( lem.errorcnt ) exit(lem.errorcnt); | 1543 if( lem.errorcnt ) exit(lem.errorcnt); |
1465 if( lem.nrule==0 ){ | 1544 if( lem.nrule==0 ){ |
1466 fprintf(stderr,"Empty grammar.\n"); | 1545 fprintf(stderr,"Empty grammar.\n"); |
1467 exit(1); | 1546 exit(1); |
1468 } | 1547 } |
1469 | 1548 |
1470 /* Count and index the symbols of the grammar */ | 1549 /* Count and index the symbols of the grammar */ |
| 1550 Symbol_new("{default}"); |
1471 lem.nsymbol = Symbol_count(); | 1551 lem.nsymbol = Symbol_count(); |
1472 Symbol_new("{default}"); | |
1473 lem.symbols = Symbol_arrayof(); | 1552 lem.symbols = Symbol_arrayof(); |
1474 for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i; | 1553 for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; |
1475 qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*), Symbolcmpp); | 1554 qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp); |
1476 for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i; | 1555 for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; |
| 1556 while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; } |
| 1557 assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 ); |
| 1558 lem.nsymbol = i - 1; |
1477 for(i=1; isupper(lem.symbols[i]->name[0]); i++); | 1559 for(i=1; isupper(lem.symbols[i]->name[0]); i++); |
1478 lem.nterminal = i; | 1560 lem.nterminal = i; |
1479 | 1561 |
1480 /* Generate a reprint of the grammar, if requested on the command line */ | 1562 /* Generate a reprint of the grammar, if requested on the command line */ |
1481 if( rpflag ){ | 1563 if( rpflag ){ |
1482 Reprint(&lem); | 1564 Reprint(&lem); |
1483 }else{ | 1565 }else{ |
1484 /* Initialize the size for all follow and first sets */ | 1566 /* Initialize the size for all follow and first sets */ |
1485 SetSize(lem.nterminal+1); | 1567 SetSize(lem.nterminal+1); |
1486 | 1568 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1530 lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule); | 1612 lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule); |
1531 printf(" %d states, %d parser table entries, %d conflicts\
n", | 1613 printf(" %d states, %d parser table entries, %d conflicts\
n", |
1532 lem.nstate, lem.tablesize, lem.nconflict); | 1614 lem.nstate, lem.tablesize, lem.nconflict); |
1533 } | 1615 } |
1534 if( lem.nconflict > 0 ){ | 1616 if( lem.nconflict > 0 ){ |
1535 fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict); | 1617 fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict); |
1536 } | 1618 } |
1537 | 1619 |
1538 /* return 0 on success, 1 on failure. */ | 1620 /* return 0 on success, 1 on failure. */ |
1539 exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0; | 1621 exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0; |
1540 successful_exit = (exitcode == 0); | |
1541 exit(exitcode); | 1622 exit(exitcode); |
1542 return (exitcode); | 1623 return (exitcode); |
1543 } | 1624 } |
1544 /******************** From the file "msort.c" *******************************/ | 1625 /******************** From the file "msort.c" *******************************/ |
1545 /* | 1626 /* |
1546 ** A generic merge-sort program. | 1627 ** A generic merge-sort program. |
1547 ** | 1628 ** |
1548 ** USAGE: | 1629 ** USAGE: |
1549 ** Let "ptr" be a pointer to some structure which is at the head of | 1630 ** Let "ptr" be a pointer to some structure which is at the head of |
1550 ** a null-terminated list. Then to sort the list call: | 1631 ** a null-terminated list. Then to sort the list call: |
(...skipping 10 matching lines...) Expand all Loading... |
1561 ** The function returns a new pointer which is the head of the list | 1642 ** The function returns a new pointer which is the head of the list |
1562 ** after sorting. | 1643 ** after sorting. |
1563 ** | 1644 ** |
1564 ** ALGORITHM: | 1645 ** ALGORITHM: |
1565 ** Merge-sort. | 1646 ** Merge-sort. |
1566 */ | 1647 */ |
1567 | 1648 |
1568 /* | 1649 /* |
1569 ** Return a pointer to the next structure in the linked list. | 1650 ** Return a pointer to the next structure in the linked list. |
1570 */ | 1651 */ |
1571 #define NEXT(A) (*(char**)(((unsigned long)A)+offset)) | 1652 #define NEXT(A) (*(char**)(((char*)A)+offset)) |
1572 | 1653 |
1573 /* | 1654 /* |
1574 ** Inputs: | 1655 ** Inputs: |
1575 ** a: A sorted, null-terminated linked list. (May be null). | 1656 ** a: A sorted, null-terminated linked list. (May be null). |
1576 ** b: A sorted, null-terminated linked list. (May be null). | 1657 ** b: A sorted, null-terminated linked list. (May be null). |
1577 ** cmp: A pointer to the comparison function. | 1658 ** cmp: A pointer to the comparison function. |
1578 ** offset: Offset in the structure to the "next" field. | 1659 ** offset: Offset in the structure to the "next" field. |
1579 ** | 1660 ** |
1580 ** Return Value: | 1661 ** Return Value: |
1581 ** A pointer to the head of a sorted list containing the elements | 1662 ** A pointer to the head of a sorted list containing the elements |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1955 LHS_ALIAS_3, | 2036 LHS_ALIAS_3, |
1956 RHS_ALIAS_1, | 2037 RHS_ALIAS_1, |
1957 RHS_ALIAS_2, | 2038 RHS_ALIAS_2, |
1958 PRECEDENCE_MARK_1, | 2039 PRECEDENCE_MARK_1, |
1959 PRECEDENCE_MARK_2, | 2040 PRECEDENCE_MARK_2, |
1960 RESYNC_AFTER_RULE_ERROR, | 2041 RESYNC_AFTER_RULE_ERROR, |
1961 RESYNC_AFTER_DECL_ERROR, | 2042 RESYNC_AFTER_DECL_ERROR, |
1962 WAITING_FOR_DESTRUCTOR_SYMBOL, | 2043 WAITING_FOR_DESTRUCTOR_SYMBOL, |
1963 WAITING_FOR_DATATYPE_SYMBOL, | 2044 WAITING_FOR_DATATYPE_SYMBOL, |
1964 WAITING_FOR_FALLBACK_ID, | 2045 WAITING_FOR_FALLBACK_ID, |
1965 WAITING_FOR_WILDCARD_ID | 2046 WAITING_FOR_WILDCARD_ID, |
| 2047 WAITING_FOR_CLASS_ID, |
| 2048 WAITING_FOR_CLASS_TOKEN |
1966 }; | 2049 }; |
1967 struct pstate { | 2050 struct pstate { |
1968 char *filename; /* Name of the input file */ | 2051 char *filename; /* Name of the input file */ |
1969 int tokenlineno; /* Linenumber at which current token starts */ | 2052 int tokenlineno; /* Linenumber at which current token starts */ |
1970 int errorcnt; /* Number of errors so far */ | 2053 int errorcnt; /* Number of errors so far */ |
1971 char *tokenstart; /* Text of current token */ | 2054 char *tokenstart; /* Text of current token */ |
1972 struct lemon *gp; /* Global state vector */ | 2055 struct lemon *gp; /* Global state vector */ |
1973 enum e_state state; /* The state of the parser */ | 2056 enum e_state state; /* The state of the parser */ |
1974 struct symbol *fallback; /* The fallback token */ | 2057 struct symbol *fallback; /* The fallback token */ |
| 2058 struct symbol *tkclass; /* Token class symbol */ |
1975 struct symbol *lhs; /* Left-hand side of current rule */ | 2059 struct symbol *lhs; /* Left-hand side of current rule */ |
1976 const char *lhsalias; /* Alias for the LHS */ | 2060 const char *lhsalias; /* Alias for the LHS */ |
1977 int nrhs; /* Number of right-hand side symbols seen */ | 2061 int nrhs; /* Number of right-hand side symbols seen */ |
1978 struct symbol *rhs[MAXRHS]; /* RHS symbols */ | 2062 struct symbol *rhs[MAXRHS]; /* RHS symbols */ |
1979 const char *alias[MAXRHS]; /* Aliases for each RHS symbol (or NULL) */ | 2063 const char *alias[MAXRHS]; /* Aliases for each RHS symbol (or NULL) */ |
1980 struct rule *prevrule; /* Previous rule parsed */ | 2064 struct rule *prevrule; /* Previous rule parsed */ |
1981 const char *declkeyword; /* Keyword of a declaration */ | 2065 const char *declkeyword; /* Keyword of a declaration */ |
1982 char **declargslot; /* Where the declaration argument should be put */ | 2066 char **declargslot; /* Where the declaration argument should be put */ |
1983 int insertLineMacro; /* Add #line before declaration insert */ | 2067 int insertLineMacro; /* Add #line before declaration insert */ |
1984 int *decllinenoslot; /* Where to write declaration line number */ | 2068 int *decllinenoslot; /* Where to write declaration line number */ |
(...skipping 23 matching lines...) Expand all Loading... |
2008 if( x[0]=='%' ){ | 2092 if( x[0]=='%' ){ |
2009 psp->state = WAITING_FOR_DECL_KEYWORD; | 2093 psp->state = WAITING_FOR_DECL_KEYWORD; |
2010 }else if( islower(x[0]) ){ | 2094 }else if( islower(x[0]) ){ |
2011 psp->lhs = Symbol_new(x); | 2095 psp->lhs = Symbol_new(x); |
2012 psp->nrhs = 0; | 2096 psp->nrhs = 0; |
2013 psp->lhsalias = 0; | 2097 psp->lhsalias = 0; |
2014 psp->state = WAITING_FOR_ARROW; | 2098 psp->state = WAITING_FOR_ARROW; |
2015 }else if( x[0]=='{' ){ | 2099 }else if( x[0]=='{' ){ |
2016 if( psp->prevrule==0 ){ | 2100 if( psp->prevrule==0 ){ |
2017 ErrorMsg(psp->filename,psp->tokenlineno, | 2101 ErrorMsg(psp->filename,psp->tokenlineno, |
2018 "There is no prior rule opon which to attach the code \ | 2102 "There is no prior rule upon which to attach the code \ |
2019 fragment which begins on this line."); | 2103 fragment which begins on this line."); |
2020 psp->errorcnt++; | 2104 psp->errorcnt++; |
2021 » }else if( psp->prevrule->code!=0 ){ | 2105 }else if( psp->prevrule->code!=0 ){ |
2022 ErrorMsg(psp->filename,psp->tokenlineno, | 2106 ErrorMsg(psp->filename,psp->tokenlineno, |
2023 "Code fragment beginning on this line is not the first \ | 2107 "Code fragment beginning on this line is not the first \ |
2024 to follow the previous rule."); | 2108 to follow the previous rule."); |
2025 psp->errorcnt++; | 2109 psp->errorcnt++; |
2026 }else{ | 2110 }else{ |
2027 psp->prevrule->line = psp->tokenlineno; | 2111 psp->prevrule->line = psp->tokenlineno; |
2028 psp->prevrule->code = &x[1]; | 2112 psp->prevrule->code = &x[1]; |
2029 » } | 2113 } |
2030 }else if( x[0]=='[' ){ | 2114 }else if( x[0]=='[' ){ |
2031 psp->state = PRECEDENCE_MARK_1; | 2115 psp->state = PRECEDENCE_MARK_1; |
2032 }else{ | 2116 }else{ |
2033 ErrorMsg(psp->filename,psp->tokenlineno, | 2117 ErrorMsg(psp->filename,psp->tokenlineno, |
2034 "Token \"%s\" should be either \"%%\" or a nonterminal name.", | 2118 "Token \"%s\" should be either \"%%\" or a nonterminal name.", |
2035 x); | 2119 x); |
2036 psp->errorcnt++; | 2120 psp->errorcnt++; |
2037 } | 2121 } |
2038 break; | 2122 break; |
2039 case PRECEDENCE_MARK_1: | 2123 case PRECEDENCE_MARK_1: |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2112 case IN_RHS: | 2196 case IN_RHS: |
2113 if( x[0]=='.' ){ | 2197 if( x[0]=='.' ){ |
2114 struct rule *rp; | 2198 struct rule *rp; |
2115 rp = (struct rule *)calloc( sizeof(struct rule) + | 2199 rp = (struct rule *)calloc( sizeof(struct rule) + |
2116 sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1); | 2200 sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1); |
2117 if( rp==0 ){ | 2201 if( rp==0 ){ |
2118 ErrorMsg(psp->filename,psp->tokenlineno, | 2202 ErrorMsg(psp->filename,psp->tokenlineno, |
2119 "Can't allocate enough memory for this rule."); | 2203 "Can't allocate enough memory for this rule."); |
2120 psp->errorcnt++; | 2204 psp->errorcnt++; |
2121 psp->prevrule = 0; | 2205 psp->prevrule = 0; |
2122 » }else{ | 2206 }else{ |
2123 int i; | 2207 int i; |
2124 rp->ruleline = psp->tokenlineno; | 2208 rp->ruleline = psp->tokenlineno; |
2125 rp->rhs = (struct symbol**)&rp[1]; | 2209 rp->rhs = (struct symbol**)&rp[1]; |
2126 rp->rhsalias = (const char**)&(rp->rhs[psp->nrhs]); | 2210 rp->rhsalias = (const char**)&(rp->rhs[psp->nrhs]); |
2127 for(i=0; i<psp->nrhs; i++){ | 2211 for(i=0; i<psp->nrhs; i++){ |
2128 rp->rhs[i] = psp->rhs[i]; | 2212 rp->rhs[i] = psp->rhs[i]; |
2129 rp->rhsalias[i] = psp->alias[i]; | 2213 rp->rhsalias[i] = psp->alias[i]; |
2130 » } | 2214 } |
2131 rp->lhs = psp->lhs; | 2215 rp->lhs = psp->lhs; |
2132 rp->lhsalias = psp->lhsalias; | 2216 rp->lhsalias = psp->lhsalias; |
2133 rp->nrhs = psp->nrhs; | 2217 rp->nrhs = psp->nrhs; |
2134 rp->code = 0; | 2218 rp->code = 0; |
2135 rp->precsym = 0; | 2219 rp->precsym = 0; |
2136 rp->index = psp->gp->nrule++; | 2220 rp->index = psp->gp->nrule++; |
2137 rp->nextlhs = rp->lhs->rule; | 2221 rp->nextlhs = rp->lhs->rule; |
2138 rp->lhs->rule = rp; | 2222 rp->lhs->rule = rp; |
2139 rp->next = 0; | 2223 rp->next = 0; |
2140 if( psp->firstrule==0 ){ | 2224 if( psp->firstrule==0 ){ |
2141 psp->firstrule = psp->lastrule = rp; | 2225 psp->firstrule = psp->lastrule = rp; |
2142 » }else{ | 2226 }else{ |
2143 psp->lastrule->next = rp; | 2227 psp->lastrule->next = rp; |
2144 psp->lastrule = rp; | 2228 psp->lastrule = rp; |
2145 » } | 2229 } |
2146 psp->prevrule = rp; | 2230 psp->prevrule = rp; |
2147 » } | 2231 } |
2148 psp->state = WAITING_FOR_DECL_OR_RULE; | 2232 psp->state = WAITING_FOR_DECL_OR_RULE; |
2149 }else if( isalpha(x[0]) ){ | 2233 }else if( isalpha(x[0]) ){ |
2150 if( psp->nrhs>=MAXRHS ){ | 2234 if( psp->nrhs>=MAXRHS ){ |
2151 ErrorMsg(psp->filename,psp->tokenlineno, | 2235 ErrorMsg(psp->filename,psp->tokenlineno, |
2152 "Too many symbols on RHS of rule beginning at \"%s\".", | 2236 "Too many symbols on RHS of rule beginning at \"%s\".", |
2153 x); | 2237 x); |
2154 psp->errorcnt++; | 2238 psp->errorcnt++; |
2155 psp->state = RESYNC_AFTER_RULE_ERROR; | 2239 psp->state = RESYNC_AFTER_RULE_ERROR; |
2156 » }else{ | 2240 }else{ |
2157 psp->rhs[psp->nrhs] = Symbol_new(x); | 2241 psp->rhs[psp->nrhs] = Symbol_new(x); |
2158 psp->alias[psp->nrhs] = 0; | 2242 psp->alias[psp->nrhs] = 0; |
2159 psp->nrhs++; | 2243 psp->nrhs++; |
2160 » } | 2244 } |
2161 }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){ | 2245 }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){ |
2162 struct symbol *msp = psp->rhs[psp->nrhs-1]; | 2246 struct symbol *msp = psp->rhs[psp->nrhs-1]; |
2163 if( msp->type!=MULTITERMINAL ){ | 2247 if( msp->type!=MULTITERMINAL ){ |
2164 struct symbol *origsp = msp; | 2248 struct symbol *origsp = msp; |
2165 msp = (struct symbol *) calloc(1,sizeof(*msp)); | 2249 msp = (struct symbol *) calloc(1,sizeof(*msp)); |
2166 memset(msp, 0, sizeof(*msp)); | 2250 memset(msp, 0, sizeof(*msp)); |
2167 msp->type = MULTITERMINAL; | 2251 msp->type = MULTITERMINAL; |
2168 msp->nsubsym = 1; | 2252 msp->nsubsym = 1; |
2169 msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*)); | 2253 msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*)); |
2170 msp->subsym[0] = origsp; | 2254 msp->subsym[0] = origsp; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2214 case WAITING_FOR_DECL_KEYWORD: | 2298 case WAITING_FOR_DECL_KEYWORD: |
2215 if( isalpha(x[0]) ){ | 2299 if( isalpha(x[0]) ){ |
2216 psp->declkeyword = x; | 2300 psp->declkeyword = x; |
2217 psp->declargslot = 0; | 2301 psp->declargslot = 0; |
2218 psp->decllinenoslot = 0; | 2302 psp->decllinenoslot = 0; |
2219 psp->insertLineMacro = 1; | 2303 psp->insertLineMacro = 1; |
2220 psp->state = WAITING_FOR_DECL_ARG; | 2304 psp->state = WAITING_FOR_DECL_ARG; |
2221 if( strcmp(x,"name")==0 ){ | 2305 if( strcmp(x,"name")==0 ){ |
2222 psp->declargslot = &(psp->gp->name); | 2306 psp->declargslot = &(psp->gp->name); |
2223 psp->insertLineMacro = 0; | 2307 psp->insertLineMacro = 0; |
2224 » }else if( strcmp(x,"include")==0 ){ | 2308 }else if( strcmp(x,"include")==0 ){ |
2225 psp->declargslot = &(psp->gp->include); | 2309 psp->declargslot = &(psp->gp->include); |
2226 » }else if( strcmp(x,"code")==0 ){ | 2310 }else if( strcmp(x,"code")==0 ){ |
2227 psp->declargslot = &(psp->gp->extracode); | 2311 psp->declargslot = &(psp->gp->extracode); |
2228 » }else if( strcmp(x,"token_destructor")==0 ){ | 2312 }else if( strcmp(x,"token_destructor")==0 ){ |
2229 psp->declargslot = &psp->gp->tokendest; | 2313 psp->declargslot = &psp->gp->tokendest; |
2230 » }else if( strcmp(x,"default_destructor")==0 ){ | 2314 }else if( strcmp(x,"default_destructor")==0 ){ |
2231 psp->declargslot = &psp->gp->vardest; | 2315 psp->declargslot = &psp->gp->vardest; |
2232 » }else if( strcmp(x,"token_prefix")==0 ){ | 2316 }else if( strcmp(x,"token_prefix")==0 ){ |
2233 psp->declargslot = &psp->gp->tokenprefix; | 2317 psp->declargslot = &psp->gp->tokenprefix; |
2234 psp->insertLineMacro = 0; | 2318 psp->insertLineMacro = 0; |
2235 » }else if( strcmp(x,"syntax_error")==0 ){ | 2319 }else if( strcmp(x,"syntax_error")==0 ){ |
2236 psp->declargslot = &(psp->gp->error); | 2320 psp->declargslot = &(psp->gp->error); |
2237 » }else if( strcmp(x,"parse_accept")==0 ){ | 2321 }else if( strcmp(x,"parse_accept")==0 ){ |
2238 psp->declargslot = &(psp->gp->accept); | 2322 psp->declargslot = &(psp->gp->accept); |
2239 » }else if( strcmp(x,"parse_failure")==0 ){ | 2323 }else if( strcmp(x,"parse_failure")==0 ){ |
2240 psp->declargslot = &(psp->gp->failure); | 2324 psp->declargslot = &(psp->gp->failure); |
2241 » }else if( strcmp(x,"stack_overflow")==0 ){ | 2325 }else if( strcmp(x,"stack_overflow")==0 ){ |
2242 psp->declargslot = &(psp->gp->overflow); | 2326 psp->declargslot = &(psp->gp->overflow); |
2243 }else if( strcmp(x,"extra_argument")==0 ){ | 2327 }else if( strcmp(x,"extra_argument")==0 ){ |
2244 psp->declargslot = &(psp->gp->arg); | 2328 psp->declargslot = &(psp->gp->arg); |
2245 psp->insertLineMacro = 0; | 2329 psp->insertLineMacro = 0; |
2246 }else if( strcmp(x,"token_type")==0 ){ | 2330 }else if( strcmp(x,"token_type")==0 ){ |
2247 psp->declargslot = &(psp->gp->tokentype); | 2331 psp->declargslot = &(psp->gp->tokentype); |
2248 psp->insertLineMacro = 0; | 2332 psp->insertLineMacro = 0; |
2249 }else if( strcmp(x,"default_type")==0 ){ | 2333 }else if( strcmp(x,"default_type")==0 ){ |
2250 psp->declargslot = &(psp->gp->vartype); | 2334 psp->declargslot = &(psp->gp->vartype); |
2251 psp->insertLineMacro = 0; | 2335 psp->insertLineMacro = 0; |
2252 }else if( strcmp(x,"stack_size")==0 ){ | 2336 }else if( strcmp(x,"stack_size")==0 ){ |
2253 psp->declargslot = &(psp->gp->stacksize); | 2337 psp->declargslot = &(psp->gp->stacksize); |
2254 psp->insertLineMacro = 0; | 2338 psp->insertLineMacro = 0; |
2255 }else if( strcmp(x,"start_symbol")==0 ){ | 2339 }else if( strcmp(x,"start_symbol")==0 ){ |
2256 psp->declargslot = &(psp->gp->start); | 2340 psp->declargslot = &(psp->gp->start); |
2257 psp->insertLineMacro = 0; | 2341 psp->insertLineMacro = 0; |
2258 }else if( strcmp(x,"left")==0 ){ | 2342 }else if( strcmp(x,"left")==0 ){ |
2259 psp->preccounter++; | 2343 psp->preccounter++; |
2260 psp->declassoc = LEFT; | 2344 psp->declassoc = LEFT; |
2261 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; | 2345 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; |
2262 }else if( strcmp(x,"right")==0 ){ | 2346 }else if( strcmp(x,"right")==0 ){ |
2263 psp->preccounter++; | 2347 psp->preccounter++; |
2264 psp->declassoc = RIGHT; | 2348 psp->declassoc = RIGHT; |
2265 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; | 2349 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; |
2266 }else if( strcmp(x,"nonassoc")==0 ){ | 2350 }else if( strcmp(x,"nonassoc")==0 ){ |
2267 psp->preccounter++; | 2351 psp->preccounter++; |
2268 psp->declassoc = NONE; | 2352 psp->declassoc = NONE; |
2269 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; | 2353 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; |
2270 » }else if( strcmp(x,"destructor")==0 ){ | 2354 }else if( strcmp(x,"destructor")==0 ){ |
2271 psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL; | 2355 psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL; |
2272 » }else if( strcmp(x,"type")==0 ){ | 2356 }else if( strcmp(x,"type")==0 ){ |
2273 psp->state = WAITING_FOR_DATATYPE_SYMBOL; | 2357 psp->state = WAITING_FOR_DATATYPE_SYMBOL; |
2274 }else if( strcmp(x,"fallback")==0 ){ | 2358 }else if( strcmp(x,"fallback")==0 ){ |
2275 psp->fallback = 0; | 2359 psp->fallback = 0; |
2276 psp->state = WAITING_FOR_FALLBACK_ID; | 2360 psp->state = WAITING_FOR_FALLBACK_ID; |
2277 }else if( strcmp(x,"wildcard")==0 ){ | 2361 }else if( strcmp(x,"wildcard")==0 ){ |
2278 psp->state = WAITING_FOR_WILDCARD_ID; | 2362 psp->state = WAITING_FOR_WILDCARD_ID; |
| 2363 }else if( strcmp(x,"token_class")==0 ){ |
| 2364 psp->state = WAITING_FOR_CLASS_ID; |
2279 }else{ | 2365 }else{ |
2280 ErrorMsg(psp->filename,psp->tokenlineno, | 2366 ErrorMsg(psp->filename,psp->tokenlineno, |
2281 "Unknown declaration keyword: \"%%%s\".",x); | 2367 "Unknown declaration keyword: \"%%%s\".",x); |
2282 psp->errorcnt++; | 2368 psp->errorcnt++; |
2283 psp->state = RESYNC_AFTER_DECL_ERROR; | 2369 psp->state = RESYNC_AFTER_DECL_ERROR; |
2284 » } | 2370 } |
2285 }else{ | 2371 }else{ |
2286 ErrorMsg(psp->filename,psp->tokenlineno, | 2372 ErrorMsg(psp->filename,psp->tokenlineno, |
2287 "Illegal declaration keyword: \"%s\".",x); | 2373 "Illegal declaration keyword: \"%s\".",x); |
2288 psp->errorcnt++; | 2374 psp->errorcnt++; |
2289 psp->state = RESYNC_AFTER_DECL_ERROR; | 2375 psp->state = RESYNC_AFTER_DECL_ERROR; |
2290 } | 2376 } |
2291 break; | 2377 break; |
2292 case WAITING_FOR_DESTRUCTOR_SYMBOL: | 2378 case WAITING_FOR_DESTRUCTOR_SYMBOL: |
2293 if( !isalpha(x[0]) ){ | 2379 if( !isalpha(x[0]) ){ |
2294 ErrorMsg(psp->filename,psp->tokenlineno, | 2380 ErrorMsg(psp->filename,psp->tokenlineno, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2329 case WAITING_FOR_PRECEDENCE_SYMBOL: | 2415 case WAITING_FOR_PRECEDENCE_SYMBOL: |
2330 if( x[0]=='.' ){ | 2416 if( x[0]=='.' ){ |
2331 psp->state = WAITING_FOR_DECL_OR_RULE; | 2417 psp->state = WAITING_FOR_DECL_OR_RULE; |
2332 }else if( isupper(x[0]) ){ | 2418 }else if( isupper(x[0]) ){ |
2333 struct symbol *sp; | 2419 struct symbol *sp; |
2334 sp = Symbol_new(x); | 2420 sp = Symbol_new(x); |
2335 if( sp->prec>=0 ){ | 2421 if( sp->prec>=0 ){ |
2336 ErrorMsg(psp->filename,psp->tokenlineno, | 2422 ErrorMsg(psp->filename,psp->tokenlineno, |
2337 "Symbol \"%s\" has already be given a precedence.",x); | 2423 "Symbol \"%s\" has already be given a precedence.",x); |
2338 psp->errorcnt++; | 2424 psp->errorcnt++; |
2339 » }else{ | 2425 }else{ |
2340 sp->prec = psp->preccounter; | 2426 sp->prec = psp->preccounter; |
2341 sp->assoc = psp->declassoc; | 2427 sp->assoc = psp->declassoc; |
2342 » } | 2428 } |
2343 }else{ | 2429 }else{ |
2344 ErrorMsg(psp->filename,psp->tokenlineno, | 2430 ErrorMsg(psp->filename,psp->tokenlineno, |
2345 "Can't assign a precedence to \"%s\".",x); | 2431 "Can't assign a precedence to \"%s\".",x); |
2346 psp->errorcnt++; | 2432 psp->errorcnt++; |
2347 } | 2433 } |
2348 break; | 2434 break; |
2349 case WAITING_FOR_DECL_ARG: | 2435 case WAITING_FOR_DECL_ARG: |
2350 if( x[0]=='{' || x[0]=='\"' || isalnum(x[0]) ){ | 2436 if( x[0]=='{' || x[0]=='\"' || isalnum(x[0]) ){ |
2351 const char *zOld, *zNew; | 2437 const char *zOld, *zNew; |
2352 char *zBuf, *z; | 2438 char *zBuf, *z; |
2353 int nOld, n, nLine, nNew, nBack; | 2439 int nOld, n, nLine, nNew, nBack; |
2354 int addLineMacro; | 2440 int addLineMacro; |
2355 char zLine[50]; | 2441 char zLine[50]; |
2356 zNew = x; | 2442 zNew = x; |
2357 if( zNew[0]=='"' || zNew[0]=='{' ) zNew++; | 2443 if( zNew[0]=='"' || zNew[0]=='{' ) zNew++; |
2358 nNew = lemonStrlen(zNew); | 2444 nNew = lemonStrlen(zNew); |
2359 if( *psp->declargslot ){ | 2445 if( *psp->declargslot ){ |
2360 zOld = *psp->declargslot; | 2446 zOld = *psp->declargslot; |
2361 }else{ | 2447 }else{ |
2362 zOld = ""; | 2448 zOld = ""; |
2363 } | 2449 } |
2364 nOld = lemonStrlen(zOld); | 2450 nOld = lemonStrlen(zOld); |
2365 n = nOld + nNew + 20; | 2451 n = nOld + nNew + 20; |
2366 addLineMacro = !psp->gp->nolinenosflag && psp->insertLineMacro && | 2452 addLineMacro = !psp->gp->nolinenosflag && psp->insertLineMacro && |
2367 (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0); | 2453 (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0); |
2368 if( addLineMacro ){ | 2454 if( addLineMacro ){ |
2369 for(z=psp->filename, nBack=0; *z; z++){ | 2455 for(z=psp->filename, nBack=0; *z; z++){ |
2370 if( *z=='\\' ) nBack++; | 2456 if( *z=='\\' ) nBack++; |
2371 } | 2457 } |
2372 sprintf(zLine, "#line %d ", psp->tokenlineno); | 2458 lemon_sprintf(zLine, "#line %d ", psp->tokenlineno); |
2373 nLine = lemonStrlen(zLine); | 2459 nLine = lemonStrlen(zLine); |
2374 n += nLine + lemonStrlen(psp->filename) + nBack; | 2460 n += nLine + lemonStrlen(psp->filename) + nBack; |
2375 } | 2461 } |
2376 *psp->declargslot = (char *) realloc(*psp->declargslot, n); | 2462 *psp->declargslot = (char *) realloc(*psp->declargslot, n); |
2377 zBuf = *psp->declargslot + nOld; | 2463 zBuf = *psp->declargslot + nOld; |
2378 if( addLineMacro ){ | 2464 if( addLineMacro ){ |
2379 if( nOld && zBuf[-1]!='\n' ){ | 2465 if( nOld && zBuf[-1]!='\n' ){ |
2380 *(zBuf++) = '\n'; | 2466 *(zBuf++) = '\n'; |
2381 } | 2467 } |
2382 memcpy(zBuf, zLine, nLine); | 2468 memcpy(zBuf, zLine, nLine); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2437 struct symbol *sp = Symbol_new(x); | 2523 struct symbol *sp = Symbol_new(x); |
2438 if( psp->gp->wildcard==0 ){ | 2524 if( psp->gp->wildcard==0 ){ |
2439 psp->gp->wildcard = sp; | 2525 psp->gp->wildcard = sp; |
2440 }else{ | 2526 }else{ |
2441 ErrorMsg(psp->filename, psp->tokenlineno, | 2527 ErrorMsg(psp->filename, psp->tokenlineno, |
2442 "Extra wildcard to token: %s", x); | 2528 "Extra wildcard to token: %s", x); |
2443 psp->errorcnt++; | 2529 psp->errorcnt++; |
2444 } | 2530 } |
2445 } | 2531 } |
2446 break; | 2532 break; |
| 2533 case WAITING_FOR_CLASS_ID: |
| 2534 if( !islower(x[0]) ){ |
| 2535 ErrorMsg(psp->filename, psp->tokenlineno, |
| 2536 "%%token_class must be followed by an identifier: ", x); |
| 2537 psp->errorcnt++; |
| 2538 psp->state = RESYNC_AFTER_DECL_ERROR; |
| 2539 }else if( Symbol_find(x) ){ |
| 2540 ErrorMsg(psp->filename, psp->tokenlineno, |
| 2541 "Symbol \"%s\" already used", x); |
| 2542 psp->errorcnt++; |
| 2543 psp->state = RESYNC_AFTER_DECL_ERROR; |
| 2544 }else{ |
| 2545 psp->tkclass = Symbol_new(x); |
| 2546 psp->tkclass->type = MULTITERMINAL; |
| 2547 psp->state = WAITING_FOR_CLASS_TOKEN; |
| 2548 } |
| 2549 break; |
| 2550 case WAITING_FOR_CLASS_TOKEN: |
| 2551 if( x[0]=='.' ){ |
| 2552 psp->state = WAITING_FOR_DECL_OR_RULE; |
| 2553 }else if( isupper(x[0]) || ((x[0]=='|' || x[0]=='/') && isupper(x[1])) ){ |
| 2554 struct symbol *msp = psp->tkclass; |
| 2555 msp->nsubsym++; |
| 2556 msp->subsym = (struct symbol **) realloc(msp->subsym, |
| 2557 sizeof(struct symbol*)*msp->nsubsym); |
| 2558 if( !isupper(x[0]) ) x++; |
| 2559 msp->subsym[msp->nsubsym-1] = Symbol_new(x); |
| 2560 }else{ |
| 2561 ErrorMsg(psp->filename, psp->tokenlineno, |
| 2562 "%%token_class argument \"%s\" should be a token", x); |
| 2563 psp->errorcnt++; |
| 2564 psp->state = RESYNC_AFTER_DECL_ERROR; |
| 2565 } |
| 2566 break; |
2447 case RESYNC_AFTER_RULE_ERROR: | 2567 case RESYNC_AFTER_RULE_ERROR: |
2448 /* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; | 2568 /* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; |
2449 ** break; */ | 2569 ** break; */ |
2450 case RESYNC_AFTER_DECL_ERROR: | 2570 case RESYNC_AFTER_DECL_ERROR: |
2451 if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; | 2571 if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; |
2452 if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD; | 2572 if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD; |
2453 break; | 2573 break; |
2454 } | 2574 } |
2455 } | 2575 } |
2456 | 2576 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2531 fp = fopen(ps.filename,"rb"); | 2651 fp = fopen(ps.filename,"rb"); |
2532 if( fp==0 ){ | 2652 if( fp==0 ){ |
2533 ErrorMsg(ps.filename,0,"Can't open this file for reading."); | 2653 ErrorMsg(ps.filename,0,"Can't open this file for reading."); |
2534 gp->errorcnt++; | 2654 gp->errorcnt++; |
2535 return; | 2655 return; |
2536 } | 2656 } |
2537 fseek(fp,0,2); | 2657 fseek(fp,0,2); |
2538 filesize = ftell(fp); | 2658 filesize = ftell(fp); |
2539 rewind(fp); | 2659 rewind(fp); |
2540 filebuf = (char *)malloc( filesize+1 ); | 2660 filebuf = (char *)malloc( filesize+1 ); |
2541 if( filebuf==0 ){ | 2661 if( filesize>100000000 || filebuf==0 ){ |
2542 ErrorMsg(ps.filename,0,"Can't allocate %d of memory to hold this file.", | 2662 ErrorMsg(ps.filename,0,"Input file too large."); |
2543 filesize+1); | |
2544 gp->errorcnt++; | 2663 gp->errorcnt++; |
| 2664 fclose(fp); |
2545 return; | 2665 return; |
2546 } | 2666 } |
2547 if( fread(filebuf,1,filesize,fp)!=filesize ){ | 2667 if( fread(filebuf,1,filesize,fp)!=filesize ){ |
2548 ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.", | 2668 ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.", |
2549 filesize); | 2669 filesize); |
2550 free(filebuf); | 2670 free(filebuf); |
2551 gp->errorcnt++; | 2671 gp->errorcnt++; |
| 2672 fclose(fp); |
2552 return; | 2673 return; |
2553 } | 2674 } |
2554 fclose(fp); | 2675 fclose(fp); |
2555 filebuf[filesize] = 0; | 2676 filebuf[filesize] = 0; |
2556 | 2677 |
2557 /* Make an initial pass through the file to handle %ifdef and %ifndef */ | 2678 /* Make an initial pass through the file to handle %ifdef and %ifndef */ |
2558 preprocess_input(filebuf); | 2679 preprocess_input(filebuf); |
2559 | 2680 |
2560 /* Now scan the text of the input file */ | 2681 /* Now scan the text of the input file */ |
2561 lineno = 1; | 2682 lineno = 1; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2600 else if( c=='{' ) level++; | 2721 else if( c=='{' ) level++; |
2601 else if( c=='}' ) level--; | 2722 else if( c=='}' ) level--; |
2602 else if( c=='/' && cp[1]=='*' ){ /* Skip comments */ | 2723 else if( c=='/' && cp[1]=='*' ){ /* Skip comments */ |
2603 int prevc; | 2724 int prevc; |
2604 cp = &cp[2]; | 2725 cp = &cp[2]; |
2605 prevc = 0; | 2726 prevc = 0; |
2606 while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){ | 2727 while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){ |
2607 if( c=='\n' ) lineno++; | 2728 if( c=='\n' ) lineno++; |
2608 prevc = c; | 2729 prevc = c; |
2609 cp++; | 2730 cp++; |
2610 » } | 2731 } |
2611 » }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */ | 2732 }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */ |
2612 cp = &cp[2]; | 2733 cp = &cp[2]; |
2613 while( (c= *cp)!=0 && c!='\n' ) cp++; | 2734 while( (c= *cp)!=0 && c!='\n' ) cp++; |
2614 if( c ) lineno++; | 2735 if( c ) lineno++; |
2615 » }else if( c=='\'' || c=='\"' ){ /* String a character literals */ | 2736 }else if( c=='\'' || c=='\"' ){ /* String a character literals */ |
2616 int startchar, prevc; | 2737 int startchar, prevc; |
2617 startchar = c; | 2738 startchar = c; |
2618 prevc = 0; | 2739 prevc = 0; |
2619 for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){ | 2740 for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){ |
2620 if( c=='\n' ) lineno++; | 2741 if( c=='\n' ) lineno++; |
2621 if( prevc=='\\' ) prevc = 0; | 2742 if( prevc=='\\' ) prevc = 0; |
2622 else prevc = c; | 2743 else prevc = c; |
2623 » } | 2744 } |
2624 » } | 2745 } |
2625 } | 2746 } |
2626 if( c==0 ){ | 2747 if( c==0 ){ |
2627 ErrorMsg(ps.filename,ps.tokenlineno, | 2748 ErrorMsg(ps.filename,ps.tokenlineno, |
2628 "C code starting on this line is not terminated before the end of the file."); | 2749 "C code starting on this line is not terminated before the end of the file."); |
2629 ps.errorcnt++; | 2750 ps.errorcnt++; |
2630 nextcp = cp; | 2751 nextcp = cp; |
2631 }else{ | 2752 }else{ |
2632 nextcp = cp+1; | 2753 nextcp = cp+1; |
2633 } | 2754 } |
2634 }else if( isalnum(c) ){ /* Identifiers */ | 2755 }else if( isalnum(c) ){ /* Identifiers */ |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2729 PRIVATE char *file_makename(struct lemon *lemp, const char *suffix) | 2850 PRIVATE char *file_makename(struct lemon *lemp, const char *suffix) |
2730 { | 2851 { |
2731 char *name; | 2852 char *name; |
2732 char *cp; | 2853 char *cp; |
2733 | 2854 |
2734 name = (char*)malloc( lemonStrlen(lemp->filename) + lemonStrlen(suffix) + 5 ); | 2855 name = (char*)malloc( lemonStrlen(lemp->filename) + lemonStrlen(suffix) + 5 ); |
2735 if( name==0 ){ | 2856 if( name==0 ){ |
2736 fprintf(stderr,"Can't allocate space for a filename.\n"); | 2857 fprintf(stderr,"Can't allocate space for a filename.\n"); |
2737 exit(1); | 2858 exit(1); |
2738 } | 2859 } |
2739 strcpy(name,lemp->filename); | 2860 lemon_strcpy(name,lemp->filename); |
2740 cp = strrchr(name,'.'); | 2861 cp = strrchr(name,'.'); |
2741 if( cp ) *cp = 0; | 2862 if( cp ) *cp = 0; |
2742 strcat(name,suffix); | 2863 lemon_strcat(name,suffix); |
2743 return name; | 2864 return name; |
2744 } | 2865 } |
2745 | 2866 |
2746 /* Open a file with a name based on the name of the input file, | 2867 /* Open a file with a name based on the name of the input file, |
2747 ** but with a different (specified) suffix, and return a pointer | 2868 ** but with a different (specified) suffix, and return a pointer |
2748 ** to the stream */ | 2869 ** to the stream */ |
2749 PRIVATE FILE *file_open( | 2870 PRIVATE FILE *file_open( |
2750 struct lemon *lemp, | 2871 struct lemon *lemp, |
2751 const char *suffix, | 2872 const char *suffix, |
2752 const char *mode | 2873 const char *mode |
2753 ){ | 2874 ){ |
2754 FILE *fp; | 2875 FILE *fp; |
2755 | 2876 |
2756 if( lemp->outname ) free(lemp->outname); | 2877 if( lemp->outname ) free(lemp->outname); |
2757 lemp->outname = file_makename(lemp, suffix); | 2878 lemp->outname = file_makename(lemp, suffix); |
2758 fp = fopen(lemp->outname,mode); | 2879 fp = fopen(lemp->outname,mode); |
2759 if( fp==0 && *mode=='w' ){ | 2880 if( fp==0 && *mode=='w' ){ |
2760 fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname); | 2881 fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname); |
2761 lemp->errorcnt++; | 2882 lemp->errorcnt++; |
2762 return 0; | 2883 return 0; |
2763 } | 2884 } |
2764 | |
2765 /* Add files we create to a list, so we can delete them if we fail. This | |
2766 ** is to keep makefiles from getting confused. We don't include .out files, | |
2767 ** though: this is debug information, and you don't want it deleted if there | |
2768 ** was an error you need to track down. | |
2769 */ | |
2770 if(( *mode=='w' ) && (strcmp(suffix, ".out") != 0)){ | |
2771 const char **ptr = (const char **) | |
2772 realloc(made_files, sizeof (const char **) * (made_files_count + 1)); | |
2773 const char *fname = Strsafe(lemp->outname); | |
2774 if ((ptr == NULL) || (fname == NULL)) { | |
2775 free(ptr); | |
2776 memory_error(); | |
2777 } | |
2778 made_files = ptr; | |
2779 made_files[made_files_count++] = fname; | |
2780 } | |
2781 return fp; | 2885 return fp; |
2782 } | 2886 } |
2783 | 2887 |
2784 /* Duplicate the input file without comments and without actions | 2888 /* Duplicate the input file without comments and without actions |
2785 ** on rules */ | 2889 ** on rules */ |
2786 void Reprint(struct lemon *lemp) | 2890 void Reprint(struct lemon *lemp) |
2787 { | 2891 { |
2788 struct rule *rp; | 2892 struct rule *rp; |
2789 struct symbol *sp; | 2893 struct symbol *sp; |
2790 int i, j, maxlen, len, ncolumns, skip; | 2894 int i, j, maxlen, len, ncolumns, skip; |
(...skipping 15 matching lines...) Expand all Loading... |
2806 printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name); | 2910 printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name); |
2807 } | 2911 } |
2808 printf("\n"); | 2912 printf("\n"); |
2809 } | 2913 } |
2810 for(rp=lemp->rule; rp; rp=rp->next){ | 2914 for(rp=lemp->rule; rp; rp=rp->next){ |
2811 printf("%s",rp->lhs->name); | 2915 printf("%s",rp->lhs->name); |
2812 /* if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */ | 2916 /* if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */ |
2813 printf(" ::="); | 2917 printf(" ::="); |
2814 for(i=0; i<rp->nrhs; i++){ | 2918 for(i=0; i<rp->nrhs; i++){ |
2815 sp = rp->rhs[i]; | 2919 sp = rp->rhs[i]; |
2816 printf(" %s", sp->name); | |
2817 if( sp->type==MULTITERMINAL ){ | 2920 if( sp->type==MULTITERMINAL ){ |
| 2921 printf(" %s", sp->subsym[0]->name); |
2818 for(j=1; j<sp->nsubsym; j++){ | 2922 for(j=1; j<sp->nsubsym; j++){ |
2819 printf("|%s", sp->subsym[j]->name); | 2923 printf("|%s", sp->subsym[j]->name); |
2820 } | 2924 } |
| 2925 }else{ |
| 2926 printf(" %s", sp->name); |
2821 } | 2927 } |
2822 /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */ | 2928 /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */ |
2823 } | 2929 } |
2824 printf("."); | 2930 printf("."); |
2825 if( rp->precsym ) printf(" [%s]",rp->precsym->name); | 2931 if( rp->precsym ) printf(" [%s]",rp->precsym->name); |
2826 /* if( rp->code ) printf("\n %s",rp->code); */ | 2932 /* if( rp->code ) printf("\n %s",rp->code); */ |
2827 printf("\n"); | 2933 printf("\n"); |
2828 } | 2934 } |
2829 } | 2935 } |
2830 | 2936 |
2831 void ConfigPrint(FILE *fp, struct config *cfp) | 2937 void ConfigPrint(FILE *fp, struct config *cfp) |
2832 { | 2938 { |
2833 struct rule *rp; | 2939 struct rule *rp; |
2834 struct symbol *sp; | 2940 struct symbol *sp; |
2835 int i, j; | 2941 int i, j; |
2836 rp = cfp->rp; | 2942 rp = cfp->rp; |
2837 fprintf(fp,"%s ::=",rp->lhs->name); | 2943 fprintf(fp,"%s ::=",rp->lhs->name); |
2838 for(i=0; i<=rp->nrhs; i++){ | 2944 for(i=0; i<=rp->nrhs; i++){ |
2839 if( i==cfp->dot ) fprintf(fp," *"); | 2945 if( i==cfp->dot ) fprintf(fp," *"); |
2840 if( i==rp->nrhs ) break; | 2946 if( i==rp->nrhs ) break; |
2841 sp = rp->rhs[i]; | 2947 sp = rp->rhs[i]; |
2842 fprintf(fp," %s", sp->name); | |
2843 if( sp->type==MULTITERMINAL ){ | 2948 if( sp->type==MULTITERMINAL ){ |
| 2949 fprintf(fp," %s", sp->subsym[0]->name); |
2844 for(j=1; j<sp->nsubsym; j++){ | 2950 for(j=1; j<sp->nsubsym; j++){ |
2845 fprintf(fp,"|%s",sp->subsym[j]->name); | 2951 fprintf(fp,"|%s",sp->subsym[j]->name); |
2846 } | 2952 } |
| 2953 }else{ |
| 2954 fprintf(fp," %s", sp->name); |
2847 } | 2955 } |
2848 } | 2956 } |
2849 } | 2957 } |
2850 | 2958 |
2851 /* #define TEST */ | 2959 /* #define TEST */ |
2852 #if 0 | 2960 #if 0 |
2853 /* Print a set */ | 2961 /* Print a set */ |
2854 PRIVATE void SetPrint(out,set,lemp) | 2962 PRIVATE void SetPrint(out,set,lemp) |
2855 FILE *out; | 2963 FILE *out; |
2856 char *set; | 2964 char *set; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2946 fp = file_open(lemp,".out","wb"); | 3054 fp = file_open(lemp,".out","wb"); |
2947 if( fp==0 ) return; | 3055 if( fp==0 ) return; |
2948 for(i=0; i<lemp->nstate; i++){ | 3056 for(i=0; i<lemp->nstate; i++){ |
2949 stp = lemp->sorted[i]; | 3057 stp = lemp->sorted[i]; |
2950 fprintf(fp,"State %d:\n",stp->statenum); | 3058 fprintf(fp,"State %d:\n",stp->statenum); |
2951 if( lemp->basisflag ) cfp=stp->bp; | 3059 if( lemp->basisflag ) cfp=stp->bp; |
2952 else cfp=stp->cfp; | 3060 else cfp=stp->cfp; |
2953 while( cfp ){ | 3061 while( cfp ){ |
2954 char buf[20]; | 3062 char buf[20]; |
2955 if( cfp->dot==cfp->rp->nrhs ){ | 3063 if( cfp->dot==cfp->rp->nrhs ){ |
2956 sprintf(buf,"(%d)",cfp->rp->index); | 3064 lemon_sprintf(buf,"(%d)",cfp->rp->index); |
2957 fprintf(fp," %5s ",buf); | 3065 fprintf(fp," %5s ",buf); |
2958 }else{ | 3066 }else{ |
2959 fprintf(fp," "); | 3067 fprintf(fp," "); |
2960 } | 3068 } |
2961 ConfigPrint(fp,cfp); | 3069 ConfigPrint(fp,cfp); |
2962 fprintf(fp,"\n"); | 3070 fprintf(fp,"\n"); |
2963 #if 0 | 3071 #if 0 |
2964 SetPrint(fp,cfp->fws,lemp); | 3072 SetPrint(fp,cfp->fws,lemp); |
2965 PlinkPrint(fp,cfp->fplp,"To "); | 3073 PlinkPrint(fp,cfp->fplp,"To "); |
2966 PlinkPrint(fp,cfp->bplp,"From"); | 3074 PlinkPrint(fp,cfp->bplp,"From"); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3011 | 3119 |
3012 #ifdef __WIN32__ | 3120 #ifdef __WIN32__ |
3013 cp = strrchr(argv0,'\\'); | 3121 cp = strrchr(argv0,'\\'); |
3014 #else | 3122 #else |
3015 cp = strrchr(argv0,'/'); | 3123 cp = strrchr(argv0,'/'); |
3016 #endif | 3124 #endif |
3017 if( cp ){ | 3125 if( cp ){ |
3018 c = *cp; | 3126 c = *cp; |
3019 *cp = 0; | 3127 *cp = 0; |
3020 path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 ); | 3128 path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 ); |
3021 if( path ) sprintf(path,"%s/%s",argv0,name); | 3129 if( path ) lemon_sprintf(path,"%s/%s",argv0,name); |
3022 *cp = c; | 3130 *cp = c; |
3023 }else{ | 3131 }else{ |
3024 pathlist = getenv("PATH"); | 3132 pathlist = getenv("PATH"); |
3025 if( pathlist==0 ) pathlist = ".:/bin:/usr/bin"; | 3133 if( pathlist==0 ) pathlist = ".:/bin:/usr/bin"; |
3026 pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 ); | 3134 pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 ); |
3027 path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 ); | 3135 path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 ); |
3028 if( (pathbuf != 0) && (path!=0) ){ | 3136 if( (pathbuf != 0) && (path!=0) ){ |
3029 pathbufptr = pathbuf; | 3137 pathbufptr = pathbuf; |
3030 strcpy(pathbuf, pathlist); | 3138 lemon_strcpy(pathbuf, pathlist); |
3031 while( *pathbuf ){ | 3139 while( *pathbuf ){ |
3032 cp = strchr(pathbuf,':'); | 3140 cp = strchr(pathbuf,':'); |
3033 if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)]; | 3141 if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)]; |
3034 c = *cp; | 3142 c = *cp; |
3035 *cp = 0; | 3143 *cp = 0; |
3036 sprintf(path,"%s/%s",pathbuf,name); | 3144 lemon_sprintf(path,"%s/%s",pathbuf,name); |
3037 *cp = c; | 3145 *cp = c; |
3038 if( c==0 ) pathbuf[0] = 0; | 3146 if( c==0 ) pathbuf[0] = 0; |
3039 else pathbuf = &cp[1]; | 3147 else pathbuf = &cp[1]; |
3040 if( access(path,modemask)==0 ) break; | 3148 if( access(path,modemask)==0 ) break; |
3041 } | 3149 } |
3042 free(pathbufptr); | 3150 free(pathbufptr); |
3043 } | 3151 } |
3044 } | 3152 } |
3045 return path; | 3153 return path; |
3046 } | 3154 } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3117 if( in==0 ){ | 3225 if( in==0 ){ |
3118 fprintf(stderr,"Can't open the template file \"%s\".\n",user_templatename)
; | 3226 fprintf(stderr,"Can't open the template file \"%s\".\n",user_templatename)
; |
3119 lemp->errorcnt++; | 3227 lemp->errorcnt++; |
3120 return 0; | 3228 return 0; |
3121 } | 3229 } |
3122 return in; | 3230 return in; |
3123 } | 3231 } |
3124 | 3232 |
3125 cp = strrchr(lemp->filename,'.'); | 3233 cp = strrchr(lemp->filename,'.'); |
3126 if( cp ){ | 3234 if( cp ){ |
3127 sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename); | 3235 lemon_sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename); |
3128 }else{ | 3236 }else{ |
3129 sprintf(buf,"%s.lt",lemp->filename); | 3237 lemon_sprintf(buf,"%s.lt",lemp->filename); |
3130 } | 3238 } |
3131 if( access(buf,004)==0 ){ | 3239 if( access(buf,004)==0 ){ |
3132 tpltname = buf; | 3240 tpltname = buf; |
3133 }else if( access(templatename,004)==0 ){ | 3241 }else if( access(templatename,004)==0 ){ |
3134 tpltname = templatename; | 3242 tpltname = templatename; |
3135 }else{ | 3243 }else{ |
3136 tpltname = pathsearch(lemp->argv0,templatename,0); | 3244 tpltname = pathsearch(lemp->argv0,templatename,0); |
3137 } | 3245 } |
3138 if( tpltname==0 ){ | 3246 if( tpltname==0 ){ |
3139 fprintf(stderr,"Can't find the parser driver template file \"%s\".\n", | 3247 fprintf(stderr,"Can't find the parser driver template file \"%s\".\n", |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3270 n = lemonStrlen(zText); | 3378 n = lemonStrlen(zText); |
3271 } | 3379 } |
3272 if( (int) (n+sizeof(zInt)*2+used) >= alloced ){ | 3380 if( (int) (n+sizeof(zInt)*2+used) >= alloced ){ |
3273 alloced = n + sizeof(zInt)*2 + used + 200; | 3381 alloced = n + sizeof(zInt)*2 + used + 200; |
3274 z = (char *) realloc(z, alloced); | 3382 z = (char *) realloc(z, alloced); |
3275 } | 3383 } |
3276 if( z==0 ) return empty; | 3384 if( z==0 ) return empty; |
3277 while( n-- > 0 ){ | 3385 while( n-- > 0 ){ |
3278 c = *(zText++); | 3386 c = *(zText++); |
3279 if( c=='%' && n>0 && zText[0]=='d' ){ | 3387 if( c=='%' && n>0 && zText[0]=='d' ){ |
3280 sprintf(zInt, "%d", p1); | 3388 lemon_sprintf(zInt, "%d", p1); |
3281 p1 = p2; | 3389 p1 = p2; |
3282 strcpy(&z[used], zInt); | 3390 lemon_strcpy(&z[used], zInt); |
3283 used += lemonStrlen(&z[used]); | 3391 used += lemonStrlen(&z[used]); |
3284 zText++; | 3392 zText++; |
3285 n--; | 3393 n--; |
3286 }else{ | 3394 }else{ |
3287 z[used++] = c; | 3395 z[used++] = c; |
3288 } | 3396 } |
3289 } | 3397 } |
3290 z[used] = 0; | 3398 z[used] = 0; |
3291 return z; | 3399 return z; |
3292 } | 3400 } |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3421 struct lemon *lemp, /* The main info structure for this parser */ | 3529 struct lemon *lemp, /* The main info structure for this parser */ |
3422 int *plineno, /* Pointer to the line number */ | 3530 int *plineno, /* Pointer to the line number */ |
3423 int mhflag /* True if generating makeheaders output */ | 3531 int mhflag /* True if generating makeheaders output */ |
3424 ){ | 3532 ){ |
3425 int lineno = *plineno; /* The line number of the output */ | 3533 int lineno = *plineno; /* The line number of the output */ |
3426 char **types; /* A hash table of datatypes */ | 3534 char **types; /* A hash table of datatypes */ |
3427 int arraysize; /* Size of the "types" array */ | 3535 int arraysize; /* Size of the "types" array */ |
3428 int maxdtlength; /* Maximum length of any ".datatype" field. */ | 3536 int maxdtlength; /* Maximum length of any ".datatype" field. */ |
3429 char *stddt; /* Standardized name for a datatype */ | 3537 char *stddt; /* Standardized name for a datatype */ |
3430 int i,j; /* Loop counters */ | 3538 int i,j; /* Loop counters */ |
3431 int hash; /* For hashing the name of a type */ | 3539 unsigned hash; /* For hashing the name of a type */ |
3432 const char *name; /* Name of the parser */ | 3540 const char *name; /* Name of the parser */ |
3433 | 3541 |
3434 /* Allocate and initialize types[] and allocate stddt[] */ | 3542 /* Allocate and initialize types[] and allocate stddt[] */ |
3435 arraysize = lemp->nsymbol * 2; | 3543 arraysize = lemp->nsymbol * 2; |
3436 types = (char**)calloc( arraysize, sizeof(char*) ); | 3544 types = (char**)calloc( arraysize, sizeof(char*) ); |
| 3545 if( types==0 ){ |
| 3546 fprintf(stderr,"Out of memory.\n"); |
| 3547 exit(1); |
| 3548 } |
3437 for(i=0; i<arraysize; i++) types[i] = 0; | 3549 for(i=0; i<arraysize; i++) types[i] = 0; |
3438 maxdtlength = 0; | 3550 maxdtlength = 0; |
3439 if( lemp->vartype ){ | 3551 if( lemp->vartype ){ |
3440 maxdtlength = lemonStrlen(lemp->vartype); | 3552 maxdtlength = lemonStrlen(lemp->vartype); |
3441 } | 3553 } |
3442 for(i=0; i<lemp->nsymbol; i++){ | 3554 for(i=0; i<lemp->nsymbol; i++){ |
3443 int len; | 3555 int len; |
3444 struct symbol *sp = lemp->symbols[i]; | 3556 struct symbol *sp = lemp->symbols[i]; |
3445 if( sp->datatype==0 ) continue; | 3557 if( sp->datatype==0 ) continue; |
3446 len = lemonStrlen(sp->datatype); | 3558 len = lemonStrlen(sp->datatype); |
3447 if( len>maxdtlength ) maxdtlength = len; | 3559 if( len>maxdtlength ) maxdtlength = len; |
3448 } | 3560 } |
3449 stddt = (char*)malloc( maxdtlength*2 + 1 ); | 3561 stddt = (char*)malloc( maxdtlength*2 + 1 ); |
3450 if( types==0 || stddt==0 ){ | 3562 if( stddt==0 ){ |
3451 fprintf(stderr,"Out of memory.\n"); | 3563 fprintf(stderr,"Out of memory.\n"); |
3452 exit(1); | 3564 exit(1); |
3453 } | 3565 } |
3454 | 3566 |
3455 /* Build a hash table of datatypes. The ".dtnum" field of each symbol | 3567 /* Build a hash table of datatypes. The ".dtnum" field of each symbol |
3456 ** is filled in with the hash index plus 1. A ".dtnum" value of 0 is | 3568 ** is filled in with the hash index plus 1. A ".dtnum" value of 0 is |
3457 ** used for terminal symbols. If there is no %default_type defined then | 3569 ** used for terminal symbols. If there is no %default_type defined then |
3458 ** 0 is also used as the .dtnum value for nonterminals which do not specify | 3570 ** 0 is also used as the .dtnum value for nonterminals which do not specify |
3459 ** a datatype using the %type directive. | 3571 ** a datatype using the %type directive. |
3460 */ | 3572 */ |
(...skipping 23 matching lines...) Expand all Loading... |
3484 for(j=0; stddt[j]; j++){ | 3596 for(j=0; stddt[j]; j++){ |
3485 hash = hash*53 + stddt[j]; | 3597 hash = hash*53 + stddt[j]; |
3486 } | 3598 } |
3487 hash = (hash & 0x7fffffff)%arraysize; | 3599 hash = (hash & 0x7fffffff)%arraysize; |
3488 while( types[hash] ){ | 3600 while( types[hash] ){ |
3489 if( strcmp(types[hash],stddt)==0 ){ | 3601 if( strcmp(types[hash],stddt)==0 ){ |
3490 sp->dtnum = hash + 1; | 3602 sp->dtnum = hash + 1; |
3491 break; | 3603 break; |
3492 } | 3604 } |
3493 hash++; | 3605 hash++; |
3494 if( hash>=arraysize ) hash = 0; | 3606 if( hash>=(unsigned)arraysize ) hash = 0; |
3495 } | 3607 } |
3496 if( types[hash]==0 ){ | 3608 if( types[hash]==0 ){ |
3497 sp->dtnum = hash + 1; | 3609 sp->dtnum = hash + 1; |
3498 types[hash] = (char*)malloc( lemonStrlen(stddt)+1 ); | 3610 types[hash] = (char*)malloc( lemonStrlen(stddt)+1 ); |
3499 if( types[hash]==0 ){ | 3611 if( types[hash]==0 ){ |
3500 fprintf(stderr,"Out of memory.\n"); | 3612 fprintf(stderr,"Out of memory.\n"); |
3501 exit(1); | 3613 exit(1); |
3502 } | 3614 } |
3503 strcpy(types[hash],stddt); | 3615 lemon_strcpy(types[hash],stddt); |
3504 } | 3616 } |
3505 } | 3617 } |
3506 | 3618 |
3507 /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */ | 3619 /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */ |
3508 name = lemp->name ? lemp->name : "Parse"; | 3620 name = lemp->name ? lemp->name : "Parse"; |
3509 lineno = *plineno; | 3621 lineno = *plineno; |
3510 if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; } | 3622 if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; } |
3511 fprintf(out,"#define %sTOKENTYPE %s\n",name, | 3623 fprintf(out,"#define %sTOKENTYPE %s\n",name, |
3512 lemp->tokentype?lemp->tokentype:"void*"); lineno++; | 3624 lemp->tokentype?lemp->tokentype:"void*"); lineno++; |
3513 if( mhflag ){ fprintf(out,"#endif\n"); lineno++; } | 3625 if( mhflag ){ fprintf(out,"#endif\n"); lineno++; } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3579 } | 3691 } |
3580 | 3692 |
3581 /* | 3693 /* |
3582 ** Write text on "out" that describes the rule "rp". | 3694 ** Write text on "out" that describes the rule "rp". |
3583 */ | 3695 */ |
3584 static void writeRuleText(FILE *out, struct rule *rp){ | 3696 static void writeRuleText(FILE *out, struct rule *rp){ |
3585 int j; | 3697 int j; |
3586 fprintf(out,"%s ::=", rp->lhs->name); | 3698 fprintf(out,"%s ::=", rp->lhs->name); |
3587 for(j=0; j<rp->nrhs; j++){ | 3699 for(j=0; j<rp->nrhs; j++){ |
3588 struct symbol *sp = rp->rhs[j]; | 3700 struct symbol *sp = rp->rhs[j]; |
3589 fprintf(out," %s", sp->name); | 3701 if( sp->type!=MULTITERMINAL ){ |
3590 if( sp->type==MULTITERMINAL ){ | 3702 fprintf(out," %s", sp->name); |
| 3703 }else{ |
3591 int k; | 3704 int k; |
| 3705 fprintf(out," %s", sp->subsym[0]->name); |
3592 for(k=1; k<sp->nsubsym; k++){ | 3706 for(k=1; k<sp->nsubsym; k++){ |
3593 fprintf(out,"|%s",sp->subsym[k]->name); | 3707 fprintf(out,"|%s",sp->subsym[k]->name); |
3594 } | 3708 } |
3595 } | 3709 } |
3596 } | 3710 } |
3597 } | 3711 } |
3598 | 3712 |
3599 | 3713 |
3600 /* Generate C source code for the parser */ | 3714 /* Generate C source code for the parser */ |
3601 void ReportTable( | 3715 void ReportTable( |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3882 p->name, p->fallback->name); | 3996 p->name, p->fallback->name); |
3883 } | 3997 } |
3884 lineno++; | 3998 lineno++; |
3885 } | 3999 } |
3886 } | 4000 } |
3887 tplt_xfer(lemp->name, in, out, &lineno); | 4001 tplt_xfer(lemp->name, in, out, &lineno); |
3888 | 4002 |
3889 /* Generate a table containing the symbolic name of every symbol | 4003 /* Generate a table containing the symbolic name of every symbol |
3890 */ | 4004 */ |
3891 for(i=0; i<lemp->nsymbol; i++){ | 4005 for(i=0; i<lemp->nsymbol; i++){ |
3892 sprintf(line,"\"%s\",",lemp->symbols[i]->name); | 4006 lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name); |
3893 fprintf(out," %-15s",line); | 4007 fprintf(out," %-15s",line); |
3894 if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; } | 4008 if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; } |
3895 } | 4009 } |
3896 if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; } | 4010 if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; } |
3897 tplt_xfer(lemp->name,in,out,&lineno); | 4011 tplt_xfer(lemp->name,in,out,&lineno); |
3898 | 4012 |
3899 /* Generate a table containing a text string that describes every | 4013 /* Generate a table containing a text string that describes every |
3900 ** rule in the rule set of the grammar. This information is used | 4014 ** rule in the rule set of the grammar. This information is used |
3901 ** when tracing REDUCE actions. | 4015 ** when tracing REDUCE actions. |
3902 */ | 4016 */ |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4047 FILE *out, *in; | 4161 FILE *out, *in; |
4048 const char *prefix; | 4162 const char *prefix; |
4049 char line[LINESIZE]; | 4163 char line[LINESIZE]; |
4050 char pattern[LINESIZE]; | 4164 char pattern[LINESIZE]; |
4051 int i; | 4165 int i; |
4052 | 4166 |
4053 if( lemp->tokenprefix ) prefix = lemp->tokenprefix; | 4167 if( lemp->tokenprefix ) prefix = lemp->tokenprefix; |
4054 else prefix = ""; | 4168 else prefix = ""; |
4055 in = file_open(lemp,".h","rb"); | 4169 in = file_open(lemp,".h","rb"); |
4056 if( in ){ | 4170 if( in ){ |
| 4171 int nextChar; |
4057 for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){ | 4172 for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){ |
4058 sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); | 4173 lemon_sprintf(pattern,"#define %s%-30s %3d\n", |
| 4174 prefix,lemp->symbols[i]->name,i); |
4059 if( strcmp(line,pattern) ) break; | 4175 if( strcmp(line,pattern) ) break; |
4060 } | 4176 } |
| 4177 nextChar = fgetc(in); |
4061 fclose(in); | 4178 fclose(in); |
4062 if( i==lemp->nterminal ){ | 4179 if( i==lemp->nterminal && nextChar==EOF ){ |
4063 /* No change in the file. Don't rewrite it. */ | 4180 /* No change in the file. Don't rewrite it. */ |
4064 return; | 4181 return; |
4065 } | 4182 } |
4066 } | 4183 } |
4067 out = file_open(lemp,".h","wb"); | 4184 out = file_open(lemp,".h","wb"); |
4068 if( out ){ | 4185 if( out ){ |
4069 for(i=1; i<lemp->nterminal; i++){ | 4186 for(i=1; i<lemp->nterminal; i++){ |
4070 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); | 4187 fprintf(out,"#define %s%-30s %3d\n",prefix,lemp->symbols[i]->name,i); |
4071 } | 4188 } |
4072 fclose(out); | 4189 fclose(out); |
4073 } | 4190 } |
4074 return; | 4191 return; |
4075 } | 4192 } |
4076 | 4193 |
4077 /* Reduce the size of the action tables, if possible, by making use | 4194 /* Reduce the size of the action tables, if possible, by making use |
4078 ** of defaults. | 4195 ** of defaults. |
4079 ** | 4196 ** |
4080 ** In this version, we take the most frequent REDUCE action and make | 4197 ** In this version, we take the most frequent REDUCE action and make |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4258 ** from a specification in the file | 4375 ** from a specification in the file |
4259 ** "table.q" | 4376 ** "table.q" |
4260 ** by the associative array code building program "aagen". | 4377 ** by the associative array code building program "aagen". |
4261 ** Do not edit this file! Instead, edit the specification | 4378 ** Do not edit this file! Instead, edit the specification |
4262 ** file, then rerun aagen. | 4379 ** file, then rerun aagen. |
4263 */ | 4380 */ |
4264 /* | 4381 /* |
4265 ** Code for processing tables in the LEMON parser generator. | 4382 ** Code for processing tables in the LEMON parser generator. |
4266 */ | 4383 */ |
4267 | 4384 |
4268 PRIVATE int strhash(const char *x) | 4385 PRIVATE unsigned strhash(const char *x) |
4269 { | 4386 { |
4270 int h = 0; | 4387 unsigned h = 0; |
4271 while( *x) h = h*13 + *(x++); | 4388 while( *x ) h = h*13 + *(x++); |
4272 return h; | 4389 return h; |
4273 } | 4390 } |
4274 | 4391 |
4275 /* Works like strdup, sort of. Save a string in malloced memory, but | 4392 /* Works like strdup, sort of. Save a string in malloced memory, but |
4276 ** keep strings in a table so that the same string is not in more | 4393 ** keep strings in a table so that the same string is not in more |
4277 ** than one place. | 4394 ** than one place. |
4278 */ | 4395 */ |
4279 const char *Strsafe(const char *y) | 4396 const char *Strsafe(const char *y) |
4280 { | 4397 { |
4281 const char *z; | 4398 const char *z; |
4282 char *cpy; | 4399 char *cpy; |
4283 | 4400 |
4284 if( y==0 ) return 0; | 4401 if( y==0 ) return 0; |
4285 z = Strsafe_find(y); | 4402 z = Strsafe_find(y); |
4286 if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){ | 4403 if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){ |
4287 strcpy(cpy,y); | 4404 lemon_strcpy(cpy,y); |
4288 z = cpy; | 4405 z = cpy; |
4289 Strsafe_insert(z); | 4406 Strsafe_insert(z); |
4290 } | 4407 } |
4291 MemoryCheck(z); | 4408 MemoryCheck(z); |
4292 return z; | 4409 return z; |
4293 } | 4410 } |
4294 | 4411 |
4295 /* There is one instance of the following structure for each | 4412 /* There is one instance of the following structure for each |
4296 ** associative array of type "x1". | 4413 ** associative array of type "x1". |
4297 */ | 4414 */ |
(...skipping 18 matching lines...) Expand all Loading... |
4316 /* There is only one instance of the array, which is the following */ | 4433 /* There is only one instance of the array, which is the following */ |
4317 static struct s_x1 *x1a; | 4434 static struct s_x1 *x1a; |
4318 | 4435 |
4319 /* Allocate a new associative array */ | 4436 /* Allocate a new associative array */ |
4320 void Strsafe_init(){ | 4437 void Strsafe_init(){ |
4321 if( x1a ) return; | 4438 if( x1a ) return; |
4322 x1a = (struct s_x1*)malloc( sizeof(struct s_x1) ); | 4439 x1a = (struct s_x1*)malloc( sizeof(struct s_x1) ); |
4323 if( x1a ){ | 4440 if( x1a ){ |
4324 x1a->size = 1024; | 4441 x1a->size = 1024; |
4325 x1a->count = 0; | 4442 x1a->count = 0; |
4326 x1a->tbl = (x1node*)malloc( | 4443 x1a->tbl = (x1node*)calloc(1024, sizeof(x1node) + sizeof(x1node*)); |
4327 (sizeof(x1node) + sizeof(x1node*))*1024 ); | |
4328 if( x1a->tbl==0 ){ | 4444 if( x1a->tbl==0 ){ |
4329 free(x1a); | 4445 free(x1a); |
4330 x1a = 0; | 4446 x1a = 0; |
4331 }else{ | 4447 }else{ |
4332 int i; | 4448 int i; |
4333 x1a->ht = (x1node**)&(x1a->tbl[1024]); | 4449 x1a->ht = (x1node**)&(x1a->tbl[1024]); |
4334 for(i=0; i<1024; i++) x1a->ht[i] = 0; | 4450 for(i=0; i<1024; i++) x1a->ht[i] = 0; |
4335 } | 4451 } |
4336 } | 4452 } |
4337 } | 4453 } |
4338 /* Insert a new record into the array. Return TRUE if successful. | 4454 /* Insert a new record into the array. Return TRUE if successful. |
4339 ** Prior data with the same key is NOT overwritten */ | 4455 ** Prior data with the same key is NOT overwritten */ |
4340 int Strsafe_insert(const char *data) | 4456 int Strsafe_insert(const char *data) |
4341 { | 4457 { |
4342 x1node *np; | 4458 x1node *np; |
4343 int h; | 4459 unsigned h; |
4344 int ph; | 4460 unsigned ph; |
4345 | 4461 |
4346 if( x1a==0 ) return 0; | 4462 if( x1a==0 ) return 0; |
4347 ph = strhash(data); | 4463 ph = strhash(data); |
4348 h = ph & (x1a->size-1); | 4464 h = ph & (x1a->size-1); |
4349 np = x1a->ht[h]; | 4465 np = x1a->ht[h]; |
4350 while( np ){ | 4466 while( np ){ |
4351 if( strcmp(np->data,data)==0 ){ | 4467 if( strcmp(np->data,data)==0 ){ |
4352 /* An existing entry with the same key is found. */ | 4468 /* An existing entry with the same key is found. */ |
4353 /* Fail because overwrite is not allows. */ | 4469 /* Fail because overwrite is not allows. */ |
4354 return 0; | 4470 return 0; |
4355 } | 4471 } |
4356 np = np->next; | 4472 np = np->next; |
4357 } | 4473 } |
4358 if( x1a->count>=x1a->size ){ | 4474 if( x1a->count>=x1a->size ){ |
4359 /* Need to make the hash table bigger */ | 4475 /* Need to make the hash table bigger */ |
4360 int i,size; | 4476 int i,size; |
4361 struct s_x1 array; | 4477 struct s_x1 array; |
4362 array.size = size = x1a->size*2; | 4478 array.size = size = x1a->size*2; |
4363 array.count = x1a->count; | 4479 array.count = x1a->count; |
4364 array.tbl = (x1node*)malloc( | 4480 array.tbl = (x1node*)calloc(size, sizeof(x1node) + sizeof(x1node*)); |
4365 (sizeof(x1node) + sizeof(x1node*))*size ); | |
4366 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 4481 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
4367 array.ht = (x1node**)&(array.tbl[size]); | 4482 array.ht = (x1node**)&(array.tbl[size]); |
4368 for(i=0; i<size; i++) array.ht[i] = 0; | 4483 for(i=0; i<size; i++) array.ht[i] = 0; |
4369 for(i=0; i<x1a->count; i++){ | 4484 for(i=0; i<x1a->count; i++){ |
4370 x1node *oldnp, *newnp; | 4485 x1node *oldnp, *newnp; |
4371 oldnp = &(x1a->tbl[i]); | 4486 oldnp = &(x1a->tbl[i]); |
4372 h = strhash(oldnp->data) & (size-1); | 4487 h = strhash(oldnp->data) & (size-1); |
4373 newnp = &(array.tbl[i]); | 4488 newnp = &(array.tbl[i]); |
4374 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); | 4489 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
4375 newnp->next = array.ht[h]; | 4490 newnp->next = array.ht[h]; |
(...skipping 12 matching lines...) Expand all Loading... |
4388 np->next = x1a->ht[h]; | 4503 np->next = x1a->ht[h]; |
4389 x1a->ht[h] = np; | 4504 x1a->ht[h] = np; |
4390 np->from = &(x1a->ht[h]); | 4505 np->from = &(x1a->ht[h]); |
4391 return 1; | 4506 return 1; |
4392 } | 4507 } |
4393 | 4508 |
4394 /* Return a pointer to data assigned to the given key. Return NULL | 4509 /* Return a pointer to data assigned to the given key. Return NULL |
4395 ** if no such key. */ | 4510 ** if no such key. */ |
4396 const char *Strsafe_find(const char *key) | 4511 const char *Strsafe_find(const char *key) |
4397 { | 4512 { |
4398 int h; | 4513 unsigned h; |
4399 x1node *np; | 4514 x1node *np; |
4400 | 4515 |
4401 if( x1a==0 ) return 0; | 4516 if( x1a==0 ) return 0; |
4402 h = strhash(key) & (x1a->size-1); | 4517 h = strhash(key) & (x1a->size-1); |
4403 np = x1a->ht[h]; | 4518 np = x1a->ht[h]; |
4404 while( np ){ | 4519 while( np ){ |
4405 if( strcmp(np->data,key)==0 ) break; | 4520 if( strcmp(np->data,key)==0 ) break; |
4406 np = np->next; | 4521 np = np->next; |
4407 } | 4522 } |
4408 return np ? np->data : 0; | 4523 return np ? np->data : 0; |
(...skipping 21 matching lines...) Expand all Loading... |
4430 sp->destructor = 0; | 4545 sp->destructor = 0; |
4431 sp->destLineno = 0; | 4546 sp->destLineno = 0; |
4432 sp->datatype = 0; | 4547 sp->datatype = 0; |
4433 sp->useCnt = 0; | 4548 sp->useCnt = 0; |
4434 Symbol_insert(sp,sp->name); | 4549 Symbol_insert(sp,sp->name); |
4435 } | 4550 } |
4436 sp->useCnt++; | 4551 sp->useCnt++; |
4437 return sp; | 4552 return sp; |
4438 } | 4553 } |
4439 | 4554 |
4440 /* Compare two symbols for working purposes | 4555 /* Compare two symbols for sorting purposes. Return negative, |
| 4556 ** zero, or positive if a is less then, equal to, or greater |
| 4557 ** than b. |
4441 ** | 4558 ** |
4442 ** Symbols that begin with upper case letters (terminals or tokens) | 4559 ** Symbols that begin with upper case letters (terminals or tokens) |
4443 ** must sort before symbols that begin with lower case letters | 4560 ** must sort before symbols that begin with lower case letters |
4444 ** (non-terminals). Other than that, the order does not matter. | 4561 ** (non-terminals). And MULTITERMINAL symbols (created using the |
| 4562 ** %token_class directive) must sort at the very end. Other than |
| 4563 ** that, the order does not matter. |
4445 ** | 4564 ** |
4446 ** We find experimentally that leaving the symbols in their original | 4565 ** We find experimentally that leaving the symbols in their original |
4447 ** order (the order they appeared in the grammar file) gives the | 4566 ** order (the order they appeared in the grammar file) gives the |
4448 ** smallest parser tables in SQLite. | 4567 ** smallest parser tables in SQLite. |
4449 */ | 4568 */ |
4450 int Symbolcmpp(const void *_a, const void *_b) | 4569 int Symbolcmpp(const void *_a, const void *_b) |
4451 { | 4570 { |
4452 const struct symbol **a = (const struct symbol **) _a; | 4571 const struct symbol *a = *(const struct symbol **) _a; |
4453 const struct symbol **b = (const struct symbol **) _b; | 4572 const struct symbol *b = *(const struct symbol **) _b; |
4454 int i1 = (**a).index + 10000000*((**a).name[0]>'Z'); | 4573 int i1 = a->type==MULTITERMINAL ? 3 : a->name[0]>'Z' ? 2 : 1; |
4455 int i2 = (**b).index + 10000000*((**b).name[0]>'Z'); | 4574 int i2 = b->type==MULTITERMINAL ? 3 : b->name[0]>'Z' ? 2 : 1; |
4456 assert( i1!=i2 || strcmp((**a).name,(**b).name)==0 ); | 4575 return i1==i2 ? a->index - b->index : i1 - i2; |
4457 return i1-i2; | |
4458 } | 4576 } |
4459 | 4577 |
4460 /* There is one instance of the following structure for each | 4578 /* There is one instance of the following structure for each |
4461 ** associative array of type "x2". | 4579 ** associative array of type "x2". |
4462 */ | 4580 */ |
4463 struct s_x2 { | 4581 struct s_x2 { |
4464 int size; /* The number of available slots. */ | 4582 int size; /* The number of available slots. */ |
4465 /* Must be a power of 2 greater than or */ | 4583 /* Must be a power of 2 greater than or */ |
4466 /* equal to 1 */ | 4584 /* equal to 1 */ |
4467 int count; /* Number of currently slots filled */ | 4585 int count; /* Number of currently slots filled */ |
(...skipping 14 matching lines...) Expand all Loading... |
4482 /* There is only one instance of the array, which is the following */ | 4600 /* There is only one instance of the array, which is the following */ |
4483 static struct s_x2 *x2a; | 4601 static struct s_x2 *x2a; |
4484 | 4602 |
4485 /* Allocate a new associative array */ | 4603 /* Allocate a new associative array */ |
4486 void Symbol_init(){ | 4604 void Symbol_init(){ |
4487 if( x2a ) return; | 4605 if( x2a ) return; |
4488 x2a = (struct s_x2*)malloc( sizeof(struct s_x2) ); | 4606 x2a = (struct s_x2*)malloc( sizeof(struct s_x2) ); |
4489 if( x2a ){ | 4607 if( x2a ){ |
4490 x2a->size = 128; | 4608 x2a->size = 128; |
4491 x2a->count = 0; | 4609 x2a->count = 0; |
4492 x2a->tbl = (x2node*)malloc( | 4610 x2a->tbl = (x2node*)calloc(128, sizeof(x2node) + sizeof(x2node*)); |
4493 (sizeof(x2node) + sizeof(x2node*))*128 ); | |
4494 if( x2a->tbl==0 ){ | 4611 if( x2a->tbl==0 ){ |
4495 free(x2a); | 4612 free(x2a); |
4496 x2a = 0; | 4613 x2a = 0; |
4497 }else{ | 4614 }else{ |
4498 int i; | 4615 int i; |
4499 x2a->ht = (x2node**)&(x2a->tbl[128]); | 4616 x2a->ht = (x2node**)&(x2a->tbl[128]); |
4500 for(i=0; i<128; i++) x2a->ht[i] = 0; | 4617 for(i=0; i<128; i++) x2a->ht[i] = 0; |
4501 } | 4618 } |
4502 } | 4619 } |
4503 } | 4620 } |
4504 /* Insert a new record into the array. Return TRUE if successful. | 4621 /* Insert a new record into the array. Return TRUE if successful. |
4505 ** Prior data with the same key is NOT overwritten */ | 4622 ** Prior data with the same key is NOT overwritten */ |
4506 int Symbol_insert(struct symbol *data, const char *key) | 4623 int Symbol_insert(struct symbol *data, const char *key) |
4507 { | 4624 { |
4508 x2node *np; | 4625 x2node *np; |
4509 int h; | 4626 unsigned h; |
4510 int ph; | 4627 unsigned ph; |
4511 | 4628 |
4512 if( x2a==0 ) return 0; | 4629 if( x2a==0 ) return 0; |
4513 ph = strhash(key); | 4630 ph = strhash(key); |
4514 h = ph & (x2a->size-1); | 4631 h = ph & (x2a->size-1); |
4515 np = x2a->ht[h]; | 4632 np = x2a->ht[h]; |
4516 while( np ){ | 4633 while( np ){ |
4517 if( strcmp(np->key,key)==0 ){ | 4634 if( strcmp(np->key,key)==0 ){ |
4518 /* An existing entry with the same key is found. */ | 4635 /* An existing entry with the same key is found. */ |
4519 /* Fail because overwrite is not allows. */ | 4636 /* Fail because overwrite is not allows. */ |
4520 return 0; | 4637 return 0; |
4521 } | 4638 } |
4522 np = np->next; | 4639 np = np->next; |
4523 } | 4640 } |
4524 if( x2a->count>=x2a->size ){ | 4641 if( x2a->count>=x2a->size ){ |
4525 /* Need to make the hash table bigger */ | 4642 /* Need to make the hash table bigger */ |
4526 int i,size; | 4643 int i,size; |
4527 struct s_x2 array; | 4644 struct s_x2 array; |
4528 array.size = size = x2a->size*2; | 4645 array.size = size = x2a->size*2; |
4529 array.count = x2a->count; | 4646 array.count = x2a->count; |
4530 array.tbl = (x2node*)malloc( | 4647 array.tbl = (x2node*)calloc(size, sizeof(x2node) + sizeof(x2node*)); |
4531 (sizeof(x2node) + sizeof(x2node*))*size ); | |
4532 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 4648 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
4533 array.ht = (x2node**)&(array.tbl[size]); | 4649 array.ht = (x2node**)&(array.tbl[size]); |
4534 for(i=0; i<size; i++) array.ht[i] = 0; | 4650 for(i=0; i<size; i++) array.ht[i] = 0; |
4535 for(i=0; i<x2a->count; i++){ | 4651 for(i=0; i<x2a->count; i++){ |
4536 x2node *oldnp, *newnp; | 4652 x2node *oldnp, *newnp; |
4537 oldnp = &(x2a->tbl[i]); | 4653 oldnp = &(x2a->tbl[i]); |
4538 h = strhash(oldnp->key) & (size-1); | 4654 h = strhash(oldnp->key) & (size-1); |
4539 newnp = &(array.tbl[i]); | 4655 newnp = &(array.tbl[i]); |
4540 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); | 4656 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
4541 newnp->next = array.ht[h]; | 4657 newnp->next = array.ht[h]; |
(...skipping 14 matching lines...) Expand all Loading... |
4556 np->next = x2a->ht[h]; | 4672 np->next = x2a->ht[h]; |
4557 x2a->ht[h] = np; | 4673 x2a->ht[h] = np; |
4558 np->from = &(x2a->ht[h]); | 4674 np->from = &(x2a->ht[h]); |
4559 return 1; | 4675 return 1; |
4560 } | 4676 } |
4561 | 4677 |
4562 /* Return a pointer to data assigned to the given key. Return NULL | 4678 /* Return a pointer to data assigned to the given key. Return NULL |
4563 ** if no such key. */ | 4679 ** if no such key. */ |
4564 struct symbol *Symbol_find(const char *key) | 4680 struct symbol *Symbol_find(const char *key) |
4565 { | 4681 { |
4566 int h; | 4682 unsigned h; |
4567 x2node *np; | 4683 x2node *np; |
4568 | 4684 |
4569 if( x2a==0 ) return 0; | 4685 if( x2a==0 ) return 0; |
4570 h = strhash(key) & (x2a->size-1); | 4686 h = strhash(key) & (x2a->size-1); |
4571 np = x2a->ht[h]; | 4687 np = x2a->ht[h]; |
4572 while( np ){ | 4688 while( np ){ |
4573 if( strcmp(np->key,key)==0 ) break; | 4689 if( strcmp(np->key,key)==0 ) break; |
4574 np = np->next; | 4690 np = np->next; |
4575 } | 4691 } |
4576 return np ? np->data : 0; | 4692 return np ? np->data : 0; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4630 if( rc==0 ) rc = a->dot - b->dot; | 4746 if( rc==0 ) rc = a->dot - b->dot; |
4631 } | 4747 } |
4632 if( rc==0 ){ | 4748 if( rc==0 ){ |
4633 if( a ) rc = 1; | 4749 if( a ) rc = 1; |
4634 if( b ) rc = -1; | 4750 if( b ) rc = -1; |
4635 } | 4751 } |
4636 return rc; | 4752 return rc; |
4637 } | 4753 } |
4638 | 4754 |
4639 /* Hash a state */ | 4755 /* Hash a state */ |
4640 PRIVATE int statehash(struct config *a) | 4756 PRIVATE unsigned statehash(struct config *a) |
4641 { | 4757 { |
4642 int h=0; | 4758 unsigned h=0; |
4643 while( a ){ | 4759 while( a ){ |
4644 h = h*571 + a->rp->index*37 + a->dot; | 4760 h = h*571 + a->rp->index*37 + a->dot; |
4645 a = a->bp; | 4761 a = a->bp; |
4646 } | 4762 } |
4647 return h; | 4763 return h; |
4648 } | 4764 } |
4649 | 4765 |
4650 /* Allocate a new state structure */ | 4766 /* Allocate a new state structure */ |
4651 struct state *State_new() | 4767 struct state *State_new() |
4652 { | 4768 { |
(...skipping 28 matching lines...) Expand all Loading... |
4681 /* There is only one instance of the array, which is the following */ | 4797 /* There is only one instance of the array, which is the following */ |
4682 static struct s_x3 *x3a; | 4798 static struct s_x3 *x3a; |
4683 | 4799 |
4684 /* Allocate a new associative array */ | 4800 /* Allocate a new associative array */ |
4685 void State_init(){ | 4801 void State_init(){ |
4686 if( x3a ) return; | 4802 if( x3a ) return; |
4687 x3a = (struct s_x3*)malloc( sizeof(struct s_x3) ); | 4803 x3a = (struct s_x3*)malloc( sizeof(struct s_x3) ); |
4688 if( x3a ){ | 4804 if( x3a ){ |
4689 x3a->size = 128; | 4805 x3a->size = 128; |
4690 x3a->count = 0; | 4806 x3a->count = 0; |
4691 x3a->tbl = (x3node*)malloc( | 4807 x3a->tbl = (x3node*)calloc(128, sizeof(x3node) + sizeof(x3node*)); |
4692 (sizeof(x3node) + sizeof(x3node*))*128 ); | |
4693 if( x3a->tbl==0 ){ | 4808 if( x3a->tbl==0 ){ |
4694 free(x3a); | 4809 free(x3a); |
4695 x3a = 0; | 4810 x3a = 0; |
4696 }else{ | 4811 }else{ |
4697 int i; | 4812 int i; |
4698 x3a->ht = (x3node**)&(x3a->tbl[128]); | 4813 x3a->ht = (x3node**)&(x3a->tbl[128]); |
4699 for(i=0; i<128; i++) x3a->ht[i] = 0; | 4814 for(i=0; i<128; i++) x3a->ht[i] = 0; |
4700 } | 4815 } |
4701 } | 4816 } |
4702 } | 4817 } |
4703 /* Insert a new record into the array. Return TRUE if successful. | 4818 /* Insert a new record into the array. Return TRUE if successful. |
4704 ** Prior data with the same key is NOT overwritten */ | 4819 ** Prior data with the same key is NOT overwritten */ |
4705 int State_insert(struct state *data, struct config *key) | 4820 int State_insert(struct state *data, struct config *key) |
4706 { | 4821 { |
4707 x3node *np; | 4822 x3node *np; |
4708 int h; | 4823 unsigned h; |
4709 int ph; | 4824 unsigned ph; |
4710 | 4825 |
4711 if( x3a==0 ) return 0; | 4826 if( x3a==0 ) return 0; |
4712 ph = statehash(key); | 4827 ph = statehash(key); |
4713 h = ph & (x3a->size-1); | 4828 h = ph & (x3a->size-1); |
4714 np = x3a->ht[h]; | 4829 np = x3a->ht[h]; |
4715 while( np ){ | 4830 while( np ){ |
4716 if( statecmp(np->key,key)==0 ){ | 4831 if( statecmp(np->key,key)==0 ){ |
4717 /* An existing entry with the same key is found. */ | 4832 /* An existing entry with the same key is found. */ |
4718 /* Fail because overwrite is not allows. */ | 4833 /* Fail because overwrite is not allows. */ |
4719 return 0; | 4834 return 0; |
4720 } | 4835 } |
4721 np = np->next; | 4836 np = np->next; |
4722 } | 4837 } |
4723 if( x3a->count>=x3a->size ){ | 4838 if( x3a->count>=x3a->size ){ |
4724 /* Need to make the hash table bigger */ | 4839 /* Need to make the hash table bigger */ |
4725 int i,size; | 4840 int i,size; |
4726 struct s_x3 array; | 4841 struct s_x3 array; |
4727 array.size = size = x3a->size*2; | 4842 array.size = size = x3a->size*2; |
4728 array.count = x3a->count; | 4843 array.count = x3a->count; |
4729 array.tbl = (x3node*)malloc( | 4844 array.tbl = (x3node*)calloc(size, sizeof(x3node) + sizeof(x3node*)); |
4730 (sizeof(x3node) + sizeof(x3node*))*size ); | |
4731 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 4845 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
4732 array.ht = (x3node**)&(array.tbl[size]); | 4846 array.ht = (x3node**)&(array.tbl[size]); |
4733 for(i=0; i<size; i++) array.ht[i] = 0; | 4847 for(i=0; i<size; i++) array.ht[i] = 0; |
4734 for(i=0; i<x3a->count; i++){ | 4848 for(i=0; i<x3a->count; i++){ |
4735 x3node *oldnp, *newnp; | 4849 x3node *oldnp, *newnp; |
4736 oldnp = &(x3a->tbl[i]); | 4850 oldnp = &(x3a->tbl[i]); |
4737 h = statehash(oldnp->key) & (size-1); | 4851 h = statehash(oldnp->key) & (size-1); |
4738 newnp = &(array.tbl[i]); | 4852 newnp = &(array.tbl[i]); |
4739 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); | 4853 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
4740 newnp->next = array.ht[h]; | 4854 newnp->next = array.ht[h]; |
(...skipping 14 matching lines...) Expand all Loading... |
4755 np->next = x3a->ht[h]; | 4869 np->next = x3a->ht[h]; |
4756 x3a->ht[h] = np; | 4870 x3a->ht[h] = np; |
4757 np->from = &(x3a->ht[h]); | 4871 np->from = &(x3a->ht[h]); |
4758 return 1; | 4872 return 1; |
4759 } | 4873 } |
4760 | 4874 |
4761 /* Return a pointer to data assigned to the given key. Return NULL | 4875 /* Return a pointer to data assigned to the given key. Return NULL |
4762 ** if no such key. */ | 4876 ** if no such key. */ |
4763 struct state *State_find(struct config *key) | 4877 struct state *State_find(struct config *key) |
4764 { | 4878 { |
4765 int h; | 4879 unsigned h; |
4766 x3node *np; | 4880 x3node *np; |
4767 | 4881 |
4768 if( x3a==0 ) return 0; | 4882 if( x3a==0 ) return 0; |
4769 h = statehash(key) & (x3a->size-1); | 4883 h = statehash(key) & (x3a->size-1); |
4770 np = x3a->ht[h]; | 4884 np = x3a->ht[h]; |
4771 while( np ){ | 4885 while( np ){ |
4772 if( statecmp(np->key,key)==0 ) break; | 4886 if( statecmp(np->key,key)==0 ) break; |
4773 np = np->next; | 4887 np = np->next; |
4774 } | 4888 } |
4775 return np ? np->data : 0; | 4889 return np ? np->data : 0; |
4776 } | 4890 } |
4777 | 4891 |
4778 /* Return an array of pointers to all data in the table. | 4892 /* Return an array of pointers to all data in the table. |
4779 ** The array is obtained from malloc. Return NULL if memory allocation | 4893 ** The array is obtained from malloc. Return NULL if memory allocation |
4780 ** problems, or if the array is empty. */ | 4894 ** problems, or if the array is empty. */ |
4781 struct state **State_arrayof() | 4895 struct state **State_arrayof() |
4782 { | 4896 { |
4783 struct state **array; | 4897 struct state **array; |
4784 int i,size; | 4898 int i,size; |
4785 if( x3a==0 ) return 0; | 4899 if( x3a==0 ) return 0; |
4786 size = x3a->count; | 4900 size = x3a->count; |
4787 array = (struct state **)malloc( sizeof(struct state *)*size ); | 4901 array = (struct state **)calloc(size, sizeof(struct state *)); |
4788 if( array ){ | 4902 if( array ){ |
4789 for(i=0; i<size; i++) array[i] = x3a->tbl[i].data; | 4903 for(i=0; i<size; i++) array[i] = x3a->tbl[i].data; |
4790 } | 4904 } |
4791 return array; | 4905 return array; |
4792 } | 4906 } |
4793 | 4907 |
4794 /* Hash a configuration */ | 4908 /* Hash a configuration */ |
4795 PRIVATE int confighash(struct config *a) | 4909 PRIVATE unsigned confighash(struct config *a) |
4796 { | 4910 { |
4797 int h=0; | 4911 unsigned h=0; |
4798 h = h*571 + a->rp->index*37 + a->dot; | 4912 h = h*571 + a->rp->index*37 + a->dot; |
4799 return h; | 4913 return h; |
4800 } | 4914 } |
4801 | 4915 |
4802 /* There is one instance of the following structure for each | 4916 /* There is one instance of the following structure for each |
4803 ** associative array of type "x4". | 4917 ** associative array of type "x4". |
4804 */ | 4918 */ |
4805 struct s_x4 { | 4919 struct s_x4 { |
4806 int size; /* The number of available slots. */ | 4920 int size; /* The number of available slots. */ |
4807 /* Must be a power of 2 greater than or */ | 4921 /* Must be a power of 2 greater than or */ |
(...skipping 15 matching lines...) Expand all Loading... |
4823 /* There is only one instance of the array, which is the following */ | 4937 /* There is only one instance of the array, which is the following */ |
4824 static struct s_x4 *x4a; | 4938 static struct s_x4 *x4a; |
4825 | 4939 |
4826 /* Allocate a new associative array */ | 4940 /* Allocate a new associative array */ |
4827 void Configtable_init(){ | 4941 void Configtable_init(){ |
4828 if( x4a ) return; | 4942 if( x4a ) return; |
4829 x4a = (struct s_x4*)malloc( sizeof(struct s_x4) ); | 4943 x4a = (struct s_x4*)malloc( sizeof(struct s_x4) ); |
4830 if( x4a ){ | 4944 if( x4a ){ |
4831 x4a->size = 64; | 4945 x4a->size = 64; |
4832 x4a->count = 0; | 4946 x4a->count = 0; |
4833 x4a->tbl = (x4node*)malloc( | 4947 x4a->tbl = (x4node*)calloc(64, sizeof(x4node) + sizeof(x4node*)); |
4834 (sizeof(x4node) + sizeof(x4node*))*64 ); | |
4835 if( x4a->tbl==0 ){ | 4948 if( x4a->tbl==0 ){ |
4836 free(x4a); | 4949 free(x4a); |
4837 x4a = 0; | 4950 x4a = 0; |
4838 }else{ | 4951 }else{ |
4839 int i; | 4952 int i; |
4840 x4a->ht = (x4node**)&(x4a->tbl[64]); | 4953 x4a->ht = (x4node**)&(x4a->tbl[64]); |
4841 for(i=0; i<64; i++) x4a->ht[i] = 0; | 4954 for(i=0; i<64; i++) x4a->ht[i] = 0; |
4842 } | 4955 } |
4843 } | 4956 } |
4844 } | 4957 } |
4845 /* Insert a new record into the array. Return TRUE if successful. | 4958 /* Insert a new record into the array. Return TRUE if successful. |
4846 ** Prior data with the same key is NOT overwritten */ | 4959 ** Prior data with the same key is NOT overwritten */ |
4847 int Configtable_insert(struct config *data) | 4960 int Configtable_insert(struct config *data) |
4848 { | 4961 { |
4849 x4node *np; | 4962 x4node *np; |
4850 int h; | 4963 unsigned h; |
4851 int ph; | 4964 unsigned ph; |
4852 | 4965 |
4853 if( x4a==0 ) return 0; | 4966 if( x4a==0 ) return 0; |
4854 ph = confighash(data); | 4967 ph = confighash(data); |
4855 h = ph & (x4a->size-1); | 4968 h = ph & (x4a->size-1); |
4856 np = x4a->ht[h]; | 4969 np = x4a->ht[h]; |
4857 while( np ){ | 4970 while( np ){ |
4858 if( Configcmp((const char *) np->data,(const char *) data)==0 ){ | 4971 if( Configcmp((const char *) np->data,(const char *) data)==0 ){ |
4859 /* An existing entry with the same key is found. */ | 4972 /* An existing entry with the same key is found. */ |
4860 /* Fail because overwrite is not allows. */ | 4973 /* Fail because overwrite is not allows. */ |
4861 return 0; | 4974 return 0; |
4862 } | 4975 } |
4863 np = np->next; | 4976 np = np->next; |
4864 } | 4977 } |
4865 if( x4a->count>=x4a->size ){ | 4978 if( x4a->count>=x4a->size ){ |
4866 /* Need to make the hash table bigger */ | 4979 /* Need to make the hash table bigger */ |
4867 int i,size; | 4980 int i,size; |
4868 struct s_x4 array; | 4981 struct s_x4 array; |
4869 array.size = size = x4a->size*2; | 4982 array.size = size = x4a->size*2; |
4870 array.count = x4a->count; | 4983 array.count = x4a->count; |
4871 array.tbl = (x4node*)malloc( | 4984 array.tbl = (x4node*)calloc(size, sizeof(x4node) + sizeof(x4node*)); |
4872 (sizeof(x4node) + sizeof(x4node*))*size ); | |
4873 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 4985 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
4874 array.ht = (x4node**)&(array.tbl[size]); | 4986 array.ht = (x4node**)&(array.tbl[size]); |
4875 for(i=0; i<size; i++) array.ht[i] = 0; | 4987 for(i=0; i<size; i++) array.ht[i] = 0; |
4876 for(i=0; i<x4a->count; i++){ | 4988 for(i=0; i<x4a->count; i++){ |
4877 x4node *oldnp, *newnp; | 4989 x4node *oldnp, *newnp; |
4878 oldnp = &(x4a->tbl[i]); | 4990 oldnp = &(x4a->tbl[i]); |
4879 h = confighash(oldnp->data) & (size-1); | 4991 h = confighash(oldnp->data) & (size-1); |
4880 newnp = &(array.tbl[i]); | 4992 newnp = &(array.tbl[i]); |
4881 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); | 4993 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
4882 newnp->next = array.ht[h]; | 4994 newnp->next = array.ht[h]; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4919 ** as it is removed. ("f" may be null to avoid this step.) */ | 5031 ** as it is removed. ("f" may be null to avoid this step.) */ |
4920 void Configtable_clear(int(*f)(struct config *)) | 5032 void Configtable_clear(int(*f)(struct config *)) |
4921 { | 5033 { |
4922 int i; | 5034 int i; |
4923 if( x4a==0 || x4a->count==0 ) return; | 5035 if( x4a==0 || x4a->count==0 ) return; |
4924 if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data); | 5036 if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data); |
4925 for(i=0; i<x4a->size; i++) x4a->ht[i] = 0; | 5037 for(i=0; i<x4a->size; i++) x4a->ht[i] = 0; |
4926 x4a->count = 0; | 5038 x4a->count = 0; |
4927 return; | 5039 return; |
4928 } | 5040 } |
OLD | NEW |