fixed problems with declaration syntax

This commit is contained in:
eck 1990-09-03 13:46:30 +00:00
parent 2f83a7e3d9
commit 02ea4988d1
3 changed files with 56 additions and 64 deletions

View file

@ -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)

View file

@ -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:

View file

@ -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)