1 /* Copyright (c) 1979 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)yycosts.c 1.3 08/27/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 == ';' && (with == ',' || with == '.')) 153 return (CLIMIT - 1); 154 c = delcost(what) + inscost(with); 155 /* 156 * It costs extra to replace something which has 157 * semantics by something which doesn't. 158 */ 159 if (nullsem(what) == NIL && nullsem(with) != NIL) 160 c += 4; 161 return (c); 162 } 163 164 /* 165 * Deletion costs 166 */ 167 delcost(what) 168 int what; 169 { 170 171 switch (what) { 172 case '.': 173 case ':': 174 case ',': 175 case '=': 176 case '(': 177 return (3); 178 case YELSE: 179 case YTHEN: 180 return (4); 181 default: 182 return (5); 183 case YLABEL: 184 case YCONST: 185 case YTYPE: 186 case YVAR: 187 return (10); 188 case YPROCEDURE: 189 case YFUNCTION: 190 case YBEGIN: 191 case YEND: 192 return ((CLIMIT * 3) / 4); 193 case ';': 194 case YEOF: 195 return (INFINITY); 196 } 197 } 198 #ifdef DEBUG 199 200 /* 201 * Routine to print out costs with "-K" option. 202 */ 203 char yysyms[] = ";,:=*+/-|&()[]<>~^"; 204 205 206 yycosts() 207 { 208 register int c; 209 register char *cp; 210 211 printf("Insert\tDelete\tRep(ID)\tSymbol\n"); 212 for (cp = yysyms; *cp; cp++) 213 yydocost(*cp); 214 for (c = ERROR + 1; c < YLAST; c++) 215 yydocost(c); 216 #ifdef PXP 217 flush(); 218 #endif 219 } 220 221 yydocost(c) 222 int c; 223 { 224 225 printf("%4d\t", inscost(c, -1)); 226 printf("%4d\t", delcost(c)); 227 if (repcost(c, YID) != inscost(YID) + delcost(c)) 228 printf("%4d", repcost(c, YID)); 229 printf("\t%s%s\n", charname(c)); 230 } 231 #endif 232