1 /* Copyright (c) 1979 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)yycosts.c 1.2 03/08/81"; 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 case YASSERT: 104 return (5); 105 case YPROCEDURE: 106 case YFUNCTION: 107 case YCASE: 108 return (6); 109 case YEND: 110 return (8); 111 case YBEGIN: 112 case YEOF: 113 case YREPEAT: 114 case YRECORD: 115 return (INFINITY); 116 } 117 } 118 119 /* 120 * Replacement costs 121 * 122 * Most replacement costs are the same as an insertion 123 * plus a deletion cost. One special case is the replacement 124 * of a large number of keywords by an identifier. 125 * These are given lower costs, especially the keyword "to". 126 */ 127 repcost(what, with) 128 register int what, with; 129 { 130 register int c; 131 132 if (with == what) 133 return (INFINITY); 134 if (with == YID && what > ERROR) 135 switch (what) { 136 case YID: 137 case YDOTDOT: 138 case YINT: 139 case YBINT: 140 case YSTRING: 141 case YNUMB: 142 break; 143 case YTO: 144 return (3); 145 default: 146 return (5); 147 case YRECORD: 148 case YTHEN: 149 return (6); 150 case YBEGIN: 151 break; 152 } 153 if (what == ';' && (with == ',' || with == '.')) 154 return (CLIMIT - 1); 155 c = delcost(what) + inscost(with); 156 /* 157 * It costs extra to replace something which has 158 * semantics by something which doesn't. 159 */ 160 if (nullsem(what) == NIL && nullsem(with) != NIL) 161 c += 4; 162 return (c); 163 } 164 165 /* 166 * Deletion costs 167 */ 168 delcost(what) 169 int what; 170 { 171 172 switch (what) { 173 case '.': 174 case ':': 175 case ',': 176 case '=': 177 case '(': 178 return (3); 179 case YELSE: 180 case YTHEN: 181 return (4); 182 default: 183 return (5); 184 case YLABEL: 185 case YCONST: 186 case YTYPE: 187 case YVAR: 188 return (10); 189 case YPROCEDURE: 190 case YFUNCTION: 191 case YBEGIN: 192 case YEND: 193 return ((CLIMIT * 3) / 4); 194 case ';': 195 case YEOF: 196 return (INFINITY); 197 } 198 } 199 #ifdef DEBUG 200 201 /* 202 * Routine to print out costs with "-K" option. 203 */ 204 char yysyms[] = ";,:=*+/-|&()[]<>~^"; 205 206 207 yycosts() 208 { 209 register int c; 210 register char *cp; 211 212 printf("Insert\tDelete\tRep(ID)\tSymbol\n"); 213 for (cp = yysyms; *cp; cp++) 214 yydocost(*cp); 215 for (c = ERROR + 1; c < YLAST; c++) 216 yydocost(c); 217 #ifdef PXP 218 flush(); 219 #endif 220 } 221 222 yydocost(c) 223 int c; 224 { 225 226 printf("%4d\t", inscost(c, -1)); 227 printf("%4d\t", delcost(c)); 228 if (repcost(c, YID) != inscost(YID) + delcost(c)) 229 printf("%4d", repcost(c, YID)); 230 printf("\t%s%s\n", charname(c)); 231 } 232 #endif 233