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