Release 0.7.8
[vala-lang.git] / vala / valaparser.vala
blob6828341f0b323da57d37113b3ce0c9cef5a6db9b
1 /* valaparser.vala
3 * Copyright (C) 2006-2009 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
25 /**
26 * Code visitor parsing all Vala source files.
28 public class Vala.Parser : CodeVisitor {
29 Scanner scanner;
31 CodeContext context;
33 // token buffer
34 TokenInfo[] tokens;
35 // index of current token in buffer
36 int index;
37 // number of tokens in buffer
38 int size;
40 Comment comment;
42 const int BUFFER_SIZE = 32;
44 struct TokenInfo {
45 public TokenType type;
46 public SourceLocation begin;
47 public SourceLocation end;
50 enum ModifierFlags {
51 NONE,
52 ABSTRACT = 1 << 0,
53 CLASS = 1 << 1,
54 EXTERN = 1 << 2,
55 INLINE = 1 << 3,
56 NEW = 1 << 4,
57 OVERRIDE = 1 << 5,
58 STATIC = 1 << 6,
59 VIRTUAL = 1 << 7,
60 ASYNC = 1 << 8
63 public Parser () {
64 tokens = new TokenInfo[BUFFER_SIZE];
67 /**
68 * Parses all .vala and .vapi source files in the specified code
69 * context and builds a code tree.
71 * @param context a code context
73 public void parse (CodeContext context) {
74 this.context = context;
75 context.accept (this);
78 public override void visit_source_file (SourceFile source_file) {
79 if (source_file.filename.has_suffix (".vala") || source_file.filename.has_suffix (".vapi")) {
80 parse_file (source_file);
84 inline bool next () {
85 index = (index + 1) % BUFFER_SIZE;
86 size--;
87 if (size <= 0) {
88 SourceLocation begin, end;
89 TokenType type = scanner.read_token (out begin, out end);
90 tokens[index].type = type;
91 tokens[index].begin = begin;
92 tokens[index].end = end;
93 size = 1;
95 return (tokens[index].type != TokenType.EOF);
98 inline void prev () {
99 index = (index - 1 + BUFFER_SIZE) % BUFFER_SIZE;
100 size++;
101 assert (size <= BUFFER_SIZE);
104 inline TokenType current () {
105 return tokens[index].type;
108 inline bool accept (TokenType type) {
109 if (current () == type) {
110 next ();
111 return true;
113 return false;
116 string get_error (string msg) {
117 var begin = get_location ();
118 next ();
119 Report.error (get_src (begin), "syntax error, " + msg);
120 return msg;
123 inline bool expect (TokenType type) throws ParseError {
124 if (accept (type)) {
125 return true;
128 throw new ParseError.SYNTAX (get_error ("expected %s".printf (type.to_string ())));
131 inline SourceLocation get_location () {
132 return tokens[index].begin;
135 string get_current_string () {
136 return ((string) tokens[index].begin.pos).ndup ((tokens[index].end.pos - tokens[index].begin.pos));
139 string get_last_string () {
140 int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE;
141 return ((string) tokens[last_index].begin.pos).ndup ((tokens[last_index].end.pos - tokens[last_index].begin.pos));
144 SourceReference get_src (SourceLocation begin) {
145 int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE;
147 return new SourceReference (scanner.source_file, begin.line, begin.column, tokens[last_index].end.line, tokens[last_index].end.column);
150 SourceReference get_current_src () {
151 return new SourceReference (scanner.source_file, tokens[index].begin.line, tokens[index].begin.column, tokens[index].end.line, tokens[index].end.column);
154 SourceReference get_last_src () {
155 int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE;
157 return new SourceReference (scanner.source_file, tokens[last_index].begin.line, tokens[last_index].begin.column, tokens[last_index].end.line, tokens[last_index].end.column);
160 void rollback (SourceLocation location) {
161 while (tokens[index].begin.pos != location.pos) {
162 prev ();
166 void skip_identifier () throws ParseError {
167 // also accept keywords as identifiers where there is no conflict
168 switch (current ()) {
169 case TokenType.ABSTRACT:
170 case TokenType.AS:
171 case TokenType.ASYNC:
172 case TokenType.BASE:
173 case TokenType.BREAK:
174 case TokenType.CASE:
175 case TokenType.CATCH:
176 case TokenType.CLASS:
177 case TokenType.CONST:
178 case TokenType.CONSTRUCT:
179 case TokenType.CONTINUE:
180 case TokenType.DEFAULT:
181 case TokenType.DELEGATE:
182 case TokenType.DELETE:
183 case TokenType.DO:
184 case TokenType.DYNAMIC:
185 case TokenType.ELSE:
186 case TokenType.ENUM:
187 case TokenType.ENSURES:
188 case TokenType.ERRORDOMAIN:
189 case TokenType.EXTERN:
190 case TokenType.FALSE:
191 case TokenType.FINALLY:
192 case TokenType.FOR:
193 case TokenType.FOREACH:
194 case TokenType.GET:
195 case TokenType.IDENTIFIER:
196 case TokenType.IF:
197 case TokenType.IN:
198 case TokenType.INLINE:
199 case TokenType.INTERFACE:
200 case TokenType.INTERNAL:
201 case TokenType.IS:
202 case TokenType.LOCK:
203 case TokenType.NAMESPACE:
204 case TokenType.NEW:
205 case TokenType.NULL:
206 case TokenType.OUT:
207 case TokenType.OVERRIDE:
208 case TokenType.OWNED:
209 case TokenType.PARAMS:
210 case TokenType.PRIVATE:
211 case TokenType.PROTECTED:
212 case TokenType.PUBLIC:
213 case TokenType.REF:
214 case TokenType.REQUIRES:
215 case TokenType.RETURN:
216 case TokenType.SET:
217 case TokenType.SIGNAL:
218 case TokenType.SIZEOF:
219 case TokenType.STATIC:
220 case TokenType.STRUCT:
221 case TokenType.SWITCH:
222 case TokenType.THIS:
223 case TokenType.THROW:
224 case TokenType.THROWS:
225 case TokenType.TRUE:
226 case TokenType.TRY:
227 case TokenType.TYPEOF:
228 case TokenType.UNOWNED:
229 case TokenType.USING:
230 case TokenType.VAR:
231 case TokenType.VIRTUAL:
232 case TokenType.VOID:
233 case TokenType.VOLATILE:
234 case TokenType.WEAK:
235 case TokenType.WHILE:
236 case TokenType.YIELD:
237 next ();
238 return;
239 case TokenType.INTEGER_LITERAL:
240 case TokenType.REAL_LITERAL:
241 // also accept integer and real literals
242 // as long as they contain at least one character
243 // and no decimal point
244 // for example, 2D and 3D
245 string id = get_current_string ();
246 if (id[id.length - 1].isalpha () && !("." in id)) {
247 next ();
248 return;
250 break;
251 default:
252 throw new ParseError.SYNTAX (get_error ("expected identifier"));
256 string parse_identifier () throws ParseError {
257 skip_identifier ();
258 return get_last_string ();
261 Expression parse_literal () throws ParseError {
262 var begin = get_location ();
264 switch (current ()) {
265 case TokenType.TRUE:
266 next ();
267 return new BooleanLiteral (true, get_src (begin));
268 case TokenType.FALSE:
269 next ();
270 return new BooleanLiteral (false, get_src (begin));
271 case TokenType.INTEGER_LITERAL:
272 next ();
273 return new IntegerLiteral (get_last_string (), get_src (begin));
274 case TokenType.REAL_LITERAL:
275 next ();
276 return new RealLiteral (get_last_string (), get_src (begin));
277 case TokenType.CHARACTER_LITERAL:
278 next ();
279 // FIXME validate and unescape here and just pass unichar to CharacterLiteral
280 var lit = new CharacterLiteral (get_last_string (), get_src (begin));
281 if (lit.error) {
282 Report.error (lit.source_reference, "invalid character literal");
284 return lit;
285 case TokenType.STRING_LITERAL:
286 next ();
287 return new StringLiteral (get_last_string (), get_src (begin));
288 case TokenType.TEMPLATE_STRING_LITERAL:
289 next ();
290 return new StringLiteral ("\"%s\"".printf (get_last_string ()), get_src (begin));
291 case TokenType.VERBATIM_STRING_LITERAL:
292 next ();
293 string raw_string = get_last_string ();
294 string escaped_string = raw_string.substring (3, raw_string.len () - 6).escape ("");
295 return new StringLiteral ("\"%s\"".printf (escaped_string), get_src (begin));
296 case TokenType.NULL:
297 next ();
298 return new NullLiteral (get_src (begin));
299 default:
300 throw new ParseError.SYNTAX (get_error ("expected literal"));
304 public void parse_file (SourceFile source_file) {
305 scanner = new Scanner (source_file);
306 parse_file_comments ();
308 index = -1;
309 size = 0;
311 next ();
314 try {
315 parse_using_directives (context.root);
316 parse_declarations (context.root, true);
317 if (accept (TokenType.CLOSE_BRACE)) {
318 // only report error if it's not a secondary error
319 if (context.report.get_errors () == 0) {
320 Report.error (get_last_src (), "unexpected `}'");
323 } catch (ParseError e) {
324 // already reported
327 scanner = null;
330 void parse_file_comments () {
331 scanner.parse_file_comments ();
334 void skip_symbol_name () throws ParseError {
335 do {
336 skip_identifier ();
337 } while (accept (TokenType.DOT) || accept (TokenType.DOUBLE_COLON));
340 UnresolvedSymbol parse_symbol_name () throws ParseError {
341 var begin = get_location ();
342 UnresolvedSymbol sym = null;
343 do {
344 string name = parse_identifier ();
345 if (name == "global" && accept (TokenType.DOUBLE_COLON)) {
346 // global::Name
347 // qualified access to global symbol
348 name = parse_identifier ();
349 sym = new UnresolvedSymbol (sym, name, get_src (begin));
350 sym.qualified = true;
351 continue;
353 sym = new UnresolvedSymbol (sym, name, get_src (begin));
354 } while (accept (TokenType.DOT));
355 return sym;
358 void skip_type () throws ParseError {
359 if (accept (TokenType.VOID)) {
360 while (accept (TokenType.STAR)) {
362 return;
364 accept (TokenType.DYNAMIC);
365 accept (TokenType.OWNED);
366 accept (TokenType.UNOWNED);
367 accept (TokenType.WEAK);
368 skip_symbol_name ();
369 skip_type_argument_list ();
370 while (accept (TokenType.STAR)) {
372 accept (TokenType.INTERR);
373 while (accept (TokenType.OPEN_BRACKET)) {
374 do {
375 // required for decision between expression and declaration statement
376 if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
377 parse_expression ();
379 } while (accept (TokenType.COMMA));
380 expect (TokenType.CLOSE_BRACKET);
381 accept (TokenType.INTERR);
383 accept (TokenType.OP_NEG);
384 accept (TokenType.HASH);
387 DataType parse_type (bool owned_by_default = true) throws ParseError {
388 var begin = get_location ();
390 if (accept (TokenType.VOID)) {
391 DataType type = new VoidType (get_src (begin));
392 while (accept (TokenType.STAR)) {
393 type = new PointerType (type);
395 return type;
398 bool is_dynamic = accept (TokenType.DYNAMIC);
400 bool value_owned = owned_by_default;
402 if (owned_by_default) {
403 if (accept (TokenType.UNOWNED)
404 || accept (TokenType.WEAK)) {
405 value_owned = false;
407 } else {
408 value_owned = accept (TokenType.OWNED);
411 var sym = parse_symbol_name ();
412 List<DataType> type_arg_list = parse_type_argument_list (false);
414 DataType type = new UnresolvedType.from_symbol (sym, get_src (begin));
415 if (type_arg_list != null) {
416 foreach (DataType type_arg in type_arg_list) {
417 type.add_type_argument (type_arg);
421 while (accept (TokenType.STAR)) {
422 type = new PointerType (type, get_src (begin));
425 if (!(type is PointerType)) {
426 type.nullable = accept (TokenType.INTERR);
429 // array brackets in types are read from right to left,
430 // this is more logical, especially when nullable arrays
431 // or pointers are involved
432 while (accept (TokenType.OPEN_BRACKET)) {
433 bool invalid_array = false;
434 int array_rank = 0;
435 do {
436 array_rank++;
437 // required for decision between expression and declaration statement
438 if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
439 parse_expression ();
440 // only used for parsing, reject use as real type
441 invalid_array = true;
443 } while (accept (TokenType.COMMA));
444 expect (TokenType.CLOSE_BRACKET);
446 // arrays contain strong references by default
447 type.value_owned = true;
449 var array_type = new ArrayType (type, array_rank, get_src (begin));
450 array_type.nullable = accept (TokenType.INTERR);
451 array_type.invalid_syntax = invalid_array;
453 type = array_type;
456 if (accept (TokenType.OP_NEG)) {
457 Report.warning (get_last_src (), "obsolete syntax, types are non-null by default");
460 if (!owned_by_default) {
461 if (accept (TokenType.HASH)) {
462 if (!context.deprecated) {
463 Report.warning (get_last_src (), "deprecated syntax, use `owned` modifier");
465 value_owned = true;
469 type.is_dynamic = is_dynamic;
470 type.value_owned = value_owned;
471 return type;
474 DataType? parse_inline_array_type (DataType? type) throws ParseError {
475 var begin = get_location ();
477 // inline-allocated array
478 if (type != null && accept (TokenType.OPEN_BRACKET)) {
479 int array_length = -1;
481 if (current () != TokenType.CLOSE_BRACKET) {
482 if (current () != TokenType.INTEGER_LITERAL) {
483 throw new ParseError.SYNTAX (get_error ("expected `]' or integer literal"));
486 var length_literal = (IntegerLiteral) parse_literal ();
487 array_length = length_literal.value.to_int ();
489 expect (TokenType.CLOSE_BRACKET);
491 var array_type = new ArrayType (type, 1, get_src (begin));
492 array_type.inline_allocated = true;
493 if (array_length > 0) {
494 array_type.fixed_length = true;
495 array_type.length = array_length;
498 return array_type;
500 return type;
503 List<Expression> parse_argument_list () throws ParseError {
504 var list = new ArrayList<Expression> ();
505 if (current () != TokenType.CLOSE_PARENS) {
506 do {
507 list.add (parse_argument ());
508 } while (accept (TokenType.COMMA));
510 return list;
513 Expression parse_argument () throws ParseError {
514 var begin = get_location ();
516 if (accept (TokenType.REF)) {
517 var inner = parse_expression ();
518 return new UnaryExpression (UnaryOperator.REF, inner, get_src (begin));
519 } else if (accept (TokenType.OUT)) {
520 var inner = parse_expression ();
521 return new UnaryExpression (UnaryOperator.OUT, inner, get_src (begin));
522 } else {
523 var expr = parse_expression ();
524 var ma = expr as MemberAccess;
525 if (ma != null && ma.inner == null && accept (TokenType.COLON)) {
526 // named argument
527 expr = parse_expression ();
528 return new NamedArgument (ma.member_name, expr, get_src (begin));
529 } else {
530 return expr;
535 Expression parse_primary_expression () throws ParseError {
536 var begin = get_location ();
538 Expression expr;
540 switch (current ()) {
541 case TokenType.TRUE:
542 case TokenType.FALSE:
543 case TokenType.INTEGER_LITERAL:
544 case TokenType.REAL_LITERAL:
545 case TokenType.CHARACTER_LITERAL:
546 case TokenType.STRING_LITERAL:
547 case TokenType.TEMPLATE_STRING_LITERAL:
548 case TokenType.VERBATIM_STRING_LITERAL:
549 case TokenType.NULL:
550 expr = parse_literal ();
551 break;
552 case TokenType.OPEN_BRACE:
553 expr = parse_initializer ();
554 break;
555 case TokenType.OPEN_PARENS:
556 expr = parse_tuple ();
557 break;
558 case TokenType.OPEN_TEMPLATE:
559 expr = parse_template ();
560 break;
561 case TokenType.THIS:
562 expr = parse_this_access ();
563 break;
564 case TokenType.BASE:
565 expr = parse_base_access ();
566 break;
567 case TokenType.NEW:
568 expr = parse_object_or_array_creation_expression ();
569 break;
570 case TokenType.YIELD:
571 expr = parse_yield_expression ();
572 break;
573 case TokenType.SIZEOF:
574 expr = parse_sizeof_expression ();
575 break;
576 case TokenType.TYPEOF:
577 expr = parse_typeof_expression ();
578 break;
579 default:
580 expr = parse_simple_name ();
581 break;
584 // process primary expressions that start with an inner primary expression
585 bool found = true;
586 while (found) {
587 switch (current ()) {
588 case TokenType.DOT:
589 expr = parse_member_access (begin, expr);
590 break;
591 case TokenType.OP_PTR:
592 expr = parse_pointer_member_access (begin, expr);
593 break;
594 case TokenType.OPEN_PARENS:
595 expr = parse_method_call (begin, expr);
596 break;
597 case TokenType.OPEN_BRACKET:
598 expr = parse_element_access (begin, expr);
599 break;
600 case TokenType.OP_INC:
601 expr = parse_post_increment_expression (begin, expr);
602 break;
603 case TokenType.OP_DEC:
604 expr = parse_post_decrement_expression (begin, expr);
605 break;
606 default:
607 found = false;
608 break;
612 return expr;
615 Expression parse_simple_name () throws ParseError {
616 var begin = get_location ();
617 string id = parse_identifier ();
618 bool qualified = false;
619 if (id == "global" && accept (TokenType.DOUBLE_COLON)) {
620 id = parse_identifier ();
621 qualified = true;
623 List<DataType> type_arg_list = parse_type_argument_list (true);
624 var expr = new MemberAccess (null, id, get_src (begin));
625 expr.qualified = qualified;
626 if (type_arg_list != null) {
627 foreach (DataType type_arg in type_arg_list) {
628 expr.add_type_argument (type_arg);
631 return expr;
634 Expression parse_tuple () throws ParseError {
635 expect (TokenType.OPEN_PARENS);
636 var expr_list = new ArrayList<Expression> ();
637 if (current () != TokenType.CLOSE_PARENS) {
638 do {
639 expr_list.add (parse_expression ());
640 } while (accept (TokenType.COMMA));
642 expect (TokenType.CLOSE_PARENS);
643 if (expr_list.size != 1) {
644 var tuple = new Tuple ();
645 foreach (Expression expr in expr_list) {
646 tuple.add_expression (expr);
648 return tuple;
650 return expr_list.get (0);
653 Expression parse_template () throws ParseError {
654 var begin = get_location ();
655 var template = new Template ();
657 expect (TokenType.OPEN_TEMPLATE);
658 while (current () != TokenType.CLOSE_TEMPLATE) {
659 template.add_expression (parse_expression ());
660 expect (TokenType.COMMA);
662 expect (TokenType.CLOSE_TEMPLATE);
664 template.source_reference = get_src (begin);
665 return template;
668 Expression parse_member_access (SourceLocation begin, Expression inner) throws ParseError {
669 expect (TokenType.DOT);
670 string id = parse_identifier ();
671 List<DataType> type_arg_list = parse_type_argument_list (true);
672 var expr = new MemberAccess (inner, id, get_src (begin));
673 if (type_arg_list != null) {
674 foreach (DataType type_arg in type_arg_list) {
675 expr.add_type_argument (type_arg);
678 return expr;
681 Expression parse_pointer_member_access (SourceLocation begin, Expression inner) throws ParseError {
682 expect (TokenType.OP_PTR);
683 string id = parse_identifier ();
684 List<DataType> type_arg_list = parse_type_argument_list (true);
685 var expr = new MemberAccess.pointer (inner, id, get_src (begin));
686 if (type_arg_list != null) {
687 foreach (DataType type_arg in type_arg_list) {
688 expr.add_type_argument (type_arg);
691 return expr;
694 Expression parse_method_call (SourceLocation begin, Expression inner) throws ParseError {
695 expect (TokenType.OPEN_PARENS);
696 var arg_list = parse_argument_list ();
697 expect (TokenType.CLOSE_PARENS);
698 var init_list = parse_object_initializer ();
700 if (init_list.size > 0 && inner is MemberAccess) {
701 // struct creation expression
702 var member = (MemberAccess) inner;
703 member.creation_member = true;
705 var expr = new ObjectCreationExpression (member, get_src (begin));
706 expr.struct_creation = true;
707 foreach (Expression arg in arg_list) {
708 expr.add_argument (arg);
710 foreach (MemberInitializer initializer in init_list) {
711 expr.add_member_initializer (initializer);
713 return expr;
714 } else {
715 var expr = new MethodCall (inner, get_src (begin));
716 foreach (Expression arg in arg_list) {
717 expr.add_argument (arg);
719 return expr;
723 Expression parse_element_access (SourceLocation begin, Expression inner) throws ParseError {
724 expect (TokenType.OPEN_BRACKET);
725 var index_list = parse_expression_list ();
726 expect (TokenType.CLOSE_BRACKET);
728 var expr = new ElementAccess (inner, get_src (begin));
729 foreach (Expression index in index_list) {
730 expr.append_index (index);
732 return expr;
735 List<Expression> parse_expression_list () throws ParseError {
736 var list = new ArrayList<Expression> ();
737 do {
738 list.add (parse_expression ());
739 } while (accept (TokenType.COMMA));
740 return list;
743 Expression parse_this_access () throws ParseError {
744 var begin = get_location ();
745 expect (TokenType.THIS);
746 return new MemberAccess (null, "this", get_src (begin));
749 Expression parse_base_access () throws ParseError {
750 var begin = get_location ();
751 expect (TokenType.BASE);
752 return new BaseAccess (get_src (begin));
755 Expression parse_post_increment_expression (SourceLocation begin, Expression inner) throws ParseError {
756 expect (TokenType.OP_INC);
757 return new PostfixExpression (inner, true, get_src (begin));
760 Expression parse_post_decrement_expression (SourceLocation begin, Expression inner) throws ParseError {
761 expect (TokenType.OP_DEC);
762 return new PostfixExpression (inner, false, get_src (begin));
765 Expression parse_object_or_array_creation_expression () throws ParseError {
766 var begin = get_location ();
767 expect (TokenType.NEW);
768 var member = parse_member_name ();
769 if (accept (TokenType.OPEN_PARENS)) {
770 var expr = parse_object_creation_expression (begin, member);
771 return expr;
772 } else if (accept (TokenType.OPEN_BRACKET)) {
773 var expr = parse_array_creation_expression (begin, member);
774 return expr;
775 } else {
776 throw new ParseError.SYNTAX (get_error ("expected ( or ["));
780 Expression parse_object_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError {
781 member.creation_member = true;
782 var arg_list = parse_argument_list ();
783 expect (TokenType.CLOSE_PARENS);
784 var init_list = parse_object_initializer ();
786 var expr = new ObjectCreationExpression (member, get_src (begin));
787 foreach (Expression arg in arg_list) {
788 expr.add_argument (arg);
790 foreach (MemberInitializer initializer in init_list) {
791 expr.add_member_initializer (initializer);
793 return expr;
796 Expression parse_array_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError {
797 bool size_specified = false;
798 List<Expression> size_specifier_list = null;
799 bool first = true;
800 DataType element_type = UnresolvedType.new_from_expression (member);
801 do {
802 if (!first) {
803 // array of arrays: new T[][42]
804 element_type = new ArrayType (element_type, size_specifier_list.size, element_type.source_reference);
805 } else {
806 first = false;
809 size_specifier_list = new ArrayList<Expression> ();
810 do {
811 Expression size = null;
812 if (current () != TokenType.CLOSE_BRACKET && current () != TokenType.COMMA) {
813 size = parse_expression ();
814 size_specified = true;
816 size_specifier_list.add (size);
817 } while (accept (TokenType.COMMA));
818 expect (TokenType.CLOSE_BRACKET);
819 } while (accept (TokenType.OPEN_BRACKET));
821 InitializerList initializer = null;
822 if (current () == TokenType.OPEN_BRACE) {
823 initializer = parse_initializer ();
825 var expr = new ArrayCreationExpression (element_type, size_specifier_list.size, initializer, get_src (begin));
826 if (size_specified) {
827 foreach (Expression size in size_specifier_list) {
828 expr.append_size (size);
831 return expr;
834 List<MemberInitializer> parse_object_initializer () throws ParseError {
835 var list = new ArrayList<MemberInitializer> ();
836 if (accept (TokenType.OPEN_BRACE)) {
837 do {
838 list.add (parse_member_initializer ());
839 } while (accept (TokenType.COMMA));
840 expect (TokenType.CLOSE_BRACE);
842 return list;
845 MemberInitializer parse_member_initializer () throws ParseError {
846 var begin = get_location ();
847 string id = parse_identifier ();
848 expect (TokenType.ASSIGN);
849 var expr = parse_expression ();
851 return new MemberInitializer (id, expr, get_src (begin));
854 Expression parse_yield_expression () throws ParseError {
855 var begin = get_location ();
856 expect (TokenType.YIELD);
857 var member = parse_member_name ();
858 var call = (MethodCall) parse_method_call (begin, member);
859 call.is_yield_expression = true;
860 return call;
863 Expression parse_sizeof_expression () throws ParseError {
864 var begin = get_location ();
865 expect (TokenType.SIZEOF);
866 expect (TokenType.OPEN_PARENS);
867 var type = parse_type ();
868 expect (TokenType.CLOSE_PARENS);
870 return new SizeofExpression (type, get_src (begin));
873 Expression parse_typeof_expression () throws ParseError {
874 var begin = get_location ();
875 expect (TokenType.TYPEOF);
876 expect (TokenType.OPEN_PARENS);
877 var type = parse_type ();
878 expect (TokenType.CLOSE_PARENS);
880 return new TypeofExpression (type, get_src (begin));
883 UnaryOperator get_unary_operator (TokenType token_type) {
884 switch (token_type) {
885 case TokenType.PLUS: return UnaryOperator.PLUS;
886 case TokenType.MINUS: return UnaryOperator.MINUS;
887 case TokenType.OP_NEG: return UnaryOperator.LOGICAL_NEGATION;
888 case TokenType.TILDE: return UnaryOperator.BITWISE_COMPLEMENT;
889 case TokenType.OP_INC: return UnaryOperator.INCREMENT;
890 case TokenType.OP_DEC: return UnaryOperator.DECREMENT;
891 default: return UnaryOperator.NONE;
895 Expression parse_unary_expression () throws ParseError {
896 var begin = get_location ();
897 var operator = get_unary_operator (current ());
898 if (operator != UnaryOperator.NONE) {
899 next ();
900 var op = parse_unary_expression ();
901 return new UnaryExpression (operator, op, get_src (begin));
903 switch (current ()) {
904 case TokenType.HASH:
905 if (!context.deprecated) {
906 Report.warning (get_last_src (), "deprecated syntax, use `(owned)` cast");
908 next ();
909 var op = parse_unary_expression ();
910 return new ReferenceTransferExpression (op, get_src (begin));
911 case TokenType.OPEN_PARENS:
912 next ();
913 switch (current ()) {
914 case TokenType.OWNED:
915 // (owned) foo
916 next ();
917 if (accept (TokenType.CLOSE_PARENS)) {
918 var op = parse_unary_expression ();
919 return new ReferenceTransferExpression (op, get_src (begin));
921 break;
922 case TokenType.VOID:
923 case TokenType.DYNAMIC:
924 case TokenType.IDENTIFIER:
925 var type = parse_type ();
926 if (accept (TokenType.CLOSE_PARENS)) {
927 // check follower to decide whether to create cast expression
928 switch (current ()) {
929 case TokenType.OP_NEG:
930 case TokenType.TILDE:
931 case TokenType.OPEN_PARENS:
932 case TokenType.TRUE:
933 case TokenType.FALSE:
934 case TokenType.INTEGER_LITERAL:
935 case TokenType.REAL_LITERAL:
936 case TokenType.CHARACTER_LITERAL:
937 case TokenType.STRING_LITERAL:
938 case TokenType.TEMPLATE_STRING_LITERAL:
939 case TokenType.VERBATIM_STRING_LITERAL:
940 case TokenType.NULL:
941 case TokenType.THIS:
942 case TokenType.BASE:
943 case TokenType.NEW:
944 case TokenType.SIZEOF:
945 case TokenType.TYPEOF:
946 case TokenType.IDENTIFIER:
947 case TokenType.PARAMS:
948 var inner = parse_unary_expression ();
949 return new CastExpression (inner, type, get_src (begin), false);
950 default:
951 break;
954 break;
955 case TokenType.OP_NEG:
956 next ();
957 if (accept (TokenType.CLOSE_PARENS)) {
958 // (!) non-null cast
959 var inner = parse_unary_expression ();
960 return new CastExpression.non_null (inner, get_src (begin));
962 break;
963 default:
964 break;
966 // no cast expression
967 rollback (begin);
968 break;
969 case TokenType.STAR:
970 next ();
971 var op = parse_unary_expression ();
972 return new PointerIndirection (op, get_src (begin));
973 case TokenType.BITWISE_AND:
974 next ();
975 var op = parse_unary_expression ();
976 return new AddressofExpression (op, get_src (begin));
977 default:
978 break;
981 var expr = parse_primary_expression ();
982 return expr;
985 BinaryOperator get_binary_operator (TokenType token_type) {
986 switch (token_type) {
987 case TokenType.STAR: return BinaryOperator.MUL;
988 case TokenType.DIV: return BinaryOperator.DIV;
989 case TokenType.PERCENT: return BinaryOperator.MOD;
990 case TokenType.PLUS: return BinaryOperator.PLUS;
991 case TokenType.MINUS: return BinaryOperator.MINUS;
992 case TokenType.OP_LT: return BinaryOperator.LESS_THAN;
993 case TokenType.OP_GT: return BinaryOperator.GREATER_THAN;
994 case TokenType.OP_LE: return BinaryOperator.LESS_THAN_OR_EQUAL;
995 case TokenType.OP_GE: return BinaryOperator.GREATER_THAN_OR_EQUAL;
996 case TokenType.OP_EQ: return BinaryOperator.EQUALITY;
997 case TokenType.OP_NE: return BinaryOperator.INEQUALITY;
998 default: return BinaryOperator.NONE;
1002 Expression parse_multiplicative_expression () throws ParseError {
1003 var begin = get_location ();
1004 var left = parse_unary_expression ();
1005 bool found = true;
1006 while (found) {
1007 var operator = get_binary_operator (current ());
1008 switch (operator) {
1009 case BinaryOperator.MUL:
1010 case BinaryOperator.DIV:
1011 case BinaryOperator.MOD:
1012 next ();
1013 var right = parse_unary_expression ();
1014 left = new BinaryExpression (operator, left, right, get_src (begin));
1015 break;
1016 default:
1017 found = false;
1018 break;
1021 return left;
1024 Expression parse_additive_expression () throws ParseError {
1025 var begin = get_location ();
1026 var left = parse_multiplicative_expression ();
1027 bool found = true;
1028 while (found) {
1029 var operator = get_binary_operator (current ());
1030 switch (operator) {
1031 case BinaryOperator.PLUS:
1032 case BinaryOperator.MINUS:
1033 next ();
1034 var right = parse_multiplicative_expression ();
1035 left = new BinaryExpression (operator, left, right, get_src (begin));
1036 break;
1037 default:
1038 found = false;
1039 break;
1042 return left;
1045 Expression parse_shift_expression () throws ParseError {
1046 var begin = get_location ();
1047 var left = parse_additive_expression ();
1048 bool found = true;
1049 while (found) {
1050 switch (current ()) {
1051 case TokenType.OP_SHIFT_LEFT:
1052 next ();
1053 var right = parse_additive_expression ();
1054 left = new BinaryExpression (BinaryOperator.SHIFT_LEFT, left, right, get_src (begin));
1055 break;
1056 // don't use OP_SHIFT_RIGHT to support >> for nested generics
1057 case TokenType.OP_GT:
1058 char* first_gt_pos = tokens[index].begin.pos;
1059 next ();
1060 // only accept >> when there is no space between the two > signs
1061 if (current () == TokenType.OP_GT && tokens[index].begin.pos == first_gt_pos + 1) {
1062 next ();
1063 var right = parse_additive_expression ();
1064 left = new BinaryExpression (BinaryOperator.SHIFT_RIGHT, left, right, get_src (begin));
1065 } else {
1066 prev ();
1067 found = false;
1069 break;
1070 default:
1071 found = false;
1072 break;
1075 return left;
1078 Expression parse_relational_expression () throws ParseError {
1079 var begin = get_location ();
1080 var left = parse_shift_expression ();
1081 bool found = true;
1082 while (found) {
1083 var operator = get_binary_operator (current ());
1084 switch (operator) {
1085 case BinaryOperator.LESS_THAN:
1086 case BinaryOperator.LESS_THAN_OR_EQUAL:
1087 case BinaryOperator.GREATER_THAN_OR_EQUAL:
1088 next ();
1089 var right = parse_shift_expression ();
1090 left = new BinaryExpression (operator, left, right, get_src (begin));
1091 break;
1092 case BinaryOperator.GREATER_THAN:
1093 next ();
1094 // ignore >> and >>= (two tokens due to generics)
1095 if (current () != TokenType.OP_GT && current () != TokenType.OP_GE) {
1096 var right = parse_shift_expression ();
1097 left = new BinaryExpression (operator, left, right, get_src (begin));
1098 } else {
1099 prev ();
1100 found = false;
1102 break;
1103 default:
1104 switch (current ()) {
1105 case TokenType.IS:
1106 next ();
1107 var type = parse_type ();
1108 left = new TypeCheck (left, type, get_src (begin));
1109 break;
1110 case TokenType.AS:
1111 next ();
1112 var type = parse_type ();
1113 left = new CastExpression (left, type, get_src (begin), true);
1114 break;
1115 default:
1116 found = false;
1117 break;
1119 break;
1122 return left;
1125 Expression parse_equality_expression () throws ParseError {
1126 var begin = get_location ();
1127 var left = parse_relational_expression ();
1128 bool found = true;
1129 while (found) {
1130 var operator = get_binary_operator (current ());
1131 switch (operator) {
1132 case BinaryOperator.EQUALITY:
1133 case BinaryOperator.INEQUALITY:
1134 next ();
1135 var right = parse_relational_expression ();
1136 left = new BinaryExpression (operator, left, right, get_src (begin));
1137 break;
1138 default:
1139 found = false;
1140 break;
1143 return left;
1146 Expression parse_and_expression () throws ParseError {
1147 var begin = get_location ();
1148 var left = parse_equality_expression ();
1149 while (accept (TokenType.BITWISE_AND)) {
1150 var right = parse_equality_expression ();
1151 left = new BinaryExpression (BinaryOperator.BITWISE_AND, left, right, get_src (begin));
1153 return left;
1156 Expression parse_exclusive_or_expression () throws ParseError {
1157 var begin = get_location ();
1158 var left = parse_and_expression ();
1159 while (accept (TokenType.CARRET)) {
1160 var right = parse_and_expression ();
1161 left = new BinaryExpression (BinaryOperator.BITWISE_XOR, left, right, get_src (begin));
1163 return left;
1166 Expression parse_inclusive_or_expression () throws ParseError {
1167 var begin = get_location ();
1168 var left = parse_exclusive_or_expression ();
1169 while (accept (TokenType.BITWISE_OR)) {
1170 var right = parse_exclusive_or_expression ();
1171 left = new BinaryExpression (BinaryOperator.BITWISE_OR, left, right, get_src (begin));
1173 return left;
1176 Expression parse_in_expression () throws ParseError {
1177 var begin = get_location ();
1178 var left = parse_inclusive_or_expression ();
1179 while (accept (TokenType.IN)) {
1180 var right = parse_inclusive_or_expression ();
1181 left = new BinaryExpression (BinaryOperator.IN, left, right, get_src (begin));
1183 return left;
1186 Expression parse_conditional_and_expression () throws ParseError {
1187 var begin = get_location ();
1188 var left = parse_in_expression ();
1189 while (accept (TokenType.OP_AND)) {
1190 var right = parse_in_expression ();
1191 left = new BinaryExpression (BinaryOperator.AND, left, right, get_src (begin));
1193 return left;
1196 Expression parse_conditional_or_expression () throws ParseError {
1197 var begin = get_location ();
1198 var left = parse_conditional_and_expression ();
1199 while (accept (TokenType.OP_OR)) {
1200 var right = parse_conditional_and_expression ();
1201 left = new BinaryExpression (BinaryOperator.OR, left, right, get_src (begin));
1203 return left;
1206 Expression parse_conditional_expression () throws ParseError {
1207 var begin = get_location ();
1208 var condition = parse_conditional_or_expression ();
1209 if (accept (TokenType.INTERR)) {
1210 var true_expr = parse_expression ();
1211 expect (TokenType.COLON);
1212 var false_expr = parse_expression ();
1213 return new ConditionalExpression (condition, true_expr, false_expr, get_src (begin));
1214 } else {
1215 return condition;
1219 Expression parse_lambda_expression () throws ParseError {
1220 var begin = get_location ();
1221 List<string> params = new ArrayList<string> ();
1222 if (accept (TokenType.OPEN_PARENS)) {
1223 if (current () != TokenType.CLOSE_PARENS) {
1224 do {
1225 params.add (parse_identifier ());
1226 } while (accept (TokenType.COMMA));
1228 expect (TokenType.CLOSE_PARENS);
1229 } else {
1230 params.add (parse_identifier ());
1232 expect (TokenType.LAMBDA);
1234 LambdaExpression lambda;
1235 if (current () == TokenType.OPEN_BRACE) {
1236 var block = parse_block ();
1237 lambda = new LambdaExpression.with_statement_body (block, get_src (begin));
1238 } else {
1239 var expr = parse_expression ();
1240 lambda = new LambdaExpression (expr, get_src (begin));
1242 foreach (string param in params) {
1243 lambda.add_parameter (param);
1245 return lambda;
1248 AssignmentOperator get_assignment_operator (TokenType token_type) {
1249 switch (token_type) {
1250 case TokenType.ASSIGN: return AssignmentOperator.SIMPLE;
1251 case TokenType.ASSIGN_ADD: return AssignmentOperator.ADD;
1252 case TokenType.ASSIGN_SUB: return AssignmentOperator.SUB;
1253 case TokenType.ASSIGN_BITWISE_OR: return AssignmentOperator.BITWISE_OR;
1254 case TokenType.ASSIGN_BITWISE_AND: return AssignmentOperator.BITWISE_AND;
1255 case TokenType.ASSIGN_BITWISE_XOR: return AssignmentOperator.BITWISE_XOR;
1256 case TokenType.ASSIGN_DIV: return AssignmentOperator.DIV;
1257 case TokenType.ASSIGN_MUL: return AssignmentOperator.MUL;
1258 case TokenType.ASSIGN_PERCENT: return AssignmentOperator.PERCENT;
1259 case TokenType.ASSIGN_SHIFT_LEFT: return AssignmentOperator.SHIFT_LEFT;
1260 default: return AssignmentOperator.NONE;
1264 Expression parse_expression () throws ParseError {
1265 var begin = get_location ();
1266 Expression expr = parse_conditional_expression ();
1268 if (current () == TokenType.LAMBDA) {
1269 rollback (begin);
1270 var lambda = parse_lambda_expression ();
1271 return lambda;
1274 while (true) {
1275 var operator = get_assignment_operator (current ());
1276 if (operator != AssignmentOperator.NONE) {
1277 next ();
1278 var rhs = parse_expression ();
1279 expr = new Assignment (expr, rhs, operator, get_src (begin));
1280 } else if (current () == TokenType.OP_GT) { // >>=
1281 char* first_gt_pos = tokens[index].begin.pos;
1282 next ();
1283 // only accept >>= when there is no space between the two > signs
1284 if (current () == TokenType.OP_GE && tokens[index].begin.pos == first_gt_pos + 1) {
1285 next ();
1286 var rhs = parse_expression ();
1287 expr = new Assignment (expr, rhs, AssignmentOperator.SHIFT_RIGHT, get_src (begin));
1288 } else {
1289 prev ();
1290 break;
1292 } else {
1293 break;
1297 return expr;
1300 void parse_statements (Block block) throws ParseError {
1301 while (current () != TokenType.CLOSE_BRACE
1302 && current () != TokenType.CASE
1303 && current () != TokenType.DEFAULT) {
1304 try {
1305 Statement stmt = null;
1306 bool is_decl = false;
1308 comment = scanner.pop_comment ();
1309 switch (current ()) {
1310 case TokenType.OPEN_BRACE:
1311 stmt = parse_block ();
1312 break;
1313 case TokenType.SEMICOLON:
1314 stmt = parse_empty_statement ();
1315 break;
1316 case TokenType.IF:
1317 stmt = parse_if_statement ();
1318 break;
1319 case TokenType.SWITCH:
1320 stmt = parse_switch_statement ();
1321 break;
1322 case TokenType.WHILE:
1323 stmt = parse_while_statement ();
1324 break;
1325 case TokenType.DO:
1326 stmt = parse_do_statement ();
1327 break;
1328 case TokenType.FOR:
1329 stmt = parse_for_statement ();
1330 break;
1331 case TokenType.FOREACH:
1332 stmt = parse_foreach_statement ();
1333 break;
1334 case TokenType.BREAK:
1335 stmt = parse_break_statement ();
1336 break;
1337 case TokenType.CONTINUE:
1338 stmt = parse_continue_statement ();
1339 break;
1340 case TokenType.RETURN:
1341 stmt = parse_return_statement ();
1342 break;
1343 case TokenType.YIELD:
1344 stmt = parse_yield_statement ();
1345 break;
1346 case TokenType.THROW:
1347 stmt = parse_throw_statement ();
1348 break;
1349 case TokenType.TRY:
1350 stmt = parse_try_statement ();
1351 break;
1352 case TokenType.LOCK:
1353 stmt = parse_lock_statement ();
1354 break;
1355 case TokenType.DELETE:
1356 stmt = parse_delete_statement ();
1357 break;
1358 case TokenType.VAR:
1359 is_decl = true;
1360 parse_local_variable_declarations (block);
1361 break;
1362 case TokenType.OP_INC:
1363 case TokenType.OP_DEC:
1364 case TokenType.BASE:
1365 case TokenType.THIS:
1366 case TokenType.OPEN_PARENS:
1367 case TokenType.STAR:
1368 case TokenType.NEW:
1369 stmt = parse_expression_statement ();
1370 break;
1371 default:
1372 bool is_expr = is_expression ();
1373 if (is_expr) {
1374 stmt = parse_expression_statement ();
1375 } else {
1376 is_decl = true;
1377 parse_local_variable_declarations (block);
1379 break;
1382 if (!is_decl) {
1383 block.add_statement (stmt);
1385 } catch (ParseError e) {
1386 if (recover () != RecoveryState.STATEMENT_BEGIN) {
1387 // beginning of next declaration or end of file reached
1388 // return what we have so far
1389 break;
1395 bool is_expression () throws ParseError {
1396 var begin = get_location ();
1398 // decide between declaration and expression statement
1399 skip_type ();
1400 switch (current ()) {
1401 // invocation expression
1402 case TokenType.OPEN_PARENS:
1403 // postfix increment
1404 case TokenType.OP_INC:
1405 // postfix decrement
1406 case TokenType.OP_DEC:
1407 // assignments
1408 case TokenType.ASSIGN:
1409 case TokenType.ASSIGN_ADD:
1410 case TokenType.ASSIGN_BITWISE_AND:
1411 case TokenType.ASSIGN_BITWISE_OR:
1412 case TokenType.ASSIGN_BITWISE_XOR:
1413 case TokenType.ASSIGN_DIV:
1414 case TokenType.ASSIGN_MUL:
1415 case TokenType.ASSIGN_PERCENT:
1416 case TokenType.ASSIGN_SHIFT_LEFT:
1417 case TokenType.ASSIGN_SUB:
1418 case TokenType.OP_GT: // >>=
1419 // member access
1420 case TokenType.DOT:
1421 // pointer member access
1422 case TokenType.OP_PTR:
1423 rollback (begin);
1424 return true;
1425 default:
1426 rollback (begin);
1427 return false;
1431 Block parse_embedded_statement () throws ParseError {
1432 if (current () == TokenType.OPEN_BRACE) {
1433 var block = parse_block ();
1434 return block;
1437 comment = scanner.pop_comment ();
1439 var block = new Block (get_src (get_location ()));
1440 block.add_statement (parse_embedded_statement_without_block ());
1441 return block;
1445 Statement parse_embedded_statement_without_block () throws ParseError {
1446 switch (current ()) {
1447 case TokenType.SEMICOLON: return parse_empty_statement ();
1448 case TokenType.IF: return parse_if_statement ();
1449 case TokenType.SWITCH: return parse_switch_statement ();
1450 case TokenType.WHILE: return parse_while_statement ();
1451 case TokenType.DO: return parse_do_statement ();
1452 case TokenType.FOR: return parse_for_statement ();
1453 case TokenType.FOREACH: return parse_foreach_statement ();
1454 case TokenType.BREAK: return parse_break_statement ();
1455 case TokenType.CONTINUE: return parse_continue_statement ();
1456 case TokenType.RETURN: return parse_return_statement ();
1457 case TokenType.YIELD: return parse_yield_statement ();
1458 case TokenType.THROW: return parse_throw_statement ();
1459 case TokenType.TRY: return parse_try_statement ();
1460 case TokenType.LOCK: return parse_lock_statement ();
1461 case TokenType.DELETE: return parse_delete_statement ();
1462 default: return parse_expression_statement ();
1466 Block parse_block () throws ParseError {
1467 var begin = get_location ();
1468 expect (TokenType.OPEN_BRACE);
1469 var block = new Block (get_src (begin));
1470 parse_statements (block);
1471 if (!accept (TokenType.CLOSE_BRACE)) {
1472 // only report error if it's not a secondary error
1473 if (context.report.get_errors () == 0) {
1474 Report.error (get_current_src (), "expected `}'");
1478 block.source_reference.last_line = get_current_src ().last_line;
1479 block.source_reference.last_column = get_current_src ().last_column;
1481 return block;
1484 Statement parse_empty_statement () throws ParseError {
1485 var begin = get_location ();
1486 expect (TokenType.SEMICOLON);
1487 return new EmptyStatement (get_src (begin));
1490 void parse_local_variable_declarations (Block block) throws ParseError {
1491 DataType variable_type;
1492 if (accept (TokenType.VAR)) {
1493 variable_type = null;
1494 } else {
1495 variable_type = parse_type ();
1497 do {
1498 DataType type_copy = null;
1499 if (variable_type != null) {
1500 type_copy = variable_type.copy ();
1502 var local = parse_local_variable (type_copy);
1503 block.add_statement (new DeclarationStatement (local, local.source_reference));
1504 } while (accept (TokenType.COMMA));
1505 expect (TokenType.SEMICOLON);
1508 LocalVariable parse_local_variable (DataType? variable_type) throws ParseError {
1509 var begin = get_location ();
1510 string id = parse_identifier ();
1512 var type = parse_inline_array_type (variable_type);
1514 Expression initializer = null;
1515 if (accept (TokenType.ASSIGN)) {
1516 initializer = parse_expression ();
1518 return new LocalVariable (type, id, initializer, get_src (begin));
1521 Statement parse_expression_statement () throws ParseError {
1522 var begin = get_location ();
1523 var expr = parse_statement_expression ();
1524 expect (TokenType.SEMICOLON);
1525 return new ExpressionStatement (expr, get_src (begin));
1528 Expression parse_statement_expression () throws ParseError {
1529 // invocation expression, assignment,
1530 // or pre/post increment/decrement expression
1531 var expr = parse_expression ();
1532 return expr;
1535 Statement parse_if_statement () throws ParseError {
1536 var begin = get_location ();
1537 expect (TokenType.IF);
1538 expect (TokenType.OPEN_PARENS);
1539 var condition = parse_expression ();
1540 expect (TokenType.CLOSE_PARENS);
1541 var src = get_src (begin);
1542 var true_stmt = parse_embedded_statement ();
1543 Block false_stmt = null;
1544 if (accept (TokenType.ELSE)) {
1545 false_stmt = parse_embedded_statement ();
1547 return new IfStatement (condition, true_stmt, false_stmt, src);
1550 Statement parse_switch_statement () throws ParseError {
1551 var begin = get_location ();
1552 expect (TokenType.SWITCH);
1553 expect (TokenType.OPEN_PARENS);
1554 var condition = parse_expression ();
1555 expect (TokenType.CLOSE_PARENS);
1556 var stmt = new SwitchStatement (condition, get_src (begin));
1557 expect (TokenType.OPEN_BRACE);
1558 while (current () != TokenType.CLOSE_BRACE) {
1559 var section = new SwitchSection (get_src (begin));
1560 do {
1561 if (accept (TokenType.CASE)) {
1562 section.add_label (new SwitchLabel (parse_expression (), get_src (begin)));
1563 } else {
1564 expect (TokenType.DEFAULT);
1565 section.add_label (new SwitchLabel.with_default (get_src (begin)));
1567 expect (TokenType.COLON);
1568 } while (current () == TokenType.CASE || current () == TokenType.DEFAULT);
1569 parse_statements (section);
1570 stmt.add_section (section);
1572 expect (TokenType.CLOSE_BRACE);
1573 return stmt;
1576 Statement parse_while_statement () throws ParseError {
1577 var begin = get_location ();
1578 expect (TokenType.WHILE);
1579 expect (TokenType.OPEN_PARENS);
1580 var condition = parse_expression ();
1581 expect (TokenType.CLOSE_PARENS);
1582 var body = parse_embedded_statement ();
1583 return new WhileStatement (condition, body, get_src (begin));
1586 Statement parse_do_statement () throws ParseError {
1587 var begin = get_location ();
1588 expect (TokenType.DO);
1589 var body = parse_embedded_statement ();
1590 expect (TokenType.WHILE);
1591 expect (TokenType.OPEN_PARENS);
1592 var condition = parse_expression ();
1593 expect (TokenType.CLOSE_PARENS);
1594 expect (TokenType.SEMICOLON);
1595 return new DoStatement (body, condition, get_src (begin));
1598 Statement parse_for_statement () throws ParseError {
1599 var begin = get_location ();
1600 Block block = null;
1601 expect (TokenType.FOR);
1602 expect (TokenType.OPEN_PARENS);
1603 var initializer_list = new ArrayList<Expression> ();
1604 if (!accept (TokenType.SEMICOLON)) {
1605 bool is_expr;
1606 switch (current ()) {
1607 case TokenType.VAR:
1608 is_expr = false;
1609 break;
1610 case TokenType.OP_INC:
1611 case TokenType.OP_DEC:
1612 is_expr = true;
1613 break;
1614 default:
1615 is_expr = is_expression ();
1616 break;
1619 if (is_expr) {
1620 do {
1621 initializer_list.add (parse_statement_expression ());
1622 } while (accept (TokenType.COMMA));
1623 } else {
1624 block = new Block (get_src (begin));
1625 DataType variable_type;
1626 if (accept (TokenType.VAR)) {
1627 variable_type = null;
1628 } else {
1629 variable_type = parse_type ();
1631 var local = parse_local_variable (variable_type);
1632 block.add_statement (new DeclarationStatement (local, local.source_reference));
1634 expect (TokenType.SEMICOLON);
1636 Expression condition = null;
1637 if (current () != TokenType.SEMICOLON) {
1638 condition = parse_expression ();
1640 expect (TokenType.SEMICOLON);
1641 var iterator_list = new ArrayList<Expression> ();
1642 if (current () != TokenType.CLOSE_PARENS) {
1643 do {
1644 iterator_list.add (parse_statement_expression ());
1645 } while (accept (TokenType.COMMA));
1647 expect (TokenType.CLOSE_PARENS);
1648 var src = get_src (begin);
1649 var body = parse_embedded_statement ();
1650 var stmt = new ForStatement (condition, body, src);
1651 foreach (Expression init in initializer_list) {
1652 stmt.add_initializer (init);
1654 foreach (Expression iter in iterator_list) {
1655 stmt.add_iterator (iter);
1657 if (block != null) {
1658 block.add_statement (stmt);
1659 return block;
1660 } else {
1661 return stmt;
1665 Statement parse_foreach_statement () throws ParseError {
1666 var begin = get_location ();
1667 expect (TokenType.FOREACH);
1668 expect (TokenType.OPEN_PARENS);
1669 DataType type = null;
1670 if (!accept (TokenType.VAR)) {
1671 type = parse_type ();
1673 string id = parse_identifier ();
1674 expect (TokenType.IN);
1675 var collection = parse_expression ();
1676 expect (TokenType.CLOSE_PARENS);
1677 var src = get_src (begin);
1678 var body = parse_embedded_statement ();
1679 return new ForeachStatement (type, id, collection, body, src);
1682 Statement parse_break_statement () throws ParseError {
1683 var begin = get_location ();
1684 expect (TokenType.BREAK);
1685 expect (TokenType.SEMICOLON);
1686 return new BreakStatement (get_src (begin));
1689 Statement parse_continue_statement () throws ParseError {
1690 var begin = get_location ();
1691 expect (TokenType.CONTINUE);
1692 expect (TokenType.SEMICOLON);
1693 return new ContinueStatement (get_src (begin));
1696 Statement parse_return_statement () throws ParseError {
1697 var begin = get_location ();
1698 expect (TokenType.RETURN);
1699 Expression expr = null;
1700 if (current () != TokenType.SEMICOLON) {
1701 expr = parse_expression ();
1703 expect (TokenType.SEMICOLON);
1704 return new ReturnStatement (expr, get_src (begin));
1707 Statement parse_yield_statement () throws ParseError {
1708 var begin = get_location ();
1709 expect (TokenType.YIELD);
1710 if (current () != TokenType.SEMICOLON && current () != TokenType.RETURN) {
1711 // yield expression
1712 prev ();
1713 return parse_expression_statement ();
1715 Expression expr = null;
1716 if (accept (TokenType.RETURN)) {
1717 expr = parse_expression ();
1719 expect (TokenType.SEMICOLON);
1720 return new YieldStatement (expr, get_src (begin));
1723 Statement parse_throw_statement () throws ParseError {
1724 var begin = get_location ();
1725 expect (TokenType.THROW);
1726 var expr = parse_expression ();
1727 expect (TokenType.SEMICOLON);
1728 return new ThrowStatement (expr, get_src (begin));
1731 Statement parse_try_statement () throws ParseError {
1732 var begin = get_location ();
1733 expect (TokenType.TRY);
1734 var try_block = parse_block ();
1735 Block finally_clause = null;
1736 var catch_clauses = new ArrayList<CatchClause> ();
1737 if (current () == TokenType.CATCH) {
1738 parse_catch_clauses (catch_clauses);
1739 if (current () == TokenType.FINALLY) {
1740 finally_clause = parse_finally_clause ();
1742 } else {
1743 finally_clause = parse_finally_clause ();
1745 var stmt = new TryStatement (try_block, finally_clause, get_src (begin));
1746 foreach (CatchClause clause in catch_clauses) {
1747 stmt.add_catch_clause (clause);
1749 return stmt;
1752 void parse_catch_clauses (List<CatchClause> catch_clauses) throws ParseError {
1753 while (accept (TokenType.CATCH)) {
1754 var begin = get_location ();
1755 DataType type = null;
1756 string id = null;
1757 if (accept (TokenType.OPEN_PARENS)) {
1758 type = parse_type ();
1759 id = parse_identifier ();
1760 expect (TokenType.CLOSE_PARENS);
1762 var block = parse_block ();
1763 catch_clauses.add (new CatchClause (type, id, block, get_src (begin)));
1767 Block parse_finally_clause () throws ParseError {
1768 expect (TokenType.FINALLY);
1769 var block = parse_block ();
1770 return block;
1773 Statement parse_lock_statement () throws ParseError {
1774 var begin = get_location ();
1775 expect (TokenType.LOCK);
1776 expect (TokenType.OPEN_PARENS);
1777 var expr = parse_expression ();
1778 expect (TokenType.CLOSE_PARENS);
1779 var stmt = parse_embedded_statement ();
1780 return new LockStatement (expr, stmt, get_src (begin));
1783 Statement parse_delete_statement () throws ParseError {
1784 var begin = get_location ();
1785 expect (TokenType.DELETE);
1786 var expr = parse_expression ();
1787 expect (TokenType.SEMICOLON);
1788 return new DeleteStatement (expr, get_src (begin));
1791 List<Attribute>? parse_attributes () throws ParseError {
1792 if (current () != TokenType.OPEN_BRACKET) {
1793 return null;
1795 var attrs = new ArrayList<Attribute> ();
1796 while (accept (TokenType.OPEN_BRACKET)) {
1797 do {
1798 var begin = get_location ();
1799 string id = parse_identifier ();
1800 var attr = new Attribute (id, get_src (begin));
1801 if (accept (TokenType.OPEN_PARENS)) {
1802 if (current () != TokenType.CLOSE_PARENS) {
1803 do {
1804 id = parse_identifier ();
1805 expect (TokenType.ASSIGN);
1806 var expr = parse_expression ();
1807 attr.add_argument (id, expr);
1808 } while (accept (TokenType.COMMA));
1810 expect (TokenType.CLOSE_PARENS);
1812 attrs.add (attr);
1813 } while (accept (TokenType.COMMA));
1814 expect (TokenType.CLOSE_BRACKET);
1816 return attrs;
1819 void set_attributes (CodeNode node, List<Attribute>? attributes) {
1820 if (attributes != null) {
1821 foreach (Attribute attr in (List<Attribute>) attributes) {
1822 node.attributes.append (attr);
1827 Symbol parse_declaration () throws ParseError {
1828 comment = scanner.pop_comment ();
1829 var attrs = parse_attributes ();
1831 var begin = get_location ();
1833 TokenType last_keyword = current ();
1835 while (is_declaration_keyword (current ())) {
1836 last_keyword = current ();
1837 next ();
1840 switch (current ()) {
1841 case TokenType.CONSTRUCT:
1842 if (context.profile == Profile.GOBJECT) {
1843 rollback (begin);
1844 return parse_constructor_declaration (attrs);
1846 break;
1847 case TokenType.TILDE:
1848 rollback (begin);
1849 return parse_destructor_declaration (attrs);
1850 default:
1851 skip_type ();
1852 switch (current ()) {
1853 case TokenType.OPEN_BRACE:
1854 case TokenType.SEMICOLON:
1855 case TokenType.COLON:
1856 rollback (begin);
1857 switch (last_keyword) {
1858 case TokenType.CLASS: return parse_class_declaration (attrs);
1859 case TokenType.ENUM: return parse_enum_declaration (attrs);
1860 case TokenType.ERRORDOMAIN: return parse_errordomain_declaration (attrs);
1861 case TokenType.INTERFACE: return parse_interface_declaration (attrs);
1862 case TokenType.NAMESPACE: return parse_namespace_declaration (attrs);
1863 case TokenType.STRUCT: return parse_struct_declaration (attrs);
1864 default: break;
1866 break;
1867 case TokenType.OPEN_PARENS:
1868 rollback (begin);
1869 return parse_creation_method_declaration (attrs);
1870 default:
1871 skip_type (); // might contain type parameter list
1872 switch (current ()) {
1873 case TokenType.OPEN_PARENS:
1874 rollback (begin);
1875 switch (last_keyword) {
1876 case TokenType.DELEGATE: return parse_delegate_declaration (attrs);
1877 case TokenType.SIGNAL: return parse_signal_declaration (attrs);
1878 default: return parse_method_declaration (attrs);
1880 case TokenType.ASSIGN:
1881 case TokenType.SEMICOLON:
1882 rollback (begin);
1883 switch (last_keyword) {
1884 case TokenType.CONST: return parse_constant_declaration (attrs);
1885 default: return parse_field_declaration (attrs);
1887 case TokenType.OPEN_BRACE:
1888 case TokenType.THROWS:
1889 rollback (begin);
1890 return parse_property_declaration (attrs);
1891 default:
1892 break;
1894 break;
1896 break;
1899 rollback (begin);
1901 throw new ParseError.SYNTAX (get_error ("expected declaration"));
1904 void parse_declarations (Symbol parent, bool root = false) throws ParseError {
1905 if (!root) {
1906 expect (TokenType.OPEN_BRACE);
1908 while (current () != TokenType.CLOSE_BRACE && current () != TokenType.EOF) {
1909 try {
1910 if (parent is Namespace) {
1911 parse_namespace_member ((Namespace) parent);
1912 } else if (parent is Class) {
1913 parse_class_member ((Class) parent);
1914 } else if (parent is Struct) {
1915 parse_struct_member ((Struct) parent);
1916 } else if (parent is Interface) {
1917 parse_interface_member ((Interface) parent);
1919 } catch (ParseError e) {
1920 int r;
1921 do {
1922 r = recover ();
1923 if (r == RecoveryState.STATEMENT_BEGIN) {
1924 next ();
1925 } else {
1926 break;
1928 } while (true);
1929 if (r == RecoveryState.EOF) {
1930 return;
1934 if (!root) {
1935 if (!accept (TokenType.CLOSE_BRACE)) {
1936 // only report error if it's not a secondary error
1937 if (context.report.get_errors () == 0) {
1938 Report.error (get_current_src (), "expected `}'");
1944 enum RecoveryState {
1945 EOF,
1946 DECLARATION_BEGIN,
1947 STATEMENT_BEGIN
1950 RecoveryState recover () {
1951 while (current () != TokenType.EOF) {
1952 switch (current ()) {
1953 case TokenType.ABSTRACT:
1954 case TokenType.CLASS:
1955 case TokenType.CONST:
1956 case TokenType.CONSTRUCT:
1957 case TokenType.DELEGATE:
1958 case TokenType.ENUM:
1959 case TokenType.ERRORDOMAIN:
1960 case TokenType.EXTERN:
1961 case TokenType.INLINE:
1962 case TokenType.INTERFACE:
1963 case TokenType.INTERNAL:
1964 case TokenType.NAMESPACE:
1965 case TokenType.NEW:
1966 case TokenType.OVERRIDE:
1967 case TokenType.PRIVATE:
1968 case TokenType.PROTECTED:
1969 case TokenType.PUBLIC:
1970 case TokenType.SIGNAL:
1971 case TokenType.STATIC:
1972 case TokenType.STRUCT:
1973 case TokenType.VIRTUAL:
1974 case TokenType.VOLATILE:
1975 return RecoveryState.DECLARATION_BEGIN;
1976 case TokenType.BREAK:
1977 case TokenType.CONTINUE:
1978 case TokenType.DELETE:
1979 case TokenType.DO:
1980 case TokenType.FOR:
1981 case TokenType.FOREACH:
1982 case TokenType.IF:
1983 case TokenType.LOCK:
1984 case TokenType.RETURN:
1985 case TokenType.SWITCH:
1986 case TokenType.THROW:
1987 case TokenType.TRY:
1988 case TokenType.VAR:
1989 case TokenType.WHILE:
1990 case TokenType.YIELD:
1991 return RecoveryState.STATEMENT_BEGIN;
1992 default:
1993 next ();
1994 break;
1997 return RecoveryState.EOF;
2000 Namespace parse_namespace_declaration (List<Attribute>? attrs) throws ParseError {
2001 var begin = get_location ();
2002 expect (TokenType.NAMESPACE);
2003 var sym = parse_symbol_name ();
2004 var ns = new Namespace (sym.name, get_src (begin));
2005 if (comment != null) {
2006 ns.add_comment (comment);
2007 comment = null;
2010 set_attributes (ns, attrs);
2012 expect (TokenType.OPEN_BRACE);
2014 var old_using_directives = scanner.source_file.current_using_directives;
2015 parse_using_directives (ns);
2017 parse_declarations (ns, true);
2019 scanner.source_file.current_using_directives = old_using_directives;
2021 if (!accept (TokenType.CLOSE_BRACE)) {
2022 // only report error if it's not a secondary error
2023 if (context.report.get_errors () == 0) {
2024 Report.error (get_current_src (), "expected `}'");
2028 Namespace result = ns;
2029 while (sym.inner != null) {
2030 sym = sym.inner;
2031 ns = new Namespace (sym.name, result.source_reference);
2032 ns.add_namespace ((Namespace) result);
2033 result = ns;
2035 return result;
2038 void parse_namespace_member (Namespace ns) throws ParseError {
2039 var sym = parse_declaration ();
2041 if (sym is Namespace) {
2042 ns.add_namespace ((Namespace) sym);
2043 } else if (sym is Class) {
2044 ns.add_class ((Class) sym);
2045 } else if (sym is Interface) {
2046 ns.add_interface ((Interface) sym);
2047 } else if (sym is Struct) {
2048 ns.add_struct ((Struct) sym);
2049 } else if (sym is Enum) {
2050 ns.add_enum ((Enum) sym);
2051 } else if (sym is ErrorDomain) {
2052 ns.add_error_domain ((ErrorDomain) sym);
2053 } else if (sym is Delegate) {
2054 ns.add_delegate ((Delegate) sym);
2055 } else if (sym is Method) {
2056 var method = (Method) sym;
2057 if (method.binding == MemberBinding.INSTANCE) {
2058 // default to static member binding
2059 method.binding = MemberBinding.STATIC;
2061 ns.add_method (method);
2062 } else if (sym is Field) {
2063 var field = (Field) sym;
2064 if (field.binding == MemberBinding.INSTANCE) {
2065 // default to static member binding
2066 field.binding = MemberBinding.STATIC;
2068 ns.add_field (field);
2069 } else if (sym is Constant) {
2070 ns.add_constant ((Constant) sym);
2071 } else {
2072 Report.error (sym.source_reference, "unexpected declaration in namespace");
2074 scanner.source_file.add_node (sym);
2077 void parse_using_directives (Namespace ns) throws ParseError {
2078 while (accept (TokenType.USING)) {
2079 do {
2080 var begin = get_location ();
2081 var sym = parse_symbol_name ();
2082 var ns_ref = new UsingDirective (sym, get_src (begin));
2083 scanner.source_file.add_using_directive (ns_ref);
2084 ns.add_using_directive (ns_ref);
2085 } while (accept (TokenType.COMMA));
2086 expect (TokenType.SEMICOLON);
2090 Symbol parse_class_declaration (List<Attribute>? attrs) throws ParseError {
2091 var begin = get_location ();
2092 var access = parse_access_modifier ();
2093 var flags = parse_type_declaration_modifiers ();
2094 expect (TokenType.CLASS);
2095 var sym = parse_symbol_name ();
2096 var type_param_list = parse_type_parameter_list ();
2097 var base_types = new ArrayList<DataType> ();
2098 if (accept (TokenType.COLON)) {
2099 do {
2100 base_types.add (parse_type ());
2101 } while (accept (TokenType.COMMA));
2104 var cl = new Class (sym.name, get_src (begin), comment);
2105 cl.access = access;
2106 if (ModifierFlags.ABSTRACT in flags) {
2107 cl.is_abstract = true;
2109 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2110 cl.external = true;
2112 set_attributes (cl, attrs);
2113 foreach (TypeParameter type_param in type_param_list) {
2114 cl.add_type_parameter (type_param);
2116 foreach (DataType base_type in base_types) {
2117 cl.add_base_type (base_type);
2120 parse_declarations (cl);
2122 // ensure there is always a default construction method
2123 if (!scanner.source_file.external_package
2124 && cl.default_construction_method == null) {
2125 var m = new CreationMethod (cl.name, null, cl.source_reference);
2126 m.access = SymbolAccessibility.PUBLIC;
2127 m.body = new Block (cl.source_reference);
2128 cl.add_method (m);
2131 Symbol result = cl;
2132 while (sym.inner != null) {
2133 sym = sym.inner;
2134 var ns = new Namespace (sym.name, cl.source_reference);
2135 if (result is Namespace) {
2136 ns.add_namespace ((Namespace) result);
2137 } else {
2138 ns.add_class ((Class) result);
2139 scanner.source_file.add_node (result);
2141 result = ns;
2143 return result;
2146 void parse_class_member (Class cl) throws ParseError {
2147 var sym = parse_declaration ();
2148 if (sym is Class) {
2149 cl.add_class ((Class) sym);
2150 } else if (sym is Struct) {
2151 cl.add_struct ((Struct) sym);
2152 } else if (sym is Enum) {
2153 cl.add_enum ((Enum) sym);
2154 } else if (sym is Delegate) {
2155 cl.add_delegate ((Delegate) sym);
2156 } else if (sym is Method) {
2157 cl.add_method ((Method) sym);
2158 } else if (sym is Signal) {
2159 cl.add_signal ((Signal) sym);
2160 } else if (sym is Field) {
2161 cl.add_field ((Field) sym);
2162 } else if (sym is Constant) {
2163 cl.add_constant ((Constant) sym);
2164 } else if (sym is Property) {
2165 cl.add_property ((Property) sym);
2166 } else if (sym is Constructor) {
2167 var c = (Constructor) sym;
2168 if (c.binding == MemberBinding.INSTANCE) {
2169 cl.constructor = c;
2170 } else if (c.binding == MemberBinding.CLASS) {
2171 cl.class_constructor = c;
2172 } else {
2173 cl.static_constructor = c;
2175 } else if (sym is Destructor) {
2176 var d = (Destructor) sym;
2177 if (d.binding == MemberBinding.STATIC) {
2178 cl.static_destructor = (Destructor) d;
2179 } else if (d.binding == MemberBinding.CLASS) {
2180 cl.class_destructor = (Destructor) d;
2181 } else {
2182 cl.destructor = (Destructor) d;
2184 } else {
2185 Report.error (sym.source_reference, "unexpected declaration in class");
2189 Constant parse_constant_declaration (List<Attribute>? attrs) throws ParseError {
2190 var begin = get_location ();
2191 var access = parse_access_modifier ();
2192 var flags = parse_member_declaration_modifiers ();
2193 expect (TokenType.CONST);
2194 var type = parse_type (false);
2195 string id = parse_identifier ();
2197 type = parse_inline_array_type (type);
2199 Expression initializer = null;
2200 if (accept (TokenType.ASSIGN)) {
2201 initializer = parse_expression ();
2203 expect (TokenType.SEMICOLON);
2205 // constant arrays don't own their element
2206 var array_type = type as ArrayType;
2207 if (array_type != null) {
2208 array_type.element_type.value_owned = false;
2211 var c = new Constant (id, type, initializer, get_src (begin), comment);
2212 c.access = access;
2213 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2214 c.external = true;
2216 if (ModifierFlags.NEW in flags) {
2217 c.hides = true;
2219 set_attributes (c, attrs);
2220 return c;
2223 Field parse_field_declaration (List<Attribute>? attrs) throws ParseError {
2224 var begin = get_location ();
2225 var access = parse_access_modifier ();
2226 var flags = parse_member_declaration_modifiers ();
2227 var type = parse_type ();
2228 string id = parse_identifier ();
2230 type = parse_inline_array_type (type);
2232 var f = new Field (id, type, null, get_src (begin), comment);
2233 f.access = access;
2234 set_attributes (f, attrs);
2235 if (ModifierFlags.STATIC in flags) {
2236 f.binding = MemberBinding.STATIC;
2237 } else if (ModifierFlags.CLASS in flags) {
2238 f.binding = MemberBinding.CLASS;
2240 if (ModifierFlags.ABSTRACT in flags
2241 || ModifierFlags.VIRTUAL in flags
2242 || ModifierFlags.OVERRIDE in flags) {
2243 Report.error (f.source_reference, "abstract, virtual, and override modifiers are not applicable to fields");
2245 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2246 f.external = true;
2248 if (ModifierFlags.NEW in flags) {
2249 f.hides = true;
2251 if (accept (TokenType.ASSIGN)) {
2252 f.initializer = parse_expression ();
2254 expect (TokenType.SEMICOLON);
2255 return f;
2258 InitializerList parse_initializer () throws ParseError {
2259 var begin = get_location ();
2260 expect (TokenType.OPEN_BRACE);
2261 var initializer = new InitializerList (get_src (begin));
2262 if (current () != TokenType.CLOSE_BRACE) {
2263 do {
2264 var init = parse_argument ();
2265 initializer.append (init);
2266 } while (accept (TokenType.COMMA));
2268 expect (TokenType.CLOSE_BRACE);
2269 return initializer;
2272 Method parse_method_declaration (List<Attribute>? attrs) throws ParseError {
2273 var begin = get_location ();
2274 var access = parse_access_modifier ();
2275 var flags = parse_member_declaration_modifiers ();
2276 var type = parse_type ();
2277 string id = parse_identifier ();
2278 var type_param_list = parse_type_parameter_list ();
2279 var method = new Method (id, type, get_src (begin), comment);
2280 method.access = access;
2281 set_attributes (method, attrs);
2282 foreach (TypeParameter type_param in type_param_list) {
2283 method.add_type_parameter (type_param);
2285 if (ModifierFlags.STATIC in flags) {
2286 method.binding = MemberBinding.STATIC;
2287 } else if (ModifierFlags.CLASS in flags) {
2288 method.binding = MemberBinding.CLASS;
2290 if (ModifierFlags.ASYNC in flags) {
2291 method.coroutine = true;
2293 if (ModifierFlags.NEW in flags) {
2294 method.hides = true;
2297 if (method.binding == MemberBinding.INSTANCE) {
2298 if (ModifierFlags.ABSTRACT in flags) {
2299 method.is_abstract = true;
2301 if (ModifierFlags.VIRTUAL in flags) {
2302 method.is_virtual = true;
2304 if (ModifierFlags.OVERRIDE in flags) {
2305 method.overrides = true;
2307 if ((method.is_abstract && method.is_virtual)
2308 || (method.is_abstract && method.overrides)
2309 || (method.is_virtual && method.overrides)) {
2310 throw new ParseError.SYNTAX (get_error ("only one of `abstract', `virtual', or `override' may be specified"));
2312 } else {
2313 if (ModifierFlags.ABSTRACT in flags
2314 || ModifierFlags.VIRTUAL in flags
2315 || ModifierFlags.OVERRIDE in flags) {
2316 throw new ParseError.SYNTAX (get_error ("the modifiers `abstract', `virtual', and `override' are not valid for static methods"));
2320 if (ModifierFlags.INLINE in flags) {
2321 method.is_inline = true;
2323 if (ModifierFlags.EXTERN in flags) {
2324 method.external = true;
2326 expect (TokenType.OPEN_PARENS);
2327 if (current () != TokenType.CLOSE_PARENS) {
2328 do {
2329 var param = parse_parameter ();
2330 method.add_parameter (param);
2331 } while (accept (TokenType.COMMA));
2333 expect (TokenType.CLOSE_PARENS);
2334 if (accept (TokenType.THROWS)) {
2335 do {
2336 method.add_error_type (parse_type ());
2337 } while (accept (TokenType.COMMA));
2339 while (accept (TokenType.REQUIRES)) {
2340 expect (TokenType.OPEN_PARENS);
2341 method.add_precondition (parse_expression ());
2342 expect (TokenType.CLOSE_PARENS);
2344 while (accept (TokenType.ENSURES)) {
2345 expect (TokenType.OPEN_PARENS);
2346 method.add_postcondition (parse_expression ());
2347 expect (TokenType.CLOSE_PARENS);
2349 if (!accept (TokenType.SEMICOLON)) {
2350 method.body = parse_block ();
2351 } else if (scanner.source_file.external_package) {
2352 method.external = true;
2354 return method;
2357 Property parse_property_declaration (List<Attribute>? attrs) throws ParseError {
2358 var begin = get_location ();
2359 var access = parse_access_modifier ();
2360 var flags = parse_member_declaration_modifiers ();
2361 var type = parse_type ();
2363 bool getter_owned = false;
2364 if (accept (TokenType.HASH)) {
2365 if (!context.deprecated) {
2366 Report.warning (get_last_src (), "deprecated syntax, use `owned` modifier before `get'");
2368 getter_owned = true;
2371 string id = parse_identifier ();
2372 var prop = new Property (id, type, null, null, get_src (begin), comment);
2373 prop.access = access;
2374 set_attributes (prop, attrs);
2375 if (ModifierFlags.STATIC in flags) {
2376 prop.binding = MemberBinding.STATIC;
2377 } else if (ModifierFlags.CLASS in flags) {
2378 prop.binding = MemberBinding.CLASS;
2380 if (ModifierFlags.ABSTRACT in flags) {
2381 prop.is_abstract = true;
2383 if (ModifierFlags.VIRTUAL in flags) {
2384 prop.is_virtual = true;
2386 if (ModifierFlags.OVERRIDE in flags) {
2387 prop.overrides = true;
2389 if (ModifierFlags.NEW in flags) {
2390 prop.hides = true;
2392 if (ModifierFlags.ASYNC in flags) {
2393 Report.error (prop.source_reference, "async properties are not supported yet");
2395 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2396 prop.external = true;
2398 if (accept (TokenType.THROWS)) {
2399 do {
2400 prop.add_error_type (parse_type ());
2401 } while (accept (TokenType.COMMA));
2402 Report.error (prop.source_reference, "properties throwing errors are not supported yet");
2404 expect (TokenType.OPEN_BRACE);
2405 while (current () != TokenType.CLOSE_BRACE) {
2406 if (accept (TokenType.DEFAULT)) {
2407 if (prop.default_expression != null) {
2408 throw new ParseError.SYNTAX (get_error ("property default value already defined"));
2410 expect (TokenType.ASSIGN);
2411 prop.default_expression = parse_expression ();
2412 expect (TokenType.SEMICOLON);
2413 } else {
2414 var accessor_begin = get_location ();
2415 var accessor_attrs = parse_attributes ();
2416 var accessor_access = parse_access_modifier (SymbolAccessibility.PUBLIC);
2418 var value_type = type.copy ();
2419 value_type.value_owned = accept (TokenType.OWNED);
2421 if (accept (TokenType.GET)) {
2422 if (prop.get_accessor != null) {
2423 throw new ParseError.SYNTAX (get_error ("property get accessor already defined"));
2426 if (getter_owned) {
2427 value_type.value_owned = true;
2430 Block block = null;
2431 if (!accept (TokenType.SEMICOLON)) {
2432 block = parse_block ();
2433 prop.external = false;
2435 prop.get_accessor = new PropertyAccessor (true, false, false, value_type, block, get_src (accessor_begin));
2436 set_attributes (prop.get_accessor, accessor_attrs);
2437 prop.get_accessor.access = accessor_access;
2438 } else {
2439 bool writable, _construct;
2440 if (accept (TokenType.SET)) {
2441 writable = true;
2442 _construct = (context.profile == Profile.GOBJECT) && accept (TokenType.CONSTRUCT);
2443 } else if (context.profile == Profile.GOBJECT && accept (TokenType.CONSTRUCT)) {
2444 _construct = true;
2445 writable = accept (TokenType.SET);
2446 } else {
2447 throw new ParseError.SYNTAX (get_error ("expected get, set, or construct"));
2449 if (prop.set_accessor != null) {
2450 throw new ParseError.SYNTAX (get_error ("property set accessor already defined"));
2452 Block block = null;
2453 if (!accept (TokenType.SEMICOLON)) {
2454 block = parse_block ();
2455 prop.external = false;
2457 prop.set_accessor = new PropertyAccessor (false, writable, _construct, value_type, block, get_src (accessor_begin));
2458 set_attributes (prop.set_accessor, accessor_attrs);
2459 prop.set_accessor.access = accessor_access;
2463 expect (TokenType.CLOSE_BRACE);
2465 if (!prop.is_abstract && !prop.external) {
2466 bool empty_get = (prop.get_accessor != null && prop.get_accessor.body == null);
2467 bool empty_set = (prop.set_accessor != null && prop.set_accessor.body == null);
2469 if (empty_get != empty_set) {
2470 if (empty_get) {
2471 Report.error (prop.source_reference, "property getter must have a body");
2472 } else if (empty_set) {
2473 Report.error (prop.source_reference, "property setter must have a body");
2475 prop.error = true;
2478 if (empty_get && empty_set) {
2479 /* automatic property accessor body generation */
2480 var field_type = prop.property_type.copy ();
2481 prop.field = new Field ("_%s".printf (prop.name), field_type, prop.default_expression, prop.source_reference);
2482 prop.field.access = SymbolAccessibility.PRIVATE;
2483 prop.field.binding = prop.binding;
2487 return prop;
2490 Signal parse_signal_declaration (List<Attribute>? attrs) throws ParseError {
2491 var begin = get_location ();
2492 var access = parse_access_modifier ();
2493 var flags = parse_member_declaration_modifiers ();
2494 expect (TokenType.SIGNAL);
2495 var type = parse_type ();
2496 string id = parse_identifier ();
2497 var sig = new Signal (id, type, get_src (begin), comment);
2498 sig.access = access;
2499 set_attributes (sig, attrs);
2500 if (ModifierFlags.STATIC in flags) {
2501 throw new ParseError.SYNTAX (get_error ("`static' modifier not allowed on signals"));
2502 } else if (ModifierFlags.CLASS in flags) {
2503 throw new ParseError.SYNTAX (get_error ("`class' modifier not allowed on signals"));
2505 if (ModifierFlags.VIRTUAL in flags) {
2506 sig.is_virtual = true;
2508 if (ModifierFlags.NEW in flags) {
2509 sig.hides = true;
2511 expect (TokenType.OPEN_PARENS);
2512 if (current () != TokenType.CLOSE_PARENS) {
2513 do {
2514 var param = parse_parameter ();
2515 sig.add_parameter (param);
2516 } while (accept (TokenType.COMMA));
2518 expect (TokenType.CLOSE_PARENS);
2519 if (!accept (TokenType.SEMICOLON)) {
2520 sig.body = parse_block ();
2523 return sig;
2526 Constructor parse_constructor_declaration (List<Attribute>? attrs) throws ParseError {
2527 var begin = get_location ();
2528 var flags = parse_member_declaration_modifiers ();
2529 expect (TokenType.CONSTRUCT);
2530 if (ModifierFlags.NEW in flags) {
2531 throw new ParseError.SYNTAX (get_error ("`new' modifier not allowed on constructor"));
2533 var c = new Constructor (get_src (begin));
2534 if (ModifierFlags.STATIC in flags) {
2535 c.binding = MemberBinding.STATIC;
2536 } else if (ModifierFlags.CLASS in flags) {
2537 c.binding = MemberBinding.CLASS;
2539 c.body = parse_block ();
2540 return c;
2543 Destructor parse_destructor_declaration (List<Attribute>? attrs) throws ParseError {
2544 var begin = get_location ();
2545 var flags = parse_member_declaration_modifiers ();
2546 expect (TokenType.TILDE);
2547 parse_identifier ();
2548 expect (TokenType.OPEN_PARENS);
2549 expect (TokenType.CLOSE_PARENS);
2550 if (ModifierFlags.NEW in flags) {
2551 throw new ParseError.SYNTAX (get_error ("`new' modifier not allowed on destructor"));
2553 var d = new Destructor (get_src (begin));
2554 if (ModifierFlags.STATIC in flags) {
2555 d.binding = MemberBinding.STATIC;
2556 } else if (ModifierFlags.CLASS in flags) {
2557 d.binding = MemberBinding.CLASS;
2559 d.body = parse_block ();
2560 return d;
2563 Symbol parse_struct_declaration (List<Attribute>? attrs) throws ParseError {
2564 var begin = get_location ();
2565 var access = parse_access_modifier ();
2566 var flags = parse_type_declaration_modifiers ();
2567 expect (TokenType.STRUCT);
2568 var sym = parse_symbol_name ();
2569 var type_param_list = parse_type_parameter_list ();
2570 DataType base_type = null;
2571 if (accept (TokenType.COLON)) {
2572 base_type = parse_type ();
2574 var st = new Struct (sym.name, get_src (begin), comment);
2575 st.access = access;
2576 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2577 st.external = true;
2579 set_attributes (st, attrs);
2580 foreach (TypeParameter type_param in type_param_list) {
2581 st.add_type_parameter (type_param);
2583 if (base_type != null) {
2584 st.base_type = base_type;
2587 parse_declarations (st);
2589 Symbol result = st;
2590 while (sym.inner != null) {
2591 sym = sym.inner;
2593 var ns = new Namespace (sym.name, st.source_reference);
2594 if (result is Namespace) {
2595 ns.add_namespace ((Namespace) result);
2596 } else {
2597 ns.add_struct ((Struct) result);
2598 scanner.source_file.add_node (result);
2600 result = ns;
2602 return result;
2605 void parse_struct_member (Struct st) throws ParseError {
2606 var sym = parse_declaration ();
2607 if (sym is Method) {
2608 st.add_method ((Method) sym);
2609 } else if (sym is Field) {
2610 st.add_field ((Field) sym);
2611 } else if (sym is Constant) {
2612 st.add_constant ((Constant) sym);
2613 } else if (sym is Property) {
2614 st.add_property ((Property) sym);
2615 } else {
2616 Report.error (sym.source_reference, "unexpected declaration in struct");
2620 Symbol parse_interface_declaration (List<Attribute>? attrs) throws ParseError {
2621 var begin = get_location ();
2622 var access = parse_access_modifier ();
2623 var flags = parse_type_declaration_modifiers ();
2624 expect (TokenType.INTERFACE);
2625 var sym = parse_symbol_name ();
2626 var type_param_list = parse_type_parameter_list ();
2627 var base_types = new ArrayList<DataType> ();
2628 if (accept (TokenType.COLON)) {
2629 do {
2630 var type = parse_type ();
2631 base_types.add (type);
2632 } while (accept (TokenType.COMMA));
2634 var iface = new Interface (sym.name, get_src (begin), comment);
2635 iface.access = access;
2636 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2637 iface.external = true;
2639 set_attributes (iface, attrs);
2640 foreach (TypeParameter type_param in type_param_list) {
2641 iface.add_type_parameter (type_param);
2643 foreach (DataType base_type in base_types) {
2644 iface.add_prerequisite (base_type);
2647 parse_declarations (iface);
2649 Symbol result = iface;
2650 while (sym.inner != null) {
2651 sym = sym.inner;
2652 var ns = new Namespace (sym.name, iface.source_reference);
2653 if (result is Namespace) {
2654 ns.add_namespace ((Namespace) result);
2655 } else {
2656 ns.add_interface ((Interface) result);
2657 scanner.source_file.add_node (result);
2659 result = ns;
2661 return result;
2664 void parse_interface_member (Interface iface) throws ParseError {
2665 var sym = parse_declaration ();
2666 if (sym is Class) {
2667 iface.add_class ((Class) sym);
2668 } else if (sym is Struct) {
2669 iface.add_struct ((Struct) sym);
2670 } else if (sym is Enum) {
2671 iface.add_enum ((Enum) sym);
2672 } else if (sym is Delegate) {
2673 iface.add_delegate ((Delegate) sym);
2674 } else if (sym is Method) {
2675 iface.add_method ((Method) sym);
2676 } else if (sym is Signal) {
2677 iface.add_signal ((Signal) sym);
2678 } else if (sym is Field) {
2679 iface.add_field ((Field) sym);
2680 } else if (sym is Constant) {
2681 iface.add_constant ((Constant) sym);
2682 } else if (sym is Property) {
2683 iface.add_property ((Property) sym);
2684 } else {
2685 Report.error (sym.source_reference, "unexpected declaration in interface");
2689 Symbol parse_enum_declaration (List<Attribute>? attrs) throws ParseError {
2690 var begin = get_location ();
2691 var access = parse_access_modifier ();
2692 var flags = parse_type_declaration_modifiers ();
2693 expect (TokenType.ENUM);
2694 var sym = parse_symbol_name ();
2695 var en = new Enum (sym.name, get_src (begin), comment);
2696 en.access = access;
2697 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2698 en.external = true;
2700 set_attributes (en, attrs);
2702 expect (TokenType.OPEN_BRACE);
2703 do {
2704 if (current () == TokenType.CLOSE_BRACE
2705 && en.get_values ().size > 0) {
2706 // allow trailing comma
2707 break;
2709 var value_attrs = parse_attributes ();
2710 var value_begin = get_location ();
2711 string id = parse_identifier ();
2712 comment = scanner.pop_comment ();
2713 var ev = new EnumValue (id, get_src (value_begin), comment);
2714 set_attributes (ev, value_attrs);
2715 if (accept (TokenType.ASSIGN)) {
2716 ev.value = parse_expression ();
2718 en.add_value (ev);
2719 } while (accept (TokenType.COMMA));
2720 if (accept (TokenType.SEMICOLON)) {
2721 // enum methods
2722 while (current () != TokenType.CLOSE_BRACE) {
2723 var member_sym = parse_declaration ();
2724 if (member_sym is Method) {
2725 en.add_method ((Method) member_sym);
2726 } else {
2727 Report.error (member_sym.source_reference, "unexpected declaration in enum");
2731 expect (TokenType.CLOSE_BRACE);
2733 Symbol result = en;
2734 while (sym.inner != null) {
2735 sym = sym.inner;
2736 var ns = new Namespace (sym.name, en.source_reference);
2737 if (result is Namespace) {
2738 ns.add_namespace ((Namespace) result);
2739 } else {
2740 ns.add_enum ((Enum) result);
2741 scanner.source_file.add_node (result);
2743 result = ns;
2745 return result;
2748 Symbol parse_errordomain_declaration (List<Attribute>? attrs) throws ParseError {
2749 var begin = get_location ();
2750 var access = parse_access_modifier ();
2751 var flags = parse_type_declaration_modifiers ();
2752 expect (TokenType.ERRORDOMAIN);
2753 var sym = parse_symbol_name ();
2754 var ed = new ErrorDomain (sym.name, get_src (begin), comment);
2755 ed.access = access;
2756 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2757 ed.external = true;
2759 set_attributes (ed, attrs);
2761 expect (TokenType.OPEN_BRACE);
2762 do {
2763 if (current () == TokenType.CLOSE_BRACE
2764 && ed.get_codes ().size > 0) {
2765 // allow trailing comma
2766 break;
2768 var code_attrs = parse_attributes ();
2769 var code_begin = get_location ();
2770 string id = parse_identifier ();
2771 comment = scanner.pop_comment ();
2772 var ec = new ErrorCode (id, get_src (code_begin), comment);
2773 set_attributes (ec, code_attrs);
2774 if (accept (TokenType.ASSIGN)) {
2775 ec.value = parse_expression ();
2777 ed.add_code (ec);
2778 } while (accept (TokenType.COMMA));
2779 if (accept (TokenType.SEMICOLON)) {
2780 // errordomain methods
2781 while (current () != TokenType.CLOSE_BRACE) {
2782 var member_sym = parse_declaration ();
2783 if (member_sym is Method) {
2784 ed.add_method ((Method) member_sym);
2785 } else {
2786 Report.error (member_sym.source_reference, "unexpected declaration in errordomain");
2790 expect (TokenType.CLOSE_BRACE);
2792 Symbol result = ed;
2793 while (sym.inner != null) {
2794 sym = sym.inner;
2795 var ns = new Namespace (sym.name, ed.source_reference);
2796 if (result is Namespace) {
2797 ns.add_namespace ((Namespace) result);
2798 } else {
2799 ns.add_error_domain ((ErrorDomain) result);
2800 scanner.source_file.add_node (result);
2802 result = ns;
2804 return result;
2807 SymbolAccessibility parse_access_modifier (SymbolAccessibility default_access = SymbolAccessibility.PRIVATE) {
2808 switch (current ()) {
2809 case TokenType.PRIVATE:
2810 next ();
2811 return SymbolAccessibility.PRIVATE;
2812 case TokenType.PROTECTED:
2813 next ();
2814 return SymbolAccessibility.PROTECTED;
2815 case TokenType.INTERNAL:
2816 next ();
2817 return SymbolAccessibility.INTERNAL;
2818 case TokenType.PUBLIC:
2819 next ();
2820 return SymbolAccessibility.PUBLIC;
2821 default:
2822 return default_access;
2826 ModifierFlags parse_type_declaration_modifiers () {
2827 ModifierFlags flags = 0;
2828 while (true) {
2829 switch (current ()) {
2830 case TokenType.ABSTRACT:
2831 next ();
2832 flags |= ModifierFlags.ABSTRACT;
2833 break;
2834 case TokenType.EXTERN:
2835 next ();
2836 flags |= ModifierFlags.EXTERN;
2837 break;
2838 case TokenType.STATIC:
2839 next ();
2840 flags |= ModifierFlags.STATIC;
2841 break;
2842 default:
2843 return flags;
2848 ModifierFlags parse_member_declaration_modifiers () {
2849 ModifierFlags flags = 0;
2850 while (true) {
2851 switch (current ()) {
2852 case TokenType.ABSTRACT:
2853 next ();
2854 flags |= ModifierFlags.ABSTRACT;
2855 break;
2856 case TokenType.ASYNC:
2857 next ();
2858 flags |= ModifierFlags.ASYNC;
2859 break;
2860 case TokenType.CLASS:
2861 next ();
2862 flags |= ModifierFlags.CLASS;
2863 break;
2864 case TokenType.EXTERN:
2865 next ();
2866 flags |= ModifierFlags.EXTERN;
2867 break;
2868 case TokenType.INLINE:
2869 next ();
2870 flags |= ModifierFlags.INLINE;
2871 break;
2872 case TokenType.NEW:
2873 next ();
2874 flags |= ModifierFlags.NEW;
2875 break;
2876 case TokenType.OVERRIDE:
2877 next ();
2878 flags |= ModifierFlags.OVERRIDE;
2879 break;
2880 case TokenType.STATIC:
2881 next ();
2882 flags |= ModifierFlags.STATIC;
2883 break;
2884 case TokenType.VIRTUAL:
2885 next ();
2886 flags |= ModifierFlags.VIRTUAL;
2887 break;
2888 default:
2889 return flags;
2894 FormalParameter parse_parameter () throws ParseError {
2895 var attrs = parse_attributes ();
2896 var begin = get_location ();
2897 if (accept (TokenType.ELLIPSIS)) {
2898 // varargs
2899 return new FormalParameter.with_ellipsis (get_src (begin));
2901 bool params_array = accept (TokenType.PARAMS);
2902 var direction = ParameterDirection.IN;
2903 if (accept (TokenType.OUT)) {
2904 direction = ParameterDirection.OUT;
2905 } else if (accept (TokenType.REF)) {
2906 direction = ParameterDirection.REF;
2909 DataType type;
2910 if (direction == ParameterDirection.IN) {
2911 // in parameters are weak by default
2912 type = parse_type (false);
2913 } else {
2914 // out parameters own the value by default
2915 type = parse_type (true);
2917 string id = parse_identifier ();
2918 var param = new FormalParameter (id, type, get_src (begin));
2919 set_attributes (param, attrs);
2920 param.direction = direction;
2921 param.params_array = params_array;
2922 if (accept (TokenType.ASSIGN)) {
2923 param.default_expression = parse_expression ();
2925 return param;
2928 CreationMethod parse_creation_method_declaration (List<Attribute>? attrs) throws ParseError {
2929 var begin = get_location ();
2930 var access = parse_access_modifier ();
2931 var flags = parse_member_declaration_modifiers ();
2932 var sym = parse_symbol_name ();
2933 if (ModifierFlags.NEW in flags) {
2934 throw new ParseError.SYNTAX (get_error ("`new' modifier not allowed on creation method"));
2936 CreationMethod method;
2937 if (sym.inner == null) {
2938 method = new CreationMethod (sym.name, null, get_src (begin), comment);
2939 } else {
2940 method = new CreationMethod (sym.inner.name, sym.name, get_src (begin), comment);
2942 if (ModifierFlags.EXTERN in flags) {
2943 method.external = true;
2945 if (ModifierFlags.ABSTRACT in flags
2946 || ModifierFlags.VIRTUAL in flags
2947 || ModifierFlags.OVERRIDE in flags) {
2948 Report.error (method.source_reference, "abstract, virtual, and override modifiers are not applicable to creation methods");
2950 if (ModifierFlags.ASYNC in flags) {
2951 method.coroutine = true;
2953 expect (TokenType.OPEN_PARENS);
2954 if (current () != TokenType.CLOSE_PARENS) {
2955 do {
2956 var param = parse_parameter ();
2957 method.add_parameter (param);
2958 } while (accept (TokenType.COMMA));
2960 expect (TokenType.CLOSE_PARENS);
2961 if (accept (TokenType.THROWS)) {
2962 do {
2963 method.add_error_type (parse_type ());
2964 } while (accept (TokenType.COMMA));
2966 method.access = access;
2967 set_attributes (method, attrs);
2968 if (!accept (TokenType.SEMICOLON)) {
2969 method.body = parse_block ();
2970 } else if (scanner.source_file.external_package) {
2971 method.external = true;
2973 return method;
2976 Symbol parse_delegate_declaration (List<Attribute>? attrs) throws ParseError {
2977 var begin = get_location ();
2978 var access = parse_access_modifier ();
2979 var flags = parse_member_declaration_modifiers ();
2980 expect (TokenType.DELEGATE);
2981 if (ModifierFlags.NEW in flags) {
2982 throw new ParseError.SYNTAX (get_error ("`new' modifier not allowed on delegates"));
2984 var type = parse_type ();
2985 var sym = parse_symbol_name ();
2986 var type_param_list = parse_type_parameter_list ();
2987 var d = new Delegate (sym.name, type, get_src (begin), comment);
2988 d.access = access;
2989 set_attributes (d, attrs);
2990 if (ModifierFlags.STATIC in flags) {
2991 if (!context.deprecated) {
2992 // TODO enable warning in future releases
2993 // Report.warning (get_last_src (), "deprecated syntax, use [CCode (has_target = false)]");
2995 } else {
2996 d.has_target = true;
2998 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2999 d.external = true;
3001 foreach (TypeParameter type_param in type_param_list) {
3002 d.add_type_parameter (type_param);
3004 expect (TokenType.OPEN_PARENS);
3005 if (current () != TokenType.CLOSE_PARENS) {
3006 do {
3007 var param = parse_parameter ();
3008 d.add_parameter (param);
3009 } while (accept (TokenType.COMMA));
3011 expect (TokenType.CLOSE_PARENS);
3012 if (accept (TokenType.THROWS)) {
3013 do {
3014 d.add_error_type (parse_type ());
3015 } while (accept (TokenType.COMMA));
3017 expect (TokenType.SEMICOLON);
3019 Symbol result = d;
3020 while (sym.inner != null) {
3021 sym = sym.inner;
3022 var ns = new Namespace (sym.name, d.source_reference);
3023 if (result is Namespace) {
3024 ns.add_namespace ((Namespace) result);
3025 } else {
3026 ns.add_delegate ((Delegate) result);
3027 scanner.source_file.add_node (result);
3029 result = ns;
3031 return result;
3034 List<TypeParameter> parse_type_parameter_list () throws ParseError {
3035 var list = new ArrayList<TypeParameter> ();
3036 if (accept (TokenType.OP_LT)) {
3037 do {
3038 var begin = get_location ();
3039 string id = parse_identifier ();
3040 list.add (new TypeParameter (id, get_src (begin)));
3041 } while (accept (TokenType.COMMA));
3042 expect (TokenType.OP_GT);
3044 return list;
3047 void skip_type_argument_list () throws ParseError {
3048 if (accept (TokenType.OP_LT)) {
3049 do {
3050 skip_type ();
3051 } while (accept (TokenType.COMMA));
3052 expect (TokenType.OP_GT);
3056 // try to parse type argument list
3057 List<DataType>? parse_type_argument_list (bool maybe_expression) throws ParseError {
3058 var begin = get_location ();
3059 if (accept (TokenType.OP_LT)) {
3060 var list = new ArrayList<DataType> ();
3061 do {
3062 switch (current ()) {
3063 case TokenType.VOID:
3064 case TokenType.DYNAMIC:
3065 case TokenType.UNOWNED:
3066 case TokenType.WEAK:
3067 case TokenType.IDENTIFIER:
3068 var type = parse_type ();
3069 list.add (type);
3070 break;
3071 default:
3072 rollback (begin);
3073 return null;
3075 } while (accept (TokenType.COMMA));
3076 if (!accept (TokenType.OP_GT)) {
3077 rollback (begin);
3078 return null;
3080 if (maybe_expression) {
3081 // check follower to decide whether to keep type argument list
3082 switch (current ()) {
3083 case TokenType.OPEN_PARENS:
3084 case TokenType.CLOSE_PARENS:
3085 case TokenType.CLOSE_BRACKET:
3086 case TokenType.COLON:
3087 case TokenType.SEMICOLON:
3088 case TokenType.COMMA:
3089 case TokenType.DOT:
3090 case TokenType.INTERR:
3091 case TokenType.OP_EQ:
3092 case TokenType.OP_NE:
3093 // keep type argument list
3094 break;
3095 default:
3096 // interpret tokens as expression
3097 rollback (begin);
3098 return null;
3101 return list;
3103 return null;
3106 MemberAccess parse_member_name () throws ParseError {
3107 var begin = get_location ();
3108 MemberAccess expr = null;
3109 bool first = true;
3110 do {
3111 string id = parse_identifier ();
3113 // The first member access can be global:: qualified
3114 bool qualified = false;
3115 if (first && id == "global" && accept (TokenType.DOUBLE_COLON)) {
3116 id = parse_identifier ();
3117 qualified = true;
3120 List<DataType> type_arg_list = parse_type_argument_list (false);
3121 expr = new MemberAccess (expr, id, get_src (begin));
3122 expr.qualified = qualified;
3123 if (type_arg_list != null) {
3124 foreach (DataType type_arg in type_arg_list) {
3125 expr.add_type_argument (type_arg);
3129 first = false;
3130 } while (accept (TokenType.DOT));
3131 return expr;
3134 bool is_declaration_keyword (TokenType type) {
3135 switch (type) {
3136 case TokenType.ABSTRACT:
3137 case TokenType.ASYNC:
3138 case TokenType.CLASS:
3139 case TokenType.CONST:
3140 case TokenType.DELEGATE:
3141 case TokenType.ENUM:
3142 case TokenType.ERRORDOMAIN:
3143 case TokenType.EXTERN:
3144 case TokenType.INLINE:
3145 case TokenType.INTERFACE:
3146 case TokenType.INTERNAL:
3147 case TokenType.NAMESPACE:
3148 case TokenType.NEW:
3149 case TokenType.OVERRIDE:
3150 case TokenType.PRIVATE:
3151 case TokenType.PROTECTED:
3152 case TokenType.PUBLIC:
3153 case TokenType.SIGNAL:
3154 case TokenType.STATIC:
3155 case TokenType.STRUCT:
3156 case TokenType.VIRTUAL:
3157 case TokenType.VOLATILE:
3158 return true;
3159 default:
3160 return false;
3165 public errordomain Vala.ParseError {
3166 FAILED,
3167 SYNTAX