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