fixed problems with declaration syntax
This commit is contained in:
		
							parent
							
								
									2f83a7e3d9
								
							
						
					
					
						commit
						02ea4988d1
					
				
					 3 changed files with 56 additions and 64 deletions
				
			
		| 
						 | 
				
			
			@ -67,43 +67,38 @@ declaration
 | 
			
		|||
		short typedef yepp;
 | 
			
		||||
	makes all hope of writing a specific grammar for typedefs illusory.
 | 
			
		||||
*/
 | 
			
		||||
/*	We do not accept the whole of the grammar, since when we see
 | 
			
		||||
	something like 'unsigned plain' (where plain is a typedef) is
 | 
			
		||||
	illegal if 'plain' is a typedef.  Therefore, we assume that
 | 
			
		||||
	'plain' is the identifier of a declarator.  Unfortunately, this
 | 
			
		||||
	causes declarations like 'unsigned plain x;' to be rejected on the
 | 
			
		||||
	grounds of syntax, even though it is syntactically right.  This may
 | 
			
		||||
	cause a lot of extra messages.
 | 
			
		||||
	To do this, decl_specifiers is divided into:
 | 
			
		||||
	1: normal specifiers == storage class specifiers + type_qualifiers
 | 
			
		||||
	2: special specifiers == short + long + signed + unsigned
 | 
			
		||||
	3: basic types == void + char + int + float + double
 | 
			
		||||
	4: single type specifiers == struct or union specifiers
 | 
			
		||||
				    + enum specifiers + typedef names
 | 
			
		||||
/*	Accept a single declaration specifier.  Then accept zero or more
 | 
			
		||||
	type-specifiers.  There can be a conflict on both TYPE_IDENTIFIER
 | 
			
		||||
	and IDENTIFIER.
 | 
			
		||||
	The following rule is used:
 | 
			
		||||
	When we see a TYPE_IDENTIFIER, we accept it if no type-specifier
 | 
			
		||||
	was given, and it is not directly followed by an identifier.
 | 
			
		||||
	If no type-dpecifier was given, it is taken as the identifier being
 | 
			
		||||
	declared.  If it is followed by an identifier, we assume that an
 | 
			
		||||
	error has been  made, (e.g. unsigned typedeffed_int x;) and that
 | 
			
		||||
	this will be detected later on.
 | 
			
		||||
	When we see an IDENTIFIER, directly followed by another IDENTIFIER,
 | 
			
		||||
	we assume that a typing mistake has been made, and we accept it as
 | 
			
		||||
	an erroneous type-identifier.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 */
 | 
			
		||||
decl_specifiers	/* non-empty */ (register struct decspecs *ds;)
 | 
			
		||||
	/*	Reads a non-empty decl_specifiers and fills the struct
 | 
			
		||||
		decspecs *ds.
 | 
			
		||||
	*/
 | 
			
		||||
:
 | 
			
		||||
[ %if (AHEAD == IDENTIFIER)			/* like: register i; */
 | 
			
		||||
	normal_specifier(ds)
 | 
			
		||||
|
 | 
			
		||||
	normal_specifier(ds)*
 | 
			
		||||
	[	special_specifier(ds)
 | 
			
		||||
	|	basic_type(ds)
 | 
			
		||||
	|	single_type_specifier(ds)
 | 
			
		||||
	]
 | 
			
		||||
	[	normal_specifier(ds)
 | 
			
		||||
	|	special_specifier(ds)
 | 
			
		||||
	|	basic_type(ds)
 | 
			
		||||
	single_decl_specifier(ds)
 | 
			
		||||
	[ %while(  (DOT==TYPE_IDENTIFIER
 | 
			
		||||
			&& ds->ds_size == 0
 | 
			
		||||
			&& ds->ds_unsigned == 0
 | 
			
		||||
			&& ds->ds_type == (struct type *)0)
 | 
			
		||||
		    || AHEAD == IDENTIFIER)	/* always an error */
 | 
			
		||||
		single_decl_specifier(ds)
 | 
			
		||||
	]*
 | 
			
		||||
]
 | 
			
		||||
	{do_decspecs(ds);}
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
normal_specifier(register struct decspecs *ds;)
 | 
			
		||||
single_decl_specifier /* non_empty */ (register struct decspecs *ds;)
 | 
			
		||||
:
 | 
			
		||||
	[ AUTO | STATIC | EXTERN | TYPEDEF | REGISTER ]
 | 
			
		||||
	{	if (ds->ds_sc_given)
 | 
			
		||||
| 
						 | 
				
			
			@ -112,28 +107,18 @@ normal_specifier(register struct decspecs *ds;)
 | 
			
		|||
		ds->ds_sc = DOT;
 | 
			
		||||
	}
 | 
			
		||||
|
 | 
			
		||||
	/*	This qualifier applies to the top type.
 | 
			
		||||
		E.g. volatile float * is a pointer to volatile float.
 | 
			
		||||
	*/
 | 
			
		||||
	VOLATILE
 | 
			
		||||
	{	if (ds->ds_typequal & TQ_VOLATILE)
 | 
			
		||||
			error("repeated type qualifier");
 | 
			
		||||
		ds->ds_typequal |= TQ_VOLATILE;
 | 
			
		||||
	}
 | 
			
		||||
|
 | 
			
		||||
	/*	This qualifier applies to the top type.
 | 
			
		||||
		E.g. volatile float * is a pointer to volatile float.
 | 
			
		||||
	*/
 | 
			
		||||
	CONST
 | 
			
		||||
	{
 | 
			
		||||
		if (ds->ds_typequal & TQ_CONST)
 | 
			
		||||
	{	if (ds->ds_typequal & TQ_CONST)
 | 
			
		||||
			error("repeated type qualifier");
 | 
			
		||||
		ds->ds_typequal |= TQ_CONST;
 | 
			
		||||
	}
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
special_specifier(register struct decspecs *ds;)
 | 
			
		||||
:
 | 
			
		||||
|
 | 
			
		||||
	[ SHORT | LONG ]
 | 
			
		||||
	{	if (ds->ds_size)
 | 
			
		||||
			error("repeated size specifier");
 | 
			
		||||
| 
						 | 
				
			
			@ -145,35 +130,14 @@ special_specifier(register struct decspecs *ds;)
 | 
			
		|||
			error("repeated sign specifier");
 | 
			
		||||
		ds->ds_unsigned = DOT;
 | 
			
		||||
	}
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
/* 3.5.2 */
 | 
			
		||||
type_specifier(struct type **tpp;)
 | 
			
		||||
	/*	Used in struct/union declarations and in casts; only the
 | 
			
		||||
		type is relevant.
 | 
			
		||||
	*/
 | 
			
		||||
	{struct decspecs Ds; Ds = null_decspecs;}
 | 
			
		||||
:
 | 
			
		||||
	decl_specifiers(&Ds)
 | 
			
		||||
	{
 | 
			
		||||
		if (Ds.ds_sc_given)
 | 
			
		||||
			error("storage class ignored");
 | 
			
		||||
		if (Ds.ds_sc == REGISTER)
 | 
			
		||||
			error("register ignored");
 | 
			
		||||
	}
 | 
			
		||||
	{*tpp = Ds.ds_type;}
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
basic_type(register struct decspecs *ds;):
 | 
			
		||||
|
 | 
			
		||||
	[ VOID | CHAR | INT | FLOAT | DOUBLE ]
 | 
			
		||||
	{
 | 
			
		||||
		idf2type(dot.tk_idf, &ds->ds_type);
 | 
			
		||||
		ds->ds_typedef = 0;
 | 
			
		||||
	}
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
single_type_specifier(register struct decspecs *ds;):
 | 
			
		||||
	%default TYPE_IDENTIFIER	/* this includes INT, CHAR, etc. */
 | 
			
		||||
|
 | 
			
		||||
	%default TYPE_IDENTIFIER
 | 
			
		||||
	{
 | 
			
		||||
		idf2type(dot.tk_idf, &ds->ds_type);
 | 
			
		||||
		ds->ds_typedef = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -194,6 +158,23 @@ single_type_specifier(register struct decspecs *ds;):
 | 
			
		|||
	enum_specifier(&ds->ds_type)
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
/* 3.5.2 */
 | 
			
		||||
type_specifier(struct type **tpp;)
 | 
			
		||||
	/*	Used in struct/union declarations and in casts; only the
 | 
			
		||||
		type is relevant.
 | 
			
		||||
	*/
 | 
			
		||||
	{struct decspecs Ds; Ds = null_decspecs;}
 | 
			
		||||
:
 | 
			
		||||
	decl_specifiers(&Ds)
 | 
			
		||||
	{
 | 
			
		||||
		if (Ds.ds_sc_given)
 | 
			
		||||
			error("storage class ignored");
 | 
			
		||||
		if (Ds.ds_sc == REGISTER)
 | 
			
		||||
			error("register ignored");
 | 
			
		||||
	}
 | 
			
		||||
	{*tpp = Ds.ds_type;}
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
/* 3.5 */
 | 
			
		||||
init_declarator_list(struct decspecs *ds;):
 | 
			
		||||
	init_declarator(ds)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -195,6 +195,17 @@ int to_endif;
 | 
			
		|||
		*/
 | 
			
		||||
		switch(tk.tk_idf->id_resmac) {
 | 
			
		||||
		default:
 | 
			
		||||
		case K_UNKNOWN:
 | 
			
		||||
			/* invalid word seen after the '#'      */
 | 
			
		||||
			lexerror("%s: unknown control", tk.tk_idf->id_text);
 | 
			
		||||
			/* fallthrough */
 | 
			
		||||
		case K_DEFINE:
 | 
			
		||||
		case K_ERROR:
 | 
			
		||||
		case K_INCLUDE:
 | 
			
		||||
		case K_LINE:
 | 
			
		||||
		case K_PRAGMA:
 | 
			
		||||
		case K_UNDEF:
 | 
			
		||||
		case K_FILE:
 | 
			
		||||
			SkipToNewLine();
 | 
			
		||||
			break;
 | 
			
		||||
		case K_IF:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,8 +41,8 @@ enter_label(idf, defining)
 | 
			
		|||
	}
 | 
			
		||||
	else	{
 | 
			
		||||
		add_def(idf, LABEL, label_type, L_LOCAL);
 | 
			
		||||
		def = idf->id_def;
 | 
			
		||||
	}
 | 
			
		||||
	def = idf->id_def;	/* might be changed by 1 of the 2 add_defs */
 | 
			
		||||
	if (def->df_address == 0)
 | 
			
		||||
		def->df_address = (arith) text_label();
 | 
			
		||||
	if (defining)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue