summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vincent.sanders@collabora.co.uk>2012-10-04 19:08:39 +0100
committerVincent Sanders <vincent.sanders@collabora.co.uk>2012-10-04 19:08:39 +0100
commitf09b0cb293c034df8efccdce12235e74a5ae6d13 (patch)
tree901617e8dd7aabe512aa0eb4d12c3c13c618dbbb
parent35f2b9fc8120776bbd5e6f2aa3ddf68ddb46bf33 (diff)
downloadnsgenbind-f09b0cb293c034df8efccdce12235e74a5ae6d13.tar.gz
nsgenbind-f09b0cb293c034df8efccdce12235e74a5ae6d13.tar.bz2
fix polymorphism in teh AST generation
-rw-r--r--src/webidl-ast.c75
-rw-r--r--src/webidl-ast.h5
-rw-r--r--src/webidl-parser.y144
3 files changed, 154 insertions, 70 deletions
diff --git a/src/webidl-ast.c b/src/webidl-ast.c
index 8160d55..084c199 100644
--- a/src/webidl-ast.c
+++ b/src/webidl-ast.c
@@ -31,16 +31,24 @@ struct webidl_node {
} r;
};
-/* insert node at beginning of a list */
+/* insert node(s) at beginning of a list */
struct webidl_node *
-webidl_node_prepend(struct webidl_node *list, struct webidl_node *node)
+webidl_node_prepend(struct webidl_node *list, struct webidl_node *inst)
{
- if (node == NULL) {
+ struct webidl_node *end = inst;
+
+ if (inst == NULL) {
return list; /* no node to prepend - return existing list */
}
- node->l = list;
- return node;
+ /* find end of inserted node list */
+ while (end->l != NULL) {
+ end = end->l;
+ }
+
+ end->l = list;
+
+ return inst;
}
/* append node at end of a list */
@@ -61,13 +69,33 @@ webidl_node_append(struct webidl_node *list, struct webidl_node *node)
return list;
}
+/* prepend list to a nodes list
+ *
+ * inserts a list into the beginning of a nodes r list
+ *
+ * CAUTION: if the \a node element is not a node type the node will not be added
+ */
struct webidl_node *
-webidl_add_interface_member(struct webidl_node *list, struct webidl_node *new)
+webidl_node_add(struct webidl_node *node, struct webidl_node *list)
{
- return webidl_node_prepend(list, new);
+ struct webidl_node *node_list;
+
+ node_list = webidl_node_getnode(node);
+ if (node_list == NULL) {
+ /* not a node type node */
+ return list;
+ }
+
+ node->r.node = webidl_node_prepend(node_list, list);
+
+ return node;
}
-struct webidl_node *webidl_node_new(enum webidl_node_type type, struct webidl_node *l, void *r)
+
+struct webidl_node *
+webidl_node_new(enum webidl_node_type type,
+ struct webidl_node *l,
+ void *r)
{
struct webidl_node *nn;
nn = calloc(1, sizeof(struct webidl_node));
@@ -77,11 +105,11 @@ struct webidl_node *webidl_node_new(enum webidl_node_type type, struct webidl_no
return nn;
}
-void
+void
webidl_node_set(struct webidl_node *node, enum webidl_node_type type, void *r)
{
node->type = type;
- node->r.value = r;
+ node->r.value = r;
}
int
@@ -117,7 +145,7 @@ webidl_node_find(struct webidl_node *node,
{
struct webidl_node *ret;
- if ((node == NULL) || (node == prev)){
+ if ((node == NULL) || (node == prev)) {
return NULL;
}
@@ -143,8 +171,8 @@ int webidl_cmp_node_type(struct webidl_node *node, void *ctx)
}
struct webidl_node *
-webidl_node_find_type_ident(struct webidl_node *root_node,
- enum webidl_node_type type,
+webidl_node_find_type_ident(struct webidl_node *root_node,
+ enum webidl_node_type type,
const char *ident)
{
struct webidl_node *node;
@@ -205,6 +233,13 @@ webidl_node_getint(struct webidl_node *node)
return -1;
}
+
+enum webidl_node_type webidl_node_gettype(struct webidl_node *node)
+{
+ return node->type;
+}
+
+
struct webidl_node *webidl_node_getnode(struct webidl_node *node)
{
if (node != NULL) {
@@ -217,6 +252,7 @@ struct webidl_node *webidl_node_getnode(struct webidl_node *node)
case WEBIDL_NODE_TYPE_OPTIONAL_ARGUMENT:
case WEBIDL_NODE_TYPE_ARGUMENT:
case WEBIDL_NODE_TYPE_TYPE:
+ case WEBIDL_NODE_TYPE_CONST:
return node->r.node;
default:
break;
@@ -268,6 +304,9 @@ static const char *webidl_node_type_to_str(enum webidl_node_type type)
case WEBIDL_NODE_TYPE_MODIFIER:
return "Modifier";
+ case WEBIDL_NODE_TYPE_CONST:
+ return "Const";
+
default:
return "Unknown";
}
@@ -310,7 +349,7 @@ static FILE *idlopen(const char *filename)
if (options->verbose) {
printf("Opening IDL file %s\n", filename);
}
- idlfile = fopen(filename, "r");
+ idlfile = fopen(filename, "r");
} else {
char *fullname;
int fulllen = strlen(options->idlpath) + strlen(filename) + 2;
@@ -319,7 +358,7 @@ static FILE *idlopen(const char *filename)
if (options->verbose) {
printf("Opening IDL file %s\n", fullname);
}
- idlfile = fopen(fullname, "r");
+ idlfile = fopen(fullname, "r");
free(fullname);
}
return idlfile;
@@ -327,13 +366,13 @@ static FILE *idlopen(const char *filename)
int webidl_parsefile(char *filename, struct webidl_node **webidl_ast)
{
-
+
FILE *idlfile;
idlfile = idlopen(filename);
if (!idlfile) {
fprintf(stderr, "Error opening %s: %s\n",
- filename,
+ filename,
strerror(errno));
return 2;
}
@@ -345,7 +384,7 @@ int webidl_parsefile(char *filename, struct webidl_node **webidl_ast)
/* set flex to read from file */
webidl_restart(idlfile);
-
+
/* parse the file */
return webidl_parse(webidl_ast);
}
diff --git a/src/webidl-ast.h b/src/webidl-ast.h
index 7f21df5..0e38b8c 100644
--- a/src/webidl-ast.h
+++ b/src/webidl-ast.h
@@ -23,6 +23,7 @@ enum webidl_node_type {
WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE,
WEBIDL_NODE_TYPE_ATTRIBUTE,
WEBIDL_NODE_TYPE_OPERATION,
+ WEBIDL_NODE_TYPE_CONST,
WEBIDL_NODE_TYPE_OPTIONAL_ARGUMENT,
WEBIDL_NODE_TYPE_ARGUMENT,
WEBIDL_NODE_TYPE_ELLIPSIS,
@@ -67,13 +68,13 @@ void webidl_node_set(struct webidl_node *node, enum webidl_node_type type, void
struct webidl_node *webidl_node_prepend(struct webidl_node *list, struct webidl_node *node);
struct webidl_node *webidl_node_append(struct webidl_node *list, struct webidl_node *node);
-struct webidl_node *webidl_add_interface_member(struct webidl_node *list, struct webidl_node *new);
+struct webidl_node *webidl_node_add(struct webidl_node *node, struct webidl_node *list);
/* node contents acessors */
char *webidl_node_gettext(struct webidl_node *node);
struct webidl_node *webidl_node_getnode(struct webidl_node *node);
int webidl_node_getint(struct webidl_node *node);
-
+enum webidl_node_type webidl_node_gettype(struct webidl_node *node);
/* node searches */
int webidl_node_for_each_type(struct webidl_node *node,
diff --git a/src/webidl-parser.y b/src/webidl-parser.y
index 81f0dfc..7d93a4e 100644
--- a/src/webidl-parser.y
+++ b/src/webidl-parser.y
@@ -236,40 +236,30 @@ Interface:
{
/* 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);
+ }
+
+ members = webidl_node_new(WEBIDL_NODE_TYPE_LIST, members, $5);
+
+
interface_node = webidl_node_find_type_ident(*webidl_ast,
WEBIDL_NODE_TYPE_INTERFACE,
$2);
if (interface_node == NULL) {
- struct webidl_node *members;
- struct webidl_node *ident;
- struct webidl_node *inheritance = NULL;
-
- if ($3 != NULL) {
- inheritance = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE, NULL, $3);
- }
-
- members = webidl_node_new(WEBIDL_NODE_TYPE_LIST, inheritance, $5);
+ /* no existing interface - create one with ident */
+ members = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, members, $2);
- ident = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, members, $2);
-
- $$ = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE, NULL, ident);
+ $$ = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE, NULL, members);
} else {
- struct webidl_node *members;
- struct webidl_node *inheritance = webidl_node_getnode(interface_node);
-
- if ($3 != NULL) {
- inheritance = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE, inheritance, $3);
- }
-
- members = webidl_node_new(WEBIDL_NODE_TYPE_LIST,
- inheritance,
- $5);
+ /* update the existing interface */
/* link member node into interfaces_node */
- webidl_node_set(interface_node,
- WEBIDL_NODE_TYPE_INTERFACE,
- members);
- $$ = NULL; /* updated existing interface do not add it again */
+ webidl_node_add(interface_node, members);
+
+ $$ = NULL; /* updating so no need to add a new node */
}
}
;
@@ -294,33 +284,28 @@ PartialInterface:
TOK_INTERFACE TOK_IDENTIFIER '{' InterfaceMembers '}' ';'
{
/* extend interface with additional members */
+ struct webidl_node *members;
struct webidl_node *interface_node;
+
interface_node = webidl_node_find_type_ident(*webidl_ast,
WEBIDL_NODE_TYPE_INTERFACE,
$2);
- if (interface_node == NULL) {
- /* doesnt already exist so create it */
- struct webidl_node *members;
- struct webidl_node *ident;
- members = webidl_node_new(WEBIDL_NODE_TYPE_LIST, NULL, $4);
+ members = webidl_node_new(WEBIDL_NODE_TYPE_LIST, NULL, $4);
- ident = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, members, $2);
+ if (interface_node == NULL) {
+ /* doesnt already exist so create it */
- $$ = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE, NULL, ident);
+ members = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, members, $2);
+ $$ = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE, NULL, members);
} else {
- struct webidl_node *members;
- members = webidl_node_new(WEBIDL_NODE_TYPE_LIST,
- webidl_node_getnode(interface_node),
- $4);
+ /* update the existing interface */
/* link member node into interfaces_node */
- webidl_node_set(interface_node,
- WEBIDL_NODE_TYPE_INTERFACE,
- members);
+ webidl_node_add(interface_node, members);
- $$ = NULL; /* updated existing interface do not add it again */
+ $$ = NULL; /* updating so no need to add a new node */
}
}
;
@@ -333,8 +318,54 @@ InterfaceMembers:
}
|
InterfaceMembers ExtendedAttributeList InterfaceMember
- {
- $$ = webidl_add_interface_member($1, $3);
+ /* 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(webidl_node_getnode($3),
+ NULL,
+ webidl_cmp_node_type,
+ (void *)WEBIDL_NODE_TYPE_IDENT);
+
+ list_node = webidl_node_find(webidl_node_getnode($3),
+ NULL,
+ webidl_cmp_node_type,
+ (void *)WEBIDL_NODE_TYPE_LIST);
+
+ if (ident_node == NULL) {
+ /* something with no ident - possibly constructors? */
+ /* @todo understand this abtter */
+
+ $$ = webidl_node_prepend($1, $3);
+ } else if (list_node == NULL) {
+ /* something with no argument list - cannot be polymorphic */
+ $$ = webidl_node_prepend($1, $3);
+ } else {
+ /* 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 {
+
+ fprintf(stderr,
+ "HERE: New polymorphic member %p, ident node %p (%s), list node %p\n",
+ (void *)$3, (void *)ident_node, webidl_node_gettext(ident_node), (void *)list_node);
+
+ webidl_node_add(member_node, list_node);
+ $$ = $1; /* updated existing node do not add new one */
+ }
+ }
}
;
@@ -462,7 +493,18 @@ ImplementsStatement:
Const:
TOK_CONST ConstType TOK_IDENTIFIER '=' ConstValue ';'
{
- $$ = NULL;
+ struct webidl_node *constant;
+
+ constant = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, NULL, $3);
+
+ /* add constant type */
+ //constant = webidl_node_prepend(constant, $2);
+
+ /* add constant value */
+ //constant = webidl_node_prepend(constant, $5);
+
+ $$ = webidl_node_new(WEBIDL_NODE_TYPE_CONST, NULL, constant);
+
}
;
@@ -512,6 +554,10 @@ StringifierAttributeOrOperation:
Attribute
|
OperationRest
+ {
+ /* @todo deal with stringifier */
+ $$ = webidl_node_new(WEBIDL_NODE_TYPE_OPERATION, NULL, $1);
+ }
|
';'
{
@@ -570,7 +616,8 @@ ReadOnly:
Operation:
Qualifiers OperationRest
{
- $$=$2;
+ /* @todo fix qualifiers */
+ $$ = webidl_node_new(WEBIDL_NODE_TYPE_OPERATION, NULL, $2);
}
;
@@ -605,18 +652,15 @@ Special:
OperationRest:
ReturnType OptionalIdentifier '(' ArgumentList ')' ';'
{
- struct webidl_node *operation;
struct webidl_node *arglist;
/* put return type in argument list */
arglist = webidl_node_prepend($4, $1);
/* argument list */
- operation = webidl_node_new(WEBIDL_NODE_TYPE_LIST, NULL, arglist);
-
- operation = webidl_node_prepend(operation, $2); /* identifier */
+ $$ = webidl_node_new(WEBIDL_NODE_TYPE_LIST, NULL, arglist);
- $$ = webidl_node_new(WEBIDL_NODE_TYPE_OPERATION, NULL, operation);
+ $$ = webidl_node_prepend($$, $2); /* identifier */
}
;