* parse.c, parser-defs.h (follow_types): New function.

* c-exp.y (ptype : typebase abs_decl): Use it.
	* c-exp.y (ptype): Add support for type qualifiers after the
	typebase.  The typebase rule already has support for them before
	the typebase.
	* Makefile.in: Change the expected number of shift/reduce
	conflicts to 6.  This is OK--the 2 new conflicts are basically the
	same as one of the old ones.
This commit is contained in:
Jim Kingdon 1993-10-18 01:10:25 +00:00
parent cf4d863151
commit f843c95fc3
3 changed files with 73 additions and 41 deletions

View File

@ -722,48 +722,23 @@ variable: name_not_typename
; ;
/* shift/reduce conflict: "typebase ." and the token is '('. (Shows up
twice, once where qualified_name is a possibility and once where
it is not). */
/* shift/reduce conflict: "typebase CONST_KEYWORD ." and the token is '('. */
/* shift/reduce conflict: "typebase VOLATILE_KEYWORD ." and the token is
'('. */
ptype : typebase ptype : typebase
/* "const" and "volatile" are curently ignored. A type qualifier
before the type is currently handled in the typebase rule. */
| typebase CONST_KEYWORD
| typebase VOLATILE_KEYWORD
| typebase abs_decl | typebase abs_decl
{ { $$ = follow_types ($1); }
/* This is where the interesting stuff happens. */ | typebase CONST_KEYWORD abs_decl
int done = 0; { $$ = follow_types ($1); }
int array_size; | typebase VOLATILE_KEYWORD abs_decl
struct type *follow_type = $1; { $$ = follow_types ($1); }
struct type *range_type;
while (!done)
switch (pop_type ())
{
case tp_end:
done = 1;
break;
case tp_pointer:
follow_type = lookup_pointer_type (follow_type);
break;
case tp_reference:
follow_type = lookup_reference_type (follow_type);
break;
case tp_array:
array_size = pop_type_int ();
if (array_size != -1)
{
range_type =
create_range_type ((struct type *) NULL,
builtin_type_int, 0,
array_size - 1);
follow_type =
create_array_type ((struct type *) NULL,
follow_type, range_type);
}
else
follow_type = lookup_pointer_type (follow_type);
break;
case tp_function:
follow_type = lookup_function_type (follow_type);
break;
}
$$ = follow_type;
}
; ;
abs_decl: '*' abs_decl: '*'
@ -790,6 +765,10 @@ direct_abs_decl: '(' abs_decl ')'
push_type (tp_array); push_type (tp_array);
$$ = 0; $$ = 0;
} }
/* shift/reduce conflict. "direct_abs_decl . func_mod", and the token
is '('. */
| direct_abs_decl func_mod | direct_abs_decl func_mod
{ push_type (tp_function); } { push_type (tp_function); }
| func_mod | func_mod
@ -808,6 +787,8 @@ func_mod: '(' ')'
{ free ((PTR)$2); $$ = 0; } { free ((PTR)$2); $$ = 0; }
; ;
/* shift/reduce conflict: "type '(' typebase COLONCOLON '*' ')' ." and the
token is '('. */
type : ptype type : ptype
| typebase COLONCOLON '*' | typebase COLONCOLON '*'
{ $$ = lookup_member_type (builtin_type_int, $1); } { $$ = lookup_member_type (builtin_type_int, $1); }
@ -871,7 +852,9 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */
{ $$ = lookup_template_type(copy_name($2), $4, { $$ = lookup_template_type(copy_name($2), $4,
expression_context_block); expression_context_block);
} }
/* "const" and "volatile" are curently ignored. */ /* "const" and "volatile" are curently ignored. A type qualifier
after the type is handled in the ptype rule. I think these could
be too. */
| CONST_KEYWORD typebase { $$ = $2; } | CONST_KEYWORD typebase { $$ = $2; }
| VOLATILE_KEYWORD typebase { $$ = $2; } | VOLATILE_KEYWORD typebase { $$ = $2; }
; ;

View File

@ -726,6 +726,9 @@ parse_expression (string)
error ("Junk after end of expression."); error ("Junk after end of expression.");
return exp; return exp;
} }
/* Stuff for maintaining a stack of types. Currently just used by C, but
probably useful for any language which declares its types "backwards". */
void void
push_type (tp) push_type (tp)
@ -770,6 +773,50 @@ pop_type_int ()
return 0; return 0;
} }
/* Pop the type stack and return the type which corresponds to FOLLOW_TYPE
as modified by all the stuff on the stack. */
struct type *
follow_types (follow_type)
struct type *follow_type;
{
int done = 0;
int array_size;
struct type *range_type;
while (!done)
switch (pop_type ())
{
case tp_end:
done = 1;
break;
case tp_pointer:
follow_type = lookup_pointer_type (follow_type);
break;
case tp_reference:
follow_type = lookup_reference_type (follow_type);
break;
case tp_array:
array_size = pop_type_int ();
if (array_size != -1)
{
range_type =
create_range_type ((struct type *) NULL,
builtin_type_int, 0,
array_size - 1);
follow_type =
create_array_type ((struct type *) NULL,
follow_type, range_type);
}
else
follow_type = lookup_pointer_type (follow_type);
break;
case tp_function:
follow_type = lookup_function_type (follow_type);
break;
}
return follow_type;
}
void void
_initialize_parse () _initialize_parse ()
{ {

View File

@ -133,6 +133,8 @@ pop_type PARAMS ((void));
extern int extern int
pop_type_int PARAMS ((void)); pop_type_int PARAMS ((void));
extern struct type *follow_types PARAMS ((struct type *));
/* During parsing of a C expression, the pointer to the next character /* During parsing of a C expression, the pointer to the next character
is in this variable. */ is in this variable. */