Remove workarounds for old Vala versions
[vala-lang.git] / vala / valagenieparser.vala
blob9dc35e76b0ae616816314d24620b6769b2735ad5
1 /* valagenieparser.vala
3 * Copyright (C) 2008 Jamie McCracken, Jürg Billeter
4 * Based on code by Jürg Billeter
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Author:
21 * Jamie McCracken jamiemcc gnome org
24 using GLib;
25 using Gee;
28 /**
29 * Code visitor parsing all Genie source files.
31 public class Vala.Genie.Parser : CodeVisitor {
32 Scanner scanner;
34 CodeContext context;
36 // token buffer
37 TokenInfo[] tokens;
38 // index of current token in buffer
39 int index;
40 // number of tokens in buffer
41 int size;
43 string comment;
45 string class_name;
47 /* hack needed to know if any part of an expression is a lambda one */
48 bool current_expr_is_lambda;
50 const int BUFFER_SIZE = 32;
52 struct TokenInfo {
53 public TokenType type;
54 public SourceLocation begin;
55 public SourceLocation end;
58 enum ModifierFlags {
59 NONE,
60 ABSTRACT = 1 << 0,
61 CLASS = 1 << 1,
62 EXTERN = 1 << 2,
63 INLINE = 1 << 3,
64 OVERRIDE = 1 << 4,
65 STATIC = 1 << 5,
66 VIRTUAL = 1 << 6,
67 PRIVATE = 1 << 7
70 public Parser () {
71 tokens = new TokenInfo[BUFFER_SIZE];
72 class_name = null;
73 current_expr_is_lambda = false;
76 /**
77 * Parses all .gs source files in the specified code context and
78 * builds a code tree.
80 * @param context a code context
82 public void parse (CodeContext context) {
83 this.context = context;
84 context.accept (this);
87 public override void visit_source_file (SourceFile source_file) {
88 if (source_file.filename.has_suffix (".gs")) {
89 parse_file (source_file);
93 inline bool next () {
94 index = (index + 1) % BUFFER_SIZE;
95 size--;
96 if (size <= 0) {
97 SourceLocation begin, end;
98 TokenType type = scanner.read_token (out begin, out end);
99 tokens[index].type = type;
100 tokens[index].begin = begin;
101 tokens[index].end = end;
102 size = 1;
104 return (tokens[index].type != TokenType.EOF);
107 inline void prev () {
108 index = (index - 1 + BUFFER_SIZE) % BUFFER_SIZE;
109 size++;
110 assert (size <= BUFFER_SIZE);
113 inline TokenType current () {
114 return tokens[index].type;
117 inline bool accept (TokenType type) {
118 if (current () == type) {
119 next ();
120 return true;
122 return false;
125 inline bool accept_terminator () {
126 if (current () == TokenType.SEMICOLON || current () == TokenType.EOL) {
127 next ();
128 return true;
130 return false;
133 inline bool accept_block () {
135 bool has_term = accept_terminator ();
137 if (accept (TokenType.INDENT)) {
138 prev();
139 return true;
142 if (has_term) {
143 prev ();
146 return false;
149 string get_error (string msg) {
150 var begin = get_location ();
151 next ();
152 Report.error (get_src (begin), "syntax error, " + msg);
153 return msg;
156 inline bool expect (TokenType type) throws ParseError {
157 if (accept (type)) {
158 return true;
161 TokenType cur = current ();
162 TokenType pre = tokens[index - 1].type;
164 throw new ParseError.SYNTAX (get_error ("expected %s but got %s with previous %s".printf (type.to_string (), cur.to_string (), pre.to_string())));
167 inline bool expect_terminator () throws ParseError {
168 if (accept_terminator ()) {
169 return true;
172 TokenType cur = current ();
174 throw new ParseError.SYNTAX (get_error ("expected line end or semicolon but got %s".printf (cur.to_string())));
177 inline SourceLocation get_location () {
178 return tokens[index].begin;
181 string get_last_string () {
182 int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE;
183 return ((string) tokens[last_index].begin.pos).ndup ((tokens[last_index].end.pos - tokens[last_index].begin.pos));
186 SourceReference get_src (SourceLocation begin) {
187 int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE;
189 return new SourceReference (scanner.source_file, begin.line, begin.column, tokens[last_index].end.line, tokens[last_index].end.column);
192 SourceReference get_src_com (SourceLocation begin) {
193 int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE;
195 var src = new SourceReference.with_comment (scanner.source_file, begin.line, begin.column, tokens[last_index].end.line, tokens[last_index].end.column, comment);
196 comment = null;
197 return src;
200 SourceReference get_current_src () {
201 return new SourceReference (scanner.source_file, tokens[index].begin.line, tokens[index].begin.column, tokens[index].end.line, tokens[index].end.column);
204 void rollback (SourceLocation location) {
205 while (tokens[index].begin.pos != location.pos) {
206 prev ();
210 inline SymbolAccessibility get_access (string s) {
211 if (s[0] == '_') {
212 return SymbolAccessibility.PRIVATE;
215 return SymbolAccessibility.PUBLIC;
218 void skip_identifier () throws ParseError {
219 // also accept keywords as identifiers where there is no conflict
220 switch (current ()) {
221 case TokenType.ABSTRACT:
222 case TokenType.AS:
223 case TokenType.ASSERT:
224 case TokenType.BREAK:
225 case TokenType.CLASS:
226 case TokenType.CONST:
227 case TokenType.CONTINUE:
228 case TokenType.DEDENT:
229 case TokenType.DEF:
230 case TokenType.DEFAULT:
231 case TokenType.DELEGATE:
232 case TokenType.DELETE:
233 case TokenType.DO:
234 case TokenType.DOWNTO:
235 case TokenType.DYNAMIC:
236 case TokenType.ELSE:
237 case TokenType.EOL:
238 case TokenType.ENUM:
239 case TokenType.ENSURES:
240 case TokenType.ERRORDOMAIN:
241 case TokenType.EVENT:
242 case TokenType.EXCEPT:
243 case TokenType.EXTERN:
244 case TokenType.FALSE:
245 case TokenType.FINAL:
246 case TokenType.FINALLY:
247 case TokenType.FOR:
248 case TokenType.GET:
249 case TokenType.IDENTIFIER:
250 case TokenType.IF:
251 case TokenType.IN:
252 case TokenType.INDENT:
253 case TokenType.INIT:
254 case TokenType.INLINE:
255 case TokenType.INTERFACE:
256 case TokenType.IS:
257 case TokenType.ISA:
258 case TokenType.LOCK:
259 case TokenType.NAMESPACE:
260 case TokenType.NEW:
261 case TokenType.NULL:
262 case TokenType.OF:
263 case TokenType.OUT:
264 case TokenType.OVERRIDE:
265 case TokenType.PASS:
266 case TokenType.PRINT:
267 case TokenType.PRIVATE:
268 case TokenType.PROP:
269 case TokenType.RAISE:
270 case TokenType.RAISES:
271 case TokenType.REF:
272 case TokenType.REQUIRES:
273 case TokenType.RETURN:
274 case TokenType.SET:
275 case TokenType.SIZEOF:
276 case TokenType.STATIC:
277 case TokenType.STRUCT:
278 case TokenType.SUPER:
279 case TokenType.THIS:
280 case TokenType.TO:
281 case TokenType.TRUE:
282 case TokenType.TRY:
283 case TokenType.TYPEOF:
284 case TokenType.USES:
285 case TokenType.VAR:
286 case TokenType.VIRTUAL:
287 case TokenType.VOID:
288 case TokenType.VOLATILE:
289 case TokenType.WEAK:
290 case TokenType.WHEN:
291 case TokenType.WHILE:
292 next ();
293 return;
294 default:
295 throw new ParseError.SYNTAX (get_error ("expected identifier"));
299 string parse_identifier () throws ParseError {
300 skip_identifier ();
301 return get_last_string ();
304 Expression parse_literal () throws ParseError {
305 var begin = get_location ();
307 switch (current ()) {
308 case TokenType.TRUE:
309 next ();
310 return new BooleanLiteral (true, get_src (begin));
311 case TokenType.FALSE:
312 next ();
313 return new BooleanLiteral (false, get_src (begin));
314 case TokenType.INTEGER_LITERAL:
315 next ();
316 return new IntegerLiteral (get_last_string (), get_src (begin));
317 case TokenType.REAL_LITERAL:
318 next ();
319 return new RealLiteral (get_last_string (), get_src (begin));
320 case TokenType.CHARACTER_LITERAL:
321 next ();
322 return new CharacterLiteral (get_last_string (), get_src (begin));
323 case TokenType.STRING_LITERAL:
324 next ();
325 return new StringLiteral (get_last_string (), get_src (begin));
326 case TokenType.NULL:
327 next ();
328 return new NullLiteral (get_src (begin));
329 default:
330 throw new ParseError.SYNTAX (get_error ("expected literal"));
334 public void parse_file (SourceFile source_file) {
335 scanner = new Scanner (source_file);
336 scanner.indent_spaces = 0;
337 index = -1;
338 size = 0;
340 next ();
342 try {
343 var begin = get_location ();
344 /* see if there is an indent attribute */
345 if (accept (TokenType.OPEN_BRACKET)) {
346 var id = parse_identifier ();
347 if (id == "indent") {
348 expect (TokenType.ASSIGN);
349 expect (TokenType.INTEGER_LITERAL);
350 scanner.indent_spaces = get_last_string().to_int();
351 expect (TokenType.CLOSE_BRACKET);
352 expect (TokenType.EOL);
353 } else {
354 rollback (begin);
358 parse_using_directives ();
359 parse_declarations (context.root, true);
360 } catch (ParseError e) {
361 // already reported
364 scanner = null;
367 void skip_symbol_name () throws ParseError {
368 do {
369 skip_identifier ();
370 } while (accept (TokenType.DOT));
373 UnresolvedSymbol parse_symbol_name () throws ParseError {
374 var begin = get_location ();
375 UnresolvedSymbol sym = null;
376 do {
377 string name = parse_identifier ();
378 sym = new UnresolvedSymbol (sym, name, get_src (begin));
379 } while (accept (TokenType.DOT));
380 return sym;
383 void skip_type () throws ParseError {
384 if (accept (TokenType.VOID)) {
385 while (accept (TokenType.STAR)) {
387 return;
389 accept (TokenType.DYNAMIC);
391 accept (TokenType.WEAK);
393 if (accept (TokenType.ARRAY) || accept (TokenType.LIST) || accept (TokenType.DICT)) {
394 accept (TokenType.OF);
397 skip_symbol_name ();
398 skip_type_argument_list ();
399 while (accept (TokenType.OPEN_BRACKET)) {
400 do {
401 if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
402 parse_expression ();
404 } while (accept (TokenType.COMMA));
405 expect (TokenType.CLOSE_BRACKET);
407 accept (TokenType.OP_NEG);
408 accept (TokenType.INTERR);
409 accept (TokenType.HASH);
412 DataType parse_type (bool owned_by_default = true) throws ParseError {
413 var begin = get_location ();
415 if (accept (TokenType.VOID)) {
416 DataType type = new VoidType ();
417 while (accept (TokenType.STAR)) {
418 type = new PointerType (type);
420 return type;
423 Gee.List<DataType> type_arg_list = null;
424 UnresolvedSymbol sym = null;
426 bool is_dynamic = accept (TokenType.DYNAMIC);
427 bool value_owned = owned_by_default;
428 if (owned_by_default) {
429 value_owned = !accept (TokenType.WEAK);
432 /* handle arrays */
433 bool is_array = false;
435 if (accept (TokenType.ARRAY)) {
436 expect (TokenType.OF);
437 is_array = true;
440 /* handle lists */
441 bool is_list = false;
443 if (accept (TokenType.LIST)) {
444 expect (TokenType.OF);
445 prev ();
446 is_list = true;
449 /* handle dicts */
450 bool is_dict = false;
452 if (accept (TokenType.DICT)) {
453 expect (TokenType.OF);
454 prev ();
455 is_dict = true;
458 if (is_list) {
459 var sym_parent = new UnresolvedSymbol (null, "Gee", get_src (begin));
460 sym = new UnresolvedSymbol (sym_parent, "ArrayList", get_src (begin));
461 } else if (is_dict) {
462 var sym_parent = new UnresolvedSymbol (null, "Gee", get_src (begin));
463 sym = new UnresolvedSymbol (sym_parent, "HashMap", get_src (begin));
464 } else {
465 sym = parse_symbol_name ();
468 type_arg_list = parse_type_argument_list (false);
470 DataType type = new UnresolvedType.from_symbol (sym, get_src (begin));
471 if (type_arg_list != null) {
472 foreach (DataType type_arg in type_arg_list) {
473 type.add_type_argument (type_arg);
477 while (accept (TokenType.STAR)) {
478 type = new PointerType (type, get_src (begin));
481 if (!(type is PointerType)) {
482 type.nullable = accept (TokenType.INTERR);
485 if (is_array) {
487 if (!accept (TokenType.OPEN_BRACKET)) {
488 type.value_owned = true;
489 type = new ArrayType (type, 1, get_src (begin));
490 type.nullable = accept (TokenType.INTERR);
492 } else {
493 prev ();
495 while (accept (TokenType.OPEN_BRACKET)) {
496 int array_rank = 0;
497 do {
498 array_rank++;
499 // support for stack-allocated arrays
500 // also required for decision between expression and declaration statement
501 if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
502 parse_expression ();
505 while (accept (TokenType.COMMA));
506 expect (TokenType.CLOSE_BRACKET);
508 type.value_owned = true;
509 type = new ArrayType (type, array_rank, get_src (begin));
510 type.nullable = accept (TokenType.INTERR);
515 if (!owned_by_default) {
516 value_owned = accept (TokenType.HASH);
519 type.is_dynamic = is_dynamic;
520 type.value_owned = value_owned;
521 return type;
524 Gee.List<Expression> parse_argument_list () throws ParseError {
525 var list = new ArrayList<Expression> ();
526 if (current () != TokenType.CLOSE_PARENS) {
527 do {
528 list.add (parse_expression ());
529 } while (accept (TokenType.COMMA));
531 return list;
534 Expression parse_primary_expression () throws ParseError {
535 var begin = get_location ();
537 Expression expr;
539 switch (current ()) {
540 case TokenType.TRUE:
541 case TokenType.FALSE:
542 case TokenType.INTEGER_LITERAL:
543 case TokenType.REAL_LITERAL:
544 case TokenType.CHARACTER_LITERAL:
545 case TokenType.STRING_LITERAL:
546 case TokenType.NULL:
547 expr = parse_literal ();
548 break;
549 case TokenType.ASSERT:
550 return parse_assert_expression ();
551 case TokenType.OPEN_PARENS:
552 expr = parse_tuple ();
553 break;
554 case TokenType.THIS:
555 expr = parse_this_access ();
556 break;
557 case TokenType.SUPER:
558 expr = parse_base_access ();
559 break;
560 case TokenType.NEW:
561 expr = parse_object_or_array_creation_expression ();
562 break;
563 case TokenType.PRINT:
564 return parse_print_expression ();
565 case TokenType.SIZEOF:
566 expr = parse_sizeof_expression ();
567 break;
568 case TokenType.TYPEOF:
569 expr = parse_typeof_expression ();
570 break;
571 default:
572 expr = parse_simple_name ();
573 break;
576 // process primary expressions that start with an inner primary expression
577 bool found = true;
578 while (found) {
579 switch (current ()) {
580 case TokenType.DOT:
581 expr = parse_member_access (begin, expr);
582 break;
583 case TokenType.OP_PTR:
584 expr = parse_pointer_member_access (begin, expr);
585 break;
586 case TokenType.OPEN_PARENS:
587 expr = parse_method_call (begin, expr);
588 break;
589 case TokenType.OPEN_BRACKET:
590 expr = parse_element_access (begin, expr);
591 break;
592 case TokenType.OP_INC:
593 expr = parse_post_increment_expression (begin, expr);
594 break;
595 case TokenType.OP_DEC:
596 expr = parse_post_decrement_expression (begin, expr);
597 break;
599 default:
600 found = false;
601 break;
605 return expr;
608 Expression parse_simple_name () throws ParseError {
609 var begin = get_location ();
610 string id = parse_identifier ();
611 Gee.List<DataType> type_arg_list = parse_type_argument_list (true);
612 var expr = new MemberAccess (null, id, get_src (begin));
613 if (type_arg_list != null) {
614 foreach (DataType type_arg in type_arg_list) {
615 expr.add_type_argument (type_arg);
618 return expr;
621 Expression parse_tuple () throws ParseError {
622 var begin = get_location ();
623 expect (TokenType.OPEN_PARENS);
624 var expr_list = new ArrayList<Expression> ();
625 if (current () != TokenType.CLOSE_PARENS) {
626 do {
627 expr_list.add (parse_expression ());
628 } while (accept (TokenType.COMMA));
630 expect (TokenType.CLOSE_PARENS);
631 if (expr_list.size != 1) {
632 var tuple = new Tuple ();
633 foreach (Expression expr in expr_list) {
634 tuple.add_expression (expr);
636 return tuple;
638 return new ParenthesizedExpression (expr_list.get (0), get_src (begin));
641 Expression parse_member_access (SourceLocation begin, Expression inner) throws ParseError {
642 expect (TokenType.DOT);
643 string id = parse_identifier ();
644 Gee.List<DataType> type_arg_list = parse_type_argument_list (true);
645 var expr = new MemberAccess (inner, id, get_src (begin));
646 if (type_arg_list != null) {
647 foreach (DataType type_arg in type_arg_list) {
648 expr.add_type_argument (type_arg);
651 return expr;
654 Expression parse_pointer_member_access (SourceLocation begin, Expression inner) throws ParseError {
655 expect (TokenType.OP_PTR);
656 string id = parse_identifier ();
657 Gee.List<DataType> type_arg_list = parse_type_argument_list (true);
658 var expr = new MemberAccess.pointer (inner, id, get_src (begin));
659 if (type_arg_list != null) {
660 foreach (DataType type_arg in type_arg_list) {
661 expr.add_type_argument (type_arg);
664 return expr;
668 Gee.List<Expression> parse_print_argument_list () throws ParseError {
669 var list = new ArrayList<Expression> ();
670 var i = 0;
671 var begin = get_location ();
673 if (current () != TokenType.CLOSE_PARENS) {
674 do {
675 var p_expr = parse_expression ();
676 if (i == 0) {
677 i++;
679 if (p_expr != null) {
680 string s = "\\n\"";
682 if (p_expr is StringLiteral) {
683 var s_exp = (StringLiteral) p_expr;
684 var len = s_exp.value.size ();
686 if (len > 2) {
687 var st = s_exp.value.ndup (len-1);
688 st += s;
689 s_exp.value = st;
691 } else {
692 var rhs = new StringLiteral (s, get_src (begin));
693 p_expr = new BinaryExpression (BinaryOperator.PLUS, p_expr, rhs, get_src (begin));
698 list.add (p_expr);
700 } while (accept (TokenType.COMMA));
702 return list;
705 Expression parse_print_expression () throws ParseError {
706 var begin = get_location ();
708 expect (TokenType.PRINT);
709 accept (TokenType.OPEN_PARENS);
711 var expr = new MemberAccess (null, "print", get_src (begin));
713 var arg_list = parse_print_argument_list ();
715 accept (TokenType.CLOSE_PARENS);
717 var print_expr = new MethodCall (expr, get_src (begin));
719 foreach (Expression arg in arg_list) {
720 print_expr.add_argument (arg);
723 return print_expr;
727 Expression parse_assert_expression () throws ParseError {
728 var begin = get_location ();
730 expect (TokenType.ASSERT);
731 accept (TokenType.OPEN_PARENS);
733 var expr = new MemberAccess (null, "assert", get_src (begin));
735 var arg_list = parse_argument_list ();
737 accept (TokenType.CLOSE_PARENS);
739 var assert_expr = new MethodCall (expr, get_src (begin));
741 foreach (Expression arg in arg_list) {
742 assert_expr.add_argument (arg);
745 return assert_expr;
749 Expression parse_method_call (SourceLocation begin, Expression inner) throws ParseError {
750 expect (TokenType.OPEN_PARENS);
751 var arg_list = parse_argument_list ();
752 expect (TokenType.CLOSE_PARENS);
753 var init_list = parse_object_initializer ();
755 if (init_list.size > 0 && inner is MemberAccess) {
756 // struct creation expression
757 var member = (MemberAccess) inner;
758 member.creation_member = true;
760 var expr = new ObjectCreationExpression (member, get_src (begin));
761 expr.struct_creation = true;
762 foreach (Expression arg in arg_list) {
763 expr.add_argument (arg);
765 foreach (MemberInitializer initializer in init_list) {
766 expr.add_member_initializer (initializer);
768 return expr;
769 } else {
770 var expr = new MethodCall (inner, get_src (begin));
771 foreach (Expression arg in arg_list) {
772 expr.add_argument (arg);
774 return expr;
778 Expression parse_element_access (SourceLocation begin, Expression inner) throws ParseError {
779 expect (TokenType.OPEN_BRACKET);
780 var index_list = parse_expression_list ();
781 expect (TokenType.CLOSE_BRACKET);
783 var expr = new ElementAccess (inner, get_src (begin));
784 foreach (Expression index in index_list) {
785 expr.append_index (index);
787 return expr;
790 Gee.List<Expression> parse_expression_list () throws ParseError {
791 var list = new ArrayList<Expression> ();
792 do {
793 list.add (parse_expression ());
794 } while (accept (TokenType.COMMA));
795 return list;
798 Expression parse_this_access () throws ParseError {
799 var begin = get_location ();
800 expect (TokenType.THIS);
801 return new MemberAccess (null, "this", get_src (begin));
804 Expression parse_base_access () throws ParseError {
805 var begin = get_location ();
806 expect (TokenType.SUPER);
807 return new BaseAccess (get_src (begin));
810 Expression parse_post_increment_expression (SourceLocation begin, Expression inner) throws ParseError {
811 expect (TokenType.OP_INC);
812 return new PostfixExpression (inner, true, get_src (begin));
815 Expression parse_post_decrement_expression (SourceLocation begin, Expression inner) throws ParseError {
816 expect (TokenType.OP_DEC);
817 return new PostfixExpression (inner, false, get_src (begin));
820 Expression parse_object_or_array_creation_expression () throws ParseError {
821 var begin = get_location ();
822 expect (TokenType.NEW);
824 if (accept (TokenType.ARRAY)) {
825 expect (TokenType.OF);
826 var m = parse_member_name ();
827 var expr = parse_array_creation_expression (begin, m);
828 return expr;
831 if (accept (TokenType.LIST)) {
832 expect (TokenType.OF);
833 var m = parse_member_name ();
834 var expr = parse_list_creation_expression (begin, m);
835 return expr;
838 if (accept (TokenType.DICT)) {
839 expect (TokenType.OF);
840 var m1 = parse_member_name ();
841 expect (TokenType.COMMA);
842 var m2 = parse_member_name ();
843 var expr = parse_dict_creation_expression (begin, m1, m2);
844 return expr;
848 var member = parse_member_name ();
849 var expr = parse_object_creation_expression (begin, member);
850 return expr;
854 Expression parse_object_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError {
855 member.creation_member = true;
856 Gee.List<Expression> arg_list;
857 if (accept (TokenType.OPEN_PARENS)) {
858 arg_list = parse_argument_list ();
859 expect (TokenType.CLOSE_PARENS);
860 } else {
861 arg_list = new ArrayList<Expression> ();
864 var init_list = parse_object_initializer ();
866 var expr = new ObjectCreationExpression (member, get_src (begin));
867 foreach (Expression arg in arg_list) {
868 expr.add_argument (arg);
870 foreach (MemberInitializer initializer in init_list) {
871 expr.add_member_initializer (initializer);
873 return expr;
876 Expression parse_array_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError {
877 bool size_specified = false;
878 Gee.List<Expression> size_specifier_list = null;
879 bool first = true;
880 DataType element_type = UnresolvedType.new_from_expression (member);
882 var has_bracket = accept (TokenType.OPEN_BRACKET);
884 do {
885 if (!first) {
886 // array of arrays: new T[][42]
887 element_type = new ArrayType (element_type, size_specifier_list.size, element_type.source_reference);
888 } else {
889 first = false;
892 size_specifier_list = new ArrayList<Expression> ();
893 do {
894 Expression size = null;
895 if (has_bracket && current () != TokenType.CLOSE_BRACKET && current () != TokenType.COMMA) {
896 size = parse_expression ();
897 size_specified = true;
899 size_specifier_list.add (size);
900 } while (accept (TokenType.COMMA));
902 if (has_bracket) {
903 expect (TokenType.CLOSE_BRACKET);
905 } while (accept (TokenType.OPEN_BRACKET));
907 InitializerList initializer = null;
908 if (accept (TokenType.ASSIGN)) {
910 initializer = parse_initializer ();
912 var expr = new ArrayCreationExpression (element_type, size_specifier_list.size, initializer, get_src (begin));
913 if (size_specified) {
914 foreach (Expression size in size_specifier_list) {
915 expr.append_size (size);
918 return expr;
922 Expression parse_list_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError {
924 DataType element_type = UnresolvedType.new_from_expression (member);
925 MemberAccess list_member = null, parent_member = null;
927 parent_member = new MemberAccess (null, "Gee", get_src (begin));
928 list_member = new MemberAccess (parent_member, "ArrayList", get_src (begin));
929 list_member.add_type_argument (element_type);
931 list_member.creation_member = true;
933 var expr = new ObjectCreationExpression (list_member, get_src (begin));
935 if (member.member_name == "string") {
936 parent_member = new MemberAccess (null, "GLib", get_src (begin));
937 expr.add_argument (new MemberAccess (parent_member, "str_equal", get_src (begin)));
939 } else if (member.member_name == "int") {
940 parent_member = new MemberAccess (null, "GLib", get_src (begin));
941 expr.add_argument (new MemberAccess (parent_member, "int_equal", get_src (begin)));
944 return expr;
947 Expression parse_dict_creation_expression (SourceLocation begin, MemberAccess member_key, MemberAccess member_value) throws ParseError {
949 DataType key_type = UnresolvedType.new_from_expression (member_key);
950 DataType value_type = UnresolvedType.new_from_expression (member_value);
952 MemberAccess dict_member = null, parent_member = null, dict_hash = null, dict_equal = null;
954 parent_member = new MemberAccess (null, "Gee", get_src (begin));
955 dict_member = new MemberAccess (parent_member, "HashMap", get_src (begin));
956 dict_member.add_type_argument (key_type);
957 dict_member.add_type_argument (value_type);
959 if (member_key.member_name == "string") {
960 parent_member = new MemberAccess (null, "GLib", get_src (begin));
961 dict_hash = new MemberAccess (parent_member, "str_hash", get_src (begin));
962 dict_equal = new MemberAccess (parent_member, "str_equal", get_src (begin));
964 } else if (member_key.member_name == "int") {
965 parent_member = new MemberAccess (null, "GLib", get_src (begin));
966 dict_hash = new MemberAccess (parent_member, "int_hash", get_src (begin));
967 dict_equal = new MemberAccess (parent_member, "int_equal", get_src (begin));
970 dict_member.creation_member = true;
972 var expr = new ObjectCreationExpression (dict_member, get_src (begin));
974 if (dict_hash != null && dict_equal != null) {
975 expr.add_argument (dict_hash);
976 expr.add_argument (dict_equal);
980 return expr;
984 Gee.List<MemberInitializer> parse_object_initializer () throws ParseError {
985 var list = new ArrayList<MemberInitializer> ();
986 if (accept (TokenType.OPEN_BRACE)) {
987 do {
988 list.add (parse_member_initializer ());
989 } while (accept (TokenType.COMMA));
990 expect (TokenType.CLOSE_BRACE);
992 return list;
995 MemberInitializer parse_member_initializer () throws ParseError {
996 var begin = get_location ();
997 string id = parse_identifier ();
998 expect (TokenType.ASSIGN);
999 var expr = parse_expression ();
1001 return new MemberInitializer (id, expr, get_src (begin));
1004 Expression parse_sizeof_expression () throws ParseError {
1005 var begin = get_location ();
1006 expect (TokenType.SIZEOF);
1007 expect (TokenType.OPEN_PARENS);
1008 var type = parse_type ();
1009 expect (TokenType.CLOSE_PARENS);
1011 return new SizeofExpression (type, get_src (begin));
1014 Expression parse_typeof_expression () throws ParseError {
1015 var begin = get_location ();
1016 expect (TokenType.TYPEOF);
1017 expect (TokenType.OPEN_PARENS);
1018 var type = parse_type ();
1019 expect (TokenType.CLOSE_PARENS);
1021 return new TypeofExpression (type, get_src (begin));
1024 UnaryOperator get_unary_operator (TokenType token_type) {
1025 switch (token_type) {
1026 case TokenType.PLUS: return UnaryOperator.PLUS;
1027 case TokenType.MINUS: return UnaryOperator.MINUS;
1028 case TokenType.OP_NEG: return UnaryOperator.LOGICAL_NEGATION;
1029 case TokenType.TILDE: return UnaryOperator.BITWISE_COMPLEMENT;
1030 case TokenType.OP_INC: return UnaryOperator.INCREMENT;
1031 case TokenType.OP_DEC: return UnaryOperator.DECREMENT;
1032 case TokenType.REF: return UnaryOperator.REF;
1033 case TokenType.OUT: return UnaryOperator.OUT;
1034 default: return UnaryOperator.NONE;
1038 Expression parse_unary_expression () throws ParseError {
1039 var begin = get_location ();
1040 var operator = get_unary_operator (current ());
1041 if (operator != UnaryOperator.NONE) {
1042 next ();
1043 var op = parse_unary_expression ();
1044 return new UnaryExpression (operator, op, get_src (begin));
1046 switch (current ()) {
1047 case TokenType.HASH:
1048 next ();
1049 var op = parse_unary_expression ();
1050 return new ReferenceTransferExpression (op, get_src (begin));
1051 case TokenType.OPEN_PARENS:
1052 next ();
1053 switch (current ()) {
1054 case TokenType.VOID:
1055 case TokenType.DYNAMIC:
1056 case TokenType.WEAK:
1057 case TokenType.IDENTIFIER:
1058 var type = parse_type ();
1059 if (accept (TokenType.CLOSE_PARENS)) {
1060 // check follower to decide whether to create cast expression
1061 switch (current ()) {
1062 case TokenType.OP_NEG:
1063 case TokenType.TILDE:
1064 case TokenType.OPEN_PARENS:
1065 case TokenType.TRUE:
1066 case TokenType.FALSE:
1067 case TokenType.INTEGER_LITERAL:
1068 case TokenType.REAL_LITERAL:
1069 case TokenType.CHARACTER_LITERAL:
1070 case TokenType.STRING_LITERAL:
1071 case TokenType.NULL:
1072 case TokenType.THIS:
1073 case TokenType.SUPER:
1074 case TokenType.NEW:
1075 case TokenType.SIZEOF:
1076 case TokenType.TYPEOF:
1077 case TokenType.IDENTIFIER:
1078 if (!(type is PointerType) && !type.value_owned) {
1079 Report.warning (get_src (begin), "obsolete syntax, weak type modifier unused in cast expressions");
1081 var inner = parse_unary_expression ();
1082 return new CastExpression (inner, type, get_src (begin), false);
1083 default:
1084 break;
1087 break;
1088 default:
1089 break;
1091 // no cast expression
1092 rollback (begin);
1093 break;
1094 case TokenType.STAR:
1095 next ();
1096 var op = parse_unary_expression ();
1097 return new PointerIndirection (op, get_src (begin));
1098 case TokenType.BITWISE_AND:
1099 next ();
1100 var op = parse_unary_expression ();
1101 return new AddressofExpression (op, get_src (begin));
1102 default:
1103 break;
1106 var expr = parse_primary_expression ();
1107 return expr;
1110 BinaryOperator get_binary_operator (TokenType token_type) {
1111 switch (token_type) {
1112 case TokenType.STAR: return BinaryOperator.MUL;
1113 case TokenType.DIV: return BinaryOperator.DIV;
1114 case TokenType.PERCENT: return BinaryOperator.MOD;
1115 case TokenType.PLUS: return BinaryOperator.PLUS;
1116 case TokenType.MINUS: return BinaryOperator.MINUS;
1117 case TokenType.OP_LT: return BinaryOperator.LESS_THAN;
1118 case TokenType.OP_GT: return BinaryOperator.GREATER_THAN;
1119 case TokenType.OP_LE: return BinaryOperator.LESS_THAN_OR_EQUAL;
1120 case TokenType.OP_GE: return BinaryOperator.GREATER_THAN_OR_EQUAL;
1121 case TokenType.OP_EQ: return BinaryOperator.EQUALITY;
1122 case TokenType.IS:
1123 next();
1124 if (current () == TokenType.OP_NEG) {
1125 prev ();
1126 return BinaryOperator.INEQUALITY;
1128 prev ();
1129 return BinaryOperator.EQUALITY;
1130 case TokenType.OP_NE: return BinaryOperator.INEQUALITY;
1131 default: return BinaryOperator.NONE;
1135 Expression parse_multiplicative_expression () throws ParseError {
1136 var begin = get_location ();
1137 var left = parse_unary_expression ();
1138 bool found = true;
1139 while (found) {
1140 var operator = get_binary_operator (current ());
1141 switch (operator) {
1142 case BinaryOperator.MUL:
1143 case BinaryOperator.DIV:
1144 case BinaryOperator.MOD:
1145 next ();
1146 var right = parse_unary_expression ();
1147 left = new BinaryExpression (operator, left, right, get_src (begin));
1148 break;
1149 default:
1150 found = false;
1151 break;
1154 return left;
1157 Expression parse_additive_expression () throws ParseError {
1158 var begin = get_location ();
1159 var left = parse_multiplicative_expression ();
1160 bool found = true;
1161 while (found) {
1162 var operator = get_binary_operator (current ());
1163 switch (operator) {
1164 case BinaryOperator.PLUS:
1165 case BinaryOperator.MINUS:
1166 next ();
1167 var right = parse_multiplicative_expression ();
1168 left = new BinaryExpression (operator, left, right, get_src (begin));
1169 break;
1170 default:
1171 found = false;
1172 break;
1175 return left;
1178 Expression parse_shift_expression () throws ParseError {
1179 var begin = get_location ();
1180 var left = parse_additive_expression ();
1181 bool found = true;
1182 while (found) {
1183 switch (current ()) {
1184 case TokenType.OP_SHIFT_LEFT:
1185 next ();
1186 var right = parse_additive_expression ();
1187 left = new BinaryExpression (BinaryOperator.SHIFT_LEFT, left, right, get_src (begin));
1188 break;
1189 // don't use OP_SHIFT_RIGHT to support >> for nested generics
1190 case TokenType.OP_GT:
1191 char* first_gt_pos = tokens[index].begin.pos;
1192 next ();
1193 // only accept >> when there is no space between the two > signs
1194 if (current () == TokenType.OP_GT && tokens[index].begin.pos == first_gt_pos + 1) {
1195 next ();
1196 var right = parse_additive_expression ();
1197 left = new BinaryExpression (BinaryOperator.SHIFT_RIGHT, left, right, get_src (begin));
1198 } else {
1199 prev ();
1200 found = false;
1202 break;
1203 default:
1204 found = false;
1205 break;
1208 return left;
1211 Expression parse_relational_expression () throws ParseError {
1212 var begin = get_location ();
1213 var left = parse_shift_expression ();
1214 bool found = true;
1215 while (found) {
1216 var operator = get_binary_operator (current ());
1217 switch (operator) {
1218 case BinaryOperator.LESS_THAN:
1219 case BinaryOperator.LESS_THAN_OR_EQUAL:
1220 case BinaryOperator.GREATER_THAN_OR_EQUAL:
1221 next ();
1222 var right = parse_shift_expression ();
1223 left = new BinaryExpression (operator, left, right, get_src (begin));
1224 break;
1225 case BinaryOperator.GREATER_THAN:
1226 next ();
1227 // ignore >> and >>= (two tokens due to generics)
1228 if (current () != TokenType.OP_GT && current () != TokenType.OP_GE) {
1229 var right = parse_shift_expression ();
1230 left = new BinaryExpression (operator, left, right, get_src (begin));
1231 } else {
1232 prev ();
1233 found = false;
1235 break;
1236 default:
1237 switch (current ()) {
1238 case TokenType.ISA:
1239 next ();
1240 var type = parse_type ();
1241 left = new TypeCheck (left, type, get_src (begin));
1242 break;
1243 case TokenType.AS:
1244 next ();
1245 var type = parse_type ();
1246 left = new CastExpression (left, type, get_src (begin), true);
1247 break;
1248 default:
1249 found = false;
1250 break;
1252 break;
1255 return left;
1258 Expression parse_equality_expression () throws ParseError {
1259 var begin = get_location ();
1260 var left = parse_relational_expression ();
1261 bool found = true;
1262 while (found) {
1263 var operator = get_binary_operator (current ());
1264 switch (operator) {
1265 case BinaryOperator.INEQUALITY:
1266 case BinaryOperator.EQUALITY:
1267 if ((operator == BinaryOperator.INEQUALITY) && (current () == TokenType.IS)) {
1268 next ();
1270 next ();
1271 var right = parse_relational_expression ();
1272 left = new BinaryExpression (operator, left, right, get_src (begin));
1273 break;
1274 default:
1275 found = false;
1276 break;
1279 return left;
1282 Expression parse_and_expression () throws ParseError {
1283 var begin = get_location ();
1284 var left = parse_equality_expression ();
1285 while (accept (TokenType.BITWISE_AND)) {
1286 var right = parse_equality_expression ();
1287 left = new BinaryExpression (BinaryOperator.BITWISE_AND, left, right, get_src (begin));
1289 return left;
1292 Expression parse_exclusive_or_expression () throws ParseError {
1293 var begin = get_location ();
1294 var left = parse_and_expression ();
1295 while (accept (TokenType.CARRET)) {
1296 var right = parse_and_expression ();
1297 left = new BinaryExpression (BinaryOperator.BITWISE_XOR, left, right, get_src (begin));
1299 return left;
1302 Expression parse_inclusive_or_expression () throws ParseError {
1303 var begin = get_location ();
1304 var left = parse_exclusive_or_expression ();
1305 while (accept (TokenType.BITWISE_OR)) {
1306 var right = parse_exclusive_or_expression ();
1307 left = new BinaryExpression (BinaryOperator.BITWISE_OR, left, right, get_src (begin));
1309 return left;
1312 Expression parse_in_expression () throws ParseError {
1313 var begin = get_location ();
1314 var left = parse_inclusive_or_expression ();
1315 while (accept (TokenType.IN)) {
1316 var right = parse_inclusive_or_expression ();
1317 left = new BinaryExpression (BinaryOperator.IN, left, right, get_src (begin));
1319 return left;
1322 Expression parse_conditional_and_expression () throws ParseError {
1323 var begin = get_location ();
1324 var left = parse_in_expression ();
1325 while (accept (TokenType.OP_AND)) {
1326 var right = parse_in_expression ();
1327 left = new BinaryExpression (BinaryOperator.AND, left, right, get_src (begin));
1329 return left;
1332 Expression parse_conditional_or_expression () throws ParseError {
1333 var begin = get_location ();
1334 var left = parse_conditional_and_expression ();
1335 while (accept (TokenType.OP_OR)) {
1336 var right = parse_conditional_and_expression ();
1337 left = new BinaryExpression (BinaryOperator.OR, left, right, get_src (begin));
1339 return left;
1342 Expression parse_conditional_expression () throws ParseError {
1343 var begin = get_location ();
1344 var condition = parse_conditional_or_expression ();
1345 if (accept (TokenType.INTERR)) {
1346 var true_expr = parse_expression ();
1347 expect (TokenType.COLON);
1348 var false_expr = parse_expression ();
1349 return new ConditionalExpression (condition, true_expr, false_expr, get_src (begin));
1350 } else {
1351 return condition;
1355 Expression parse_lambda_expression () throws ParseError {
1356 var begin = get_location ();
1357 Gee.List<string> params = new ArrayList<string> ();
1359 expect (TokenType.DEF);
1361 if (accept (TokenType.OPEN_PARENS)) {
1362 if (current () != TokenType.CLOSE_PARENS) {
1363 do {
1364 params.add (parse_identifier ());
1365 } while (accept (TokenType.COMMA));
1367 expect (TokenType.CLOSE_PARENS);
1368 } else {
1369 params.add (parse_identifier ());
1373 LambdaExpression lambda;
1374 if (accept_block ()) {
1375 var block = parse_block ();
1376 lambda = new LambdaExpression.with_statement_body (block, get_src (begin));
1377 } else {
1378 var expr = parse_expression ();
1379 lambda = new LambdaExpression (expr, get_src (begin));
1380 expect_terminator ();
1385 foreach (string param in params) {
1386 lambda.add_parameter (param);
1388 return lambda;
1391 AssignmentOperator get_assignment_operator (TokenType token_type) {
1392 switch (token_type) {
1393 case TokenType.ASSIGN: return AssignmentOperator.SIMPLE;
1394 case TokenType.ASSIGN_ADD: return AssignmentOperator.ADD;
1395 case TokenType.ASSIGN_SUB: return AssignmentOperator.SUB;
1396 case TokenType.ASSIGN_BITWISE_OR: return AssignmentOperator.BITWISE_OR;
1397 case TokenType.ASSIGN_BITWISE_AND: return AssignmentOperator.BITWISE_AND;
1398 case TokenType.ASSIGN_BITWISE_XOR: return AssignmentOperator.BITWISE_XOR;
1399 case TokenType.ASSIGN_DIV: return AssignmentOperator.DIV;
1400 case TokenType.ASSIGN_MUL: return AssignmentOperator.MUL;
1401 case TokenType.ASSIGN_PERCENT: return AssignmentOperator.PERCENT;
1402 case TokenType.ASSIGN_SHIFT_LEFT: return AssignmentOperator.SHIFT_LEFT;
1403 default: return AssignmentOperator.NONE;
1407 Expression parse_expression () throws ParseError {
1408 if (current () == TokenType.DEF) {
1409 var lambda = parse_lambda_expression ();
1410 current_expr_is_lambda = true;
1411 return lambda;
1414 var begin = get_location ();
1415 Expression expr = parse_conditional_expression ();
1417 while (true) {
1418 var operator = get_assignment_operator (current ());
1419 if (operator != AssignmentOperator.NONE) {
1420 next ();
1421 var rhs = parse_expression ();
1422 expr = new Assignment (expr, rhs, operator, get_src (begin));
1423 } else if (current () == TokenType.OP_GT) { // >>=
1424 char* first_gt_pos = tokens[index].begin.pos;
1425 next ();
1426 // only accept >>= when there is no space between the two > signs
1427 if (current () == TokenType.OP_GE && tokens[index].begin.pos == first_gt_pos + 1) {
1428 next ();
1429 var rhs = parse_expression ();
1430 expr = new Assignment (expr, rhs, AssignmentOperator.SHIFT_RIGHT, get_src (begin));
1431 } else {
1432 prev ();
1433 break;
1435 } else {
1436 break;
1440 return expr;
1444 Statement get_for_statement_type () throws ParseError {
1446 var begin = get_location ();
1447 bool is_foreach = false;
1449 while (current () != TokenType.EOL && current () != TokenType.DO) {
1450 next ();
1451 if (accept (TokenType.IN)) {
1452 is_foreach = true;
1453 break;
1457 rollback (begin);
1459 if (is_foreach) {
1460 return parse_foreach_statement ();
1461 } else {
1462 return parse_for_statement ();
1467 void parse_statements (Block block) throws ParseError {
1468 while (current () != TokenType.DEDENT
1469 && current () != TokenType.WHEN
1470 && current () != TokenType.DEFAULT) {
1471 try {
1472 Statement stmt = null;
1473 bool is_decl = false;
1474 comment = scanner.pop_comment ();
1475 switch (current ()) {
1477 /* skip over requires and ensures as we handled them in method declaration */
1478 case TokenType.REQUIRES:
1479 case TokenType.ENSURES:
1480 var begin = get_location ();
1481 next ();
1483 if (accept (TokenType.EOL) && accept (TokenType.INDENT)) {
1484 while (current () != TokenType.DEDENT) {
1485 next();
1488 expect (TokenType.DEDENT);
1489 } else {
1490 while (current () != TokenType.EOL) {
1491 next();
1494 expect (TokenType.EOL);
1497 stmt = new EmptyStatement (get_src_com (begin));
1498 break;
1501 case TokenType.INDENT:
1502 stmt = parse_block ();
1503 break;
1504 case TokenType.SEMICOLON:
1505 case TokenType.PASS:
1506 stmt = parse_empty_statement ();
1507 break;
1508 case TokenType.PRINT:
1509 case TokenType.ASSERT:
1510 stmt = parse_expression_statement ();
1511 break;
1512 case TokenType.IF:
1513 stmt = parse_if_statement ();
1514 break;
1515 case TokenType.CASE:
1516 stmt = parse_switch_statement ();
1517 break;
1518 case TokenType.WHILE:
1519 stmt = parse_while_statement ();
1520 break;
1521 case TokenType.DO:
1522 stmt = parse_do_statement ();
1523 break;
1524 case TokenType.FOR:
1525 stmt = get_for_statement_type ();
1526 break;
1527 case TokenType.BREAK:
1528 stmt = parse_break_statement ();
1529 break;
1530 case TokenType.CONTINUE:
1531 stmt = parse_continue_statement ();
1532 break;
1533 case TokenType.RETURN:
1534 stmt = parse_return_statement ();
1535 break;
1536 case TokenType.RAISE:
1537 stmt = parse_throw_statement ();
1538 break;
1539 case TokenType.TRY:
1540 stmt = parse_try_statement ();
1541 break;
1542 case TokenType.LOCK:
1543 stmt = parse_lock_statement ();
1544 break;
1545 case TokenType.DELETE:
1546 stmt = parse_delete_statement ();
1547 break;
1548 case TokenType.VAR:
1549 is_decl = true;
1550 parse_local_variable_declarations (block);
1551 break;
1554 case TokenType.OP_INC:
1555 case TokenType.OP_DEC:
1556 case TokenType.SUPER:
1557 case TokenType.THIS:
1558 case TokenType.OPEN_PARENS:
1559 case TokenType.STAR:
1560 case TokenType.NEW:
1561 stmt = parse_expression_statement ();
1562 break;
1563 default:
1564 bool is_expr = is_expression ();
1565 if (is_expr) {
1566 stmt = parse_expression_statement ();
1567 } else {
1568 is_decl = true;
1569 parse_local_variable_declarations (block);
1571 break;
1574 if (!is_decl) {
1575 block.add_statement (stmt);
1577 } catch (ParseError e) {
1578 if (recover () != RecoveryState.STATEMENT_BEGIN) {
1579 // beginning of next declaration or end of file reached
1580 // return what we have so far
1581 break;
1587 bool is_expression () throws ParseError {
1588 var begin = get_location ();
1590 // decide between declaration and expression statement
1591 skip_type ();
1592 switch (current ()) {
1593 // invocation expression
1594 case TokenType.OPEN_PARENS:
1595 // postfix increment
1596 case TokenType.OP_INC:
1597 // postfix decrement
1598 case TokenType.OP_DEC:
1599 // assignments
1600 case TokenType.ASSIGN:
1601 case TokenType.ASSIGN_ADD:
1602 case TokenType.ASSIGN_BITWISE_AND:
1603 case TokenType.ASSIGN_BITWISE_OR:
1604 case TokenType.ASSIGN_BITWISE_XOR:
1605 case TokenType.ASSIGN_DIV:
1606 case TokenType.ASSIGN_MUL:
1607 case TokenType.ASSIGN_PERCENT:
1608 case TokenType.ASSIGN_SHIFT_LEFT:
1609 case TokenType.ASSIGN_SUB:
1610 case TokenType.OP_GT: // >>=
1611 // member access
1612 case TokenType.DOT:
1613 // pointer member access
1614 case TokenType.OP_PTR:
1615 rollback (begin);
1616 return true;
1617 default:
1618 rollback (begin);
1619 return false;
1623 Block parse_embedded_statement () throws ParseError {
1624 if (current () == TokenType.INDENT) {
1625 var block = parse_block ();
1626 return block;
1629 comment = scanner.pop_comment ();
1631 var block = new Block (get_src_com (get_location ()));
1632 block.add_statement (parse_embedded_statement_without_block ());
1633 return block;
1637 Statement parse_embedded_statement_without_block () throws ParseError {
1638 switch (current ()) {
1639 case TokenType.PASS:
1640 case TokenType.SEMICOLON: return parse_empty_statement ();
1641 case TokenType.IF: return parse_if_statement ();
1642 case TokenType.CASE: return parse_switch_statement ();
1643 case TokenType.WHILE: return parse_while_statement ();
1644 case TokenType.DO: return parse_do_statement ();
1645 case TokenType.FOR: return get_for_statement_type ();
1646 case TokenType.BREAK: return parse_break_statement ();
1647 case TokenType.CONTINUE: return parse_continue_statement ();
1648 case TokenType.RETURN: return parse_return_statement ();
1649 case TokenType.RAISE: return parse_throw_statement ();
1650 case TokenType.TRY: return parse_try_statement ();
1651 case TokenType.LOCK: return parse_lock_statement ();
1652 case TokenType.DELETE: return parse_delete_statement ();
1653 default: return parse_expression_statement ();
1657 Block parse_block () throws ParseError {
1658 var begin = get_location ();
1659 expect (TokenType.INDENT);
1660 var block = new Block (get_src_com (begin));
1661 parse_statements (block);
1662 if (!accept (TokenType.DEDENT)) {
1663 // only report error if it's not a secondary error
1664 if (Report.get_errors () == 0) {
1665 Report.error (get_current_src (), "tab indentation is incorrect");
1669 return block;
1672 Statement parse_empty_statement () throws ParseError {
1673 var begin = get_location ();
1675 accept (TokenType.PASS);
1676 accept (TokenType.SEMICOLON);
1677 expect_terminator ();
1679 return new EmptyStatement (get_src_com (begin));
1682 void add_local_var_variable (Block block, string id) throws ParseError {
1683 DataType type_copy = null;
1684 var local = parse_local_variable (type_copy, id);
1685 block.add_statement (new DeclarationStatement (local, local.source_reference));
1688 void parse_local_variable_declarations (Block block) throws ParseError {
1689 if (accept (TokenType.VAR)) {
1690 /* support block vars */
1691 if (accept (TokenType.EOL) && accept (TokenType.INDENT)) {
1692 while (current () != TokenType.DEDENT) {
1693 var s = parse_identifier ();
1694 add_local_var_variable (block, s);
1695 accept (TokenType.EOL);
1696 accept (TokenType.SEMICOLON);
1699 expect (TokenType.DEDENT);
1700 } else {
1701 var s = parse_identifier ();
1702 add_local_var_variable (block, s);
1703 expect_terminator ();
1706 return;
1709 var id_list = new ArrayList<string> ();
1710 DataType variable_type = null;
1712 do {
1713 id_list.add (parse_identifier ());
1714 } while (accept (TokenType.COMMA));
1716 expect (TokenType.COLON);
1718 variable_type = parse_type ();
1720 foreach (string id in id_list) {
1721 DataType type_copy = null;
1722 if (variable_type != null) {
1723 type_copy = variable_type.copy ();
1725 var local = parse_local_variable (type_copy, id);
1726 block.add_statement (new DeclarationStatement (local, local.source_reference));
1729 expect_terminator ();
1732 LocalVariable parse_local_variable (DataType? variable_type, string id) throws ParseError {
1733 var begin = get_location ();
1734 Expression initializer = null;
1735 if (accept (TokenType.ASSIGN)) {
1736 initializer = parse_variable_initializer ();
1737 var array_type = variable_type as ArrayType;
1738 if (array_type != null && initializer is InitializerList) {
1739 initializer = new ArrayCreationExpression (array_type.element_type.copy (), array_type.rank, (InitializerList) initializer, initializer.source_reference);
1742 return new LocalVariable (variable_type, id, initializer, get_src_com (begin));
1745 Statement parse_expression_statement () throws ParseError {
1746 var begin = get_location ();
1747 var expr = parse_statement_expression ();
1749 if (current_expr_is_lambda) {
1750 current_expr_is_lambda = false;
1751 } else {
1752 expect_terminator ();
1755 return new ExpressionStatement (expr, get_src_com (begin));
1758 Expression parse_statement_expression () throws ParseError {
1759 // invocation expression, assignment,
1760 // or pre/post increment/decrement expression
1761 var expr = parse_expression ();
1762 return expr;
1765 Statement parse_if_statement () throws ParseError {
1766 var begin = get_location ();
1768 expect (TokenType.IF);
1770 var condition = parse_expression ();
1772 if (!accept (TokenType.DO)) {
1773 expect (TokenType.EOL);
1774 } else {
1775 accept (TokenType.EOL);
1778 var src = get_src_com (begin);
1779 var true_stmt = parse_embedded_statement ();
1780 Block false_stmt = null;
1781 if (accept (TokenType.ELSE)) {
1782 false_stmt = parse_embedded_statement ();
1784 return new IfStatement (condition, true_stmt, false_stmt, src);
1787 Statement parse_switch_statement () throws ParseError {
1788 var begin = get_location ();
1789 expect (TokenType.CASE);
1790 var condition = parse_expression ();
1792 expect (TokenType.EOL);
1794 var stmt = new SwitchStatement (condition, get_src_com (begin));
1795 expect (TokenType.INDENT);
1796 while (current () != TokenType.DEDENT) {
1797 var section = new SwitchSection (get_src_com (begin));
1799 if (accept (TokenType.WHEN)) {
1800 do {
1801 section.add_label (new SwitchLabel (parse_expression (), get_src_com (begin)));
1803 while (accept (TokenType.COMMA));
1804 } else {
1805 expect (TokenType.DEFAULT);
1806 section.add_label (new SwitchLabel.with_default (get_src_com (begin)));
1809 if (!accept (TokenType.EOL)) {
1810 expect (TokenType.DO);
1813 parse_statements (section);
1815 /* add break statement for each block */
1816 var break_stmt = new BreakStatement (get_src_com (begin));
1817 section.add_statement (break_stmt);
1819 stmt.add_section (section);
1821 expect (TokenType.DEDENT);
1822 return stmt;
1825 Statement parse_while_statement () throws ParseError {
1826 var begin = get_location ();
1827 expect (TokenType.WHILE);
1828 var condition = parse_expression ();
1830 if (!accept (TokenType.DO)) {
1831 expect (TokenType.EOL);
1832 } else {
1833 accept (TokenType.EOL);
1836 var body = parse_embedded_statement ();
1837 return new WhileStatement (condition, body, get_src_com (begin));
1840 Statement parse_do_statement () throws ParseError {
1841 var begin = get_location ();
1842 expect (TokenType.DO);
1843 expect (TokenType.EOL);
1844 var body = parse_embedded_statement ();
1845 expect (TokenType.WHILE);
1847 var condition = parse_expression ();
1849 expect_terminator ();
1851 return new DoStatement (body, condition, get_src_com (begin));
1855 Statement parse_for_statement () throws ParseError {
1856 var begin = get_location ();
1857 Block block = null;
1858 Expression initializer = null;
1859 Expression condition = null;
1860 Expression iterator = null;
1861 bool is_expr;
1862 string id;
1864 expect (TokenType.FOR);
1866 switch (current ()) {
1867 case TokenType.VAR:
1868 is_expr = false;
1869 break;
1870 default:
1872 bool local_is_expr = is_expression ();
1873 is_expr = local_is_expr;
1874 break;
1877 if (is_expr) {
1878 var expr_begin = get_location ();
1879 id = parse_identifier ();
1880 rollback (expr_begin);
1881 initializer = parse_statement_expression ();
1882 } else {
1883 block = new Block (get_src (begin));
1884 DataType variable_type;
1885 if (accept (TokenType.VAR)) {
1886 variable_type = null;
1887 id = parse_identifier ();
1888 } else {
1889 id = parse_identifier ();
1890 expect (TokenType.COLON);
1891 variable_type = parse_type ();
1894 DataType type_copy = null;
1895 if (variable_type != null) {
1896 type_copy = variable_type.copy ();
1898 var local = parse_local_variable (type_copy, id);
1900 block.add_statement (new DeclarationStatement (local, local.source_reference));
1905 if (accept (TokenType.TO)) {
1906 /* create expression for condition and incrementing iterator */
1907 var to_begin = get_location ();
1908 var to_src = get_src (to_begin);
1909 var left = new MemberAccess (null, id, to_src);
1910 var right = parse_primary_expression ();
1912 condition = new BinaryExpression (BinaryOperator.LESS_THAN_OR_EQUAL, left, right, to_src);
1914 iterator = new PostfixExpression (left, true, to_src);
1915 } else {
1916 expect (TokenType.DOWNTO);
1917 var downto_begin = get_location ();
1918 var downto_src = get_src (downto_begin);
1919 /* create expression for condition and decrementing iterator */
1920 var left = new MemberAccess (null, id, downto_src);
1921 var right = parse_primary_expression ();
1923 condition = new BinaryExpression (BinaryOperator.GREATER_THAN_OR_EQUAL, left, right, downto_src);
1925 iterator = new PostfixExpression (left, false, downto_src);
1928 if (!accept (TokenType.EOL)) {
1929 expect (TokenType.DO);
1932 var src = get_src_com (begin);
1933 var body = parse_embedded_statement ();
1934 var stmt = new ForStatement (condition, body, src);
1936 if (initializer != null) stmt.add_initializer (initializer);
1938 stmt.add_iterator (iterator);
1941 if (block != null) {
1942 block.add_statement (stmt);
1943 return block;
1944 } else {
1945 return stmt;
1949 Statement parse_foreach_statement () throws ParseError {
1950 var begin = get_location ();
1951 DataType type = null;
1952 string id = null;
1954 expect (TokenType.FOR);
1956 if (accept (TokenType.VAR)) {
1957 id = parse_identifier ();
1958 } else {
1959 id = parse_identifier ();
1960 if (accept (TokenType.COLON)) {
1961 type = parse_type ();
1965 expect (TokenType.IN);
1966 var collection = parse_expression ();
1967 if (!accept (TokenType.EOL)) {
1968 expect (TokenType.DO);
1970 var src = get_src_com (begin);
1971 var body = parse_embedded_statement ();
1972 return new ForeachStatement (type, id, collection, body, src);
1975 Statement parse_break_statement () throws ParseError {
1976 var begin = get_location ();
1977 expect (TokenType.BREAK);
1978 expect_terminator ();
1979 return new BreakStatement (get_src_com (begin));
1982 Statement parse_continue_statement () throws ParseError {
1983 var begin = get_location ();
1984 expect (TokenType.CONTINUE);
1985 expect_terminator ();
1986 return new ContinueStatement (get_src_com (begin));
1989 Statement parse_return_statement () throws ParseError {
1990 var begin = get_location ();
1991 expect (TokenType.RETURN);
1992 Expression expr = null;
1993 if (current () != TokenType.SEMICOLON && current () != TokenType.EOL) {
1994 expr = parse_expression ();
1996 expect_terminator ();
1997 return new ReturnStatement (expr, get_src_com (begin));
2000 Statement parse_throw_statement () throws ParseError {
2001 var begin = get_location ();
2002 expect (TokenType.RAISE);
2003 var expr = parse_expression ();
2004 expect_terminator ();
2005 return new ThrowStatement (expr, get_src_com (begin));
2008 Statement parse_try_statement () throws ParseError {
2009 var begin = get_location ();
2010 expect (TokenType.TRY);
2011 expect (TokenType.EOL);
2012 var try_block = parse_block ();
2013 Block finally_clause = null;
2014 var catch_clauses = new ArrayList<CatchClause> ();
2015 if (current () == TokenType.EXCEPT) {
2016 parse_catch_clauses (catch_clauses);
2017 if (current () == TokenType.FINALLY) {
2018 finally_clause = parse_finally_clause ();
2020 } else {
2021 finally_clause = parse_finally_clause ();
2023 var stmt = new TryStatement (try_block, finally_clause, get_src_com (begin));
2024 foreach (CatchClause clause in catch_clauses) {
2025 stmt.add_catch_clause (clause);
2027 return stmt;
2030 void parse_catch_clauses (Gee.List<CatchClause> catch_clauses) throws ParseError {
2031 while (accept (TokenType.EXCEPT)) {
2032 var begin = get_location ();
2033 DataType type = null;
2034 string id = null;
2035 if (!accept (TokenType.EOL)) {
2036 id = parse_identifier ();
2037 expect (TokenType.COLON);
2038 type = parse_type ();
2039 expect (TokenType.EOL);
2042 var block = parse_block ();
2043 catch_clauses.add (new CatchClause (type, id, block, get_src (begin)));
2047 Block parse_finally_clause () throws ParseError {
2048 expect (TokenType.FINALLY);
2049 accept_block ();
2050 var block = parse_block ();
2051 return block;
2054 Statement parse_lock_statement () throws ParseError {
2055 var begin = get_location ();
2056 expect (TokenType.LOCK);
2057 expect (TokenType.OPEN_PARENS);
2058 var expr = parse_expression ();
2059 expect (TokenType.CLOSE_PARENS);
2060 var stmt = parse_embedded_statement ();
2061 return new LockStatement (expr, stmt, get_src_com (begin));
2064 Statement parse_delete_statement () throws ParseError {
2065 var begin = get_location ();
2066 expect (TokenType.DELETE);
2067 var expr = parse_expression ();
2068 expect_terminator ();
2069 return new DeleteStatement (expr, get_src_com (begin));
2072 Gee.List<Attribute>? parse_attributes () throws ParseError {
2073 if (current () != TokenType.OPEN_BRACKET) {
2074 return null;
2076 var attrs = new ArrayList<Attribute> ();
2077 while (accept (TokenType.OPEN_BRACKET)) {
2078 do {
2079 var begin = get_location ();
2080 string id = parse_identifier ();
2081 var attr = new Attribute (id, get_src (begin));
2082 if (accept (TokenType.OPEN_PARENS)) {
2083 if (current () != TokenType.CLOSE_PARENS) {
2084 do {
2085 id = parse_identifier ();
2086 expect (TokenType.ASSIGN);
2087 var expr = parse_expression ();
2088 attr.add_argument (id, expr);
2089 } while (accept (TokenType.COMMA));
2091 expect (TokenType.CLOSE_PARENS);
2093 attrs.add (attr);
2094 } while (accept (TokenType.COMMA));
2095 expect (TokenType.CLOSE_BRACKET);
2097 expect (TokenType.EOL);
2099 return attrs;
2102 void set_attributes (CodeNode node, Gee.List<Attribute>? attributes) {
2103 if (attributes != null) {
2104 foreach (Attribute attr in (Gee.List<Attribute>) attributes) {
2105 node.attributes.append (attr);
2110 Symbol parse_declaration (bool is_root = false) throws ParseError {
2111 comment = scanner.pop_comment ();
2112 var attrs = parse_attributes ();
2114 switch (current ()) {
2115 case TokenType.CONST:
2116 return parse_constant_declaration (attrs);
2117 case TokenType.CONSTRUCT:
2118 return parse_creation_method_declaration (attrs);
2119 case TokenType.CLASS:
2120 return parse_class_declaration (attrs);
2121 case TokenType.INIT:
2122 if (is_root) {
2123 return parse_main_method_declaration (attrs);
2125 return parse_constructor_declaration (attrs);
2126 case TokenType.DELEGATE:
2127 return parse_delegate_declaration (attrs);
2128 case TokenType.DEF:
2129 return parse_method_declaration (attrs);
2130 case TokenType.ENUM:
2131 return parse_enum_declaration (attrs);
2132 case TokenType.ERRORDOMAIN:
2133 return parse_errordomain_declaration (attrs);
2134 case TokenType.FINAL:
2135 return parse_destructor_declaration (attrs);
2136 case TokenType.INTERFACE:
2137 return parse_interface_declaration (attrs);
2138 case TokenType.NAMESPACE:
2139 return parse_namespace_declaration (attrs);
2140 case TokenType.PROP:
2141 return parse_property_declaration (attrs);
2142 case TokenType.EVENT:
2143 return parse_signal_declaration (attrs);
2144 case TokenType.STRUCT:
2145 return parse_struct_declaration (attrs);
2146 default:
2147 var begin = get_location ();
2148 while (current () != TokenType.EOL && current () != TokenType.SEMICOLON && current () != TokenType.EOF) {
2149 if (current () == TokenType.COLON) {
2150 rollback (begin);
2151 return parse_field_declaration (attrs);
2152 } else {
2153 next ();
2156 rollback (begin);
2158 break;
2161 TokenType cur = current ();
2162 TokenType pre = tokens[index-1].type;
2164 throw new ParseError.SYNTAX (get_error ("expected declaration but got %s with previous %s".printf (cur.to_string (), pre.to_string())));
2167 void parse_declarations (Symbol parent, bool root = false) throws ParseError {
2168 if (!root) {
2169 expect (TokenType.INDENT);
2171 while (current () != TokenType.DEDENT && current () != TokenType.EOF) {
2172 try {
2173 if (parent is Namespace) {
2174 parse_namespace_member ((Namespace) parent);
2175 } else if (parent is Class) {
2176 parse_class_member ((Class) parent);
2177 } else if (parent is Struct) {
2178 parse_struct_member ((Struct) parent);
2179 } else if (parent is Interface) {
2180 parse_interface_member ((Interface) parent);
2182 } catch (ParseError e) {
2183 int r;
2184 do {
2185 r = recover ();
2186 if (r == RecoveryState.STATEMENT_BEGIN) {
2187 next ();
2188 } else {
2189 break;
2191 } while (true);
2192 if (r == RecoveryState.EOF) {
2193 return;
2197 if (!root) {
2198 if (!accept (TokenType.DEDENT)) {
2199 // only report error if it's not a secondary error
2200 if (Report.get_errors () == 0) {
2201 Report.error (get_current_src (), "expected dedent");
2207 enum RecoveryState {
2208 EOF,
2209 DECLARATION_BEGIN,
2210 STATEMENT_BEGIN
2213 RecoveryState recover () {
2214 while (current () != TokenType.EOF) {
2215 switch (current ()) {
2216 case TokenType.CLASS:
2217 case TokenType.CONST:
2218 case TokenType.CONSTRUCT:
2219 case TokenType.INIT:
2220 case TokenType.DEF:
2221 case TokenType.DELEGATE:
2222 case TokenType.ENUM:
2223 case TokenType.ERRORDOMAIN:
2224 case TokenType.FINAL:
2225 case TokenType.INTERFACE:
2226 case TokenType.NAMESPACE:
2227 case TokenType.PROP:
2228 case TokenType.EVENT:
2229 case TokenType.STRUCT:
2230 return RecoveryState.DECLARATION_BEGIN;
2231 case TokenType.BREAK:
2232 case TokenType.CASE:
2233 case TokenType.CONTINUE:
2234 case TokenType.DELETE:
2235 case TokenType.DO:
2236 case TokenType.FOR:
2237 case TokenType.IF:
2238 case TokenType.LOCK:
2239 case TokenType.RETURN:
2240 case TokenType.RAISE:
2241 case TokenType.TRY:
2242 case TokenType.VAR:
2243 case TokenType.WHILE:
2244 return RecoveryState.STATEMENT_BEGIN;
2245 default:
2246 next ();
2247 break;
2250 return RecoveryState.EOF;
2253 Namespace parse_namespace_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2254 var begin = get_location ();
2255 expect (TokenType.NAMESPACE);
2256 var sym = parse_symbol_name ();
2257 var ns = new Namespace (sym.name, get_src_com (begin));
2258 set_attributes (ns, attrs);
2259 expect (TokenType.EOL);
2260 parse_declarations (ns);
2261 return ns;
2264 void parse_namespace_member (Namespace ns) throws ParseError {
2266 var sym = parse_declaration ((ns == context.root));
2267 if (sym is Namespace) {
2268 ns.add_namespace ((Namespace) sym);
2269 } else if (sym is Class) {
2270 ns.add_class ((Class) sym);
2271 } else if (sym is Interface) {
2272 ns.add_interface ((Interface) sym);
2273 } else if (sym is Struct) {
2274 ns.add_struct ((Struct) sym);
2275 } else if (sym is Enum) {
2276 ns.add_enum ((Enum) sym);
2277 } else if (sym is ErrorDomain) {
2278 ns.add_error_domain ((ErrorDomain) sym);
2279 } else if (sym is Delegate) {
2280 ns.add_delegate ((Delegate) sym);
2281 } else if (sym is Method) {
2282 var method = (Method) sym;
2283 if (method.binding == MemberBinding.INSTANCE) {
2284 method.binding = MemberBinding.STATIC;
2286 ns.add_method (method);
2287 } else if (sym is Field) {
2288 var field = (Field) sym;
2289 if (field.binding == MemberBinding.INSTANCE) {
2290 field.binding = MemberBinding.STATIC;
2292 ns.add_field (field);
2293 } else if (sym is Constant) {
2294 ns.add_constant ((Constant) sym);
2295 } else {
2296 Report.error (sym.source_reference, "unexpected declaration in namespace");
2298 scanner.source_file.add_node (sym);
2302 void add_uses_clause () throws ParseError {
2303 var begin = get_location ();
2304 var sym = parse_symbol_name ();
2305 var ns_ref = new UsingDirective (sym, get_src (begin));
2307 scanner.source_file.add_using_directive (ns_ref);
2310 void parse_using_directives () throws ParseError {
2311 while (accept (TokenType.USES)) {
2312 if (accept_block ()) {
2313 expect (TokenType.INDENT);
2315 while (current () != TokenType.DEDENT && current () != TokenType.EOF) {
2316 add_uses_clause ();
2317 expect (TokenType.EOL);
2320 expect (TokenType.DEDENT);
2321 } else {
2322 do {
2323 add_uses_clause ();
2324 } while (accept (TokenType.COMMA));
2326 expect_terminator ();
2332 Symbol parse_class_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2333 var begin = get_location ();
2334 expect (TokenType.CLASS);
2336 var flags = parse_type_declaration_modifiers ();
2338 var sym = parse_symbol_name ();
2339 var type_param_list = parse_type_parameter_list ();
2340 var base_types = new ArrayList<DataType> ();
2341 if (accept (TokenType.COLON)) {
2342 base_types.add (parse_type ());
2344 if (accept (TokenType.IMPLEMENTS)) {
2345 do {
2346 base_types.add (parse_type ());
2347 } while (accept (TokenType.COMMA));
2351 accept (TokenType.EOL);
2353 var cl = new Class (sym.name, get_src_com (begin));
2355 if (ModifierFlags.PRIVATE in flags) {
2356 cl.access = SymbolAccessibility.PRIVATE;
2357 } else {
2358 /* class must always be Public unless its name starts wtih underscore */
2359 if (sym.name[0] == '_') {
2360 cl.access = SymbolAccessibility.PRIVATE;
2361 } else {
2362 cl.access = SymbolAccessibility.PUBLIC;
2366 if (ModifierFlags.ABSTRACT in flags) {
2367 cl.is_abstract = true;
2369 set_attributes (cl, attrs);
2370 foreach (TypeParameter type_param in type_param_list) {
2371 cl.add_type_parameter (type_param);
2373 foreach (DataType base_type in base_types) {
2374 cl.add_base_type (base_type);
2377 class_name = cl.name;
2379 parse_declarations (cl);
2381 // ensure there is always a default construction method
2382 if (!scanner.source_file.external_package
2383 && !cl.is_abstract
2384 && cl.default_construction_method == null) {
2385 var m = new CreationMethod (cl.name, null, cl.source_reference);
2386 m.binding = MemberBinding.STATIC;
2387 m.access = SymbolAccessibility.PUBLIC;
2388 m.body = new Block (cl.source_reference);
2389 cl.add_method (m);
2392 Symbol result = cl;
2393 while (sym.inner != null) {
2394 sym = sym.inner;
2395 var ns = new Namespace (sym.name, cl.source_reference);
2396 if (result is Namespace) {
2397 ns.add_namespace ((Namespace) result);
2398 } else {
2399 ns.add_class ((Class) result);
2400 scanner.source_file.add_node (result);
2402 result = ns;
2404 return result;
2407 void parse_class_member (Class cl) throws ParseError {
2408 var sym = parse_declaration ();
2409 if (sym is Class) {
2410 cl.add_class ((Class) sym);
2411 } else if (sym is Struct) {
2412 cl.add_struct ((Struct) sym);
2413 } else if (sym is Enum) {
2414 cl.add_enum ((Enum) sym);
2415 } else if (sym is Delegate) {
2416 cl.add_delegate ((Delegate) sym);
2417 } else if (sym is Method) {
2418 cl.add_method ((Method) sym);
2419 } else if (sym is Vala.Signal) {
2420 cl.add_signal ((Vala.Signal) sym);
2421 } else if (sym is Field) {
2422 cl.add_field ((Field) sym);
2423 } else if (sym is Constant) {
2424 cl.add_constant ((Constant) sym);
2425 } else if (sym is Property) {
2426 cl.add_property ((Property) sym);
2427 } else if (sym is Constructor) {
2428 var c = (Constructor) sym;
2429 if (c.binding == MemberBinding.INSTANCE) {
2430 cl.constructor = c;
2431 } else if (c.binding == MemberBinding.CLASS) {
2432 cl.class_constructor = c;
2433 } else {
2434 cl.static_constructor = c;
2436 } else if (sym is Destructor) {
2437 cl.destructor = (Destructor) sym;
2438 } else {
2439 Report.error (sym.source_reference, "unexpected declaration in class");
2443 Constant parse_constant_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2444 var begin = get_location ();
2446 expect (TokenType.CONST);
2448 parse_member_declaration_modifiers ();
2450 string id = parse_identifier ();
2451 expect (TokenType.COLON);
2452 var type = parse_type (false);
2454 Expression initializer = null;
2455 if (accept (TokenType.ASSIGN)) {
2456 initializer = parse_variable_initializer ();
2458 expect_terminator ();
2460 // constant arrays don't own their element
2461 var array_type = type as ArrayType;
2462 if (array_type != null) {
2463 array_type.element_type.value_owned = false;
2466 var c = new Constant (id, type, initializer, get_src_com (begin));
2467 c.access = get_access (id);
2468 set_attributes (c, attrs);
2469 return c;
2472 Field parse_field_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2473 var begin = get_location ();
2474 string id = parse_identifier ();
2475 expect (TokenType.COLON);
2477 var flags = parse_member_declaration_modifiers ();
2479 var type = parse_type ();
2481 var f = new Field (id, type, null, get_src_com (begin));
2483 if (ModifierFlags.ABSTRACT in flags || ModifierFlags.VIRTUAL in flags || ModifierFlags.OVERRIDE in flags) {
2484 Report.error (f.source_reference, "abstract, virtual, and override modifiers are not applicable to fields");
2487 if (ModifierFlags.PRIVATE in flags) {
2488 f.access = SymbolAccessibility.PRIVATE;
2489 } else {
2490 f.access = get_access (id);
2493 set_attributes (f, attrs);
2495 if (accept (TokenType.ASSIGN)) {
2496 f.initializer = parse_expression ();
2499 if (ModifierFlags.STATIC in flags) {
2500 f.binding = MemberBinding.STATIC;
2501 } else if (ModifierFlags.CLASS in flags) {
2502 f.binding = MemberBinding.CLASS;
2505 expect_terminator ();
2507 return f;
2510 InitializerList parse_initializer () throws ParseError {
2511 var begin = get_location ();
2512 if (!accept (TokenType.OPEN_PARENS)) {
2513 expect (TokenType.OPEN_BRACE);
2515 var initializer = new InitializerList (get_src (begin));
2516 if (current () != TokenType.DEDENT) {
2517 do {
2518 var init = parse_variable_initializer ();
2519 initializer.append (init);
2520 } while (accept (TokenType.COMMA));
2522 if (!accept (TokenType.CLOSE_PARENS)) {
2523 expect (TokenType.CLOSE_BRACE);
2525 return initializer;
2528 bool is_initializer () throws ParseError {
2529 if (current () == TokenType.OPEN_BRACE) {
2530 return true;
2534 if (current () == TokenType.OPEN_PARENS) {
2535 var begin = get_location ();
2536 var is_array = false;
2538 next ();
2540 var expr = parse_expression ();
2541 is_array = (accept (TokenType.COMMA));
2543 rollback (begin);
2545 return is_array;
2549 return false;
2553 Expression parse_variable_initializer () throws ParseError {
2554 if (is_initializer ()) {
2555 var expr = parse_initializer ();
2556 return expr;
2557 } else {
2558 var expr = parse_expression ();
2559 return expr;
2564 Method parse_main_method_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2565 var id = "main";
2566 var begin = get_location ();
2567 DataType type = new VoidType ();
2568 expect (TokenType.INIT);
2570 var method = new Method (id, type, get_src_com (begin));
2571 method.access = SymbolAccessibility.PUBLIC;
2573 set_attributes (method, attrs);
2575 method.binding = MemberBinding.STATIC;
2577 var sym = new UnresolvedSymbol (null, "string", get_src (begin));
2578 type = new UnresolvedType.from_symbol (sym, get_src (begin));
2579 type.value_owned = true;
2580 type = new ArrayType (type, 1, get_src (begin));
2581 type.nullable = false;
2583 var param = new FormalParameter ("args", type, get_src (begin));
2584 method.add_parameter (param);
2587 expect (TokenType.EOL);
2589 if (accept_block ()) {
2590 method.body = parse_block ();
2593 return method;
2596 Method parse_method_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2597 var begin = get_location ();
2598 DataType type = new VoidType ();
2599 expect (TokenType.DEF);
2600 var flags = parse_member_declaration_modifiers ();
2602 string id = parse_identifier ();
2604 var params = new ArrayList<FormalParameter> ();
2605 expect (TokenType.OPEN_PARENS);
2607 if (current () != TokenType.CLOSE_PARENS) {
2608 do {
2609 var param = parse_parameter ();
2610 params.add (param);
2611 } while (accept (TokenType.COMMA));
2614 expect (TokenType.CLOSE_PARENS);
2617 /* deal with return value */
2618 if (accept (TokenType.COLON)) {
2619 type = parse_type ();
2620 parse_type_parameter_list ();
2624 var method = new Method (id, type, get_src_com (begin));
2625 if (ModifierFlags.PRIVATE in flags) {
2626 method.access = SymbolAccessibility.PRIVATE;
2627 } else {
2628 method.access = get_access (id);
2632 set_attributes (method, attrs);
2634 foreach (FormalParameter param in params) {
2635 method.add_parameter (param);
2638 if (accept (TokenType.RAISES)) {
2639 do {
2640 method.add_error_type (parse_type ());
2641 } while (accept (TokenType.COMMA));
2645 if (ModifierFlags.STATIC in flags || id == "main") {
2646 method.binding = MemberBinding.STATIC;
2648 if (ModifierFlags.ABSTRACT in flags) {
2649 method.is_abstract = true;
2651 if (ModifierFlags.VIRTUAL in flags) {
2652 method.is_virtual = true;
2654 if (ModifierFlags.OVERRIDE in flags) {
2655 method.overrides = true;
2657 if (ModifierFlags.INLINE in flags) {
2658 method.is_inline = true;
2661 expect (TokenType.EOL);
2663 var body_location = get_location ();
2666 /* "requires" and "ensures" if present will be at start of the method body */
2667 if (accept (TokenType.INDENT)) {
2668 if (accept (TokenType.REQUIRES)) {
2670 if (accept (TokenType.EOL) && accept (TokenType.INDENT)) {
2671 while (current() != TokenType.DEDENT) {
2672 method.add_precondition (parse_expression ());
2673 expect (TokenType.EOL);
2676 expect (TokenType.DEDENT);
2677 accept_terminator ();
2678 } else {
2680 method.add_precondition (parse_expression ());
2681 expect_terminator ();
2687 if (accept (TokenType.ENSURES)) {
2688 if (accept (TokenType.EOL) && accept (TokenType.INDENT)) {
2689 while (current() != TokenType.DEDENT) {
2690 method.add_postcondition (parse_expression ());
2691 expect (TokenType.EOL);
2694 expect (TokenType.DEDENT);
2695 accept_terminator ();
2696 } else {
2697 method.add_postcondition (parse_expression ());
2698 expect_terminator ();
2703 rollback (body_location);
2706 if (accept_block ()) {
2707 method.body = parse_block ();
2709 return method;
2712 Property parse_property_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2713 var begin = get_location ();
2714 var readonly = false;
2716 expect (TokenType.PROP);
2718 var flags = parse_member_declaration_modifiers ();
2720 readonly = accept (TokenType.READONLY);
2722 string id = parse_identifier ();
2723 expect (TokenType.COLON);
2725 bool is_weak = accept (TokenType.WEAK);
2726 var type = parse_type (false);
2728 var prop = new Property (id, type, null, null, get_src_com (begin));
2729 if (ModifierFlags.PRIVATE in flags) {
2730 prop.access = SymbolAccessibility.PRIVATE;
2731 } else {
2732 prop.access = get_access (id);
2735 set_attributes (prop, attrs);
2736 if (ModifierFlags.ABSTRACT in flags) {
2737 prop.is_abstract = true;
2739 if (ModifierFlags.VIRTUAL in flags) {
2740 prop.is_virtual = true;
2742 if (ModifierFlags.OVERRIDE in flags) {
2743 prop.overrides = true;
2746 if (accept (TokenType.ASSIGN)) {
2747 prop.default_expression = parse_expression ();
2751 if (accept_block ()) {
2752 expect (TokenType.INDENT);
2753 while (current () != TokenType.DEDENT) {
2754 var accessor_begin = get_location ();
2755 parse_attributes ();
2756 if (accept (TokenType.GET)) {
2757 if (prop.get_accessor != null) {
2758 throw new ParseError.SYNTAX (get_error ("property get accessor already defined"));
2760 Block block = null;
2761 if (accept_block ()) {
2762 block = parse_block ();
2764 prop.get_accessor = new PropertyAccessor (true, false, false, block, get_src (accessor_begin));
2765 prop.get_accessor.access = SymbolAccessibility.PUBLIC;
2766 } else {
2767 bool _construct = false;
2768 if (accept (TokenType.SET)) {
2769 if (readonly) {
2770 throw new ParseError.SYNTAX (get_error ("set block not allowed for a read only property"));
2772 _construct = accept (TokenType.CONSTRUCT);
2773 } else if (accept (TokenType.CONSTRUCT)) {
2774 _construct = true;
2775 } else if (!accept (TokenType.EOL)) {
2776 throw new ParseError.SYNTAX (get_error ("expected get, set, or construct"));
2779 if (prop.set_accessor != null) {
2780 throw new ParseError.SYNTAX (get_error ("property set accessor already defined"));
2783 Block block = null;
2784 if (accept_block ()) {
2785 block = parse_block ();
2787 prop.set_accessor = new PropertyAccessor (false, !readonly, _construct, block, get_src (accessor_begin));
2788 prop.set_accessor.access = SymbolAccessibility.PUBLIC;
2791 accept (TokenType.EOL);
2792 expect (TokenType.DEDENT);
2793 } else {
2794 prop.get_accessor = new PropertyAccessor (true, false, false, null, get_src (begin));
2795 prop.get_accessor.access = SymbolAccessibility.PUBLIC;
2797 if (!readonly) {
2798 prop.set_accessor = new PropertyAccessor (false, true, false, null, get_src (begin));
2799 prop.set_accessor.access = SymbolAccessibility.PUBLIC;
2803 expect_terminator ();
2806 if (!prop.is_abstract && !scanner.source_file.external_package) {
2807 var needs_var = (readonly && (prop.get_accessor != null && prop.get_accessor.body == null));
2809 if (!needs_var) {
2810 needs_var = (prop.get_accessor != null && prop.get_accessor.body == null) || (prop.set_accessor != null && prop.set_accessor.body == null);
2813 if (needs_var) {
2814 /* automatic property accessor body generation */
2815 var field_type = prop.property_type.copy ();
2816 field_type.value_owned = !is_weak;
2817 prop.field = new Field ("_%s".printf (prop.name), field_type, prop.default_expression, prop.source_reference);
2818 prop.field.access = SymbolAccessibility.PRIVATE;
2822 return prop;
2825 Vala.Signal parse_signal_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2826 var begin = get_location ();
2827 DataType type;
2829 expect (TokenType.EVENT);
2830 var flags = parse_member_declaration_modifiers ();
2831 string id = parse_identifier ();
2834 var params = new ArrayList<FormalParameter> ();
2836 expect (TokenType.OPEN_PARENS);
2837 if (current () != TokenType.CLOSE_PARENS) {
2838 do {
2839 var param = parse_parameter ();
2840 params.add (param);
2841 } while (accept (TokenType.COMMA));
2843 expect (TokenType.CLOSE_PARENS);
2845 if (accept (TokenType.COLON)) {
2846 type = parse_type ();
2847 } else {
2848 type = new VoidType ();
2851 var sig = new Vala.Signal (id, type, get_src_com (begin));
2852 if (ModifierFlags.PRIVATE in flags) {
2853 sig.access = SymbolAccessibility.PRIVATE;
2854 } else {
2855 sig.access = get_access (id);
2858 if (ModifierFlags.VIRTUAL in flags) {
2859 sig.is_virtual = true;
2862 set_attributes (sig, attrs);
2864 foreach (FormalParameter formal_param in params) {
2865 sig.add_parameter (formal_param);
2868 expect_terminator ();
2869 return sig;
2872 Constructor parse_constructor_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2873 var begin = get_location ();
2875 expect (TokenType.INIT);
2876 var flags = parse_member_declaration_modifiers ();
2878 var c = new Constructor (get_src_com (begin));
2879 if (ModifierFlags.STATIC in flags) {
2880 c.binding = MemberBinding.STATIC;
2881 } else if (ModifierFlags.CLASS in flags) {
2882 c.binding = MemberBinding.CLASS;
2885 accept_block ();
2886 c.body = parse_block ();
2887 return c;
2890 Destructor parse_destructor_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2891 var begin = get_location ();
2892 expect (TokenType.FINAL);
2893 var d = new Destructor (get_src_com (begin));
2894 accept_block ();
2895 d.body = parse_block ();
2896 return d;
2899 Symbol parse_struct_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2900 var begin = get_location ();
2902 expect (TokenType.STRUCT);
2903 var flags = parse_type_declaration_modifiers ();
2904 var sym = parse_symbol_name ();
2905 var type_param_list = parse_type_parameter_list ();
2906 var base_types = new ArrayList<DataType> ();
2907 if (accept (TokenType.COLON)) {
2908 do {
2909 base_types.add (parse_type ());
2910 } while (accept (TokenType.COMMA));
2912 var st = new Struct (sym.name, get_src_com (begin));
2913 if (ModifierFlags.PRIVATE in flags) {
2914 st.access = SymbolAccessibility.PRIVATE;
2915 } else {
2916 st.access = get_access (sym.name);
2918 set_attributes (st, attrs);
2919 foreach (TypeParameter type_param in type_param_list) {
2920 st.add_type_parameter (type_param);
2922 foreach (DataType base_type in base_types) {
2923 st.add_base_type (base_type);
2926 expect (TokenType.EOL);
2928 parse_declarations (st);
2930 Symbol result = st;
2931 while (sym.inner != null) {
2932 sym = sym.inner;
2933 var ns = new Namespace (sym.name, st.source_reference);
2934 if (result is Namespace) {
2935 ns.add_namespace ((Namespace) result);
2936 } else {
2937 ns.add_struct ((Struct) result);
2938 scanner.source_file.add_node (result);
2940 result = ns;
2942 return result;
2945 void parse_struct_member (Struct st) throws ParseError {
2946 var sym = parse_declaration ();
2947 if (sym is Method) {
2948 st.add_method ((Method) sym);
2949 } else if (sym is Field) {
2950 st.add_field ((Field) sym);
2951 } else if (sym is Constant) {
2952 st.add_constant ((Constant) sym);
2953 } else {
2954 Report.error (sym.source_reference, "unexpected declaration in struct");
2958 Symbol parse_interface_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2959 var begin = get_location ();
2961 expect (TokenType.INTERFACE);
2962 var flags = parse_type_declaration_modifiers ();
2963 var sym = parse_symbol_name ();
2964 var type_param_list = parse_type_parameter_list ();
2965 var base_types = new ArrayList<DataType> ();
2966 if (accept (TokenType.COLON)) {
2967 do {
2968 base_types.add (parse_type ());
2969 } while (accept (TokenType.COMMA));
2971 var iface = new Interface (sym.name, get_src_com (begin));
2972 if (ModifierFlags.PRIVATE in flags) {
2973 iface.access = SymbolAccessibility.PRIVATE;
2974 } else {
2975 iface.access = get_access (sym.name);
2978 set_attributes (iface, attrs);
2979 foreach (TypeParameter type_param in type_param_list) {
2980 iface.add_type_parameter (type_param);
2982 foreach (DataType base_type in base_types) {
2983 iface.add_prerequisite (base_type);
2987 expect (TokenType.EOL);
2989 parse_declarations (iface);
2992 Symbol result = iface;
2993 while (sym.inner != null) {
2994 sym = sym.inner;
2995 var ns = new Namespace (sym.name, iface.source_reference);
2996 if (result is Namespace) {
2997 ns.add_namespace ((Namespace) result);
2998 } else {
2999 ns.add_interface ((Interface) result);
3000 scanner.source_file.add_node (result);
3002 result = ns;
3004 return result;
3007 void parse_interface_member (Interface iface) throws ParseError {
3008 var sym = parse_declaration ();
3009 if (sym is Class) {
3010 iface.add_class ((Class) sym);
3011 } else if (sym is Struct) {
3012 iface.add_struct ((Struct) sym);
3013 } else if (sym is Enum) {
3014 iface.add_enum ((Enum) sym);
3015 } else if (sym is Delegate) {
3016 iface.add_delegate ((Delegate) sym);
3017 } else if (sym is Method) {
3018 iface.add_method ((Method) sym);
3019 } else if (sym is Vala.Signal) {
3020 iface.add_signal ((Vala.Signal) sym);
3021 } else if (sym is Field) {
3022 iface.add_field ((Field) sym);
3023 } else if (sym is Property) {
3024 iface.add_property ((Property) sym);
3025 } else {
3026 Report.error (sym.source_reference, "unexpected declaration in interface");
3030 Symbol parse_enum_declaration (Gee.List<Attribute>? attrs) throws ParseError {
3031 var begin = get_location ();
3032 expect (TokenType.ENUM);
3033 var flags = parse_type_declaration_modifiers ();
3035 var sym = parse_symbol_name ();
3036 var en = new Enum (sym.name, get_src_com (begin));
3037 if (ModifierFlags.PRIVATE in flags) {
3038 en.access = SymbolAccessibility.PRIVATE;
3039 } else {
3040 en.access = get_access (sym.name);
3042 set_attributes (en, attrs);
3044 expect (TokenType.EOL);
3045 expect (TokenType.INDENT);
3046 do {
3047 if (current () == TokenType.DEDENT) {
3048 // allow trailing comma
3049 break;
3051 var value_attrs = parse_attributes ();
3052 var value_begin = get_location ();
3053 string id = parse_identifier ();
3055 var ev = new EnumValue (id, get_src (value_begin));
3056 set_attributes (ev, value_attrs);
3058 if (accept (TokenType.ASSIGN)) {
3059 ev.value = parse_expression ();
3061 en.add_value (ev);
3062 expect (TokenType.EOL);
3063 } while (true);
3065 expect (TokenType.DEDENT);
3067 Symbol result = en;
3068 while (sym.inner != null) {
3069 sym = sym.inner;
3070 var ns = new Namespace (sym.name, en.source_reference);
3071 if (result is Namespace) {
3072 ns.add_namespace ((Namespace) result);
3073 } else {
3074 ns.add_enum ((Enum) result);
3075 scanner.source_file.add_node (result);
3077 result = ns;
3079 return result;
3082 Symbol parse_errordomain_declaration (Gee.List<Attribute>? attrs) throws ParseError {
3083 var begin = get_location ();
3084 expect (TokenType.ERRORDOMAIN);
3085 var flags = parse_type_declaration_modifiers ();
3087 var sym = parse_symbol_name ();
3088 var ed = new ErrorDomain (sym.name, get_src_com (begin));
3089 if (ModifierFlags.PRIVATE in flags) {
3090 ed.access = SymbolAccessibility.PRIVATE;
3091 } else {
3092 ed.access = get_access (sym.name);
3095 set_attributes (ed, attrs);
3097 expect (TokenType.EOL);
3098 expect (TokenType.INDENT);
3100 do {
3101 if (current () == TokenType.DEDENT) {
3102 // allow trailing comma
3103 break;
3105 var code_attrs = parse_attributes ();
3106 string id = parse_identifier ();
3108 var ec = new ErrorCode (id);
3109 set_attributes (ec, code_attrs);
3110 if (accept (TokenType.ASSIGN)) {
3111 ec.value = parse_expression ();
3113 ed.add_code (ec);
3114 accept (TokenType.EOL);
3115 } while (true);
3118 expect (TokenType.DEDENT);
3120 Symbol result = ed;
3121 while (sym.inner != null) {
3122 sym = sym.inner;
3123 var ns = new Namespace (sym.name, ed.source_reference);
3125 if (result is Namespace) {
3126 ns.add_namespace ((Namespace) result);
3127 } else {
3128 ns.add_error_domain ((ErrorDomain) result);
3129 scanner.source_file.add_node (result);
3131 result = ns;
3133 return result;
3136 ModifierFlags parse_type_declaration_modifiers () {
3137 ModifierFlags flags = 0;
3138 while (true) {
3139 switch (current ()) {
3140 case TokenType.ABSTRACT:
3141 next ();
3142 flags |= ModifierFlags.ABSTRACT;
3143 break;
3145 case TokenType.EXTERN:
3146 next ();
3147 flags |= ModifierFlags.EXTERN;
3148 break;
3150 case TokenType.STATIC:
3151 next ();
3152 flags |= ModifierFlags.STATIC;
3153 break;
3155 case TokenType.PRIVATE:
3156 next ();
3157 flags |= ModifierFlags.PRIVATE;
3158 break;
3160 default:
3161 return flags;
3166 ModifierFlags parse_member_declaration_modifiers () {
3167 ModifierFlags flags = 0;
3168 while (true) {
3169 switch (current ()) {
3170 case TokenType.ABSTRACT:
3171 next ();
3172 flags |= ModifierFlags.ABSTRACT;
3173 break;
3174 case TokenType.CLASS:
3175 next ();
3176 flags |= ModifierFlags.CLASS;
3177 break;
3178 case TokenType.EXTERN:
3179 next ();
3180 flags |= ModifierFlags.EXTERN;
3181 break;
3182 case TokenType.INLINE:
3183 next ();
3184 flags |= ModifierFlags.INLINE;
3185 break;
3186 case TokenType.OVERRIDE:
3187 next ();
3188 flags |= ModifierFlags.OVERRIDE;
3189 break;
3190 case TokenType.STATIC:
3191 next ();
3192 flags |= ModifierFlags.STATIC;
3193 break;
3194 case TokenType.VIRTUAL:
3195 next ();
3196 flags |= ModifierFlags.VIRTUAL;
3197 break;
3198 case TokenType.PRIVATE:
3199 next ();
3200 flags |= ModifierFlags.PRIVATE;
3201 break;
3202 default:
3203 return flags;
3208 FormalParameter parse_parameter () throws ParseError {
3209 var attrs = parse_attributes ();
3210 var begin = get_location ();
3211 if (accept (TokenType.ELLIPSIS)) {
3212 // varargs
3213 return new FormalParameter.with_ellipsis (get_src (begin));
3216 var direction = ParameterDirection.IN;
3217 if (accept (TokenType.OUT)) {
3218 direction = ParameterDirection.OUT;
3219 } else if (accept (TokenType.REF)) {
3220 direction = ParameterDirection.REF;
3223 string id = parse_identifier ();
3225 expect (TokenType.COLON);
3227 DataType type;
3228 if (direction == ParameterDirection.IN) {
3229 type = parse_type (false);
3230 } else {
3231 type = parse_type (true);
3234 var param = new FormalParameter (id, type, get_src (begin));
3235 set_attributes (param, attrs);
3236 param.direction = direction;
3237 param.construct_parameter = false;
3238 if (accept (TokenType.ASSIGN)) {
3239 param.default_expression = parse_expression ();
3241 return param;
3244 CreationMethod parse_creation_method_declaration (Gee.List<Attribute>? attrs) throws ParseError {
3245 var begin = get_location ();
3246 CreationMethod method;
3248 expect (TokenType.CONSTRUCT);
3250 parse_member_declaration_modifiers ();
3253 if (accept (TokenType.OPEN_PARENS)) {
3254 /* create default name using class name */
3255 method = new CreationMethod (class_name, null, get_src_com (begin));
3256 } else {
3257 var sym = parse_symbol_name ();
3258 if (sym.inner == null) {
3260 if (sym.name != class_name) {
3261 method = new CreationMethod (class_name, sym.name, get_src_com (begin));
3262 } else {
3263 method = new CreationMethod (sym.name, null, get_src_com (begin));
3265 } else {
3266 method = new CreationMethod (sym.inner.name, sym.name, get_src_com (begin));
3268 expect (TokenType.OPEN_PARENS);
3272 if (current () != TokenType.CLOSE_PARENS) {
3273 do {
3274 var param = parse_parameter ();
3275 method.add_parameter (param);
3276 } while (accept (TokenType.COMMA));
3278 expect (TokenType.CLOSE_PARENS);
3279 if (accept (TokenType.RAISES)) {
3280 do {
3281 method.add_error_type (parse_type ());
3282 } while (accept (TokenType.COMMA));
3284 method.access = SymbolAccessibility.PUBLIC;
3285 set_attributes (method, attrs);
3286 method.binding = MemberBinding.STATIC;
3288 if (accept_block ()) {
3289 method.body = parse_block ();
3292 return method;
3295 Symbol parse_delegate_declaration (Gee.List<Attribute>? attrs) throws ParseError {
3296 var begin = get_location ();
3297 DataType type;
3299 expect (TokenType.DELEGATE);
3301 var flags = parse_member_declaration_modifiers ();
3303 var sym = parse_symbol_name ();
3305 var type_param_list = parse_type_parameter_list ();
3308 var params = new ArrayList<FormalParameter> ();
3310 expect (TokenType.OPEN_PARENS);
3311 if (current () != TokenType.CLOSE_PARENS) {
3312 do {
3313 var param = parse_parameter ();
3314 params.add (param);
3315 } while (accept (TokenType.COMMA));
3317 expect (TokenType.CLOSE_PARENS);
3319 if (accept (TokenType.COLON)) {
3320 type = parse_type ();
3322 } else {
3323 type = new VoidType ();
3326 if (accept (TokenType.RAISES)) {
3327 do {
3328 parse_type ();
3329 } while (accept (TokenType.COMMA));
3332 expect_terminator ();
3334 var d = new Delegate (sym.name, type, get_src_com (begin));
3335 if (ModifierFlags.PRIVATE in flags) {
3336 d.access = SymbolAccessibility.PRIVATE;
3337 } else {
3338 d.access = get_access (sym.name);
3341 set_attributes (d, attrs);
3343 foreach (TypeParameter type_param in type_param_list) {
3344 d.add_type_parameter (type_param);
3347 foreach (FormalParameter formal_param in params) {
3348 d.add_parameter (formal_param);
3351 if (!(ModifierFlags.STATIC in flags)) {
3352 d.has_target = true;
3356 Symbol result = d;
3357 while (sym.inner != null) {
3358 sym = sym.inner;
3359 var ns = new Namespace (sym.name, d.source_reference);
3361 if (result is Namespace) {
3362 ns.add_namespace ((Namespace) result);
3363 } else {
3364 ns.add_delegate ((Delegate) result);
3365 scanner.source_file.add_node (result);
3367 result = ns;
3369 return result;
3372 Gee.List<TypeParameter> parse_type_parameter_list () throws ParseError {
3373 var list = new ArrayList<TypeParameter> ();
3374 if (accept (TokenType.OF)) {
3375 do {
3376 var begin = get_location ();
3377 string id = parse_identifier ();
3378 list.add (new TypeParameter (id, get_src (begin)));
3379 } while (accept (TokenType.COMMA));
3382 return list;
3385 void skip_type_argument_list () throws ParseError {
3386 if (accept (TokenType.OF)) {
3387 do {
3388 skip_type ();
3389 } while (accept (TokenType.COMMA));
3393 // try to parse type argument list
3394 Gee.List<DataType>? parse_type_argument_list (bool maybe_expression) throws ParseError {
3395 var begin = get_location ();
3396 if (accept (TokenType.OF)) {
3397 var list = new ArrayList<DataType> ();
3398 do {
3399 switch (current ()) {
3400 case TokenType.VOID:
3401 case TokenType.DYNAMIC:
3402 case TokenType.WEAK:
3403 case TokenType.IDENTIFIER:
3404 var type = parse_type ();
3406 list.add (type);
3407 break;
3408 default:
3409 rollback (begin);
3410 return null;
3412 } while (accept (TokenType.COMMA));
3414 return list;
3416 return null;
3419 MemberAccess parse_member_name () throws ParseError {
3420 var begin = get_location ();
3421 MemberAccess expr = null;
3422 do {
3423 string id = parse_identifier ();
3424 Gee.List<DataType> type_arg_list = parse_type_argument_list (false);
3425 expr = new MemberAccess (expr, id, get_src (begin));
3426 if (type_arg_list != null) {
3427 foreach (DataType type_arg in type_arg_list) {
3428 expr.add_type_argument (type_arg);
3431 } while (accept (TokenType.DOT));
3432 return expr;