grammar.y revision 1.2       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  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *	This product includes software developed by the University of
     19  *	California, Berkeley and its contributors.
     20  * 4. Neither the name of the University nor the names of its contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  */
     36 
     37 /*
     38  * Copyright (c) 1987 by Ed James, UC Berkeley.  All rights reserved.
     39  *
     40  * Copy permission is hereby granted provided that this notice is
     41  * retained on all partial or complete copies.
     42  *
     43  * For more info on this and all of my stuff, mail edjames (at) berkeley.edu.
     44  */
     45 
     46 %token <ival>	HeightOp
     47 %token <ival>	WidthOp
     48 %token <ival>	UpdateOp
     49 %token <ival>	NewplaneOp
     50 %token <cval>	DirOp
     51 %token <ival>	ConstOp
     52 %token <ival>	LineOp
     53 %token <ival>	AirportOp
     54 %token <ival>	BeaconOp
     55 %token <ival>	ExitOp
     56 %union {
     57 	int	ival;
     58 	char	cval;
     59 }
     60 
     61 %{
     62 #include "include.h"
     63 
     64 #ifndef lint
     65 /*static char sccsid[] = "from: @(#)grammar.y	5.2 (Berkeley) 4/30/90";*/
     66 static char rcsid[] = "$Id: grammar.y,v 1.2 1993/08/01 18:57:12 mycroft Exp $";
     67 #endif /* not lint */
     68 
     69 int	errors = 0;
     70 int	line = 1;
     71 %}
     72 
     73 %%
     74 file:
     75 	bunch_of_defs { if (checkdefs() < 0) return (errors); } bunch_of_lines
     76 		{
     77 		if (sp->num_exits + sp->num_airports < 2)
     78 			yyerror("Need at least 2 airports and/or exits.");
     79 		return (errors);
     80 		}
     81 	;
     82 
     83 bunch_of_defs:
     84 	def bunch_of_defs
     85 	| def
     86 	;
     87 
     88 def:
     89 	udef
     90 	| ndef
     91 	| wdef
     92 	| hdef
     93 	;
     94 
     95 udef:
     96 	UpdateOp '=' ConstOp ';'
     97 		{
     98 		if (sp->update_secs != 0)
     99 			return (yyerror("Redefinition of 'update'."));
    100 		else if ($3 < 1)
    101 			return (yyerror("'update' is too small."));
    102 		else
    103 			sp->update_secs = $3;
    104 		}
    105 	;
    106 
    107 ndef:
    108 	NewplaneOp '=' ConstOp ';'
    109 		{
    110 		if (sp->newplane_time != 0)
    111 			return (yyerror("Redefinition of 'newplane'."));
    112 		else if ($3 < 1)
    113 			return (yyerror("'newplane' is too small."));
    114 		else
    115 			sp->newplane_time = $3;
    116 		}
    117 	;
    118 
    119 hdef:
    120 	HeightOp '=' ConstOp ';'
    121 		{
    122 		if (sp->height != 0)
    123 			return (yyerror("Redefinition of 'height'."));
    124 		else if ($3 < 3)
    125 			return (yyerror("'height' is too small."));
    126 		else
    127 			sp->height = $3;
    128 		}
    129 	;
    130 
    131 wdef:
    132 	WidthOp '=' ConstOp ';'
    133 		{
    134 		if (sp->height != 0)
    135 			return (yyerror("Redefinition of 'width'."));
    136 		else if ($3 < 3)
    137 			return (yyerror("'width' is too small."));
    138 		else
    139 			sp->width = $3;
    140 		}
    141 	;
    142 
    143 bunch_of_lines:
    144 	line bunch_of_lines
    145 		{}
    146 	| line
    147 		{}
    148 	;
    149 
    150 line:
    151 	BeaconOp ':' Bpoint_list ';'
    152 		{}
    153 	| ExitOp ':' Epoint_list ';'
    154 		{}
    155 	| LineOp ':' Lline_list ';'
    156 		{}
    157 	| AirportOp ':' Apoint_list ';'
    158 		{}
    159 	;
    160 
    161 Bpoint_list:
    162 	Bpoint Bpoint_list
    163 		{}
    164 	| Bpoint
    165 		{}
    166 	;
    167 
    168 Bpoint:
    169 	'(' ConstOp ConstOp ')'
    170 		{
    171 		if (sp->num_beacons % REALLOC == 0) {
    172 			if (sp->beacon == NULL)
    173 				sp->beacon = (BEACON *) malloc((sp->num_beacons
    174 					+ REALLOC) * sizeof (BEACON));
    175 			else
    176 				sp->beacon = (BEACON *) realloc(sp->beacon,
    177 					(sp->num_beacons + REALLOC) *
    178 					sizeof (BEACON));
    179 			if (sp->beacon == NULL)
    180 				return (yyerror("No memory available."));
    181 		}
    182 		sp->beacon[sp->num_beacons].x = $2;
    183 		sp->beacon[sp->num_beacons].y = $3;
    184 		check_point($2, $3);
    185 		sp->num_beacons++;
    186 		}
    187 	;
    188 
    189 Epoint_list:
    190 	Epoint Epoint_list
    191 		{}
    192 	| Epoint
    193 		{}
    194 	;
    195 
    196 Epoint:
    197 	'(' ConstOp ConstOp DirOp ')'
    198 		{
    199 		int	dir;
    200 
    201 		if (sp->num_exits % REALLOC == 0) {
    202 			if (sp->exit == NULL)
    203 				sp->exit = (EXIT *) malloc((sp->num_exits +
    204 					REALLOC) * sizeof (EXIT));
    205 			else
    206 				sp->exit = (EXIT *) realloc(sp->exit,
    207 					(sp->num_exits + REALLOC) *
    208 					sizeof (EXIT));
    209 			if (sp->exit == NULL)
    210 				return (yyerror("No memory available."));
    211 		}
    212 		dir = dir_no($4);
    213 		sp->exit[sp->num_exits].x = $2;
    214 		sp->exit[sp->num_exits].y = $3;
    215 		sp->exit[sp->num_exits].dir = dir;
    216 		check_edge($2, $3);
    217 		check_edir($2, $3, dir);
    218 		sp->num_exits++;
    219 		}
    220 	;
    221 
    222 Apoint_list:
    223 	Apoint Apoint_list
    224 		{}
    225 	| Apoint
    226 		{}
    227 	;
    228 
    229 Apoint:
    230 	'(' ConstOp ConstOp DirOp ')'
    231 		{
    232 		int	dir;
    233 
    234 		if (sp->num_airports % REALLOC == 0) {
    235 			if (sp->airport == NULL)
    236 				sp->airport=(AIRPORT *)malloc((sp->num_airports
    237 					+ REALLOC) * sizeof(AIRPORT));
    238 			else
    239 				sp->airport = (AIRPORT *) realloc(sp->airport,
    240 					(sp->num_airports + REALLOC) *
    241 					sizeof(AIRPORT));
    242 			if (sp->airport == NULL)
    243 				return (yyerror("No memory available."));
    244 		}
    245 		dir = dir_no($4);
    246 		sp->airport[sp->num_airports].x = $2;
    247 		sp->airport[sp->num_airports].y = $3;
    248 		sp->airport[sp->num_airports].dir = dir;
    249 		check_point($2, $3);
    250 		check_adir($2, $3, dir);
    251 		sp->num_airports++;
    252 		}
    253 	;
    254 
    255 Lline_list:
    256 	Lline Lline_list
    257 		{}
    258 	| Lline
    259 		{}
    260 	;
    261 
    262 Lline:
    263 	'[' '(' ConstOp ConstOp ')' '(' ConstOp ConstOp ')' ']'
    264 		{
    265 		if (sp->num_lines % REALLOC == 0) {
    266 			if (sp->line == NULL)
    267 				sp->line = (LINE *) malloc((sp->num_lines +
    268 					REALLOC) * sizeof (LINE));
    269 			else
    270 				sp->line = (LINE *) realloc(sp->line,
    271 					(sp->num_lines + REALLOC) *
    272 					sizeof (LINE));
    273 			if (sp->line == NULL)
    274 				return (yyerror("No memory available."));
    275 		}
    276 		sp->line[sp->num_lines].p1.x = $3;
    277 		sp->line[sp->num_lines].p1.y = $4;
    278 		sp->line[sp->num_lines].p2.x = $7;
    279 		sp->line[sp->num_lines].p2.y = $8;
    280 		check_line($3, $4, $7, $8);
    281 		sp->num_lines++;
    282 		}
    283 	;
    284 %%
    285 
    286 check_edge(x, y)
    287 {
    288 	if (!(x == 0) && !(x == sp->width - 1) &&
    289 	    !(y == 0) && !(y == sp->height - 1))
    290 		yyerror("edge value not on edge.");
    291 }
    292 
    293 check_point(x, y)
    294 {
    295 	if (x < 1 || x >= sp->width - 1)
    296 		yyerror("X value out of range.");
    297 	if (y < 1 || y >= sp->height - 1)
    298 		yyerror("Y value out of range.");
    299 }
    300 
    301 check_linepoint(x, y)
    302 {
    303 	if (x < 0 || x >= sp->width)
    304 		yyerror("X value out of range.");
    305 	if (y < 0 || y >= sp->height)
    306 		yyerror("Y value out of range.");
    307 }
    308 
    309 check_line(x1, y1, x2, y2)
    310 {
    311 	int	d1, d2;
    312 
    313 	check_linepoint(x1, y1);
    314 	check_linepoint(x2, y2);
    315 
    316 	d1 = ABS(x2 - x1);
    317 	d2 = ABS(y2 - y1);
    318 
    319 	if (!(d1 == d2) && !(d1 == 0) && !(d2 == 0))
    320 		yyerror("Bad line endpoints.");
    321 }
    322 
    323 yyerror(s)
    324 {
    325 	fprintf(stderr, "\"%s\": line %d: %s\n", file, line, s);
    326 	errors++;
    327 
    328 	return (errors);
    329 }
    330 
    331 check_edir(x, y, dir)
    332 {
    333 	int	bad = 0;
    334 
    335 	if (x == sp->width - 1)
    336 		x = 2;
    337 	else if (x != 0)
    338 		x = 1;
    339 	if (y == sp->height - 1)
    340 		y = 2;
    341 	else if (y != 0)
    342 		y = 1;
    343 
    344 	switch (x * 10 + y) {
    345 	case 00: if (dir != 3) bad++; break;
    346 	case 01: if (dir < 1 || dir > 3) bad++; break;
    347 	case 02: if (dir != 1) bad++; break;
    348 	case 10: if (dir < 3 || dir > 5) bad++; break;
    349 	case 11: break;
    350 	case 12: if (dir > 1 && dir < 7) bad++; break;
    351 	case 20: if (dir != 5) bad++; break;
    352 	case 21: if (dir < 5) bad++; break;
    353 	case 22: if (dir != 7) bad++; break;
    354 	default:
    355 		yyerror("Unknown value in checkdir!  Get help!");
    356 		break;
    357 	}
    358 	if (bad)
    359 		yyerror("Bad direction for entrance at exit.");
    360 }
    361 
    362 check_adir(x, y, dir)
    363 {
    364 }
    365 
    366 checkdefs()
    367 {
    368 	int	err = 0;
    369 
    370 	if (sp->width == 0) {
    371 		yyerror("'width' undefined.");
    372 		err++;
    373 	}
    374 	if (sp->height == 0) {
    375 		yyerror("'height' undefined.");
    376 		err++;
    377 	}
    378 	if (sp->update_secs == 0) {
    379 		yyerror("'update' undefined.");
    380 		err++;
    381 	}
    382 	if (sp->newplane_time == 0) {
    383 		yyerror("'newplane' undefined.");
    384 		err++;
    385 	}
    386 	if (err)
    387 		return (-1);
    388 	else
    389 		return (0);
    390 }
    391