xref: /original-bsd/usr.bin/pascal/src/yycosts.c (revision f0fd5f8a)
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