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