xref: /csrg-svn/usr.bin/pascal/src/yycosts.c (revision 7999)
1783Speter /* Copyright (c) 1979 Regents of the University of California */
2783Speter 
3*7999Smckusick static char sccsid[] = "@(#)yycosts.c 1.4 08/30/82";
4783Speter 
5783Speter #include "whoami.h"
6783Speter #include "0.h"
7783Speter #include "yy.h"
8783Speter 
9783Speter /*
10783Speter  * Symbol costs for Pascal.
11783Speter  *
12783Speter  * Cost strategy of August 14, 1977.
13783Speter  *
14783Speter  * The costs determined by the routines in this file are used by
15783Speter  * the recovery in choosing appropriate corrections.
16783Speter  * The cost vectors and the error productions in the grammar
17783Speter  * work together to define the corrective capacity of the grammar.
18783Speter  *
19783Speter  * The costs here largely derive from those given in Steve Rhode's
20783Speter  * thesis for the Pascal-I error correcting parser which he implemented.
21783Speter  * Some minor changes have been made to adjust for the fact that
22783Speter  * the current error recovery is not as "smart", both because of the
23783Speter  * limited forward move and because of the lack of any type information
24783Speter  * about identifiers.
25783Speter  *
26783Speter  * These adjustments largely take the form of increased costs for certain
27783Speter  * tokens, noticeably keywords which are major brackets such as "begin"
28783Speter  * "label", "procedure", etc.
29783Speter  *
30783Speter  * The overall weighting strategy is still similar to Rhodes' strategy.
31783Speter  * The costs can be considered:
32783Speter  *
33783Speter  *	LOW	<= 3
34783Speter  *	MEDIUM	4 or 5
35783Speter  *	HIGH	>= 6
36783Speter  */
37783Speter 
38783Speter /*
39783Speter  * Insertion costs
40783Speter  *
41783Speter  * In addition to the normal symbol insertion costs,
42783Speter  * there are zero cost insertions here.
43783Speter  * The current error recovery system treats symbols
44783Speter  * which have zero insertion cost in a special way,
45783Speter  * inserting them but suppressing diagnostics.
46783Speter  * This allows the system to hold of on bracketing
47783Speter  * error diagnostics about missing end's until the
48783Speter  * reduction occurs which knows the line number of the
49783Speter  * corresponding "begin", "repeat", etc.
50783Speter  * A more intelligent and useful diagnostic can then
51783Speter  * be printed.
52783Speter  *
53783Speter  * Although this routine never allows the insertion
54783Speter  * of the keyword begin, it can be inserted after a
55783Speter  * procedure or function body starts, if it was omitted
56783Speter  * by a special case in the panic routine, which notices
57783Speter  * the keywords in the statement body of the procedure
58783Speter  * and inserts the begin to recover.
59783Speter  *
60783Speter  * Similarly, we do not insert end-of-file, but
61783Speter  * the fact that end-of-file is the unique input
62783Speter  * is noticed by the recovery routines as a special
63783Speter  * case and handled there.
64783Speter  */
65783Speter inscost(sy, before)
66783Speter 	register int sy, before;
67783Speter {
68783Speter 
69783Speter 	switch (before) {
70783Speter 		case YEND:
71783Speter 			if (sy == YEND)
72783Speter 				break;
73783Speter 		case YPROCEDURE:
74783Speter 		case YFUNCTION:
75783Speter 			if (sy == YUNTIL || sy == YEND)
76783Speter 				return (0);
77783Speter 	}
78783Speter 	switch (sy) {
79783Speter 		case ';':
80783Speter 			return (1);
81783Speter 		case ',':
82783Speter 		case ':':
83783Speter 		case YOF:
84783Speter 		case YDO:
85783Speter 			return (2);
86783Speter 		case YARRAY:
87783Speter 		case '+':
88783Speter 		case '*':
89783Speter 			return (3);
90783Speter 		default:
91783Speter 			return (4);
92783Speter 		case '^':
93783Speter 		case YNOT:
94783Speter 		case YLABEL:
95783Speter 		case YCONST:
96783Speter 		case YTYPE:
97783Speter 		case YVAR:
98783Speter 		case YUNTIL:
99783Speter 		case '(':
100783Speter 		case '[':
101783Speter 		case YWHILE:
102783Speter 		case YWITH:
103783Speter 			return (5);
104783Speter 		case YPROCEDURE:
105783Speter 		case YFUNCTION:
106783Speter 		case YCASE:
107783Speter 			return (6);
108783Speter 		case YEND:
109783Speter 			return (8);
110783Speter 		case YBEGIN:
111783Speter 		case YEOF:
112783Speter 		case YREPEAT:
113783Speter 		case YRECORD:
114783Speter 			return (INFINITY);
115783Speter 	}
116783Speter }
117783Speter 
118783Speter /*
119783Speter  * Replacement costs
120783Speter  *
121783Speter  * Most replacement costs are the same as an insertion
122783Speter  * plus a deletion cost.  One special case is the replacement
123783Speter  * of a large number of keywords by an identifier.
124783Speter  * These are given lower costs, especially the keyword "to".
125783Speter  */
126783Speter repcost(what, with)
127783Speter 	register int what, with;
128783Speter {
129783Speter 	register int c;
130783Speter 
131783Speter 	if (with == what)
132783Speter 		return (INFINITY);
133783Speter 	if (with == YID && what > ERROR)
134783Speter 		switch (what) {
135783Speter 			case YID:
136783Speter 			case YDOTDOT:
137783Speter 			case YINT:
138783Speter 			case YBINT:
139783Speter 			case YSTRING:
140783Speter 			case YNUMB:
141783Speter 				break;
142783Speter 			case YTO:
143783Speter 				return (3);
144783Speter 			default:
145783Speter 				return (5);
146783Speter 			case YRECORD:
147783Speter 			case YTHEN:
148783Speter 				return (6);
149783Speter 			case YBEGIN:
150783Speter 				break;
151783Speter 		}
152*7999Smckusick 	if (what == YID && with == YFORWARD)
153*7999Smckusick 		return(5);
154783Speter 	if (what == ';' && (with == ',' || with == '.'))
155783Speter 		return (CLIMIT - 1);
156783Speter 	c = delcost(what) + inscost(with);
157783Speter 	/*
158783Speter 	 * It costs extra to replace something which has
159783Speter 	 * semantics by something which doesn't.
160783Speter 	 */
161783Speter 	if (nullsem(what) == NIL && nullsem(with) != NIL)
1623084Smckusic 		c += 4;
163783Speter 	return (c);
164783Speter }
165783Speter 
166783Speter /*
167783Speter  * Deletion costs
168783Speter  */
169783Speter delcost(what)
170783Speter 	int what;
171783Speter {
172783Speter 
173783Speter 	switch (what) {
174783Speter 		case '.':
175783Speter 		case ':':
176783Speter 		case ',':
177783Speter 		case '=':
178783Speter 		case '(':
179783Speter 			return (3);
180783Speter 		case YELSE:
181783Speter 		case YTHEN:
182783Speter 			return (4);
183783Speter 		default:
184783Speter 			return (5);
185783Speter 		case YLABEL:
186783Speter 		case YCONST:
187783Speter 		case YTYPE:
188783Speter 		case YVAR:
189783Speter 			return (10);
190783Speter 		case YPROCEDURE:
191783Speter 		case YFUNCTION:
192783Speter 		case YBEGIN:
193783Speter 		case YEND:
194783Speter 			return ((CLIMIT * 3) / 4);
195783Speter 		case ';':
196783Speter 		case YEOF:
197783Speter 			return (INFINITY);
198783Speter 	}
199783Speter }
200783Speter #ifdef DEBUG
201783Speter 
202783Speter /*
203783Speter  * Routine to print out costs with "-K" option.
204783Speter  */
2053084Smckusic char	yysyms[] = ";,:=*+/-|&()[]<>~^";
206783Speter 
207783Speter 
208783Speter yycosts()
209783Speter {
210783Speter 	register int c;
211783Speter 	register char *cp;
212783Speter 
213783Speter 	printf("Insert\tDelete\tRep(ID)\tSymbol\n");
214783Speter 	for (cp = yysyms; *cp; cp++)
215783Speter 		yydocost(*cp);
216783Speter 	for (c = ERROR + 1; c < YLAST; c++)
217783Speter 		yydocost(c);
218783Speter #ifdef PXP
219783Speter 	flush();
220783Speter #endif
221783Speter }
222783Speter 
223783Speter yydocost(c)
224783Speter 	int c;
225783Speter {
226783Speter 
227783Speter 	printf("%4d\t", inscost(c, -1));
228783Speter 	printf("%4d\t", delcost(c));
229783Speter 	if (repcost(c, YID) != inscost(YID) + delcost(c))
230783Speter 		printf("%4d", repcost(c, YID));
231783Speter 	printf("\t%s%s\n", charname(c));
232783Speter }
233783Speter #endif
234