From 4a7185fd4a25b1456737b8fa2ac6a770a3e1721e Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Fri, 25 Sep 2015 11:44:59 +0100 Subject: Make the binding parser understand c types Instead of c types being opaque strings this makes the bindig parser understand them. This is necessary for extended attribute parsing in future but also makes the binding more easily understandable. --- src/duk-libdom-common.c | 39 ++++++++ src/duk-libdom-interface.c | 62 +++++++++---- src/duk-libdom.c | 21 +---- src/duk-libdom.h | 15 ++++ src/nsgenbind-ast.c | 34 +------ src/nsgenbind-ast.h | 26 +----- src/nsgenbind-lexer.l | 23 ++--- src/nsgenbind-parser.y | 219 ++++++++++++++++++++++++--------------------- src/nsgenbind.c | 2 +- 9 files changed, 229 insertions(+), 212 deletions(-) (limited to 'src') diff --git a/src/duk-libdom-common.c b/src/duk-libdom-common.c index 9a0f660..a1298e9 100644 --- a/src/duk-libdom-common.c +++ b/src/duk-libdom-common.c @@ -76,3 +76,42 @@ int output_tool_prologue(FILE* outf) return 0; } + + +/* exported interface documented in duk-libdom.h */ +int output_ctype(FILE *outf, struct genbind_node *node, bool identifier) +{ + const char *type_cdata = NULL; + struct genbind_node *typename_node; + + typename_node = genbind_node_find_type(genbind_node_getnode(node), + NULL, + GENBIND_NODE_TYPE_NAME); + while (typename_node != NULL) { + type_cdata = genbind_node_gettext(typename_node); + + fprintf(outf, "%s", type_cdata); + + typename_node = genbind_node_find_type( + genbind_node_getnode(node), + typename_node, + GENBIND_NODE_TYPE_NAME); + + /* separate all but the last entry with spaces */ + if (typename_node != NULL) { + fputc(' ', outf); + } + } + + if (identifier) { + if ((type_cdata != NULL) && + (type_cdata[0] != '*') && + (type_cdata[0] != ' ')) { + fputc(' ', outf); + } + + output_cdata(outf, node, GENBIND_NODE_TYPE_IDENT); + } + + return 0; +} diff --git a/src/duk-libdom-interface.c b/src/duk-libdom-interface.c index ad40741..38e1277 100644 --- a/src/duk-libdom-interface.c +++ b/src/duk-libdom-interface.c @@ -327,6 +327,42 @@ output_interface_destructor(FILE* outf, struct ir_entry *interfacee) return 0; } +/** + * Compare two nodes to check their c types match. + */ +static bool compare_ctypes(struct genbind_node *a, struct genbind_node *b) +{ + struct genbind_node *ta; + struct genbind_node *tb; + + ta = genbind_node_find_type(genbind_node_getnode(a), + NULL, GENBIND_NODE_TYPE_NAME); + tb = genbind_node_find_type(genbind_node_getnode(b), + NULL, GENBIND_NODE_TYPE_NAME); + + while ((ta != NULL) && (tb != NULL)) { + char *txt_a; + char *txt_b; + + txt_a = genbind_node_gettext(ta); + txt_b = genbind_node_gettext(tb); + + if (strcmp(txt_a, txt_b) != 0) { + return false; /* missmatch */ + } + + ta = genbind_node_find_type(genbind_node_getnode(a), + ta, GENBIND_NODE_TYPE_NAME); + tb = genbind_node_find_type(genbind_node_getnode(b), + tb, GENBIND_NODE_TYPE_NAME); + } + if (ta != tb) { + return false; + } + + return true; +} + /** * generate an initialisor call to parent interface */ @@ -389,26 +425,14 @@ output_interface_inherit_init(FILE* outf, param_name); return -1; } else { - char *param_type; - char *inh_param_type; - fprintf(outf, ", "); /* cast the parameter if required */ - param_type = genbind_node_gettext( - genbind_node_find_type( - genbind_node_getnode(param_node), - NULL, - GENBIND_NODE_TYPE_TYPE)); - - inh_param_type = genbind_node_gettext( - genbind_node_find_type( - genbind_node_getnode(inh_param_node), - NULL, - GENBIND_NODE_TYPE_TYPE)); - - if (strcmp(param_type, inh_param_type) != 0) { - fprintf(outf, "(%s)", inh_param_type); + if (compare_ctypes(param_node, + inh_param_node) == false) { + fputc('(', outf); + output_ctype(outf, inh_param_node, false); + fputc(')', outf); } /* output the parameter identifier */ @@ -449,8 +473,8 @@ output_interface_init_declaration(FILE* outf, while (param_node != NULL) { interfacee->class_init_argc++; fprintf(outf, ", "); - output_cdata(outf, param_node, GENBIND_NODE_TYPE_TYPE); - output_cdata(outf, param_node, GENBIND_NODE_TYPE_IDENT); + + output_ctype(outf, param_node, true); param_node = genbind_node_find_type( genbind_node_getnode(init_node), diff --git a/src/duk-libdom.c b/src/duk-libdom.c index 084a68f..ee7cc3b 100644 --- a/src/duk-libdom.c +++ b/src/duk-libdom.c @@ -228,25 +228,10 @@ output_private_header(struct ir *ir) NULL, GENBIND_NODE_TYPE_PRIVATE); while (priv_node != NULL) { - /* generate the private variable definition ensuring - * the type is separated from the identifier with - * either a * or space. - */ - const char *type_cdata; - char cdatae; - type_cdata = genbind_node_gettext( - genbind_node_find_type( - genbind_node_getnode(priv_node), - NULL, - GENBIND_NODE_TYPE_TYPE)); - - fprintf(privf, "\t%s", type_cdata); - cdatae = type_cdata[strlen(type_cdata) - 1]; - if ((cdatae != '*') && (cdatae != ' ')) { - fputc(' ', privf); - } + fprintf(privf, "\t"); + + output_ctype(privf, priv_node, true); - output_cdata(privf, priv_node, GENBIND_NODE_TYPE_IDENT); fprintf(privf, ";\n"); priv_node = genbind_node_find_type( diff --git a/src/duk-libdom.h b/src/duk-libdom.h index 79b440e..3b07009 100644 --- a/src/duk-libdom.h +++ b/src/duk-libdom.h @@ -56,4 +56,19 @@ int output_tool_prologue(FILE* outf); */ int output_cdata(FILE* outf, struct genbind_node *node, enum genbind_node_type nodetype); +/** + * output a C variable type + * + * Used to output c type and optionlly identifier declarations for parameters + * and structure entries. + * If the optional identifier is output it is ensured the type is separated + * from the identifier with either a * or space. + * + * \param outf The file handle to write output. + * \param node The node to generate content for. + * \param identifier If the indentifier should be output. + * \return 0 on success. + */ +int output_ctype(FILE *outf, struct genbind_node *node, bool identifier); + #endif diff --git a/src/nsgenbind-ast.c b/src/nsgenbind-ast.c index 4f0654a..6b39461 100644 --- a/src/nsgenbind-ast.c +++ b/src/nsgenbind-ast.c @@ -259,34 +259,6 @@ genbind_node_find_type_ident(struct genbind_node *node, return found_node; } -/* exported interface documented in nsgenbind-ast.h */ -struct genbind_node * -genbind_node_find_type_type(struct genbind_node *node, - struct genbind_node *prev, - enum genbind_node_type type, - const char *ident) -{ - struct genbind_node *found_node; - struct genbind_node *ident_node; - - found_node = genbind_node_find_type(node, prev, type); - - - while (found_node != NULL) { - /* look for a type node */ - ident_node = genbind_node_find_type(genbind_node_getnode(found_node), - NULL, - GENBIND_NODE_TYPE_TYPE); - if (ident_node != NULL) { - if (strcmp(ident_node->r.text, ident) == 0) - break; - } - - /* look for next matching node */ - found_node = genbind_node_find_type(node, found_node, type); - } - return found_node; -} /* exported interface documented in nsgenbind-ast.h */ @@ -371,7 +343,7 @@ char *genbind_node_gettext(struct genbind_node *node) case GENBIND_NODE_TYPE_EPILOGUE: case GENBIND_NODE_TYPE_POSTFACE: case GENBIND_NODE_TYPE_IDENT: - case GENBIND_NODE_TYPE_TYPE: + case GENBIND_NODE_TYPE_NAME: case GENBIND_NODE_TYPE_CDATA: return node->r.text; @@ -449,8 +421,8 @@ static const char *genbind_node_type_to_str(enum genbind_node_type type) case GENBIND_NODE_TYPE_BINDING: return "Binding"; - case GENBIND_NODE_TYPE_TYPE: - return "Type"; + case GENBIND_NODE_TYPE_NAME: + return "TypeName"; case GENBIND_NODE_TYPE_PRIVATE: return "Private"; diff --git a/src/nsgenbind-ast.h b/src/nsgenbind-ast.h index 2a384b2..282544e 100644 --- a/src/nsgenbind-ast.h +++ b/src/nsgenbind-ast.h @@ -12,7 +12,7 @@ enum genbind_node_type { GENBIND_NODE_TYPE_ROOT = 0, GENBIND_NODE_TYPE_IDENT, /**< generic identifier string */ - GENBIND_NODE_TYPE_TYPE, /**< generic type string */ + GENBIND_NODE_TYPE_NAME, /**< generic type string */ GENBIND_NODE_TYPE_MODIFIER, /**< node modifier */ GENBIND_NODE_TYPE_CDATA, /**< verbatim block of character data */ GENBIND_NODE_TYPE_STRING, /**< text string */ @@ -151,30 +151,6 @@ genbind_node_find_type_ident(struct genbind_node *node, const char *ident); -/** - * Returning node of the specified type with a GENBIND_NODE_TYPE_TYPE - * subnode with matching text. - * - * This is a conveniance wrapper around nested calls to - * genbind_node_find_type() which performs a depth first left hand - * search returning nodes of the specified type and a child node of - * GENBIND_NODE_TYPE_TYPE with matching text. - * - * - * @param node The node to start the search from - * @param prev The node at which to stop the search, either NULL to - * search the full tree depth (initial search) or the result - * of a previous search to continue. - * @param nodetype The type of node to seach for. - * @param type The text to match the type child node to. - */ -struct genbind_node * -genbind_node_find_type_type(struct genbind_node *node, - struct genbind_node *prev, - enum genbind_node_type nodetype, - const char *type_text); - - /** * Find a method node of a given method type * diff --git a/src/nsgenbind-lexer.l b/src/nsgenbind-lexer.l index d092195..f32a948 100644 --- a/src/nsgenbind-lexer.l +++ b/src/nsgenbind-lexer.l @@ -93,50 +93,39 @@ dblcolon \:\: /* binding terminals */ binding return TOK_BINDING; - webidl return TOK_WEBIDL; - preface return TOK_PREFACE; - prologue return TOK_PROLOGUE; - epilogue return TOK_EPILOGUE; - postface return TOK_POSTFACE; /* class member terminals */ class return TOK_CLASS; - private return TOK_PRIVATE; - internal return TOK_INTERNAL; - flags return TOK_FLAGS; - type return TOK_TYPE; - unshared return TOK_UNSHARED; - shared return TOK_SHARED; - property return TOK_PROPERTY; /* implementation terminals */ init return TOK_INIT; - fini return TOK_FINI; - method return TOK_METHOD; - getter return TOK_GETTER; - setter return TOK_SETTER; - prototype return TOK_PROTOTYPE; + /* c type terminals */ + +struct return TOK_STRUCT; +union return TOK_UNION; +unsigned return TOK_UNSIGNED; + /* other terminals */ {dblcolon} return TOK_DBLCOLON; diff --git a/src/nsgenbind-parser.y b/src/nsgenbind-parser.y index 1462b39..b883833 100644 --- a/src/nsgenbind-parser.y +++ b/src/nsgenbind-parser.y @@ -27,9 +27,9 @@ static void nsgenbind_error(YYLTYPE *locp, struct genbind_node **genbind_ast, const char *str) { - locp = locp; - genbind_ast = genbind_ast; - errtxt = strdup(str); + locp = locp; + genbind_ast = genbind_ast; + errtxt = strdup(str); } static struct genbind_node * @@ -104,9 +104,9 @@ add_method(struct genbind_node **genbind_ast, %union { - char *text; - struct genbind_node *node; - long value; + char *text; + struct genbind_node *node; + long value; } %token TOK_BINDING @@ -135,6 +135,10 @@ add_method(struct genbind_node **genbind_ast, %token TOK_DBLCOLON +%token TOK_STRUCT +%token TOK_UNION +%token TOK_UNSIGNED + %token TOK_IDENTIFIER %token TOK_STRING_LITERAL %token TOK_CCODE_LITERAL @@ -169,38 +173,36 @@ add_method(struct genbind_node **genbind_ast, %type Property %type ParameterList -%type TypeIdent +%type CTypeIdent +%type CType +%type CTypeSpecifier %% -Input - : +Input: Statements - { - *genbind_ast = $1; + { + *genbind_ast = $1; } ; - -Statements - : - Statement +Statements: + Statement | - Statements Statement + Statements Statement { - $$ = *genbind_ast = genbind_node_prepend($2, $1); + $$ = *genbind_ast = genbind_node_prepend($2, $1); } - | - error ';' - { - fprintf(stderr, "%d: %s\n", yylloc.first_line, errtxt); - free(errtxt); - YYABORT ; + | + error ';' + { + fprintf(stderr, "%d: %s\n", yylloc.first_line, errtxt); + free(errtxt); + YYABORT ; } ; -Statement - : +Statement: Binding | Class @@ -208,18 +210,17 @@ Statement Method ; -Binding - : - TOK_BINDING TOK_IDENTIFIER '{' BindingArgs '}' +Binding: + TOK_BINDING TOK_IDENTIFIER '{' BindingArgs '}' ';' { - $$ = genbind_new_node(GENBIND_NODE_TYPE_BINDING, - NULL, - genbind_new_node(GENBIND_NODE_TYPE_TYPE, $4, $2)); + $$ = genbind_new_node(GENBIND_NODE_TYPE_BINDING, + NULL, + genbind_new_node(GENBIND_NODE_TYPE_NAME, + $4, $2)); } ; -BindingArgs - : +BindingArgs: BindingArg | BindingArgs BindingArg @@ -228,8 +229,7 @@ BindingArgs } ; -BindingArg - : +BindingArg: WebIDL | Preface @@ -241,71 +241,102 @@ BindingArg Postface ; - /* [3] a web IDL file specifier */ -WebIDL - : + /* a web IDL file specifier */ +WebIDL: TOK_WEBIDL TOK_STRING_LITERAL ';' { - $$ = genbind_new_node(GENBIND_NODE_TYPE_WEBIDL, NULL, $2); + $$ = genbind_new_node(GENBIND_NODE_TYPE_WEBIDL, NULL, $2); } ; + /* parse a c type specifier. This probably also needs to cope with + * void, char, short, int, long, float, double, signed, enum + */ +CTypeSpecifier: + TOK_UNSIGNED TOK_IDENTIFIER + { + $$ = genbind_new_node(GENBIND_NODE_TYPE_NAME, + genbind_new_node(GENBIND_NODE_TYPE_NAME, + NULL, + strdup("unsigned")), + $2); + } + | + TOK_STRUCT TOK_IDENTIFIER + { + $$ = genbind_new_node(GENBIND_NODE_TYPE_NAME, + genbind_new_node(GENBIND_NODE_TYPE_NAME, + NULL, + strdup("struct")), + $2); + } + | + TOK_UNION TOK_IDENTIFIER + { + $$ = genbind_new_node(GENBIND_NODE_TYPE_NAME, + genbind_new_node(GENBIND_NODE_TYPE_NAME, + NULL, + strdup("union")), + $2); + } + | + TOK_IDENTIFIER + { + $$ = genbind_new_node(GENBIND_NODE_TYPE_NAME, NULL, $1); + } + ; + +CType: + CTypeSpecifier + | + CTypeSpecifier '*' + { + $$ = genbind_new_node(GENBIND_NODE_TYPE_NAME, $1, strdup("*")); + } /* type and identifier of a variable */ -TypeIdent - : - TOK_STRING_LITERAL TOK_IDENTIFIER +CTypeIdent: + CType TOK_IDENTIFIER { - $$ = genbind_new_node(GENBIND_NODE_TYPE_IDENT, - genbind_new_node(GENBIND_NODE_TYPE_TYPE, NULL, $1), $2); + $$ = genbind_new_node(GENBIND_NODE_TYPE_IDENT, $1, $2); } | - TOK_STRING_LITERAL TOK_IDENTIFIER TOK_DBLCOLON TOK_IDENTIFIER + CType TOK_IDENTIFIER TOK_DBLCOLON TOK_IDENTIFIER { - $$ = genbind_new_node(GENBIND_NODE_TYPE_IDENT, - genbind_new_node(GENBIND_NODE_TYPE_IDENT, - genbind_new_node(GENBIND_NODE_TYPE_TYPE, - NULL, - $1), - $2), - $4); + $$ = genbind_new_node(GENBIND_NODE_TYPE_IDENT, + genbind_new_node(GENBIND_NODE_TYPE_IDENT, $1, $2), $4); } ; -Preface - : +Preface: TOK_PREFACE CBlock ';' { - $$ = genbind_new_node(GENBIND_NODE_TYPE_PREFACE, NULL, $2); + $$ = genbind_new_node(GENBIND_NODE_TYPE_PREFACE, NULL, $2); } ; -Prologue - : +Prologue: TOK_PROLOGUE CBlock ';' { $$ = genbind_new_node(GENBIND_NODE_TYPE_PROLOGUE, NULL, $2); } ; -Epilogue - : +Epilogue: TOK_EPILOGUE CBlock ';' { $$ = genbind_new_node(GENBIND_NODE_TYPE_EPILOGUE, NULL, $2); } ; -Postface - : +Postface: TOK_POSTFACE CBlock ';' { $$ = genbind_new_node(GENBIND_NODE_TYPE_POSTFACE, NULL, $2); } ; -CBlock - : +CBlock: TOK_CCODE_LITERAL | CBlock TOK_CCODE_LITERAL @@ -314,8 +345,7 @@ CBlock } ; -MethodType - : +MethodType: TOK_INIT { $$ = GENBIND_METHOD_TYPE_INIT; @@ -347,14 +377,13 @@ MethodType } ; -ParameterList - : - TypeIdent +ParameterList: + CTypeIdent { $$ = genbind_new_node(GENBIND_NODE_TYPE_PARAMETER, NULL, $1); } | - ParameterList ',' TypeIdent + ParameterList ',' CTypeIdent { $$ = genbind_node_prepend($1, genbind_new_node( @@ -364,8 +393,7 @@ ParameterList } ; -MethodDeclarator - : +MethodDeclarator: TOK_IDENTIFIER TOK_DBLCOLON TOK_IDENTIFIER '(' ParameterList ')' { $$ = genbind_new_node(GENBIND_NODE_TYPE_CLASS, @@ -406,8 +434,7 @@ MethodDeclarator } ; -Method - : +Method: MethodType MethodDeclarator CBlock { $$ = add_method(genbind_ast, $1, $2, $3); @@ -419,17 +446,15 @@ Method } ; -Class - : - TOK_CLASS TOK_IDENTIFIER '{' ClassArgs '}' +Class: + TOK_CLASS TOK_IDENTIFIER '{' ClassArgs '}' ';' { $$ = genbind_new_node(GENBIND_NODE_TYPE_CLASS, NULL, genbind_new_node(GENBIND_NODE_TYPE_IDENT, $4, $2)); } ; -ClassArgs - : +ClassArgs: ClassArg | ClassArgs ClassArg @@ -438,8 +463,7 @@ ClassArgs } ; -ClassArg - : +ClassArg: Private | Internal @@ -458,45 +482,40 @@ ClassArg ; -Private - : - TOK_PRIVATE TypeIdent ';' +Private: + TOK_PRIVATE CTypeIdent ';' { - $$ = genbind_new_node(GENBIND_NODE_TYPE_PRIVATE, NULL, $2); + $$ = genbind_new_node(GENBIND_NODE_TYPE_PRIVATE, NULL, $2); } ; -Internal - : - TOK_INTERNAL TypeIdent ';' +Internal: + TOK_INTERNAL CTypeIdent ';' { - $$ = genbind_new_node(GENBIND_NODE_TYPE_INTERNAL, NULL, $2); + $$ = genbind_new_node(GENBIND_NODE_TYPE_INTERNAL, NULL, $2); } ; -ClassFlag - : +ClassFlag: TOK_FLAGS ClassFlags ';' { - $$ = genbind_new_node(GENBIND_NODE_TYPE_FLAGS, NULL, $2); + $$ = genbind_new_node(GENBIND_NODE_TYPE_FLAGS, NULL, $2); } ; -ClassFlags - : +ClassFlags: TOK_IDENTIFIER { - $$ = genbind_new_node(GENBIND_NODE_TYPE_IDENT, NULL, $1); + $$ = genbind_new_node(GENBIND_NODE_TYPE_IDENT, NULL, $1); } | ClassFlags ',' TOK_IDENTIFIER { - $$ = genbind_new_node(GENBIND_NODE_TYPE_IDENT, $1, $3); + $$ = genbind_new_node(GENBIND_NODE_TYPE_IDENT, $1, $3); } ; -Property - : +Property: TOK_PROPERTY Modifiers TOK_IDENTIFIER ';' { $$ = genbind_new_node(GENBIND_NODE_TYPE_PROPERTY, NULL, @@ -508,8 +527,7 @@ Property } ; -Modifiers - : +Modifiers: /* empty */ { $$ = GENBIND_TYPE_NONE; @@ -521,8 +539,7 @@ Modifiers } ; -Modifier - : +Modifier: TOK_TYPE { $$ = GENBIND_TYPE_TYPE; diff --git a/src/nsgenbind.c b/src/nsgenbind.c index 135c5c0..09d4c29 100644 --- a/src/nsgenbind.c +++ b/src/nsgenbind.c @@ -168,7 +168,7 @@ static enum bindingtype_e genbind_get_type(struct genbind_node *node) genbind_node_find_type( genbind_node_getnode(binding_node), NULL, - GENBIND_NODE_TYPE_TYPE)); + GENBIND_NODE_TYPE_NAME)); if (binding_type == NULL) { fprintf(stderr, "Error: missing binding type\n"); return BINDINGTYPE_UNKNOWN; -- cgit v1.2.3