[qfcc] Handle protocol forward declarations

This commit is contained in:
Bill Currie 2020-03-01 19:37:40 +09:00
parent 92cb3a5285
commit 254bf29bd4
2 changed files with 37 additions and 12 deletions

View file

@ -515,7 +515,11 @@ class_add_protocols (class_t *class, protocollist_t *protocols)
for (i = 0; i < protocols->count; i++) { for (i = 0; i < protocols->count; i++) {
p = protocols->list[i]; p = protocols->list[i];
if (p->methods) {
copy_methods (methods, p->methods); copy_methods (methods, p->methods);
} else {
warning (0, "definition of protocol `%s' not found", p->name);
}
if (p->protocols) if (p->protocols)
class_add_protocols (class, p->protocols); class_add_protocols (class, p->protocols);
} }
@ -1356,7 +1360,7 @@ get_protocol (const char *name, int create)
p = calloc (sizeof (protocol_t), 1); p = calloc (sizeof (protocol_t), 1);
p->name = name; p->name = name;
p->methods = new_methodlist (); p->methods = 0;
p->class_type.type = ct_protocol; p->class_type.type = ct_protocol;
p->class_type.c.protocol = p; p->class_type.c.protocol = p;
if (name) if (name)

View file

@ -192,7 +192,7 @@ int yylex (void);
%type <symbol> overloaded_identifier %type <symbol> overloaded_identifier
%type <expr> identifier_list %type <expr> identifier_list
%type <symbol> selector reserved_word %type <symbol> protocol_name_list selector reserved_word
%type <param> optional_param_list unaryselector keyworddecl %type <param> optional_param_list unaryselector keyworddecl
%type <param> keywordselector %type <param> keywordselector
%type <method> methodproto methoddecl %type <method> methodproto methoddecl
@ -1443,6 +1443,7 @@ identifier
obj_def obj_def
: classdef { } : classdef { }
| classdecl | classdecl
| protocoldecl
| protocoldef | protocoldef
| { if (!current_class) PARSE_ERROR; } methoddef | { if (!current_class) PARSE_ERROR; } methoddef
| END | END
@ -1570,17 +1571,18 @@ category_reference
} }
; ;
protocol_name protocol_name
: identifier : identifier
{ {
$$ = get_protocol ($1->name, 0); $$ = get_protocol ($1->name, 0);
if ($$) { if ($$ && $$->methods) {
error (0, "redefinition of %s", $1->name); error (0, "redefinition of protocol %s", $1->name);
$$ = get_protocol (0, 1); $$ = get_protocol (0, 1);
} else { }
if (!$$) {
$$ = get_protocol ($1->name, 1); $$ = get_protocol ($1->name, 1);
} }
$$->methods = new_methodlist ();
current_class = &$$->class_type; current_class = &$$->class_type;
} }
; ;
@ -1673,18 +1675,33 @@ classdef
| REFERENCE category_reference ';' { } | REFERENCE category_reference ';' { }
; ;
protocoldecl
: protocol
protocol_name_list ';'
{
while ($2) {
get_protocol ($2->name, 1);
$2 = $2->next;
}
}
;
protocoldef protocoldef
: PROTOCOL { $<class_type>$ = current_class; } : protocol
protocol_name protocol_name
protocolrefs { protocol_add_protocols ($3, $4); $<class>$ = 0; } protocolrefs { protocol_add_protocols ($2, $3); $<class>$ = 0; }
methodprotolist { protocol_add_methods ($3, $6); } methodprotolist { protocol_add_methods ($2, $5); }
END END
{ {
current_class = $<class_type>2; current_class = $<class_type>1;
(void) ($<class>5); (void) ($<class>4);
} }
; ;
protocol
: PROTOCOL { $<class_type>$ = current_class; }
;
protocolrefs protocolrefs
: /* emtpy */ { $$ = 0; } : /* emtpy */ { $$ = 0; }
| LT { $<protocol_list>$ = new_protocol_list (); } | LT { $<protocol_list>$ = new_protocol_list (); }
@ -1870,6 +1887,10 @@ keywordselector
| keywordselector keyworddecl { $2->next = $1; $$ = $2; } | keywordselector keyworddecl { $2->next = $1; $$ = $2; }
; ;
protocol_name_list
: identifier
| protocol_name_list ',' identifier { $3->next = $1; $$ = $3; }
selector selector
: NAME { $$ = $1; } : NAME { $$ = $1; }
| CLASS_NAME { $$ = $1; } | CLASS_NAME { $$ = $1; }