posix.vapi: signal is allowed to be null (restoring the original handler)
[vala-lang.git] / vala / valagenieparser.vala
blobb90acb92bac4dfae981728c618834197f8e7a4b8
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 expect (TokenType.OPEN_PARENS);
623 var expr_list = new ArrayList<Expression> ();
624 if (current () != TokenType.CLOSE_PARENS) {
625 do {
626 expr_list.add (parse_expression ());
627 } while (accept (TokenType.COMMA));
629 expect (TokenType.CLOSE_PARENS);
630 if (expr_list.size != 1) {
631 var tuple = new Tuple ();
632 foreach (Expression expr in expr_list) {
633 tuple.add_expression (expr);
635 return tuple;
637 return expr_list.get (0);
640 Expression parse_member_access (SourceLocation begin, Expression inner) throws ParseError {
641 expect (TokenType.DOT);
642 string id = parse_identifier ();
643 Gee.List<DataType> type_arg_list = parse_type_argument_list (true);
644 var expr = new MemberAccess (inner, id, get_src (begin));
645 if (type_arg_list != null) {
646 foreach (DataType type_arg in type_arg_list) {
647 expr.add_type_argument (type_arg);
650 return expr;
653 Expression parse_pointer_member_access (SourceLocation begin, Expression inner) throws ParseError {
654 expect (TokenType.OP_PTR);
655 string id = parse_identifier ();
656 Gee.List<DataType> type_arg_list = parse_type_argument_list (true);
657 var expr = new MemberAccess.pointer (inner, id, get_src (begin));
658 if (type_arg_list != null) {
659 foreach (DataType type_arg in type_arg_list) {
660 expr.add_type_argument (type_arg);
663 return expr;
667 Gee.List<Expression> parse_print_argument_list () throws ParseError {
668 var list = new ArrayList<Expression> ();
669 var i = 0;
670 var begin = get_location ();
672 if (current () != TokenType.CLOSE_PARENS) {
673 do {
674 var p_expr = parse_expression ();
675 if (i == 0) {
676 i++;
678 if (p_expr != null) {
679 string s = "\\n\"";
681 if (p_expr is StringLiteral) {
682 var s_exp = (StringLiteral) p_expr;
683 var len = s_exp.value.size ();
685 if (len > 2) {
686 var st = s_exp.value.ndup (len-1);
687 st += s;
688 s_exp.value = st;
690 } else {
691 var rhs = new StringLiteral (s, get_src (begin));
692 p_expr = new BinaryExpression (BinaryOperator.PLUS, p_expr, rhs, get_src (begin));
697 list.add (p_expr);
699 } while (accept (TokenType.COMMA));
701 return list;
704 Expression parse_print_expression () throws ParseError {
705 var begin = get_location ();
707 expect (TokenType.PRINT);
708 accept (TokenType.OPEN_PARENS);
710 var expr = new MemberAccess (null, "print", get_src (begin));
712 var arg_list = parse_print_argument_list ();
714 accept (TokenType.CLOSE_PARENS);
716 var print_expr = new MethodCall (expr, get_src (begin));
718 foreach (Expression arg in arg_list) {
719 print_expr.add_argument (arg);
722 return print_expr;
726 Expression parse_assert_expression () throws ParseError {
727 var begin = get_location ();
729 expect (TokenType.ASSERT);
730 accept (TokenType.OPEN_PARENS);
732 var expr = new MemberAccess (null, "assert", get_src (begin));
734 var arg_list = parse_argument_list ();
736 accept (TokenType.CLOSE_PARENS);
738 var assert_expr = new MethodCall (expr, get_src (begin));
740 foreach (Expression arg in arg_list) {
741 assert_expr.add_argument (arg);
744 return assert_expr;
748 Expression parse_method_call (SourceLocation begin, Expression inner) throws ParseError {
749 expect (TokenType.OPEN_PARENS);
750 var arg_list = parse_argument_list ();
751 expect (TokenType.CLOSE_PARENS);
752 var init_list = parse_object_initializer ();
754 if (init_list.size > 0 && inner is MemberAccess) {
755 // struct creation expression
756 var member = (MemberAccess) inner;
757 member.creation_member = true;
759 var expr = new ObjectCreationExpression (member, get_src (begin));
760 expr.struct_creation = true;
761 foreach (Expression arg in arg_list) {
762 expr.add_argument (arg);
764 foreach (MemberInitializer initializer in init_list) {
765 expr.add_member_initializer (initializer);
767 return expr;
768 } else {
769 var expr = new MethodCall (inner, get_src (begin));
770 foreach (Expression arg in arg_list) {
771 expr.add_argument (arg);
773 return expr;
777 Expression parse_element_access (SourceLocation begin, Expression inner) throws ParseError {
778 expect (TokenType.OPEN_BRACKET);
779 var index_list = parse_expression_list ();
780 expect (TokenType.CLOSE_BRACKET);
782 var expr = new ElementAccess (inner, get_src (begin));
783 foreach (Expression index in index_list) {
784 expr.append_index (index);
786 return expr;
789 Gee.List<Expression> parse_expression_list () throws ParseError {
790 var list = new ArrayList<Expression> ();
791 do {
792 list.add (parse_expression ());
793 } while (accept (TokenType.COMMA));
794 return list;
797 Expression parse_this_access () throws ParseError {
798 var begin = get_location ();
799 expect (TokenType.THIS);
800 return new MemberAccess (null, "this", get_src (begin));
803 Expression parse_base_access () throws ParseError {
804 var begin = get_location ();
805 expect (TokenType.SUPER);
806 return new BaseAccess (get_src (begin));
809 Expression parse_post_increment_expression (SourceLocation begin, Expression inner) throws ParseError {
810 expect (TokenType.OP_INC);
811 return new PostfixExpression (inner, true, get_src (begin));
814 Expression parse_post_decrement_expression (SourceLocation begin, Expression inner) throws ParseError {
815 expect (TokenType.OP_DEC);
816 return new PostfixExpression (inner, false, get_src (begin));
819 Expression parse_object_or_array_creation_expression () throws ParseError {
820 var begin = get_location ();
821 expect (TokenType.NEW);
823 if (accept (TokenType.ARRAY)) {
824 expect (TokenType.OF);
825 var m = parse_member_name ();
826 var expr = parse_array_creation_expression (begin, m);
827 return expr;
830 if (accept (TokenType.LIST)) {
831 expect (TokenType.OF);
832 var m = parse_member_name ();
833 var expr = parse_list_creation_expression (begin, m);
834 return expr;
837 if (accept (TokenType.DICT)) {
838 expect (TokenType.OF);
839 var m1 = parse_member_name ();
840 expect (TokenType.COMMA);
841 var m2 = parse_member_name ();
842 var expr = parse_dict_creation_expression (begin, m1, m2);
843 return expr;
847 var member = parse_member_name ();
848 var expr = parse_object_creation_expression (begin, member);
849 return expr;
853 Expression parse_object_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError {
854 member.creation_member = true;
855 Gee.List<Expression> arg_list;
856 if (accept (TokenType.OPEN_PARENS)) {
857 arg_list = parse_argument_list ();
858 expect (TokenType.CLOSE_PARENS);
859 } else {
860 arg_list = new ArrayList<Expression> ();
863 var init_list = parse_object_initializer ();
865 var expr = new ObjectCreationExpression (member, get_src (begin));
866 foreach (Expression arg in arg_list) {
867 expr.add_argument (arg);
869 foreach (MemberInitializer initializer in init_list) {
870 expr.add_member_initializer (initializer);
872 return expr;
875 Expression parse_array_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError {
876 bool size_specified = false;
877 Gee.List<Expression> size_specifier_list = null;
878 bool first = true;
879 DataType element_type = UnresolvedType.new_from_expression (member);
881 var has_bracket = accept (TokenType.OPEN_BRACKET);
883 do {
884 if (!first) {
885 // array of arrays: new T[][42]
886 element_type = new ArrayType (element_type, size_specifier_list.size, element_type.source_reference);
887 } else {
888 first = false;
891 size_specifier_list = new ArrayList<Expression> ();
892 do {
893 Expression size = null;
894 if (has_bracket && current () != TokenType.CLOSE_BRACKET && current () != TokenType.COMMA) {
895 size = parse_expression ();
896 size_specified = true;
898 size_specifier_list.add (size);
899 } while (accept (TokenType.COMMA));
901 if (has_bracket) {
902 expect (TokenType.CLOSE_BRACKET);
904 } while (accept (TokenType.OPEN_BRACKET));
906 InitializerList initializer = null;
907 if (accept (TokenType.ASSIGN)) {
909 initializer = parse_initializer ();
911 var expr = new ArrayCreationExpression (element_type, size_specifier_list.size, initializer, get_src (begin));
912 if (size_specified) {
913 foreach (Expression size in size_specifier_list) {
914 expr.append_size (size);
917 return expr;
921 Expression parse_list_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError {
923 DataType element_type = UnresolvedType.new_from_expression (member);
924 MemberAccess list_member = null, parent_member = null;
926 parent_member = new MemberAccess (null, "Gee", get_src (begin));
927 list_member = new MemberAccess (parent_member, "ArrayList", get_src (begin));
928 list_member.add_type_argument (element_type);
930 list_member.creation_member = true;
932 var expr = new ObjectCreationExpression (list_member, get_src (begin));
934 if (member.member_name == "string") {
935 parent_member = new MemberAccess (null, "GLib", get_src (begin));
936 expr.add_argument (new MemberAccess (parent_member, "str_equal", get_src (begin)));
938 } else if (member.member_name == "int") {
939 parent_member = new MemberAccess (null, "GLib", get_src (begin));
940 expr.add_argument (new MemberAccess (parent_member, "int_equal", get_src (begin)));
943 return expr;
946 Expression parse_dict_creation_expression (SourceLocation begin, MemberAccess member_key, MemberAccess member_value) throws ParseError {
948 DataType key_type = UnresolvedType.new_from_expression (member_key);
949 DataType value_type = UnresolvedType.new_from_expression (member_value);
951 MemberAccess dict_member = null, parent_member = null, dict_hash = null, dict_equal = null;
953 parent_member = new MemberAccess (null, "Gee", get_src (begin));
954 dict_member = new MemberAccess (parent_member, "HashMap", get_src (begin));
955 dict_member.add_type_argument (key_type);
956 dict_member.add_type_argument (value_type);
958 if (member_key.member_name == "string") {
959 parent_member = new MemberAccess (null, "GLib", get_src (begin));
960 dict_hash = new MemberAccess (parent_member, "str_hash", get_src (begin));
961 dict_equal = new MemberAccess (parent_member, "str_equal", get_src (begin));
963 } else if (member_key.member_name == "int") {
964 parent_member = new MemberAccess (null, "GLib", get_src (begin));
965 dict_hash = new MemberAccess (parent_member, "int_hash", get_src (begin));
966 dict_equal = new MemberAccess (parent_member, "int_equal", get_src (begin));
969 dict_member.creation_member = true;
971 var expr = new ObjectCreationExpression (dict_member, get_src (begin));
973 if (dict_hash != null && dict_equal != null) {
974 expr.add_argument (dict_hash);
975 expr.add_argument (dict_equal);
979 return expr;
983 Gee.List<MemberInitializer> parse_object_initializer () throws ParseError {
984 var list = new ArrayList<MemberInitializer> ();
985 if (accept (TokenType.OPEN_BRACE)) {
986 do {
987 list.add (parse_member_initializer ());
988 } while (accept (TokenType.COMMA));
989 expect (TokenType.CLOSE_BRACE);
991 return list;
994 MemberInitializer parse_member_initializer () throws ParseError {
995 var begin = get_location ();
996 string id = parse_identifier ();
997 expect (TokenType.ASSIGN);
998 var expr = parse_expression ();
1000 return new MemberInitializer (id, expr, get_src (begin));
1003 Expression parse_sizeof_expression () throws ParseError {
1004 var begin = get_location ();
1005 expect (TokenType.SIZEOF);
1006 expect (TokenType.OPEN_PARENS);
1007 var type = parse_type ();
1008 expect (TokenType.CLOSE_PARENS);
1010 return new SizeofExpression (type, get_src (begin));
1013 Expression parse_typeof_expression () throws ParseError {
1014 var begin = get_location ();
1015 expect (TokenType.TYPEOF);
1016 expect (TokenType.OPEN_PARENS);
1017 var type = parse_type ();
1018 expect (TokenType.CLOSE_PARENS);
1020 return new TypeofExpression (type, get_src (begin));
1023 UnaryOperator get_unary_operator (TokenType token_type) {
1024 switch (token_type) {
1025 case TokenType.PLUS: return UnaryOperator.PLUS;
1026 case TokenType.MINUS: return UnaryOperator.MINUS;
1027 case TokenType.OP_NEG: return UnaryOperator.LOGICAL_NEGATION;
1028 case TokenType.TILDE: return UnaryOperator.BITWISE_COMPLEMENT;
1029 case TokenType.OP_INC: return UnaryOperator.INCREMENT;
1030 case TokenType.OP_DEC: return UnaryOperator.DECREMENT;
1031 case TokenType.REF: return UnaryOperator.REF;
1032 case TokenType.OUT: return UnaryOperator.OUT;
1033 default: return UnaryOperator.NONE;
1037 Expression parse_unary_expression () throws ParseError {
1038 var begin = get_location ();
1039 var operator = get_unary_operator (current ());
1040 if (operator != UnaryOperator.NONE) {
1041 next ();
1042 var op = parse_unary_expression ();
1043 return new UnaryExpression (operator, op, get_src (begin));
1045 switch (current ()) {
1046 case TokenType.HASH:
1047 next ();
1048 var op = parse_unary_expression ();
1049 return new ReferenceTransferExpression (op, get_src (begin));
1050 case TokenType.OPEN_PARENS:
1051 next ();
1052 switch (current ()) {
1053 case TokenType.VOID:
1054 case TokenType.DYNAMIC:
1055 case TokenType.WEAK:
1056 case TokenType.IDENTIFIER:
1057 var type = parse_type ();
1058 if (accept (TokenType.CLOSE_PARENS)) {
1059 // check follower to decide whether to create cast expression
1060 switch (current ()) {
1061 case TokenType.OP_NEG:
1062 case TokenType.TILDE:
1063 case TokenType.OPEN_PARENS:
1064 case TokenType.TRUE:
1065 case TokenType.FALSE:
1066 case TokenType.INTEGER_LITERAL:
1067 case TokenType.REAL_LITERAL:
1068 case TokenType.CHARACTER_LITERAL:
1069 case TokenType.STRING_LITERAL:
1070 case TokenType.NULL:
1071 case TokenType.THIS:
1072 case TokenType.SUPER:
1073 case TokenType.NEW:
1074 case TokenType.SIZEOF:
1075 case TokenType.TYPEOF:
1076 case TokenType.IDENTIFIER:
1077 if (!(type is PointerType) && !type.value_owned) {
1078 Report.warning (get_src (begin), "obsolete syntax, weak type modifier unused in cast expressions");
1080 var inner = parse_unary_expression ();
1081 return new CastExpression (inner, type, get_src (begin), false);
1082 default:
1083 break;
1086 break;
1087 default:
1088 break;
1090 // no cast expression
1091 rollback (begin);
1092 break;
1093 case TokenType.STAR:
1094 next ();
1095 var op = parse_unary_expression ();
1096 return new PointerIndirection (op, get_src (begin));
1097 case TokenType.BITWISE_AND:
1098 next ();
1099 var op = parse_unary_expression ();
1100 return new AddressofExpression (op, get_src (begin));
1101 default:
1102 break;
1105 var expr = parse_primary_expression ();
1106 return expr;
1109 BinaryOperator get_binary_operator (TokenType token_type) {
1110 switch (token_type) {
1111 case TokenType.STAR: return BinaryOperator.MUL;
1112 case TokenType.DIV: return BinaryOperator.DIV;
1113 case TokenType.PERCENT: return BinaryOperator.MOD;
1114 case TokenType.PLUS: return BinaryOperator.PLUS;
1115 case TokenType.MINUS: return BinaryOperator.MINUS;
1116 case TokenType.OP_LT: return BinaryOperator.LESS_THAN;
1117 case TokenType.OP_GT: return BinaryOperator.GREATER_THAN;
1118 case TokenType.OP_LE: return BinaryOperator.LESS_THAN_OR_EQUAL;
1119 case TokenType.OP_GE: return BinaryOperator.GREATER_THAN_OR_EQUAL;
1120 case TokenType.OP_EQ: return BinaryOperator.EQUALITY;
1121 case TokenType.IS:
1122 next();
1123 if (current () == TokenType.OP_NEG) {
1124 prev ();
1125 return BinaryOperator.INEQUALITY;
1127 prev ();
1128 return BinaryOperator.EQUALITY;
1129 case TokenType.OP_NE: return BinaryOperator.INEQUALITY;
1130 default: return BinaryOperator.NONE;
1134 Expression parse_multiplicative_expression () throws ParseError {
1135 var begin = get_location ();
1136 var left = parse_unary_expression ();
1137 bool found = true;
1138 while (found) {
1139 var operator = get_binary_operator (current ());
1140 switch (operator) {
1141 case BinaryOperator.MUL:
1142 case BinaryOperator.DIV:
1143 case BinaryOperator.MOD:
1144 next ();
1145 var right = parse_unary_expression ();
1146 left = new BinaryExpression (operator, left, right, get_src (begin));
1147 break;
1148 default:
1149 found = false;
1150 break;
1153 return left;
1156 Expression parse_additive_expression () throws ParseError {
1157 var begin = get_location ();
1158 var left = parse_multiplicative_expression ();
1159 bool found = true;
1160 while (found) {
1161 var operator = get_binary_operator (current ());
1162 switch (operator) {
1163 case BinaryOperator.PLUS:
1164 case BinaryOperator.MINUS:
1165 next ();
1166 var right = parse_multiplicative_expression ();
1167 left = new BinaryExpression (operator, left, right, get_src (begin));
1168 break;
1169 default:
1170 found = false;
1171 break;
1174 return left;
1177 Expression parse_shift_expression () throws ParseError {
1178 var begin = get_location ();
1179 var left = parse_additive_expression ();
1180 bool found = true;
1181 while (found) {
1182 switch (current ()) {
1183 case TokenType.OP_SHIFT_LEFT:
1184 next ();
1185 var right = parse_additive_expression ();
1186 left = new BinaryExpression (BinaryOperator.SHIFT_LEFT, left, right, get_src (begin));
1187 break;
1188 // don't use OP_SHIFT_RIGHT to support >> for nested generics
1189 case TokenType.OP_GT:
1190 char* first_gt_pos = tokens[index].begin.pos;
1191 next ();
1192 // only accept >> when there is no space between the two > signs
1193 if (current () == TokenType.OP_GT && tokens[index].begin.pos == first_gt_pos + 1) {
1194 next ();
1195 var right = parse_additive_expression ();
1196 left = new BinaryExpression (BinaryOperator.SHIFT_RIGHT, left, right, get_src (begin));
1197 } else {
1198 prev ();
1199 found = false;
1201 break;
1202 default:
1203 found = false;
1204 break;
1207 return left;
1210 Expression parse_relational_expression () throws ParseError {
1211 var begin = get_location ();
1212 var left = parse_shift_expression ();
1213 bool found = true;
1214 while (found) {
1215 var operator = get_binary_operator (current ());
1216 switch (operator) {
1217 case BinaryOperator.LESS_THAN:
1218 case BinaryOperator.LESS_THAN_OR_EQUAL:
1219 case BinaryOperator.GREATER_THAN_OR_EQUAL:
1220 next ();
1221 var right = parse_shift_expression ();
1222 left = new BinaryExpression (operator, left, right, get_src (begin));
1223 break;
1224 case BinaryOperator.GREATER_THAN:
1225 next ();
1226 // ignore >> and >>= (two tokens due to generics)
1227 if (current () != TokenType.OP_GT && current () != TokenType.OP_GE) {
1228 var right = parse_shift_expression ();
1229 left = new BinaryExpression (operator, left, right, get_src (begin));
1230 } else {
1231 prev ();
1232 found = false;
1234 break;
1235 default:
1236 switch (current ()) {
1237 case TokenType.ISA:
1238 next ();
1239 var type = parse_type ();
1240 left = new TypeCheck (left, type, get_src (begin));
1241 break;
1242 case TokenType.AS:
1243 next ();
1244 var type = parse_type ();
1245 left = new CastExpression (left, type, get_src (begin), true);
1246 break;
1247 default:
1248 found = false;
1249 break;
1251 break;
1254 return left;
1257 Expression parse_equality_expression () throws ParseError {
1258 var begin = get_location ();
1259 var left = parse_relational_expression ();
1260 bool found = true;
1261 while (found) {
1262 var operator = get_binary_operator (current ());
1263 switch (operator) {
1264 case BinaryOperator.INEQUALITY:
1265 case BinaryOperator.EQUALITY:
1266 if ((operator == BinaryOperator.INEQUALITY) && (current () == TokenType.IS)) {
1267 next ();
1269 next ();
1270 var right = parse_relational_expression ();
1271 left = new BinaryExpression (operator, left, right, get_src (begin));
1272 break;
1273 default:
1274 found = false;
1275 break;
1278 return left;
1281 Expression parse_and_expression () throws ParseError {
1282 var begin = get_location ();
1283 var left = parse_equality_expression ();
1284 while (accept (TokenType.BITWISE_AND)) {
1285 var right = parse_equality_expression ();
1286 left = new BinaryExpression (BinaryOperator.BITWISE_AND, left, right, get_src (begin));
1288 return left;
1291 Expression parse_exclusive_or_expression () throws ParseError {
1292 var begin = get_location ();
1293 var left = parse_and_expression ();
1294 while (accept (TokenType.CARRET)) {
1295 var right = parse_and_expression ();
1296 left = new BinaryExpression (BinaryOperator.BITWISE_XOR, left, right, get_src (begin));
1298 return left;
1301 Expression parse_inclusive_or_expression () throws ParseError {
1302 var begin = get_location ();
1303 var left = parse_exclusive_or_expression ();
1304 while (accept (TokenType.BITWISE_OR)) {
1305 var right = parse_exclusive_or_expression ();
1306 left = new BinaryExpression (BinaryOperator.BITWISE_OR, left, right, get_src (begin));
1308 return left;
1311 Expression parse_in_expression () throws ParseError {
1312 var begin = get_location ();
1313 var left = parse_inclusive_or_expression ();
1314 while (accept (TokenType.IN)) {
1315 var right = parse_inclusive_or_expression ();
1316 left = new BinaryExpression (BinaryOperator.IN, left, right, get_src (begin));
1318 return left;
1321 Expression parse_conditional_and_expression () throws ParseError {
1322 var begin = get_location ();
1323 var left = parse_in_expression ();
1324 while (accept (TokenType.OP_AND)) {
1325 var right = parse_in_expression ();
1326 left = new BinaryExpression (BinaryOperator.AND, left, right, get_src (begin));
1328 return left;
1331 Expression parse_conditional_or_expression () throws ParseError {
1332 var begin = get_location ();
1333 var left = parse_conditional_and_expression ();
1334 while (accept (TokenType.OP_OR)) {
1335 var right = parse_conditional_and_expression ();
1336 left = new BinaryExpression (BinaryOperator.OR, left, right, get_src (begin));
1338 return left;
1341 Expression parse_conditional_expression () throws ParseError {
1342 var begin = get_location ();
1343 var condition = parse_conditional_or_expression ();
1344 if (accept (TokenType.INTERR)) {
1345 var true_expr = parse_expression ();
1346 expect (TokenType.COLON);
1347 var false_expr = parse_expression ();
1348 return new ConditionalExpression (condition, true_expr, false_expr, get_src (begin));
1349 } else {
1350 return condition;
1354 Expression parse_lambda_expression () throws ParseError {
1355 var begin = get_location ();
1356 Gee.List<string> params = new ArrayList<string> ();
1358 expect (TokenType.DEF);
1360 if (accept (TokenType.OPEN_PARENS)) {
1361 if (current () != TokenType.CLOSE_PARENS) {
1362 do {
1363 params.add (parse_identifier ());
1364 } while (accept (TokenType.COMMA));
1366 expect (TokenType.CLOSE_PARENS);
1367 } else {
1368 params.add (parse_identifier ());
1372 LambdaExpression lambda;
1373 if (accept_block ()) {
1374 var block = parse_block ();
1375 lambda = new LambdaExpression.with_statement_body (block, get_src (begin));
1376 } else {
1377 var expr = parse_expression ();
1378 lambda = new LambdaExpression (expr, get_src (begin));
1379 expect_terminator ();
1384 foreach (string param in params) {
1385 lambda.add_parameter (param);
1387 return lambda;
1390 AssignmentOperator get_assignment_operator (TokenType token_type) {
1391 switch (token_type) {
1392 case TokenType.ASSIGN: return AssignmentOperator.SIMPLE;
1393 case TokenType.ASSIGN_ADD: return AssignmentOperator.ADD;
1394 case TokenType.ASSIGN_SUB: return AssignmentOperator.SUB;
1395 case TokenType.ASSIGN_BITWISE_OR: return AssignmentOperator.BITWISE_OR;
1396 case TokenType.ASSIGN_BITWISE_AND: return AssignmentOperator.BITWISE_AND;
1397 case TokenType.ASSIGN_BITWISE_XOR: return AssignmentOperator.BITWISE_XOR;
1398 case TokenType.ASSIGN_DIV: return AssignmentOperator.DIV;
1399 case TokenType.ASSIGN_MUL: return AssignmentOperator.MUL;
1400 case TokenType.ASSIGN_PERCENT: return AssignmentOperator.PERCENT;
1401 case TokenType.ASSIGN_SHIFT_LEFT: return AssignmentOperator.SHIFT_LEFT;
1402 default: return AssignmentOperator.NONE;
1406 Expression parse_expression () throws ParseError {
1407 if (current () == TokenType.DEF) {
1408 var lambda = parse_lambda_expression ();
1409 current_expr_is_lambda = true;
1410 return lambda;
1413 var begin = get_location ();
1414 Expression expr = parse_conditional_expression ();
1416 while (true) {
1417 var operator = get_assignment_operator (current ());
1418 if (operator != AssignmentOperator.NONE) {
1419 next ();
1420 var rhs = parse_expression ();
1421 expr = new Assignment (expr, rhs, operator, get_src (begin));
1422 } else if (current () == TokenType.OP_GT) { // >>=
1423 char* first_gt_pos = tokens[index].begin.pos;
1424 next ();
1425 // only accept >>= when there is no space between the two > signs
1426 if (current () == TokenType.OP_GE && tokens[index].begin.pos == first_gt_pos + 1) {
1427 next ();
1428 var rhs = parse_expression ();
1429 expr = new Assignment (expr, rhs, AssignmentOperator.SHIFT_RIGHT, get_src (begin));
1430 } else {
1431 prev ();
1432 break;
1434 } else {
1435 break;
1439 return expr;
1443 Statement get_for_statement_type () throws ParseError {
1445 var begin = get_location ();
1446 bool is_foreach = false;
1448 while (current () != TokenType.EOL && current () != TokenType.DO) {
1449 next ();
1450 if (accept (TokenType.IN)) {
1451 is_foreach = true;
1452 break;
1456 rollback (begin);
1458 if (is_foreach) {
1459 return parse_foreach_statement ();
1460 } else {
1461 return parse_for_statement ();
1466 void parse_statements (Block block) throws ParseError {
1467 while (current () != TokenType.DEDENT
1468 && current () != TokenType.WHEN
1469 && current () != TokenType.DEFAULT) {
1470 try {
1471 Statement stmt = null;
1472 bool is_decl = false;
1473 comment = scanner.pop_comment ();
1474 switch (current ()) {
1476 /* skip over requires and ensures as we handled them in method declaration */
1477 case TokenType.REQUIRES:
1478 case TokenType.ENSURES:
1479 var begin = get_location ();
1480 next ();
1482 if (accept (TokenType.EOL) && accept (TokenType.INDENT)) {
1483 while (current () != TokenType.DEDENT) {
1484 next();
1487 expect (TokenType.DEDENT);
1488 } else {
1489 while (current () != TokenType.EOL) {
1490 next();
1493 expect (TokenType.EOL);
1496 stmt = new EmptyStatement (get_src_com (begin));
1497 break;
1500 case TokenType.INDENT:
1501 stmt = parse_block ();
1502 break;
1503 case TokenType.SEMICOLON:
1504 case TokenType.PASS:
1505 stmt = parse_empty_statement ();
1506 break;
1507 case TokenType.PRINT:
1508 case TokenType.ASSERT:
1509 stmt = parse_expression_statement ();
1510 break;
1511 case TokenType.IF:
1512 stmt = parse_if_statement ();
1513 break;
1514 case TokenType.CASE:
1515 stmt = parse_switch_statement ();
1516 break;
1517 case TokenType.WHILE:
1518 stmt = parse_while_statement ();
1519 break;
1520 case TokenType.DO:
1521 stmt = parse_do_statement ();
1522 break;
1523 case TokenType.FOR:
1524 stmt = get_for_statement_type ();
1525 break;
1526 case TokenType.BREAK:
1527 stmt = parse_break_statement ();
1528 break;
1529 case TokenType.CONTINUE:
1530 stmt = parse_continue_statement ();
1531 break;
1532 case TokenType.RETURN:
1533 stmt = parse_return_statement ();
1534 break;
1535 case TokenType.RAISE:
1536 stmt = parse_throw_statement ();
1537 break;
1538 case TokenType.TRY:
1539 stmt = parse_try_statement ();
1540 break;
1541 case TokenType.LOCK:
1542 stmt = parse_lock_statement ();
1543 break;
1544 case TokenType.DELETE:
1545 stmt = parse_delete_statement ();
1546 break;
1547 case TokenType.VAR:
1548 is_decl = true;
1549 parse_local_variable_declarations (block);
1550 break;
1553 case TokenType.OP_INC:
1554 case TokenType.OP_DEC:
1555 case TokenType.SUPER:
1556 case TokenType.THIS:
1557 case TokenType.OPEN_PARENS:
1558 case TokenType.STAR:
1559 case TokenType.NEW:
1560 stmt = parse_expression_statement ();
1561 break;
1562 default:
1563 bool is_expr = is_expression ();
1564 if (is_expr) {
1565 stmt = parse_expression_statement ();
1566 } else {
1567 is_decl = true;
1568 parse_local_variable_declarations (block);
1570 break;
1573 if (!is_decl) {
1574 block.add_statement (stmt);
1576 } catch (ParseError e) {
1577 if (recover () != RecoveryState.STATEMENT_BEGIN) {
1578 // beginning of next declaration or end of file reached
1579 // return what we have so far
1580 break;
1586 bool is_expression () throws ParseError {
1587 var begin = get_location ();
1589 // decide between declaration and expression statement
1590 skip_type ();
1591 switch (current ()) {
1592 // invocation expression
1593 case TokenType.OPEN_PARENS:
1594 // postfix increment
1595 case TokenType.OP_INC:
1596 // postfix decrement
1597 case TokenType.OP_DEC:
1598 // assignments
1599 case TokenType.ASSIGN:
1600 case TokenType.ASSIGN_ADD:
1601 case TokenType.ASSIGN_BITWISE_AND:
1602 case TokenType.ASSIGN_BITWISE_OR:
1603 case TokenType.ASSIGN_BITWISE_XOR:
1604 case TokenType.ASSIGN_DIV:
1605 case TokenType.ASSIGN_MUL:
1606 case TokenType.ASSIGN_PERCENT:
1607 case TokenType.ASSIGN_SHIFT_LEFT:
1608 case TokenType.ASSIGN_SUB:
1609 case TokenType.OP_GT: // >>=
1610 // member access
1611 case TokenType.DOT:
1612 // pointer member access
1613 case TokenType.OP_PTR:
1614 rollback (begin);
1615 return true;
1616 default:
1617 rollback (begin);
1618 return false;
1622 Block parse_embedded_statement () throws ParseError {
1623 if (current () == TokenType.INDENT) {
1624 var block = parse_block ();
1625 return block;
1628 comment = scanner.pop_comment ();
1630 var block = new Block (get_src_com (get_location ()));
1631 block.add_statement (parse_embedded_statement_without_block ());
1632 return block;
1636 Statement parse_embedded_statement_without_block () throws ParseError {
1637 switch (current ()) {
1638 case TokenType.PASS:
1639 case TokenType.SEMICOLON: return parse_empty_statement ();
1640 case TokenType.IF: return parse_if_statement ();
1641 case TokenType.CASE: return parse_switch_statement ();
1642 case TokenType.WHILE: return parse_while_statement ();
1643 case TokenType.DO: return parse_do_statement ();
1644 case TokenType.FOR: return get_for_statement_type ();
1645 case TokenType.BREAK: return parse_break_statement ();
1646 case TokenType.CONTINUE: return parse_continue_statement ();
1647 case TokenType.RETURN: return parse_return_statement ();
1648 case TokenType.RAISE: return parse_throw_statement ();
1649 case TokenType.TRY: return parse_try_statement ();
1650 case TokenType.LOCK: return parse_lock_statement ();
1651 case TokenType.DELETE: return parse_delete_statement ();
1652 default: return parse_expression_statement ();
1656 Block parse_block () throws ParseError {
1657 var begin = get_location ();
1658 expect (TokenType.INDENT);
1659 var block = new Block (get_src_com (begin));
1660 parse_statements (block);
1661 if (!accept (TokenType.DEDENT)) {
1662 // only report error if it's not a secondary error
1663 if (context.report.get_errors () == 0) {
1664 Report.error (get_current_src (), "tab indentation is incorrect");
1668 return block;
1671 Statement parse_empty_statement () throws ParseError {
1672 var begin = get_location ();
1674 accept (TokenType.PASS);
1675 accept (TokenType.SEMICOLON);
1676 expect_terminator ();
1678 return new EmptyStatement (get_src_com (begin));
1681 void add_local_var_variable (Block block, string id) throws ParseError {
1682 DataType type_copy = null;
1683 var local = parse_local_variable (type_copy, id);
1684 block.add_statement (new DeclarationStatement (local, local.source_reference));
1687 void parse_local_variable_declarations (Block block) throws ParseError {
1688 if (accept (TokenType.VAR)) {
1689 /* support block vars */
1690 if (accept (TokenType.EOL) && accept (TokenType.INDENT)) {
1691 while (current () != TokenType.DEDENT) {
1692 var s = parse_identifier ();
1693 add_local_var_variable (block, s);
1694 accept (TokenType.EOL);
1695 accept (TokenType.SEMICOLON);
1698 expect (TokenType.DEDENT);
1699 } else {
1700 var s = parse_identifier ();
1701 add_local_var_variable (block, s);
1702 expect_terminator ();
1705 return;
1708 var id_list = new ArrayList<string> ();
1709 DataType variable_type = null;
1711 do {
1712 id_list.add (parse_identifier ());
1713 } while (accept (TokenType.COMMA));
1715 expect (TokenType.COLON);
1717 variable_type = parse_type ();
1719 foreach (string id in id_list) {
1720 DataType type_copy = null;
1721 if (variable_type != null) {
1722 type_copy = variable_type.copy ();
1724 var local = parse_local_variable (type_copy, id);
1725 block.add_statement (new DeclarationStatement (local, local.source_reference));
1728 expect_terminator ();
1731 LocalVariable parse_local_variable (DataType? variable_type, string id) throws ParseError {
1732 var begin = get_location ();
1733 Expression initializer = null;
1734 if (accept (TokenType.ASSIGN)) {
1735 initializer = parse_variable_initializer ();
1737 return new LocalVariable (variable_type, id, initializer, get_src_com (begin));
1740 Statement parse_expression_statement () throws ParseError {
1741 var begin = get_location ();
1742 var expr = parse_statement_expression ();
1744 if (current_expr_is_lambda) {
1745 current_expr_is_lambda = false;
1746 } else {
1747 expect_terminator ();
1750 return new ExpressionStatement (expr, get_src_com (begin));
1753 Expression parse_statement_expression () throws ParseError {
1754 // invocation expression, assignment,
1755 // or pre/post increment/decrement expression
1756 var expr = parse_expression ();
1757 return expr;
1760 Statement parse_if_statement () throws ParseError {
1761 var begin = get_location ();
1763 expect (TokenType.IF);
1765 var condition = parse_expression ();
1767 if (!accept (TokenType.DO)) {
1768 expect (TokenType.EOL);
1769 } else {
1770 accept (TokenType.EOL);
1773 var src = get_src_com (begin);
1774 var true_stmt = parse_embedded_statement ();
1775 Block false_stmt = null;
1776 if (accept (TokenType.ELSE)) {
1777 // allow `else if' on the same line without `do'
1778 if (!accept (TokenType.DO) && current () != TokenType.IF) {
1779 expect (TokenType.EOL);
1780 } else {
1781 accept (TokenType.EOL);
1784 false_stmt = parse_embedded_statement ();
1786 return new IfStatement (condition, true_stmt, false_stmt, src);
1789 Statement parse_switch_statement () throws ParseError {
1790 var begin = get_location ();
1791 expect (TokenType.CASE);
1792 var condition = parse_expression ();
1794 expect (TokenType.EOL);
1796 var stmt = new SwitchStatement (condition, get_src_com (begin));
1797 expect (TokenType.INDENT);
1798 while (current () != TokenType.DEDENT) {
1799 var section = new SwitchSection (get_src_com (begin));
1801 if (accept (TokenType.WHEN)) {
1802 do {
1803 section.add_label (new SwitchLabel (parse_expression (), get_src_com (begin)));
1805 while (accept (TokenType.COMMA));
1806 } else {
1807 expect (TokenType.DEFAULT);
1808 section.add_label (new SwitchLabel.with_default (get_src_com (begin)));
1811 if (!accept (TokenType.EOL)) {
1812 expect (TokenType.DO);
1815 parse_statements (section);
1817 /* add break statement for each block */
1818 var break_stmt = new BreakStatement (get_src_com (begin));
1819 section.add_statement (break_stmt);
1821 stmt.add_section (section);
1823 expect (TokenType.DEDENT);
1824 return stmt;
1827 Statement parse_while_statement () throws ParseError {
1828 var begin = get_location ();
1829 expect (TokenType.WHILE);
1830 var condition = parse_expression ();
1832 if (!accept (TokenType.DO)) {
1833 expect (TokenType.EOL);
1834 } else {
1835 accept (TokenType.EOL);
1838 var body = parse_embedded_statement ();
1839 return new WhileStatement (condition, body, get_src_com (begin));
1842 Statement parse_do_statement () throws ParseError {
1843 var begin = get_location ();
1844 expect (TokenType.DO);
1845 expect (TokenType.EOL);
1846 var body = parse_embedded_statement ();
1847 expect (TokenType.WHILE);
1849 var condition = parse_expression ();
1851 expect_terminator ();
1853 return new DoStatement (body, condition, get_src_com (begin));
1857 Statement parse_for_statement () throws ParseError {
1858 var begin = get_location ();
1859 Block block = null;
1860 Expression initializer = null;
1861 Expression condition = null;
1862 Expression iterator = null;
1863 bool is_expr;
1864 string id;
1866 expect (TokenType.FOR);
1868 switch (current ()) {
1869 case TokenType.VAR:
1870 is_expr = false;
1871 break;
1872 default:
1874 bool local_is_expr = is_expression ();
1875 is_expr = local_is_expr;
1876 break;
1879 if (is_expr) {
1880 var expr_begin = get_location ();
1881 id = parse_identifier ();
1882 rollback (expr_begin);
1883 initializer = parse_statement_expression ();
1884 } else {
1885 block = new Block (get_src (begin));
1886 DataType variable_type;
1887 if (accept (TokenType.VAR)) {
1888 variable_type = null;
1889 id = parse_identifier ();
1890 } else {
1891 id = parse_identifier ();
1892 expect (TokenType.COLON);
1893 variable_type = parse_type ();
1896 DataType type_copy = null;
1897 if (variable_type != null) {
1898 type_copy = variable_type.copy ();
1900 var local = parse_local_variable (type_copy, id);
1902 block.add_statement (new DeclarationStatement (local, local.source_reference));
1907 if (accept (TokenType.TO)) {
1908 /* create expression for condition and incrementing iterator */
1909 var to_begin = get_location ();
1910 var to_src = get_src (to_begin);
1911 var left = new MemberAccess (null, id, to_src);
1912 var right = parse_primary_expression ();
1914 condition = new BinaryExpression (BinaryOperator.LESS_THAN_OR_EQUAL, left, right, to_src);
1916 iterator = new PostfixExpression (left, true, to_src);
1917 } else {
1918 expect (TokenType.DOWNTO);
1919 var downto_begin = get_location ();
1920 var downto_src = get_src (downto_begin);
1921 /* create expression for condition and decrementing iterator */
1922 var left = new MemberAccess (null, id, downto_src);
1923 var right = parse_primary_expression ();
1925 condition = new BinaryExpression (BinaryOperator.GREATER_THAN_OR_EQUAL, left, right, downto_src);
1927 iterator = new PostfixExpression (left, false, downto_src);
1930 if (!accept (TokenType.EOL)) {
1931 expect (TokenType.DO);
1934 var src = get_src_com (begin);
1935 var body = parse_embedded_statement ();
1936 var stmt = new ForStatement (condition, body, src);
1938 if (initializer != null) stmt.add_initializer (initializer);
1940 stmt.add_iterator (iterator);
1943 if (block != null) {
1944 block.add_statement (stmt);
1945 return block;
1946 } else {
1947 return stmt;
1951 Statement parse_foreach_statement () throws ParseError {
1952 var begin = get_location ();
1953 DataType type = null;
1954 string id = null;
1956 expect (TokenType.FOR);
1958 if (accept (TokenType.VAR)) {
1959 id = parse_identifier ();
1960 } else {
1961 id = parse_identifier ();
1962 if (accept (TokenType.COLON)) {
1963 type = parse_type ();
1967 expect (TokenType.IN);
1968 var collection = parse_expression ();
1969 if (!accept (TokenType.EOL)) {
1970 expect (TokenType.DO);
1972 var src = get_src_com (begin);
1973 var body = parse_embedded_statement ();
1974 return new ForeachStatement (type, id, collection, body, src);
1977 Statement parse_break_statement () throws ParseError {
1978 var begin = get_location ();
1979 expect (TokenType.BREAK);
1980 expect_terminator ();
1981 return new BreakStatement (get_src_com (begin));
1984 Statement parse_continue_statement () throws ParseError {
1985 var begin = get_location ();
1986 expect (TokenType.CONTINUE);
1987 expect_terminator ();
1988 return new ContinueStatement (get_src_com (begin));
1991 Statement parse_return_statement () throws ParseError {
1992 var begin = get_location ();
1993 expect (TokenType.RETURN);
1994 Expression expr = null;
1995 if (current () != TokenType.SEMICOLON && current () != TokenType.EOL) {
1996 expr = parse_expression ();
1998 expect_terminator ();
1999 return new ReturnStatement (expr, get_src_com (begin));
2002 Statement parse_throw_statement () throws ParseError {
2003 var begin = get_location ();
2004 expect (TokenType.RAISE);
2005 var expr = parse_expression ();
2006 expect_terminator ();
2007 return new ThrowStatement (expr, get_src_com (begin));
2010 Statement parse_try_statement () throws ParseError {
2011 var begin = get_location ();
2012 expect (TokenType.TRY);
2013 expect (TokenType.EOL);
2014 var try_block = parse_block ();
2015 Block finally_clause = null;
2016 var catch_clauses = new ArrayList<CatchClause> ();
2017 if (current () == TokenType.EXCEPT) {
2018 parse_catch_clauses (catch_clauses);
2019 if (current () == TokenType.FINALLY) {
2020 finally_clause = parse_finally_clause ();
2022 } else {
2023 finally_clause = parse_finally_clause ();
2025 var stmt = new TryStatement (try_block, finally_clause, get_src_com (begin));
2026 foreach (CatchClause clause in catch_clauses) {
2027 stmt.add_catch_clause (clause);
2029 return stmt;
2032 void parse_catch_clauses (Gee.List<CatchClause> catch_clauses) throws ParseError {
2033 while (accept (TokenType.EXCEPT)) {
2034 var begin = get_location ();
2035 DataType type = null;
2036 string id = null;
2037 if (!accept (TokenType.EOL)) {
2038 id = parse_identifier ();
2039 expect (TokenType.COLON);
2040 type = parse_type ();
2041 expect (TokenType.EOL);
2044 var block = parse_block ();
2045 catch_clauses.add (new CatchClause (type, id, block, get_src (begin)));
2049 Block parse_finally_clause () throws ParseError {
2050 expect (TokenType.FINALLY);
2051 accept_block ();
2052 var block = parse_block ();
2053 return block;
2056 Statement parse_lock_statement () throws ParseError {
2057 var begin = get_location ();
2058 expect (TokenType.LOCK);
2059 expect (TokenType.OPEN_PARENS);
2060 var expr = parse_expression ();
2061 expect (TokenType.CLOSE_PARENS);
2062 var stmt = parse_embedded_statement ();
2063 return new LockStatement (expr, stmt, get_src_com (begin));
2066 Statement parse_delete_statement () throws ParseError {
2067 var begin = get_location ();
2068 expect (TokenType.DELETE);
2069 var expr = parse_expression ();
2070 expect_terminator ();
2071 return new DeleteStatement (expr, get_src_com (begin));
2074 Gee.List<Attribute>? parse_attributes () throws ParseError {
2075 if (current () != TokenType.OPEN_BRACKET) {
2076 return null;
2078 var attrs = new ArrayList<Attribute> ();
2079 while (accept (TokenType.OPEN_BRACKET)) {
2080 do {
2081 var begin = get_location ();
2082 string id = parse_identifier ();
2083 var attr = new Attribute (id, get_src (begin));
2084 if (accept (TokenType.OPEN_PARENS)) {
2085 if (current () != TokenType.CLOSE_PARENS) {
2086 do {
2087 id = parse_identifier ();
2088 expect (TokenType.ASSIGN);
2089 var expr = parse_expression ();
2090 attr.add_argument (id, expr);
2091 } while (accept (TokenType.COMMA));
2093 expect (TokenType.CLOSE_PARENS);
2095 attrs.add (attr);
2096 } while (accept (TokenType.COMMA));
2097 expect (TokenType.CLOSE_BRACKET);
2099 expect (TokenType.EOL);
2101 return attrs;
2104 void set_attributes (CodeNode node, Gee.List<Attribute>? attributes) {
2105 if (attributes != null) {
2106 foreach (Attribute attr in (Gee.List<Attribute>) attributes) {
2107 node.attributes.append (attr);
2112 Symbol parse_declaration (bool is_root = false) throws ParseError {
2113 comment = scanner.pop_comment ();
2114 var attrs = parse_attributes ();
2116 switch (current ()) {
2117 case TokenType.CONST:
2118 return parse_constant_declaration (attrs);
2119 case TokenType.CONSTRUCT:
2120 return parse_creation_method_declaration (attrs);
2121 case TokenType.CLASS:
2122 return parse_class_declaration (attrs);
2123 case TokenType.INIT:
2124 if (is_root) {
2125 return parse_main_method_declaration (attrs);
2127 return parse_constructor_declaration (attrs);
2128 case TokenType.DELEGATE:
2129 return parse_delegate_declaration (attrs);
2130 case TokenType.DEF:
2131 return parse_method_declaration (attrs);
2132 case TokenType.ENUM:
2133 return parse_enum_declaration (attrs);
2134 case TokenType.ERRORDOMAIN:
2135 return parse_errordomain_declaration (attrs);
2136 case TokenType.FINAL:
2137 return parse_destructor_declaration (attrs);
2138 case TokenType.INTERFACE:
2139 return parse_interface_declaration (attrs);
2140 case TokenType.NAMESPACE:
2141 return parse_namespace_declaration (attrs);
2142 case TokenType.PROP:
2143 return parse_property_declaration (attrs);
2144 case TokenType.EVENT:
2145 return parse_signal_declaration (attrs);
2146 case TokenType.STRUCT:
2147 return parse_struct_declaration (attrs);
2148 default:
2149 var begin = get_location ();
2150 while (current () != TokenType.EOL && current () != TokenType.SEMICOLON && current () != TokenType.EOF) {
2151 if (current () == TokenType.COLON) {
2152 rollback (begin);
2153 return parse_field_declaration (attrs);
2154 } else {
2155 next ();
2158 rollback (begin);
2160 break;
2163 TokenType cur = current ();
2164 TokenType pre = tokens[index-1].type;
2166 throw new ParseError.SYNTAX (get_error ("expected declaration but got %s with previous %s".printf (cur.to_string (), pre.to_string())));
2169 void parse_declarations (Symbol parent, bool root = false) throws ParseError {
2170 if (!root) {
2171 expect (TokenType.INDENT);
2173 while (current () != TokenType.DEDENT && current () != TokenType.EOF) {
2174 try {
2175 if (parent is Namespace) {
2176 parse_namespace_member ((Namespace) parent);
2177 } else if (parent is Class) {
2178 parse_class_member ((Class) parent);
2179 } else if (parent is Struct) {
2180 parse_struct_member ((Struct) parent);
2181 } else if (parent is Interface) {
2182 parse_interface_member ((Interface) parent);
2184 } catch (ParseError e) {
2185 int r;
2186 do {
2187 r = recover ();
2188 if (r == RecoveryState.STATEMENT_BEGIN) {
2189 next ();
2190 } else {
2191 break;
2193 } while (true);
2194 if (r == RecoveryState.EOF) {
2195 return;
2199 if (!root) {
2200 if (!accept (TokenType.DEDENT)) {
2201 // only report error if it's not a secondary error
2202 if (context.report.get_errors () == 0) {
2203 Report.error (get_current_src (), "expected dedent");
2209 enum RecoveryState {
2210 EOF,
2211 DECLARATION_BEGIN,
2212 STATEMENT_BEGIN
2215 RecoveryState recover () {
2216 while (current () != TokenType.EOF) {
2217 switch (current ()) {
2218 case TokenType.CLASS:
2219 case TokenType.CONST:
2220 case TokenType.CONSTRUCT:
2221 case TokenType.INIT:
2222 case TokenType.DEF:
2223 case TokenType.DELEGATE:
2224 case TokenType.ENUM:
2225 case TokenType.ERRORDOMAIN:
2226 case TokenType.FINAL:
2227 case TokenType.INTERFACE:
2228 case TokenType.NAMESPACE:
2229 case TokenType.PROP:
2230 case TokenType.EVENT:
2231 case TokenType.STRUCT:
2232 return RecoveryState.DECLARATION_BEGIN;
2233 case TokenType.BREAK:
2234 case TokenType.CASE:
2235 case TokenType.CONTINUE:
2236 case TokenType.DELETE:
2237 case TokenType.DO:
2238 case TokenType.FOR:
2239 case TokenType.IF:
2240 case TokenType.LOCK:
2241 case TokenType.RETURN:
2242 case TokenType.RAISE:
2243 case TokenType.TRY:
2244 case TokenType.VAR:
2245 case TokenType.WHILE:
2246 return RecoveryState.STATEMENT_BEGIN;
2247 default:
2248 next ();
2249 break;
2252 return RecoveryState.EOF;
2255 Namespace parse_namespace_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2256 var begin = get_location ();
2257 expect (TokenType.NAMESPACE);
2258 var sym = parse_symbol_name ();
2259 var ns = new Namespace (sym.name, get_src_com (begin));
2260 set_attributes (ns, attrs);
2261 expect (TokenType.EOL);
2262 parse_declarations (ns);
2263 return ns;
2266 void parse_namespace_member (Namespace ns) throws ParseError {
2268 var sym = parse_declaration ((ns == context.root));
2269 if (sym is Namespace) {
2270 ns.add_namespace ((Namespace) sym);
2271 } else if (sym is Class) {
2272 ns.add_class ((Class) sym);
2273 } else if (sym is Interface) {
2274 ns.add_interface ((Interface) sym);
2275 } else if (sym is Struct) {
2276 ns.add_struct ((Struct) sym);
2277 } else if (sym is Enum) {
2278 ns.add_enum ((Enum) sym);
2279 } else if (sym is ErrorDomain) {
2280 ns.add_error_domain ((ErrorDomain) sym);
2281 } else if (sym is Delegate) {
2282 ns.add_delegate ((Delegate) sym);
2283 } else if (sym is Method) {
2284 var method = (Method) sym;
2285 if (method.binding == MemberBinding.INSTANCE) {
2286 method.binding = MemberBinding.STATIC;
2288 ns.add_method (method);
2289 } else if (sym is Field) {
2290 var field = (Field) sym;
2291 if (field.binding == MemberBinding.INSTANCE) {
2292 field.binding = MemberBinding.STATIC;
2294 ns.add_field (field);
2295 } else if (sym is Constant) {
2296 ns.add_constant ((Constant) sym);
2297 } else {
2298 Report.error (sym.source_reference, "unexpected declaration in namespace");
2300 scanner.source_file.add_node (sym);
2304 void add_uses_clause () throws ParseError {
2305 var begin = get_location ();
2306 var sym = parse_symbol_name ();
2307 var ns_ref = new UsingDirective (sym, get_src (begin));
2309 scanner.source_file.add_using_directive (ns_ref);
2312 void parse_using_directives () throws ParseError {
2313 while (accept (TokenType.USES)) {
2314 if (accept_block ()) {
2315 expect (TokenType.INDENT);
2317 while (current () != TokenType.DEDENT && current () != TokenType.EOF) {
2318 add_uses_clause ();
2319 expect (TokenType.EOL);
2322 expect (TokenType.DEDENT);
2323 } else {
2324 do {
2325 add_uses_clause ();
2326 } while (accept (TokenType.COMMA));
2328 expect_terminator ();
2334 Symbol parse_class_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2335 var begin = get_location ();
2336 expect (TokenType.CLASS);
2338 var flags = parse_type_declaration_modifiers ();
2340 var sym = parse_symbol_name ();
2341 var type_param_list = parse_type_parameter_list ();
2342 var base_types = new ArrayList<DataType> ();
2343 if (accept (TokenType.COLON)) {
2344 base_types.add (parse_type ());
2346 if (accept (TokenType.IMPLEMENTS)) {
2347 do {
2348 base_types.add (parse_type ());
2349 } while (accept (TokenType.COMMA));
2353 accept (TokenType.EOL);
2355 var cl = new Class (sym.name, get_src_com (begin));
2357 if (ModifierFlags.PRIVATE in flags) {
2358 cl.access = SymbolAccessibility.PRIVATE;
2359 } else {
2360 /* class must always be Public unless its name starts wtih underscore */
2361 if (sym.name[0] == '_') {
2362 cl.access = SymbolAccessibility.PRIVATE;
2363 } else {
2364 cl.access = SymbolAccessibility.PUBLIC;
2368 if (ModifierFlags.ABSTRACT in flags) {
2369 cl.is_abstract = true;
2371 set_attributes (cl, attrs);
2372 foreach (TypeParameter type_param in type_param_list) {
2373 cl.add_type_parameter (type_param);
2375 foreach (DataType base_type in base_types) {
2376 cl.add_base_type (base_type);
2379 class_name = cl.name;
2381 parse_declarations (cl);
2383 // ensure there is always a default construction method
2384 if (!scanner.source_file.external_package
2385 && !cl.is_abstract
2386 && cl.default_construction_method == null) {
2387 var m = new CreationMethod (cl.name, null, cl.source_reference);
2388 m.binding = MemberBinding.STATIC;
2389 m.access = SymbolAccessibility.PUBLIC;
2390 m.body = new Block (cl.source_reference);
2391 cl.add_method (m);
2394 Symbol result = cl;
2395 while (sym.inner != null) {
2396 sym = sym.inner;
2397 var ns = new Namespace (sym.name, cl.source_reference);
2398 if (result is Namespace) {
2399 ns.add_namespace ((Namespace) result);
2400 } else {
2401 ns.add_class ((Class) result);
2402 scanner.source_file.add_node (result);
2404 result = ns;
2406 return result;
2409 void parse_class_member (Class cl) throws ParseError {
2410 var sym = parse_declaration ();
2411 if (sym is Class) {
2412 cl.add_class ((Class) sym);
2413 } else if (sym is Struct) {
2414 cl.add_struct ((Struct) sym);
2415 } else if (sym is Enum) {
2416 cl.add_enum ((Enum) sym);
2417 } else if (sym is Delegate) {
2418 cl.add_delegate ((Delegate) sym);
2419 } else if (sym is Method) {
2420 cl.add_method ((Method) sym);
2421 } else if (sym is Vala.Signal) {
2422 cl.add_signal ((Vala.Signal) sym);
2423 } else if (sym is Field) {
2424 cl.add_field ((Field) sym);
2425 } else if (sym is Constant) {
2426 cl.add_constant ((Constant) sym);
2427 } else if (sym is Property) {
2428 cl.add_property ((Property) sym);
2429 } else if (sym is Constructor) {
2430 var c = (Constructor) sym;
2431 if (c.binding == MemberBinding.INSTANCE) {
2432 cl.constructor = c;
2433 } else if (c.binding == MemberBinding.CLASS) {
2434 cl.class_constructor = c;
2435 } else {
2436 cl.static_constructor = c;
2438 } else if (sym is Destructor) {
2439 cl.destructor = (Destructor) sym;
2440 } else {
2441 Report.error (sym.source_reference, "unexpected declaration in class");
2445 Constant parse_constant_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2446 var begin = get_location ();
2448 expect (TokenType.CONST);
2450 parse_member_declaration_modifiers ();
2452 string id = parse_identifier ();
2453 expect (TokenType.COLON);
2454 var type = parse_type (false);
2456 Expression initializer = null;
2457 if (accept (TokenType.ASSIGN)) {
2458 initializer = parse_variable_initializer ();
2460 expect_terminator ();
2462 // constant arrays don't own their element
2463 var array_type = type as ArrayType;
2464 if (array_type != null) {
2465 array_type.element_type.value_owned = false;
2468 var c = new Constant (id, type, initializer, get_src_com (begin));
2469 c.access = get_access (id);
2470 set_attributes (c, attrs);
2471 return c;
2474 Field parse_field_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2475 var begin = get_location ();
2476 string id = parse_identifier ();
2477 expect (TokenType.COLON);
2479 var flags = parse_member_declaration_modifiers ();
2481 var type = parse_type ();
2483 var f = new Field (id, type, null, get_src_com (begin));
2485 if (ModifierFlags.ABSTRACT in flags || ModifierFlags.VIRTUAL in flags || ModifierFlags.OVERRIDE in flags) {
2486 Report.error (f.source_reference, "abstract, virtual, and override modifiers are not applicable to fields");
2489 if (ModifierFlags.PRIVATE in flags) {
2490 f.access = SymbolAccessibility.PRIVATE;
2491 } else {
2492 f.access = get_access (id);
2495 set_attributes (f, attrs);
2497 if (accept (TokenType.ASSIGN)) {
2498 f.initializer = parse_expression ();
2501 if (ModifierFlags.STATIC in flags) {
2502 f.binding = MemberBinding.STATIC;
2503 } else if (ModifierFlags.CLASS in flags) {
2504 f.binding = MemberBinding.CLASS;
2507 expect_terminator ();
2509 return f;
2512 InitializerList parse_initializer () throws ParseError {
2513 var begin = get_location ();
2514 if (!accept (TokenType.OPEN_PARENS)) {
2515 expect (TokenType.OPEN_BRACE);
2517 var initializer = new InitializerList (get_src (begin));
2518 if (current () != TokenType.DEDENT) {
2519 do {
2520 var init = parse_variable_initializer ();
2521 initializer.append (init);
2522 } while (accept (TokenType.COMMA));
2524 if (!accept (TokenType.CLOSE_PARENS)) {
2525 expect (TokenType.CLOSE_BRACE);
2527 return initializer;
2530 bool is_initializer () throws ParseError {
2531 if (current () == TokenType.OPEN_BRACE) {
2532 return true;
2536 if (current () == TokenType.OPEN_PARENS) {
2537 var begin = get_location ();
2538 var is_array = false;
2540 next ();
2542 var expr = parse_expression ();
2543 is_array = (accept (TokenType.COMMA));
2545 rollback (begin);
2547 return is_array;
2551 return false;
2555 Expression parse_variable_initializer () throws ParseError {
2556 if (is_initializer ()) {
2557 var expr = parse_initializer ();
2558 return expr;
2559 } else {
2560 var expr = parse_expression ();
2561 return expr;
2566 Method parse_main_method_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2567 var id = "main";
2568 var begin = get_location ();
2569 DataType type = new VoidType ();
2570 expect (TokenType.INIT);
2572 var method = new Method (id, type, get_src_com (begin));
2573 method.access = SymbolAccessibility.PUBLIC;
2575 set_attributes (method, attrs);
2577 method.binding = MemberBinding.STATIC;
2579 var sym = new UnresolvedSymbol (null, "string", get_src (begin));
2580 type = new UnresolvedType.from_symbol (sym, get_src (begin));
2581 type.value_owned = true;
2582 type = new ArrayType (type, 1, get_src (begin));
2583 type.nullable = false;
2585 var param = new FormalParameter ("args", type, get_src (begin));
2586 method.add_parameter (param);
2589 expect (TokenType.EOL);
2591 if (accept_block ()) {
2592 method.body = parse_block ();
2595 return method;
2598 Method parse_method_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2599 var begin = get_location ();
2600 DataType type = new VoidType ();
2601 expect (TokenType.DEF);
2602 var flags = parse_member_declaration_modifiers ();
2604 string id = parse_identifier ();
2606 var params = new ArrayList<FormalParameter> ();
2607 expect (TokenType.OPEN_PARENS);
2609 if (current () != TokenType.CLOSE_PARENS) {
2610 do {
2611 var param = parse_parameter ();
2612 params.add (param);
2613 } while (accept (TokenType.COMMA));
2616 expect (TokenType.CLOSE_PARENS);
2619 /* deal with return value */
2620 if (accept (TokenType.COLON)) {
2621 type = parse_type ();
2622 parse_type_parameter_list ();
2626 var method = new Method (id, type, get_src_com (begin));
2627 if (ModifierFlags.PRIVATE in flags) {
2628 method.access = SymbolAccessibility.PRIVATE;
2629 } else {
2630 method.access = get_access (id);
2634 set_attributes (method, attrs);
2636 foreach (FormalParameter param in params) {
2637 method.add_parameter (param);
2640 if (accept (TokenType.RAISES)) {
2641 do {
2642 method.add_error_type (parse_type ());
2643 } while (accept (TokenType.COMMA));
2647 if (ModifierFlags.STATIC in flags || id == "main") {
2648 method.binding = MemberBinding.STATIC;
2650 if (ModifierFlags.ABSTRACT in flags) {
2651 method.is_abstract = true;
2653 if (ModifierFlags.VIRTUAL in flags) {
2654 method.is_virtual = true;
2656 if (ModifierFlags.OVERRIDE in flags) {
2657 method.overrides = true;
2659 if (ModifierFlags.INLINE in flags) {
2660 method.is_inline = true;
2663 expect (TokenType.EOL);
2665 var body_location = get_location ();
2668 /* "requires" and "ensures" if present will be at start of the method body */
2669 if (accept (TokenType.INDENT)) {
2670 if (accept (TokenType.REQUIRES)) {
2672 if (accept (TokenType.EOL) && accept (TokenType.INDENT)) {
2673 while (current() != TokenType.DEDENT) {
2674 method.add_precondition (parse_expression ());
2675 expect (TokenType.EOL);
2678 expect (TokenType.DEDENT);
2679 accept_terminator ();
2680 } else {
2682 method.add_precondition (parse_expression ());
2683 expect_terminator ();
2689 if (accept (TokenType.ENSURES)) {
2690 if (accept (TokenType.EOL) && accept (TokenType.INDENT)) {
2691 while (current() != TokenType.DEDENT) {
2692 method.add_postcondition (parse_expression ());
2693 expect (TokenType.EOL);
2696 expect (TokenType.DEDENT);
2697 accept_terminator ();
2698 } else {
2699 method.add_postcondition (parse_expression ());
2700 expect_terminator ();
2705 rollback (body_location);
2708 if (accept_block ()) {
2709 method.body = parse_block ();
2711 return method;
2714 Property parse_property_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2715 var begin = get_location ();
2716 var readonly = false;
2718 expect (TokenType.PROP);
2720 var flags = parse_member_declaration_modifiers ();
2722 readonly = accept (TokenType.READONLY);
2724 string id = parse_identifier ();
2725 expect (TokenType.COLON);
2727 bool is_weak = accept (TokenType.WEAK);
2728 var type = parse_type (false);
2730 var prop = new Property (id, type, null, null, get_src_com (begin));
2731 if (ModifierFlags.PRIVATE in flags) {
2732 prop.access = SymbolAccessibility.PRIVATE;
2733 } else {
2734 prop.access = get_access (id);
2737 set_attributes (prop, attrs);
2738 if (ModifierFlags.ABSTRACT in flags) {
2739 prop.is_abstract = true;
2741 if (ModifierFlags.VIRTUAL in flags) {
2742 prop.is_virtual = true;
2744 if (ModifierFlags.OVERRIDE in flags) {
2745 prop.overrides = true;
2748 if (accept (TokenType.ASSIGN)) {
2749 prop.default_expression = parse_expression ();
2753 if (accept_block ()) {
2754 expect (TokenType.INDENT);
2755 while (current () != TokenType.DEDENT) {
2756 var accessor_begin = get_location ();
2757 parse_attributes ();
2759 var value_type = type.copy ();
2760 value_type.value_owned = false;
2762 if (accept (TokenType.GET)) {
2763 if (prop.get_accessor != null) {
2764 throw new ParseError.SYNTAX (get_error ("property get accessor already defined"));
2766 Block block = null;
2767 if (accept_block ()) {
2768 block = parse_block ();
2770 prop.get_accessor = new PropertyAccessor (true, false, false, type.copy (), block, get_src (accessor_begin));
2771 prop.get_accessor.access = SymbolAccessibility.PUBLIC;
2772 } else {
2773 bool _construct = false;
2774 if (accept (TokenType.SET)) {
2775 if (readonly) {
2776 throw new ParseError.SYNTAX (get_error ("set block not allowed for a read only property"));
2778 _construct = accept (TokenType.CONSTRUCT);
2779 } else if (accept (TokenType.CONSTRUCT)) {
2780 _construct = true;
2781 } else if (!accept (TokenType.EOL)) {
2782 throw new ParseError.SYNTAX (get_error ("expected get, set, or construct"));
2785 if (prop.set_accessor != null) {
2786 throw new ParseError.SYNTAX (get_error ("property set accessor already defined"));
2789 Block block = null;
2790 if (accept_block ()) {
2791 block = parse_block ();
2793 prop.set_accessor = new PropertyAccessor (false, !readonly, _construct, value_type, block, get_src (accessor_begin));
2794 prop.set_accessor.access = SymbolAccessibility.PUBLIC;
2797 accept (TokenType.EOL);
2798 expect (TokenType.DEDENT);
2799 } else {
2800 var value_type = type.copy ();
2801 value_type.value_owned = false;
2803 prop.get_accessor = new PropertyAccessor (true, false, false, value_type, null, get_src (begin));
2804 prop.get_accessor.access = SymbolAccessibility.PUBLIC;
2806 if (!readonly) {
2807 value_type = type.copy ();
2808 value_type.value_owned = false;
2810 prop.set_accessor = new PropertyAccessor (false, true, false, value_type, null, get_src (begin));
2811 prop.set_accessor.access = SymbolAccessibility.PUBLIC;
2815 expect_terminator ();
2818 if (!prop.is_abstract && !scanner.source_file.external_package) {
2819 var needs_var = (readonly && (prop.get_accessor != null && prop.get_accessor.body == null));
2821 if (!needs_var) {
2822 needs_var = (prop.get_accessor != null && prop.get_accessor.body == null) || (prop.set_accessor != null && prop.set_accessor.body == null);
2825 if (needs_var) {
2826 /* automatic property accessor body generation */
2827 var field_type = prop.property_type.copy ();
2828 field_type.value_owned = !is_weak;
2829 prop.field = new Field ("_%s".printf (prop.name), field_type, prop.default_expression, prop.source_reference);
2830 prop.field.access = SymbolAccessibility.PRIVATE;
2834 return prop;
2837 Vala.Signal parse_signal_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2838 var begin = get_location ();
2839 DataType type;
2841 expect (TokenType.EVENT);
2842 var flags = parse_member_declaration_modifiers ();
2843 string id = parse_identifier ();
2846 var params = new ArrayList<FormalParameter> ();
2848 expect (TokenType.OPEN_PARENS);
2849 if (current () != TokenType.CLOSE_PARENS) {
2850 do {
2851 var param = parse_parameter ();
2852 params.add (param);
2853 } while (accept (TokenType.COMMA));
2855 expect (TokenType.CLOSE_PARENS);
2857 if (accept (TokenType.COLON)) {
2858 type = parse_type ();
2859 } else {
2860 type = new VoidType ();
2863 var sig = new Vala.Signal (id, type, get_src_com (begin));
2864 if (ModifierFlags.PRIVATE in flags) {
2865 sig.access = SymbolAccessibility.PRIVATE;
2866 } else {
2867 sig.access = get_access (id);
2870 if (ModifierFlags.VIRTUAL in flags) {
2871 sig.is_virtual = true;
2874 set_attributes (sig, attrs);
2876 foreach (FormalParameter formal_param in params) {
2877 sig.add_parameter (formal_param);
2880 expect_terminator ();
2881 return sig;
2884 Constructor parse_constructor_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2885 var begin = get_location ();
2887 expect (TokenType.INIT);
2888 var flags = parse_member_declaration_modifiers ();
2890 var c = new Constructor (get_src_com (begin));
2891 if (ModifierFlags.STATIC in flags) {
2892 c.binding = MemberBinding.STATIC;
2893 } else if (ModifierFlags.CLASS in flags) {
2894 c.binding = MemberBinding.CLASS;
2897 accept_block ();
2898 c.body = parse_block ();
2899 return c;
2902 Destructor parse_destructor_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2903 var begin = get_location ();
2904 expect (TokenType.FINAL);
2905 var d = new Destructor (get_src_com (begin));
2906 accept_block ();
2907 d.body = parse_block ();
2908 return d;
2911 Symbol parse_struct_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2912 var begin = get_location ();
2914 expect (TokenType.STRUCT);
2915 var flags = parse_type_declaration_modifiers ();
2916 var sym = parse_symbol_name ();
2917 var type_param_list = parse_type_parameter_list ();
2918 DataType base_type = null;
2919 if (accept (TokenType.COLON)) {
2920 base_type = parse_type ();
2922 var st = new Struct (sym.name, get_src_com (begin));
2923 if (ModifierFlags.PRIVATE in flags) {
2924 st.access = SymbolAccessibility.PRIVATE;
2925 } else {
2926 st.access = get_access (sym.name);
2928 set_attributes (st, attrs);
2929 foreach (TypeParameter type_param in type_param_list) {
2930 st.add_type_parameter (type_param);
2932 if (base_type != null) {
2933 st.base_type = base_type;
2936 expect (TokenType.EOL);
2938 parse_declarations (st);
2940 Symbol result = st;
2941 while (sym.inner != null) {
2942 sym = sym.inner;
2943 var ns = new Namespace (sym.name, st.source_reference);
2944 if (result is Namespace) {
2945 ns.add_namespace ((Namespace) result);
2946 } else {
2947 ns.add_struct ((Struct) result);
2948 scanner.source_file.add_node (result);
2950 result = ns;
2952 return result;
2955 void parse_struct_member (Struct st) throws ParseError {
2956 var sym = parse_declaration ();
2957 if (sym is Method) {
2958 st.add_method ((Method) sym);
2959 } else if (sym is Field) {
2960 st.add_field ((Field) sym);
2961 } else if (sym is Constant) {
2962 st.add_constant ((Constant) sym);
2963 } else {
2964 Report.error (sym.source_reference, "unexpected declaration in struct");
2968 Symbol parse_interface_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2969 var begin = get_location ();
2971 expect (TokenType.INTERFACE);
2972 var flags = parse_type_declaration_modifiers ();
2973 var sym = parse_symbol_name ();
2974 var type_param_list = parse_type_parameter_list ();
2975 var base_types = new ArrayList<DataType> ();
2976 if (accept (TokenType.COLON)) {
2977 do {
2978 base_types.add (parse_type ());
2979 } while (accept (TokenType.COMMA));
2981 var iface = new Interface (sym.name, get_src_com (begin));
2982 if (ModifierFlags.PRIVATE in flags) {
2983 iface.access = SymbolAccessibility.PRIVATE;
2984 } else {
2985 iface.access = get_access (sym.name);
2988 set_attributes (iface, attrs);
2989 foreach (TypeParameter type_param in type_param_list) {
2990 iface.add_type_parameter (type_param);
2992 foreach (DataType base_type in base_types) {
2993 iface.add_prerequisite (base_type);
2997 expect (TokenType.EOL);
2999 parse_declarations (iface);
3002 Symbol result = iface;
3003 while (sym.inner != null) {
3004 sym = sym.inner;
3005 var ns = new Namespace (sym.name, iface.source_reference);
3006 if (result is Namespace) {
3007 ns.add_namespace ((Namespace) result);
3008 } else {
3009 ns.add_interface ((Interface) result);
3010 scanner.source_file.add_node (result);
3012 result = ns;
3014 return result;
3017 void parse_interface_member (Interface iface) throws ParseError {
3018 var sym = parse_declaration ();
3019 if (sym is Class) {
3020 iface.add_class ((Class) sym);
3021 } else if (sym is Struct) {
3022 iface.add_struct ((Struct) sym);
3023 } else if (sym is Enum) {
3024 iface.add_enum ((Enum) sym);
3025 } else if (sym is Delegate) {
3026 iface.add_delegate ((Delegate) sym);
3027 } else if (sym is Method) {
3028 iface.add_method ((Method) sym);
3029 } else if (sym is Vala.Signal) {
3030 iface.add_signal ((Vala.Signal) sym);
3031 } else if (sym is Field) {
3032 iface.add_field ((Field) sym);
3033 } else if (sym is Property) {
3034 iface.add_property ((Property) sym);
3035 } else {
3036 Report.error (sym.source_reference, "unexpected declaration in interface");
3040 Symbol parse_enum_declaration (Gee.List<Attribute>? attrs) throws ParseError {
3041 var begin = get_location ();
3042 expect (TokenType.ENUM);
3043 var flags = parse_type_declaration_modifiers ();
3045 var sym = parse_symbol_name ();
3046 var en = new Enum (sym.name, get_src_com (begin));
3047 if (ModifierFlags.PRIVATE in flags) {
3048 en.access = SymbolAccessibility.PRIVATE;
3049 } else {
3050 en.access = get_access (sym.name);
3052 set_attributes (en, attrs);
3054 expect (TokenType.EOL);
3055 expect (TokenType.INDENT);
3056 do {
3057 if (current () == TokenType.DEDENT) {
3058 // allow trailing comma
3059 break;
3061 var value_attrs = parse_attributes ();
3062 var value_begin = get_location ();
3063 string id = parse_identifier ();
3065 var ev = new EnumValue (id, get_src (value_begin));
3066 set_attributes (ev, value_attrs);
3068 if (accept (TokenType.ASSIGN)) {
3069 ev.value = parse_expression ();
3071 en.add_value (ev);
3072 expect (TokenType.EOL);
3073 } while (true);
3075 expect (TokenType.DEDENT);
3077 Symbol result = en;
3078 while (sym.inner != null) {
3079 sym = sym.inner;
3080 var ns = new Namespace (sym.name, en.source_reference);
3081 if (result is Namespace) {
3082 ns.add_namespace ((Namespace) result);
3083 } else {
3084 ns.add_enum ((Enum) result);
3085 scanner.source_file.add_node (result);
3087 result = ns;
3089 return result;
3092 Symbol parse_errordomain_declaration (Gee.List<Attribute>? attrs) throws ParseError {
3093 var begin = get_location ();
3094 expect (TokenType.ERRORDOMAIN);
3095 var flags = parse_type_declaration_modifiers ();
3097 var sym = parse_symbol_name ();
3098 var ed = new ErrorDomain (sym.name, get_src_com (begin));
3099 if (ModifierFlags.PRIVATE in flags) {
3100 ed.access = SymbolAccessibility.PRIVATE;
3101 } else {
3102 ed.access = get_access (sym.name);
3105 set_attributes (ed, attrs);
3107 expect (TokenType.EOL);
3108 expect (TokenType.INDENT);
3110 do {
3111 if (current () == TokenType.DEDENT) {
3112 // allow trailing comma
3113 break;
3115 var code_attrs = parse_attributes ();
3116 string id = parse_identifier ();
3118 var ec = new ErrorCode (id);
3119 set_attributes (ec, code_attrs);
3120 if (accept (TokenType.ASSIGN)) {
3121 ec.value = parse_expression ();
3123 ed.add_code (ec);
3124 accept (TokenType.EOL);
3125 } while (true);
3128 expect (TokenType.DEDENT);
3130 Symbol result = ed;
3131 while (sym.inner != null) {
3132 sym = sym.inner;
3133 var ns = new Namespace (sym.name, ed.source_reference);
3135 if (result is Namespace) {
3136 ns.add_namespace ((Namespace) result);
3137 } else {
3138 ns.add_error_domain ((ErrorDomain) result);
3139 scanner.source_file.add_node (result);
3141 result = ns;
3143 return result;
3146 ModifierFlags parse_type_declaration_modifiers () {
3147 ModifierFlags flags = 0;
3148 while (true) {
3149 switch (current ()) {
3150 case TokenType.ABSTRACT:
3151 next ();
3152 flags |= ModifierFlags.ABSTRACT;
3153 break;
3155 case TokenType.EXTERN:
3156 next ();
3157 flags |= ModifierFlags.EXTERN;
3158 break;
3160 case TokenType.STATIC:
3161 next ();
3162 flags |= ModifierFlags.STATIC;
3163 break;
3165 case TokenType.PRIVATE:
3166 next ();
3167 flags |= ModifierFlags.PRIVATE;
3168 break;
3170 default:
3171 return flags;
3176 ModifierFlags parse_member_declaration_modifiers () {
3177 ModifierFlags flags = 0;
3178 while (true) {
3179 switch (current ()) {
3180 case TokenType.ABSTRACT:
3181 next ();
3182 flags |= ModifierFlags.ABSTRACT;
3183 break;
3184 case TokenType.CLASS:
3185 next ();
3186 flags |= ModifierFlags.CLASS;
3187 break;
3188 case TokenType.EXTERN:
3189 next ();
3190 flags |= ModifierFlags.EXTERN;
3191 break;
3192 case TokenType.INLINE:
3193 next ();
3194 flags |= ModifierFlags.INLINE;
3195 break;
3196 case TokenType.OVERRIDE:
3197 next ();
3198 flags |= ModifierFlags.OVERRIDE;
3199 break;
3200 case TokenType.STATIC:
3201 next ();
3202 flags |= ModifierFlags.STATIC;
3203 break;
3204 case TokenType.VIRTUAL:
3205 next ();
3206 flags |= ModifierFlags.VIRTUAL;
3207 break;
3208 case TokenType.PRIVATE:
3209 next ();
3210 flags |= ModifierFlags.PRIVATE;
3211 break;
3212 default:
3213 return flags;
3218 FormalParameter parse_parameter () throws ParseError {
3219 var attrs = parse_attributes ();
3220 var begin = get_location ();
3221 if (accept (TokenType.ELLIPSIS)) {
3222 // varargs
3223 return new FormalParameter.with_ellipsis (get_src (begin));
3226 var direction = ParameterDirection.IN;
3227 if (accept (TokenType.OUT)) {
3228 direction = ParameterDirection.OUT;
3229 } else if (accept (TokenType.REF)) {
3230 direction = ParameterDirection.REF;
3233 string id = parse_identifier ();
3235 expect (TokenType.COLON);
3237 DataType type;
3238 if (direction == ParameterDirection.IN) {
3239 type = parse_type (false);
3240 } else {
3241 type = parse_type (true);
3244 var param = new FormalParameter (id, type, get_src (begin));
3245 set_attributes (param, attrs);
3246 param.direction = direction;
3247 if (accept (TokenType.ASSIGN)) {
3248 param.default_expression = parse_expression ();
3250 return param;
3253 CreationMethod parse_creation_method_declaration (Gee.List<Attribute>? attrs) throws ParseError {
3254 var begin = get_location ();
3255 CreationMethod method;
3257 expect (TokenType.CONSTRUCT);
3259 parse_member_declaration_modifiers ();
3262 if (accept (TokenType.OPEN_PARENS)) {
3263 /* create default name using class name */
3264 method = new CreationMethod (class_name, null, get_src_com (begin));
3265 } else {
3266 var sym = parse_symbol_name ();
3267 if (sym.inner == null) {
3269 if (sym.name != class_name) {
3270 method = new CreationMethod (class_name, sym.name, get_src_com (begin));
3271 } else {
3272 method = new CreationMethod (sym.name, null, get_src_com (begin));
3274 } else {
3275 method = new CreationMethod (sym.inner.name, sym.name, get_src_com (begin));
3277 expect (TokenType.OPEN_PARENS);
3281 if (current () != TokenType.CLOSE_PARENS) {
3282 do {
3283 var param = parse_parameter ();
3284 method.add_parameter (param);
3285 } while (accept (TokenType.COMMA));
3287 expect (TokenType.CLOSE_PARENS);
3288 if (accept (TokenType.RAISES)) {
3289 do {
3290 method.add_error_type (parse_type ());
3291 } while (accept (TokenType.COMMA));
3293 method.access = SymbolAccessibility.PUBLIC;
3294 set_attributes (method, attrs);
3295 method.binding = MemberBinding.STATIC;
3297 if (accept_block ()) {
3298 method.body = parse_block ();
3301 return method;
3304 Symbol parse_delegate_declaration (Gee.List<Attribute>? attrs) throws ParseError {
3305 var begin = get_location ();
3306 DataType type;
3308 expect (TokenType.DELEGATE);
3310 var flags = parse_member_declaration_modifiers ();
3312 var sym = parse_symbol_name ();
3314 var type_param_list = parse_type_parameter_list ();
3317 var params = new ArrayList<FormalParameter> ();
3319 expect (TokenType.OPEN_PARENS);
3320 if (current () != TokenType.CLOSE_PARENS) {
3321 do {
3322 var param = parse_parameter ();
3323 params.add (param);
3324 } while (accept (TokenType.COMMA));
3326 expect (TokenType.CLOSE_PARENS);
3328 if (accept (TokenType.COLON)) {
3329 type = parse_type ();
3331 } else {
3332 type = new VoidType ();
3335 if (accept (TokenType.RAISES)) {
3336 do {
3337 parse_type ();
3338 } while (accept (TokenType.COMMA));
3341 expect_terminator ();
3343 var d = new Delegate (sym.name, type, get_src_com (begin));
3344 if (ModifierFlags.PRIVATE in flags) {
3345 d.access = SymbolAccessibility.PRIVATE;
3346 } else {
3347 d.access = get_access (sym.name);
3350 set_attributes (d, attrs);
3352 foreach (TypeParameter type_param in type_param_list) {
3353 d.add_type_parameter (type_param);
3356 foreach (FormalParameter formal_param in params) {
3357 d.add_parameter (formal_param);
3360 if (!(ModifierFlags.STATIC in flags)) {
3361 d.has_target = true;
3365 Symbol result = d;
3366 while (sym.inner != null) {
3367 sym = sym.inner;
3368 var ns = new Namespace (sym.name, d.source_reference);
3370 if (result is Namespace) {
3371 ns.add_namespace ((Namespace) result);
3372 } else {
3373 ns.add_delegate ((Delegate) result);
3374 scanner.source_file.add_node (result);
3376 result = ns;
3378 return result;
3381 Gee.List<TypeParameter> parse_type_parameter_list () throws ParseError {
3382 var list = new ArrayList<TypeParameter> ();
3383 if (accept (TokenType.OF)) {
3384 do {
3385 var begin = get_location ();
3386 string id = parse_identifier ();
3387 list.add (new TypeParameter (id, get_src (begin)));
3388 } while (accept (TokenType.COMMA));
3391 return list;
3394 void skip_type_argument_list () throws ParseError {
3395 if (accept (TokenType.OF)) {
3396 do {
3397 skip_type ();
3398 } while (accept (TokenType.COMMA));
3402 // try to parse type argument list
3403 Gee.List<DataType>? parse_type_argument_list (bool maybe_expression) throws ParseError {
3404 var begin = get_location ();
3405 if (accept (TokenType.OF)) {
3406 var list = new ArrayList<DataType> ();
3407 do {
3408 switch (current ()) {
3409 case TokenType.VOID:
3410 case TokenType.DYNAMIC:
3411 case TokenType.WEAK:
3412 case TokenType.IDENTIFIER:
3413 var type = parse_type ();
3415 list.add (type);
3416 break;
3417 default:
3418 rollback (begin);
3419 return null;
3421 } while (accept (TokenType.COMMA));
3423 return list;
3425 return null;
3428 MemberAccess parse_member_name () throws ParseError {
3429 var begin = get_location ();
3430 MemberAccess expr = null;
3431 do {
3432 string id = parse_identifier ();
3433 Gee.List<DataType> type_arg_list = parse_type_argument_list (false);
3434 expr = new MemberAccess (expr, id, get_src (begin));
3435 if (type_arg_list != null) {
3436 foreach (DataType type_arg in type_arg_list) {
3437 expr.add_type_argument (type_arg);
3440 } while (accept (TokenType.DOT));
3441 return expr;