From 40cd6a199d8a5f92f71c5638f4da021a779e7a5c Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 17 Aug 2015 17:41:18 +0200 Subject: Add WebIDL parsing of dictionaries This adds correct parsing of dictionaries into the AST. These entries in the AST are not yet used but do not affect generation of interfaces. --- src/interface-map.c | 2 +- src/webidl-ast.c | 11 +- src/webidl-ast.h | 6 +- src/webidl-lexer.l | 2 + src/webidl-parser.y | 300 +++++++++++++++++++++++++++++++++++++++------------- 5 files changed, 240 insertions(+), 81 deletions(-) (limited to 'src') diff --git a/src/interface-map.c b/src/interface-map.c index a5a672a..822892f 100644 --- a/src/interface-map.c +++ b/src/interface-map.c @@ -596,7 +596,7 @@ int interface_map_new(struct genbind_node *genbind, webidl_node_find_type( webidl_node_getnode(node), NULL, - WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE)); + WEBIDL_NODE_TYPE_INHERITANCE)); /* is the interface marked as not generating an object */ if (webidl_node_find_type_ident( diff --git a/src/webidl-ast.c b/src/webidl-ast.c index 87e3485..dc78e1f 100644 --- a/src/webidl-ast.c +++ b/src/webidl-ast.c @@ -96,6 +96,7 @@ webidl_node_add(struct webidl_node *node, struct webidl_node *list) switch (node->type) { case WEBIDL_NODE_TYPE_ROOT: case WEBIDL_NODE_TYPE_INTERFACE: + case WEBIDL_NODE_TYPE_DICTIONARY: case WEBIDL_NODE_TYPE_LIST: case WEBIDL_NODE_TYPE_EXTENDED_ATTRIBUTE: case WEBIDL_NODE_TYPE_ATTRIBUTE: @@ -265,7 +266,7 @@ char *webidl_node_gettext(struct webidl_node *node) switch(node->type) { case WEBIDL_NODE_TYPE_IDENT: - case WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE: + case WEBIDL_NODE_TYPE_INHERITANCE: case WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS: case WEBIDL_NODE_TYPE_LITERAL_STRING: return node->r.text; @@ -311,6 +312,7 @@ struct webidl_node *webidl_node_getnode(struct webidl_node *node) switch (node->type) { case WEBIDL_NODE_TYPE_ROOT: case WEBIDL_NODE_TYPE_INTERFACE: + case WEBIDL_NODE_TYPE_DICTIONARY: case WEBIDL_NODE_TYPE_LIST: case WEBIDL_NODE_TYPE_EXTENDED_ATTRIBUTE: case WEBIDL_NODE_TYPE_ATTRIBUTE: @@ -338,7 +340,7 @@ static const char *webidl_node_type_to_str(enum webidl_node_type type) case WEBIDL_NODE_TYPE_IDENT: return "Ident"; - case WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE: + case WEBIDL_NODE_TYPE_INHERITANCE: return "Inherit"; case WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS: @@ -347,6 +349,9 @@ static const char *webidl_node_type_to_str(enum webidl_node_type type) case WEBIDL_NODE_TYPE_INTERFACE: return "Interface"; + case WEBIDL_NODE_TYPE_DICTIONARY: + return "Dictionary"; + case WEBIDL_NODE_TYPE_LIST: return "List"; @@ -600,7 +605,7 @@ static int implements_copy_nodes(struct webidl_node *src_node, while (src != NULL) { if (src->type == WEBIDL_NODE_TYPE_LIST) { - /** @todo technicaly this should copy WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE */ + /** @todo technicaly this should copy WEBIDL_NODE_TYPE_INHERITANCE */ dst = webidl_node_new(src->type, dst, src->r.text); } src = src->l; diff --git a/src/webidl-ast.h b/src/webidl-ast.h index 109159f..0872965 100644 --- a/src/webidl-ast.h +++ b/src/webidl-ast.h @@ -19,14 +19,16 @@ enum webidl_node_type { WEBIDL_NODE_TYPE_LIST, /* non structural node types */ - WEBIDL_NODE_TYPE_INTERFACE, - WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE, + WEBIDL_NODE_TYPE_INTERFACE, /**< node is an interface*/ WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS, WEBIDL_NODE_TYPE_ATTRIBUTE, WEBIDL_NODE_TYPE_OPERATION, WEBIDL_NODE_TYPE_CONST, + WEBIDL_NODE_TYPE_DICTIONARY, /**< node is a dictionary */ + + WEBIDL_NODE_TYPE_INHERITANCE, /**< node has inheritance */ WEBIDL_NODE_TYPE_SPECIAL, WEBIDL_NODE_TYPE_ARGUMENT, WEBIDL_NODE_TYPE_OPTIONAL, diff --git a/src/webidl-lexer.l b/src/webidl-lexer.l index 8c68fdf..4788610 100644 --- a/src/webidl-lexer.l +++ b/src/webidl-lexer.l @@ -213,6 +213,8 @@ iterable return TOK_ITERABLE; legacyiterable return TOK_LEGACYITERABLE; +required return TOK_REQUIRED; + {identifier} { /* A leading "_" is used to escape an identifier from * looking like a reserved word terminal. */ diff --git a/src/webidl-parser.y b/src/webidl-parser.y index 42fed63..406962f 100644 --- a/src/webidl-parser.y +++ b/src/webidl-parser.y @@ -66,7 +66,6 @@ webidl_error(YYLTYPE *locp, struct webidl_node **winbind_ast, const char *str) %token TOK_BOOLEAN %token TOK_BYTE %token TOK_CALLBACK -%token TOK_LEGACYCALLER %token TOK_CONST %token TOK_CREATOR %token TOK_DATE @@ -87,6 +86,7 @@ webidl_error(YYLTYPE *locp, struct webidl_node **winbind_ast, const char *str) %token TOK_INHERIT %token TOK_INTERFACE %token TOK_ITERABLE +%token TOK_LEGACYCALLER %token TOK_LEGACYITERABLE %token TOK_LONG %token TOK_MODULE @@ -102,6 +102,7 @@ webidl_error(YYLTYPE *locp, struct webidl_node **winbind_ast, const char *str) %token TOK_PROMISE %token TOK_RAISES %token TOK_READONLY +%token TOK_REQUIRED %token TOK_SETRAISES %token TOK_SETTER %token TOK_SEQUENCE @@ -134,6 +135,8 @@ webidl_error(YYLTYPE *locp, struct webidl_node **winbind_ast, const char *str) %type Dictionary %type PartialDictionary +%type DictionaryMembers +%type DictionaryMember %type Exception %type Enum @@ -151,6 +154,8 @@ webidl_error(YYLTYPE *locp, struct webidl_node **winbind_ast, const char *str) %type Attribute %type AttributeRest +%type AttributeName +%type AttributeNameKeyword %type AttributeOrOperation %type StringifierAttributeOrOperation %type Const @@ -201,6 +206,7 @@ webidl_error(YYLTYPE *locp, struct webidl_node **winbind_ast, const char *str) %type ReadOnly %type OptionalLong %type Inherit + //%type Required %type ExtendedAttributeList %type ExtendedAttributes @@ -210,6 +216,7 @@ webidl_error(YYLTYPE *locp, struct webidl_node **winbind_ast, const char *str) %type Other %type OtherOrComma + %% /* [1] default rule to add built AST to passed in one, altered from @@ -274,34 +281,40 @@ CallbackRestOrInterface: Interface: TOK_INTERFACE TOK_IDENTIFIER Inheritance '{' InterfaceMembers '}' ';' { - /* extend interface with additional members */ - struct webidl_node *interface_node; - struct webidl_node *members = NULL; + /* extend interface with additional members */ + struct webidl_node *interface_node; + struct webidl_node *members = NULL; - if ($3 != NULL) { - members = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE, members, $3); - } + if ($3 != NULL) { + members = webidl_node_new(WEBIDL_NODE_TYPE_INHERITANCE, + members, + $3); + } - members = webidl_node_new(WEBIDL_NODE_TYPE_LIST, members, $5); + members = webidl_node_new(WEBIDL_NODE_TYPE_LIST, members, $5); - interface_node = webidl_node_find_type_ident(*webidl_ast, + interface_node = webidl_node_find_type_ident(*webidl_ast, WEBIDL_NODE_TYPE_INTERFACE, - $2); + $2); - if (interface_node == NULL) { - /* no existing interface - create one with ident */ - members = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, members, $2); + if (interface_node == NULL) { + /* no existing interface - create one with ident */ + members = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, + members, + $2); - $$ = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE, NULL, members); - } else { - /* update the existing interface */ + $$ = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE, + NULL, + members); + } else { + /* update the existing interface */ - /* link member node into interfaces_node */ - webidl_node_add(interface_node, members); + /* link member node into interfaces_node */ + webidl_node_add(interface_node, members); - $$ = NULL; /* updating so no need to add a new node */ - } + $$ = NULL; /* updating so no need to add a new node */ + } } ; @@ -353,64 +366,65 @@ PartialInterface: /* [9] slightly altered from original grammar to be left recursive */ InterfaceMembers: - /* empty */ { - $$ = NULL; + $$ = NULL; /* empty */ } | InterfaceMembers ExtendedAttributeList InterfaceMember - /* This needs to deal with members with the same identifier which - * indicate polymorphism. this is handled in the AST by adding the - * argument lists for each polymorphism to the same - * WEBIDL_NODE_TYPE_OPERATION - * - * @todo need to consider qualifer/stringifier compatibility - */ - { - struct webidl_node *member_node; - struct webidl_node *ident_node; - struct webidl_node *list_node; - - ident_node = webidl_node_find_type(webidl_node_getnode($3), - NULL, - WEBIDL_NODE_TYPE_IDENT); - - list_node = webidl_node_find_type(webidl_node_getnode($3), - NULL, - WEBIDL_NODE_TYPE_LIST); - - if (ident_node == NULL) { - /* something with no ident - possibly constructors? */ - /* @todo understand this better */ - - $$ = webidl_node_prepend($1, $3); - - } else if (list_node == NULL) { - /* member with no argument list, usually an attribute, cannot - * be polymorphic + { + /* This needs to deal with members with the same + * identifier which indicate polymorphism. this is + * handled in the AST by adding the argument lists for + * each polymorphism to the same + * WEBIDL_NODE_TYPE_OPERATION + * + * @todo need to consider qualifer/stringifier compatibility */ + struct webidl_node *member_node; + struct webidl_node *ident_node; + struct webidl_node *list_node; - /* add extended attributes to parameter list */ - webidl_node_add($3, $2); + ident_node = webidl_node_find_type(webidl_node_getnode($3), + NULL, + WEBIDL_NODE_TYPE_IDENT); - $$ = webidl_node_prepend($1, $3); + list_node = webidl_node_find_type(webidl_node_getnode($3), + NULL, + WEBIDL_NODE_TYPE_LIST); + + if (ident_node == NULL) { + /* something with no ident - possibly constructors? */ + /* @todo understand this better */ + + $$ = webidl_node_prepend($1, $3); + + } else if (list_node == NULL) { + /* member with no argument list, usually an + * attribute, cannot be polymorphic + */ + + /* add extended attributes to parameter list */ + webidl_node_add($3, $2); + + $$ = webidl_node_prepend($1, $3); - } else { - /* add extended attributes to parameter list */ - webidl_node_add(list_node, $2); - - /* has an arguemnt list so can be polymorphic */ - member_node = webidl_node_find_type_ident($1, - webidl_node_gettype($3), - webidl_node_gettext(ident_node)); - if (member_node == NULL) { - /* not a member with that ident already present */ - $$ = webidl_node_prepend($1, $3); } else { - webidl_node_add(member_node, list_node); - $$ = $1; /* updated existing node do not add new one */ + /* add extended attributes to parameter list */ + webidl_node_add(list_node, $2); + + /* has an arguemnt list so can be polymorphic */ + member_node = webidl_node_find_type_ident( + $1, + webidl_node_gettype($3), + webidl_node_gettext(ident_node)); + if (member_node == NULL) { + /* not a member with that ident already present */ + $$ = webidl_node_prepend($1, $3); + } else { + webidl_node_add(member_node, list_node); + $$ = $1; /* updated existing node do not add new one */ + } } - } } ; @@ -433,28 +447,134 @@ InterfaceMember: Dictionary: TOK_DICTIONARY TOK_IDENTIFIER Inheritance '{' DictionaryMembers '}' ';' { - $$ = NULL; + /* extend dictionary with additional members */ + struct webidl_node *dictionary_node; + struct webidl_node *members = NULL; + + if ($3 != NULL) { + members = webidl_node_new(WEBIDL_NODE_TYPE_INHERITANCE, + members, + $3); + } + + members = webidl_node_new(WEBIDL_NODE_TYPE_LIST, members, $5); + + dictionary_node = webidl_node_find_type_ident( + *webidl_ast, + WEBIDL_NODE_TYPE_DICTIONARY, + $2); + + if (dictionary_node == NULL) { + /* no existing interface - create one with ident */ + members = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, + members, + $2); + + $$ = webidl_node_new(WEBIDL_NODE_TYPE_DICTIONARY, + NULL, + members); + } else { + /* update the existing interface */ + + /* link member node into interfaces_node */ + webidl_node_add(dictionary_node, members); + + $$ = NULL; /* updating so no need to add a new node */ + } } ; - /* [12] */ + /* SE[12] */ DictionaryMembers: - /* empty */ + { + $$ = NULL; /* empty */ + } | ExtendedAttributeList DictionaryMember DictionaryMembers + { + /** \todo handle ExtendedAttributeList */ + $$ = webidl_node_append($3, $2); + } ; - /* [13] */ + /* SE[13] + * Second edition introduces Required except required type may not + * have default so why not express this in grammar here and remove + * rule 14? + */ DictionaryMember: + TOK_REQUIRED Type TOK_IDENTIFIER ';' + { + struct webidl_node *member; + /* add name */ + member = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, NULL, $3); + /* add type node */ + member = webidl_node_prepend(member, $2); + + $$ = webidl_node_new(WEBIDL_NODE_TYPE_ARGUMENT, NULL, member); + } + | Type TOK_IDENTIFIER Default ';' + { + struct webidl_node *member; + /* add name */ + member = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, NULL, $2); + /* add default */ + member = webidl_node_new(WEBIDL_NODE_TYPE_OPTIONAL, member, $3); + /* add type node */ + member = webidl_node_prepend(member, $1); + + $$ = webidl_node_new(WEBIDL_NODE_TYPE_ARGUMENT, NULL, member); + } ; +/* SE[14] */ +//Required: +// { +// $$ = false; /* empty */ +// } +// | +// TOK_REQUIRED +// { +// $$ = true; +// } +// ; + /* [14] */ PartialDictionary: TOK_DICTIONARY TOK_IDENTIFIER '{' DictionaryMembers '}' ';' { - $$ = NULL; + /* extend dictionary with additional members */ + struct webidl_node *members; + struct webidl_node *dictionary_node; + + dictionary_node = webidl_node_find_type_ident( + *webidl_ast, + WEBIDL_NODE_TYPE_DICTIONARY, + $2); + + members = webidl_node_new(WEBIDL_NODE_TYPE_LIST, NULL, $4); + + if (dictionary_node == NULL) { + /* doesnt already exist so create it */ + + members = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, + members, + $2); + + $$ = webidl_node_new(WEBIDL_NODE_TYPE_DICTIONARY, + NULL, + members); + } else { + /* update the existing dictionary */ + + /* link member node into dictionary node */ + webidl_node_add(dictionary_node, members); + + $$ = NULL; /* updating so no need to add a new node */ + } } + ; /* [15] */ Default: @@ -778,12 +898,25 @@ StaticMemberRest: /* SE[42] */ AttributeRest: - TOK_ATTRIBUTE Type TOK_IDENTIFIER ';' + TOK_ATTRIBUTE Type AttributeName ';' { $$ = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, $2, $3); } ; +/* SE[43] */ +AttributeName: + AttributeNameKeyword + | + TOK_IDENTIFIER + ; + +/* SE[44] */ +AttributeNameKeyword: + TOK_REQUIRED + { + $$ = strdup("required"); + } /* [33] * SE[45] @@ -1333,7 +1466,9 @@ Other: } ; - /* [55] */ + /* [55] + * SE[71] extended with new keywords + */ ArgumentNameKeyword: TOK_ATTRIBUTE { @@ -1395,16 +1530,31 @@ ArgumentNameKeyword: $$ = strdup("interface"); } | + TOK_ITERABLE + { + $$ = strdup("iterable"); + } + | TOK_LEGACYCALLER { $$ = strdup("legacycaller"); } | + TOK_LEGACYITERABLE + { + $$ = strdup("legacyiterable"); + } + | TOK_PARTIAL { $$ = strdup("partial"); } | + TOK_REQUIRED + { + $$ = strdup("required"); + } + | TOK_SETTER { $$ = strdup("setter"); -- cgit v1.2.3