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