OLD | NEW |
(Empty) | |
| 1 /* Bison Action Scanner -*- C -*- |
| 2 |
| 3 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc. |
| 4 |
| 5 This file is part of Bison, the GNU Compiler Compiler. |
| 6 |
| 7 This program is free software: you can redistribute it and/or modify |
| 8 it under the terms of the GNU General Public License as published by |
| 9 the Free Software Foundation, either version 3 of the License, or |
| 10 (at your option) any later version. |
| 11 |
| 12 This program is distributed in the hope that it will be useful, |
| 13 but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 GNU General Public License for more details. |
| 16 |
| 17 You should have received a copy of the GNU General Public License |
| 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| 19 |
| 20 %option debug nodefault nounput noyywrap never-interactive |
| 21 %option prefix="code_" outfile="lex.yy.c" |
| 22 |
| 23 %{ |
| 24 /* Work around a bug in flex 2.5.31. See Debian bug 333231 |
| 25 <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>. */ |
| 26 #undef code_wrap |
| 27 #define code_wrap() 1 |
| 28 |
| 29 #define FLEX_PREFIX(Id) code_ ## Id |
| 30 #include "flex-scanner.h" |
| 31 |
| 32 #include "complain.h" |
| 33 #include "reader.h" |
| 34 #include "getargs.h" |
| 35 #include <get-errno.h> |
| 36 #include <quote.h> |
| 37 |
| 38 #include "scan-code.h" |
| 39 #include "symlist.h" |
| 40 |
| 41 /* The current calling start condition: SC_RULE_ACTION or |
| 42 SC_SYMBOL_ACTION. */ |
| 43 # define YY_DECL static char *code_lex (code_props *self, int sc_context) |
| 44 YY_DECL; |
| 45 |
| 46 #define YY_USER_ACTION location_compute (loc, &loc->end, yytext, yyleng); |
| 47 |
| 48 static void handle_action_dollar (symbol_list *rule, char *cp, |
| 49 location dollar_loc); |
| 50 static void handle_action_at (symbol_list *rule, char *cp, location at_loc); |
| 51 static location the_location; |
| 52 static location *loc = &the_location; |
| 53 |
| 54 /* A string representing the most recent translation. */ |
| 55 static char *last_string; |
| 56 |
| 57 /* True if an untyped $$ or $n was seen. */ |
| 58 static bool untyped_var_seen; |
| 59 %} |
| 60 /* C and C++ comments in code. */ |
| 61 %x SC_COMMENT SC_LINE_COMMENT |
| 62 /* Strings and characters in code. */ |
| 63 %x SC_STRING SC_CHARACTER |
| 64 /* Whether in a rule or symbol action. Specifies the translation |
| 65 of $ and @. */ |
| 66 %x SC_RULE_ACTION SC_SYMBOL_ACTION |
| 67 |
| 68 |
| 69 /* POSIX says that a tag must be both an id and a C union member, but |
| 70 historically almost any character is allowed in a tag. We disallow |
| 71 NUL and newline, as this simplifies our implementation. */ |
| 72 tag [^\0\n>]+ |
| 73 |
| 74 /* Zero or more instances of backslash-newline. Following GCC, allow |
| 75 white space between the backslash and the newline. */ |
| 76 splice (\\[ \f\t\v]*\n)* |
| 77 |
| 78 %% |
| 79 |
| 80 %{ |
| 81 /* Nesting level of the current code in braces. */ |
| 82 int braces_level = 0; |
| 83 |
| 84 /* This scanner is special: it is invoked only once, henceforth |
| 85 is expected to return only once. This initialization is |
| 86 therefore done once per action to translate. */ |
| 87 aver (sc_context == SC_SYMBOL_ACTION |
| 88 || sc_context == SC_RULE_ACTION |
| 89 || sc_context == INITIAL); |
| 90 BEGIN sc_context; |
| 91 %} |
| 92 |
| 93 /*------------------------------------------------------------. |
| 94 | Scanning a C comment. The initial `/ *' is already eaten. | |
| 95 `------------------------------------------------------------*/ |
| 96 |
| 97 <SC_COMMENT> |
| 98 { |
| 99 "*"{splice}"/" STRING_GROW; BEGIN sc_context; |
| 100 } |
| 101 |
| 102 |
| 103 /*--------------------------------------------------------------. |
| 104 | Scanning a line comment. The initial `//' is already eaten. | |
| 105 `--------------------------------------------------------------*/ |
| 106 |
| 107 <SC_LINE_COMMENT> |
| 108 { |
| 109 "\n" STRING_GROW; BEGIN sc_context; |
| 110 {splice} STRING_GROW; |
| 111 } |
| 112 |
| 113 |
| 114 /*--------------------------------------------. |
| 115 | Scanning user-code characters and strings. | |
| 116 `--------------------------------------------*/ |
| 117 |
| 118 <SC_CHARACTER,SC_STRING> |
| 119 { |
| 120 {splice}|\\{splice}. STRING_GROW; |
| 121 } |
| 122 |
| 123 <SC_CHARACTER> |
| 124 { |
| 125 "'" STRING_GROW; BEGIN sc_context; |
| 126 } |
| 127 |
| 128 <SC_STRING> |
| 129 { |
| 130 "\"" STRING_GROW; BEGIN sc_context; |
| 131 } |
| 132 |
| 133 |
| 134 <SC_RULE_ACTION,SC_SYMBOL_ACTION>{ |
| 135 "'" { |
| 136 STRING_GROW; |
| 137 BEGIN SC_CHARACTER; |
| 138 } |
| 139 "\"" { |
| 140 STRING_GROW; |
| 141 BEGIN SC_STRING; |
| 142 } |
| 143 "/"{splice}"*" { |
| 144 STRING_GROW; |
| 145 BEGIN SC_COMMENT; |
| 146 } |
| 147 "/"{splice}"/" { |
| 148 STRING_GROW; |
| 149 BEGIN SC_LINE_COMMENT; |
| 150 } |
| 151 } |
| 152 |
| 153 <SC_RULE_ACTION> |
| 154 { |
| 155 "$"("<"{tag}">")?(-?[0-9]+|"$") { |
| 156 handle_action_dollar (self->rule, yytext, *loc); |
| 157 } |
| 158 "@"(-?[0-9]+|"$") { |
| 159 handle_action_at (self->rule, yytext, *loc); |
| 160 } |
| 161 |
| 162 "$" { |
| 163 warn_at (*loc, _("stray `$'")); |
| 164 obstack_sgrow (&obstack_for_string, "$]["); |
| 165 } |
| 166 "@" { |
| 167 warn_at (*loc, _("stray `@'")); |
| 168 obstack_sgrow (&obstack_for_string, "@@"); |
| 169 } |
| 170 |
| 171 "{" STRING_GROW; ++braces_level; |
| 172 "}" { |
| 173 bool outer_brace = --braces_level == 0; |
| 174 |
| 175 /* As an undocumented Bison extension, append `;' before the last |
| 176 brace in braced code, so that the user code can omit trailing |
| 177 `;'. But do not append `;' if emulating Yacc, since Yacc does |
| 178 not append one. Also, some output languages (like Java) do not |
| 179 accept an extra semicolon, so don't append if the user specified |
| 180 a skeleton or language. |
| 181 |
| 182 FIXME: Bison should warn if a semicolon seems to be necessary |
| 183 here, and should omit the semicolon if it seems unnecessary |
| 184 (e.g., after ';', '{', or '}', each followed by comments or |
| 185 white space). Such a warning shouldn't depend on --yacc; it |
| 186 should depend on a new --pedantic option, which would cause |
| 187 Bison to warn if it detects an extension to POSIX. --pedantic |
| 188 should also diagnose other Bison extensions like %yacc. |
| 189 Perhaps there should also be a GCC-style --pedantic-errors |
| 190 option, so that such warnings are diagnosed as errors. */ |
| 191 if (outer_brace && !yacc_flag && language_prio == default_prio |
| 192 && skeleton_prio == default_prio) |
| 193 obstack_1grow (&obstack_for_string, ';'); |
| 194 |
| 195 STRING_GROW; |
| 196 } |
| 197 } |
| 198 |
| 199 <SC_SYMBOL_ACTION> |
| 200 { |
| 201 "$$" { |
| 202 obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar["); |
| 203 self->is_value_used = true; |
| 204 } |
| 205 "@$" { |
| 206 obstack_sgrow (&obstack_for_string, "]b4_at_dollar["); |
| 207 locations_flag = true; |
| 208 } |
| 209 } |
| 210 |
| 211 |
| 212 /*-----------------------------------------. |
| 213 | Escape M4 quoting characters in C code. | |
| 214 `-----------------------------------------*/ |
| 215 |
| 216 <*> |
| 217 { |
| 218 \$ obstack_sgrow (&obstack_for_string, "$]["); |
| 219 \@ obstack_sgrow (&obstack_for_string, "@@"); |
| 220 \[ obstack_sgrow (&obstack_for_string, "@{"); |
| 221 \] obstack_sgrow (&obstack_for_string, "@}"); |
| 222 } |
| 223 |
| 224 /*-----------------------------------------------------. |
| 225 | By default, grow the string obstack with the input. | |
| 226 `-----------------------------------------------------*/ |
| 227 |
| 228 <*>.|\n STRING_GROW; |
| 229 |
| 230 /* End of processing. */ |
| 231 <*><<EOF>> { |
| 232 STRING_FINISH; |
| 233 return last_string; |
| 234 } |
| 235 |
| 236 %% |
| 237 |
| 238 /* Keeps track of the maximum number of semantic values to the left of |
| 239 a handle (those referenced by $0, $-1, etc.) are required by the |
| 240 semantic actions of this grammar. */ |
| 241 int max_left_semantic_context = 0; |
| 242 |
| 243 |
| 244 /*------------------------------------------------------------------. |
| 245 | TEXT is pointing to a wannabee semantic value (i.e., a `$'). | |
| 246 | | |
| 247 | Possible inputs: $[<TYPENAME>]($|integer) | |
| 248 | | |
| 249 | Output to OBSTACK_FOR_STRING a reference to this semantic value. | |
| 250 `------------------------------------------------------------------*/ |
| 251 |
| 252 static void |
| 253 handle_action_dollar (symbol_list *rule, char *text, location dollar_loc) |
| 254 { |
| 255 char const *type_name = NULL; |
| 256 char *cp = text + 1; |
| 257 symbol_list *effective_rule; |
| 258 int effective_rule_length; |
| 259 |
| 260 if (rule->midrule_parent_rule) |
| 261 { |
| 262 effective_rule = rule->midrule_parent_rule; |
| 263 effective_rule_length = rule->midrule_parent_rhs_index - 1; |
| 264 } |
| 265 else |
| 266 { |
| 267 effective_rule = rule; |
| 268 effective_rule_length = symbol_list_length (rule->next); |
| 269 } |
| 270 |
| 271 /* Get the type name if explicit. */ |
| 272 if (*cp == '<') |
| 273 { |
| 274 type_name = ++cp; |
| 275 while (*cp != '>') |
| 276 ++cp; |
| 277 *cp = '\0'; |
| 278 ++cp; |
| 279 if (untyped_var_seen) |
| 280 complain_at (dollar_loc, _("explicit type given in untyped grammar")); |
| 281 tag_seen = true; |
| 282 } |
| 283 |
| 284 if (*cp == '$') |
| 285 { |
| 286 if (!type_name) |
| 287 type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0); |
| 288 |
| 289 if (!type_name) |
| 290 { |
| 291 if (union_seen | tag_seen) |
| 292 { |
| 293 if (rule->midrule_parent_rule) |
| 294 complain_at (dollar_loc, |
| 295 _("$$ for the midrule at $%d of `%s'" |
| 296 " has no declared type"), |
| 297 rule->midrule_parent_rhs_index, |
| 298 effective_rule->content.sym->tag); |
| 299 else |
| 300 complain_at (dollar_loc, _("$$ of `%s' has no declared type"), |
| 301 rule->content.sym->tag); |
| 302 } |
| 303 else |
| 304 untyped_var_seen = true; |
| 305 type_name = ""; |
| 306 } |
| 307 |
| 308 obstack_fgrow1 (&obstack_for_string, |
| 309 "]b4_lhs_value([%s])[", type_name); |
| 310 rule->action_props.is_value_used = true; |
| 311 } |
| 312 else |
| 313 { |
| 314 long int num = strtol (cp, NULL, 10); |
| 315 |
| 316 if (1 - INT_MAX + effective_rule_length <= num |
| 317 && num <= effective_rule_length) |
| 318 { |
| 319 int n = num; |
| 320 if (max_left_semantic_context < 1 - n) |
| 321 max_left_semantic_context = 1 - n; |
| 322 if (!type_name && 0 < n) |
| 323 type_name = |
| 324 symbol_list_n_type_name_get (effective_rule, dollar_loc, n); |
| 325 if (!type_name) |
| 326 { |
| 327 if (union_seen | tag_seen) |
| 328 complain_at (dollar_loc, _("$%d of `%s' has no declared type"), |
| 329 n, effective_rule->content.sym->tag); |
| 330 else |
| 331 untyped_var_seen = true; |
| 332 type_name = ""; |
| 333 } |
| 334 |
| 335 obstack_fgrow3 (&obstack_for_string, |
| 336 "]b4_rhs_value(%d, %d, [%s])[", |
| 337 effective_rule_length, n, type_name); |
| 338 if (n > 0) |
| 339 symbol_list_n_get (effective_rule, n)->action_props.is_value_used = |
| 340 true; |
| 341 } |
| 342 else |
| 343 complain_at (dollar_loc, _("integer out of range: %s"), quote (text)); |
| 344 } |
| 345 } |
| 346 |
| 347 |
| 348 /*------------------------------------------------------. |
| 349 | TEXT is a location token (i.e., a `@...'). Output to | |
| 350 | OBSTACK_FOR_STRING a reference to this location. | |
| 351 `------------------------------------------------------*/ |
| 352 |
| 353 static void |
| 354 handle_action_at (symbol_list *rule, char *text, location at_loc) |
| 355 { |
| 356 char *cp = text + 1; |
| 357 int effective_rule_length = |
| 358 (rule->midrule_parent_rule |
| 359 ? rule->midrule_parent_rhs_index - 1 |
| 360 : symbol_list_length (rule->next)); |
| 361 |
| 362 locations_flag = true; |
| 363 |
| 364 if (*cp == '$') |
| 365 obstack_sgrow (&obstack_for_string, "]b4_lhs_location["); |
| 366 else |
| 367 { |
| 368 long int num = strtol (cp, NULL, 10); |
| 369 |
| 370 if (1 - INT_MAX + effective_rule_length <= num |
| 371 && num <= effective_rule_length) |
| 372 { |
| 373 int n = num; |
| 374 obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[", |
| 375 effective_rule_length, n); |
| 376 } |
| 377 else |
| 378 complain_at (at_loc, _("integer out of range: %s"), quote (text)); |
| 379 } |
| 380 } |
| 381 |
| 382 |
| 383 /*-------------------------. |
| 384 | Initialize the scanner. | |
| 385 `-------------------------*/ |
| 386 |
| 387 /* Translate the dollars and ats in \a self, in the context \a sc_context |
| 388 (SC_RULE_ACTION, SC_SYMBOL_ACTION, INITIAL). */ |
| 389 |
| 390 static char const * |
| 391 translate_action (code_props *self, int sc_context) |
| 392 { |
| 393 char *res; |
| 394 static bool initialized = false; |
| 395 if (!initialized) |
| 396 { |
| 397 obstack_init (&obstack_for_string); |
| 398 yy_flex_debug = 0; |
| 399 initialized = true; |
| 400 } |
| 401 |
| 402 loc->start = loc->end = self->location.start; |
| 403 yy_switch_to_buffer (yy_scan_string (self->code)); |
| 404 res = code_lex (self, sc_context); |
| 405 yy_delete_buffer (YY_CURRENT_BUFFER); |
| 406 |
| 407 return res; |
| 408 } |
| 409 |
| 410 /*------------------------------------------------------------------------. |
| 411 | Implementation of the public interface as documented in "scan-code.h". | |
| 412 `------------------------------------------------------------------------*/ |
| 413 |
| 414 void |
| 415 code_props_none_init (code_props *self) |
| 416 { |
| 417 *self = code_props_none; |
| 418 } |
| 419 |
| 420 code_props const code_props_none = CODE_PROPS_NONE_INIT; |
| 421 |
| 422 void |
| 423 code_props_plain_init (code_props *self, char const *code, location code_loc) |
| 424 { |
| 425 self->kind = CODE_PROPS_PLAIN; |
| 426 self->code = code; |
| 427 self->location = code_loc; |
| 428 self->is_value_used = false; |
| 429 self->rule = NULL; |
| 430 } |
| 431 |
| 432 void |
| 433 code_props_symbol_action_init (code_props *self, char const *code, |
| 434 location code_loc) |
| 435 { |
| 436 self->kind = CODE_PROPS_SYMBOL_ACTION; |
| 437 self->code = code; |
| 438 self->location = code_loc; |
| 439 self->is_value_used = false; |
| 440 self->rule = NULL; |
| 441 } |
| 442 |
| 443 void |
| 444 code_props_rule_action_init (code_props *self, char const *code, |
| 445 location code_loc, symbol_list *rule) |
| 446 { |
| 447 self->kind = CODE_PROPS_RULE_ACTION; |
| 448 self->code = code; |
| 449 self->location = code_loc; |
| 450 self->is_value_used = false; |
| 451 self->rule = rule; |
| 452 } |
| 453 |
| 454 void |
| 455 code_props_translate_code (code_props *self) |
| 456 { |
| 457 switch (self->kind) |
| 458 { |
| 459 case CODE_PROPS_NONE: |
| 460 break; |
| 461 case CODE_PROPS_PLAIN: |
| 462 self->code = translate_action (self, INITIAL); |
| 463 break; |
| 464 case CODE_PROPS_SYMBOL_ACTION: |
| 465 self->code = translate_action (self, SC_SYMBOL_ACTION); |
| 466 break; |
| 467 case CODE_PROPS_RULE_ACTION: |
| 468 self->code = translate_action (self, SC_RULE_ACTION); |
| 469 break; |
| 470 } |
| 471 } |
| 472 |
| 473 void |
| 474 code_scanner_last_string_free (void) |
| 475 { |
| 476 STRING_FREE; |
| 477 } |
| 478 |
| 479 void |
| 480 code_scanner_free (void) |
| 481 { |
| 482 obstack_free (&obstack_for_string, 0); |
| 483 /* Reclaim Flex's buffers. */ |
| 484 yylex_destroy (); |
| 485 } |
OLD | NEW |