Message ID | CANkmNDcrHFOoi+jXGNXjS3e_7L74GYyo0jtfDFmxo5atRPcGHw@mail.gmail.com |
---|---|
State | New |
Headers | show |
Hi - 2012/8/30 Aaron Gray <aaronngray.lists@gmail.com>: > First of two patches for class'ized cp/parser.c|h gives limited > support for gengtype to parse C++ classes and enums as first class > citizens. Please sync with Diego to avoid duplicate work and/or conflicting designs. Thanks,
On 2012-08-29 20:31 , Aaron Gray wrote: > 2012-08-30 Aaron Gray <aaronngray.lists@gmail.com> > > * gengtype-lex.l: Support for FILE > Support for C++ single line Comments > Support for classes > Support for enums > ignore 'static' > ignore 'inline' > ignore 'public:' > ignore 'protected:' > ignore 'private:' > ignore 'friend' > support for 'operator' token > support for 'new' > support for 'delete' > added support for '+' as a token for summations in enum bodies > > * gengtype.h: added 'TYPE_ENUM' to 'enum typekind' > added enum TYPE_ENUM to 'struct type' union Write entries like these as: * gengtype.h (enum type_kind): Add TYPE_ENUM. (struct type): Add TYPE_ENUM. > added OPERATOR_KEYWORD and OPERATOR keywords to Token Code enum Likewise. > > * gengtype-parser.c: updated 'token_names[]' > (direct_declarator): support for parsing limited operators > support for parsing constructors with no parameters > support for parsing enums > > * gengtype.c: added 'type_p enums' to maintain list of enums > (resolve_typedef): added support for stucture types and enums > added 'new_enum()' > > > diff --git a/gcc/gengtype-lex.l b/gcc/gengtype-lex.l > index 5788a6a..af9696a 100644 > --- a/gcc/gengtype-lex.l > +++ b/gcc/gengtype-lex.l > @@ -53,11 +53,11 @@ update_lineno (const char *l, size_t len) > ID [[:alpha:]_][[:alnum:]_]* > WS [[:space:]]+ > HWS [ \t\r\v\f]* > -IWORD short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD|CPPCHAR_SIGNED_T|ino_t|dev_t|HARD_REG_SET > +IWORD short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD|CPPCHAR_SIGNED_T|ino_t|dev_t|HARD_REG_SET|FILE > ITYPE {IWORD}({WS}{IWORD})* > EOID [^[:alnum:]_] > > -%x in_struct in_struct_comment in_comment > +%x in_struct in_struct_comment in_comment in_line_comment > in_line_struct_comment > %option warn noyywrap nounput nodefault perf-report > %option 8bit never-interactive > %% > @@ -83,6 +83,14 @@ EOID [^[:alnum:]_] > BEGIN(in_struct); > return UNION; > } > +^{HWS}class/{EOID} { > + BEGIN(in_struct); > + return STRUCT; > +} > +^{HWS}enum/{EOID} { > + BEGIN(in_struct); > + return ENUM; > +} > ^{HWS}extern/{EOID} { > BEGIN(in_struct); > return EXTERN; > @@ -101,10 +109,20 @@ EOID [^[:alnum:]_] > \\\n { lexer_line.line++; } > > "const"/{EOID} /* don't care */ > +"static"/{EOID} /* don't care */ > +"inline"/{EOID} /* don't care */ > +"public:" /* don't care */ > +"private:" /* don't care */ > +"protected:" /* don't care */ > +"operator"/{EOID} { return OPERATOR_KEYWORD; } > +"new"/{EOID} { *yylval = XDUPVAR (const char, > yytext+1, yyleng-2, yyleng-1); return OPERATOR; } > +"delete"/{EOID} { *yylval = XDUPVAR (const char, > yytext+1, yyleng-2, yyleng-1); return OPERATOR; } > +"friend"/{EOID} > "GTY"/{EOID} { return GTY_TOKEN; } > "VEC"/{EOID} { return VEC_TOKEN; } > "union"/{EOID} { return UNION; } > "struct"/{EOID} { return STRUCT; } > +"class"/{EOID} { return CLASS; } Why not just return STRUCT here? > @@ -3,7 +3,7 @@ > > This file is part of GCC. > > - GCC is free software; you can redistribute it and/or modify it under > + /GCC is free software; you can redistribute it and/or modify it under This seems out of place. > @@ -778,6 +791,7 @@ type (options_p *optsp, bool nested) > return resolve_typedef (s, &lexer_line); > > case STRUCT: > + case CLASS: I think that as far as gengtype is concerned, 'struct' and 'class' should be exactly the same thing. So, all the handling for 'CLASS' you added should not be needed. > +/* enum definition: type() does all the work. */ > +static void > +parse_enum (void) > +{ > + options_p dummy; > + type (&dummy, false); > + /* There may be junk after the type: notably, we cannot currently > + distinguish 'struct foo *function(prototype);' from 'struct foo;' > + ... we could call declarator(), but it's a waste of time at > + present. Instead, just eat whatever token is currently lookahead > + and go back to lexical skipping mode. */ > + advance (); > +} > + I'm not quite sure what is this trying to do. > @@ -601,16 +602,93 @@ type_p > resolve_typedef (const char *s, struct fileloc *pos) > { > pair_p p; > + type_p t; > + type_p e; > + > for (p = typedefs; p != NULL; p = p->next) > if (strcmp (p->name, s) == 0) > return p->type; > > + for (t = structures; t != NULL; t = t->next) > + { > + switch ( t->kind) > + { > + case TYPE_NONE: > + if (do_debug) > + fprintf(stderr, "TYPE_NONE:\n"); > + break; > + case TYPE_SCALAR: > + if (do_debug) > + fprintf(stderr, "TYPE_SCALAR:\n"); > + break; > + case TYPE_STRING: > + if (do_debug) > + fprintf(stderr, "TYPE_STRING:\n"); > + break; > + case TYPE_STRUCT: > + if (do_debug) > + fprintf(stderr, "TYPE_STRUCT: '%s'\n", t->u.s.tag); > + goto structure; > + case TYPE_UNION: > + if (do_debug) > + fprintf(stderr, "TYPE_UNION: '%s'\n", t->u.s.tag); > + goto structure; > + case TYPE_LANG_STRUCT: > + if (do_debug) > + fprintf(stderr, "TYPE_LANG_STRUCT: '%s'\n", t->u.s.tag); > + structure: > + if (strcmp (t->u.s.tag, s) == 0) > + return t; > + break; > + case TYPE_POINTER: > + if (do_debug) > + fprintf(stderr, "TYPE_POINTER:\n"); > + break; > + case TYPE_ARRAY: > + if (do_debug) > + fprintf(stderr, "TYPE_ARRAY:\n"); > + break; > + case TYPE_PARAM_STRUCT: > + if (do_debug) > + fprintf(stderr, "TYPE_PARAM_STRUCT:\n"); > + break; > + default: > + if (do_debug) > + fprintf(stderr, "default:\n"); > + break; > + } > + }; > + Yikes. What are you trying to do here? > @@ -148,9 +149,10 @@ enum typekind { > param1_is, param2_is,... use_param1, > use_param_2,... use_params) GTY > options. */ > - TYPE_USER_STRUCT /* User defined type. Walkers and markers for > + TYPE_USER_STRUCT, /* User defined type. Walkers and markers for > this type are assumed to be provided by the > user. */ > + TYPE_ENUM /* Type for enums. */ What are enums used for? Do they affect gengtype's operation in any way? > }; > > /* Discriminating kind for options. */ > @@ -309,6 +311,11 @@ struct type { > struct fileloc line; /* The source location. */ > } param_struct; > > + /* when TYPE_ENUM */ > + > + struct { > + const char *tag; /* the aggragate tag, if any. */ s/aggragate/aggregate/ Diego.
On Tue, Sep 11, 2012 at 3:41 PM, Diego Novillo <dnovillo@google.com> wrote: >> @@ -778,6 +791,7 @@ type (options_p *optsp, bool nested) >> return resolve_typedef (s, &lexer_line); >> >> case STRUCT: >> + case CLASS: > > > I think that as far as gengtype is concerned, 'struct' and 'class' should be > exactly the same thing. So, all the handling for 'CLASS' you added should > not be needed. 100% agreed. -- Gaby
On Wed, Sep 12, 2012 at 4:54 PM, Aaron Gray <aaronngray.lists@gmail.com> wrote: > On 11 September 2012 23:45, Gabriel Dos Reis > <gdr@integrable-solutions.net> wrote: >> On Tue, Sep 11, 2012 at 3:41 PM, Diego Novillo <dnovillo@google.com> wrote: >> >>>> @@ -778,6 +791,7 @@ type (options_p *optsp, bool nested) >>>> return resolve_typedef (s, &lexer_line); >>>> >>>> case STRUCT: >>>> + case CLASS: >>> >>> >>> I think that as far as gengtype is concerned, 'struct' and 'class' should be >>> exactly the same thing. So, all the handling for 'CLASS' you added should >>> not be needed. >> >> >> 100% agreed. > > The reason I included a CLASS type distinct from STRUCT was for > reporting debugging information when I get to that stage. In general, patches are easier to assess when they are self-contained (e.g. each change is justified by the purpose of the patch.) My recommendation would be for your patches to focus on one topic at a time. -- Gaby
Aaron, I'm currently fixing other issues with gengtype and I needed this patch on top of them. I will be rolling both patches into a single one and commit them today/tomorrow. If you were working on further fixes to this, please give me a chance to commit this one first. Thanks. Diego.
diff --git a/gcc/gengtype-lex.l b/gcc/gengtype-lex.l index 5788a6a..af9696a 100644 --- a/gcc/gengtype-lex.l +++ b/gcc/gengtype-lex.l @@ -53,11 +53,11 @@ update_lineno (const char *l, size_t len) ID [[:alpha:]_][[:alnum:]_]* WS [[:space:]]+ HWS [ \t\r\v\f]* -IWORD short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD|CPPCHAR_SIGNED_T|ino_t|dev_t|HARD_REG_SET +IWORD short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD|CPPCHAR_SIGNED_T|ino_t|dev_t|HARD_REG_SET|FILE ITYPE {IWORD}({WS}{IWORD})* EOID [^[:alnum:]_] -%x in_struct in_struct_comment in_comment +%x in_struct in_struct_comment in_comment in_line_comment in_line_struct_comment %option warn noyywrap nounput nodefault perf-report %option 8bit never-interactive %% @@ -83,6 +83,14 @@ EOID [^[:alnum:]_] BEGIN(in_struct); return UNION; } +^{HWS}class/{EOID} { + BEGIN(in_struct); + return STRUCT; +} +^{HWS}enum/{EOID} { + BEGIN(in_struct); + return ENUM; +} ^{HWS}extern/{EOID} { BEGIN(in_struct); return EXTERN; @@ -101,10 +109,20 @@ EOID [^[:alnum:]_] \\\n { lexer_line.line++; } "const"/{EOID} /* don't care */ +"static"/{EOID} /* don't care */ +"inline"/{EOID} /* don't care */ +"public:" /* don't care */ +"private:" /* don't care */ +"protected:" /* don't care */ +"operator"/{EOID} { return OPERATOR_KEYWORD; } +"new"/{EOID} { *yylval = XDUPVAR (const char, yytext+1, yyleng-2, yyleng-1); return OPERATOR; } +"delete"/{EOID} { *yylval = XDUPVAR (const char, yytext+1, yyleng-2, yyleng-1); return OPERATOR; } +"friend"/{EOID} "GTY"/{EOID} { return GTY_TOKEN; } "VEC"/{EOID} { return VEC_TOKEN; } "union"/{EOID} { return UNION; } "struct"/{EOID} { return STRUCT; } +"class"/{EOID} { return CLASS; } "enum"/{EOID} { return ENUM; } "ptr_alias"/{EOID} { return PTR_ALIAS; } "nested_ptr"/{EOID} { return NESTED_PTR; } @@ -148,7 +166,7 @@ EOID [^[:alnum:]_] } "..." { return ELLIPSIS; } -[(){},*:<>;=%|-] { return yytext[0]; } +[(){},*:<>;=%|\-\+] { return yytext[0]; } /* ignore pp-directives */ ^{HWS}"#"{HWS}[a-z_]+[^\n]*\n {lexer_line.line++;} @@ -159,6 +177,7 @@ EOID [^[:alnum:]_] } "/*" { BEGIN(in_comment); } +"//" { BEGIN(in_line_comment); } \n { lexer_line.line++; } {ID} | "'"("\\".|[^\\])"'" | @@ -172,8 +191,17 @@ EOID [^[:alnum:]_] [^*\n] /* do nothing */ "*"/[^/] /* do nothing */ } + +<in_line_comment,in_line_struct_comment>{ +[^*\n]{16} | +[^*\n] /* do nothing */ +"*"/[^/] /* do nothing */ +} + <in_comment>"*/" { BEGIN(INITIAL); } <in_struct_comment>"*/" { BEGIN(in_struct); } +<in_line_comment>\n { lexer_line.line++; BEGIN(INITIAL); } +<in_line_struct_comment>\n { lexer_line.line++; BEGIN(in_struct); } ["/] | <in_struct_comment,in_comment>"*" { diff --git a/gcc/gengtype-parse.c b/gcc/gengtype-parse.c index 03ee781..663db56 100644 --- a/gcc/gengtype-parse.c +++ b/gcc/gengtype-parse.c @@ -3,7 +3,7 @@ This file is part of GCC. - GCC is free software; you can redistribute it and/or modify it under + /GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. @@ -75,6 +75,7 @@ static const char *const token_names[] = { "static", "union", "struct", + "class", "enum", "VEC", "...", @@ -608,10 +609,22 @@ direct_declarator (type_p ty, const char **namep, options_p *optsp) case '(': advance (); + + if (token() == ')') + { + advance(); + return create_scalar_type ("constructor"); + } + ty = inner_declarator (ty, namep, optsp); require (')'); break; + case OPERATOR_KEYWORD: + advance(); + *namep = require (OPERATOR); + break; + default: parse_error ("expected '(', 'GTY', or an identifier, have %s", print_cur_token ()); @@ -778,6 +791,7 @@ type (options_p *optsp, bool nested) return resolve_typedef (s, &lexer_line); case STRUCT: + case CLASS: case UNION: { options_p opts = 0; @@ -923,6 +937,20 @@ struct_or_union (void) advance (); } +/* enum definition: type() does all the work. */ +static void +parse_enum (void) +{ + options_p dummy; + type (&dummy, false); + /* There may be junk after the type: notably, we cannot currently + distinguish 'struct foo *function(prototype);' from 'struct foo;' + ... we could call declarator(), but it's a waste of time at + present. Instead, just eat whatever token is currently lookahead + and go back to lexical skipping mode. */ + advance (); +} + /* GC root declaration: (extern|static) gtymarker? type ID array_declarators_opt (';'|'=') If the gtymarker is not present, we ignore the rest of the declaration. */ @@ -974,10 +1002,15 @@ parse_file (const char *fname) break; case STRUCT: + case CLASS: case UNION: struct_or_union (); break; + case ENUM: + parse_enum (); + break; + case TYPEDEF: typedef_decl (); break; diff --git a/gcc/gengtype.c b/gcc/gengtype.c index 2ae4372..2cd07fe 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -497,10 +497,11 @@ struct type scalar_char = { /* Lists of various things. */ -pair_p typedefs; -type_p structures; -type_p param_structs; -pair_p variables; +pair_p typedefs = NULL; +type_p structures = NULL; +type_p enums = NULL; +type_p param_structs = NULL; +pair_p variables = NULL; static type_p find_param_structure (type_p t, type_p param[NUM_PARAM]); static type_p adjust_field_tree_exp (type_p t, options_p opt); @@ -601,16 +602,93 @@ type_p resolve_typedef (const char *s, struct fileloc *pos) { pair_p p; + type_p t; + type_p e; + for (p = typedefs; p != NULL; p = p->next) if (strcmp (p->name, s) == 0) return p->type; + for (t = structures; t != NULL; t = t->next) + { + switch ( t->kind) + { + case TYPE_NONE: + if (do_debug) + fprintf(stderr, "TYPE_NONE:\n"); + break; + case TYPE_SCALAR: + if (do_debug) + fprintf(stderr, "TYPE_SCALAR:\n"); + break; + case TYPE_STRING: + if (do_debug) + fprintf(stderr, "TYPE_STRING:\n"); + break; + case TYPE_STRUCT: + if (do_debug) + fprintf(stderr, "TYPE_STRUCT: '%s'\n", t->u.s.tag); + goto structure; + case TYPE_UNION: + if (do_debug) + fprintf(stderr, "TYPE_UNION: '%s'\n", t->u.s.tag); + goto structure; + case TYPE_LANG_STRUCT: + if (do_debug) + fprintf(stderr, "TYPE_LANG_STRUCT: '%s'\n", t->u.s.tag); + structure: + if (strcmp (t->u.s.tag, s) == 0) + return t; + break; + case TYPE_POINTER: + if (do_debug) + fprintf(stderr, "TYPE_POINTER:\n"); + break; + case TYPE_ARRAY: + if (do_debug) + fprintf(stderr, "TYPE_ARRAY:\n"); + break; + case TYPE_PARAM_STRUCT: + if (do_debug) + fprintf(stderr, "TYPE_PARAM_STRUCT:\n"); + break; + default: + if (do_debug) + fprintf(stderr, "default:\n"); + break; + } + }; + + for (e = enums; e != NULL; e = e->next) + if (strcmp (e->u.e.tag, s) == 0) + return e; + /* If we did not find a typedef registered, assume this is a name for a user-defined type which will need to provide its own marking functions. */ return create_user_defined_type (s, pos); } +type_p +new_enum (const char *name) +{ + type_p ei; + type_p e; + + for (ei = enums; ei != NULL; ei = ei->next) + if (strcmp (name, ei->u.e.tag) == 0) + return ei; + + e = XCNEW (struct type); + + e->u.e.tag = name; + + e->next = enums; + enums = e; + + return e; +} + /* Create and return a new structure with tag NAME at POS with fields FIELDS and options O. The KIND of structure must be one of TYPE_STRUCT, TYPE_UNION or TYPE_USER_STRUCT. */ @@ -2450,6 +2528,7 @@ output_mangled_typename (outf_p of, const_type_p t) } break; case TYPE_ARRAY: + case TYPE_ENUM: gcc_unreachable (); } } @@ -3137,6 +3216,7 @@ write_types_process_field (type_p f, const struct walk_type_data *d) break; case TYPE_ARRAY: + case TYPE_ENUM: gcc_unreachable (); } } diff --git a/gcc/gengtype.h b/gcc/gengtype.h index 4a178ec..3d43c75 100644 --- a/gcc/gengtype.h +++ b/gcc/gengtype.h @@ -125,6 +125,7 @@ extern struct fileloc lexer_line; gengtype.c & in gengtype-state.c files. */ extern pair_p typedefs; extern type_p structures; +extern type_p enums; extern type_p param_structs; extern pair_p variables; @@ -148,9 +149,10 @@ enum typekind { param1_is, param2_is,... use_param1, use_param_2,... use_params) GTY options. */ - TYPE_USER_STRUCT /* User defined type. Walkers and markers for + TYPE_USER_STRUCT, /* User defined type. Walkers and markers for this type are assumed to be provided by the user. */ + TYPE_ENUM /* Type for enums. */ }; /* Discriminating kind for options. */ @@ -309,6 +311,11 @@ struct type { struct fileloc line; /* The source location. */ } param_struct; + /* when TYPE_ENUM */ + + struct { + const char *tag; /* the aggragate tag, if any. */ + } e; } u; }; @@ -425,6 +432,7 @@ extern type_p new_structure (const char *name, enum typekind kind, struct fileloc *pos, pair_p fields, options_p o); extern type_p find_structure (const char *s, enum typekind kind); +extern type_p new_enum (const char *name); extern type_p create_scalar_type (const char *name); extern type_p create_pointer (type_p t);