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…
Reference in a new issue