[cplus] More operator name parsing

Daniel Jacobowitz drow@mvista.com
Sat Dec 20 18:10:00 GMT 2003


As I alluded to last night, there's a tricky situation between
things like:
  operator int (*) (int)	[an operator name]
and
  operator int *(int)		[a function declaration]

It's possible to resolve this via clever (read: ugly) semantic actions; I
essentially unrolled parsing of function_arglist by one level inside
abstract_declarator_fn.  That necessitated some changes to
direct_abstract_declarator, and that caused even more in
abstract_declarator.  But the result works and I can now say without my
usual hedging that I no longer have any testcases that I can't parse.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

2003-12-20  Daniel Jacobowitz  <drow@mvista.com>

	* cp-names.y (%union): Remove abstract_fn.  Add abstract.
	(abstract_declarator_fn): Change type to abstract.  Fold function
	arglists lazily.  Handle start_opt after function_arglist
	and :: after more complex function types.
	(abstract_declarator): Change type to abstract.  Fold function
	arglists eagerly.
	(direct_abstract_declarator): Change type to abstract.  Fold function
	arglists only when necessary.
	(function): Move start_opt into abstract_declarator_fn.  Handle
	bare conversion typespecs and unfolded arglists.
	(declarator_1): Handle local names inside more complex function
	declarations.
	(main): Support --debug.

Index: cp-names.y
===================================================================
RCS file: /cvs/src/src/gdb/Attic/cp-names.y,v
retrieving revision 1.1.2.11
diff -u -p -r1.1.2.11 cp-names.y
--- cp-names.y	20 Dec 2003 07:08:44 -0000	1.1.2.11
+++ cp-names.y	20 Dec 2003 17:55:36 -0000
@@ -175,7 +175,7 @@ void yyerror (char *);
 %union
   {
     struct d_comp *comp;
-    struct {
+    struct nested {
       struct d_comp *comp;
       struct d_comp **last;
     } nested;
@@ -183,8 +183,11 @@ void yyerror (char *);
       struct d_comp *comp, *last;
     } nested1;
     struct {
-      struct d_comp *comp, **last, *fn;
-    } abstract_fn;
+      struct d_comp *comp, **last;
+      struct nested fn;
+      struct d_comp *start;
+      int fold_flag;
+    } abstract;
     LONGEST lval;
     struct {
       LONGEST val;
@@ -208,8 +211,8 @@ static int parse_number (char *, int, in
 %type <comp> demangler_special function conversion_op
 %type <nested> conversion_op_name
 
-%type <nested> abstract_declarator direct_abstract_declarator
-%type <abstract_fn> abstract_declarator_fn
+%type <abstract> abstract_declarator direct_abstract_declarator
+%type <abstract> abstract_declarator_fn
 %type <nested> declarator direct_declarator function_arglist
 
 %type <nested> declarator_1 direct_declarator_1
@@ -330,7 +333,10 @@ function
 			{ $$ = d_make_comp (di, D_COMP_TYPED_NAME, $1, $2.comp);
 			  if ($3) $$ = d_make_comp (di, D_COMP_LOCAL_NAME, $$, $3); }
 
-		|	conversion_op_name abstract_declarator_fn start_opt
+		|	conversion_op_name start_opt
+			{ $$ = $1.comp;
+			  if ($2) $$ = d_make_comp (di, D_COMP_LOCAL_NAME, $$, $2); }
+		|	conversion_op_name abstract_declarator_fn
 			{ if ($2.last)
 			    {
 			       /* First complete the abstract_declarator's type using
@@ -339,10 +345,13 @@ function
 			      /* Then complete the conversion_op_name with the type.  */
 			      *$1.last = $2.comp;
 			    }
-			  /* Then finally build the function.  */
-			  $$ = d_make_comp (di, D_COMP_TYPED_NAME, $1.comp, $2.fn);
-			  if ($3) $$ = d_make_comp (di, D_COMP_LOCAL_NAME, $$, $3); }
-
+			  /* If we have an arglist, build a function type.  */
+			  if ($2.fn.comp)
+			    $$ = d_make_comp (di, D_COMP_TYPED_NAME, $1.comp, $2.fn.comp);
+			  else
+			    $$ = $1.comp;
+			  if ($2.start) $$ = d_make_comp (di, D_COMP_LOCAL_NAME, $$, $2.start);
+			}
 		;
 
 demangler_special
@@ -718,28 +727,44 @@ typespec_2	:	typespec qualifiers_opt
 
 abstract_declarator
 		:	ptr_operator
+			{ $$.comp = $1.comp; $$.last = $1.last;
+			  $$.fn.comp = NULL; $$.fn.last = NULL; }
 		|	ptr_operator abstract_declarator
-			{ $$.comp = $2.comp;
-			  $$.last = $1.last;
-			  *$2.last = $1.comp; }
+			{ $$ = $2; $$.fn.comp = NULL; $$.fn.last = NULL;
+			  if ($2.fn.comp) { $$.last = $2.fn.last; *$2.last = $2.fn.comp; }
+			  *$$.last = $1.comp;
+			  $$.last = $1.last; }
 		|	direct_abstract_declarator
+			{ $$ = $1; $$.fn.comp = NULL; $$.fn.last = NULL;
+			  if ($1.fn.comp) { $$.last = $1.fn.last; *$1.last = $1.fn.comp; }
+			}
 		;
 
 direct_abstract_declarator
 		:	'(' abstract_declarator ')'
-			{ $$ = $2; }
+			{ $$ = $2; $$.fn.comp = NULL; $$.fn.last = NULL; $$.fold_flag = 1;
+			  if ($2.fn.comp) { $$.last = $2.fn.last; *$2.last = $2.fn.comp; }
+			}
 		|	direct_abstract_declarator function_arglist
-			{ $$.comp = $1.comp;
-			  *$1.last = $2.comp;
-			  $$.last = $2.last;
+			{ $$ = $1; $$.fold_flag = 0;
+			  if ($1.fn.comp) { $$.last = $1.fn.last; *$1.last = $1.fn.comp; }
+			  if ($1.fold_flag)
+			    {
+			      *$$.last = $2.comp;
+			      $$.last = $2.last;
+			    }
+			  else
+			    $$.fn = $2;
 			}
 		|	direct_abstract_declarator array_indicator
-			{ $$.comp = $1.comp;
+			{ $$ = $1; $$.fn.comp = NULL; $$.fn.last = NULL; $$.fold_flag = 0;
+			  if ($1.fn.comp) { $$.last = $1.fn.last; *$1.last = $1.fn.comp; }
 			  *$1.last = $2;
 			  $$.last = &d_right ($2);
 			}
 		|	array_indicator
-			{ $$.comp = $1;
+			{ $$.fn.comp = NULL; $$.fn.last = NULL; $$.fold_flag = 0;
+			  $$.comp = $1;
 			  $$.last = &d_right ($1);
 			}
 		/* G++ has the following except for () and (type).  Then
@@ -754,26 +779,34 @@ direct_abstract_declarator
 		;
 
 abstract_declarator_fn
-		:	function_arglist
-			{ $$.fn = $1.comp;
-			  $$.comp = NULL;
-			  $$.last = NULL;
-			}
+		:	ptr_operator
+			{ $$.comp = $1.comp; $$.last = $1.last;
+			  $$.fn.comp = NULL; $$.fn.last = NULL; $$.start = NULL; }
 		|	ptr_operator abstract_declarator_fn
-			{ $$.fn = $2.fn;
+			{ $$ = $2;
+			  if ($2.last)
+			    *$$.last = $1.comp;
+			  else
+			    $$.comp = $1.comp;
 			  $$.last = $1.last;
-			  if ($2.comp)
+			}
+		|	direct_abstract_declarator
+			{ $$.comp = $1.comp; $$.last = $1.last; $$.fn = $1.fn; $$.start = NULL; }
+		|	direct_abstract_declarator function_arglist COLONCOLON start
+			{ $$ = $1; $$.start = $4;
+			  if ($1.fn.comp) { $$.last = $1.fn.last; *$1.last = $1.fn.comp; }
+			  if ($1.fold_flag)
 			    {
-			      $$.comp = $2.comp;
-			      *$2.last = $1.comp;
+			      *$$.last = $2.comp;
+			      $$.last = $2.last;
 			    }
 			  else
-			    $$.comp = $1.comp;
+			    $$.fn = $2;
 			}
-		|	direct_abstract_declarator function_arglist
-			{ $$.fn = $2.comp;
-			  $$.comp = $1.comp;
-			  $$.last = $1.last;
+		|	function_arglist start_opt
+			{ $$.fn = $1;
+			  $$.start = $2;
+			  $$.comp = NULL; $$.last = NULL;
 			}
 		;
 
@@ -832,12 +865,19 @@ declarator_1	:	ptr_operator declarator_1
 			   our left is the type of the containing function. 
 			   This should be OK, because function local types
 			   can not be templates, so the return types of their
-			   members will not be mangled.  */
+			   members will not be mangled.  If they are hopefully
+			   they'll end up to the right of the ::.  */
 		|	colon_ext_name function_arglist COLONCOLON start
 			{ $$.comp = d_make_comp (di, D_COMP_TYPED_NAME, $1, $2.comp);
 			  $$.last = $2.last;
 			  $$.comp = d_make_comp (di, D_COMP_LOCAL_NAME, $$.comp, $4);
 			}
+		|	direct_declarator_1 function_arglist COLONCOLON start
+			{ $$.comp = $1.comp;
+			  *$1.last = $2.comp;
+			  $$.last = $2.last;
+			  $$.comp = d_make_comp (di, D_COMP_LOCAL_NAME, $$.comp, $4);
+			}
 		;
 
 direct_declarator_1
@@ -2019,8 +2059,16 @@ main (int argc, char **argv)
   struct d_info myinfo;
   char *str, *str2, *extra_chars, c;
   char buf[65536];
-  
-  if (argv[1] == NULL)
+  int arg;
+
+  arg = 1;
+  if (argv[arg] && strcmp (argv[arg], "--debug") == 0)
+    {
+      yydebug = 1;
+      arg++;
+    }
+
+  if (argv[arg] == NULL)
     while (fgets (buf, 65536, stdin) != NULL)
       {
 	result = NULL;
@@ -2052,7 +2100,7 @@ main (int argc, char **argv)
       }
   else
     {
-      lexptr = argv[1];
+      lexptr = argv[arg];
       d_init_info (NULL, DMGL_PARAMS | DMGL_ANSI, 2 * strlen (lexptr), &myinfo);
       di = &myinfo;
       if (yyparse () || result == NULL)



More information about the Gdb-patches mailing list