1%{ 2/* 3 * FILE: parser.y 4 * AUTH: Michael John Radwin <mjr@acm.org> 5 * 6 * DESC: stubgen grammar description. Portions borrowed from 7 * Newcastle University's Arjuna project (http://arjuna.ncl.ac.uk/), 8 * and Jeff Lee's ANSI Grammar 9 * (ftp://ftp.uu.net/usenet/net.sources/ansi.c.grammar.Z) 10 * This grammar is only a subset of the real C++ language. 11 * 12 * DATE: Thu Aug 15 13:10:06 EDT 1996 13 * $Id: parser.y 10 2002-07-09 12:24:59Z ejakowatz $ 14 * 15 * Copyright (c) 1996-1998 Michael John Radwin 16 * 17 * This program is free software; you can redistribute it and/or modify 18 * it under the terms of the GNU General Public License as published by 19 * the Free Software Foundation; either version 2 of the License, or 20 * (at your option) any later version. 21 * 22 * This program is distributed in the hope that it will be useful, 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * GNU General Public License for more details. 26 * 27 * You should have received a copy of the GNU General Public License 28 * along with this program; if not, write to the Free Software 29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 30 * 31 * -------------------------------------------------------------------- 32 * 33 * $Log: parser.y,v $ 34 * Revision 1.1 2002/07/09 12:24:59 ejakowatz 35 * It is accomplished ... 36 * 37 * Revision 1.1 2001/11/07 10:06:07 ithamar 38 * Added stubgen to CVS 39 * 40 * Revision 1.72 1998/07/07 00:14:06 mradwin 41 * removed extra space from throw_decl, cleaned up memory leak 42 * in ctor skeleton 43 * 44 * Revision 1.71 1998/06/11 14:52:09 mradwin 45 * allow for empty class declarations, such as 46 * class Element {}; 47 * also, differentiate structs from classes with 48 * new STRUCT_KIND tag. 49 * New version: 2.04 50 * 51 * Revision 1.70 1998/05/11 19:49:11 mradwin 52 * Version 2.03 (updated copyright information). 53 * 54 * Revision 1.69 1998/04/07 23:43:34 mradwin 55 * changed error-handling code significantly. 56 * several functions now return a value, and instead of 57 * calling fatal(), we do a YYABORT or YYERROR to get out 58 * of the parsing state. 59 * New version: 2.02. 60 * 61 * Revision 1.68 1998/03/28 02:59:41 mradwin 62 * working on slightly better error recovery; not done yet. 63 * 64 * Revision 1.67 1998/03/28 02:34:56 mradwin 65 * added multi-line function parameters 66 * also changed pointer and reference (* and &) types so there 67 * is no trailing space before the parameter name. 68 * 69 * Revision 1.66 1998/01/12 19:39:11 mradwin 70 * modified rcsid 71 * 72 * Revision 1.65 1997/11/13 22:50:55 mradwin 73 * moved copyright from parser.y to main.c 74 * 75 * Revision 1.64 1997/11/13 22:40:15 mradwin 76 * fixed a silly comment bug 77 * 78 * Revision 1.63 1997/11/13 22:37:31 mradwin 79 * changed char[] to char * to make non-gcc compilers 80 * a little happier. We need to #define const to nothing 81 * for other compilers as well. 82 * 83 * Revision 1.62 97/11/13 21:29:30 21:29:30 mradwin (Michael Radwin) 84 * moved code from parser.y to main.c 85 * 86 * Revision 1.61 1997/11/13 21:10:17 mradwin 87 * renamed stubgen.[ly] to parser.y lexer.l 88 * 89 * Revision 1.60 1997/11/11 04:11:29 mradwin 90 * fixed command-line flags: invalid options now force usgage. 91 * 92 * Revision 1.59 1997/11/11 04:03:56 mradwin 93 * changed version info 94 * 95 * Revision 1.58 1997/11/11 03:54:05 mradwin 96 * fixed a long-standing bug with -b option. a typo was causing 97 * the -b flag to be ignored. 98 * 99 * Revision 1.57 1997/11/11 03:52:06 mradwin 100 * changed fatal() 101 * 102 * Revision 1.56 1997/11/05 03:02:02 mradwin 103 * Modified logging routines. 104 * 105 * Revision 1.55 1997/11/05 02:14:38 mradwin 106 * Made some compiler warnings disappear. 107 * 108 * Revision 1.54 1997/11/01 23:26:13 mradwin 109 * new Revision string and usage info 110 * 111 * Revision 1.53 1997/11/01 23:12:43 mradwin 112 * greatly improved error-recovery. errors no longer spill over 113 * into other files because the yyerror state is properly reset. 114 * 115 * Revision 1.52 1997/10/27 01:14:23 mradwin 116 * fixed constant_value so it supports simple arithmetic. it's 117 * not as robust as full expressions, but this will handle the 118 * char buffer[BUFSIZE + 1] problem. 119 * 120 * Also removed expansion rules that simply did { $$ = $1; } because 121 * that action is implicit anyway. 122 * 123 * Revision 1.51 1997/10/26 23:16:32 mradwin 124 * changed inform_user and fatal functions to use varargs 125 * 126 * Revision 1.50 1997/10/26 22:27:07 mradwin 127 * Fixed this bug: 128 * stubgen dies on the following because the protected section is empty: 129 * 130 * class WidgetCsg : public WidgetLens { 131 * protected: 132 * 133 * public: 134 * virtual ~WidgetCsg() {} 135 * WidgetCsg(); 136 * }; 137 * 138 * Error: 139 * stubgen version 2.0-beta $Revision: 1.1 $. 140 * parse error at line 4, file test.H: 141 * public: 142 * ^ 143 * 144 * Revision 1.49 1997/10/16 19:42:48 mradwin 145 * added support for elipses, static member/array initializers, 146 * and bitfields. 147 * 148 * Revision 1.48 1997/10/16 17:35:39 mradwin 149 * cleaned up usage info 150 * 151 * Revision 1.47 1997/10/16 17:12:59 mradwin 152 * handle extern "C" blocks better now, and support multi-line 153 * macros. still need error-checking. 154 * 155 * Revision 1.46 1997/10/15 22:09:06 mradwin 156 * changed tons of names. stubelem -> sytaxelem, 157 * stubin -> infile, stubout -> outfile, stublog -> logfile. 158 * 159 * Revision 1.45 1997/10/15 21:33:36 mradwin 160 * fixed up function_hdr 161 * 162 * Revision 1.44 1997/10/15 21:33:02 mradwin 163 * *** empty log message *** 164 * 165 * Revision 1.43 1997/10/15 17:42:37 mradwin 166 * added support for 'extern "C" { ... }' blocks. 167 * 168 * Revision 1.42 1997/09/26 20:59:18 mradwin 169 * now allow "struct foobar *f" to appear in a parameter 170 * list or as a variable decl. Had to remove the 171 * class_or_struct rule and blow up the class_specifier 172 * description. 173 * 174 * Revision 1.41 1997/09/26 19:02:18 mradwin 175 * fixed memory leak involving template decls in skeleton code. 176 * Leads me to believe that skel_elemcmp() is flawed, because 177 * it may rely in parent->templ info. 178 * 179 * Revision 1.40 1997/09/26 18:44:22 mradwin 180 * changed parameter handing from char *'s to an argument type 181 * to facilitate comparisons between skeleton code 182 * and header code. Now we can correctly recognize different 183 * parameter names while still maintaining the same signature. 184 * 185 * Revision 1.39 1997/09/26 00:47:29 mradwin 186 * added better base type support -- recognize things like 187 * "long long" and "short int" now. 188 * 189 * Revision 1.38 1997/09/19 18:16:37 mradwin 190 * allowed an instance name to come after a class, struct, 191 * union, or enum. This improves parseability of typedefs 192 * commonly found in c header files, although true typedefs are 193 * not understood. 194 * 195 * Revision 1.37 1997/09/15 22:38:28 mradwin 196 * did more revision on the SGDEBUG stuff 197 * 198 * Revision 1.36 1997/09/15 19:05:26 mradwin 199 * allow logging to be compiled out by turning off SGDEBUG 200 * 201 * Revision 1.35 1997/09/12 00:58:43 mradwin 202 * duh, silly me. messed up compilation. 203 * 204 * Revision 1.34 1997/09/12 00:57:49 mradwin 205 * Revision string inserted in usage 206 * 207 * Revision 1.33 1997/09/12 00:51:19 mradwin 208 * string copyright added to code for binary copyright. 209 * 210 * Revision 1.32 1997/09/12 00:47:21 mradwin 211 * some more compactness of grammar with parameter_list_opt 212 * and also ampersand_opt 213 * 214 * Revision 1.31 1997/09/12 00:26:19 mradwin 215 * better template support, but still poor 216 * 217 * Revision 1.30 1997/09/08 23:24:51 mradwin 218 * changes to error-handling code. 219 * also got rid of the %type <flag> for the top-level rules 220 * 221 * Revision 1.30 1997/09/08 23:20:02 mradwin 222 * some error reporting changes and default values for top-level 223 * grammar stuff. 224 * 225 * Revision 1.29 1997/09/08 17:54:24 mradwin 226 * cleaned up options and usage info. 227 * 228 * Revision 1.28 1997/09/05 19:38:04 mradwin 229 * changed options for .ext instead of -l or -x 230 * 231 * Revision 1.27 1997/09/05 19:17:06 mradwin 232 * works for scanning old versions, except for parameter 233 * names that differ between .H and .C files. 234 * 235 * Revision 1.26 1997/09/05 16:34:36 mradwin 236 * GPL-ized code. 237 * 238 * Revision 1.25 1997/09/05 16:11:44 mradwin 239 * some simple cleanup before GPL-izing the code 240 * 241 * Revision 1.24 1997/09/04 19:50:34 mradwin 242 * whoo-hoo! by blowing up the description 243 * exponentially, it works! 244 * 245 * Revision 1.23 1997/03/20 16:05:41 mjr 246 * renamed syntaxelem to syntaxelem_t, cleaned up throw_decl 247 * 248 * Revision 1.22 1996/10/02 15:16:57 mjr 249 * using pathname.h instead of libgen.h 250 * 251 * Revision 1.21 1996/09/12 14:44:49 mjr 252 * Added throw decl recognition (great, another 4 bytes in syntaxelem) 253 * and cleaned up the grammar so that const_opt appears in far fewer 254 * places. const_opt is by default 0 as well, so we don't need to 255 * pass it as an arg to new_elem(). 256 * 257 * I also added a fix to a potential bug with the MINIT and INLIN 258 * exclusive start states. I think they could have been confused 259 * by braces within comments, so now I'm grabbing comments in those 260 * states as well. 261 * 262 * Revision 1.20 1996/09/12 04:55:22 mjr 263 * changed expand strategy. Don't expand while parsing now; 264 * enqueue as we go along and expand at the end. Eventually 265 * we'll need to provide similar behavior for when we parse 266 * .C files 267 * 268 * Revision 1.19 1996/09/12 03:46:10 mjr 269 * No concrete changes in code. Just added some sanity by 270 * factoring out code into util.[ch] and putting some prototypes 271 * that were in table.h into stubgen.y where they belong. 272 * 273 * Revision 1.18 1996/09/06 14:32:48 mjr 274 * defined the some_KIND constants for clarity, and made 275 * expandClass return immediately if it was give something other 276 * than a CLASS_KIND element. 277 * 278 * Revision 1.17 1996/09/06 14:05:44 mjr 279 * Almost there with expanded operator goodies. Still need 280 * to get OPERATOR type_name to work. 281 * 282 * Revision 1.16 1996/09/04 22:28:09 mjr 283 * nested classes work and default arguments are now removed 284 * from the parameter lists. 285 * 286 * Revision 1.15 1996/09/04 20:01:57 mjr 287 * non-functional expanded code. needs work. 288 * 289 * Revision 1.14 1996/09/01 21:29:34 mjr 290 * put the expanded_operator code back in as a useless rule. 291 * oughta think about fixing it up if possible 292 * 293 * Revision 1.13 1996/09/01 20:59:48 mjr 294 * Added collectMemberInitList() function, which is similar 295 * to collectInlineDef() and also the exclusive state MINIT 296 * 297 * Revision 1.12 1996/08/23 05:09:19 mjr 298 * fixed up some more portability things 299 * 300 * Revision 1.11 1996/08/22 02:43:47 mjr 301 * added parse error message (using O'Reilly p. 274) 302 * 303 * Revision 1.10 1996/08/21 18:33:50 mjr 304 * added support for template instantiation in the type_name 305 * rule. surprisingly it didn't cause any shift/reduce conflicts. 306 * 307 * Revision 1.9 1996/08/21 17:40:56 mjr 308 * added some cpp directives for porting to WIN32 309 * 310 * Revision 1.8 1996/08/21 00:00:19 mjr 311 * approaching stability and usability. command line arguments 312 * are handled now and the fopens and fcloses appear to work. 313 * 314 * Revision 1.7 1996/08/20 20:44:23 mjr 315 * added initial support for optind but it is incomplete. 316 * 317 * Revision 1.6 1996/08/19 17:14:59 mjr 318 * misordered args, fixed bug 319 * 320 * Revision 1.5 1996/08/19 17:11:41 mjr 321 * RCS got confused with the RCS-style header goodies. 322 * got it cleaned up now. 323 * 324 * Revision 1.4 1996/08/19 17:01:33 mjr 325 * Removed the expanded code checking and added 326 * lots of code that duplicates what stubgen.pl did. 327 * still need options pretty badly 328 * 329 * Revision 1.3 1996/08/17 23:21:10 mjr 330 * added the expanded operator code, cleaned up tabs. 331 * consider putting all of the expanded code in another 332 * grammar - this one is getting cluttered. 333 * 334 */ 335%} 336 337%{ 338#include "table.h" 339#include "util.h" 340#include <string.h> 341#include <stdlib.h> 342#include <stdio.h> 343 344#ifdef WIN32 345#include <malloc.h> /* defintion of alloca */ 346#include "getopt.h" /* use GNU getopt */ 347#endif /* WIN32 */ 348 349#ifndef WIN32 350#include <pwd.h> 351#endif /* WIN32 */ 352 353/* defined in lexer.l */ 354extern int collectInlineDef(); 355extern int collectMemberInitList(); 356 357/* defined here in parser.y */ 358static int error_recovery(); 359static int yyerror(char *); 360static const char rcsid[] = "$Id: parser.y 10 2002-07-09 12:24:59Z ejakowatz $"; 361 362/* defined in main.c */ 363extern FILE *outfile; 364extern char *currentFile; 365extern int lineno; 366 367%} 368 369%union { 370 char *string; 371 syntaxelem_t *elt; 372 arg_t *arg; 373 int flag; 374} 375 376%token <string> IDENTIFIER CONSTANT STRING_LITERAL 377%token <string> CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE VOID 378%token NEW DELETE TEMPLATE THROW 379 380%token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP 381%token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN 382%token SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN 383%token XOR_ASSIGN OR_ASSIGN CLCL MEM_PTR_OP 384 385%token FRIEND OPERATOR CONST CLASS STRUCT UNION ENUM 386%token PROTECTED PRIVATE PUBLIC EXTERN ELIPSIS 387 388%type <string> simple_type_name simple_signed_type non_reference_type 389%type <string> scoped_identifier pointer asterisk 390%type <string> type_name binary_operator 391%type <string> assignment_operator unary_operator any_operator 392%type <string> variable_specifier_list union_specifier 393%type <string> constant_value multiple_variable_specifier 394%type <string> enum_specifier enumerator_list enumerator 395%type <string> template_specifier template_arg template_arg_list 396%type <string> template_instance_arg template_instance_arg_list 397%type <string> throw_decl throw_list variable_name bitfield_savvy_identifier 398%type <string> primary_expression expression 399%type <string> multiplicative_expression additive_expression 400%type <flag> const_opt ampersand_opt 401%type <elt> class_specifier 402%type <elt> member_func_specifier function_specifier constructor 403%type <elt> destructor member_specifier member member_with_access 404%type <elt> mem_type_specifier member_or_error 405%type <elt> member_list member_list_opt 406%type <elt> member_func_inlined type_specifier overloaded_op_specifier 407%type <elt> member_func_skel member_func_skel_spec 408%type <elt> constructor_skeleton destructor_skeleton 409%type <elt> overloaded_op_skeleton function_skeleton 410%type <arg> variable_or_parameter variable_specifier 411%type <arg> parameter_list parameter_list_opt unnamed_parameter 412 413 414%start translation_unit 415%% 416 417translation_unit 418 : declaration 419 | translation_unit declaration 420 ; 421 422declaration 423 : declaration_specifiers ';' 424 | EXTERN STRING_LITERAL compound_statement 425{ 426 log_printf("IGNORING extern \"C\" { ... } block.\n"); 427 free($2); 428} 429 | member_func_inlined 430{ 431 $1->kind = INLINED_KIND; 432 log_printf("\nBEGIN matched dec : m_f_i rule --"); 433 print_se($1); 434 log_printf("END matched dec : m_f_i rule\n"); 435} 436 | function_skeleton 437{ 438 $1->kind = SKEL_KIND; 439 log_printf("\nBEGIN matched dec : function_skeleton rule --"); 440 print_se($1); 441 enqueue_skeleton($1); 442 log_printf("END matched dec : function_skeleton rule\n"); 443} 444 | ';' 445 | error 446{ 447 log_printf("declaration : error. Attempting to recover...\n"); 448 yyerrok; 449 yyclearin; 450 if (error_recovery() != 0) { 451 log_printf("ERROR recovery could not complete -- YYABORT.\n"); 452 YYABORT; 453 } 454 log_printf("ERROR recovery complete.\n"); 455} 456 ; 457 458declaration_specifiers 459 : member_specifier 460{ 461 /* the name of the rule "member_specifier" might be misleading, but 462 * this is either a class, struct, union, enum, global var, global 463 * prototype, etc.. */ 464 if ($1->kind == CLASS_KIND || $1->kind == STRUCT_KIND) { 465 enqueue_class($1); 466 } else { 467 log_printf("\nIGNORING dec_spec : mem_spec (%s) --", 468 string_kind($1->kind)); 469 print_se($1); 470 log_printf("END IGNORING dec_spec : mem_spec (%s)\n", 471 string_kind($1->kind)); 472 } 473} 474 | forward_decl 475 ; 476 477type_specifier 478 : union_specifier 479{ 480 /* ret_type, name, args, kind */ 481 syntaxelem_t *elem = new_elem(strdup(""), $1, NULL, IGNORE_KIND); 482/* print_se(elem); */ 483 $$ = elem; 484} 485 | enum_specifier 486{ 487 /* ret_type, name, args, kind */ 488 syntaxelem_t *elem = new_elem(strdup(""), $1, NULL, IGNORE_KIND); 489/* print_se(elem); */ 490 $$ = elem; 491} 492 | class_specifier 493 ; 494 495ampersand_opt 496 : /* nothing */ { $$ = 0; } 497 | '&' { $$ = 1; } 498 ; 499 500type_name 501 : non_reference_type ampersand_opt 502{ 503 char *tmp_str = (char *) malloc(strlen($1) + ($2 ? 2 : 0) + 1); 504 strcpy(tmp_str, $1); 505 if ($2) 506 strcat(tmp_str, " &"); 507 free($1); 508 $$ = tmp_str; 509} 510 | CONST non_reference_type ampersand_opt 511{ 512 char *tmp_str = (char *) malloc(strlen($2) + ($3 ? 2 : 0) + 7); 513 sprintf(tmp_str, "const %s%s", $2, ($3 ? " &" : "")); 514 free($2); 515 $$ = tmp_str; 516} 517 ; 518 519forward_decl 520 : CLASS IDENTIFIER { free($2); } 521 | CLASS scoped_identifier { free($2); } 522 | STRUCT IDENTIFIER { free($2); } 523 | STRUCT scoped_identifier { free($2); } 524 ; 525 526non_reference_type 527 : scoped_identifier 528 | IDENTIFIER 529 | STRUCT IDENTIFIER 530{ 531 char *tmp_str = (char *) malloc(strlen($2) + 8); 532 strcpy(tmp_str, "struct "); 533 strcat(tmp_str, $2); 534 free($2); 535 $$ = tmp_str; 536} 537 | scoped_identifier '<' template_instance_arg_list '>' 538{ 539 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 3); 540 sprintf(tmp_str, "%s<%s>", $1, $3); 541 free($1); 542 free($3); 543 $$ = tmp_str; 544} 545 | IDENTIFIER '<' template_instance_arg_list '>' 546{ 547 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 3); 548 sprintf(tmp_str, "%s<%s>", $1, $3); 549 free($1); 550 free($3); 551 $$ = tmp_str; 552} 553 | scoped_identifier '<' template_instance_arg_list '>' pointer 554{ 555 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + strlen($5) + 4); 556 sprintf(tmp_str, "%s<%s> %s", $1, $3, $5); 557 free($1); 558 free($3); 559 free($5); 560 $$ = tmp_str; 561} 562 | IDENTIFIER '<' template_instance_arg_list '>' pointer 563{ 564 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + strlen($5) + 4); 565 sprintf(tmp_str, "%s<%s> %s", $1, $3, $5); 566 free($1); 567 free($3); 568 free($5); 569 $$ = tmp_str; 570} 571 | scoped_identifier pointer 572{ 573 char *tmp_str = (char *) malloc(strlen($1) + strlen($2) + 2); 574 sprintf(tmp_str, "%s %s", $1, $2); 575 free($1); 576 free($2); 577 $$ = tmp_str; 578} 579 | IDENTIFIER pointer 580{ 581 char *tmp_str = (char *) malloc(strlen($1) + strlen($2) + 2); 582 sprintf(tmp_str, "%s %s", $1, $2); 583 free($1); 584 free($2); 585 $$ = tmp_str; 586} 587 | STRUCT IDENTIFIER pointer 588{ 589 char *tmp_str = (char *) malloc(strlen($2) + strlen($3) + 9); 590 sprintf(tmp_str, "struct %s %s", $2, $3); 591 free($2); 592 free($3); 593 $$ = tmp_str; 594} 595 | simple_signed_type 596 | simple_signed_type pointer 597{ 598 char *tmp_str = (char *) malloc(strlen($1) + strlen($2) + 2); 599 sprintf(tmp_str, "%s %s", $1, $2); 600 free($1); 601 free($2); 602 $$ = tmp_str; 603} 604 ; 605 606simple_signed_type 607 : simple_type_name 608 | SIGNED simple_type_name 609{ 610 char *tmp_str = (char *) malloc(strlen($2) + 8); 611 strcpy(tmp_str,"signed "); 612 strcat(tmp_str, $2); 613 free($1); 614 free($2); 615 $$ = tmp_str; 616} 617 | UNSIGNED simple_type_name 618{ 619 char *tmp_str = (char *) malloc(strlen($2) + 10); 620 strcpy(tmp_str,"unsigned "); 621 strcat(tmp_str, $2); 622 free($1); 623 free($2); 624 $$ = tmp_str; 625} 626 ; 627 628simple_type_name 629 : CHAR 630 | SHORT 631 | SHORT INT 632{ 633 $$ = strdup("short int"); 634 free($1); 635 free($2); 636} 637 | INT 638 | LONG 639 | LONG INT 640{ 641 $$ = strdup("long int"); 642 free($1); 643 free($2); 644} 645 | LONG LONG 646{ 647 $$ = strdup("long long"); 648 free($1); 649 free($2); 650} 651 | LONG LONG INT 652{ 653 $$ = strdup("long long int"); 654 free($1); 655 free($2); 656 free($3); 657} 658 | UNSIGNED 659 | FLOAT 660 | DOUBLE 661 | VOID 662 ; 663 664scoped_identifier 665 : IDENTIFIER CLCL IDENTIFIER 666{ 667 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 3); 668 sprintf(tmp_str, "%s::%s", $1, $3); 669 free($1); 670 free($3); 671 $$ = tmp_str; 672} 673 | scoped_identifier CLCL IDENTIFIER 674{ 675 /* control-Y programming! */ 676 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 3); 677 sprintf(tmp_str, "%s::%s", $1, $3); 678 free($1); 679 free($3); 680 $$ = tmp_str; 681} 682 ; 683 684pointer 685 : asterisk 686 | pointer asterisk 687{ 688 char *tmp_str = (char *) malloc(strlen($1) + strlen($2) + 1); 689 strcpy(tmp_str,$1); 690 strcat(tmp_str,$2); 691 free($1); 692 free($2); 693 $$ = tmp_str; 694} 695 ; 696 697asterisk 698 : '*' { $$ = strdup("*"); } 699 | '*' CONST { $$ = strdup("*const "); } 700 ; 701 702variable_or_parameter 703 : type_name bitfield_savvy_identifier 704{ 705 arg_t *new_arg = (arg_t *) malloc(sizeof(arg_t)); 706 new_arg->type = $1; 707 new_arg->name = $2; 708 new_arg->array = NULL; 709 new_arg->next = NULL; 710 $$ = new_arg; 711} 712 | type_name scoped_identifier 713{ 714 arg_t *new_arg = (arg_t *) malloc(sizeof(arg_t)); 715 new_arg->type = $1; 716 new_arg->name = $2; 717 new_arg->array = NULL; 718 new_arg->next = NULL; 719 $$ = new_arg; 720} 721 | variable_or_parameter '[' constant_value ']' 722{ 723 char *old_array = $1->array; 724 int old_len = old_array ? strlen(old_array) : 0; 725 $1->array = (char *) malloc(strlen($3) + old_len + 3); 726 sprintf($1->array, "%s[%s]", old_array ? old_array : "", $3); 727 free($3); 728 if (old_array) 729 free(old_array); 730 $$ = $1; 731} 732 | variable_or_parameter '[' ']' 733{ 734 char *old_array = $1->array; 735 int old_len = old_array ? strlen(old_array) : 0; 736 $1->array = (char *) malloc(old_len + 3); 737 sprintf($1->array, "%s[]", old_array ? old_array : ""); 738 if (old_array) 739 free(old_array); 740 $$ = $1; 741} 742 ; 743 744bitfield_savvy_identifier 745 : IDENTIFIER 746 | IDENTIFIER ':' CONSTANT { free($3); $$ = $1;} 747 ; 748 749variable_name 750 : bitfield_savvy_identifier 751 | pointer IDENTIFIER 752{ 753 char *tmp_str = (char *) malloc(strlen($1) + strlen($2) + 2); 754 sprintf(tmp_str, "%s %s", $1, $2); 755 free($1); 756 free($2); 757 $$ = tmp_str; 758} 759 | variable_name '[' constant_value ']' 760{ 761 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 3); 762 sprintf(tmp_str, "%s[%s]", $1, $3); 763 free($1); 764 free($3); 765 $$ = tmp_str; 766} 767 | variable_name '[' ']' 768{ 769 char *tmp_str = (char *) malloc(strlen($1) + 3); 770 strcpy(tmp_str, $1); 771 strcat(tmp_str, "[]"); 772 free($1); 773 $$ = tmp_str; 774} 775 ; 776 777variable_specifier 778 : variable_or_parameter 779 | EXTERN variable_or_parameter { $$ = $2; } 780 | variable_or_parameter '=' constant_value 781{ 782 free($3); 783 $$ = $1; 784} 785 ; 786 787multiple_variable_specifier 788 : variable_specifier 789{ 790 $$ = args_to_string($1, 0); 791 free_args($1); 792} 793 | multiple_variable_specifier ',' variable_name 794{ 795 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 3); 796 sprintf(tmp_str, "%s, %s", $1, $3); 797 free($1); 798 free($3); 799 $$ = tmp_str; 800} 801 ; 802 803variable_specifier_list 804 : multiple_variable_specifier ';' 805{ 806 char *tmp_str = (char *) malloc(strlen($1) + 2); 807 sprintf(tmp_str, "%s;", $1); 808 free($1); 809 $$ = tmp_str; 810} 811 | variable_specifier_list multiple_variable_specifier ';' 812{ 813 char *tmp_str = (char *) malloc(strlen($1) + strlen($2) + 3); 814 sprintf(tmp_str, "%s\n%s;", $1, $2); 815 free($1); 816 free($2); 817 $$ = tmp_str; 818} 819 ; 820 821parameter_list_opt 822 : /* nothing */ 823{ 824 $$ = NULL; 825} 826 | parameter_list 827{ 828 $$ = reverse_arg_list($1); 829} 830 | parameter_list ',' ELIPSIS 831{ 832 arg_t *new_arg = (arg_t *) malloc(sizeof(arg_t)); 833 new_arg->type = strdup("..."); 834 new_arg->name = NULL; 835 new_arg->array = NULL; 836 new_arg->next = $1; 837 $$ = reverse_arg_list(new_arg); 838} 839 | ELIPSIS 840{ 841 arg_t *new_arg = (arg_t *) malloc(sizeof(arg_t)); 842 new_arg->type = strdup("..."); 843 new_arg->name = NULL; 844 new_arg->array = NULL; 845 new_arg->next = NULL; 846 $$ = new_arg; 847} 848 ; 849 850parameter_list 851 : variable_specifier 852 | unnamed_parameter 853 | parameter_list ',' variable_specifier 854{ 855 $3->next = $1; 856 $$ = $3; 857} 858 | parameter_list ',' unnamed_parameter 859{ 860 $3->next = $1; 861 $$ = $3; 862} 863 ; 864 865unnamed_parameter 866 : type_name 867{ 868 arg_t *new_arg = (arg_t *) malloc(sizeof(arg_t)); 869 new_arg->type = $1; 870 new_arg->name = NULL; 871 new_arg->array = NULL; 872 new_arg->next = NULL; 873 $$ = new_arg; 874} 875 | type_name '=' constant_value 876{ 877 arg_t *new_arg = (arg_t *) malloc(sizeof(arg_t)); 878 new_arg->type = $1; 879 new_arg->name = NULL; 880 new_arg->array = NULL; 881 new_arg->next = NULL; 882 free($3); 883 $$ = new_arg; 884} 885 | unnamed_parameter '[' constant_value ']' 886{ 887 char *old_array = $1->array; 888 int old_len = old_array ? strlen(old_array) : 0; 889 $1->array = (char *) malloc(strlen($3) + old_len + 3); 890 sprintf($1->array, "%s[%s]", old_array ? old_array : "", $3); 891 free($3); 892 if (old_array) 893 free(old_array); 894 $$ = $1; 895} 896 | unnamed_parameter '[' ']' 897{ 898 char *old_array = $1->array; 899 int old_len = old_array ? strlen(old_array) : 0; 900 $1->array = (char *) malloc(old_len + 3); 901 sprintf($1->array, "%s[]", old_array ? old_array : ""); 902 if (old_array) 903 free(old_array); 904 $$ = $1; 905} 906 ; 907 908function_skeleton 909 : member_func_skel compound_statement 910 | constructor_skeleton ':' 911 { if (collectMemberInitList() != 0) YYERROR; } compound_statement 912 | template_specifier member_func_skel compound_statement 913{ 914 /* I think this is the correct behavior, but skel_elemcmp is wrong */ 915 /* $2->templ = $1; */ 916 free($1); 917 $$ = $2; 918} 919 | template_specifier constructor_skeleton ':' 920 { if (collectMemberInitList() != 0) YYERROR; } compound_statement 921{ 922 /* I think this is the correct behavior, but skel_elemcmp is wrong */ 923 /* $2->templ = $1; */ 924 free($1); 925 $$ = $2; 926} 927 ; 928 929member_func_inlined 930 : member_func_specifier compound_statement 931 | constructor ':' 932 { if (collectMemberInitList() != 0) YYERROR; } compound_statement 933 ; 934 935member_func_skel 936 : member_func_skel_spec const_opt throw_decl 937{ 938 $1->const_flag = $2; 939 $1->throw_decl = $3; 940 $$ = $1; 941} 942 | constructor_skeleton 943 | destructor_skeleton 944 ; 945 946member_func_specifier 947 : function_specifier const_opt throw_decl 948{ 949 $1->const_flag = $2; 950 $1->throw_decl = $3; 951 $$ = $1; 952} 953 | constructor 954 | destructor 955 ; 956 957 958member_func_skel_spec 959 : type_name scoped_identifier '(' parameter_list_opt ')' 960{ 961 /* ret_type, name, args, kind */ 962 syntaxelem_t *elem = new_elem($1, $2, $4, FUNC_KIND); 963/* print_se(elem); */ 964 $$ = elem; 965} 966 | type_name IDENTIFIER '<' template_instance_arg_list '>' CLCL IDENTIFIER '(' parameter_list_opt ')' 967{ 968 /* ret_type, name, args, kind */ 969 syntaxelem_t *elem = new_elem($1, 970 (char *) malloc(strlen($2) + strlen($4) + strlen($7) + 5), 971 $9, FUNC_KIND); 972 sprintf(elem->name,"%s<%s>::%s", $2, $4, $7); 973 free($2); 974 free($4); 975 free($7); 976 $$ = elem; 977} 978 | overloaded_op_skeleton 979 ; 980 981 982 983function_specifier 984 : type_name IDENTIFIER '(' parameter_list_opt ')' 985{ 986 /* ret_type, name, args, kind */ 987 syntaxelem_t *elem = new_elem($1, $2, $4, FUNC_KIND); 988 print_se(elem); 989 $$ = elem; 990} 991 | overloaded_op_specifier 992 ; 993 994overloaded_op_skeleton 995 : type_name scoped_identifier CLCL OPERATOR any_operator '(' parameter_list_opt ')' 996{ 997 /* ret_type, name, args, kind */ 998 syntaxelem_t *elem = new_elem($1, (char *)malloc(strlen($2) + strlen($5) + 12), 999 $7, FUNC_KIND); 1000 sprintf(elem->name, "%s::operator%s", $2, $5); 1001 free($2); 1002 free($5); 1003/* print_se(elem); */ 1004 $$ = elem; 1005} 1006 | scoped_identifier CLCL OPERATOR type_name '(' ')' 1007{ 1008 /* ret_type, name, args, kind */ 1009 syntaxelem_t *elem = new_elem(strdup(""), 1010 (char *)malloc(strlen($1) + strlen($4) + 13), 1011 NULL, FUNC_KIND); 1012 sprintf(elem->name, "%s::operator %s", $1, $4); 1013 free($1); 1014 free($4); 1015/* print_se(elem); */ 1016 $$ = elem; 1017} 1018 | type_name IDENTIFIER CLCL OPERATOR any_operator '(' parameter_list_opt ')' 1019{ 1020 /* ret_type, name, args, kind */ 1021 syntaxelem_t *elem = new_elem($1, (char *)malloc(strlen($2) + strlen($5) + 12), 1022 $7, FUNC_KIND); 1023 sprintf(elem->name, "%s::operator%s", $2, $5); 1024 free($2); 1025 free($5); 1026/* print_se(elem); */ 1027 $$ = elem; 1028} 1029 | IDENTIFIER CLCL OPERATOR type_name '(' ')' 1030{ 1031 /* ret_type, name, args, kind */ 1032 syntaxelem_t *elem = new_elem(strdup(""), 1033 (char *)malloc(strlen($1) + strlen($4) + 13), 1034 NULL, FUNC_KIND); 1035 sprintf(elem->name, "%s::operator %s", $1, $4); 1036 free($1); 1037 free($4); 1038/* print_se(elem); */ 1039 $$ = elem; 1040} 1041 ; 1042 1043overloaded_op_specifier 1044 : type_name OPERATOR any_operator '(' parameter_list_opt ')' 1045{ 1046 /* ret_type, name, args, kind */ 1047 syntaxelem_t *elem = new_elem($1, (char *)malloc(strlen($3) + 9), 1048 $5, FUNC_KIND); 1049 sprintf(elem->name, "operator%s", $3); 1050 free($3); 1051 print_se(elem); 1052 $$ = elem; 1053} 1054 | OPERATOR type_name '(' ')' 1055{ 1056 /* ret_type, name, args, kind */ 1057 syntaxelem_t *elem = new_elem(strdup(""), (char *)malloc(strlen($2) + 10), 1058 NULL, FUNC_KIND); 1059 sprintf(elem->name, "operator %s", $2); 1060 free($2); 1061 print_se(elem); 1062 $$ = elem; 1063} 1064 ; 1065 1066const_opt 1067 : /* nothing */ { $$ = 0; } 1068 | CONST { $$ = 1; } 1069 ; 1070 1071throw_decl 1072 : /* nothing */ { $$ = NULL; } 1073 | THROW '(' throw_list ')' 1074{ 1075 char *tmp_str = (char *) malloc(strlen($3) + 8); 1076 sprintf(tmp_str, "throw(%s)", $3); 1077 free($3); 1078 $$ = tmp_str; 1079} 1080 ; 1081 1082throw_list 1083 : type_name 1084 | throw_list ',' type_name 1085{ 1086 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 3); 1087 sprintf(tmp_str, "%s, %s", $1, $3); 1088 free($1); 1089 free($3); 1090 $$ = tmp_str; 1091} 1092 ; 1093 1094destructor 1095 : '~' IDENTIFIER '(' ')' 1096{ 1097 /* ret_type, name, args, kind */ 1098 syntaxelem_t *elem = new_elem(strdup(""), (char *) malloc(strlen($2) + 2), 1099 NULL, FUNC_KIND); 1100 sprintf(elem->name,"~%s", $2); 1101 free($2); 1102/* print_se(elem); */ 1103 $$ = elem; 1104} 1105 ; 1106 1107destructor_skeleton 1108 : scoped_identifier CLCL '~' IDENTIFIER '(' ')' 1109{ 1110 /* ret_type, name, args, kind */ 1111 syntaxelem_t *elem = new_elem(strdup(""), 1112 (char *) malloc(strlen($1) + strlen($4) + 4), 1113 NULL, FUNC_KIND); 1114 sprintf(elem->name,"%s::~%s", $1, $4); 1115 free($1); 1116 free($4); 1117/* print_se(elem); */ 1118 $$ = elem; 1119} 1120 | IDENTIFIER CLCL '~' IDENTIFIER '(' ')' 1121{ 1122 /* ret_type, name, args, kind */ 1123 syntaxelem_t *elem = new_elem(strdup(""), 1124 (char *) malloc(strlen($1) + strlen($4) + 4), 1125 NULL, FUNC_KIND); 1126 sprintf(elem->name,"%s::~%s", $1, $4); 1127 free($1); 1128 free($4); 1129/* print_se(elem); */ 1130 $$ = elem; 1131} 1132 | IDENTIFIER '<' template_instance_arg_list '>' CLCL '~' IDENTIFIER '(' ')' 1133{ 1134 /* ret_type, name, args, kind */ 1135 syntaxelem_t *elem = new_elem(strdup(""), 1136 (char *) malloc(strlen($1) + strlen($3) + strlen($7) + 6), 1137 NULL, FUNC_KIND); 1138 sprintf(elem->name,"%s<%s>::~%s", $1, $3, $7); 1139 free($1); 1140 free($3); 1141 free($7); 1142 $$ = elem; 1143} 1144 | scoped_identifier '<' template_instance_arg_list '>' CLCL '~' IDENTIFIER '(' ')' 1145{ 1146 /* ret_type, name, args, kind */ 1147 syntaxelem_t *elem = new_elem(strdup(""), 1148 (char *) malloc(strlen($1) + strlen($3) + strlen($7) + 6), 1149 NULL, FUNC_KIND); 1150 sprintf(elem->name,"%s<%s>::~%s", $1, $3, $7); 1151 free($1); 1152 free($3); 1153 free($7); 1154 $$ = elem; 1155} 1156 ; 1157 1158constructor 1159 : IDENTIFIER '(' parameter_list_opt ')' throw_decl 1160{ 1161 /* ret_type, name, args, kind */ 1162 syntaxelem_t *elem = new_elem(strdup(""), $1, $3, FUNC_KIND); 1163 elem->throw_decl = $5; 1164/* print_se(elem); */ 1165 $$ = elem; 1166} 1167 ; 1168 1169constructor_skeleton 1170 : scoped_identifier '(' parameter_list_opt ')' throw_decl 1171{ 1172 /* ret_type, name, args, kind */ 1173 syntaxelem_t *elem = new_elem(strdup(""), $1, $3, FUNC_KIND); 1174 elem->throw_decl = $5; 1175/* print_se(elem); */ 1176 $$ = elem; 1177} 1178 | IDENTIFIER '<' template_instance_arg_list '>' CLCL IDENTIFIER '(' parameter_list_opt ')' throw_decl 1179{ 1180 /* ret_type, name, args, kind */ 1181 syntaxelem_t *elem = new_elem(strdup(""), 1182 (char *) malloc(strlen($1) + strlen($3) + strlen($6) + 5), 1183 $8, FUNC_KIND); 1184 sprintf(elem->name,"%s<%s>::%s", $1, $3, $6); 1185 free($1); 1186 free($3); 1187 free($6); 1188 elem->throw_decl = $10; 1189 $$ = elem; 1190} 1191 | scoped_identifier '<' template_instance_arg_list '>' CLCL IDENTIFIER '(' parameter_list_opt ')' throw_decl 1192{ 1193 /* ret_type, name, args, kind */ 1194 syntaxelem_t *elem = new_elem(strdup(""), 1195 (char *) malloc(strlen($1) + strlen($3) + strlen($6) + 5), 1196 $8, FUNC_KIND); 1197 sprintf(elem->name,"%s<%s>::%s", $1, $3, $6); 1198 free($1); 1199 free($3); 1200 free($6); 1201 elem->throw_decl = $10; 1202 $$ = elem; 1203} 1204 ; 1205 1206compound_statement 1207 : '{' { if (collectInlineDef() != 0) YYERROR; } '}' 1208 ; 1209 1210enum_specifier 1211 : ENUM '{' enumerator_list '}' 1212{ 1213 char *tmp_str = (char *) malloc(strlen($3) + 10); 1214 sprintf(tmp_str, "enum { %s }", $3); 1215 free($3); 1216 $$ = tmp_str; 1217} 1218 | ENUM IDENTIFIER '{' enumerator_list '}' 1219{ 1220 char *tmp_str = (char *) malloc(strlen($2) + strlen($4) + 11); 1221 sprintf(tmp_str, "enum %s { %s }", $2, $4); 1222 free($2); 1223 free($4); 1224 $$ = tmp_str; 1225} 1226 | ENUM IDENTIFIER 1227{ 1228 char *tmp_str = (char *) malloc(strlen($2) + 6); 1229 sprintf(tmp_str, "enum %s", $2); 1230 free($2); 1231 $$ = tmp_str; 1232} 1233 ; 1234 1235enumerator_list 1236 : enumerator 1237 | enumerator_list ',' enumerator 1238{ 1239 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 3); 1240 sprintf(tmp_str, "%s, %s", $1, $3); 1241 free($1); 1242 free($3); 1243 $$ = tmp_str; 1244} 1245 ; 1246 1247enumerator 1248 : IDENTIFIER 1249 | IDENTIFIER '=' constant_value 1250{ 1251 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 2); 1252 sprintf(tmp_str, "%s=%s", $1, $3); 1253 free($1); 1254 free($3); 1255 $$ = tmp_str; 1256} 1257 ; 1258 1259access_specifier_opt 1260 : /* nothing */ 1261 | access_specifier 1262 ; 1263 1264access_specifier_list 1265 : access_specifier ':' 1266 | access_specifier_list access_specifier ':' 1267 ; 1268 1269access_specifier 1270 : PUBLIC 1271 | PRIVATE 1272 | PROTECTED 1273 ; 1274 1275unary_operator 1276 : '&' { $$ = strdup("&"); } 1277 | '*' { $$ = strdup("*"); } 1278 | '+' { $$ = strdup("+"); } 1279 | '-' { $$ = strdup("-"); } 1280 | '~' { $$ = strdup("~"); } 1281 | '!' { $$ = strdup("!"); } 1282 ; 1283 1284binary_operator 1285 : '/' { $$ = strdup("/"); } 1286 | '%' { $$ = strdup("%"); } 1287 | '^' { $$ = strdup("^"); } 1288 | '|' { $$ = strdup("|"); } 1289 | '<' { $$ = strdup("<"); } 1290 | '>' { $$ = strdup(">"); } 1291 | ',' { $$ = strdup(","); } 1292 ; 1293 1294assignment_operator 1295 : '=' { $$ = strdup("="); } 1296 | MUL_ASSIGN { $$ = strdup("*="); } 1297 | DIV_ASSIGN { $$ = strdup("/="); } 1298 | MOD_ASSIGN { $$ = strdup("%="); } 1299 | ADD_ASSIGN { $$ = strdup("+="); } 1300 | SUB_ASSIGN { $$ = strdup("-="); } 1301 | LEFT_ASSIGN { $$ = strdup("<<="); } 1302 | RIGHT_ASSIGN { $$ = strdup(">>="); } 1303 | AND_ASSIGN { $$ = strdup("&="); } 1304 | XOR_ASSIGN { $$ = strdup("^="); } 1305 | OR_ASSIGN { $$ = strdup("|="); } 1306 ; 1307 1308any_operator 1309 : assignment_operator 1310 | unary_operator 1311 | binary_operator 1312 | NEW { $$ = strdup(" new"); } 1313 | DELETE { $$ = strdup(" delete"); } 1314 | PTR_OP { $$ = strdup("->"); } 1315 | MEM_PTR_OP { $$ = strdup("->*"); } 1316 | INC_OP { $$ = strdup("++"); } 1317 | DEC_OP { $$ = strdup("--"); } 1318 | LEFT_OP { $$ = strdup("<<"); } 1319 | RIGHT_OP { $$ = strdup(">>"); } 1320 | LE_OP { $$ = strdup("<="); } 1321 | GE_OP { $$ = strdup(">="); } 1322 | EQ_OP { $$ = strdup("=="); } 1323 | NE_OP { $$ = strdup("!="); } 1324 | AND_OP { $$ = strdup("&&"); } 1325 | OR_OP { $$ = strdup("||"); } 1326 | '[' ']' { $$ = strdup("[]"); } 1327 | '(' ')' { $$ = strdup("()"); } 1328 ; 1329 1330constant_value 1331 : expression 1332 | compound_statement { $$ = strdup("{ ... }"); } 1333 ; 1334 1335expression 1336 : additive_expression 1337 ; 1338 1339primary_expression 1340 : CONSTANT 1341 | '-' CONSTANT 1342{ 1343 char *tmp_str = (char *) malloc(strlen($2) + 2); 1344 sprintf(tmp_str, "-%s", $2); 1345 free($2); 1346 $$ = tmp_str; 1347} 1348 | STRING_LITERAL 1349 | IDENTIFIER 1350 | scoped_identifier 1351 | '(' expression ')' 1352{ 1353 char *tmp_str = (char *) malloc(strlen($2) + 3); 1354 sprintf(tmp_str, "(%s)", $2); 1355 free($2); 1356 $$ = tmp_str; 1357} 1358 ; 1359 1360multiplicative_expression 1361 : primary_expression 1362 | multiplicative_expression '*' primary_expression 1363{ 1364 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 4); 1365 sprintf(tmp_str, "%s * %s", $1, $3); 1366 free($1); 1367 free($3); 1368 $$ = tmp_str; 1369} 1370 | multiplicative_expression '/' primary_expression 1371{ 1372 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 4); 1373 sprintf(tmp_str, "%s / %s", $1, $3); 1374 free($1); 1375 free($3); 1376 $$ = tmp_str; 1377} 1378 | multiplicative_expression '%' primary_expression 1379{ 1380 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 4); 1381 sprintf(tmp_str, "%s %% %s", $1, $3); 1382 free($1); 1383 free($3); 1384 $$ = tmp_str; 1385} 1386 ; 1387 1388additive_expression 1389 : multiplicative_expression 1390 | additive_expression '+' multiplicative_expression 1391{ 1392 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 4); 1393 sprintf(tmp_str, "%s + %s", $1, $3); 1394 free($1); 1395 free($3); 1396 $$ = tmp_str; 1397} 1398 | additive_expression '-' multiplicative_expression 1399{ 1400 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 4); 1401 sprintf(tmp_str, "%s - %s", $1, $3); 1402 free($1); 1403 free($3); 1404 $$ = tmp_str; 1405} 1406 ; 1407 1408 1409union_specifier 1410 : UNION IDENTIFIER '{' variable_specifier_list '}' 1411{ 1412 char *tmp_str = (char *) malloc(strlen($2) + strlen($4) + 12); 1413 sprintf(tmp_str, "union %s { %s }", $2, $4); 1414 free($2); 1415 free($4); 1416 $$ = tmp_str; 1417} 1418 | UNION '{' variable_specifier_list '}' 1419{ 1420 char *tmp_str = (char *) malloc(strlen($3) + 11); 1421 sprintf(tmp_str, "union { %s }", $3); 1422 free($3); 1423 $$ = tmp_str; 1424} 1425 | UNION IDENTIFIER 1426{ 1427 char *tmp_str = (char *) malloc(strlen($2) + 7); 1428 sprintf(tmp_str, "union %s", $2); 1429 free($2); 1430 $$ = tmp_str; 1431} 1432 ; 1433 1434class_specifier 1435 : CLASS IDENTIFIER '{' member_list_opt '}' 1436{ 1437 syntaxelem_t *child; 1438 /* ret_type, name, args, kind */ 1439 syntaxelem_t *tmp_elem = new_elem(strdup(""), $2, NULL, CLASS_KIND); 1440 tmp_elem->children = reverse_list($4); 1441 1442 for (child = tmp_elem->children; child != NULL; child = child->next) 1443 child->parent = tmp_elem; 1444 1445/* print_se(tmp_elem); */ 1446 $$ = tmp_elem; 1447} 1448 | CLASS IDENTIFIER ':' superclass_list '{' member_list_opt '}' 1449{ 1450 syntaxelem_t *child; 1451 /* ret_type, name, args, kind */ 1452 syntaxelem_t *tmp_elem = new_elem(strdup(""), $2, NULL, CLASS_KIND); 1453 tmp_elem->children = reverse_list($6); 1454 1455 for (child = tmp_elem->children; child != NULL; child = child->next) 1456 child->parent = tmp_elem; 1457 1458/* print_se(tmp_elem); */ 1459 $$ = tmp_elem; 1460} 1461 | template_specifier CLASS IDENTIFIER '{' member_list_opt '}' 1462{ 1463 syntaxelem_t *child; 1464 /* ret_type, name, args, kind */ 1465 syntaxelem_t *tmp_elem = new_elem(strdup(""), $3, NULL, CLASS_KIND); 1466 tmp_elem->children = reverse_list($5); 1467 tmp_elem->templ = $1; 1468 1469 for (child = tmp_elem->children; child != NULL; child = child->next) 1470 child->parent = tmp_elem; 1471 1472/* print_se(tmp_elem); */ 1473 $$ = tmp_elem; 1474} 1475 | template_specifier CLASS IDENTIFIER ':' superclass_list '{' member_list_opt '}' 1476{ 1477 syntaxelem_t *child; 1478 /* ret_type, name, args, kind */ 1479 syntaxelem_t *tmp_elem = new_elem(strdup(""), $3, NULL, CLASS_KIND); 1480 tmp_elem->children = reverse_list($7); 1481 tmp_elem->templ = $1; 1482 1483 for (child = tmp_elem->children; child != NULL; child = child->next) 1484 child->parent = tmp_elem; 1485 1486/* print_se(tmp_elem); */ 1487 $$ = tmp_elem; 1488} 1489 | STRUCT '{' member_list_opt '}' 1490{ 1491 syntaxelem_t *child; 1492 /* ret_type, name, args, kind */ 1493 syntaxelem_t *tmp_elem = new_elem(strdup(""), "unnamed_struct", 1494 NULL, IGNORE_KIND); 1495 tmp_elem->children = reverse_list($3); 1496 1497 for (child = tmp_elem->children; child != NULL; child = child->next) 1498 child->parent = tmp_elem; 1499 1500/* print_se(tmp_elem); */ 1501 $$ = tmp_elem; 1502} 1503 | STRUCT IDENTIFIER '{' member_list_opt '}' 1504{ 1505 syntaxelem_t *child; 1506 /* ret_type, name, args, kind */ 1507 syntaxelem_t *tmp_elem = new_elem(strdup(""), $2, NULL, STRUCT_KIND); 1508 tmp_elem->children = reverse_list($4); 1509 1510 for (child = tmp_elem->children; child != NULL; child = child->next) 1511 child->parent = tmp_elem; 1512 1513/* print_se(tmp_elem); */ 1514 $$ = tmp_elem; 1515} 1516 | STRUCT IDENTIFIER ':' superclass_list '{' member_list_opt '}' 1517{ 1518 syntaxelem_t *child; 1519 /* ret_type, name, args, kind */ 1520 syntaxelem_t *tmp_elem = new_elem(strdup(""), $2, NULL, STRUCT_KIND); 1521 tmp_elem->children = reverse_list($6); 1522 1523 for (child = tmp_elem->children; child != NULL; child = child->next) 1524 child->parent = tmp_elem; 1525 1526/* print_se(tmp_elem); */ 1527 $$ = tmp_elem; 1528} 1529 | template_specifier STRUCT IDENTIFIER '{' member_list_opt '}' 1530{ 1531 syntaxelem_t *child; 1532 /* ret_type, name, args, kind */ 1533 syntaxelem_t *tmp_elem = new_elem(strdup(""), $3, NULL, STRUCT_KIND); 1534 tmp_elem->children = reverse_list($5); 1535 tmp_elem->templ = $1; 1536 1537 for (child = tmp_elem->children; child != NULL; child = child->next) 1538 child->parent = tmp_elem; 1539 1540/* print_se(tmp_elem); */ 1541 $$ = tmp_elem; 1542} 1543 | template_specifier STRUCT IDENTIFIER ':' superclass_list '{' member_list_opt '}' 1544{ 1545 syntaxelem_t *child; 1546 /* ret_type, name, args, kind */ 1547 syntaxelem_t *tmp_elem = new_elem(strdup(""), $3, NULL, STRUCT_KIND); 1548 tmp_elem->children = reverse_list($7); 1549 tmp_elem->templ = $1; 1550 1551 for (child = tmp_elem->children; child != NULL; child = child->next) 1552 child->parent = tmp_elem; 1553 1554/* print_se(tmp_elem); */ 1555 $$ = tmp_elem; 1556} 1557 ; 1558 1559superclass_list 1560 : superclass 1561 | superclass_list ',' superclass 1562 ; 1563 1564superclass 1565 : access_specifier_opt type_name { free($2); } 1566 ; 1567 1568friend_specifier 1569 : FRIEND member_func_specifier { $2->kind = IGNORE_KIND; } 1570 | FRIEND forward_decl 1571 ; 1572 1573member_list_opt 1574 : /* nothing */ { $$ = NULL; } 1575 | member_list 1576 ; 1577 1578member_list 1579 : member_with_access 1580{ 1581 if ($1 != NULL) 1582 $1->next = NULL; 1583 1584 $$ = $1; 1585} 1586 | member_list member_with_access 1587{ 1588 if ($2 != NULL) { 1589 $2->next = $1; 1590 $$ = $2; 1591 } else { 1592 $$ = $1; 1593 } 1594} 1595 ; 1596 1597member_or_error 1598 : member 1599 | error 1600{ 1601 log_printf("member_with_access : error. Attempting to recover...\n"); 1602 yyerrok; 1603 yyclearin; 1604 if (error_recovery() != 0) { 1605 log_printf("ERROR recovery could not complete -- YYABORT.\n"); 1606 YYABORT; 1607 } 1608 log_printf("ERROR recovery complete.\n"); 1609 $$ = NULL; 1610} 1611 ; 1612 1613member_with_access 1614 : member_or_error 1615 | access_specifier_list member_or_error { $$ = $2; } 1616 ; 1617 1618member 1619 : member_specifier ';' 1620 | friend_specifier ';' { $$ = NULL; } 1621 | member_func_inlined { $1->kind = INLINED_KIND; $$ = $1; } 1622 | ';' { $$ = NULL; } 1623 ; 1624 1625member_specifier 1626 : multiple_variable_specifier 1627{ 1628 /* ret_type, name, args, kind */ 1629 syntaxelem_t *elem = new_elem(strdup(""), $1, NULL, IGNORE_KIND); 1630/* print_se(elem); */ 1631 $$ = elem; 1632} 1633 | member_func_specifier 1634 | EXTERN member_func_specifier { $$ = $2; } 1635 | member_func_specifier '=' CONSTANT { $1->kind = IGNORE_KIND; free($3); $$ = $1; } 1636 | mem_type_specifier 1637 ; 1638 1639mem_type_specifier 1640 : type_specifier 1641 | type_specifier IDENTIFIER { free($2); $$ = $1; } 1642 | mem_type_specifier '[' ']' 1643 | mem_type_specifier '[' constant_value ']' 1644{ 1645 free($3); 1646 $$ = $1; 1647} 1648 ; 1649 1650template_arg 1651 : CLASS IDENTIFIER 1652{ 1653 char *tmp_str = (char *) malloc(strlen($2) + 7); 1654 sprintf(tmp_str, "class %s", $2); 1655 free($2); 1656 $$ = tmp_str; 1657} 1658 | type_name IDENTIFIER 1659{ 1660 char *tmp_str = (char *) malloc(strlen($1) + strlen($2) + 2); 1661 sprintf(tmp_str, "%s %s", $1, $2); 1662 free($1); 1663 free($2); 1664 $$ = tmp_str; 1665} 1666 ; 1667 1668template_arg_list 1669 : template_arg 1670 | template_arg_list ',' template_arg 1671{ 1672 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 3); 1673 sprintf(tmp_str, "%s, %s", $1, $3); 1674 free($1); 1675 free($3); 1676 $$ = tmp_str; 1677} 1678 ; 1679 1680template_instance_arg 1681 : CONSTANT 1682 | type_name 1683 ; 1684 1685template_instance_arg_list 1686 : template_instance_arg 1687 | template_instance_arg_list ',' template_instance_arg 1688{ 1689 char *tmp_str = (char *) malloc(strlen($1) + strlen($3) + 3); 1690 sprintf(tmp_str, "%s, %s", $1, $3); 1691 free($1); 1692 free($3); 1693 $$ = tmp_str; 1694} 1695 ; 1696 1697template_specifier 1698 : TEMPLATE '<' template_arg_list '>' 1699{ 1700 char *tmp_str = (char *) malloc(strlen($3) + 12); 1701 sprintf(tmp_str, "template <%s>", $3); 1702 free($3); 1703 $$ = tmp_str; 1704} 1705 ; 1706 1707%% 1708 1709static int yyerror(char *s /*UNUSED*/) 1710{ 1711 if (outfile != NULL) 1712 fflush(outfile); 1713 1714 return 0; 1715} 1716 1717static int error_recovery() 1718{ 1719 extern char linebuf[]; 1720 extern int lineno; 1721 extern int column; 1722 extern int tokens_seen; 1723 1724#ifdef SGDEBUG 1725 log_printf("parse error at line %d, file %s:\n%s\n%*s\n", 1726 lineno, currentFile, linebuf, column, "^"); 1727 log_flush(); 1728#endif /* SGDEBUG */ 1729 1730 if (tokens_seen == 0) { 1731 /* 1732 * if we've seen no tokens but we're in an error, we must have 1733 * hit an EOF, either by stdin, or on a file. Just give up 1734 * now instead of complaining. 1735 */ 1736 return -1; 1737 1738 } else { 1739 fprintf(stderr, "parse error at line %d, file %s:\n%s\n%*s\n", 1740 lineno, currentFile, linebuf, column, "^"); 1741 } 1742 1743 linebuf[0] = '\0'; 1744 1745 for (;;) { 1746 int result = yylex(); 1747 1748 if (result <= 0) { 1749 /* fatal error: Unexpected EOF during parse error recovery */ 1750 1751#ifdef SGDEBUG 1752 log_printf("EOF in error recovery, line %d, file %s\n", 1753 lineno, currentFile); 1754 log_flush(); 1755#endif /* SGDEBUG */ 1756 1757 fprintf(stderr, "EOF in error recovery, line %d, file %s\n", 1758 lineno, currentFile); 1759 1760 return -1; 1761 } 1762 1763 switch(result) { 1764 case IDENTIFIER: 1765 case CONSTANT: 1766 case STRING_LITERAL: 1767 case CHAR: 1768 case SHORT: 1769 case INT: 1770 case LONG: 1771 case SIGNED: 1772 case UNSIGNED: 1773 case FLOAT: 1774 case DOUBLE: 1775 case VOID: 1776 free(yylval.string); 1777 break; 1778 case (int) '{': 1779 if (collectInlineDef() != 0) 1780 return -1; 1781 result = yylex(); 1782 return 0; 1783 case (int) ';': 1784 return 0; 1785 } 1786 } 1787} 1788