1 /* Copyright (c) 1979 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)yycosts.c 1.4 08/30/82"; 4 5 #include "whoami.h" 6 #include "0.h" 7 #include "yy.h" 8 9 /* 10 * Symbol costs for Pascal. 11 * 12 * Cost strategy of August 14, 1977. 13 * 14 * The costs determined by the routines in this file are used by 15 * the recovery in choosing appropriate corrections. 16 * The cost vectors and the error productions in the grammar 17 * work together to define the corrective capacity of the grammar. 18 * 19 * The costs here largely derive from those given in Steve Rhode's 20 * thesis for the Pascal-I error correcting parser which he implemented. 21 * Some minor changes have been made to adjust for the fact that 22 * the current error recovery is not as "smart", both because of the 23 * limited forward move and because of the lack of any type information 24 * about identifiers. 25 * 26 * These adjustments largely take the form of increased costs for certain 27 * tokens, noticeably keywords which are major brackets such as "begin" 28 * "label", "procedure", etc. 29 * 30 * The overall weighting strategy is still similar to Rhodes' strategy. 31 * The costs can be considered: 32 * 33 * LOW <= 3 34 * MEDIUM 4 or 5 35 * HIGH >= 6 36 */ 37 38 /* 39 * Insertion costs 40 * 41 * In addition to the normal symbol insertion costs, 42 * there are zero cost insertions here. 43 * The current error recovery system treats symbols 44 * which have zero insertion cost in a special way, 45 * inserting them but suppressing diagnostics. 46 * This allows the system to hold of on bracketing 47 * error diagnostics about missing end's until the 48 * reduction occurs which knows the line number of the 49 * corresponding "begin", "repeat", etc. 50 * A more intelligent and useful diagnostic can then 51 * be printed. 52 * 53 * Although this routine never allows the insertion 54 * of the keyword begin, it can be inserted after a 55 * procedure or function body starts, if it was omitted 56 * by a special case in the panic routine, which notices 57 * the keywords in the statement body of the procedure 58 * and inserts the begin to recover. 59 * 60 * Similarly, we do not insert end-of-file, but 61 * the fact that end-of-file is the unique input 62 * is noticed by the recovery routines as a special 63 * case and handled there. 64 */ 65 inscost(sy, before) 66 register int sy, before; 67 { 68 69 switch (before) { 70 case YEND: 71 if (sy == YEND) 72 break; 73 case YPROCEDURE: 74 case YFUNCTION: 75 if (sy == YUNTIL || sy == YEND) 76 return (0); 77 } 78 switch (sy) { 79 case ';': 80 return (1); 81 case ',': 82 case ':': 83 case YOF: 84 case YDO: 85 return (2); 86 case YARRAY: 87 case '+': 88 case '*': 89 return (3); 90 default: 91 return (4); 92 case '^': 93 case YNOT: 94 case YLABEL: 95 case YCONST: 96 case YTYPE: 97 case YVAR: 98 case YUNTIL: 99 case '(': 100 case '[': 101 case YWHILE: 102 case YWITH: 103 return (5); 104 case YPROCEDURE: 105 case YFUNCTION: 106 case YCASE: 107 return (6); 108 case YEND: 109 return (8); 110 case YBEGIN: 111 case YEOF: 112 case YREPEAT: 113 case YRECORD: 114 return (INFINITY); 115 } 116 } 117 118 /* 119 * Replacement costs 120 * 121 * Most replacement costs are the same as an insertion 122 * plus a deletion cost. One special case is the replacement 123 * of a large number of keywords by an identifier. 124 * These are given lower costs, especially the keyword "to". 125 */ 126 repcost(what, with) 127 register int what, with; 128 { 129 register int c; 130 131 if (with == what) 132 return (INFINITY); 133 if (with == YID && what > ERROR) 134 switch (what) { 135 case YID: 136 case YDOTDOT: 137 case YINT: 138 case YBINT: 139 case YSTRING: 140 case YNUMB: 141 break; 142 case YTO: 143 return (3); 144 default: 145 return (5); 146 case YRECORD: 147 case YTHEN: 148 return (6); 149 case YBEGIN: 150 break; 151 } 152 if (what == YID && with == YFORWARD) 153 return(5); 154 if (what == ';' && (with == ',' || with == '.')) 155 return (CLIMIT - 1); 156 c = delcost(what) + inscost(with); 157 /* 158 * It costs extra to replace something which has 159 * semantics by something which doesn't. 160 */ 161 if (nullsem(what) == NIL && nullsem(with) != NIL) 162 c += 4; 163 return (c); 164 } 165 166 /* 167 * Deletion costs 168 */ 169 delcost(what) 170 int what; 171 { 172 173 switch (what) { 174 case '.': 175 case ':': 176 case ',': 177 case '=': 178 case '(': 179 return (3); 180 case YELSE: 181 case YTHEN: 182 return (4); 183 default: 184 return (5); 185 case YLABEL: 186 case YCONST: 187 case YTYPE: 188 case YVAR: 189 return (10); 190 case YPROCEDURE: 191 case YFUNCTION: 192 case YBEGIN: 193 case YEND: 194 return ((CLIMIT * 3) / 4); 195 case ';': 196 case YEOF: 197 return (INFINITY); 198 } 199 } 200 #ifdef DEBUG 201 202 /* 203 * Routine to print out costs with "-K" option. 204 */ 205 char yysyms[] = ";,:=*+/-|&()[]<>~^"; 206 207 208 yycosts() 209 { 210 register int c; 211 register char *cp; 212 213 printf("Insert\tDelete\tRep(ID)\tSymbol\n"); 214 for (cp = yysyms; *cp; cp++) 215 yydocost(*cp); 216 for (c = ERROR + 1; c < YLAST; c++) 217 yydocost(c); 218 #ifdef PXP 219 flush(); 220 #endif 221 } 222 223 yydocost(c) 224 int c; 225 { 226 227 printf("%4d\t", inscost(c, -1)); 228 printf("%4d\t", delcost(c)); 229 if (repcost(c, YID) != inscost(YID) + delcost(c)) 230 printf("%4d", repcost(c, YID)); 231 printf("\t%s%s\n", charname(c)); 232 } 233 #endif 234