Use `internal' accessibility for namespace members by default
[vala-lang.git] / vala / valaparser.vala
blobf3c07ac3ee0075ad3bdda7cfbd87a278ff8f7a4d
1 /* valaparser.vala
3 * Copyright (C) 2006-2009 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
24 using Gee;
26 /**
27 * Code visitor parsing all Vala source files.
29 public class Vala.Parser : CodeVisitor {
30 Scanner scanner;
32 CodeContext context;
34 // token buffer
35 TokenInfo[] tokens;
36 // index of current token in buffer
37 int index;
38 // number of tokens in buffer
39 int size;
41 string comment;
43 const int BUFFER_SIZE = 32;
45 struct TokenInfo {
46 public TokenType type;
47 public SourceLocation begin;
48 public SourceLocation end;
51 enum ModifierFlags {
52 NONE,
53 ABSTRACT = 1 << 0,
54 CLASS = 1 << 1,
55 EXTERN = 1 << 2,
56 INLINE = 1 << 3,
57 OVERRIDE = 1 << 4,
58 STATIC = 1 << 5,
59 VIRTUAL = 1 << 6
62 public Parser () {
63 tokens = new TokenInfo[BUFFER_SIZE];
66 /**
67 * Parses all .vala and .vapi source files in the specified code
68 * context and builds a code tree.
70 * @param context a code context
72 public void parse (CodeContext context) {
73 this.context = context;
74 context.accept (this);
77 public override void visit_source_file (SourceFile source_file) {
78 if (source_file.filename.has_suffix (".vala") || source_file.filename.has_suffix (".vapi")) {
79 parse_file (source_file);
83 inline bool next () {
84 index = (index + 1) % BUFFER_SIZE;
85 size--;
86 if (size <= 0) {
87 SourceLocation begin, end;
88 TokenType type = scanner.read_token (out begin, out end);
89 tokens[index].type = type;
90 tokens[index].begin = begin;
91 tokens[index].end = end;
92 size = 1;
94 return (tokens[index].type != TokenType.EOF);
97 inline void prev () {
98 index = (index - 1 + BUFFER_SIZE) % BUFFER_SIZE;
99 size++;
100 assert (size <= BUFFER_SIZE);
103 inline TokenType current () {
104 return tokens[index].type;
107 inline bool accept (TokenType type) {
108 if (current () == type) {
109 next ();
110 return true;
112 return false;
115 string get_error (string msg) {
116 var begin = get_location ();
117 next ();
118 Report.error (get_src (begin), "syntax error, " + msg);
119 return msg;
122 inline bool expect (TokenType type) throws ParseError {
123 if (accept (type)) {
124 return true;
127 throw new ParseError.SYNTAX (get_error ("expected %s".printf (type.to_string ())));
130 inline SourceLocation get_location () {
131 return tokens[index].begin;
134 string get_current_string () {
135 return ((string) tokens[index].begin.pos).ndup ((tokens[index].end.pos - tokens[index].begin.pos));
138 string get_last_string () {
139 int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE;
140 return ((string) tokens[last_index].begin.pos).ndup ((tokens[last_index].end.pos - tokens[last_index].begin.pos));
143 SourceReference get_src (SourceLocation begin) {
144 int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE;
146 return new SourceReference (scanner.source_file, begin.line, begin.column, tokens[last_index].end.line, tokens[last_index].end.column);
149 SourceReference get_src_com (SourceLocation begin) {
150 int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE;
152 var src = new SourceReference.with_comment (scanner.source_file, begin.line, begin.column, tokens[last_index].end.line, tokens[last_index].end.column, comment);
153 comment = null;
154 return src;
157 SourceReference get_current_src () {
158 return new SourceReference (scanner.source_file, tokens[index].begin.line, tokens[index].begin.column, tokens[index].end.line, tokens[index].end.column);
161 SourceReference get_last_src () {
162 int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE;
164 return new SourceReference (scanner.source_file, tokens[last_index].begin.line, tokens[last_index].begin.column, tokens[last_index].end.line, tokens[last_index].end.column);
167 void rollback (SourceLocation location) {
168 while (tokens[index].begin.pos != location.pos) {
169 prev ();
173 void skip_identifier () throws ParseError {
174 // also accept keywords as identifiers where there is no conflict
175 switch (current ()) {
176 case TokenType.ABSTRACT:
177 case TokenType.AS:
178 case TokenType.BASE:
179 case TokenType.BREAK:
180 case TokenType.CASE:
181 case TokenType.CATCH:
182 case TokenType.CLASS:
183 case TokenType.CONST:
184 case TokenType.CONSTRUCT:
185 case TokenType.CONTINUE:
186 case TokenType.DEFAULT:
187 case TokenType.DELEGATE:
188 case TokenType.DELETE:
189 case TokenType.DO:
190 case TokenType.DYNAMIC:
191 case TokenType.ELSE:
192 case TokenType.ENUM:
193 case TokenType.ENSURES:
194 case TokenType.ERRORDOMAIN:
195 case TokenType.EXTERN:
196 case TokenType.FALSE:
197 case TokenType.FINALLY:
198 case TokenType.FOR:
199 case TokenType.FOREACH:
200 case TokenType.GET:
201 case TokenType.IDENTIFIER:
202 case TokenType.IF:
203 case TokenType.IN:
204 case TokenType.INLINE:
205 case TokenType.INTERFACE:
206 case TokenType.INTERNAL:
207 case TokenType.IS:
208 case TokenType.LOCK:
209 case TokenType.NAMESPACE:
210 case TokenType.NEW:
211 case TokenType.NULL:
212 case TokenType.OUT:
213 case TokenType.OVERRIDE:
214 case TokenType.OWNED:
215 case TokenType.PARAMS:
216 case TokenType.PRIVATE:
217 case TokenType.PROTECTED:
218 case TokenType.PUBLIC:
219 case TokenType.REF:
220 case TokenType.REQUIRES:
221 case TokenType.RETURN:
222 case TokenType.SET:
223 case TokenType.SIGNAL:
224 case TokenType.SIZEOF:
225 case TokenType.STATIC:
226 case TokenType.STRUCT:
227 case TokenType.SWITCH:
228 case TokenType.THIS:
229 case TokenType.THROW:
230 case TokenType.THROWS:
231 case TokenType.TRUE:
232 case TokenType.TRY:
233 case TokenType.TYPEOF:
234 case TokenType.UNOWNED:
235 case TokenType.USING:
236 case TokenType.VAR:
237 case TokenType.VIRTUAL:
238 case TokenType.VOID:
239 case TokenType.VOLATILE:
240 case TokenType.WEAK:
241 case TokenType.WHILE:
242 case TokenType.YIELD:
243 case TokenType.YIELDS:
244 next ();
245 return;
246 case TokenType.INTEGER_LITERAL:
247 case TokenType.REAL_LITERAL:
248 // also accept integer and real literals
249 // as long as they contain at least one character
250 // and no decimal point
251 // for example, 2D and 3D
252 string id = get_current_string ();
253 if (id[id.length - 1].isalpha () && !("." in id)) {
254 next ();
255 return;
257 break;
260 throw new ParseError.SYNTAX (get_error ("expected identifier"));
263 string parse_identifier () throws ParseError {
264 skip_identifier ();
265 return get_last_string ();
268 Expression parse_literal () throws ParseError {
269 var begin = get_location ();
271 switch (current ()) {
272 case TokenType.TRUE:
273 next ();
274 return new BooleanLiteral (true, get_src (begin));
275 case TokenType.FALSE:
276 next ();
277 return new BooleanLiteral (false, get_src (begin));
278 case TokenType.INTEGER_LITERAL:
279 next ();
280 return new IntegerLiteral (get_last_string (), get_src (begin));
281 case TokenType.REAL_LITERAL:
282 next ();
283 return new RealLiteral (get_last_string (), get_src (begin));
284 case TokenType.CHARACTER_LITERAL:
285 next ();
286 // FIXME validate and unescape here and just pass unichar to CharacterLiteral
287 var lit = new CharacterLiteral (get_last_string (), get_src (begin));
288 if (lit.error) {
289 Report.error (lit.source_reference, "invalid character literal");
291 return lit;
292 case TokenType.STRING_LITERAL:
293 next ();
294 return new StringLiteral (get_last_string (), get_src (begin));
295 case TokenType.VERBATIM_STRING_LITERAL:
296 next ();
297 string raw_string = get_last_string ();
298 string escaped_string = raw_string.substring (3, raw_string.len () - 6).escape ("");
299 return new StringLiteral ("\"%s\"".printf (escaped_string), get_src (begin));
300 case TokenType.NULL:
301 next ();
302 return new NullLiteral (get_src (begin));
303 default:
304 throw new ParseError.SYNTAX (get_error ("expected literal"));
308 public void parse_file (SourceFile source_file) {
309 scanner = new Scanner (source_file);
311 index = -1;
312 size = 0;
314 next ();
316 try {
317 parse_using_directives ();
318 parse_declarations (context.root, true);
319 } catch (ParseError e) {
320 // already reported
323 scanner = null;
326 void skip_symbol_name () throws ParseError {
327 do {
328 skip_identifier ();
329 } while (accept (TokenType.DOT) || accept (TokenType.DOUBLE_COLON));
332 UnresolvedSymbol parse_symbol_name () throws ParseError {
333 var begin = get_location ();
334 UnresolvedSymbol sym = null;
335 do {
336 string name = parse_identifier ();
337 if (name == "global" && accept (TokenType.DOUBLE_COLON)) {
338 // global::Name
339 // qualified access to global symbol
340 name = parse_identifier ();
341 sym = new UnresolvedSymbol (sym, name, get_src (begin));
342 sym.qualified = true;
343 continue;
345 sym = new UnresolvedSymbol (sym, name, get_src (begin));
346 } while (accept (TokenType.DOT));
347 return sym;
350 void skip_type () throws ParseError {
351 if (accept (TokenType.VOID)) {
352 while (accept (TokenType.STAR)) {
354 return;
356 accept (TokenType.DYNAMIC);
357 accept (TokenType.OWNED);
358 accept (TokenType.UNOWNED);
359 accept (TokenType.WEAK);
360 skip_symbol_name ();
361 skip_type_argument_list ();
362 while (accept (TokenType.STAR)) {
364 accept (TokenType.INTERR);
365 while (accept (TokenType.OPEN_BRACKET)) {
366 do {
367 if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
368 parse_expression ();
370 } while (accept (TokenType.COMMA));
371 expect (TokenType.CLOSE_BRACKET);
372 accept (TokenType.INTERR);
374 accept (TokenType.OP_NEG);
375 accept (TokenType.HASH);
378 DataType parse_type (bool owned_by_default = true) throws ParseError {
379 var begin = get_location ();
381 if (accept (TokenType.VOID)) {
382 DataType type = new VoidType (get_src (begin));
383 while (accept (TokenType.STAR)) {
384 type = new PointerType (type);
386 return type;
389 bool is_dynamic = accept (TokenType.DYNAMIC);
391 bool value_owned = owned_by_default;
393 if (owned_by_default) {
394 if (accept (TokenType.UNOWNED)
395 || accept (TokenType.WEAK)) {
396 value_owned = false;
398 } else {
399 value_owned = accept (TokenType.OWNED);
402 var sym = parse_symbol_name ();
403 Gee.List<DataType> type_arg_list = parse_type_argument_list (false);
405 DataType type = new UnresolvedType.from_symbol (sym, get_src (begin));
406 if (type_arg_list != null) {
407 foreach (DataType type_arg in type_arg_list) {
408 type.add_type_argument (type_arg);
412 while (accept (TokenType.STAR)) {
413 type = new PointerType (type, get_src (begin));
416 if (!(type is PointerType)) {
417 type.nullable = accept (TokenType.INTERR);
420 // array brackets in types are read from right to left,
421 // this is more logical, especially when nullable arrays
422 // or pointers are involved
423 while (accept (TokenType.OPEN_BRACKET)) {
424 int array_rank = 0;
425 do {
426 array_rank++;
427 // support for stack-allocated arrays
428 // also required for decision between expression and declaration statement
429 if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
430 parse_expression ();
433 while (accept (TokenType.COMMA));
434 expect (TokenType.CLOSE_BRACKET);
436 // arrays contain strong references by default
437 type.value_owned = true;
439 type = new ArrayType (type, array_rank, get_src (begin));
440 type.nullable = accept (TokenType.INTERR);
443 if (accept (TokenType.OP_NEG)) {
444 Report.warning (get_last_src (), "obsolete syntax, types are non-null by default");
447 if (!owned_by_default) {
448 if (accept (TokenType.HASH)) {
449 // TODO enable warning after releasing Vala 0.5.5
450 // Report.warning (get_last_src (), "deprecated syntax, use `owned` modifier");
451 value_owned = true;
455 type.is_dynamic = is_dynamic;
456 type.value_owned = value_owned;
457 return type;
460 Gee.List<Expression> parse_argument_list () throws ParseError {
461 var list = new ArrayList<Expression> ();
462 if (current () != TokenType.CLOSE_PARENS) {
463 do {
464 list.add (parse_argument ());
465 } while (accept (TokenType.COMMA));
467 return list;
470 Expression parse_argument () throws ParseError {
471 var begin = get_location ();
473 if (accept (TokenType.REF)) {
474 var inner = parse_expression ();
475 return new UnaryExpression (UnaryOperator.REF, inner, get_src (begin));
476 } else if (accept (TokenType.OUT)) {
477 var inner = parse_expression ();
478 return new UnaryExpression (UnaryOperator.OUT, inner, get_src (begin));
479 } else {
480 return parse_expression ();
484 Expression parse_primary_expression () throws ParseError {
485 var begin = get_location ();
487 Expression expr;
489 switch (current ()) {
490 case TokenType.TRUE:
491 case TokenType.FALSE:
492 case TokenType.INTEGER_LITERAL:
493 case TokenType.REAL_LITERAL:
494 case TokenType.CHARACTER_LITERAL:
495 case TokenType.STRING_LITERAL:
496 case TokenType.VERBATIM_STRING_LITERAL:
497 case TokenType.NULL:
498 expr = parse_literal ();
499 break;
500 case TokenType.OPEN_BRACE:
501 expr = parse_initializer ();
502 break;
503 case TokenType.OPEN_PARENS:
504 expr = parse_tuple ();
505 break;
506 case TokenType.THIS:
507 expr = parse_this_access ();
508 break;
509 case TokenType.BASE:
510 expr = parse_base_access ();
511 break;
512 case TokenType.NEW:
513 expr = parse_object_or_array_creation_expression ();
514 break;
515 case TokenType.SIZEOF:
516 expr = parse_sizeof_expression ();
517 break;
518 case TokenType.TYPEOF:
519 expr = parse_typeof_expression ();
520 break;
521 default:
522 expr = parse_simple_name ();
523 break;
526 // process primary expressions that start with an inner primary expression
527 bool found = true;
528 while (found) {
529 switch (current ()) {
530 case TokenType.DOT:
531 expr = parse_member_access (begin, expr);
532 break;
533 case TokenType.OP_PTR:
534 expr = parse_pointer_member_access (begin, expr);
535 break;
536 case TokenType.OPEN_PARENS:
537 expr = parse_method_call (begin, expr);
538 break;
539 case TokenType.OPEN_BRACKET:
540 expr = parse_element_access (begin, expr);
541 break;
542 case TokenType.OP_INC:
543 expr = parse_post_increment_expression (begin, expr);
544 break;
545 case TokenType.OP_DEC:
546 expr = parse_post_decrement_expression (begin, expr);
547 break;
548 default:
549 found = false;
550 break;
554 return expr;
557 Expression parse_simple_name () throws ParseError {
558 var begin = get_location ();
559 string id = parse_identifier ();
560 bool qualified = false;
561 if (id == "global" && accept (TokenType.DOUBLE_COLON)) {
562 id = parse_identifier ();
563 qualified = true;
565 Gee.List<DataType> type_arg_list = parse_type_argument_list (true);
566 var expr = new MemberAccess (null, id, get_src (begin));
567 expr.qualified = qualified;
568 if (type_arg_list != null) {
569 foreach (DataType type_arg in type_arg_list) {
570 expr.add_type_argument (type_arg);
573 return expr;
576 Expression parse_tuple () throws ParseError {
577 var begin = get_location ();
578 expect (TokenType.OPEN_PARENS);
579 var expr_list = new ArrayList<Expression> ();
580 if (current () != TokenType.CLOSE_PARENS) {
581 do {
582 expr_list.add (parse_expression ());
583 } while (accept (TokenType.COMMA));
585 expect (TokenType.CLOSE_PARENS);
586 if (expr_list.size != 1) {
587 var tuple = new Tuple ();
588 foreach (Expression expr in expr_list) {
589 tuple.add_expression (expr);
591 return tuple;
593 return new ParenthesizedExpression (expr_list.get (0), get_src (begin));
596 Expression parse_member_access (SourceLocation begin, Expression inner) throws ParseError {
597 expect (TokenType.DOT);
598 string id = parse_identifier ();
599 Gee.List<DataType> type_arg_list = parse_type_argument_list (true);
600 var expr = new MemberAccess (inner, id, get_src (begin));
601 if (type_arg_list != null) {
602 foreach (DataType type_arg in type_arg_list) {
603 expr.add_type_argument (type_arg);
606 return expr;
609 Expression parse_pointer_member_access (SourceLocation begin, Expression inner) throws ParseError {
610 expect (TokenType.OP_PTR);
611 string id = parse_identifier ();
612 Gee.List<DataType> type_arg_list = parse_type_argument_list (true);
613 var expr = new MemberAccess.pointer (inner, id, get_src (begin));
614 if (type_arg_list != null) {
615 foreach (DataType type_arg in type_arg_list) {
616 expr.add_type_argument (type_arg);
619 return expr;
622 Expression parse_method_call (SourceLocation begin, Expression inner) throws ParseError {
623 expect (TokenType.OPEN_PARENS);
624 var arg_list = parse_argument_list ();
625 expect (TokenType.CLOSE_PARENS);
626 var init_list = parse_object_initializer ();
628 if (init_list.size > 0 && inner is MemberAccess) {
629 // struct creation expression
630 var member = (MemberAccess) inner;
631 member.creation_member = true;
633 var expr = new ObjectCreationExpression (member, get_src (begin));
634 expr.struct_creation = true;
635 foreach (Expression arg in arg_list) {
636 expr.add_argument (arg);
638 foreach (MemberInitializer initializer in init_list) {
639 expr.add_member_initializer (initializer);
641 return expr;
642 } else {
643 var expr = new MethodCall (inner, get_src (begin));
644 foreach (Expression arg in arg_list) {
645 expr.add_argument (arg);
647 return expr;
651 Expression parse_element_access (SourceLocation begin, Expression inner) throws ParseError {
652 expect (TokenType.OPEN_BRACKET);
653 var index_list = parse_expression_list ();
654 expect (TokenType.CLOSE_BRACKET);
656 var expr = new ElementAccess (inner, get_src (begin));
657 foreach (Expression index in index_list) {
658 expr.append_index (index);
660 return expr;
663 Gee.List<Expression> parse_expression_list () throws ParseError {
664 var list = new ArrayList<Expression> ();
665 do {
666 list.add (parse_expression ());
667 } while (accept (TokenType.COMMA));
668 return list;
671 Expression parse_this_access () throws ParseError {
672 var begin = get_location ();
673 expect (TokenType.THIS);
674 return new MemberAccess (null, "this", get_src (begin));
677 Expression parse_base_access () throws ParseError {
678 var begin = get_location ();
679 expect (TokenType.BASE);
680 return new BaseAccess (get_src (begin));
683 Expression parse_post_increment_expression (SourceLocation begin, Expression inner) throws ParseError {
684 expect (TokenType.OP_INC);
685 return new PostfixExpression (inner, true, get_src (begin));
688 Expression parse_post_decrement_expression (SourceLocation begin, Expression inner) throws ParseError {
689 expect (TokenType.OP_DEC);
690 return new PostfixExpression (inner, false, get_src (begin));
693 Expression parse_object_or_array_creation_expression () throws ParseError {
694 var begin = get_location ();
695 expect (TokenType.NEW);
696 var member = parse_member_name ();
697 if (accept (TokenType.OPEN_PARENS)) {
698 var expr = parse_object_creation_expression (begin, member);
699 return expr;
700 } else if (accept (TokenType.OPEN_BRACKET)) {
701 var expr = parse_array_creation_expression (begin, member);
702 return expr;
703 } else {
704 throw new ParseError.SYNTAX (get_error ("expected ( or ["));
708 Expression parse_object_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError {
709 member.creation_member = true;
710 var arg_list = parse_argument_list ();
711 expect (TokenType.CLOSE_PARENS);
712 var init_list = parse_object_initializer ();
714 var expr = new ObjectCreationExpression (member, get_src (begin));
715 foreach (Expression arg in arg_list) {
716 expr.add_argument (arg);
718 foreach (MemberInitializer initializer in init_list) {
719 expr.add_member_initializer (initializer);
721 return expr;
724 Expression parse_array_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError {
725 bool size_specified = false;
726 Gee.List<Expression> size_specifier_list = null;
727 bool first = true;
728 DataType element_type = UnresolvedType.new_from_expression (member);
729 do {
730 if (!first) {
731 // array of arrays: new T[][42]
732 element_type = new ArrayType (element_type, size_specifier_list.size, element_type.source_reference);
733 } else {
734 first = false;
737 size_specifier_list = new ArrayList<Expression> ();
738 do {
739 Expression size = null;
740 if (current () != TokenType.CLOSE_BRACKET && current () != TokenType.COMMA) {
741 size = parse_expression ();
742 size_specified = true;
744 size_specifier_list.add (size);
745 } while (accept (TokenType.COMMA));
746 expect (TokenType.CLOSE_BRACKET);
747 } while (accept (TokenType.OPEN_BRACKET));
749 InitializerList initializer = null;
750 if (current () == TokenType.OPEN_BRACE) {
751 initializer = parse_initializer ();
753 var expr = new ArrayCreationExpression (element_type, size_specifier_list.size, initializer, get_src (begin));
754 if (size_specified) {
755 foreach (Expression size in size_specifier_list) {
756 expr.append_size (size);
759 return expr;
762 Gee.List<MemberInitializer> parse_object_initializer () throws ParseError {
763 var list = new ArrayList<MemberInitializer> ();
764 if (accept (TokenType.OPEN_BRACE)) {
765 do {
766 list.add (parse_member_initializer ());
767 } while (accept (TokenType.COMMA));
768 expect (TokenType.CLOSE_BRACE);
770 return list;
773 MemberInitializer parse_member_initializer () throws ParseError {
774 var begin = get_location ();
775 string id = parse_identifier ();
776 expect (TokenType.ASSIGN);
777 var expr = parse_expression ();
779 return new MemberInitializer (id, expr, get_src (begin));
782 Expression parse_sizeof_expression () throws ParseError {
783 var begin = get_location ();
784 expect (TokenType.SIZEOF);
785 expect (TokenType.OPEN_PARENS);
786 var type = parse_type ();
787 expect (TokenType.CLOSE_PARENS);
789 return new SizeofExpression (type, get_src (begin));
792 Expression parse_typeof_expression () throws ParseError {
793 var begin = get_location ();
794 expect (TokenType.TYPEOF);
795 expect (TokenType.OPEN_PARENS);
796 var type = parse_type ();
797 expect (TokenType.CLOSE_PARENS);
799 return new TypeofExpression (type, get_src (begin));
802 UnaryOperator get_unary_operator (TokenType token_type) {
803 switch (token_type) {
804 case TokenType.PLUS: return UnaryOperator.PLUS;
805 case TokenType.MINUS: return UnaryOperator.MINUS;
806 case TokenType.OP_NEG: return UnaryOperator.LOGICAL_NEGATION;
807 case TokenType.TILDE: return UnaryOperator.BITWISE_COMPLEMENT;
808 case TokenType.OP_INC: return UnaryOperator.INCREMENT;
809 case TokenType.OP_DEC: return UnaryOperator.DECREMENT;
810 default: return UnaryOperator.NONE;
814 Expression parse_unary_expression () throws ParseError {
815 var begin = get_location ();
816 var operator = get_unary_operator (current ());
817 if (operator != UnaryOperator.NONE) {
818 next ();
819 var op = parse_unary_expression ();
820 return new UnaryExpression (operator, op, get_src (begin));
822 switch (current ()) {
823 case TokenType.HASH:
824 // TODO enable warning after releasing Vala 0.5.5
825 // Report.warning (get_last_src (), "deprecated syntax, use `(owned)` cast");
826 next ();
827 var op = parse_unary_expression ();
828 return new ReferenceTransferExpression (op, get_src (begin));
829 case TokenType.OPEN_PARENS:
830 next ();
831 switch (current ()) {
832 case TokenType.OWNED:
833 // (owned) foo
834 next ();
835 if (accept (TokenType.CLOSE_PARENS)) {
836 var op = parse_unary_expression ();
837 return new ReferenceTransferExpression (op, get_src (begin));
839 break;
840 case TokenType.VOID:
841 case TokenType.DYNAMIC:
842 case TokenType.IDENTIFIER:
843 var type = parse_type ();
844 if (accept (TokenType.CLOSE_PARENS)) {
845 // check follower to decide whether to create cast expression
846 switch (current ()) {
847 case TokenType.OP_NEG:
848 case TokenType.TILDE:
849 case TokenType.OPEN_PARENS:
850 case TokenType.TRUE:
851 case TokenType.FALSE:
852 case TokenType.INTEGER_LITERAL:
853 case TokenType.REAL_LITERAL:
854 case TokenType.CHARACTER_LITERAL:
855 case TokenType.STRING_LITERAL:
856 case TokenType.VERBATIM_STRING_LITERAL:
857 case TokenType.NULL:
858 case TokenType.THIS:
859 case TokenType.BASE:
860 case TokenType.NEW:
861 case TokenType.SIZEOF:
862 case TokenType.TYPEOF:
863 case TokenType.IDENTIFIER:
864 var inner = parse_unary_expression ();
865 return new CastExpression (inner, type, get_src (begin), false);
866 default:
867 break;
870 break;
871 default:
872 break;
874 // no cast expression
875 rollback (begin);
876 break;
877 case TokenType.STAR:
878 next ();
879 var op = parse_unary_expression ();
880 return new PointerIndirection (op, get_src (begin));
881 case TokenType.BITWISE_AND:
882 next ();
883 var op = parse_unary_expression ();
884 return new AddressofExpression (op, get_src (begin));
885 default:
886 break;
889 var expr = parse_primary_expression ();
890 return expr;
893 BinaryOperator get_binary_operator (TokenType token_type) {
894 switch (token_type) {
895 case TokenType.STAR: return BinaryOperator.MUL;
896 case TokenType.DIV: return BinaryOperator.DIV;
897 case TokenType.PERCENT: return BinaryOperator.MOD;
898 case TokenType.PLUS: return BinaryOperator.PLUS;
899 case TokenType.MINUS: return BinaryOperator.MINUS;
900 case TokenType.OP_LT: return BinaryOperator.LESS_THAN;
901 case TokenType.OP_GT: return BinaryOperator.GREATER_THAN;
902 case TokenType.OP_LE: return BinaryOperator.LESS_THAN_OR_EQUAL;
903 case TokenType.OP_GE: return BinaryOperator.GREATER_THAN_OR_EQUAL;
904 case TokenType.OP_EQ: return BinaryOperator.EQUALITY;
905 case TokenType.OP_NE: return BinaryOperator.INEQUALITY;
906 default: return BinaryOperator.NONE;
910 Expression parse_multiplicative_expression () throws ParseError {
911 var begin = get_location ();
912 var left = parse_unary_expression ();
913 bool found = true;
914 while (found) {
915 var operator = get_binary_operator (current ());
916 switch (operator) {
917 case BinaryOperator.MUL:
918 case BinaryOperator.DIV:
919 case BinaryOperator.MOD:
920 next ();
921 var right = parse_unary_expression ();
922 left = new BinaryExpression (operator, left, right, get_src (begin));
923 break;
924 default:
925 found = false;
926 break;
929 return left;
932 Expression parse_additive_expression () throws ParseError {
933 var begin = get_location ();
934 var left = parse_multiplicative_expression ();
935 bool found = true;
936 while (found) {
937 var operator = get_binary_operator (current ());
938 switch (operator) {
939 case BinaryOperator.PLUS:
940 case BinaryOperator.MINUS:
941 next ();
942 var right = parse_multiplicative_expression ();
943 left = new BinaryExpression (operator, left, right, get_src (begin));
944 break;
945 default:
946 found = false;
947 break;
950 return left;
953 Expression parse_shift_expression () throws ParseError {
954 var begin = get_location ();
955 var left = parse_additive_expression ();
956 bool found = true;
957 while (found) {
958 switch (current ()) {
959 case TokenType.OP_SHIFT_LEFT:
960 next ();
961 var right = parse_additive_expression ();
962 left = new BinaryExpression (BinaryOperator.SHIFT_LEFT, left, right, get_src (begin));
963 break;
964 // don't use OP_SHIFT_RIGHT to support >> for nested generics
965 case TokenType.OP_GT:
966 char* first_gt_pos = tokens[index].begin.pos;
967 next ();
968 // only accept >> when there is no space between the two > signs
969 if (current () == TokenType.OP_GT && tokens[index].begin.pos == first_gt_pos + 1) {
970 next ();
971 var right = parse_additive_expression ();
972 left = new BinaryExpression (BinaryOperator.SHIFT_RIGHT, left, right, get_src (begin));
973 } else {
974 prev ();
975 found = false;
977 break;
978 default:
979 found = false;
980 break;
983 return left;
986 Expression parse_relational_expression () throws ParseError {
987 var begin = get_location ();
988 var left = parse_shift_expression ();
989 bool found = true;
990 while (found) {
991 var operator = get_binary_operator (current ());
992 switch (operator) {
993 case BinaryOperator.LESS_THAN:
994 case BinaryOperator.LESS_THAN_OR_EQUAL:
995 case BinaryOperator.GREATER_THAN_OR_EQUAL:
996 next ();
997 var right = parse_shift_expression ();
998 left = new BinaryExpression (operator, left, right, get_src (begin));
999 break;
1000 case BinaryOperator.GREATER_THAN:
1001 next ();
1002 // ignore >> and >>= (two tokens due to generics)
1003 if (current () != TokenType.OP_GT && current () != TokenType.OP_GE) {
1004 var right = parse_shift_expression ();
1005 left = new BinaryExpression (operator, left, right, get_src (begin));
1006 } else {
1007 prev ();
1008 found = false;
1010 break;
1011 default:
1012 switch (current ()) {
1013 case TokenType.IS:
1014 next ();
1015 var type = parse_type ();
1016 left = new TypeCheck (left, type, get_src (begin));
1017 break;
1018 case TokenType.AS:
1019 next ();
1020 var type = parse_type ();
1021 left = new CastExpression (left, type, get_src (begin), true);
1022 break;
1023 default:
1024 found = false;
1025 break;
1027 break;
1030 return left;
1033 Expression parse_equality_expression () throws ParseError {
1034 var begin = get_location ();
1035 var left = parse_relational_expression ();
1036 bool found = true;
1037 while (found) {
1038 var operator = get_binary_operator (current ());
1039 switch (operator) {
1040 case BinaryOperator.EQUALITY:
1041 case BinaryOperator.INEQUALITY:
1042 next ();
1043 var right = parse_relational_expression ();
1044 left = new BinaryExpression (operator, left, right, get_src (begin));
1045 break;
1046 default:
1047 found = false;
1048 break;
1051 return left;
1054 Expression parse_and_expression () throws ParseError {
1055 var begin = get_location ();
1056 var left = parse_equality_expression ();
1057 while (accept (TokenType.BITWISE_AND)) {
1058 var right = parse_equality_expression ();
1059 left = new BinaryExpression (BinaryOperator.BITWISE_AND, left, right, get_src (begin));
1061 return left;
1064 Expression parse_exclusive_or_expression () throws ParseError {
1065 var begin = get_location ();
1066 var left = parse_and_expression ();
1067 while (accept (TokenType.CARRET)) {
1068 var right = parse_and_expression ();
1069 left = new BinaryExpression (BinaryOperator.BITWISE_XOR, left, right, get_src (begin));
1071 return left;
1074 Expression parse_inclusive_or_expression () throws ParseError {
1075 var begin = get_location ();
1076 var left = parse_exclusive_or_expression ();
1077 while (accept (TokenType.BITWISE_OR)) {
1078 var right = parse_exclusive_or_expression ();
1079 left = new BinaryExpression (BinaryOperator.BITWISE_OR, left, right, get_src (begin));
1081 return left;
1084 Expression parse_in_expression () throws ParseError {
1085 var begin = get_location ();
1086 var left = parse_inclusive_or_expression ();
1087 while (accept (TokenType.IN)) {
1088 var right = parse_inclusive_or_expression ();
1089 left = new BinaryExpression (BinaryOperator.IN, left, right, get_src (begin));
1091 return left;
1094 Expression parse_conditional_and_expression () throws ParseError {
1095 var begin = get_location ();
1096 var left = parse_in_expression ();
1097 while (accept (TokenType.OP_AND)) {
1098 var right = parse_in_expression ();
1099 left = new BinaryExpression (BinaryOperator.AND, left, right, get_src (begin));
1101 return left;
1104 Expression parse_conditional_or_expression () throws ParseError {
1105 var begin = get_location ();
1106 var left = parse_conditional_and_expression ();
1107 while (accept (TokenType.OP_OR)) {
1108 var right = parse_conditional_and_expression ();
1109 left = new BinaryExpression (BinaryOperator.OR, left, right, get_src (begin));
1111 return left;
1114 Expression parse_conditional_expression () throws ParseError {
1115 var begin = get_location ();
1116 var condition = parse_conditional_or_expression ();
1117 if (accept (TokenType.INTERR)) {
1118 var true_expr = parse_expression ();
1119 expect (TokenType.COLON);
1120 var false_expr = parse_expression ();
1121 return new ConditionalExpression (condition, true_expr, false_expr, get_src (begin));
1122 } else {
1123 return condition;
1127 Expression parse_lambda_expression () throws ParseError {
1128 var begin = get_location ();
1129 Gee.List<string> params = new ArrayList<string> ();
1130 if (accept (TokenType.OPEN_PARENS)) {
1131 if (current () != TokenType.CLOSE_PARENS) {
1132 do {
1133 params.add (parse_identifier ());
1134 } while (accept (TokenType.COMMA));
1136 expect (TokenType.CLOSE_PARENS);
1137 } else {
1138 params.add (parse_identifier ());
1140 expect (TokenType.LAMBDA);
1142 LambdaExpression lambda;
1143 if (current () == TokenType.OPEN_BRACE) {
1144 var block = parse_block ();
1145 lambda = new LambdaExpression.with_statement_body (block, get_src (begin));
1146 } else {
1147 var expr = parse_expression ();
1148 lambda = new LambdaExpression (expr, get_src (begin));
1150 foreach (string param in params) {
1151 lambda.add_parameter (param);
1153 return lambda;
1156 AssignmentOperator get_assignment_operator (TokenType token_type) {
1157 switch (token_type) {
1158 case TokenType.ASSIGN: return AssignmentOperator.SIMPLE;
1159 case TokenType.ASSIGN_ADD: return AssignmentOperator.ADD;
1160 case TokenType.ASSIGN_SUB: return AssignmentOperator.SUB;
1161 case TokenType.ASSIGN_BITWISE_OR: return AssignmentOperator.BITWISE_OR;
1162 case TokenType.ASSIGN_BITWISE_AND: return AssignmentOperator.BITWISE_AND;
1163 case TokenType.ASSIGN_BITWISE_XOR: return AssignmentOperator.BITWISE_XOR;
1164 case TokenType.ASSIGN_DIV: return AssignmentOperator.DIV;
1165 case TokenType.ASSIGN_MUL: return AssignmentOperator.MUL;
1166 case TokenType.ASSIGN_PERCENT: return AssignmentOperator.PERCENT;
1167 case TokenType.ASSIGN_SHIFT_LEFT: return AssignmentOperator.SHIFT_LEFT;
1168 default: return AssignmentOperator.NONE;
1172 Expression parse_expression () throws ParseError {
1173 var begin = get_location ();
1174 Expression expr = parse_conditional_expression ();
1176 if (current () == TokenType.LAMBDA) {
1177 rollback (begin);
1178 var lambda = parse_lambda_expression ();
1179 return lambda;
1182 while (true) {
1183 var operator = get_assignment_operator (current ());
1184 if (operator != AssignmentOperator.NONE) {
1185 next ();
1186 var rhs = parse_expression ();
1187 expr = new Assignment (expr, rhs, operator, get_src (begin));
1188 } else if (current () == TokenType.OP_GT) { // >>=
1189 char* first_gt_pos = tokens[index].begin.pos;
1190 next ();
1191 // only accept >>= when there is no space between the two > signs
1192 if (current () == TokenType.OP_GE && tokens[index].begin.pos == first_gt_pos + 1) {
1193 next ();
1194 var rhs = parse_expression ();
1195 expr = new Assignment (expr, rhs, AssignmentOperator.SHIFT_RIGHT, get_src (begin));
1196 } else {
1197 prev ();
1198 break;
1200 } else {
1201 break;
1205 return expr;
1208 void parse_statements (Block block) throws ParseError {
1209 while (current () != TokenType.CLOSE_BRACE
1210 && current () != TokenType.CASE
1211 && current () != TokenType.DEFAULT) {
1212 try {
1213 Statement stmt = null;
1214 bool is_decl = false;
1215 comment = scanner.pop_comment ();
1216 switch (current ()) {
1217 case TokenType.OPEN_BRACE:
1218 stmt = parse_block ();
1219 break;
1220 case TokenType.SEMICOLON:
1221 stmt = parse_empty_statement ();
1222 break;
1223 case TokenType.IF:
1224 stmt = parse_if_statement ();
1225 break;
1226 case TokenType.SWITCH:
1227 stmt = parse_switch_statement ();
1228 break;
1229 case TokenType.WHILE:
1230 stmt = parse_while_statement ();
1231 break;
1232 case TokenType.DO:
1233 stmt = parse_do_statement ();
1234 break;
1235 case TokenType.FOR:
1236 stmt = parse_for_statement ();
1237 break;
1238 case TokenType.FOREACH:
1239 stmt = parse_foreach_statement ();
1240 break;
1241 case TokenType.BREAK:
1242 stmt = parse_break_statement ();
1243 break;
1244 case TokenType.CONTINUE:
1245 stmt = parse_continue_statement ();
1246 break;
1247 case TokenType.RETURN:
1248 stmt = parse_return_statement ();
1249 break;
1250 case TokenType.YIELD:
1251 stmt = parse_yield_statement ();
1252 break;
1253 case TokenType.THROW:
1254 stmt = parse_throw_statement ();
1255 break;
1256 case TokenType.TRY:
1257 stmt = parse_try_statement ();
1258 break;
1259 case TokenType.LOCK:
1260 stmt = parse_lock_statement ();
1261 break;
1262 case TokenType.DELETE:
1263 stmt = parse_delete_statement ();
1264 break;
1265 case TokenType.VAR:
1266 is_decl = true;
1267 parse_local_variable_declarations (block);
1268 break;
1269 case TokenType.OP_INC:
1270 case TokenType.OP_DEC:
1271 case TokenType.BASE:
1272 case TokenType.THIS:
1273 case TokenType.OPEN_PARENS:
1274 case TokenType.STAR:
1275 case TokenType.NEW:
1276 stmt = parse_expression_statement ();
1277 break;
1278 default:
1279 bool is_expr = is_expression ();
1280 if (is_expr) {
1281 stmt = parse_expression_statement ();
1282 } else {
1283 is_decl = true;
1284 parse_local_variable_declarations (block);
1286 break;
1289 if (!is_decl) {
1290 block.add_statement (stmt);
1292 } catch (ParseError e) {
1293 if (recover () != RecoveryState.STATEMENT_BEGIN) {
1294 // beginning of next declaration or end of file reached
1295 // return what we have so far
1296 break;
1302 bool is_expression () throws ParseError {
1303 var begin = get_location ();
1305 // decide between declaration and expression statement
1306 skip_type ();
1307 switch (current ()) {
1308 // invocation expression
1309 case TokenType.OPEN_PARENS:
1310 // postfix increment
1311 case TokenType.OP_INC:
1312 // postfix decrement
1313 case TokenType.OP_DEC:
1314 // assignments
1315 case TokenType.ASSIGN:
1316 case TokenType.ASSIGN_ADD:
1317 case TokenType.ASSIGN_BITWISE_AND:
1318 case TokenType.ASSIGN_BITWISE_OR:
1319 case TokenType.ASSIGN_BITWISE_XOR:
1320 case TokenType.ASSIGN_DIV:
1321 case TokenType.ASSIGN_MUL:
1322 case TokenType.ASSIGN_PERCENT:
1323 case TokenType.ASSIGN_SHIFT_LEFT:
1324 case TokenType.ASSIGN_SUB:
1325 case TokenType.OP_GT: // >>=
1326 // member access
1327 case TokenType.DOT:
1328 // pointer member access
1329 case TokenType.OP_PTR:
1330 rollback (begin);
1331 return true;
1332 default:
1333 rollback (begin);
1334 return false;
1338 Block parse_embedded_statement () throws ParseError {
1339 if (current () == TokenType.OPEN_BRACE) {
1340 var block = parse_block ();
1341 return block;
1344 comment = scanner.pop_comment ();
1346 var block = new Block (get_src_com (get_location ()));
1347 block.add_statement (parse_embedded_statement_without_block ());
1348 return block;
1352 Statement parse_embedded_statement_without_block () throws ParseError {
1353 switch (current ()) {
1354 case TokenType.SEMICOLON: return parse_empty_statement ();
1355 case TokenType.IF: return parse_if_statement ();
1356 case TokenType.SWITCH: return parse_switch_statement ();
1357 case TokenType.WHILE: return parse_while_statement ();
1358 case TokenType.DO: return parse_do_statement ();
1359 case TokenType.FOR: return parse_for_statement ();
1360 case TokenType.FOREACH: return parse_foreach_statement ();
1361 case TokenType.BREAK: return parse_break_statement ();
1362 case TokenType.CONTINUE: return parse_continue_statement ();
1363 case TokenType.RETURN: return parse_return_statement ();
1364 case TokenType.YIELD: return parse_yield_statement ();
1365 case TokenType.THROW: return parse_throw_statement ();
1366 case TokenType.TRY: return parse_try_statement ();
1367 case TokenType.LOCK: return parse_lock_statement ();
1368 case TokenType.DELETE: return parse_delete_statement ();
1369 default: return parse_expression_statement ();
1373 Block parse_block () throws ParseError {
1374 var begin = get_location ();
1375 expect (TokenType.OPEN_BRACE);
1376 var block = new Block (get_src_com (begin));
1377 parse_statements (block);
1378 if (!accept (TokenType.CLOSE_BRACE)) {
1379 // only report error if it's not a secondary error
1380 if (Report.get_errors () == 0) {
1381 Report.error (get_current_src (), "expected `}'");
1385 block.source_reference.last_line = get_current_src ().last_line;
1386 block.source_reference.last_column = get_current_src ().last_column;
1388 return block;
1391 Statement parse_empty_statement () throws ParseError {
1392 var begin = get_location ();
1393 expect (TokenType.SEMICOLON);
1394 return new EmptyStatement (get_src_com (begin));
1397 void parse_local_variable_declarations (Block block) throws ParseError {
1398 DataType variable_type;
1399 if (accept (TokenType.VAR)) {
1400 variable_type = null;
1401 } else {
1402 variable_type = parse_type ();
1404 do {
1405 DataType type_copy = null;
1406 if (variable_type != null) {
1407 type_copy = variable_type.copy ();
1409 var local = parse_local_variable (type_copy);
1410 block.add_statement (new DeclarationStatement (local, local.source_reference));
1411 } while (accept (TokenType.COMMA));
1412 expect (TokenType.SEMICOLON);
1415 LocalVariable parse_local_variable (DataType? variable_type) throws ParseError {
1416 var begin = get_location ();
1417 string id = parse_identifier ();
1418 Expression initializer = null;
1419 if (accept (TokenType.ASSIGN)) {
1420 initializer = parse_expression ();
1422 return new LocalVariable (variable_type, id, initializer, get_src_com (begin));
1425 Statement parse_expression_statement () throws ParseError {
1426 var begin = get_location ();
1427 var expr = parse_statement_expression ();
1428 expect (TokenType.SEMICOLON);
1429 return new ExpressionStatement (expr, get_src_com (begin));
1432 Expression parse_statement_expression () throws ParseError {
1433 // invocation expression, assignment,
1434 // or pre/post increment/decrement expression
1435 var expr = parse_expression ();
1436 return expr;
1439 Statement parse_if_statement () throws ParseError {
1440 var begin = get_location ();
1441 expect (TokenType.IF);
1442 expect (TokenType.OPEN_PARENS);
1443 var condition = parse_expression ();
1444 expect (TokenType.CLOSE_PARENS);
1445 var src = get_src_com (begin);
1446 var true_stmt = parse_embedded_statement ();
1447 Block false_stmt = null;
1448 if (accept (TokenType.ELSE)) {
1449 false_stmt = parse_embedded_statement ();
1451 return new IfStatement (condition, true_stmt, false_stmt, src);
1454 Statement parse_switch_statement () throws ParseError {
1455 var begin = get_location ();
1456 expect (TokenType.SWITCH);
1457 expect (TokenType.OPEN_PARENS);
1458 var condition = parse_expression ();
1459 expect (TokenType.CLOSE_PARENS);
1460 var stmt = new SwitchStatement (condition, get_src_com (begin));
1461 expect (TokenType.OPEN_BRACE);
1462 while (current () != TokenType.CLOSE_BRACE) {
1463 var section = new SwitchSection (get_src_com (begin));
1464 do {
1465 if (accept (TokenType.CASE)) {
1466 section.add_label (new SwitchLabel (parse_expression (), get_src_com (begin)));
1467 } else {
1468 expect (TokenType.DEFAULT);
1469 section.add_label (new SwitchLabel.with_default (get_src_com (begin)));
1471 expect (TokenType.COLON);
1472 } while (current () == TokenType.CASE || current () == TokenType.DEFAULT);
1473 parse_statements (section);
1474 stmt.add_section (section);
1476 expect (TokenType.CLOSE_BRACE);
1477 return stmt;
1480 Statement parse_while_statement () throws ParseError {
1481 var begin = get_location ();
1482 expect (TokenType.WHILE);
1483 expect (TokenType.OPEN_PARENS);
1484 var condition = parse_expression ();
1485 expect (TokenType.CLOSE_PARENS);
1486 var body = parse_embedded_statement ();
1487 return new WhileStatement (condition, body, get_src_com (begin));
1490 Statement parse_do_statement () throws ParseError {
1491 var begin = get_location ();
1492 expect (TokenType.DO);
1493 var body = parse_embedded_statement ();
1494 expect (TokenType.WHILE);
1495 expect (TokenType.OPEN_PARENS);
1496 var condition = parse_expression ();
1497 expect (TokenType.CLOSE_PARENS);
1498 expect (TokenType.SEMICOLON);
1499 return new DoStatement (body, condition, get_src_com (begin));
1502 Statement parse_for_statement () throws ParseError {
1503 var begin = get_location ();
1504 Block block = null;
1505 expect (TokenType.FOR);
1506 expect (TokenType.OPEN_PARENS);
1507 var initializer_list = new ArrayList<Expression> ();
1508 if (!accept (TokenType.SEMICOLON)) {
1509 bool is_expr;
1510 switch (current ()) {
1511 case TokenType.VAR:
1512 is_expr = false;
1513 break;
1514 case TokenType.OP_INC:
1515 case TokenType.OP_DEC:
1516 is_expr = true;
1517 break;
1518 default:
1519 is_expr = is_expression ();
1520 break;
1523 if (is_expr) {
1524 do {
1525 initializer_list.add (parse_statement_expression ());
1526 } while (accept (TokenType.COMMA));
1527 } else {
1528 block = new Block (get_src (begin));
1529 DataType variable_type;
1530 if (accept (TokenType.VAR)) {
1531 variable_type = null;
1532 } else {
1533 variable_type = parse_type ();
1535 var local = parse_local_variable (variable_type);
1536 block.add_statement (new DeclarationStatement (local, local.source_reference));
1538 expect (TokenType.SEMICOLON);
1540 Expression condition = null;
1541 if (current () != TokenType.SEMICOLON) {
1542 condition = parse_expression ();
1544 expect (TokenType.SEMICOLON);
1545 var iterator_list = new ArrayList<Expression> ();
1546 if (current () != TokenType.CLOSE_PARENS) {
1547 do {
1548 iterator_list.add (parse_statement_expression ());
1549 } while (accept (TokenType.COMMA));
1551 expect (TokenType.CLOSE_PARENS);
1552 var src = get_src_com (begin);
1553 var body = parse_embedded_statement ();
1554 var stmt = new ForStatement (condition, body, src);
1555 foreach (Expression init in initializer_list) {
1556 stmt.add_initializer (init);
1558 foreach (Expression iter in iterator_list) {
1559 stmt.add_iterator (iter);
1561 if (block != null) {
1562 block.add_statement (stmt);
1563 return block;
1564 } else {
1565 return stmt;
1569 Statement parse_foreach_statement () throws ParseError {
1570 var begin = get_location ();
1571 expect (TokenType.FOREACH);
1572 expect (TokenType.OPEN_PARENS);
1573 DataType type = null;
1574 if (!accept (TokenType.VAR)) {
1575 type = parse_type ();
1577 string id = parse_identifier ();
1578 expect (TokenType.IN);
1579 var collection = parse_expression ();
1580 expect (TokenType.CLOSE_PARENS);
1581 var src = get_src_com (begin);
1582 var body = parse_embedded_statement ();
1583 return new ForeachStatement (type, id, collection, body, src);
1586 Statement parse_break_statement () throws ParseError {
1587 var begin = get_location ();
1588 expect (TokenType.BREAK);
1589 expect (TokenType.SEMICOLON);
1590 return new BreakStatement (get_src_com (begin));
1593 Statement parse_continue_statement () throws ParseError {
1594 var begin = get_location ();
1595 expect (TokenType.CONTINUE);
1596 expect (TokenType.SEMICOLON);
1597 return new ContinueStatement (get_src_com (begin));
1600 Statement parse_return_statement () throws ParseError {
1601 var begin = get_location ();
1602 expect (TokenType.RETURN);
1603 Expression expr = null;
1604 if (current () != TokenType.SEMICOLON) {
1605 expr = parse_expression ();
1607 expect (TokenType.SEMICOLON);
1608 return new ReturnStatement (expr, get_src_com (begin));
1611 Statement parse_yield_statement () throws ParseError {
1612 var begin = get_location ();
1613 expect (TokenType.YIELD);
1614 Expression expr = null;
1615 if (current () != TokenType.SEMICOLON) {
1616 expr = parse_expression ();
1618 expect (TokenType.SEMICOLON);
1619 return new YieldStatement (expr, get_src (begin));
1622 Statement parse_throw_statement () throws ParseError {
1623 var begin = get_location ();
1624 expect (TokenType.THROW);
1625 var expr = parse_expression ();
1626 expect (TokenType.SEMICOLON);
1627 return new ThrowStatement (expr, get_src_com (begin));
1630 Statement parse_try_statement () throws ParseError {
1631 var begin = get_location ();
1632 expect (TokenType.TRY);
1633 var try_block = parse_block ();
1634 Block finally_clause = null;
1635 var catch_clauses = new ArrayList<CatchClause> ();
1636 if (current () == TokenType.CATCH) {
1637 parse_catch_clauses (catch_clauses);
1638 if (current () == TokenType.FINALLY) {
1639 finally_clause = parse_finally_clause ();
1641 } else {
1642 finally_clause = parse_finally_clause ();
1644 var stmt = new TryStatement (try_block, finally_clause, get_src_com (begin));
1645 foreach (CatchClause clause in catch_clauses) {
1646 stmt.add_catch_clause (clause);
1648 return stmt;
1651 void parse_catch_clauses (Gee.List<CatchClause> catch_clauses) throws ParseError {
1652 while (accept (TokenType.CATCH)) {
1653 var begin = get_location ();
1654 DataType type = null;
1655 string id = null;
1656 if (accept (TokenType.OPEN_PARENS)) {
1657 type = parse_type ();
1658 id = parse_identifier ();
1659 expect (TokenType.CLOSE_PARENS);
1661 var block = parse_block ();
1662 catch_clauses.add (new CatchClause (type, id, block, get_src (begin)));
1666 Block parse_finally_clause () throws ParseError {
1667 expect (TokenType.FINALLY);
1668 var block = parse_block ();
1669 return block;
1672 Statement parse_lock_statement () throws ParseError {
1673 var begin = get_location ();
1674 expect (TokenType.LOCK);
1675 expect (TokenType.OPEN_PARENS);
1676 var expr = parse_expression ();
1677 expect (TokenType.CLOSE_PARENS);
1678 var stmt = parse_embedded_statement ();
1679 return new LockStatement (expr, stmt, get_src_com (begin));
1682 Statement parse_delete_statement () throws ParseError {
1683 var begin = get_location ();
1684 expect (TokenType.DELETE);
1685 var expr = parse_expression ();
1686 expect (TokenType.SEMICOLON);
1687 return new DeleteStatement (expr, get_src_com (begin));
1690 Gee.List<Attribute>? parse_attributes () throws ParseError {
1691 if (current () != TokenType.OPEN_BRACKET) {
1692 return null;
1694 var attrs = new ArrayList<Attribute> ();
1695 while (accept (TokenType.OPEN_BRACKET)) {
1696 do {
1697 var begin = get_location ();
1698 string id = parse_identifier ();
1699 var attr = new Attribute (id, get_src (begin));
1700 if (accept (TokenType.OPEN_PARENS)) {
1701 if (current () != TokenType.CLOSE_PARENS) {
1702 do {
1703 id = parse_identifier ();
1704 expect (TokenType.ASSIGN);
1705 var expr = parse_expression ();
1706 attr.add_argument (id, expr);
1707 } while (accept (TokenType.COMMA));
1709 expect (TokenType.CLOSE_PARENS);
1711 attrs.add (attr);
1712 } while (accept (TokenType.COMMA));
1713 expect (TokenType.CLOSE_BRACKET);
1715 return attrs;
1718 void set_attributes (CodeNode node, Gee.List<Attribute>? attributes) {
1719 if (attributes != null) {
1720 foreach (Attribute attr in (Gee.List<Attribute>) attributes) {
1721 node.attributes.append (attr);
1726 Symbol parse_declaration () throws ParseError {
1727 comment = scanner.pop_comment ();
1728 var attrs = parse_attributes ();
1730 var begin = get_location ();
1732 TokenType last_keyword = current ();
1734 while (is_declaration_keyword (current ())) {
1735 last_keyword = current ();
1736 next ();
1739 switch (current ()) {
1740 case TokenType.CONSTRUCT:
1741 rollback (begin);
1742 return parse_constructor_declaration (attrs);
1743 case TokenType.TILDE:
1744 rollback (begin);
1745 return parse_destructor_declaration (attrs);
1746 default:
1747 skip_type ();
1748 switch (current ()) {
1749 case TokenType.OPEN_BRACE:
1750 case TokenType.SEMICOLON:
1751 case TokenType.COLON:
1752 rollback (begin);
1753 switch (last_keyword) {
1754 case TokenType.CLASS: return parse_class_declaration (attrs);
1755 case TokenType.ENUM: return parse_enum_declaration (attrs);
1756 case TokenType.ERRORDOMAIN: return parse_errordomain_declaration (attrs);
1757 case TokenType.INTERFACE: return parse_interface_declaration (attrs);
1758 case TokenType.NAMESPACE: return parse_namespace_declaration (attrs);
1759 case TokenType.STRUCT: return parse_struct_declaration (attrs);
1760 default: break;
1762 break;
1763 case TokenType.OPEN_PARENS:
1764 rollback (begin);
1765 return parse_creation_method_declaration (attrs);
1766 default:
1767 skip_type (); // might contain type parameter list
1768 switch (current ()) {
1769 case TokenType.OPEN_PARENS:
1770 rollback (begin);
1771 switch (last_keyword) {
1772 case TokenType.DELEGATE: return parse_delegate_declaration (attrs);
1773 case TokenType.SIGNAL: return parse_signal_declaration (attrs);
1774 default: return parse_method_declaration (attrs);
1776 case TokenType.ASSIGN:
1777 case TokenType.SEMICOLON:
1778 rollback (begin);
1779 switch (last_keyword) {
1780 case TokenType.CONST: return parse_constant_declaration (attrs);
1781 default: return parse_field_declaration (attrs);
1783 case TokenType.OPEN_BRACE:
1784 rollback (begin);
1785 return parse_property_declaration (attrs);
1786 default:
1787 break;
1789 break;
1791 break;
1794 rollback (begin);
1796 throw new ParseError.SYNTAX (get_error ("expected declaration"));
1799 void parse_declarations (Symbol parent, bool root = false) throws ParseError {
1800 if (!root) {
1801 expect (TokenType.OPEN_BRACE);
1803 while (current () != TokenType.CLOSE_BRACE && current () != TokenType.EOF) {
1804 try {
1805 if (parent is Namespace) {
1806 parse_namespace_member ((Namespace) parent);
1807 } else if (parent is Class) {
1808 parse_class_member ((Class) parent);
1809 } else if (parent is Struct) {
1810 parse_struct_member ((Struct) parent);
1811 } else if (parent is Interface) {
1812 parse_interface_member ((Interface) parent);
1814 } catch (ParseError e) {
1815 int r;
1816 do {
1817 r = recover ();
1818 if (r == RecoveryState.STATEMENT_BEGIN) {
1819 next ();
1820 } else {
1821 break;
1823 } while (true);
1824 if (r == RecoveryState.EOF) {
1825 return;
1829 if (!root) {
1830 if (!accept (TokenType.CLOSE_BRACE)) {
1831 // only report error if it's not a secondary error
1832 if (Report.get_errors () == 0) {
1833 Report.error (get_current_src (), "expected `}'");
1839 enum RecoveryState {
1840 EOF,
1841 DECLARATION_BEGIN,
1842 STATEMENT_BEGIN
1845 RecoveryState recover () {
1846 while (current () != TokenType.EOF) {
1847 switch (current ()) {
1848 case TokenType.ABSTRACT:
1849 case TokenType.CLASS:
1850 case TokenType.CONST:
1851 case TokenType.CONSTRUCT:
1852 case TokenType.DELEGATE:
1853 case TokenType.ENUM:
1854 case TokenType.ERRORDOMAIN:
1855 case TokenType.EXTERN:
1856 case TokenType.INLINE:
1857 case TokenType.INTERFACE:
1858 case TokenType.INTERNAL:
1859 case TokenType.NAMESPACE:
1860 case TokenType.OVERRIDE:
1861 case TokenType.PRIVATE:
1862 case TokenType.PROTECTED:
1863 case TokenType.PUBLIC:
1864 case TokenType.SIGNAL:
1865 case TokenType.STATIC:
1866 case TokenType.STRUCT:
1867 case TokenType.VIRTUAL:
1868 case TokenType.VOLATILE:
1869 return RecoveryState.DECLARATION_BEGIN;
1870 case TokenType.BREAK:
1871 case TokenType.CONTINUE:
1872 case TokenType.DELETE:
1873 case TokenType.DO:
1874 case TokenType.FOR:
1875 case TokenType.FOREACH:
1876 case TokenType.IF:
1877 case TokenType.LOCK:
1878 case TokenType.RETURN:
1879 case TokenType.SWITCH:
1880 case TokenType.THROW:
1881 case TokenType.TRY:
1882 case TokenType.VAR:
1883 case TokenType.WHILE:
1884 case TokenType.YIELD:
1885 return RecoveryState.STATEMENT_BEGIN;
1886 default:
1887 next ();
1888 break;
1891 return RecoveryState.EOF;
1894 Namespace parse_namespace_declaration (Gee.List<Attribute>? attrs) throws ParseError {
1895 var begin = get_location ();
1896 expect (TokenType.NAMESPACE);
1897 var sym = parse_symbol_name ();
1898 var ns = new Namespace (sym.name, get_src_com (begin));
1899 set_attributes (ns, attrs);
1900 parse_declarations (ns);
1902 Namespace result = ns;
1903 while (sym.inner != null) {
1904 sym = sym.inner;
1905 ns = new Namespace (sym.name, result.source_reference);
1906 ns.add_namespace ((Namespace) result);
1907 result = ns;
1909 return result;
1912 void parse_namespace_member (Namespace ns) throws ParseError {
1913 var sym = parse_declaration ();
1915 // namespaces do not support private memebers
1916 if (sym.access == SymbolAccessibility.PRIVATE) {
1917 sym.access = SymbolAccessibility.INTERNAL;
1920 if (sym is Namespace) {
1921 ns.add_namespace ((Namespace) sym);
1922 } else if (sym is Class) {
1923 ns.add_class ((Class) sym);
1924 } else if (sym is Interface) {
1925 ns.add_interface ((Interface) sym);
1926 } else if (sym is Struct) {
1927 ns.add_struct ((Struct) sym);
1928 } else if (sym is Enum) {
1929 ns.add_enum ((Enum) sym);
1930 } else if (sym is ErrorDomain) {
1931 ns.add_error_domain ((ErrorDomain) sym);
1932 } else if (sym is Delegate) {
1933 ns.add_delegate ((Delegate) sym);
1934 } else if (sym is Method) {
1935 var method = (Method) sym;
1936 if (method.binding == MemberBinding.INSTANCE) {
1937 // default to static member binding
1938 method.binding = MemberBinding.STATIC;
1940 ns.add_method (method);
1941 } else if (sym is Field) {
1942 var field = (Field) sym;
1943 if (field.binding == MemberBinding.INSTANCE) {
1944 // default to static member binding
1945 field.binding = MemberBinding.STATIC;
1947 ns.add_field (field);
1948 } else if (sym is Constant) {
1949 ns.add_constant ((Constant) sym);
1950 } else {
1951 Report.error (sym.source_reference, "unexpected declaration in namespace");
1953 scanner.source_file.add_node (sym);
1956 void parse_using_directives () throws ParseError {
1957 while (accept (TokenType.USING)) {
1958 do {
1959 var begin = get_location ();
1960 var sym = parse_symbol_name ();
1961 var ns_ref = new UsingDirective (sym, get_src (begin));
1962 scanner.source_file.add_using_directive (ns_ref);
1963 } while (accept (TokenType.COMMA));
1964 expect (TokenType.SEMICOLON);
1968 Symbol parse_class_declaration (Gee.List<Attribute>? attrs) throws ParseError {
1969 var begin = get_location ();
1970 var access = parse_access_modifier ();
1971 var flags = parse_type_declaration_modifiers ();
1972 expect (TokenType.CLASS);
1973 var sym = parse_symbol_name ();
1974 var type_param_list = parse_type_parameter_list ();
1975 var base_types = new ArrayList<DataType> ();
1976 if (accept (TokenType.COLON)) {
1977 do {
1978 base_types.add (parse_type ());
1979 } while (accept (TokenType.COMMA));
1982 var cl = new Class (sym.name, get_src_com (begin));
1983 cl.access = access;
1984 if (ModifierFlags.ABSTRACT in flags) {
1985 cl.is_abstract = true;
1987 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
1988 cl.external = true;
1990 set_attributes (cl, attrs);
1991 foreach (TypeParameter type_param in type_param_list) {
1992 cl.add_type_parameter (type_param);
1994 foreach (DataType base_type in base_types) {
1995 cl.add_base_type (base_type);
1998 parse_declarations (cl);
2000 // ensure there is always a default construction method
2001 if (!scanner.source_file.external_package
2002 && !cl.is_abstract
2003 && cl.default_construction_method == null) {
2004 var m = new CreationMethod (cl.name, null, cl.source_reference);
2005 m.access = SymbolAccessibility.PUBLIC;
2006 m.body = new Block (cl.source_reference);
2007 cl.add_method (m);
2010 Symbol result = cl;
2011 while (sym.inner != null) {
2012 sym = sym.inner;
2013 var ns = new Namespace (sym.name, cl.source_reference);
2014 if (result is Namespace) {
2015 ns.add_namespace ((Namespace) result);
2016 } else {
2017 ns.add_class ((Class) result);
2018 scanner.source_file.add_node (result);
2020 result = ns;
2022 return result;
2025 void parse_class_member (Class cl) throws ParseError {
2026 var sym = parse_declaration ();
2027 if (sym is Class) {
2028 cl.add_class ((Class) sym);
2029 } else if (sym is Struct) {
2030 cl.add_struct ((Struct) sym);
2031 } else if (sym is Enum) {
2032 cl.add_enum ((Enum) sym);
2033 } else if (sym is Delegate) {
2034 cl.add_delegate ((Delegate) sym);
2035 } else if (sym is Method) {
2036 cl.add_method ((Method) sym);
2037 } else if (sym is Signal) {
2038 cl.add_signal ((Signal) sym);
2039 } else if (sym is Field) {
2040 cl.add_field ((Field) sym);
2041 } else if (sym is Constant) {
2042 cl.add_constant ((Constant) sym);
2043 } else if (sym is Property) {
2044 cl.add_property ((Property) sym);
2045 } else if (sym is Constructor) {
2046 var c = (Constructor) sym;
2047 if (c.binding == MemberBinding.INSTANCE) {
2048 cl.constructor = c;
2049 } else if (c.binding == MemberBinding.CLASS) {
2050 cl.class_constructor = c;
2051 } else {
2052 cl.static_constructor = c;
2054 } else if (sym is Destructor) {
2055 var d = (Destructor) sym;
2056 if (d.binding == MemberBinding.STATIC) {
2057 cl.static_destructor = (Destructor) d;
2058 } else if (d.binding == MemberBinding.CLASS) {
2059 cl.class_destructor = (Destructor) d;
2060 } else {
2061 cl.destructor = (Destructor) d;
2063 } else {
2064 Report.error (sym.source_reference, "unexpected declaration in class");
2068 Constant parse_constant_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2069 var begin = get_location ();
2070 var access = parse_access_modifier ();
2071 var flags = parse_member_declaration_modifiers ();
2072 expect (TokenType.CONST);
2073 var type = parse_type (false);
2074 string id = parse_identifier ();
2075 Expression initializer = null;
2076 if (accept (TokenType.ASSIGN)) {
2077 initializer = parse_expression ();
2079 expect (TokenType.SEMICOLON);
2081 // constant arrays don't own their element
2082 var array_type = type as ArrayType;
2083 if (array_type != null) {
2084 array_type.element_type.value_owned = false;
2087 var c = new Constant (id, type, initializer, get_src_com (begin));
2088 c.access = access;
2089 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2090 c.external = true;
2092 set_attributes (c, attrs);
2093 return c;
2096 Field parse_field_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2097 var begin = get_location ();
2098 var access = parse_access_modifier ();
2099 var flags = parse_member_declaration_modifiers ();
2100 var type = parse_type ();
2101 string id = parse_identifier ();
2102 var f = new Field (id, type, null, get_src_com (begin));
2103 f.access = access;
2104 set_attributes (f, attrs);
2105 if (ModifierFlags.STATIC in flags) {
2106 f.binding = MemberBinding.STATIC;
2107 } else if (ModifierFlags.CLASS in flags) {
2108 f.binding = MemberBinding.CLASS;
2110 if (ModifierFlags.ABSTRACT in flags
2111 || ModifierFlags.VIRTUAL in flags
2112 || ModifierFlags.OVERRIDE in flags) {
2113 Report.error (f.source_reference, "abstract, virtual, and override modifiers are not applicable to fields");
2115 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2116 f.external = true;
2118 if (accept (TokenType.ASSIGN)) {
2119 f.initializer = parse_expression ();
2121 expect (TokenType.SEMICOLON);
2122 return f;
2125 InitializerList parse_initializer () throws ParseError {
2126 var begin = get_location ();
2127 expect (TokenType.OPEN_BRACE);
2128 var initializer = new InitializerList (get_src (begin));
2129 if (current () != TokenType.CLOSE_BRACE) {
2130 do {
2131 var init = parse_argument ();
2132 initializer.append (init);
2133 } while (accept (TokenType.COMMA));
2135 expect (TokenType.CLOSE_BRACE);
2136 return initializer;
2139 Method parse_method_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2140 var begin = get_location ();
2141 var access = parse_access_modifier ();
2142 var flags = parse_member_declaration_modifiers ();
2143 var type = parse_type ();
2144 string id = parse_identifier ();
2145 parse_type_parameter_list ();
2146 var method = new Method (id, type, get_src_com (begin));
2147 method.access = access;
2148 set_attributes (method, attrs);
2149 if (ModifierFlags.STATIC in flags) {
2150 method.binding = MemberBinding.STATIC;
2151 } else if (ModifierFlags.CLASS in flags) {
2152 method.binding = MemberBinding.CLASS;
2155 if (method.binding == MemberBinding.INSTANCE) {
2156 if (ModifierFlags.ABSTRACT in flags) {
2157 method.is_abstract = true;
2159 if (ModifierFlags.VIRTUAL in flags) {
2160 method.is_virtual = true;
2162 if (ModifierFlags.OVERRIDE in flags) {
2163 method.overrides = true;
2165 if ((method.is_abstract && method.is_virtual)
2166 || (method.is_abstract && method.overrides)
2167 || (method.is_virtual && method.overrides)) {
2168 throw new ParseError.SYNTAX (get_error ("only one of `abstract', `virtual', or `override' may be specified"));
2170 } else {
2171 if (ModifierFlags.ABSTRACT in flags
2172 || ModifierFlags.VIRTUAL in flags
2173 || ModifierFlags.OVERRIDE in flags) {
2174 throw new ParseError.SYNTAX (get_error ("the modifiers `abstract', `virtual', and `override' are not valid for static methods"));
2178 if (ModifierFlags.INLINE in flags) {
2179 method.is_inline = true;
2181 if (ModifierFlags.EXTERN in flags) {
2182 method.external = true;
2184 expect (TokenType.OPEN_PARENS);
2185 if (current () != TokenType.CLOSE_PARENS) {
2186 do {
2187 var param = parse_parameter ();
2188 method.add_parameter (param);
2189 } while (accept (TokenType.COMMA));
2191 expect (TokenType.CLOSE_PARENS);
2192 if (accept (TokenType.YIELDS)) {
2193 method.coroutine = true;
2195 if (accept (TokenType.THROWS)) {
2196 do {
2197 method.add_error_type (parse_type ());
2198 } while (accept (TokenType.COMMA));
2200 while (accept (TokenType.REQUIRES)) {
2201 expect (TokenType.OPEN_PARENS);
2202 method.add_precondition (parse_expression ());
2203 expect (TokenType.CLOSE_PARENS);
2205 while (accept (TokenType.ENSURES)) {
2206 expect (TokenType.OPEN_PARENS);
2207 method.add_postcondition (parse_expression ());
2208 expect (TokenType.CLOSE_PARENS);
2210 if (!accept (TokenType.SEMICOLON)) {
2211 method.body = parse_block ();
2212 } else if (scanner.source_file.external_package) {
2213 method.external = true;
2215 return method;
2218 Property parse_property_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2219 var begin = get_location ();
2220 var access = parse_access_modifier ();
2221 var flags = parse_member_declaration_modifiers ();
2222 var type = parse_type ();
2224 bool getter_owned = false;
2225 if (accept (TokenType.HASH)) {
2226 if (!context.deprecated) {
2227 Report.warning (get_last_src (), "deprecated syntax, use `owned` modifier before `get'");
2229 getter_owned = true;
2232 string id = parse_identifier ();
2233 var prop = new Property (id, type, null, null, get_src_com (begin));
2234 prop.access = access;
2235 set_attributes (prop, attrs);
2236 if (ModifierFlags.STATIC in flags) {
2237 prop.binding = MemberBinding.STATIC;
2238 } else if (ModifierFlags.CLASS in flags) {
2239 prop.binding = MemberBinding.CLASS;
2241 if (ModifierFlags.ABSTRACT in flags) {
2242 prop.is_abstract = true;
2244 if (ModifierFlags.VIRTUAL in flags) {
2245 prop.is_virtual = true;
2247 if (ModifierFlags.OVERRIDE in flags) {
2248 prop.overrides = true;
2250 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2251 prop.external = true;
2253 expect (TokenType.OPEN_BRACE);
2254 while (current () != TokenType.CLOSE_BRACE) {
2255 if (accept (TokenType.DEFAULT)) {
2256 if (prop.default_expression != null) {
2257 throw new ParseError.SYNTAX (get_error ("property default value already defined"));
2259 expect (TokenType.ASSIGN);
2260 prop.default_expression = parse_expression ();
2261 expect (TokenType.SEMICOLON);
2262 } else {
2263 var accessor_begin = get_location ();
2264 var attrs = parse_attributes ();
2265 var accessor_access = parse_access_modifier (SymbolAccessibility.PUBLIC);
2267 var value_type = type.copy ();
2268 value_type.value_owned = accept (TokenType.OWNED);
2270 if (accept (TokenType.GET)) {
2271 if (prop.get_accessor != null) {
2272 throw new ParseError.SYNTAX (get_error ("property get accessor already defined"));
2275 if (getter_owned) {
2276 value_type.value_owned = true;
2279 Block block = null;
2280 if (!accept (TokenType.SEMICOLON)) {
2281 block = parse_block ();
2282 prop.external = false;
2284 prop.get_accessor = new PropertyAccessor (true, false, false, value_type, block, get_src (accessor_begin));
2285 set_attributes (prop.get_accessor, attrs);
2286 prop.get_accessor.access = accessor_access;
2287 } else {
2288 bool writable, _construct;
2289 if (accept (TokenType.SET)) {
2290 writable = true;
2291 _construct = accept (TokenType.CONSTRUCT);
2292 } else if (accept (TokenType.CONSTRUCT)) {
2293 _construct = true;
2294 writable = accept (TokenType.SET);
2295 } else {
2296 throw new ParseError.SYNTAX (get_error ("expected get, set, or construct"));
2298 if (prop.set_accessor != null) {
2299 throw new ParseError.SYNTAX (get_error ("property set accessor already defined"));
2301 Block block = null;
2302 if (!accept (TokenType.SEMICOLON)) {
2303 block = parse_block ();
2304 prop.external = false;
2306 prop.set_accessor = new PropertyAccessor (false, writable, _construct, value_type, block, get_src (accessor_begin));
2307 set_attributes (prop.set_accessor, attrs);
2308 prop.set_accessor.access = accessor_access;
2312 expect (TokenType.CLOSE_BRACE);
2314 if (!prop.is_abstract && !scanner.source_file.external_package) {
2315 bool empty_get = (prop.get_accessor != null && prop.get_accessor.body == null);
2316 bool empty_set = (prop.set_accessor != null && prop.set_accessor.body == null);
2318 if (empty_get != empty_set) {
2319 if (empty_get) {
2320 Report.error (prop.source_reference, "property getter must have a body");
2321 } else if (empty_set) {
2322 Report.error (prop.source_reference, "property setter must have a body");
2324 prop.error = true;
2327 if (empty_get && empty_set) {
2328 /* automatic property accessor body generation */
2329 var field_type = prop.property_type.copy ();
2330 prop.field = new Field ("_%s".printf (prop.name), field_type, prop.default_expression, prop.source_reference);
2331 prop.field.access = SymbolAccessibility.PRIVATE;
2335 return prop;
2338 Signal parse_signal_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2339 var begin = get_location ();
2340 var access = parse_access_modifier ();
2341 var flags = parse_member_declaration_modifiers ();
2342 expect (TokenType.SIGNAL);
2343 var type = parse_type ();
2344 string id = parse_identifier ();
2345 var sig = new Signal (id, type, get_src_com (begin));
2346 sig.access = access;
2347 set_attributes (sig, attrs);
2348 if (ModifierFlags.VIRTUAL in flags) {
2349 sig.is_virtual = true;
2351 expect (TokenType.OPEN_PARENS);
2352 if (current () != TokenType.CLOSE_PARENS) {
2353 do {
2354 var param = parse_parameter ();
2355 sig.add_parameter (param);
2356 } while (accept (TokenType.COMMA));
2358 expect (TokenType.CLOSE_PARENS);
2359 expect (TokenType.SEMICOLON);
2360 return sig;
2363 Constructor parse_constructor_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2364 var begin = get_location ();
2365 var flags = parse_member_declaration_modifiers ();
2366 expect (TokenType.CONSTRUCT);
2367 var c = new Constructor (get_src_com (begin));
2368 if (ModifierFlags.STATIC in flags) {
2369 c.binding = MemberBinding.STATIC;
2370 } else if (ModifierFlags.CLASS in flags) {
2371 c.binding = MemberBinding.CLASS;
2373 c.body = parse_block ();
2374 return c;
2377 Destructor parse_destructor_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2378 var begin = get_location ();
2379 var flags = parse_member_declaration_modifiers ();
2380 expect (TokenType.TILDE);
2381 parse_identifier ();
2382 expect (TokenType.OPEN_PARENS);
2383 expect (TokenType.CLOSE_PARENS);
2384 var d = new Destructor (get_src_com (begin));
2385 if (ModifierFlags.STATIC in flags) {
2386 d.binding = MemberBinding.STATIC;
2387 } else if (ModifierFlags.CLASS in flags) {
2388 d.binding = MemberBinding.CLASS;
2390 d.body = parse_block ();
2391 return d;
2394 Symbol parse_struct_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2395 var begin = get_location ();
2396 var access = parse_access_modifier ();
2397 var flags = parse_type_declaration_modifiers ();
2398 expect (TokenType.STRUCT);
2399 var sym = parse_symbol_name ();
2400 var type_param_list = parse_type_parameter_list ();
2401 var base_types = new ArrayList<DataType> ();
2402 if (accept (TokenType.COLON)) {
2403 do {
2404 base_types.add (parse_type ());
2405 } while (accept (TokenType.COMMA));
2407 var st = new Struct (sym.name, get_src_com (begin));
2408 st.access = access;
2409 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2410 st.external = true;
2412 set_attributes (st, attrs);
2413 foreach (TypeParameter type_param in type_param_list) {
2414 st.add_type_parameter (type_param);
2416 foreach (DataType base_type in base_types) {
2417 st.add_base_type (base_type);
2420 parse_declarations (st);
2422 Symbol result = st;
2423 while (sym.inner != null) {
2424 sym = sym.inner;
2425 var ns = new Namespace (sym.name, st.source_reference);
2426 if (result is Namespace) {
2427 ns.add_namespace ((Namespace) result);
2428 } else {
2429 ns.add_struct ((Struct) result);
2430 scanner.source_file.add_node (result);
2432 result = ns;
2434 return result;
2437 void parse_struct_member (Struct st) throws ParseError {
2438 var sym = parse_declaration ();
2439 if (sym is Method) {
2440 st.add_method ((Method) sym);
2441 } else if (sym is Field) {
2442 st.add_field ((Field) sym);
2443 } else if (sym is Constant) {
2444 st.add_constant ((Constant) sym);
2445 } else {
2446 Report.error (sym.source_reference, "unexpected declaration in struct");
2450 Symbol parse_interface_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2451 var begin = get_location ();
2452 var access = parse_access_modifier ();
2453 var flags = parse_type_declaration_modifiers ();
2454 expect (TokenType.INTERFACE);
2455 var sym = parse_symbol_name ();
2456 var type_param_list = parse_type_parameter_list ();
2457 var base_types = new ArrayList<DataType> ();
2458 if (accept (TokenType.COLON)) {
2459 do {
2460 var type = parse_type ();
2461 base_types.add (type);
2462 } while (accept (TokenType.COMMA));
2464 var iface = new Interface (sym.name, get_src_com (begin));
2465 iface.access = access;
2466 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2467 iface.external = true;
2469 set_attributes (iface, attrs);
2470 foreach (TypeParameter type_param in type_param_list) {
2471 iface.add_type_parameter (type_param);
2473 foreach (DataType base_type in base_types) {
2474 iface.add_prerequisite (base_type);
2477 parse_declarations (iface);
2479 Symbol result = iface;
2480 while (sym.inner != null) {
2481 sym = sym.inner;
2482 var ns = new Namespace (sym.name, iface.source_reference);
2483 if (result is Namespace) {
2484 ns.add_namespace ((Namespace) result);
2485 } else {
2486 ns.add_interface ((Interface) result);
2487 scanner.source_file.add_node (result);
2489 result = ns;
2491 return result;
2494 void parse_interface_member (Interface iface) throws ParseError {
2495 var sym = parse_declaration ();
2496 if (sym is Class) {
2497 iface.add_class ((Class) sym);
2498 } else if (sym is Struct) {
2499 iface.add_struct ((Struct) sym);
2500 } else if (sym is Enum) {
2501 iface.add_enum ((Enum) sym);
2502 } else if (sym is Delegate) {
2503 iface.add_delegate ((Delegate) sym);
2504 } else if (sym is Method) {
2505 iface.add_method ((Method) sym);
2506 } else if (sym is Signal) {
2507 iface.add_signal ((Signal) sym);
2508 } else if (sym is Field) {
2509 iface.add_field ((Field) sym);
2510 } else if (sym is Property) {
2511 iface.add_property ((Property) sym);
2512 } else {
2513 Report.error (sym.source_reference, "unexpected declaration in interface");
2517 Symbol parse_enum_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2518 var begin = get_location ();
2519 var access = parse_access_modifier ();
2520 var flags = parse_type_declaration_modifiers ();
2521 expect (TokenType.ENUM);
2522 var sym = parse_symbol_name ();
2523 var en = new Enum (sym.name, get_src_com (begin));
2524 en.access = access;
2525 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2526 en.external = true;
2528 set_attributes (en, attrs);
2530 expect (TokenType.OPEN_BRACE);
2531 do {
2532 if (current () == TokenType.CLOSE_BRACE
2533 && en.get_values ().size > 0) {
2534 // allow trailing comma
2535 break;
2537 var value_attrs = parse_attributes ();
2538 var value_begin = get_location ();
2539 string id = parse_identifier ();
2540 var ev = new EnumValue (id, get_src (value_begin));
2541 set_attributes (ev, value_attrs);
2542 if (accept (TokenType.ASSIGN)) {
2543 ev.value = parse_expression ();
2545 en.add_value (ev);
2546 } while (accept (TokenType.COMMA));
2547 if (accept (TokenType.SEMICOLON)) {
2548 // enum methods
2549 while (current () != TokenType.CLOSE_BRACE) {
2550 var member_sym = parse_declaration ();
2551 if (member_sym is Method) {
2552 en.add_method ((Method) member_sym);
2553 } else {
2554 Report.error (member_sym.source_reference, "unexpected declaration in enum");
2558 expect (TokenType.CLOSE_BRACE);
2560 Symbol result = en;
2561 while (sym.inner != null) {
2562 sym = sym.inner;
2563 var ns = new Namespace (sym.name, en.source_reference);
2564 if (result is Namespace) {
2565 ns.add_namespace ((Namespace) result);
2566 } else {
2567 ns.add_enum ((Enum) result);
2568 scanner.source_file.add_node (result);
2570 result = ns;
2572 return result;
2575 Symbol parse_errordomain_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2576 var begin = get_location ();
2577 var access = parse_access_modifier ();
2578 var flags = parse_type_declaration_modifiers ();
2579 expect (TokenType.ERRORDOMAIN);
2580 var sym = parse_symbol_name ();
2581 var ed = new ErrorDomain (sym.name, get_src_com (begin));
2582 ed.access = access;
2583 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2584 ed.external = true;
2586 set_attributes (ed, attrs);
2588 expect (TokenType.OPEN_BRACE);
2589 do {
2590 if (current () == TokenType.CLOSE_BRACE
2591 && ed.get_codes ().size > 0) {
2592 // allow trailing comma
2593 break;
2595 var code_attrs = parse_attributes ();
2596 var code_begin = get_location ();
2597 string id = parse_identifier ();
2598 var ec = new ErrorCode (id, get_src (code_begin));
2599 set_attributes (ec, code_attrs);
2600 if (accept (TokenType.ASSIGN)) {
2601 ec.value = parse_expression ();
2603 ed.add_code (ec);
2604 } while (accept (TokenType.COMMA));
2605 if (accept (TokenType.SEMICOLON)) {
2606 // errordomain methods
2607 while (current () != TokenType.CLOSE_BRACE) {
2608 var member_sym = parse_declaration ();
2609 if (member_sym is Method) {
2610 ed.add_method ((Method) member_sym);
2611 } else {
2612 Report.error (member_sym.source_reference, "unexpected declaration in errordomain");
2616 expect (TokenType.CLOSE_BRACE);
2618 Symbol result = ed;
2619 while (sym.inner != null) {
2620 sym = sym.inner;
2621 var ns = new Namespace (sym.name, ed.source_reference);
2622 if (result is Namespace) {
2623 ns.add_namespace ((Namespace) result);
2624 } else {
2625 ns.add_error_domain ((ErrorDomain) result);
2626 scanner.source_file.add_node (result);
2628 result = ns;
2630 return result;
2633 SymbolAccessibility parse_access_modifier (SymbolAccessibility default_access = SymbolAccessibility.PRIVATE) {
2634 switch (current ()) {
2635 case TokenType.PRIVATE:
2636 next ();
2637 return SymbolAccessibility.PRIVATE;
2638 case TokenType.PROTECTED:
2639 next ();
2640 return SymbolAccessibility.PROTECTED;
2641 case TokenType.INTERNAL:
2642 next ();
2643 return SymbolAccessibility.INTERNAL;
2644 case TokenType.PUBLIC:
2645 next ();
2646 return SymbolAccessibility.PUBLIC;
2647 default:
2648 return default_access;
2652 ModifierFlags parse_type_declaration_modifiers () {
2653 ModifierFlags flags = 0;
2654 while (true) {
2655 switch (current ()) {
2656 case TokenType.ABSTRACT:
2657 next ();
2658 flags |= ModifierFlags.ABSTRACT;
2659 break;
2660 case TokenType.EXTERN:
2661 next ();
2662 flags |= ModifierFlags.EXTERN;
2663 break;
2664 case TokenType.STATIC:
2665 next ();
2666 flags |= ModifierFlags.STATIC;
2667 break;
2668 default:
2669 return flags;
2674 ModifierFlags parse_member_declaration_modifiers () {
2675 ModifierFlags flags = 0;
2676 while (true) {
2677 switch (current ()) {
2678 case TokenType.ABSTRACT:
2679 next ();
2680 flags |= ModifierFlags.ABSTRACT;
2681 break;
2682 case TokenType.CLASS:
2683 next ();
2684 flags |= ModifierFlags.CLASS;
2685 break;
2686 case TokenType.EXTERN:
2687 next ();
2688 flags |= ModifierFlags.EXTERN;
2689 break;
2690 case TokenType.INLINE:
2691 next ();
2692 flags |= ModifierFlags.INLINE;
2693 break;
2694 case TokenType.OVERRIDE:
2695 next ();
2696 flags |= ModifierFlags.OVERRIDE;
2697 break;
2698 case TokenType.STATIC:
2699 next ();
2700 flags |= ModifierFlags.STATIC;
2701 break;
2702 case TokenType.VIRTUAL:
2703 next ();
2704 flags |= ModifierFlags.VIRTUAL;
2705 break;
2706 default:
2707 return flags;
2712 FormalParameter parse_parameter () throws ParseError {
2713 var attrs = parse_attributes ();
2714 var begin = get_location ();
2715 if (accept (TokenType.ELLIPSIS)) {
2716 // varargs
2717 return new FormalParameter.with_ellipsis (get_src (begin));
2719 bool params_array = accept (TokenType.PARAMS);
2720 var direction = ParameterDirection.IN;
2721 if (accept (TokenType.OUT)) {
2722 direction = ParameterDirection.OUT;
2723 } else if (accept (TokenType.REF)) {
2724 direction = ParameterDirection.REF;
2727 DataType type;
2728 if (direction == ParameterDirection.IN) {
2729 // in parameters are weak by default
2730 type = parse_type (false);
2731 } else {
2732 // out parameters own the value by default
2733 type = parse_type (true);
2735 string id = parse_identifier ();
2736 var param = new FormalParameter (id, type, get_src (begin));
2737 set_attributes (param, attrs);
2738 param.direction = direction;
2739 param.params_array = params_array;
2740 if (accept (TokenType.ASSIGN)) {
2741 param.default_expression = parse_expression ();
2743 return param;
2746 CreationMethod parse_creation_method_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2747 var begin = get_location ();
2748 var access = parse_access_modifier ();
2749 var flags = parse_member_declaration_modifiers ();
2750 var sym = parse_symbol_name ();
2751 CreationMethod method;
2752 if (sym.inner == null) {
2753 method = new CreationMethod (sym.name, null, get_src_com (begin));
2754 } else {
2755 method = new CreationMethod (sym.inner.name, sym.name, get_src_com (begin));
2757 if (ModifierFlags.EXTERN in flags) {
2758 method.external = true;
2760 expect (TokenType.OPEN_PARENS);
2761 if (current () != TokenType.CLOSE_PARENS) {
2762 do {
2763 var param = parse_parameter ();
2764 method.add_parameter (param);
2765 } while (accept (TokenType.COMMA));
2767 expect (TokenType.CLOSE_PARENS);
2768 if (accept (TokenType.YIELDS)) {
2769 method.coroutine = true;
2771 if (accept (TokenType.THROWS)) {
2772 do {
2773 method.add_error_type (parse_type ());
2774 } while (accept (TokenType.COMMA));
2776 method.access = access;
2777 set_attributes (method, attrs);
2778 if (!accept (TokenType.SEMICOLON)) {
2779 method.body = parse_block ();
2780 } else if (scanner.source_file.external_package) {
2781 method.external = true;
2783 return method;
2786 Symbol parse_delegate_declaration (Gee.List<Attribute>? attrs) throws ParseError {
2787 var begin = get_location ();
2788 var access = parse_access_modifier ();
2789 var flags = parse_member_declaration_modifiers ();
2790 expect (TokenType.DELEGATE);
2791 var type = parse_type ();
2792 var sym = parse_symbol_name ();
2793 var type_param_list = parse_type_parameter_list ();
2794 var d = new Delegate (sym.name, type, get_src_com (begin));
2795 d.access = access;
2796 set_attributes (d, attrs);
2797 if (!(ModifierFlags.STATIC in flags)) {
2798 d.has_target = true;
2800 if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
2801 d.external = true;
2803 foreach (TypeParameter type_param in type_param_list) {
2804 d.add_type_parameter (type_param);
2806 expect (TokenType.OPEN_PARENS);
2807 if (current () != TokenType.CLOSE_PARENS) {
2808 do {
2809 var param = parse_parameter ();
2810 d.add_parameter (param);
2811 } while (accept (TokenType.COMMA));
2813 expect (TokenType.CLOSE_PARENS);
2814 if (accept (TokenType.THROWS)) {
2815 do {
2816 d.add_error_type (parse_type ());
2817 } while (accept (TokenType.COMMA));
2819 expect (TokenType.SEMICOLON);
2821 Symbol result = d;
2822 while (sym.inner != null) {
2823 sym = sym.inner;
2824 var ns = new Namespace (sym.name, d.source_reference);
2825 if (result is Namespace) {
2826 ns.add_namespace ((Namespace) result);
2827 } else {
2828 ns.add_delegate ((Delegate) result);
2829 scanner.source_file.add_node (result);
2831 result = ns;
2833 return result;
2836 Gee.List<TypeParameter> parse_type_parameter_list () throws ParseError {
2837 var list = new ArrayList<TypeParameter> ();
2838 if (accept (TokenType.OP_LT)) {
2839 do {
2840 var begin = get_location ();
2841 string id = parse_identifier ();
2842 list.add (new TypeParameter (id, get_src (begin)));
2843 } while (accept (TokenType.COMMA));
2844 expect (TokenType.OP_GT);
2846 return list;
2849 void skip_type_argument_list () throws ParseError {
2850 if (accept (TokenType.OP_LT)) {
2851 do {
2852 skip_type ();
2853 } while (accept (TokenType.COMMA));
2854 expect (TokenType.OP_GT);
2858 // try to parse type argument list
2859 Gee.List<DataType>? parse_type_argument_list (bool maybe_expression) throws ParseError {
2860 var begin = get_location ();
2861 if (accept (TokenType.OP_LT)) {
2862 var list = new ArrayList<DataType> ();
2863 do {
2864 switch (current ()) {
2865 case TokenType.VOID:
2866 case TokenType.DYNAMIC:
2867 case TokenType.UNOWNED:
2868 case TokenType.WEAK:
2869 case TokenType.IDENTIFIER:
2870 var type = parse_type ();
2871 list.add (type);
2872 break;
2873 default:
2874 rollback (begin);
2875 return null;
2877 } while (accept (TokenType.COMMA));
2878 if (!accept (TokenType.OP_GT)) {
2879 rollback (begin);
2880 return null;
2882 if (maybe_expression) {
2883 // check follower to decide whether to keep type argument list
2884 switch (current ()) {
2885 case TokenType.OPEN_PARENS:
2886 case TokenType.CLOSE_PARENS:
2887 case TokenType.CLOSE_BRACKET:
2888 case TokenType.COLON:
2889 case TokenType.SEMICOLON:
2890 case TokenType.COMMA:
2891 case TokenType.DOT:
2892 case TokenType.INTERR:
2893 case TokenType.OP_EQ:
2894 case TokenType.OP_NE:
2895 // keep type argument list
2896 break;
2897 default:
2898 // interpret tokens as expression
2899 rollback (begin);
2900 return null;
2903 return list;
2905 return null;
2908 MemberAccess parse_member_name () throws ParseError {
2909 var begin = get_location ();
2910 MemberAccess expr = null;
2911 bool first = true;
2912 do {
2913 string id = parse_identifier ();
2915 // The first member access can be global:: qualified
2916 bool qualified = false;
2917 if (first && id == "global" && accept (TokenType.DOUBLE_COLON)) {
2918 id = parse_identifier ();
2919 qualified = true;
2922 Gee.List<DataType> type_arg_list = parse_type_argument_list (false);
2923 expr = new MemberAccess (expr, id, get_src (begin));
2924 expr.qualified = qualified;
2925 if (type_arg_list != null) {
2926 foreach (DataType type_arg in type_arg_list) {
2927 expr.add_type_argument (type_arg);
2931 first = false;
2932 } while (accept (TokenType.DOT));
2933 return expr;
2936 bool is_declaration_keyword (TokenType type) {
2937 switch (type) {
2938 case TokenType.ABSTRACT:
2939 case TokenType.CLASS:
2940 case TokenType.CONST:
2941 case TokenType.DELEGATE:
2942 case TokenType.ENUM:
2943 case TokenType.ERRORDOMAIN:
2944 case TokenType.EXTERN:
2945 case TokenType.INLINE:
2946 case TokenType.INTERFACE:
2947 case TokenType.INTERNAL:
2948 case TokenType.NAMESPACE:
2949 case TokenType.OVERRIDE:
2950 case TokenType.PRIVATE:
2951 case TokenType.PROTECTED:
2952 case TokenType.PUBLIC:
2953 case TokenType.SIGNAL:
2954 case TokenType.STATIC:
2955 case TokenType.STRUCT:
2956 case TokenType.VIRTUAL:
2957 case TokenType.VOLATILE:
2958 return true;
2959 default:
2960 return false;
2965 public errordomain Vala.ParseError {
2966 FAILED,
2967 SYNTAX