xref: /original-bsd/games/atc/grammar.y (revision 77936e01)
1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Ed James.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 /*
12  * Copyright (c) 1987 by Ed James, UC Berkeley.  All rights reserved.
13  *
14  * Copy permission is hereby granted provided that this notice is
15  * retained on all partial or complete copies.
16  *
17  * For more info on this and all of my stuff, mail edjames@berkeley.edu.
18  */
19 
20 %token <ival>	HeightOp
21 %token <ival>	WidthOp
22 %token <ival>	UpdateOp
23 %token <ival>	NewplaneOp
24 %token <cval>	DirOp
25 %token <ival>	ConstOp
26 %token <ival>	LineOp
27 %token <ival>	AirportOp
28 %token <ival>	BeaconOp
29 %token <ival>	ExitOp
30 %union {
31 	int	ival;
32 	char	cval;
33 }
34 
35 %{
36 #include "include.h"
37 
38 #ifndef lint
39 static char sccsid[] = "@(#)grammar.y	5.2 (Berkeley) 04/30/90";
40 #endif /* not lint */
41 
42 int	errors = 0;
43 int	line = 1;
44 %}
45 
46 %%
47 file:
48 	bunch_of_defs { if (checkdefs() < 0) return (errors); } bunch_of_lines
49 		{
50 		if (sp->num_exits + sp->num_airports < 2)
51 			yyerror("Need at least 2 airports and/or exits.");
52 		return (errors);
53 		}
54 	;
55 
56 bunch_of_defs:
57 	def bunch_of_defs
58 	| def
59 	;
60 
61 def:
62 	udef
63 	| ndef
64 	| wdef
65 	| hdef
66 	;
67 
68 udef:
69 	UpdateOp '=' ConstOp ';'
70 		{
71 		if (sp->update_secs != 0)
72 			return (yyerror("Redefinition of 'update'."));
73 		else if ($3 < 1)
74 			return (yyerror("'update' is too small."));
75 		else
76 			sp->update_secs = $3;
77 		}
78 	;
79 
80 ndef:
81 	NewplaneOp '=' ConstOp ';'
82 		{
83 		if (sp->newplane_time != 0)
84 			return (yyerror("Redefinition of 'newplane'."));
85 		else if ($3 < 1)
86 			return (yyerror("'newplane' is too small."));
87 		else
88 			sp->newplane_time = $3;
89 		}
90 	;
91 
92 hdef:
93 	HeightOp '=' ConstOp ';'
94 		{
95 		if (sp->height != 0)
96 			return (yyerror("Redefinition of 'height'."));
97 		else if ($3 < 3)
98 			return (yyerror("'height' is too small."));
99 		else
100 			sp->height = $3;
101 		}
102 	;
103 
104 wdef:
105 	WidthOp '=' ConstOp ';'
106 		{
107 		if (sp->height != 0)
108 			return (yyerror("Redefinition of 'width'."));
109 		else if ($3 < 3)
110 			return (yyerror("'width' is too small."));
111 		else
112 			sp->width = $3;
113 		}
114 	;
115 
116 bunch_of_lines:
117 	line bunch_of_lines
118 		{}
119 	| line
120 		{}
121 	;
122 
123 line:
124 	BeaconOp ':' Bpoint_list ';'
125 		{}
126 	| ExitOp ':' Epoint_list ';'
127 		{}
128 	| LineOp ':' Lline_list ';'
129 		{}
130 	| AirportOp ':' Apoint_list ';'
131 		{}
132 	;
133 
134 Bpoint_list:
135 	Bpoint Bpoint_list
136 		{}
137 	| Bpoint
138 		{}
139 	;
140 
141 Bpoint:
142 	'(' ConstOp ConstOp ')'
143 		{
144 		if (sp->num_beacons % REALLOC == 0) {
145 			if (sp->beacon == NULL)
146 				sp->beacon = (BEACON *) malloc((sp->num_beacons
147 					+ REALLOC) * sizeof (BEACON));
148 			else
149 				sp->beacon = (BEACON *) realloc(sp->beacon,
150 					(sp->num_beacons + REALLOC) *
151 					sizeof (BEACON));
152 			if (sp->beacon == NULL)
153 				return (yyerror("No memory available."));
154 		}
155 		sp->beacon[sp->num_beacons].x = $2;
156 		sp->beacon[sp->num_beacons].y = $3;
157 		check_point($2, $3);
158 		sp->num_beacons++;
159 		}
160 	;
161 
162 Epoint_list:
163 	Epoint Epoint_list
164 		{}
165 	| Epoint
166 		{}
167 	;
168 
169 Epoint:
170 	'(' ConstOp ConstOp DirOp ')'
171 		{
172 		int	dir;
173 
174 		if (sp->num_exits % REALLOC == 0) {
175 			if (sp->exit == NULL)
176 				sp->exit = (EXIT *) malloc((sp->num_exits +
177 					REALLOC) * sizeof (EXIT));
178 			else
179 				sp->exit = (EXIT *) realloc(sp->exit,
180 					(sp->num_exits + REALLOC) *
181 					sizeof (EXIT));
182 			if (sp->exit == NULL)
183 				return (yyerror("No memory available."));
184 		}
185 		dir = dir_no($4);
186 		sp->exit[sp->num_exits].x = $2;
187 		sp->exit[sp->num_exits].y = $3;
188 		sp->exit[sp->num_exits].dir = dir;
189 		check_edge($2, $3);
190 		check_edir($2, $3, dir);
191 		sp->num_exits++;
192 		}
193 	;
194 
195 Apoint_list:
196 	Apoint Apoint_list
197 		{}
198 	| Apoint
199 		{}
200 	;
201 
202 Apoint:
203 	'(' ConstOp ConstOp DirOp ')'
204 		{
205 		int	dir;
206 
207 		if (sp->num_airports % REALLOC == 0) {
208 			if (sp->airport == NULL)
209 				sp->airport=(AIRPORT *)malloc((sp->num_airports
210 					+ REALLOC) * sizeof(AIRPORT));
211 			else
212 				sp->airport = (AIRPORT *) realloc(sp->airport,
213 					(sp->num_airports + REALLOC) *
214 					sizeof(AIRPORT));
215 			if (sp->airport == NULL)
216 				return (yyerror("No memory available."));
217 		}
218 		dir = dir_no($4);
219 		sp->airport[sp->num_airports].x = $2;
220 		sp->airport[sp->num_airports].y = $3;
221 		sp->airport[sp->num_airports].dir = dir;
222 		check_point($2, $3);
223 		check_adir($2, $3, dir);
224 		sp->num_airports++;
225 		}
226 	;
227 
228 Lline_list:
229 	Lline Lline_list
230 		{}
231 	| Lline
232 		{}
233 	;
234 
235 Lline:
236 	'[' '(' ConstOp ConstOp ')' '(' ConstOp ConstOp ')' ']'
237 		{
238 		if (sp->num_lines % REALLOC == 0) {
239 			if (sp->line == NULL)
240 				sp->line = (LINE *) malloc((sp->num_lines +
241 					REALLOC) * sizeof (LINE));
242 			else
243 				sp->line = (LINE *) realloc(sp->line,
244 					(sp->num_lines + REALLOC) *
245 					sizeof (LINE));
246 			if (sp->line == NULL)
247 				return (yyerror("No memory available."));
248 		}
249 		sp->line[sp->num_lines].p1.x = $3;
250 		sp->line[sp->num_lines].p1.y = $4;
251 		sp->line[sp->num_lines].p2.x = $7;
252 		sp->line[sp->num_lines].p2.y = $8;
253 		check_line($3, $4, $7, $8);
254 		sp->num_lines++;
255 		}
256 	;
257 %%
258 
259 check_edge(x, y)
260 {
261 	if (!(x == 0) && !(x == sp->width - 1) &&
262 	    !(y == 0) && !(y == sp->height - 1))
263 		yyerror("edge value not on edge.");
264 }
265 
266 check_point(x, y)
267 {
268 	if (x < 1 || x >= sp->width - 1)
269 		yyerror("X value out of range.");
270 	if (y < 1 || y >= sp->height - 1)
271 		yyerror("Y value out of range.");
272 }
273 
274 check_linepoint(x, y)
275 {
276 	if (x < 0 || x >= sp->width)
277 		yyerror("X value out of range.");
278 	if (y < 0 || y >= sp->height)
279 		yyerror("Y value out of range.");
280 }
281 
282 check_line(x1, y1, x2, y2)
283 {
284 	int	d1, d2;
285 
286 	check_linepoint(x1, y1);
287 	check_linepoint(x2, y2);
288 
289 	d1 = ABS(x2 - x1);
290 	d2 = ABS(y2 - y1);
291 
292 	if (!(d1 == d2) && !(d1 == 0) && !(d2 == 0))
293 		yyerror("Bad line endpoints.");
294 }
295 
296 yyerror(s)
297 {
298 	fprintf(stderr, "\"%s\": line %d: %s\n", file, line, s);
299 	errors++;
300 
301 	return (errors);
302 }
303 
304 check_edir(x, y, dir)
305 {
306 	int	bad = 0;
307 
308 	if (x == sp->width - 1)
309 		x = 2;
310 	else if (x != 0)
311 		x = 1;
312 	if (y == sp->height - 1)
313 		y = 2;
314 	else if (y != 0)
315 		y = 1;
316 
317 	switch (x * 10 + y) {
318 	case 00: if (dir != 3) bad++; break;
319 	case 01: if (dir < 1 || dir > 3) bad++; break;
320 	case 02: if (dir != 1) bad++; break;
321 	case 10: if (dir < 3 || dir > 5) bad++; break;
322 	case 11: break;
323 	case 12: if (dir > 1 && dir < 7) bad++; break;
324 	case 20: if (dir != 5) bad++; break;
325 	case 21: if (dir < 5) bad++; break;
326 	case 22: if (dir != 7) bad++; break;
327 	default:
328 		yyerror("Unknown value in checkdir!  Get help!");
329 		break;
330 	}
331 	if (bad)
332 		yyerror("Bad direction for entrance at exit.");
333 }
334 
335 check_adir(x, y, dir)
336 {
337 }
338 
339 checkdefs()
340 {
341 	int	err = 0;
342 
343 	if (sp->width == 0) {
344 		yyerror("'width' undefined.");
345 		err++;
346 	}
347 	if (sp->height == 0) {
348 		yyerror("'height' undefined.");
349 		err++;
350 	}
351 	if (sp->update_secs == 0) {
352 		yyerror("'update' undefined.");
353 		err++;
354 	}
355 	if (sp->newplane_time == 0) {
356 		yyerror("'newplane' undefined.");
357 		err++;
358 	}
359 	if (err)
360 		return (-1);
361 	else
362 		return (0);
363 }
364