Line data Source code
1 : /* valagenieparser.vala
2 : *
3 : * Copyright (C) 2008-2012 Jamie McCracken, Jürg Billeter
4 : * Based on code by Jürg Billeter
5 : *
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.
10 :
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.
15 :
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
19 : *
20 : * Author:
21 : * Jamie McCracken jamiemcc gnome org
22 : */
23 :
24 : using GLib;
25 :
26 :
27 : /**
28 : * Code visitor parsing all Genie source files.
29 : */
30 1467 : public class Vala.Genie.Parser : CodeVisitor {
31 1467 : Scanner scanner;
32 :
33 1467 : CodeContext context;
34 :
35 : // token buffer
36 1467 : TokenInfo[] tokens;
37 : // index of current token in buffer
38 : int index;
39 : // number of tokens in buffer
40 : int size;
41 :
42 1467 : Comment comment;
43 :
44 1467 : string class_name;
45 :
46 : /* hack needed to know if any part of an expression is a lambda one */
47 : bool current_expr_is_lambda;
48 :
49 : const int BUFFER_SIZE = 32;
50 :
51 : static List<TypeParameter> _empty_type_parameter_list;
52 :
53 : struct TokenInfo {
54 : public TokenType type;
55 : public SourceLocation begin;
56 : public SourceLocation end;
57 : }
58 :
59 : [Flags]
60 : enum ModifierFlags {
61 : NONE = 0,
62 : ABSTRACT,
63 : CLASS,
64 : EXTERN,
65 : INLINE,
66 : NEW,
67 : OVERRIDE,
68 : STATIC,
69 : VIRTUAL,
70 : PRIVATE,
71 : ASYNC,
72 : SEALED,
73 : PUBLIC,
74 : PROTECTED
75 : }
76 :
77 2934 : public Parser () {
78 1467 : tokens = new TokenInfo[BUFFER_SIZE];
79 1467 : class_name = null;
80 1467 : current_expr_is_lambda = false;
81 : }
82 :
83 : /**
84 : * Parses all .gs source files in the specified code context and
85 : * builds a code tree.
86 : *
87 : * @param context a code context
88 : */
89 1467 : public void parse (CodeContext context) {
90 1467 : this.context = context;
91 1467 : context.accept (this);
92 1467 : this.context = null;
93 : }
94 :
95 6309 : public override void visit_source_file (SourceFile source_file) {
96 6309 : if (source_file.filename.has_suffix (".gs")) {
97 85 : parse_file (source_file);
98 : }
99 : }
100 :
101 3270 : inline bool next () {
102 3270 : index = (index + 1) % BUFFER_SIZE;
103 3270 : size--;
104 3270 : if (size <= 0) {
105 : SourceLocation begin, end;
106 2988 : TokenType type = scanner.read_token (out begin, out end);
107 2988 : tokens[index] = { type, begin, end };
108 2988 : size = 1;
109 : }
110 3270 : return (tokens[index].type != TokenType.EOF);
111 : }
112 :
113 121 : inline void prev () {
114 121 : index = (index - 1 + BUFFER_SIZE) % BUFFER_SIZE;
115 121 : size++;
116 121 : assert (size <= BUFFER_SIZE);
117 : }
118 :
119 21909 : inline TokenType current () {
120 21909 : return tokens[index].type;
121 : }
122 :
123 10355 : inline bool accept (TokenType type) {
124 10355 : if (current () == type) {
125 1741 : next ();
126 1741 : return true;
127 : }
128 10355 : return false;
129 : }
130 :
131 5 : inline bool accept_separator () {
132 5 : if (current () == TokenType.COMMA || current () == TokenType.EOL) {
133 5 : next ();
134 5 : return true;
135 : }
136 5 : return false;
137 : }
138 :
139 414 : inline bool accept_terminator () {
140 414 : if (current () == TokenType.SEMICOLON || current () == TokenType.EOL) {
141 316 : next ();
142 316 : return true;
143 : }
144 414 : return false;
145 : }
146 :
147 116 : inline bool accept_block () {
148 :
149 116 : bool has_term = accept_terminator ();
150 :
151 116 : if (accept (TokenType.INDENT)) {
152 110 : prev();
153 110 : return true;
154 : }
155 :
156 6 : if (has_term) {
157 5 : prev ();
158 : }
159 :
160 116 : return false;
161 : }
162 :
163 0 : void report_parse_error (ParseError e) {
164 0 : var begin = get_location ();
165 0 : next ();
166 0 : Report.error (get_src (begin), "syntax error, %s", e.message);
167 : }
168 :
169 1111 : inline bool expect (TokenType type) throws ParseError {
170 1111 : if (accept (type)) {
171 : return true;
172 : }
173 :
174 0 : TokenType cur = current ();
175 0 : TokenType pre = tokens[index - 1].type;
176 :
177 0 : throw new ParseError.SYNTAX ("expected %s but got %s with previous %s", type.to_string (), cur.to_string (), pre.to_string());
178 : }
179 :
180 5 : inline bool expect_separator () throws ParseError {
181 5 : if (accept_separator ()) {
182 : return true;
183 : }
184 :
185 0 : TokenType cur = current ();
186 :
187 0 : throw new ParseError.SYNTAX ("expected line end or comma but got %s", cur.to_string());
188 : }
189 :
190 297 : inline bool expect_terminator () throws ParseError {
191 297 : if (accept_terminator ()) {
192 : return true;
193 : }
194 :
195 0 : TokenType cur = current ();
196 :
197 0 : throw new ParseError.SYNTAX ("expected line end or semicolon but got %s", cur.to_string());
198 : }
199 :
200 11140 : inline SourceLocation get_location () {
201 11140 : return tokens[index].begin;
202 : }
203 :
204 0 : string get_current_string () {
205 0 : var token = tokens[index];
206 0 : return ((string) token.begin.pos).substring (0, (int) (token.end.pos - token.begin.pos));
207 : }
208 :
209 785 : string get_last_string () {
210 785 : int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE;
211 785 : var token = tokens[last_index];
212 785 : return ((string) token.begin.pos).substring (0, (int) (token.end.pos - token.begin.pos));
213 : }
214 :
215 2193 : SourceReference get_src (SourceLocation begin) {
216 2193 : int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE;
217 :
218 2193 : return new SourceReference (scanner.source_file, begin, tokens[last_index].end);
219 : }
220 :
221 141 : SourceReference get_current_src () {
222 141 : var token = tokens[index];
223 141 : return new SourceReference (scanner.source_file, token.begin, token.end);
224 : }
225 :
226 135 : void rollback (SourceLocation location) {
227 296 : while (tokens[index].begin.pos != location.pos) {
228 161 : index = (index - 1 + BUFFER_SIZE) % BUFFER_SIZE;
229 161 : size++;
230 161 : if (size > BUFFER_SIZE) {
231 0 : scanner.seek (location);
232 0 : size = 0;
233 0 : index = 0;
234 :
235 0 : next ();
236 : }
237 : }
238 : }
239 :
240 50 : inline SymbolAccessibility get_default_accessibility (string s) {
241 50 : if (s.has_prefix("_")) {
242 : return SymbolAccessibility.PRIVATE;
243 : }
244 :
245 : return SymbolAccessibility.PUBLIC;
246 : }
247 :
248 655 : void skip_identifier () throws ParseError {
249 : // also accept keywords as identifiers where there is no conflict
250 655 : switch (current ()) {
251 : case TokenType.ABSTRACT:
252 : case TokenType.AS:
253 : case TokenType.ASSERT:
254 : case TokenType.ASYNC:
255 : case TokenType.BREAK:
256 : case TokenType.CLASS:
257 : case TokenType.CONST:
258 : case TokenType.CONTINUE:
259 : case TokenType.DEDENT:
260 : case TokenType.DEF:
261 : case TokenType.DEFAULT:
262 : case TokenType.DELEGATE:
263 : case TokenType.DELETE:
264 : case TokenType.DO:
265 : case TokenType.DOWNTO:
266 : case TokenType.DYNAMIC:
267 : case TokenType.ELSE:
268 : case TokenType.EOL:
269 : case TokenType.ENUM:
270 : case TokenType.ENSURES:
271 : case TokenType.EVENT:
272 : case TokenType.EXCEPT:
273 : case TokenType.EXCEPTION:
274 : case TokenType.EXTERN:
275 : case TokenType.FALSE:
276 : case TokenType.FINAL:
277 : case TokenType.FINALLY:
278 : case TokenType.FOR:
279 : case TokenType.GET:
280 : case TokenType.IDENTIFIER:
281 : case TokenType.IF:
282 : case TokenType.IN:
283 : case TokenType.INDENT:
284 : case TokenType.INIT:
285 : case TokenType.INLINE:
286 : case TokenType.INTERFACE:
287 : case TokenType.INTERNAL:
288 : case TokenType.IS:
289 : case TokenType.ISA:
290 : case TokenType.LOCK:
291 : case TokenType.NAMESPACE:
292 : case TokenType.NEW:
293 : case TokenType.NULL:
294 : case TokenType.OF:
295 : case TokenType.OUT:
296 : case TokenType.OVERRIDE:
297 : case TokenType.OWNED:
298 : case TokenType.PASS:
299 : case TokenType.PRINT:
300 : case TokenType.PRIVATE:
301 : case TokenType.PROTECTED:
302 : case TokenType.PROP:
303 : case TokenType.RAISE:
304 : case TokenType.RAISES:
305 : case TokenType.REF:
306 : case TokenType.REQUIRES:
307 : case TokenType.RETURN:
308 : case TokenType.SEALED:
309 : case TokenType.SELF:
310 : case TokenType.SET:
311 : case TokenType.SIZEOF:
312 : case TokenType.STATIC:
313 : case TokenType.STRUCT:
314 : case TokenType.SUPER:
315 : case TokenType.TO:
316 : case TokenType.TRUE:
317 : case TokenType.TRY:
318 : case TokenType.TYPEOF:
319 : case TokenType.UNOWNED:
320 : case TokenType.USES:
321 : case TokenType.VAR:
322 : case TokenType.VIRTUAL:
323 : case TokenType.VOID:
324 : case TokenType.VOLATILE:
325 : case TokenType.WEAK:
326 : case TokenType.WHEN:
327 : case TokenType.WHILE:
328 : case TokenType.YIELD:
329 655 : next ();
330 655 : return;
331 : case TokenType.INTEGER_LITERAL:
332 : case TokenType.REAL_LITERAL:
333 : // also accept integer and real literals
334 : // as long as they contain at least one character
335 : // and no decimal point
336 : // for example, 2D and 3D
337 0 : string id = get_current_string ();
338 0 : if (id[id.length - 1].isalpha () && !("." in id)) {
339 0 : next ();
340 0 : return;
341 : }
342 0 : break;
343 : default:
344 : break;
345 : }
346 :
347 0 : throw new ParseError.SYNTAX ("expected identifier");
348 : }
349 :
350 545 : string parse_identifier () throws ParseError {
351 545 : skip_identifier ();
352 545 : return get_last_string ();
353 : }
354 :
355 266 : Expression parse_literal () throws ParseError {
356 266 : var begin = get_location ();
357 :
358 266 : switch (current ()) {
359 : case TokenType.TRUE:
360 27 : next ();
361 27 : return new BooleanLiteral (true, get_src (begin));
362 : case TokenType.FALSE:
363 9 : next ();
364 9 : return new BooleanLiteral (false, get_src (begin));
365 : case TokenType.INTEGER_LITERAL:
366 142 : next ();
367 142 : return new IntegerLiteral (get_last_string (), get_src (begin));
368 : case TokenType.REAL_LITERAL:
369 3 : next ();
370 3 : return new RealLiteral (get_last_string (), get_src (begin));
371 : case TokenType.CHARACTER_LITERAL:
372 2 : next ();
373 : // FIXME validate and unescape here and just pass unichar to CharacterLiteral
374 2 : var lit = new CharacterLiteral (get_last_string (), get_src (begin));
375 2 : if (lit.error) {
376 0 : Report.error (lit.source_reference, "invalid character literal");
377 : }
378 2 : return lit;
379 : case TokenType.REGEX_LITERAL:
380 1 : next ();
381 1 : string match_part = get_last_string ();
382 1 : SourceReference src_begin = get_src (begin);
383 1 : expect (TokenType.CLOSE_REGEX_LITERAL);
384 1 : string close_token = get_last_string ();
385 1 : return new RegexLiteral ("%s/%s".printf (close_token, match_part), src_begin);
386 : case TokenType.STRING_LITERAL:
387 62 : next ();
388 62 : return new StringLiteral (get_last_string (), get_src (begin));
389 : case TokenType.TEMPLATE_STRING_LITERAL:
390 10 : next ();
391 10 : return new StringLiteral ("\"%s\"".printf (get_last_string ()), get_src (begin));
392 : case TokenType.VERBATIM_STRING_LITERAL:
393 1 : next ();
394 1 : string raw_string = get_last_string ();
395 1 : string escaped_string = raw_string.substring (3, raw_string.length - 6).escape ("");
396 1 : return new StringLiteral ("\"%s\"".printf (escaped_string), get_src (begin));
397 : case TokenType.VERBATIM_TEMPLATE_STRING_LITERAL:
398 7 : next ();
399 7 : string raw_string = get_last_string ();
400 7 : string escaped_string = raw_string.escape ("");
401 7 : return new StringLiteral ("\"%s\"".printf (escaped_string), get_src (begin));
402 : case TokenType.NULL:
403 2 : next ();
404 2 : return new NullLiteral (get_src (begin));
405 : default:
406 0 : throw new ParseError.SYNTAX ("expected literal");
407 : }
408 : }
409 :
410 85 : public void parse_file (SourceFile source_file) {
411 85 : var has_global_context = (context != null);
412 85 : if (!has_global_context) {
413 0 : context = source_file.context;
414 : }
415 :
416 85 : scanner = new Scanner (source_file);
417 85 : scanner.parse_file_comments ();
418 85 : scanner.indent_spaces = 0;
419 :
420 85 : tokens = new TokenInfo[BUFFER_SIZE];
421 85 : index = -1;
422 85 : size = 0;
423 :
424 85 : next ();
425 :
426 85 : try {
427 85 : var begin = get_location ();
428 : /* see if there is an indent attribute */
429 86 : if (accept (TokenType.OPEN_BRACKET)) {
430 1 : var id = parse_identifier ();
431 1 : if (id == "indent") {
432 1 : expect (TokenType.ASSIGN);
433 1 : expect (TokenType.INTEGER_LITERAL);
434 1 : scanner.indent_spaces = int.parse (get_last_string());
435 1 : expect (TokenType.CLOSE_BRACKET);
436 1 : expect (TokenType.EOL);
437 : } else {
438 0 : rollback (begin);
439 : }
440 : }
441 :
442 85 : parse_using_directives (context.root);
443 85 : parse_declarations (context.root, true);
444 : } catch (ParseError e) {
445 0 : report_parse_error (e);
446 : }
447 :
448 85 : scanner = null;
449 85 : if (!has_global_context) {
450 0 : context = null;
451 : }
452 : }
453 :
454 104 : void skip_symbol_name () throws ParseError {
455 214 : do {
456 110 : skip_identifier ();
457 110 : } while (accept (TokenType.DOT));
458 : }
459 :
460 120 : UnresolvedSymbol parse_symbol_name () throws ParseError {
461 120 : var begin = get_location ();
462 120 : UnresolvedSymbol sym = null;
463 240 : do {
464 120 : string name = parse_identifier ();
465 120 : sym = new UnresolvedSymbol (sym, name, get_src (begin));
466 120 : } while (accept (TokenType.DOT));
467 120 : return sym;
468 : }
469 :
470 104 : void skip_type () throws ParseError {
471 :
472 104 : accept (TokenType.DYNAMIC);
473 104 : accept (TokenType.OWNED);
474 104 : accept (TokenType.UNOWNED);
475 104 : accept (TokenType.WEAK);
476 :
477 :
478 104 : if (accept (TokenType.ARRAY) || accept (TokenType.LIST) || accept (TokenType.DICT)) {
479 0 : accept (TokenType.OF);
480 : }
481 :
482 104 : if (accept (TokenType.VOID)) {
483 : } else {
484 104 : skip_symbol_name ();
485 104 : skip_type_argument_list ();
486 : }
487 :
488 104 : while (accept (TokenType.OPEN_BRACKET)) {
489 0 : do {
490 0 : if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
491 0 : parse_expression ();
492 : }
493 0 : } while (accept (TokenType.COMMA));
494 0 : expect (TokenType.CLOSE_BRACKET);
495 : }
496 104 : accept (TokenType.OP_NEG);
497 104 : accept (TokenType.INTERR);
498 : }
499 :
500 :
501 1 : Expression parse_regex_literal () throws ParseError {
502 1 : expect (TokenType.OPEN_REGEX_LITERAL);
503 :
504 1 : var expr = parse_literal ();
505 :
506 : return expr;
507 : }
508 :
509 102 : DataType parse_type (bool owned_by_default, bool can_weak_ref) throws ParseError {
510 102 : var begin = get_location ();
511 :
512 102 : List<DataType> type_arg_list = null;
513 102 : UnresolvedSymbol sym = null;
514 :
515 102 : bool is_dynamic = accept (TokenType.DYNAMIC);
516 102 : bool value_owned = owned_by_default;
517 102 : bool is_nullable = false;
518 :
519 102 : if (owned_by_default) {
520 92 : if (accept (TokenType.UNOWNED)) {
521 : value_owned = false;
522 92 : } else if (accept (TokenType.WEAK)) {
523 0 : if (!can_weak_ref && !context.deprecated) {
524 0 : Report.warning (get_src (begin), "deprecated syntax, use `unowned` modifier");
525 : }
526 : value_owned = false;
527 : }
528 : } else {
529 10 : value_owned = accept (TokenType.OWNED);
530 : }
531 :
532 : /* handle arrays */
533 102 : bool is_array = false;
534 :
535 102 : if (accept (TokenType.ARRAY)) {
536 0 : expect (TokenType.OF);
537 : is_array = true;
538 : }
539 :
540 : /* handle lists */
541 102 : bool is_list = false;
542 :
543 102 : if (accept (TokenType.LIST)) {
544 0 : expect (TokenType.OF);
545 0 : prev ();
546 0 : is_list = true;
547 : }
548 :
549 : /* handle dicts */
550 102 : bool is_dict = false;
551 :
552 102 : if (accept (TokenType.DICT)) {
553 0 : expect (TokenType.OF);
554 0 : prev ();
555 0 : is_dict = true;
556 : }
557 :
558 : DataType type;
559 :
560 204 : if (!is_dynamic && value_owned == owned_by_default && accept (TokenType.VOID)) {
561 0 : type = new VoidType (get_src (begin));
562 : } else {
563 :
564 102 : if (is_list) {
565 0 : var sym_parent = new UnresolvedSymbol (null, "Gee", get_src (begin));
566 0 : sym = new UnresolvedSymbol (sym_parent, "ArrayList", get_src (begin));
567 102 : } else if (is_dict) {
568 0 : var sym_parent = new UnresolvedSymbol (null, "Gee", get_src (begin));
569 0 : sym = new UnresolvedSymbol (sym_parent, "HashMap", get_src (begin));
570 : } else {
571 102 : sym = parse_symbol_name ();
572 : }
573 :
574 102 : is_nullable = accept (TokenType.INTERR);
575 :
576 102 : type_arg_list = parse_type_argument_list (false);
577 :
578 102 : type = new UnresolvedType.from_symbol (sym, get_src (begin));
579 102 : if (type_arg_list != null) {
580 0 : foreach (DataType type_arg in type_arg_list) {
581 0 : type.add_type_argument (type_arg);
582 : }
583 : }
584 : }
585 :
586 102 : while (accept (TokenType.STAR)) {
587 0 : type = new PointerType (type, get_src (begin));
588 : }
589 :
590 102 : if (!(type is PointerType)) {
591 102 : type.nullable = is_nullable;
592 : }
593 :
594 102 : if (is_array) {
595 :
596 0 : if (!accept (TokenType.OPEN_BRACKET)) {
597 0 : type.value_owned = true;
598 0 : type = new ArrayType (type, 1, get_src (begin));
599 0 : type.nullable = accept (TokenType.INTERR);
600 :
601 : } else {
602 0 : prev ();
603 :
604 0 : while (accept (TokenType.OPEN_BRACKET)) {
605 : bool invalid_array = false;
606 : int array_rank = 0;
607 0 : do {
608 0 : array_rank++;
609 : // required for decision between expression and declaration statement
610 0 : if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
611 0 : parse_expression ();
612 : // only used for parsing, reject use as real type
613 : invalid_array = true;
614 : }
615 0 : } while (accept (TokenType.COMMA));
616 0 : expect (TokenType.CLOSE_BRACKET);
617 :
618 0 : type.value_owned = true;
619 0 : var array_type = new ArrayType (type, array_rank, get_src (begin));
620 0 : array_type.nullable = accept (TokenType.INTERR);
621 :
622 0 : array_type.invalid_syntax = invalid_array;
623 :
624 94 : type = array_type;
625 : }
626 : }
627 : }
628 :
629 102 : if (type is PointerType) {
630 102 : value_owned = false;
631 : }
632 :
633 102 : type.is_dynamic = is_dynamic;
634 102 : type.value_owned = value_owned;
635 102 : return type;
636 : }
637 :
638 63 : DataType? parse_inline_array_type (DataType? type) throws ParseError {
639 63 : var begin = get_location ();
640 :
641 : // inline-allocated array
642 63 : if (type != null && accept (TokenType.OPEN_BRACKET)) {
643 2 : Expression array_length = null;
644 :
645 2 : if (current () != TokenType.CLOSE_BRACKET) {
646 0 : array_length = parse_expression ();
647 : }
648 2 : expect (TokenType.CLOSE_BRACKET);
649 :
650 2 : var array_type = new ArrayType (type, 1, get_src (begin));
651 2 : array_type.inline_allocated = true;
652 2 : if (array_length != null) {
653 0 : array_type.fixed_length = true;
654 0 : array_type.length = array_length;
655 : }
656 2 : array_type.value_owned = type.value_owned;
657 2 : return array_type;
658 : }
659 61 : return type;
660 : }
661 :
662 :
663 159 : List<Expression> parse_argument_list () throws ParseError {
664 159 : var list = new ArrayList<Expression> ();
665 159 : if (current () != TokenType.CLOSE_PARENS) {
666 360 : do {
667 120 : list.add (parse_argument ());
668 120 : } while (accept (TokenType.COMMA));
669 : }
670 : return list;
671 : }
672 :
673 126 : Expression parse_argument () throws ParseError {
674 126 : var begin = get_location ();
675 :
676 126 : if (accept (TokenType.REF)) {
677 0 : var inner = parse_expression ();
678 0 : return new UnaryExpression (UnaryOperator.REF, inner, get_src (begin));
679 126 : } else if (accept (TokenType.OUT)) {
680 0 : var inner = parse_expression ();
681 0 : return new UnaryExpression (UnaryOperator.OUT, inner, get_src (begin));
682 : } else {
683 126 : var expr = parse_expression ();
684 126 : var ma = expr as MemberAccess;
685 3 : if (ma != null && ma.inner == null && accept (TokenType.COLON)) {
686 : // named argument
687 0 : expr = parse_expression ();
688 0 : return new NamedArgument (ma.member_name, expr, get_src (begin));
689 : } else {
690 126 : return expr;
691 : }
692 :
693 : }
694 : }
695 :
696 616 : Expression parse_primary_expression () throws ParseError {
697 616 : var begin = get_location ();
698 :
699 : Expression expr;
700 :
701 616 : switch (current ()) {
702 : case TokenType.TRUE:
703 : case TokenType.FALSE:
704 : case TokenType.INTEGER_LITERAL:
705 : case TokenType.REAL_LITERAL:
706 : case TokenType.CHARACTER_LITERAL:
707 : case TokenType.REGEX_LITERAL:
708 : case TokenType.STRING_LITERAL:
709 : case TokenType.TEMPLATE_STRING_LITERAL:
710 : case TokenType.VERBATIM_STRING_LITERAL:
711 : case TokenType.VERBATIM_TEMPLATE_STRING_LITERAL:
712 : case TokenType.NULL:
713 265 : expr = parse_literal ();
714 : break;
715 : case TokenType.ASSERT:
716 112 : return parse_assert_expression ();
717 : case TokenType.OPEN_BRACE:
718 2 : expr = parse_initializer ();
719 : break;
720 : case TokenType.OPEN_PARENS:
721 0 : expr = parse_tuple ();
722 : break;
723 : case TokenType.OPEN_REGEX_LITERAL:
724 1 : expr = parse_regex_literal ();
725 : break;
726 : case TokenType.OPEN_TEMPLATE:
727 7 : expr = parse_template ();
728 : break;
729 : case TokenType.SELF:
730 1 : expr = parse_this_access ();
731 : break;
732 : case TokenType.SUPER:
733 0 : expr = parse_base_access ();
734 : break;
735 : case TokenType.NEW:
736 11 : expr = parse_object_or_array_creation_expression ();
737 : break;
738 : case TokenType.PRINT:
739 4 : return parse_print_expression ();
740 : case TokenType.SIZEOF:
741 1 : expr = parse_sizeof_expression ();
742 : break;
743 : case TokenType.TYPEOF:
744 1 : expr = parse_typeof_expression ();
745 : break;
746 : case TokenType.YIELD:
747 0 : expr = parse_yield_expression ();
748 : break;
749 : default:
750 211 : expr = parse_simple_name ();
751 : break;
752 : }
753 :
754 : // process primary expressions that start with an inner primary expression
755 : bool found = true;
756 587 : while (found) {
757 587 : switch (current ()) {
758 : case TokenType.DOT:
759 39 : expr = parse_member_access (begin, expr);
760 39 : break;
761 : case TokenType.OP_PTR:
762 0 : expr = parse_pointer_member_access (begin, expr);
763 0 : break;
764 : case TokenType.OPEN_PARENS:
765 38 : expr = parse_method_call (begin, expr);
766 38 : break;
767 : case TokenType.OPEN_BRACKET:
768 3 : expr = parse_element_access (begin, expr);
769 3 : break;
770 : case TokenType.OP_INC:
771 5 : expr = parse_post_increment_expression (begin, expr);
772 5 : break;
773 : case TokenType.OP_DEC:
774 2 : expr = parse_post_decrement_expression (begin, expr);
775 2 : break;
776 :
777 : default:
778 : found = false;
779 : break;
780 : }
781 : }
782 :
783 : return expr;
784 : }
785 :
786 211 : Expression parse_simple_name () throws ParseError {
787 211 : var begin = get_location ();
788 211 : string id = parse_identifier ();
789 211 : List<DataType> type_arg_list = parse_type_argument_list (true);
790 211 : var expr = new MemberAccess (null, id, get_src (begin));
791 211 : if (type_arg_list != null) {
792 0 : foreach (DataType type_arg in type_arg_list) {
793 0 : expr.add_type_argument (type_arg);
794 : }
795 : }
796 211 : return expr;
797 : }
798 :
799 7 : Expression parse_template () throws ParseError {
800 7 : var begin = get_location ();
801 7 : var template = new Template ();
802 :
803 7 : expect (TokenType.OPEN_TEMPLATE);
804 63 : while (current () != TokenType.CLOSE_TEMPLATE) {
805 28 : template.add_expression (parse_expression ());
806 28 : expect (TokenType.COMMA);
807 : }
808 7 : expect (TokenType.CLOSE_TEMPLATE);
809 :
810 7 : template.source_reference = get_src (begin);
811 : return template;
812 : }
813 :
814 0 : Expression parse_tuple () throws ParseError {
815 0 : expect (TokenType.OPEN_PARENS);
816 0 : var expr_list = new ArrayList<Expression> ();
817 0 : if (current () != TokenType.CLOSE_PARENS) {
818 0 : do {
819 0 : expr_list.add (parse_expression ());
820 0 : } while (accept (TokenType.COMMA));
821 : }
822 0 : expect (TokenType.CLOSE_PARENS);
823 0 : if (expr_list.size != 1) {
824 0 : var tuple = new Tuple ();
825 0 : foreach (Expression expr in expr_list) {
826 0 : tuple.add_expression (expr);
827 : }
828 0 : return tuple;
829 : }
830 0 : return expr_list.get (0);
831 : }
832 :
833 39 : Expression parse_member_access (SourceLocation begin, Expression inner) throws ParseError {
834 39 : expect (TokenType.DOT);
835 39 : string id = parse_identifier ();
836 39 : List<DataType> type_arg_list = parse_type_argument_list (true);
837 39 : var expr = new MemberAccess (inner, id, get_src (begin));
838 39 : if (type_arg_list != null) {
839 0 : foreach (DataType type_arg in type_arg_list) {
840 0 : expr.add_type_argument (type_arg);
841 : }
842 : }
843 39 : return expr;
844 : }
845 :
846 0 : Expression parse_pointer_member_access (SourceLocation begin, Expression inner) throws ParseError {
847 0 : expect (TokenType.OP_PTR);
848 0 : string id = parse_identifier ();
849 0 : List<DataType> type_arg_list = parse_type_argument_list (true);
850 0 : var expr = new MemberAccess.pointer (inner, id, get_src (begin));
851 0 : if (type_arg_list != null) {
852 0 : foreach (DataType type_arg in type_arg_list) {
853 0 : expr.add_type_argument (type_arg);
854 : }
855 : }
856 0 : return expr;
857 : }
858 :
859 :
860 4 : List<Expression> parse_print_argument_list () throws ParseError {
861 4 : var list = new ArrayList<Expression> ();
862 4 : var i = 0;
863 4 : var begin = get_location ();
864 :
865 4 : if (current () != TokenType.CLOSE_PARENS) {
866 18 : do {
867 7 : var p_expr = parse_expression ();
868 7 : if (i == 0) {
869 4 : i++;
870 :
871 4 : if (p_expr != null) {
872 8 : if (p_expr is StringLiteral) {
873 2 : var s_exp = (StringLiteral) p_expr;
874 2 : var len = s_exp.value.length;
875 :
876 4 : if (len > 2) {
877 2 : string s = "\\n\"";
878 2 : var st = s_exp.value.substring (0, len-1);
879 2 : st += s;
880 2 : s_exp.value = st;
881 : } else {
882 0 : string s = "\"\\n\"";
883 0 : p_expr = new StringLiteral (s, get_src (begin));
884 : }
885 : } else {
886 2 : string s = "\"%s\\n\"";
887 2 : var s_exp = new StringLiteral (s, get_src (begin));
888 2 : list.add (s_exp);
889 : }
890 : }
891 : }
892 7 : list.add (p_expr);
893 :
894 7 : } while (accept (TokenType.COMMA));
895 : }
896 : return list;
897 : }
898 :
899 4 : Expression parse_print_expression () throws ParseError {
900 4 : var begin = get_location ();
901 :
902 4 : expect (TokenType.PRINT);
903 4 : bool parens = accept (TokenType.OPEN_PARENS);
904 :
905 4 : var expr = new MemberAccess (null, "print", get_src (begin));
906 :
907 4 : var arg_list = parse_print_argument_list ();
908 :
909 4 : if (parens) {
910 3 : expect (TokenType.CLOSE_PARENS);
911 : }
912 :
913 4 : var print_expr = new MethodCall (expr, get_src (begin));
914 :
915 22 : foreach (Expression arg in arg_list) {
916 9 : print_expr.add_argument (arg);
917 : }
918 :
919 4 : return print_expr;
920 :
921 : }
922 :
923 112 : Expression parse_assert_expression () throws ParseError {
924 112 : var begin = get_location ();
925 :
926 112 : expect (TokenType.ASSERT);
927 112 : bool parens = accept (TokenType.OPEN_PARENS);
928 :
929 112 : var expr = new MemberAccess (null, "assert", get_src (begin));
930 :
931 112 : var arg_list = parse_argument_list ();
932 :
933 112 : if (parens) {
934 112 : expect (TokenType.CLOSE_PARENS);
935 : }
936 :
937 112 : var assert_expr = new MethodCall (expr, get_src (begin));
938 :
939 336 : foreach (Expression arg in arg_list) {
940 112 : assert_expr.add_argument (arg);
941 : }
942 :
943 112 : return assert_expr;
944 :
945 : }
946 :
947 38 : Expression parse_method_call (SourceLocation begin, Expression inner) throws ParseError {
948 38 : expect (TokenType.OPEN_PARENS);
949 38 : var arg_list = parse_argument_list ();
950 38 : expect (TokenType.CLOSE_PARENS);
951 :
952 38 : var init_list = parse_object_initializer ();
953 :
954 38 : if (init_list.size > 0 && inner is MemberAccess) {
955 : // struct creation expression
956 0 : var member = (MemberAccess) inner;
957 :
958 0 : var expr = new ObjectCreationExpression (member, get_src (begin));
959 0 : expr.struct_creation = true;
960 0 : foreach (Expression arg in arg_list) {
961 0 : expr.add_argument (arg);
962 : }
963 0 : foreach (MemberInitializer initializer in init_list) {
964 0 : expr.add_member_initializer (initializer);
965 : }
966 0 : return expr;
967 : } else {
968 38 : var expr = new MethodCall (inner, get_src (begin));
969 50 : foreach (Expression arg in arg_list) {
970 6 : expr.add_argument (arg);
971 : }
972 38 : return expr;
973 : }
974 : }
975 :
976 3 : Expression parse_element_access (SourceLocation begin, Expression inner) throws ParseError {
977 3 : Expression? stop = null;
978 : List<Expression> index_list;
979 :
980 3 : expect (TokenType.OPEN_BRACKET);
981 3 : if (current () == TokenType.COLON) {
982 : // slice expression
983 0 : index_list = new ArrayList<Expression> ();
984 0 : index_list.add (new IntegerLiteral ("0", get_src (begin)));
985 : } else {
986 3 : index_list = parse_expression_list ();
987 : }
988 :
989 3 : if (index_list.size == 1 && accept (TokenType.COLON)) {
990 : // slice expression
991 0 : if (current () == TokenType.CLOSE_BRACKET) {
992 0 : stop = new MemberAccess (inner, "length", get_src (begin));
993 : } else {
994 0 : stop = parse_expression ();
995 : }
996 : }
997 3 : expect (TokenType.CLOSE_BRACKET);
998 :
999 3 : if (stop == null) {
1000 3 : var expr = new ElementAccess (inner, get_src (begin));
1001 9 : foreach (Expression index in index_list) {
1002 3 : expr.append_index (index);
1003 : }
1004 3 : return expr;
1005 : } else {
1006 0 : return new SliceExpression (inner, index_list[0], stop, get_src (begin));
1007 : }
1008 : }
1009 :
1010 3 : List<Expression> parse_expression_list () throws ParseError {
1011 3 : var list = new ArrayList<Expression> ();
1012 12 : do {
1013 3 : list.add (parse_expression ());
1014 3 : } while (accept (TokenType.COMMA));
1015 : return list;
1016 : }
1017 :
1018 1 : Expression parse_this_access () throws ParseError {
1019 1 : var begin = get_location ();
1020 1 : expect (TokenType.SELF);
1021 1 : return new MemberAccess (null, "this", get_src (begin));
1022 : }
1023 :
1024 0 : Expression parse_base_access () throws ParseError {
1025 0 : var begin = get_location ();
1026 0 : expect (TokenType.SUPER);
1027 0 : return new BaseAccess (get_src (begin));
1028 : }
1029 :
1030 5 : Expression parse_post_increment_expression (SourceLocation begin, Expression inner) throws ParseError {
1031 5 : expect (TokenType.OP_INC);
1032 5 : return new PostfixExpression (inner, true, get_src (begin));
1033 : }
1034 :
1035 2 : Expression parse_post_decrement_expression (SourceLocation begin, Expression inner) throws ParseError {
1036 2 : expect (TokenType.OP_DEC);
1037 2 : return new PostfixExpression (inner, false, get_src (begin));
1038 : }
1039 :
1040 11 : Expression parse_object_or_array_creation_expression () throws ParseError {
1041 11 : var begin = get_location ();
1042 11 : expect (TokenType.NEW);
1043 :
1044 11 : if (accept (TokenType.ARRAY)) {
1045 0 : expect (TokenType.OF);
1046 0 : var mtype = parse_type (true, false);
1047 0 : var expr = parse_array_creation_expression (begin, mtype);
1048 0 : return expr;
1049 : }
1050 :
1051 11 : if (accept (TokenType.LIST)) {
1052 0 : expect (TokenType.OF);
1053 0 : var mtype = parse_type (true, false);
1054 0 : var expr = parse_list_creation_expression (begin, mtype);
1055 0 : return expr;
1056 : }
1057 :
1058 11 : if (accept (TokenType.DICT)) {
1059 0 : expect (TokenType.OF);
1060 0 : var mtype1 = parse_type (true, false);
1061 0 : expect (TokenType.COMMA);
1062 0 : var mtype2 = parse_type (true, false);
1063 0 : var expr = parse_dict_creation_expression (begin, mtype1, mtype2);
1064 0 : return expr;
1065 : }
1066 :
1067 :
1068 11 : var member = parse_member_name ();
1069 11 : var expr = parse_object_creation_expression (begin, member);
1070 11 : return expr;
1071 :
1072 : }
1073 :
1074 11 : Expression parse_object_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError {
1075 : List<Expression> arg_list;
1076 11 : if (accept (TokenType.OPEN_PARENS)) {
1077 9 : arg_list = parse_argument_list ();
1078 9 : expect (TokenType.CLOSE_PARENS);
1079 : } else {
1080 2 : arg_list = new ArrayList<Expression> ();
1081 : }
1082 :
1083 11 : var init_list = parse_object_initializer ();
1084 :
1085 11 : var expr = new ObjectCreationExpression (member, get_src (begin));
1086 15 : foreach (Expression arg in arg_list) {
1087 2 : expr.add_argument (arg);
1088 : }
1089 11 : foreach (MemberInitializer initializer in init_list) {
1090 0 : expr.add_member_initializer (initializer);
1091 : }
1092 11 : return expr;
1093 : }
1094 :
1095 0 : Expression parse_array_creation_expression (SourceLocation begin, DataType element_type) throws ParseError {
1096 0 : bool size_specified = false;
1097 0 : List<Expression> size_specifier_list = null;
1098 0 : bool first = true;
1099 0 : DataType etype = element_type.copy ();
1100 :
1101 0 : var has_bracket = accept (TokenType.OPEN_BRACKET);
1102 :
1103 0 : do {
1104 0 : if (!first) {
1105 : // array of arrays: new T[][42]
1106 :
1107 0 : if (size_specified) {
1108 0 : throw new ParseError.SYNTAX ("size of inner arrays must not be specified in array creation expression");
1109 : }
1110 :
1111 0 : etype = new ArrayType (etype, size_specifier_list.size, etype.source_reference);
1112 : } else {
1113 : first = false;
1114 : }
1115 :
1116 0 : size_specifier_list = new ArrayList<Expression> ();
1117 0 : do {
1118 0 : Expression size = null;
1119 0 : if (has_bracket && current () != TokenType.CLOSE_BRACKET && current () != TokenType.COMMA) {
1120 0 : size = parse_expression ();
1121 : size_specified = true;
1122 : }
1123 0 : size_specifier_list.add (size);
1124 0 : } while (accept (TokenType.COMMA));
1125 :
1126 0 : if (has_bracket) {
1127 0 : expect (TokenType.CLOSE_BRACKET);
1128 : }
1129 0 : } while (accept (TokenType.OPEN_BRACKET));
1130 :
1131 0 : InitializerList initializer = null;
1132 0 : if (accept (TokenType.ASSIGN)) {
1133 0 : initializer = parse_initializer ();
1134 : }
1135 :
1136 0 : var expr = new ArrayCreationExpression (etype, size_specifier_list.size, initializer, get_src (begin));
1137 0 : if (size_specified) {
1138 0 : foreach (Expression size in size_specifier_list) {
1139 0 : expr.append_size (size);
1140 : }
1141 : }
1142 0 : return expr;
1143 : }
1144 :
1145 :
1146 0 : Expression parse_list_creation_expression (SourceLocation begin, DataType element_type) throws ParseError {
1147 :
1148 0 : MemberAccess list_member = null, parent_member = null;
1149 :
1150 0 : parent_member = new MemberAccess (null, "Gee", get_src (begin));
1151 0 : list_member = new MemberAccess (parent_member, "ArrayList", get_src (begin));
1152 0 : list_member.add_type_argument (element_type);
1153 :
1154 0 : var expr = new ObjectCreationExpression (list_member, get_src (begin));
1155 0 : return expr;
1156 : }
1157 :
1158 0 : Expression parse_dict_creation_expression (SourceLocation begin, DataType key_type, DataType value_type) throws ParseError {
1159 :
1160 0 : MemberAccess dict_member = null, parent_member = null;
1161 :
1162 0 : parent_member = new MemberAccess (null, "Gee", get_src (begin));
1163 0 : dict_member = new MemberAccess (parent_member, "HashMap", get_src (begin));
1164 0 : dict_member.add_type_argument (key_type);
1165 0 : dict_member.add_type_argument (value_type);
1166 :
1167 0 : var expr = new ObjectCreationExpression (dict_member, get_src (begin));
1168 :
1169 0 : return expr;
1170 : }
1171 :
1172 :
1173 49 : List<MemberInitializer> parse_object_initializer () throws ParseError {
1174 49 : var list = new ArrayList<MemberInitializer> ();
1175 49 : if (accept (TokenType.OPEN_BRACE)) {
1176 0 : do {
1177 0 : list.add (parse_member_initializer ());
1178 0 : } while (accept (TokenType.COMMA));
1179 0 : expect (TokenType.CLOSE_BRACE);
1180 : }
1181 : return list;
1182 : }
1183 :
1184 0 : MemberInitializer parse_member_initializer () throws ParseError {
1185 0 : var begin = get_location ();
1186 0 : string id = parse_identifier ();
1187 0 : expect (TokenType.ASSIGN);
1188 :
1189 0 : var inner = get_location ();
1190 : Expression expr;
1191 0 : try {
1192 : // chained member initializer
1193 0 : expr = parse_member_initializer ();
1194 : } catch {
1195 0 : rollback (inner);
1196 0 : expr = parse_expression ();
1197 : }
1198 0 : return new MemberInitializer (id, expr, get_src (begin));
1199 : }
1200 :
1201 0 : Expression parse_yield_expression () throws ParseError {
1202 0 : expect (TokenType.YIELD);
1203 :
1204 0 : var expr = parse_expression ();
1205 :
1206 0 : unowned MethodCall? call = expr as MethodCall;
1207 0 : unowned ObjectCreationExpression? object_creation = expr as ObjectCreationExpression;
1208 0 : if (call == null && object_creation == null) {
1209 0 : Report.error (expr.source_reference, "syntax error, expected method call");
1210 0 : throw new ParseError.SYNTAX ("expected method call");
1211 : }
1212 :
1213 0 : if (call != null) {
1214 0 : call.is_yield_expression = true;
1215 0 : } else if (object_creation != null) {
1216 0 : object_creation.is_yield_expression = true;
1217 : }
1218 :
1219 : return expr;
1220 : }
1221 :
1222 1 : Expression parse_sizeof_expression () throws ParseError {
1223 1 : var begin = get_location ();
1224 1 : expect (TokenType.SIZEOF);
1225 1 : expect (TokenType.OPEN_PARENS);
1226 1 : var type = parse_type (true, false);
1227 1 : expect (TokenType.CLOSE_PARENS);
1228 :
1229 1 : return new SizeofExpression (type, get_src (begin));
1230 : }
1231 :
1232 1 : Expression parse_typeof_expression () throws ParseError {
1233 1 : var begin = get_location ();
1234 1 : expect (TokenType.TYPEOF);
1235 1 : expect (TokenType.OPEN_PARENS);
1236 1 : var type = parse_type (true, false);
1237 1 : expect (TokenType.CLOSE_PARENS);
1238 :
1239 1 : return new TypeofExpression (type, get_src (begin));
1240 : }
1241 :
1242 625 : UnaryOperator get_unary_operator (TokenType token_type) {
1243 625 : switch (token_type) {
1244 625 : case TokenType.PLUS: return UnaryOperator.PLUS;
1245 4 : case TokenType.MINUS: return UnaryOperator.MINUS;
1246 4 : case TokenType.OP_NEG: return UnaryOperator.LOGICAL_NEGATION;
1247 1 : case TokenType.TILDE: return UnaryOperator.BITWISE_COMPLEMENT;
1248 1 : case TokenType.OP_INC: return UnaryOperator.INCREMENT;
1249 1 : case TokenType.OP_DEC: return UnaryOperator.DECREMENT;
1250 614 : default: return UnaryOperator.NONE;
1251 : }
1252 : }
1253 :
1254 625 : Expression parse_unary_expression () throws ParseError {
1255 625 : var begin = get_location ();
1256 625 : var operator = get_unary_operator (current ());
1257 625 : if (operator != UnaryOperator.NONE) {
1258 11 : next ();
1259 11 : var op = parse_unary_expression ();
1260 11 : return new UnaryExpression (operator, op, get_src (begin));
1261 : }
1262 614 : switch (current ()) {
1263 : case TokenType.OPEN_PARENS:
1264 0 : next ();
1265 0 : switch (current ()) {
1266 : case TokenType.OWNED:
1267 : // (owned) foo
1268 0 : next ();
1269 0 : if (accept (TokenType.CLOSE_PARENS)) {
1270 0 : var op = parse_unary_expression ();
1271 0 : return new ReferenceTransferExpression (op, get_src (begin));
1272 : }
1273 : break;
1274 : case TokenType.VOID:
1275 : case TokenType.DYNAMIC:
1276 : case TokenType.IDENTIFIER:
1277 : case TokenType.ARRAY:
1278 : case TokenType.LIST:
1279 : case TokenType.DICT:
1280 0 : var type = parse_type (true, false);
1281 0 : if (accept (TokenType.CLOSE_PARENS)) {
1282 : // check follower to decide whether to create cast expression
1283 0 : switch (current ()) {
1284 : case TokenType.OP_NEG:
1285 : case TokenType.TILDE:
1286 : case TokenType.OPEN_PARENS:
1287 : case TokenType.TRUE:
1288 : case TokenType.FALSE:
1289 : case TokenType.INTEGER_LITERAL:
1290 : case TokenType.REAL_LITERAL:
1291 : case TokenType.CHARACTER_LITERAL:
1292 : case TokenType.REGEX_LITERAL:
1293 : case TokenType.STRING_LITERAL:
1294 : case TokenType.TEMPLATE_STRING_LITERAL:
1295 : case TokenType.VERBATIM_STRING_LITERAL:
1296 : case TokenType.VERBATIM_TEMPLATE_STRING_LITERAL:
1297 : case TokenType.NULL:
1298 : case TokenType.SELF:
1299 : case TokenType.SUPER:
1300 : case TokenType.NEW:
1301 : case TokenType.SIZEOF:
1302 : case TokenType.TYPEOF:
1303 : case TokenType.IDENTIFIER:
1304 : case TokenType.PARAMS:
1305 : case TokenType.YIELD:
1306 0 : var inner = parse_unary_expression ();
1307 0 : return new CastExpression (inner, type, get_src (begin));
1308 : default:
1309 : break;
1310 : }
1311 : }
1312 0 : break;
1313 : case TokenType.OP_NEG:
1314 0 : next ();
1315 0 : if (accept (TokenType.CLOSE_PARENS)) {
1316 : // (!) non-null cast
1317 0 : var inner = parse_unary_expression ();
1318 0 : return new CastExpression.non_null (inner, get_src (begin));
1319 : }
1320 : break;
1321 :
1322 : default:
1323 : break;
1324 : }
1325 : // no cast expression
1326 0 : rollback (begin);
1327 0 : break;
1328 : case TokenType.STAR:
1329 0 : next ();
1330 0 : var op = parse_unary_expression ();
1331 0 : return new PointerIndirection (op, get_src (begin));
1332 : case TokenType.BITWISE_AND:
1333 0 : next ();
1334 0 : var op = parse_unary_expression ();
1335 0 : return new AddressofExpression (op, get_src (begin));
1336 : default:
1337 : break;
1338 : }
1339 :
1340 614 : var expr = parse_primary_expression ();
1341 625 : return expr;
1342 : }
1343 :
1344 2420 : BinaryOperator get_binary_operator (TokenType token_type) {
1345 2420 : switch (token_type) {
1346 2420 : case TokenType.STAR: return BinaryOperator.MUL;
1347 1 : case TokenType.DIV: return BinaryOperator.DIV;
1348 1 : case TokenType.PERCENT: return BinaryOperator.MOD;
1349 8 : case TokenType.PLUS: return BinaryOperator.PLUS;
1350 2 : case TokenType.MINUS: return BinaryOperator.MINUS;
1351 12 : case TokenType.OP_LT: return BinaryOperator.LESS_THAN;
1352 18 : case TokenType.OP_GT: return BinaryOperator.GREATER_THAN;
1353 6 : case TokenType.OP_LE: return BinaryOperator.LESS_THAN_OR_EQUAL;
1354 9 : case TokenType.OP_GE: return BinaryOperator.GREATER_THAN_OR_EQUAL;
1355 332 : case TokenType.OP_EQ: return BinaryOperator.EQUALITY;
1356 : case TokenType.IS:
1357 0 : next();
1358 0 : if (current () == TokenType.OP_NEG) {
1359 0 : prev ();
1360 0 : return BinaryOperator.INEQUALITY;
1361 : }
1362 0 : prev ();
1363 0 : return BinaryOperator.EQUALITY;
1364 16 : case TokenType.OP_NE: return BinaryOperator.INEQUALITY;
1365 2014 : default: return BinaryOperator.NONE;
1366 : }
1367 : }
1368 :
1369 611 : Expression parse_multiplicative_expression () throws ParseError {
1370 611 : var begin = get_location ();
1371 611 : var left = parse_unary_expression ();
1372 : bool found = true;
1373 614 : while (found) {
1374 614 : var operator = get_binary_operator (current ());
1375 614 : switch (operator) {
1376 : case BinaryOperator.MUL:
1377 : case BinaryOperator.DIV:
1378 : case BinaryOperator.MOD:
1379 3 : next ();
1380 3 : var right = parse_unary_expression ();
1381 3 : left = new BinaryExpression (operator, left, right, get_src (begin));
1382 3 : break;
1383 : default:
1384 : found = false;
1385 : break;
1386 : }
1387 : }
1388 : return left;
1389 : }
1390 :
1391 606 : Expression parse_additive_expression () throws ParseError {
1392 606 : var begin = get_location ();
1393 606 : var left = parse_multiplicative_expression ();
1394 : bool found = true;
1395 611 : while (found) {
1396 611 : var operator = get_binary_operator (current ());
1397 611 : switch (operator) {
1398 : case BinaryOperator.PLUS:
1399 : case BinaryOperator.MINUS:
1400 5 : next ();
1401 5 : var right = parse_multiplicative_expression ();
1402 5 : left = new BinaryExpression (operator, left, right, get_src (begin));
1403 5 : break;
1404 : default:
1405 : found = false;
1406 : break;
1407 : }
1408 : }
1409 : return left;
1410 : }
1411 :
1412 604 : Expression parse_shift_expression () throws ParseError {
1413 604 : var begin = get_location ();
1414 604 : var left = parse_additive_expression ();
1415 : bool found = true;
1416 611 : while (found) {
1417 606 : switch (current ()) {
1418 : case TokenType.OP_SHIFT_LEFT:
1419 1 : next ();
1420 1 : var right = parse_additive_expression ();
1421 1 : left = new BinaryExpression (BinaryOperator.SHIFT_LEFT, left, right, get_src (begin));
1422 1 : break;
1423 : // don't use OP_SHIFT_RIGHT to support >> for nested generics
1424 : case TokenType.OP_GT:
1425 6 : char* first_gt_pos = tokens[index].begin.pos;
1426 6 : next ();
1427 : // only accept >> when there is no space between the two > signs
1428 7 : if (current () == TokenType.OP_GT && tokens[index].begin.pos == first_gt_pos + 1) {
1429 1 : next ();
1430 1 : var right = parse_additive_expression ();
1431 1 : left = new BinaryExpression (BinaryOperator.SHIFT_RIGHT, left, right, get_src (begin));
1432 : } else {
1433 5 : prev ();
1434 5 : found = false;
1435 : }
1436 6 : break;
1437 : default:
1438 : found = false;
1439 : break;
1440 : }
1441 : }
1442 : return left;
1443 : }
1444 :
1445 604 : Expression parse_type_check_expression () throws ParseError {
1446 604 : var begin = get_location ();
1447 604 : var left = parse_shift_expression ();
1448 604 : if (accept (TokenType.ISA)) {
1449 0 : var type = parse_type (true, false);
1450 0 : left = new TypeCheck (left, type, get_src (begin));
1451 604 : } else if (accept (TokenType.AS)) {
1452 0 : var type = parse_type (true, false);
1453 0 : left = new CastExpression.silent (left, type, get_src (begin));
1454 : }
1455 : return left;
1456 : }
1457 :
1458 591 : Expression parse_relational_expression () throws ParseError {
1459 591 : var begin = get_location ();
1460 591 : var left = parse_type_check_expression ();
1461 : bool found = true;
1462 604 : while (found) {
1463 604 : var operator = get_binary_operator (current ());
1464 604 : switch (operator) {
1465 : case BinaryOperator.LESS_THAN:
1466 : case BinaryOperator.LESS_THAN_OR_EQUAL:
1467 : case BinaryOperator.GREATER_THAN_OR_EQUAL:
1468 9 : next ();
1469 9 : var right = parse_type_check_expression ();
1470 9 : left = new BinaryExpression (operator, left, right, get_src (begin));
1471 9 : break;
1472 : case BinaryOperator.GREATER_THAN:
1473 5 : next ();
1474 : // ignore >> and >>= (two tokens due to generics)
1475 9 : if (current () != TokenType.OP_GT && current () != TokenType.OP_GE) {
1476 4 : var right = parse_type_check_expression ();
1477 4 : left = new BinaryExpression (operator, left, right, get_src (begin));
1478 : } else {
1479 1 : prev ();
1480 1 : found = false;
1481 : }
1482 : break;
1483 : default:
1484 : found = false;
1485 : break;
1486 : }
1487 : }
1488 : return left;
1489 : }
1490 :
1491 504 : Expression parse_equality_expression () throws ParseError {
1492 504 : var begin = get_location ();
1493 504 : var left = parse_relational_expression ();
1494 : bool found = true;
1495 591 : while (found) {
1496 591 : var operator = get_binary_operator (current ());
1497 591 : switch (operator) {
1498 : case BinaryOperator.INEQUALITY:
1499 : case BinaryOperator.EQUALITY:
1500 87 : if ((operator == BinaryOperator.INEQUALITY) && (current () == TokenType.IS)) {
1501 0 : next ();
1502 : }
1503 87 : next ();
1504 87 : var right = parse_relational_expression ();
1505 87 : left = new BinaryExpression (operator, left, right, get_src (begin));
1506 87 : break;
1507 : default:
1508 : found = false;
1509 : break;
1510 : }
1511 : }
1512 : return left;
1513 : }
1514 :
1515 503 : Expression parse_and_expression () throws ParseError {
1516 503 : var begin = get_location ();
1517 503 : var left = parse_equality_expression ();
1518 504 : while (accept (TokenType.BITWISE_AND)) {
1519 1 : var right = parse_equality_expression ();
1520 1 : left = new BinaryExpression (BinaryOperator.BITWISE_AND, left, right, get_src (begin));
1521 : }
1522 503 : return left;
1523 : }
1524 :
1525 502 : Expression parse_exclusive_or_expression () throws ParseError {
1526 502 : var begin = get_location ();
1527 502 : var left = parse_and_expression ();
1528 503 : while (accept (TokenType.CARRET)) {
1529 1 : var right = parse_and_expression ();
1530 1 : left = new BinaryExpression (BinaryOperator.BITWISE_XOR, left, right, get_src (begin));
1531 : }
1532 502 : return left;
1533 : }
1534 :
1535 501 : Expression parse_inclusive_or_expression () throws ParseError {
1536 501 : var begin = get_location ();
1537 501 : var left = parse_exclusive_or_expression ();
1538 502 : while (accept (TokenType.BITWISE_OR)) {
1539 1 : var right = parse_exclusive_or_expression ();
1540 1 : left = new BinaryExpression (BinaryOperator.BITWISE_OR, left, right, get_src (begin));
1541 : }
1542 501 : return left;
1543 : }
1544 :
1545 501 : Expression parse_in_expression () throws ParseError {
1546 501 : var begin = get_location ();
1547 501 : var left = parse_inclusive_or_expression ();
1548 501 : while (accept (TokenType.IN)) {
1549 0 : var right = parse_inclusive_or_expression ();
1550 0 : left = new BinaryExpression (BinaryOperator.IN, left, right, get_src (begin));
1551 : }
1552 501 : return left;
1553 : }
1554 :
1555 499 : Expression parse_conditional_and_expression () throws ParseError {
1556 499 : var begin = get_location ();
1557 499 : var left = parse_in_expression ();
1558 501 : while (accept (TokenType.OP_AND)) {
1559 2 : var right = parse_in_expression ();
1560 2 : left = new BinaryExpression (BinaryOperator.AND, left, right, get_src (begin));
1561 : }
1562 499 : return left;
1563 : }
1564 :
1565 497 : Expression parse_conditional_or_expression () throws ParseError {
1566 497 : var begin = get_location ();
1567 497 : var left = parse_conditional_and_expression ();
1568 499 : while (accept (TokenType.OP_OR)) {
1569 2 : var right = parse_conditional_and_expression ();
1570 2 : left = new BinaryExpression (BinaryOperator.OR, left, right, get_src (begin));
1571 : }
1572 497 : return left;
1573 : }
1574 :
1575 497 : Expression parse_conditional_expression () throws ParseError {
1576 497 : var begin = get_location ();
1577 497 : var condition = parse_conditional_or_expression ();
1578 497 : if (accept (TokenType.INTERR)) {
1579 1 : var true_expr = parse_expression ();
1580 1 : expect (TokenType.COLON);
1581 1 : var false_expr = parse_expression ();
1582 1 : return new ConditionalExpression (condition, true_expr, false_expr, get_src (begin));
1583 : } else {
1584 497 : return condition;
1585 : }
1586 : }
1587 :
1588 0 : Parameter parse_lambda_parameter () throws ParseError {
1589 0 : var begin = get_location ();
1590 0 : var direction = ParameterDirection.IN;
1591 0 : if (accept (TokenType.OUT)) {
1592 : direction = ParameterDirection.OUT;
1593 0 : } else if (accept (TokenType.REF)) {
1594 0 : direction = ParameterDirection.REF;
1595 : }
1596 :
1597 0 : string id = parse_identifier ();
1598 :
1599 0 : var param = new Parameter (id, null, get_src (begin));
1600 0 : param.direction = direction;
1601 0 : return param;
1602 : }
1603 :
1604 1 : Expression parse_lambda_expression () throws ParseError {
1605 1 : var begin = get_location ();
1606 1 : List<Parameter> params = new ArrayList<Parameter> ();
1607 :
1608 1 : expect (TokenType.DEF);
1609 :
1610 1 : if (accept (TokenType.OPEN_PARENS)) {
1611 1 : if (current () != TokenType.CLOSE_PARENS) {
1612 0 : do {
1613 0 : params.add (parse_lambda_parameter ());
1614 0 : } while (accept (TokenType.COMMA));
1615 : }
1616 1 : expect (TokenType.CLOSE_PARENS);
1617 : } else {
1618 0 : params.add (parse_lambda_parameter ());
1619 : }
1620 :
1621 : LambdaExpression lambda;
1622 :
1623 2 : if (accept_block ()) {
1624 1 : var block = parse_block ();
1625 1 : lambda = new LambdaExpression.with_statement_body (block, get_src (begin));
1626 : } else {
1627 0 : var expr = parse_expression ();
1628 0 : lambda = new LambdaExpression (expr, get_src (begin));
1629 0 : expect_terminator ();
1630 :
1631 : }
1632 :
1633 :
1634 1 : foreach (var param in params) {
1635 0 : lambda.add_parameter (param);
1636 : }
1637 1 : return lambda;
1638 : }
1639 :
1640 518 : AssignmentOperator get_assignment_operator (TokenType token_type) {
1641 518 : switch (token_type) {
1642 : case TokenType.ASSIGN: return AssignmentOperator.SIMPLE;
1643 : case TokenType.ASSIGN_ADD: return AssignmentOperator.ADD;
1644 : case TokenType.ASSIGN_SUB: return AssignmentOperator.SUB;
1645 : case TokenType.ASSIGN_BITWISE_OR: return AssignmentOperator.BITWISE_OR;
1646 : case TokenType.ASSIGN_BITWISE_AND: return AssignmentOperator.BITWISE_AND;
1647 : case TokenType.ASSIGN_BITWISE_XOR: return AssignmentOperator.BITWISE_XOR;
1648 : case TokenType.ASSIGN_DIV: return AssignmentOperator.DIV;
1649 : case TokenType.ASSIGN_MUL: return AssignmentOperator.MUL;
1650 : case TokenType.ASSIGN_PERCENT: return AssignmentOperator.PERCENT;
1651 : case TokenType.ASSIGN_SHIFT_LEFT: return AssignmentOperator.SHIFT_LEFT;
1652 : default: return AssignmentOperator.NONE;
1653 : }
1654 : }
1655 :
1656 267 : Expression parse_expression_with_terminator () throws ParseError {
1657 267 : var expr = parse_expression ();
1658 267 : if (current_expr_is_lambda) {
1659 1 : current_expr_is_lambda = false;
1660 : } else {
1661 266 : expect_terminator ();
1662 : }
1663 : return expr;
1664 : }
1665 :
1666 498 : Expression parse_expression () throws ParseError {
1667 498 : if (current () == TokenType.DEF) {
1668 1 : var lambda = parse_lambda_expression ();
1669 1 : current_expr_is_lambda = true;
1670 1 : return lambda;
1671 : } else {
1672 497 : current_expr_is_lambda = false;
1673 : }
1674 :
1675 497 : var begin = get_location ();
1676 497 : Expression expr = parse_conditional_expression ();
1677 :
1678 518 : while (true) {
1679 518 : var operator = get_assignment_operator (current ());
1680 538 : if (operator != AssignmentOperator.NONE) {
1681 20 : next ();
1682 20 : var rhs = parse_expression ();
1683 20 : expr = new Assignment (expr, rhs, operator, get_src (begin));
1684 498 : } else if (current () == TokenType.OP_GT) { // >>=
1685 1 : char* first_gt_pos = tokens[index].begin.pos;
1686 1 : next ();
1687 : // only accept >>= when there is no space between the two > signs
1688 2 : if (current () == TokenType.OP_GE && tokens[index].begin.pos == first_gt_pos + 1) {
1689 1 : next ();
1690 1 : var rhs = parse_expression ();
1691 1 : expr = new Assignment (expr, rhs, AssignmentOperator.SHIFT_RIGHT, get_src (begin));
1692 : } else {
1693 0 : prev ();
1694 0 : break;
1695 : }
1696 : } else {
1697 : break;
1698 : }
1699 : }
1700 :
1701 498 : return expr;
1702 : }
1703 :
1704 :
1705 3 : Statement get_for_statement_type () throws ParseError {
1706 :
1707 3 : var begin = get_location ();
1708 3 : bool is_foreach = false;
1709 :
1710 22 : while (current () != TokenType.EOL && current () != TokenType.DO) {
1711 20 : next ();
1712 20 : if (accept (TokenType.IN)) {
1713 : is_foreach = true;
1714 : break;
1715 : }
1716 : }
1717 :
1718 3 : rollback (begin);
1719 :
1720 3 : if (is_foreach) {
1721 1 : return parse_foreach_statement ();
1722 : } else {
1723 2 : return parse_for_statement ();
1724 : }
1725 :
1726 : }
1727 :
1728 144 : void parse_statements (Block block) throws ParseError {
1729 447 : while (current () != TokenType.DEDENT
1730 305 : && current () != TokenType.WHEN
1731 304 : && current () != TokenType.DEFAULT) {
1732 606 : try {
1733 303 : Statement stmt = null;
1734 303 : bool is_decl = false;
1735 303 : comment = scanner.pop_comment ();
1736 303 : switch (current ()) {
1737 :
1738 : /* skip over requires and ensures as we handled them in method declaration */
1739 : case TokenType.REQUIRES:
1740 : case TokenType.ENSURES:
1741 0 : var begin = get_location ();
1742 0 : next ();
1743 :
1744 0 : if (accept (TokenType.EOL) && accept (TokenType.INDENT)) {
1745 0 : while (current () != TokenType.DEDENT) {
1746 0 : next();
1747 : }
1748 :
1749 0 : expect (TokenType.DEDENT);
1750 : } else {
1751 0 : while (current () != TokenType.EOL) {
1752 0 : next();
1753 : }
1754 :
1755 0 : expect (TokenType.EOL);
1756 : }
1757 :
1758 0 : stmt = new EmptyStatement (get_src (begin));
1759 0 : break;
1760 :
1761 :
1762 : case TokenType.INDENT:
1763 0 : stmt = parse_block ();
1764 : break;
1765 : case TokenType.SEMICOLON:
1766 : case TokenType.PASS:
1767 1 : stmt = parse_empty_statement ();
1768 : break;
1769 : case TokenType.PRINT:
1770 : case TokenType.ASSERT:
1771 115 : stmt = parse_expression_statement ();
1772 : break;
1773 : case TokenType.IF:
1774 16 : stmt = parse_if_statement ();
1775 : break;
1776 : case TokenType.CASE:
1777 1 : stmt = parse_switch_statement ();
1778 : break;
1779 : case TokenType.WHILE:
1780 2 : stmt = parse_while_statement ();
1781 : break;
1782 : case TokenType.DO:
1783 2 : stmt = parse_do_statement ();
1784 : break;
1785 : case TokenType.FOR:
1786 3 : stmt = get_for_statement_type ();
1787 : break;
1788 : case TokenType.BREAK:
1789 2 : stmt = parse_break_statement ();
1790 : break;
1791 : case TokenType.CONTINUE:
1792 1 : stmt = parse_continue_statement ();
1793 : break;
1794 : case TokenType.RETURN:
1795 18 : stmt = parse_return_statement ();
1796 : break;
1797 : case TokenType.RAISE:
1798 1 : stmt = parse_throw_statement ();
1799 : break;
1800 : case TokenType.TRY:
1801 1 : stmt = parse_try_statement ();
1802 : break;
1803 : case TokenType.LOCK:
1804 0 : stmt = parse_lock_statement ();
1805 : break;
1806 : case TokenType.DELETE:
1807 0 : stmt = parse_delete_statement ();
1808 : break;
1809 : case TokenType.VAR:
1810 38 : is_decl = true;
1811 38 : parse_type_inference_declaration (block);
1812 : break;
1813 : case TokenType.YIELD:
1814 0 : stmt = parse_yield_statement ();
1815 : break;
1816 :
1817 : case TokenType.OP_INC:
1818 : case TokenType.OP_DEC:
1819 : case TokenType.SUPER:
1820 : case TokenType.SELF:
1821 : case TokenType.OPEN_PARENS:
1822 : case TokenType.STAR:
1823 : case TokenType.NEW:
1824 1 : stmt = parse_expression_statement ();
1825 : break;
1826 : default:
1827 101 : bool is_expr = is_expression ();
1828 101 : if (is_expr) {
1829 215 : stmt = parse_expression_statement ();
1830 : } else {
1831 50 : is_decl = true;
1832 50 : parse_local_variable_declarations (block);
1833 : }
1834 : break;
1835 : }
1836 :
1837 0 : if (!is_decl) {
1838 215 : block.add_statement (stmt);
1839 : }
1840 : } catch (ParseError e) {
1841 0 : report_parse_error (e);
1842 0 : if (recover () != RecoveryState.STATEMENT_BEGIN) {
1843 : // beginning of next declaration or end of file reached
1844 : // return what we have so far
1845 0 : break;
1846 : }
1847 : }
1848 : }
1849 : }
1850 :
1851 104 : bool is_expression () throws ParseError {
1852 104 : var begin = get_location ();
1853 :
1854 : // decide between declaration and expression statement
1855 104 : skip_type ();
1856 104 : switch (current ()) {
1857 : // invocation expression
1858 : case TokenType.OPEN_PARENS:
1859 : // postfix increment
1860 : case TokenType.OP_INC:
1861 : // postfix decrement
1862 : case TokenType.OP_DEC:
1863 : // assignments
1864 : case TokenType.ASSIGN:
1865 : case TokenType.ASSIGN_ADD:
1866 : case TokenType.ASSIGN_BITWISE_AND:
1867 : case TokenType.ASSIGN_BITWISE_OR:
1868 : case TokenType.ASSIGN_BITWISE_XOR:
1869 : case TokenType.ASSIGN_DIV:
1870 : case TokenType.ASSIGN_MUL:
1871 : case TokenType.ASSIGN_PERCENT:
1872 : case TokenType.ASSIGN_SHIFT_LEFT:
1873 : case TokenType.ASSIGN_SUB:
1874 : case TokenType.OP_GT: // >>=
1875 : // member access
1876 : case TokenType.DOT:
1877 : // pointer member access
1878 : case TokenType.OP_PTR:
1879 52 : rollback (begin);
1880 52 : return true;
1881 : default:
1882 52 : rollback (begin);
1883 52 : return false;
1884 : }
1885 : }
1886 :
1887 33 : Block parse_embedded_statement () throws ParseError {
1888 33 : if (current () == TokenType.INDENT) {
1889 31 : var block = parse_block ();
1890 33 : return block;
1891 : }
1892 :
1893 2 : comment = scanner.pop_comment ();
1894 :
1895 2 : var block = new Block (get_src (get_location ()));
1896 2 : block.add_statement (parse_embedded_statement_without_block ());
1897 2 : return block;
1898 :
1899 : }
1900 :
1901 2 : Statement parse_embedded_statement_without_block () throws ParseError {
1902 2 : switch (current ()) {
1903 : case TokenType.PASS:
1904 0 : case TokenType.SEMICOLON: return parse_empty_statement ();
1905 1 : case TokenType.IF: return parse_if_statement ();
1906 0 : case TokenType.CASE: return parse_switch_statement ();
1907 0 : case TokenType.WHILE: return parse_while_statement ();
1908 0 : case TokenType.DO: return parse_do_statement ();
1909 0 : case TokenType.FOR: return get_for_statement_type ();
1910 0 : case TokenType.BREAK: return parse_break_statement ();
1911 0 : case TokenType.CONTINUE: return parse_continue_statement ();
1912 0 : case TokenType.RETURN: return parse_return_statement ();
1913 0 : case TokenType.YIELD: return parse_yield_statement ();
1914 0 : case TokenType.RAISE: return parse_throw_statement ();
1915 0 : case TokenType.TRY: return parse_try_statement ();
1916 0 : case TokenType.LOCK: return parse_lock_statement ();
1917 0 : case TokenType.DELETE: return parse_delete_statement ();
1918 : case TokenType.VAR:
1919 : case TokenType.CONST:
1920 0 : throw new ParseError.SYNTAX ("embedded statement cannot be declaration ");
1921 : case TokenType.OP_INC:
1922 : case TokenType.OP_DEC:
1923 : case TokenType.SUPER:
1924 : case TokenType.SELF:
1925 : case TokenType.OPEN_PARENS:
1926 : case TokenType.STAR:
1927 : case TokenType.NEW:
1928 0 : return parse_expression_statement ();
1929 : default:
1930 1 : if (is_expression ()) {
1931 1 : return parse_expression_statement ();
1932 : } else {
1933 0 : throw new ParseError.SYNTAX ("embedded statement cannot be declaration");
1934 : }
1935 : }
1936 : }
1937 :
1938 141 : Block parse_block () throws ParseError {
1939 141 : var begin = get_location ();
1940 141 : expect (TokenType.INDENT);
1941 141 : var block = new Block (get_src (begin));
1942 141 : parse_statements (block);
1943 141 : if (!accept (TokenType.DEDENT)) {
1944 : // only report error if it's not a secondary error
1945 0 : if (context.report.get_errors () == 0) {
1946 0 : Report.error (get_current_src (), "tab indentation is incorrect");
1947 : }
1948 : }
1949 :
1950 141 : block.source_reference.end = get_current_src ().end;
1951 :
1952 : return block;
1953 : }
1954 :
1955 1 : Statement parse_empty_statement () throws ParseError {
1956 1 : var begin = get_location ();
1957 :
1958 1 : accept (TokenType.PASS);
1959 1 : accept (TokenType.SEMICOLON);
1960 1 : expect_terminator ();
1961 :
1962 1 : return new EmptyStatement (get_src (begin));
1963 : }
1964 :
1965 38 : void parse_type_inference_declaration (Block block) throws ParseError {
1966 38 : expect (TokenType.VAR);
1967 38 : bool block_var = false;
1968 76 : if (accept (TokenType.EOL) && accept (TokenType.INDENT)) { block_var = true; }
1969 76 : do {
1970 38 : var s = parse_identifier ();
1971 38 : var local = parse_local_variable (null, s, true);
1972 38 : block.add_statement (new DeclarationStatement (local, local.source_reference));
1973 : }
1974 38 : while ((block_var) && (current () != TokenType.DEDENT));
1975 38 : if ( block_var ) { expect (TokenType.DEDENT); }
1976 : }
1977 :
1978 100 : void parse_local_variable_declarations (Block block) throws ParseError {
1979 50 : var id_list = new ArrayList<string> (str_equal);
1980 50 : id_list.add (parse_identifier ());
1981 : // Allow multiple declarations
1982 50 : while (accept (TokenType.COMMA)) {
1983 0 : id_list.add (parse_identifier ());
1984 : }
1985 :
1986 50 : expect (TokenType.COLON);
1987 50 : DataType variable_type = parse_type (true, true);
1988 50 : var type = parse_inline_array_type (variable_type);
1989 :
1990 50 : var iterator = id_list.iterator();
1991 50 : iterator.next();
1992 50 : bool expect_terminator = false;
1993 100 : while (!expect_terminator) {
1994 50 : string id = iterator.get();
1995 50 : DataType type_copy = null;
1996 50 : if (type != null) {
1997 50 : type_copy = type.copy ();
1998 : }
1999 50 : if (!iterator.next()) {
2000 50 : expect_terminator = true;
2001 : }
2002 50 : var local = parse_local_variable (type_copy, id, expect_terminator);
2003 50 : block.add_statement (new DeclarationStatement (local, local.source_reference));
2004 : }
2005 : }
2006 :
2007 90 : LocalVariable parse_local_variable (DataType? variable_type, string id, bool expect_terminator = false) throws ParseError {
2008 90 : var begin = get_location ();
2009 90 : Expression initializer = null;
2010 90 : if (accept (TokenType.ASSIGN)) {
2011 90 : if (expect_terminator) {
2012 88 : initializer = parse_expression_with_terminator ();
2013 : } else {
2014 2 : initializer = parse_expression ();
2015 : }
2016 0 : } else if (expect_terminator) {
2017 0 : this.expect_terminator();
2018 : }
2019 90 : return new LocalVariable (variable_type, id, initializer, get_src (begin));
2020 : }
2021 :
2022 168 : Statement parse_expression_statement () throws ParseError {
2023 168 : var begin = get_location ();
2024 168 : var expr = parse_expression_with_terminator ();
2025 168 : return new ExpressionStatement (expr, get_src (begin));
2026 : }
2027 :
2028 0 : Expression parse_statement_expression () throws ParseError {
2029 : // invocation expression, assignment,
2030 : // or pre/post increment/decrement expression
2031 0 : var expr = parse_expression ();
2032 : return expr;
2033 : }
2034 :
2035 17 : Statement parse_if_statement () throws ParseError {
2036 17 : var begin = get_location ();
2037 :
2038 17 : expect (TokenType.IF);
2039 :
2040 17 : var condition = parse_expression ();
2041 :
2042 17 : if (!accept (TokenType.DO)) {
2043 16 : expect (TokenType.EOL);
2044 : } else {
2045 1 : accept (TokenType.EOL);
2046 : }
2047 :
2048 17 : var src = get_src (begin);
2049 17 : var true_stmt = parse_embedded_statement ();
2050 17 : Block false_stmt = null;
2051 17 : if (accept (TokenType.ELSE)) {
2052 : // allow `else if' on the same line without `do'
2053 9 : if (!accept (TokenType.DO) && current () != TokenType.IF) {
2054 8 : expect (TokenType.EOL);
2055 : } else {
2056 1 : accept (TokenType.EOL);
2057 : }
2058 :
2059 9 : false_stmt = parse_embedded_statement ();
2060 : }
2061 17 : return new IfStatement (condition, true_stmt, false_stmt, src);
2062 : }
2063 :
2064 1 : Statement parse_switch_statement () throws ParseError {
2065 1 : var begin = get_location ();
2066 1 : expect (TokenType.CASE);
2067 1 : var condition = parse_expression ();
2068 :
2069 1 : expect (TokenType.EOL);
2070 :
2071 1 : var stmt = new SwitchStatement (condition, get_src (begin));
2072 1 : expect (TokenType.INDENT);
2073 4 : while (current () != TokenType.DEDENT) {
2074 3 : var section = new SwitchSection (get_src (begin));
2075 :
2076 3 : if (accept (TokenType.WHEN)) {
2077 5 : do {
2078 3 : section.add_label (new SwitchLabel (parse_expression (), get_src (begin)));
2079 : }
2080 3 : while (accept (TokenType.COMMA));
2081 : } else {
2082 1 : expect (TokenType.DEFAULT);
2083 1 : section.add_label (new SwitchLabel.with_default (get_src (begin)));
2084 : }
2085 :
2086 3 : if (!accept (TokenType.EOL)) {
2087 0 : expect (TokenType.DO);
2088 : }
2089 :
2090 3 : parse_statements (section);
2091 :
2092 : /* add break statement for each block */
2093 3 : var break_stmt = new BreakStatement (get_src (begin));
2094 3 : section.add_statement (break_stmt);
2095 :
2096 3 : stmt.add_section (section);
2097 : }
2098 1 : expect (TokenType.DEDENT);
2099 1 : return stmt;
2100 : }
2101 :
2102 2 : Statement parse_while_statement () throws ParseError {
2103 2 : var begin = get_location ();
2104 2 : expect (TokenType.WHILE);
2105 2 : var condition = parse_expression ();
2106 :
2107 2 : if (!accept (TokenType.DO)) {
2108 1 : expect (TokenType.EOL);
2109 : } else {
2110 1 : accept (TokenType.EOL);
2111 : }
2112 :
2113 2 : var body = parse_embedded_statement ();
2114 2 : return new WhileStatement (condition, body, get_src (begin));
2115 : }
2116 :
2117 2 : Statement parse_do_statement () throws ParseError {
2118 2 : var begin = get_location ();
2119 2 : expect (TokenType.DO);
2120 2 : expect (TokenType.EOL);
2121 2 : var body = parse_embedded_statement ();
2122 2 : expect (TokenType.WHILE);
2123 :
2124 2 : var condition = parse_expression ();
2125 :
2126 2 : expect_terminator ();
2127 :
2128 2 : return new DoStatement (condition, body, get_src (begin));
2129 : }
2130 :
2131 :
2132 2 : Statement parse_for_statement () throws ParseError {
2133 2 : var begin = get_location ();
2134 2 : Block block = null;
2135 2 : Expression initializer = null;
2136 2 : Expression condition = null;
2137 2 : Expression iterator = null;
2138 : bool is_expr;
2139 : string id;
2140 :
2141 2 : expect (TokenType.FOR);
2142 :
2143 2 : switch (current ()) {
2144 : case TokenType.VAR:
2145 : is_expr = false;
2146 : break;
2147 : default:
2148 :
2149 2 : bool local_is_expr = is_expression ();
2150 : is_expr = local_is_expr;
2151 : break;
2152 : }
2153 :
2154 4 : if (is_expr) {
2155 0 : var expr_begin = get_location ();
2156 0 : id = parse_identifier ();
2157 0 : rollback (expr_begin);
2158 0 : initializer = parse_statement_expression ();
2159 : } else {
2160 2 : block = new Block (get_src (begin));
2161 : DataType variable_type;
2162 2 : if (accept (TokenType.VAR)) {
2163 0 : variable_type = null;
2164 0 : id = parse_identifier ();
2165 : } else {
2166 2 : id = parse_identifier ();
2167 2 : expect (TokenType.COLON);
2168 2 : variable_type = parse_type (true, true);
2169 : }
2170 :
2171 2 : DataType type_copy = null;
2172 2 : if (variable_type != null) {
2173 2 : type_copy = variable_type.copy ();
2174 : }
2175 2 : var local = parse_local_variable (type_copy, id);
2176 :
2177 2 : block.add_statement (new DeclarationStatement (local, local.source_reference));
2178 : }
2179 :
2180 :
2181 :
2182 4 : if (accept (TokenType.TO)) {
2183 : /* create expression for condition and incrementing iterator */
2184 1 : var to_begin = get_location ();
2185 1 : var to_src = get_src (to_begin);
2186 1 : var left = new MemberAccess (null, id, to_src);
2187 1 : var right = parse_primary_expression ();
2188 :
2189 1 : condition = new BinaryExpression (BinaryOperator.LESS_THAN_OR_EQUAL, left, right, to_src);
2190 :
2191 1 : iterator = new PostfixExpression (left, true, to_src);
2192 : } else {
2193 1 : expect (TokenType.DOWNTO);
2194 1 : var downto_begin = get_location ();
2195 1 : var downto_src = get_src (downto_begin);
2196 : /* create expression for condition and decrementing iterator */
2197 1 : var left = new MemberAccess (null, id, downto_src);
2198 1 : var right = parse_primary_expression ();
2199 :
2200 1 : condition = new BinaryExpression (BinaryOperator.GREATER_THAN_OR_EQUAL, left, right, downto_src);
2201 :
2202 1 : iterator = new PostfixExpression (left, false, downto_src);
2203 : }
2204 :
2205 2 : if (!accept (TokenType.EOL)) {
2206 0 : expect (TokenType.DO);
2207 : }
2208 :
2209 2 : var src = get_src (begin);
2210 2 : var body = parse_embedded_statement ();
2211 2 : var stmt = new ForStatement (condition, body, src);
2212 :
2213 2 : if (initializer != null) stmt.add_initializer (initializer);
2214 :
2215 2 : stmt.add_iterator (iterator);
2216 :
2217 :
2218 2 : if (block != null) {
2219 2 : block.add_statement (stmt);
2220 2 : return block;
2221 : } else {
2222 0 : return stmt;
2223 : }
2224 : }
2225 :
2226 1 : Statement parse_foreach_statement () throws ParseError {
2227 1 : var begin = get_location ();
2228 1 : DataType type = null;
2229 1 : string id = null;
2230 :
2231 1 : expect (TokenType.FOR);
2232 :
2233 1 : if (accept (TokenType.VAR)) {
2234 0 : id = parse_identifier ();
2235 : } else {
2236 1 : id = parse_identifier ();
2237 1 : if (accept (TokenType.COLON)) {
2238 1 : type = parse_type (true, true);
2239 : }
2240 : }
2241 :
2242 1 : expect (TokenType.IN);
2243 1 : var collection = parse_expression ();
2244 1 : if (!accept (TokenType.EOL)) {
2245 0 : expect (TokenType.DO);
2246 : }
2247 1 : var src = get_src (begin);
2248 1 : var body = parse_embedded_statement ();
2249 1 : return new ForeachStatement (type, id, collection, body, src);
2250 : }
2251 :
2252 2 : Statement parse_break_statement () throws ParseError {
2253 2 : var begin = get_location ();
2254 2 : expect (TokenType.BREAK);
2255 2 : expect_terminator ();
2256 2 : return new BreakStatement (get_src (begin));
2257 : }
2258 :
2259 1 : Statement parse_continue_statement () throws ParseError {
2260 1 : var begin = get_location ();
2261 1 : expect (TokenType.CONTINUE);
2262 1 : expect_terminator ();
2263 1 : return new ContinueStatement (get_src (begin));
2264 : }
2265 :
2266 18 : Statement parse_return_statement () throws ParseError {
2267 18 : var begin = get_location ();
2268 18 : expect (TokenType.RETURN);
2269 18 : Expression expr = null;
2270 18 : if (current () != TokenType.SEMICOLON && current () != TokenType.EOL) {
2271 11 : expr = parse_expression_with_terminator ();
2272 : } else {
2273 7 : expect_terminator ();
2274 : }
2275 18 : return new ReturnStatement (expr, get_src (begin));
2276 : }
2277 :
2278 0 : Statement parse_yield_statement () throws ParseError {
2279 0 : var begin = get_location ();
2280 0 : expect (TokenType.YIELD);
2281 0 : if (current () != TokenType.SEMICOLON && current () != TokenType.EOL) {
2282 0 : prev ();
2283 0 : return parse_expression_statement ();
2284 : }
2285 0 : expect_terminator ();
2286 0 : return new YieldStatement (get_src (begin));
2287 : }
2288 :
2289 1 : Statement parse_throw_statement () throws ParseError {
2290 1 : var begin = get_location ();
2291 1 : expect (TokenType.RAISE);
2292 1 : var expr = parse_expression ();
2293 1 : expect_terminator ();
2294 1 : return new ThrowStatement (expr, get_src (begin));
2295 : }
2296 :
2297 1 : Statement parse_try_statement () throws ParseError {
2298 1 : var begin = get_location ();
2299 1 : expect (TokenType.TRY);
2300 1 : expect (TokenType.EOL);
2301 1 : var try_block = parse_block ();
2302 1 : Block finally_clause = null;
2303 1 : var catch_clauses = new ArrayList<CatchClause> ();
2304 1 : if (current () == TokenType.EXCEPT) {
2305 1 : parse_catch_clauses (catch_clauses);
2306 1 : if (current () == TokenType.FINALLY) {
2307 1 : finally_clause = parse_finally_clause ();
2308 : }
2309 : } else {
2310 0 : finally_clause = parse_finally_clause ();
2311 : }
2312 1 : var stmt = new TryStatement (try_block, finally_clause, get_src (begin));
2313 3 : foreach (CatchClause clause in catch_clauses) {
2314 1 : stmt.add_catch_clause (clause);
2315 : }
2316 1 : return stmt;
2317 : }
2318 :
2319 1 : void parse_catch_clauses (List<CatchClause> catch_clauses) throws ParseError {
2320 2 : while (accept (TokenType.EXCEPT)) {
2321 1 : var begin = get_location ();
2322 1 : DataType type = null;
2323 1 : string id = null;
2324 1 : if (!accept (TokenType.EOL)) {
2325 1 : id = parse_identifier ();
2326 1 : expect (TokenType.COLON);
2327 1 : type = parse_type (true, true);
2328 1 : expect (TokenType.EOL);
2329 :
2330 : }
2331 1 : var block = parse_block ();
2332 1 : catch_clauses.add (new CatchClause (type, id, block, get_src (begin)));
2333 : }
2334 : }
2335 :
2336 1 : Block parse_finally_clause () throws ParseError {
2337 1 : expect (TokenType.FINALLY);
2338 1 : accept_block ();
2339 1 : var block = parse_block ();
2340 : return block;
2341 : }
2342 :
2343 0 : Statement parse_lock_statement () throws ParseError {
2344 0 : var begin = get_location ();
2345 0 : expect (TokenType.LOCK);
2346 0 : expect (TokenType.OPEN_PARENS);
2347 0 : var expr = parse_expression ();
2348 0 : expect (TokenType.CLOSE_PARENS);
2349 0 : var stmt = parse_embedded_statement ();
2350 0 : return new LockStatement (expr, stmt, get_src (begin));
2351 : }
2352 :
2353 0 : Statement parse_delete_statement () throws ParseError {
2354 0 : var begin = get_location ();
2355 0 : expect (TokenType.DELETE);
2356 0 : var expr = parse_expression ();
2357 0 : expect_terminator ();
2358 0 : return new DeleteStatement (expr, get_src (begin));
2359 : }
2360 :
2361 10 : string parse_attribute_value () throws ParseError {
2362 10 : switch (current ()) {
2363 : case TokenType.NULL:
2364 : case TokenType.TRUE:
2365 : case TokenType.FALSE:
2366 : case TokenType.INTEGER_LITERAL:
2367 : case TokenType.REAL_LITERAL:
2368 : case TokenType.STRING_LITERAL:
2369 10 : next ();
2370 10 : return get_last_string ();
2371 : case TokenType.MINUS:
2372 0 : next ();
2373 0 : switch (current ()) {
2374 : case TokenType.INTEGER_LITERAL:
2375 : case TokenType.REAL_LITERAL:
2376 0 : next ();
2377 0 : return "-" + get_last_string ();
2378 : default:
2379 0 : throw new ParseError.SYNTAX ("expected number");
2380 : }
2381 : default:
2382 0 : throw new ParseError.SYNTAX ("expected literal");
2383 : }
2384 : }
2385 :
2386 163 : List<Attribute>? parse_attributes () throws ParseError {
2387 163 : if (current () != TokenType.OPEN_BRACKET) {
2388 153 : return null;
2389 : }
2390 10 : var attrs = new ArrayList<Attribute> ();
2391 20 : while (accept (TokenType.OPEN_BRACKET)) {
2392 20 : do {
2393 10 : var begin = get_location ();
2394 10 : string id = parse_identifier ();
2395 10 : var attr = new Attribute (id, get_src (begin));
2396 10 : if (accept (TokenType.OPEN_PARENS)) {
2397 10 : if (current () != TokenType.CLOSE_PARENS) {
2398 20 : do {
2399 10 : id = parse_identifier ();
2400 10 : expect (TokenType.ASSIGN);
2401 10 : attr.add_argument (id, parse_attribute_value ());
2402 10 : } while (accept (TokenType.COMMA));
2403 : }
2404 10 : expect (TokenType.CLOSE_PARENS);
2405 : }
2406 10 : attrs.add (attr);
2407 10 : } while (accept (TokenType.COMMA));
2408 10 : expect (TokenType.CLOSE_BRACKET);
2409 : }
2410 10 : accept (TokenType.EOL);
2411 :
2412 10 : return attrs;
2413 : }
2414 :
2415 159 : void set_attributes (CodeNode node, List<Attribute>? attributes) {
2416 159 : if (attributes != null) {
2417 30 : foreach (Attribute attr in (List<Attribute>) attributes) {
2418 10 : if (node.has_attribute (attr.name)) {
2419 0 : Report.error (attr.source_reference, "duplicate attribute `%s'", attr.name);
2420 : }
2421 20 : node.attributes.append (attr);
2422 : }
2423 : }
2424 : }
2425 :
2426 143 : Symbol parse_declaration (bool is_root = false) throws ParseError {
2427 143 : comment = scanner.pop_comment ();
2428 143 : var attrs = parse_attributes ();
2429 143 : var begin = get_location ();
2430 :
2431 143 : switch (current ()) {
2432 : case TokenType.CONST:
2433 1 : return parse_constant_declaration (attrs);
2434 : case TokenType.CONSTRUCT:
2435 4 : return parse_creation_method_declaration (attrs);
2436 : case TokenType.CLASS:
2437 11 : return parse_class_declaration (attrs);
2438 : case TokenType.INIT:
2439 88 : if (is_root) {
2440 85 : return parse_main_method_declaration (attrs);
2441 : }
2442 3 : if (context.profile == Profile.GOBJECT) {
2443 3 : rollback (begin);
2444 3 : return parse_constructor_declaration (attrs);
2445 : }
2446 : break;
2447 : case TokenType.DELEGATE:
2448 1 : return parse_delegate_declaration (attrs);
2449 : case TokenType.DEF:
2450 13 : return parse_method_declaration (attrs);
2451 : case TokenType.ENUM:
2452 2 : return parse_enum_declaration (attrs);
2453 : case TokenType.EXCEPTION:
2454 1 : return parse_errordomain_declaration (attrs);
2455 : case TokenType.FINAL:
2456 1 : return parse_destructor_declaration (attrs);
2457 : case TokenType.INTERFACE:
2458 1 : return parse_interface_declaration (attrs);
2459 : case TokenType.NAMESPACE:
2460 0 : return parse_namespace_declaration (attrs);
2461 : case TokenType.PROP:
2462 5 : return parse_property_declaration (attrs);
2463 : case TokenType.EVENT:
2464 1 : return parse_signal_declaration (attrs);
2465 : case TokenType.STRUCT:
2466 2 : return parse_struct_declaration (attrs);
2467 : default:
2468 :
2469 24 : while (current () != TokenType.EOL && current () != TokenType.SEMICOLON && current () != TokenType.EOF) {
2470 24 : if (current () == TokenType.COLON) {
2471 12 : rollback (begin);
2472 12 : return parse_field_declaration (attrs);
2473 : } else {
2474 12 : next ();
2475 : }
2476 : }
2477 0 : rollback (begin);
2478 :
2479 0 : break;
2480 : }
2481 :
2482 0 : TokenType cur = current ();
2483 0 : TokenType pre = tokens[index-1].type;
2484 :
2485 0 : throw new ParseError.SYNTAX ("expected a declaration after %s, but got %s", pre.to_string (), cur.to_string());
2486 : }
2487 :
2488 99 : void parse_declarations (Symbol parent, bool root = false) throws ParseError {
2489 99 : if (!root) {
2490 14 : expect (TokenType.INDENT);
2491 : }
2492 242 : while (current () != TokenType.DEDENT && current () != TokenType.EOF) {
2493 143 : try {
2494 143 : if (parent is Namespace) {
2495 114 : parse_namespace_member ((Namespace) parent);
2496 29 : } else if (parent is Class) {
2497 24 : parse_class_member ((Class) parent);
2498 5 : } else if (parent is Struct) {
2499 4 : parse_struct_member ((Struct) parent);
2500 1 : } else if (parent is Interface) {
2501 1 : parse_interface_member ((Interface) parent);
2502 : }
2503 : } catch (ParseError e) {
2504 0 : report_parse_error (e);
2505 : int r;
2506 0 : do {
2507 0 : r = recover ();
2508 0 : if (r == RecoveryState.STATEMENT_BEGIN) {
2509 0 : next ();
2510 : } else {
2511 : break;
2512 : }
2513 : } while (true);
2514 0 : if (r == RecoveryState.EOF) {
2515 0 : return;
2516 : }
2517 : }
2518 : }
2519 99 : if (!root) {
2520 14 : if (!accept (TokenType.DEDENT)) {
2521 : // only report error if it's not a secondary error
2522 0 : if (context.report.get_errors () == 0) {
2523 0 : Report.error (get_current_src (), "expected dedent");
2524 : }
2525 : }
2526 : }
2527 : }
2528 :
2529 : enum RecoveryState {
2530 : EOF,
2531 : DECLARATION_BEGIN,
2532 : STATEMENT_BEGIN
2533 : }
2534 :
2535 0 : RecoveryState recover () {
2536 0 : while (current () != TokenType.EOF) {
2537 0 : switch (current ()) {
2538 : case TokenType.CLASS:
2539 : case TokenType.CONST:
2540 : case TokenType.CONSTRUCT:
2541 : case TokenType.INIT:
2542 : case TokenType.DEF:
2543 : case TokenType.DELEGATE:
2544 : case TokenType.ENUM:
2545 : case TokenType.EXCEPTION:
2546 : case TokenType.FINAL:
2547 : case TokenType.INTERFACE:
2548 : case TokenType.NAMESPACE:
2549 : case TokenType.PROP:
2550 : case TokenType.EVENT:
2551 : case TokenType.STRUCT:
2552 : return RecoveryState.DECLARATION_BEGIN;
2553 : case TokenType.BREAK:
2554 : case TokenType.CASE:
2555 : case TokenType.CONTINUE:
2556 : case TokenType.DELETE:
2557 : case TokenType.DO:
2558 : case TokenType.FOR:
2559 : case TokenType.IF:
2560 : case TokenType.LOCK:
2561 : case TokenType.RETURN:
2562 : case TokenType.RAISE:
2563 : case TokenType.TRY:
2564 : case TokenType.VAR:
2565 : case TokenType.WHILE:
2566 : case TokenType.YIELD:
2567 : return RecoveryState.STATEMENT_BEGIN;
2568 : default:
2569 0 : next ();
2570 0 : break;
2571 : }
2572 : }
2573 : return RecoveryState.EOF;
2574 : }
2575 :
2576 0 : Namespace parse_namespace_declaration (List<Attribute>? attrs) throws ParseError {
2577 0 : var begin = get_location ();
2578 0 : expect (TokenType.NAMESPACE);
2579 0 : var sym = parse_symbol_name ();
2580 0 : var ns = new Namespace (sym.name, get_src (begin));
2581 0 : if (comment != null) {
2582 0 : ns.add_comment (comment);
2583 0 : comment = null;
2584 : }
2585 0 : set_attributes (ns, attrs);
2586 0 : expect (TokenType.EOL);
2587 0 : parse_declarations (ns);
2588 :
2589 0 : Namespace result = ns;
2590 0 : while (sym.inner != null) {
2591 0 : sym = sym.inner;
2592 0 : ns = new Namespace (sym.name, result.source_reference);
2593 0 : ns.add_namespace ((Namespace) result);
2594 0 : result = ns;
2595 : }
2596 0 : return result;
2597 : }
2598 :
2599 228 : void parse_namespace_member (Namespace ns) throws ParseError {
2600 :
2601 114 : var sym = parse_declaration ((ns == context.root));
2602 114 : if (sym is Namespace) {
2603 0 : ns.add_namespace ((Namespace) sym);
2604 114 : } else if (sym is Class) {
2605 11 : ns.add_class ((Class) sym);
2606 103 : } else if (sym is Interface) {
2607 1 : ns.add_interface ((Interface) sym);
2608 102 : } else if (sym is Struct) {
2609 2 : ns.add_struct ((Struct) sym);
2610 100 : } else if (sym is Enum) {
2611 2 : ns.add_enum ((Enum) sym);
2612 98 : } else if (sym is ErrorDomain) {
2613 1 : ns.add_error_domain ((ErrorDomain) sym);
2614 97 : } else if (sym is Delegate) {
2615 1 : ns.add_delegate ((Delegate) sym);
2616 96 : } else if (sym is Method) {
2617 94 : unowned Method method = (Method) sym;
2618 94 : if (method.binding == MemberBinding.INSTANCE) {
2619 9 : method.binding = MemberBinding.STATIC;
2620 : }
2621 94 : ns.add_method (method);
2622 2 : } else if (sym is Field) {
2623 1 : unowned Field field = (Field) sym;
2624 1 : if (field.binding == MemberBinding.INSTANCE) {
2625 1 : field.binding = MemberBinding.STATIC;
2626 : }
2627 1 : ns.add_field (field);
2628 1 : } else if (sym is Constant) {
2629 1 : ns.add_constant ((Constant) sym);
2630 : } else {
2631 0 : Report.error (sym.source_reference, "unexpected declaration in namespace");
2632 : }
2633 : }
2634 :
2635 :
2636 0 : void add_uses_clause (Namespace ns) throws ParseError {
2637 0 : var begin = get_location ();
2638 0 : var sym = parse_symbol_name ();
2639 0 : var ns_ref = new UsingDirective (sym, get_src (begin));
2640 :
2641 0 : scanner.source_file.add_using_directive (ns_ref);
2642 0 : ns.add_using_directive (ns_ref);
2643 : }
2644 :
2645 85 : void parse_using_directives (Namespace ns) throws ParseError {
2646 85 : while (accept (TokenType.USES)) {
2647 0 : if (accept_block ()) {
2648 0 : expect (TokenType.INDENT);
2649 :
2650 0 : while (current () != TokenType.DEDENT && current () != TokenType.EOF) {
2651 0 : add_uses_clause (ns);
2652 0 : expect (TokenType.EOL);
2653 : }
2654 :
2655 0 : expect (TokenType.DEDENT);
2656 : } else {
2657 0 : do {
2658 0 : add_uses_clause (ns);
2659 0 : } while (accept (TokenType.COMMA));
2660 :
2661 0 : expect_terminator ();
2662 : }
2663 : }
2664 :
2665 : }
2666 :
2667 11 : Symbol parse_class_declaration (List<Attribute>? attrs) throws ParseError {
2668 11 : var begin = get_location ();
2669 11 : expect (TokenType.CLASS);
2670 :
2671 11 : var flags = parse_type_declaration_modifiers ();
2672 :
2673 11 : var sym = parse_symbol_name ();
2674 11 : var type_param_list = parse_type_parameter_list ();
2675 11 : var base_types = new ArrayList<DataType> ();
2676 14 : if (accept (TokenType.COLON)) {
2677 3 : var type1 = parse_type (true, false);
2678 3 : base_types.add (type1);
2679 :
2680 3 : if (accept (TokenType.IMPLEMENTS)) {
2681 3 : do {
2682 1 : var type2 = parse_type (true, true);
2683 1 : base_types.add (type2);
2684 1 : } while (accept (TokenType.COMMA));
2685 : }
2686 : }
2687 :
2688 11 : accept (TokenType.EOL);
2689 :
2690 11 : var cl = new Class (sym.name, get_src (begin), comment);
2691 :
2692 11 : if (ModifierFlags.PRIVATE in flags) {
2693 0 : cl.access = SymbolAccessibility.PRIVATE;
2694 11 : } else if (ModifierFlags.PROTECTED in flags) {
2695 0 : cl.access = SymbolAccessibility.PROTECTED;
2696 : } else {
2697 11 : cl.access = get_default_accessibility (sym.name);
2698 : }
2699 :
2700 11 : if (ModifierFlags.ABSTRACT in flags) {
2701 2 : cl.is_abstract = true;
2702 : }
2703 11 : set_attributes (cl, attrs);
2704 11 : foreach (TypeParameter type_param in type_param_list) {
2705 0 : cl.add_type_parameter (type_param);
2706 : }
2707 19 : foreach (DataType base_type in base_types) {
2708 4 : cl.add_base_type (base_type);
2709 : }
2710 :
2711 22 : class_name = cl.name;
2712 :
2713 11 : parse_declarations (cl);
2714 :
2715 : // ensure there is always a default construction method
2716 20 : if (scanner.source_file.file_type == SourceFileType.SOURCE
2717 11 : && cl.default_construction_method == null) {
2718 9 : var m = new CreationMethod (cl.name, null, cl.source_reference);
2719 9 : m.access = (cl.is_abstract ? SymbolAccessibility.PROTECTED : SymbolAccessibility.PUBLIC);
2720 9 : m.body = new Block (cl.source_reference);
2721 9 : cl.add_method (m);
2722 : }
2723 :
2724 11 : Symbol result = cl;
2725 11 : while (sym.inner != null) {
2726 0 : sym = sym.inner;
2727 0 : var ns = new Namespace (sym.name, cl.source_reference);
2728 0 : if (result is Namespace) {
2729 0 : ns.add_namespace ((Namespace) result);
2730 : } else {
2731 0 : ns.add_class ((Class) result);
2732 : }
2733 0 : result = ns;
2734 : }
2735 11 : return result;
2736 : }
2737 :
2738 48 : void parse_class_member (Class cl) throws ParseError {
2739 24 : var sym = parse_declaration ();
2740 24 : if (sym is Class) {
2741 0 : cl.add_class ((Class) sym);
2742 24 : } else if (sym is Struct) {
2743 0 : cl.add_struct ((Struct) sym);
2744 24 : } else if (sym is Enum) {
2745 0 : cl.add_enum ((Enum) sym);
2746 24 : } else if (sym is Delegate) {
2747 0 : cl.add_delegate ((Delegate) sym);
2748 24 : } else if (sym is Method) {
2749 5 : cl.add_method ((Method) sym);
2750 19 : } else if (sym is Vala.Signal) {
2751 1 : cl.add_signal ((Vala.Signal) sym);
2752 18 : } else if (sym is Field) {
2753 9 : cl.add_field ((Field) sym);
2754 9 : } else if (sym is Constant) {
2755 0 : cl.add_constant ((Constant) sym);
2756 9 : } else if (sym is Property) {
2757 5 : cl.add_property ((Property) sym);
2758 4 : } else if (sym is Constructor) {
2759 3 : cl.add_constructor ((Constructor) sym);
2760 1 : } else if (sym is Destructor) {
2761 1 : cl.add_destructor ((Destructor) sym);
2762 : } else {
2763 0 : Report.error (sym.source_reference, "unexpected declaration in class");
2764 : }
2765 : }
2766 :
2767 1 : Constant parse_constant_declaration (List<Attribute>? attrs) throws ParseError {
2768 1 : var begin = get_location ();
2769 :
2770 1 : expect (TokenType.CONST);
2771 :
2772 1 : var flags = parse_member_declaration_modifiers ();
2773 :
2774 1 : string id = parse_identifier ();
2775 :
2776 1 : expect (TokenType.COLON);
2777 1 : var type = parse_type (false, false);
2778 1 : type = parse_inline_array_type (type);
2779 :
2780 1 : Expression initializer = null;
2781 1 : if (accept (TokenType.ASSIGN)) {
2782 1 : initializer = parse_expression ();
2783 : }
2784 1 : expect_terminator ();
2785 :
2786 : // constant arrays don't own their element
2787 1 : unowned ArrayType? array_type = type as ArrayType;
2788 0 : if (array_type != null) {
2789 0 : array_type.element_type.value_owned = false;
2790 : }
2791 :
2792 1 : var c = new Constant (id, type, initializer, get_src (begin), comment);
2793 1 : c.access = get_default_accessibility (id);
2794 :
2795 1 : if (ModifierFlags.EXTERN in flags) {
2796 0 : c.is_extern = true;
2797 : }
2798 1 : if (ModifierFlags.NEW in flags) {
2799 0 : c.hides = true;
2800 : }
2801 :
2802 1 : set_attributes (c, attrs);
2803 :
2804 1 : if (ModifierFlags.STATIC in flags) {
2805 0 : Report.warning (c.source_reference, "the modifier `static' is not applicable to constants");
2806 : }
2807 :
2808 1 : return c;
2809 : }
2810 :
2811 12 : Field parse_field_declaration (List<Attribute>? attrs) throws ParseError {
2812 12 : var begin = get_location ();
2813 12 : string id = parse_identifier ();
2814 12 : expect (TokenType.COLON);
2815 :
2816 12 : var flags = parse_member_declaration_modifiers ();
2817 :
2818 12 : var type = parse_type (true, true);
2819 :
2820 12 : type = parse_inline_array_type (type);
2821 :
2822 12 : var f = new Field (id, type, null, get_src (begin), comment);
2823 :
2824 12 : if (ModifierFlags.ABSTRACT in flags || ModifierFlags.VIRTUAL in flags || ModifierFlags.OVERRIDE in flags) {
2825 0 : Report.error (f.source_reference, "abstract, virtual, and override modifiers are not applicable to fields");
2826 : }
2827 :
2828 12 : if (ModifierFlags.PRIVATE in flags) {
2829 0 : f.access = SymbolAccessibility.PRIVATE;
2830 12 : } else if (ModifierFlags.PROTECTED in flags) {
2831 0 : f.access = SymbolAccessibility.PROTECTED;
2832 : } else {
2833 12 : f.access = get_default_accessibility (id);
2834 : }
2835 :
2836 12 : set_attributes (f, attrs);
2837 :
2838 12 : if (ModifierFlags.EXTERN in flags) {
2839 0 : f.is_extern = true;
2840 : }
2841 12 : if (ModifierFlags.NEW in flags) {
2842 0 : f.hides = true;
2843 : }
2844 :
2845 20 : if (accept (TokenType.ASSIGN)) {
2846 8 : f.initializer = parse_expression ();
2847 : }
2848 :
2849 12 : if (ModifierFlags.STATIC in flags) {
2850 1 : f.binding = MemberBinding.STATIC;
2851 11 : } else if (ModifierFlags.CLASS in flags) {
2852 1 : f.binding = MemberBinding.CLASS;
2853 : }
2854 :
2855 12 : expect_terminator ();
2856 :
2857 12 : return f;
2858 : }
2859 :
2860 2 : InitializerList parse_initializer () throws ParseError {
2861 2 : var begin = get_location ();
2862 2 : if (!accept (TokenType.OPEN_PARENS)) {
2863 2 : expect (TokenType.OPEN_BRACE);
2864 : }
2865 2 : var initializer = new InitializerList (get_src (begin));
2866 2 : if (current () != TokenType.DEDENT) {
2867 14 : do {
2868 6 : var init = parse_argument ();
2869 6 : initializer.append (init);
2870 6 : } while (accept (TokenType.COMMA));
2871 : }
2872 2 : if (!accept (TokenType.CLOSE_PARENS)) {
2873 2 : expect (TokenType.CLOSE_BRACE);
2874 : }
2875 : return initializer;
2876 : }
2877 :
2878 :
2879 :
2880 :
2881 85 : Method parse_main_method_declaration (List<Attribute>? attrs) throws ParseError {
2882 85 : var begin = get_location ();
2883 : DataType type;
2884 :
2885 85 : expect (TokenType.INIT);
2886 :
2887 85 : if (accept (TokenType.COLON)) {
2888 1 : type = parse_type (true, false);
2889 1 : if (type.to_string () != "int") {
2890 0 : throw new ParseError.SYNTAX ("main `init' must return void or `int', but got `%s'".printf (type.to_string ()));
2891 : }
2892 : } else {
2893 84 : type = new VoidType ();
2894 : }
2895 :
2896 85 : var method = new Method ("main", type, get_src (begin), comment);
2897 85 : method.access = SymbolAccessibility.PUBLIC;
2898 85 : method.binding = MemberBinding.STATIC;
2899 85 : set_attributes (method, attrs);
2900 :
2901 85 : var sym = new UnresolvedSymbol (null, "string", get_src (begin));
2902 85 : type = new UnresolvedType.from_symbol (sym, get_src (begin));
2903 85 : type.value_owned = true;
2904 85 : type = new ArrayType (type, 1, get_src (begin));
2905 85 : type.nullable = false;
2906 :
2907 85 : var param = new Parameter ("args", type, get_src (begin));
2908 85 : method.add_parameter (param);
2909 :
2910 :
2911 85 : expect (TokenType.EOL);
2912 :
2913 170 : if (accept_block ()) {
2914 85 : method.body = parse_block ();
2915 : }
2916 :
2917 85 : return method;
2918 : }
2919 :
2920 13 : Method parse_method_declaration (List<Attribute>? attrs) throws ParseError {
2921 13 : var begin = get_location ();
2922 : DataType type;
2923 :
2924 13 : expect (TokenType.DEF);
2925 13 : var flags = parse_member_declaration_modifiers ();
2926 :
2927 13 : string id = parse_identifier ();
2928 :
2929 13 : var params = new ArrayList<Parameter> ();
2930 13 : expect (TokenType.OPEN_PARENS);
2931 :
2932 13 : if (current () != TokenType.CLOSE_PARENS) {
2933 22 : do {
2934 8 : var param = parse_parameter ();
2935 8 : params.add (param);
2936 8 : } while (accept (TokenType.COMMA));
2937 : }
2938 :
2939 13 : expect (TokenType.CLOSE_PARENS);
2940 :
2941 :
2942 : /* deal with return value */
2943 13 : if (accept (TokenType.COLON)) {
2944 9 : type = parse_type (true, false);
2945 : } else {
2946 4 : type = new VoidType ();
2947 : }
2948 :
2949 13 : var type_param_list = parse_type_parameter_list ();
2950 :
2951 13 : var method = new Method (id, type, get_src (begin), comment);
2952 13 : if (ModifierFlags.PRIVATE in flags) {
2953 0 : method.access = SymbolAccessibility.PRIVATE;
2954 13 : } else if (ModifierFlags.PROTECTED in flags) {
2955 0 : method.access = SymbolAccessibility.PROTECTED;
2956 : } else {
2957 13 : method.access = get_default_accessibility (id);
2958 : }
2959 :
2960 :
2961 13 : set_attributes (method, attrs);
2962 :
2963 13 : foreach (TypeParameter type_param in type_param_list) {
2964 0 : method.add_type_parameter (type_param);
2965 : }
2966 :
2967 :
2968 29 : foreach (Parameter param in params) {
2969 8 : method.add_parameter (param);
2970 : }
2971 :
2972 13 : if (accept (TokenType.RAISES)) {
2973 5 : do {
2974 2 : method.add_error_type (parse_type (true, false));
2975 2 : } while (accept (TokenType.COMMA));
2976 : }
2977 :
2978 :
2979 13 : if (ModifierFlags.STATIC in flags || id == "main") {
2980 0 : method.binding = MemberBinding.STATIC;
2981 13 : } else if (ModifierFlags.CLASS in flags) {
2982 0 : method.binding = MemberBinding.CLASS;
2983 : }
2984 13 : if (ModifierFlags.ASYNC in flags) {
2985 0 : method.coroutine = true;
2986 : }
2987 :
2988 13 : if (ModifierFlags.NEW in flags) {
2989 0 : method.hides = true;
2990 : }
2991 :
2992 13 : if (method.binding == MemberBinding.INSTANCE) {
2993 13 : if (ModifierFlags.ABSTRACT in flags) {
2994 1 : method.is_abstract = true;
2995 : }
2996 13 : if (ModifierFlags.VIRTUAL in flags) {
2997 0 : method.is_virtual = true;
2998 : }
2999 13 : if (ModifierFlags.OVERRIDE in flags) {
3000 0 : method.overrides = true;
3001 : }
3002 13 : if ((method.is_abstract && method.is_virtual)
3003 13 : || (method.is_abstract && method.overrides)
3004 13 : || (method.is_virtual && method.overrides)) {
3005 0 : throw new ParseError.SYNTAX ("only one of `abstract', `virtual', or `override' may be specified");
3006 : }
3007 : } else {
3008 0 : if (ModifierFlags.ABSTRACT in flags
3009 0 : || ModifierFlags.VIRTUAL in flags
3010 0 : || ModifierFlags.OVERRIDE in flags) {
3011 0 : throw new ParseError.SYNTAX ("the modifiers `abstract', `virtual', and `override' are not valid for static methods");
3012 : }
3013 : }
3014 :
3015 13 : if (ModifierFlags.INLINE in flags) {
3016 0 : method.is_inline = true;
3017 : }
3018 13 : if (ModifierFlags.EXTERN in flags) {
3019 0 : method.is_extern = true;
3020 : }
3021 :
3022 13 : expect (TokenType.EOL);
3023 :
3024 13 : var body_location = get_location ();
3025 :
3026 :
3027 : /* "requires" and "ensures" if present will be at start of the method body */
3028 13 : if (accept (TokenType.INDENT)) {
3029 12 : if (accept (TokenType.REQUIRES)) {
3030 :
3031 0 : if (accept (TokenType.EOL) && accept (TokenType.INDENT)) {
3032 0 : while (current() != TokenType.DEDENT) {
3033 0 : method.add_precondition (parse_expression ());
3034 0 : expect (TokenType.EOL);
3035 : }
3036 :
3037 0 : expect (TokenType.DEDENT);
3038 0 : accept_terminator ();
3039 : } else {
3040 :
3041 0 : method.add_precondition (parse_expression ());
3042 0 : expect_terminator ();
3043 :
3044 : }
3045 :
3046 : }
3047 :
3048 12 : if (accept (TokenType.ENSURES)) {
3049 0 : if (accept (TokenType.EOL) && accept (TokenType.INDENT)) {
3050 0 : while (current() != TokenType.DEDENT) {
3051 0 : method.add_postcondition (parse_expression ());
3052 0 : expect (TokenType.EOL);
3053 : }
3054 :
3055 0 : expect (TokenType.DEDENT);
3056 0 : accept_terminator ();
3057 : } else {
3058 0 : method.add_postcondition (parse_expression ());
3059 0 : expect_terminator ();
3060 : }
3061 : }
3062 : }
3063 :
3064 13 : rollback (body_location);
3065 :
3066 :
3067 25 : if (accept_block ()) {
3068 12 : method.body = parse_block ();
3069 12 : method.external = false;
3070 : }
3071 13 : return method;
3072 : }
3073 :
3074 5 : Property parse_property_declaration (List<Attribute>? attrs) throws ParseError {
3075 5 : var begin = get_location ();
3076 5 : var readonly = false;
3077 :
3078 5 : expect (TokenType.PROP);
3079 :
3080 5 : var flags = parse_member_declaration_modifiers ();
3081 :
3082 5 : readonly = accept (TokenType.READONLY);
3083 :
3084 5 : string id = parse_identifier ();
3085 5 : expect (TokenType.COLON);
3086 :
3087 5 : var type = parse_type (true, true);
3088 :
3089 5 : var prop = new Property (id, type, null, null, get_src (begin), comment);
3090 5 : if (ModifierFlags.PRIVATE in flags) {
3091 0 : prop.access = SymbolAccessibility.PRIVATE;
3092 5 : } else if (ModifierFlags.PROTECTED in flags) {
3093 0 : prop.access = SymbolAccessibility.PROTECTED;
3094 : } else {
3095 5 : prop.access = get_default_accessibility (id);
3096 : }
3097 :
3098 5 : set_attributes (prop, attrs);
3099 :
3100 5 : if (ModifierFlags.STATIC in flags) {
3101 0 : prop.binding = MemberBinding.STATIC;
3102 5 : } else if (ModifierFlags.CLASS in flags) {
3103 0 : prop.binding = MemberBinding.CLASS;
3104 : }
3105 5 : if (ModifierFlags.ABSTRACT in flags) {
3106 0 : prop.is_abstract = true;
3107 : }
3108 5 : if (ModifierFlags.VIRTUAL in flags) {
3109 0 : prop.is_virtual = true;
3110 : }
3111 5 : if (ModifierFlags.OVERRIDE in flags) {
3112 0 : prop.overrides = true;
3113 : }
3114 :
3115 5 : if (ModifierFlags.NEW in flags) {
3116 0 : prop.hides = true;
3117 : }
3118 5 : if (ModifierFlags.EXTERN in flags) {
3119 0 : prop.is_extern = true;
3120 : }
3121 :
3122 5 : if (ModifierFlags.ASYNC in flags) {
3123 0 : Report.error (prop.source_reference, "async properties are not supported yet");
3124 : }
3125 :
3126 7 : if (accept (TokenType.ASSIGN)) {
3127 2 : prop.initializer = parse_expression ();
3128 : }
3129 :
3130 :
3131 8 : if (accept_block ()) {
3132 2 : expect (TokenType.INDENT);
3133 5 : while (current () != TokenType.DEDENT) {
3134 3 : var accessor_begin = get_location ();
3135 3 : var attribs = parse_attributes ();
3136 :
3137 3 : var value_type = type.copy ();
3138 3 : value_type.value_owned = accept (TokenType.OWNED);
3139 :
3140 6 : if (accept (TokenType.GET)) {
3141 2 : if (prop.get_accessor != null) {
3142 0 : throw new ParseError.SYNTAX ("property get accessor already defined");
3143 : }
3144 2 : Block block = null;
3145 2 : if (accept_block ()) {
3146 1 : block = parse_block ();
3147 1 : prop.external = false;
3148 : } else {
3149 1 : accept (TokenType.EOL);
3150 : }
3151 2 : prop.get_accessor = new PropertyAccessor (true, false, false, value_type, block, get_src (accessor_begin));
3152 2 : set_attributes (prop.get_accessor, attribs);
3153 2 : prop.get_accessor.access = SymbolAccessibility.PUBLIC;
3154 : } else {
3155 1 : bool _construct = false;
3156 1 : if (accept (TokenType.SET)) {
3157 1 : if (readonly) {
3158 0 : throw new ParseError.SYNTAX ("set block not allowed for a read only property");
3159 : }
3160 1 : _construct = (context.profile == Profile.GOBJECT) && accept (TokenType.CONSTRUCT);
3161 0 : } else if (context.profile == Profile.GOBJECT && accept (TokenType.CONSTRUCT)) {
3162 : _construct = true;
3163 0 : } else if (!accept (TokenType.EOL)) {
3164 0 : throw new ParseError.SYNTAX ("expected get, set, or construct");
3165 : }
3166 :
3167 1 : if (prop.set_accessor != null) {
3168 0 : throw new ParseError.SYNTAX ("property set accessor already defined");
3169 : }
3170 :
3171 1 : Block block = null;
3172 1 : if (accept_block ()) {
3173 0 : block = parse_block ();
3174 0 : prop.external = false;
3175 : } else {
3176 1 : accept (TokenType.EOL);
3177 : }
3178 1 : prop.set_accessor = new PropertyAccessor (false, !readonly, _construct, value_type, block, get_src (accessor_begin));
3179 1 : set_attributes (prop.set_accessor, attribs);
3180 1 : prop.set_accessor.access = SymbolAccessibility.PUBLIC;
3181 : }
3182 : }
3183 2 : accept (TokenType.EOL);
3184 2 : expect (TokenType.DEDENT);
3185 : } else {
3186 3 : var value_type = type.copy ();
3187 3 : value_type.value_owned = false;
3188 :
3189 3 : prop.get_accessor = new PropertyAccessor (true, false, false, value_type, null, get_src (begin));
3190 3 : prop.get_accessor.access = SymbolAccessibility.PUBLIC;
3191 :
3192 3 : if (!readonly) {
3193 3 : value_type = type.copy ();
3194 3 : value_type.value_owned = false;
3195 :
3196 3 : prop.set_accessor = new PropertyAccessor (false, true, false, value_type, null, get_src (begin));
3197 3 : prop.set_accessor.access = SymbolAccessibility.PUBLIC;
3198 :
3199 : }
3200 :
3201 3 : expect_terminator ();
3202 : }
3203 :
3204 5 : return prop;
3205 : }
3206 :
3207 1 : Vala.Signal parse_signal_declaration (List<Attribute>? attrs) throws ParseError {
3208 1 : var begin = get_location ();
3209 : DataType type;
3210 :
3211 1 : expect (TokenType.EVENT);
3212 1 : var flags = parse_member_declaration_modifiers ();
3213 1 : string id = parse_identifier ();
3214 :
3215 :
3216 1 : var params = new ArrayList<Parameter> ();
3217 :
3218 1 : expect (TokenType.OPEN_PARENS);
3219 1 : if (current () != TokenType.CLOSE_PARENS) {
3220 3 : do {
3221 1 : var param = parse_parameter ();
3222 1 : params.add (param);
3223 1 : } while (accept (TokenType.COMMA));
3224 : }
3225 1 : expect (TokenType.CLOSE_PARENS);
3226 :
3227 1 : if (accept (TokenType.COLON)) {
3228 1 : type = parse_type (true, false);
3229 : } else {
3230 0 : type = new VoidType ();
3231 : }
3232 :
3233 1 : var sig = new Vala.Signal (id, type, get_src (begin), comment);
3234 1 : if (ModifierFlags.PRIVATE in flags) {
3235 0 : sig.access = SymbolAccessibility.PRIVATE;
3236 1 : } else if (ModifierFlags.PROTECTED in flags) {
3237 0 : sig.access = SymbolAccessibility.PROTECTED;
3238 : } else {
3239 1 : sig.access = get_default_accessibility (id);
3240 : }
3241 :
3242 1 : if (ModifierFlags.VIRTUAL in flags) {
3243 0 : sig.is_virtual = true;
3244 : }
3245 1 : if (ModifierFlags.NEW in flags) {
3246 0 : sig.hides = true;
3247 : }
3248 :
3249 1 : if (ModifierFlags.STATIC in flags) {
3250 0 : throw new ParseError.SYNTAX ("`static' modifier not allowed on signals");
3251 1 : } else if (ModifierFlags.CLASS in flags) {
3252 0 : throw new ParseError.SYNTAX ("`class' modifier not allowed on signals");
3253 : }
3254 :
3255 1 : set_attributes (sig, attrs);
3256 :
3257 3 : foreach (Parameter formal_param in params) {
3258 1 : sig.add_parameter (formal_param);
3259 : }
3260 :
3261 1 : if (!accept_terminator ()) {
3262 0 : sig.body = parse_block ();
3263 : }
3264 1 : return sig;
3265 : }
3266 :
3267 3 : Constructor parse_constructor_declaration (List<Attribute>? attrs) throws ParseError {
3268 3 : var begin = get_location ();
3269 :
3270 3 : expect (TokenType.INIT);
3271 3 : var flags = parse_member_declaration_modifiers ();
3272 :
3273 3 : var c = new Constructor (get_src (begin));
3274 3 : if (ModifierFlags.STATIC in flags) {
3275 1 : c.binding = MemberBinding.STATIC;
3276 2 : } else if (ModifierFlags.CLASS in flags) {
3277 1 : c.binding = MemberBinding.CLASS;
3278 : }
3279 :
3280 3 : accept_block ();
3281 3 : c.body = parse_block ();
3282 3 : return c;
3283 : }
3284 :
3285 1 : Destructor parse_destructor_declaration (List<Attribute>? attrs) throws ParseError {
3286 1 : var begin = get_location ();
3287 1 : expect (TokenType.FINAL);
3288 1 : var d = new Destructor (get_src (begin));
3289 1 : accept_block ();
3290 1 : d.body = parse_block ();
3291 1 : return d;
3292 : }
3293 :
3294 2 : Symbol parse_struct_declaration (List<Attribute>? attrs) throws ParseError {
3295 2 : var begin = get_location ();
3296 :
3297 2 : expect (TokenType.STRUCT);
3298 2 : var flags = parse_type_declaration_modifiers ();
3299 2 : var sym = parse_symbol_name ();
3300 2 : var type_param_list = parse_type_parameter_list ();
3301 2 : DataType base_type = null;
3302 2 : if (accept (TokenType.COLON)) {
3303 0 : base_type = parse_type (true, false);
3304 : }
3305 :
3306 2 : var st = new Struct (sym.name, get_src (begin), comment);
3307 2 : if (ModifierFlags.PRIVATE in flags) {
3308 0 : st.access = SymbolAccessibility.PRIVATE;
3309 2 : } else if (ModifierFlags.PROTECTED in flags) {
3310 0 : st.access = SymbolAccessibility.PROTECTED;
3311 : } else {
3312 2 : st.access = get_default_accessibility (sym.name);
3313 : }
3314 2 : set_attributes (st, attrs);
3315 2 : foreach (TypeParameter type_param in type_param_list) {
3316 0 : st.add_type_parameter (type_param);
3317 : }
3318 2 : if (base_type != null) {
3319 0 : st.base_type = base_type;
3320 : }
3321 :
3322 2 : expect (TokenType.EOL);
3323 :
3324 4 : class_name = st.name;
3325 :
3326 2 : parse_declarations (st);
3327 :
3328 2 : Symbol result = st;
3329 2 : while (sym.inner != null) {
3330 0 : sym = sym.inner;
3331 0 : var ns = new Namespace (sym.name, st.source_reference);
3332 0 : if (result is Namespace) {
3333 0 : ns.add_namespace ((Namespace) result);
3334 : } else {
3335 0 : ns.add_struct ((Struct) result);
3336 : }
3337 0 : result = ns;
3338 : }
3339 2 : return result;
3340 : }
3341 :
3342 8 : void parse_struct_member (Struct st) throws ParseError {
3343 4 : var sym = parse_declaration ();
3344 4 : if (sym is Method) {
3345 2 : st.add_method ((Method) sym);
3346 2 : } else if (sym is Field) {
3347 2 : st.add_field ((Field) sym);
3348 0 : } else if (sym is Constant) {
3349 0 : st.add_constant ((Constant) sym);
3350 0 : } else if (sym is Property) {
3351 0 : st.add_property ((Property) sym);
3352 : } else {
3353 0 : Report.error (sym.source_reference, "unexpected declaration in struct");
3354 : }
3355 : }
3356 :
3357 1 : Symbol parse_interface_declaration (List<Attribute>? attrs) throws ParseError {
3358 1 : var begin = get_location ();
3359 :
3360 1 : expect (TokenType.INTERFACE);
3361 1 : var flags = parse_type_declaration_modifiers ();
3362 1 : var sym = parse_symbol_name ();
3363 1 : var type_param_list = parse_type_parameter_list ();
3364 1 : var base_types = new ArrayList<DataType> ();
3365 1 : if (accept (TokenType.COLON)) {
3366 3 : do {
3367 1 : var type = parse_type (true, false);
3368 1 : base_types.add (type);
3369 1 : } while (accept (TokenType.COMMA));
3370 : }
3371 :
3372 1 : var iface = new Interface (sym.name, get_src (begin), comment);
3373 1 : if (ModifierFlags.PRIVATE in flags) {
3374 0 : iface.access = SymbolAccessibility.PRIVATE;
3375 1 : } else if (ModifierFlags.PROTECTED in flags) {
3376 0 : iface.access = SymbolAccessibility.PROTECTED;
3377 : } else {
3378 1 : iface.access = get_default_accessibility (sym.name);
3379 : }
3380 1 : if (ModifierFlags.EXTERN in flags) {
3381 0 : iface.is_extern = true;
3382 : }
3383 1 : set_attributes (iface, attrs);
3384 1 : foreach (TypeParameter type_param in type_param_list) {
3385 0 : iface.add_type_parameter (type_param);
3386 : }
3387 3 : foreach (DataType base_type in base_types) {
3388 1 : iface.add_prerequisite (base_type);
3389 : }
3390 :
3391 :
3392 1 : expect (TokenType.EOL);
3393 :
3394 1 : parse_declarations (iface);
3395 :
3396 :
3397 1 : Symbol result = iface;
3398 1 : while (sym.inner != null) {
3399 0 : sym = sym.inner;
3400 0 : var ns = new Namespace (sym.name, iface.source_reference);
3401 0 : if (result is Namespace) {
3402 0 : ns.add_namespace ((Namespace) result);
3403 : } else {
3404 0 : ns.add_interface ((Interface) result);
3405 : }
3406 0 : result = ns;
3407 : }
3408 1 : return result;
3409 : }
3410 :
3411 2 : void parse_interface_member (Interface iface) throws ParseError {
3412 1 : var sym = parse_declaration ();
3413 1 : if (sym is Class) {
3414 0 : iface.add_class ((Class) sym);
3415 1 : } else if (sym is Struct) {
3416 0 : iface.add_struct ((Struct) sym);
3417 1 : } else if (sym is Enum) {
3418 0 : iface.add_enum ((Enum) sym);
3419 1 : } else if (sym is Delegate) {
3420 0 : iface.add_delegate ((Delegate) sym);
3421 1 : } else if (sym is Method) {
3422 1 : iface.add_method ((Method) sym);
3423 0 : } else if (sym is Vala.Signal) {
3424 0 : iface.add_signal ((Vala.Signal) sym);
3425 0 : } else if (sym is Field) {
3426 0 : iface.add_field ((Field) sym);
3427 0 : } else if (sym is Constant) {
3428 0 : iface.add_constant ((Constant) sym);
3429 0 : } else if (sym is Property) {
3430 0 : iface.add_property ((Property) sym);
3431 : } else {
3432 0 : Report.error (sym.source_reference, "unexpected declaration in interface");
3433 : }
3434 : }
3435 :
3436 2 : Symbol parse_enum_declaration (List<Attribute>? attrs) throws ParseError {
3437 2 : var begin = get_location ();
3438 2 : expect (TokenType.ENUM);
3439 2 : var flags = parse_type_declaration_modifiers ();
3440 :
3441 2 : var sym = parse_symbol_name ();
3442 2 : var en = new Enum (sym.name, get_src (begin), comment);
3443 2 : if (ModifierFlags.PRIVATE in flags) {
3444 0 : en.access = SymbolAccessibility.PRIVATE;
3445 2 : } else if (ModifierFlags.PROTECTED in flags) {
3446 0 : en.access = SymbolAccessibility.PROTECTED;
3447 : } else {
3448 2 : en.access = get_default_accessibility (sym.name);
3449 : }
3450 2 : if (ModifierFlags.EXTERN in flags) {
3451 0 : en.is_extern = true;
3452 : }
3453 2 : set_attributes (en, attrs);
3454 :
3455 2 : expect (TokenType.EOL);
3456 2 : expect (TokenType.INDENT);
3457 7 : do {
3458 7 : if (current () == TokenType.DEDENT && en.get_values ().size > 0) {
3459 : // allow trailing comma
3460 : break;
3461 : }
3462 5 : var value_attrs = parse_attributes ();
3463 5 : var value_begin = get_location ();
3464 5 : string id = parse_identifier ();
3465 5 : comment = scanner.pop_comment ();
3466 :
3467 5 : Expression value = null;
3468 5 : if (accept (TokenType.ASSIGN)) {
3469 0 : value = parse_expression ();
3470 : }
3471 :
3472 5 : var ev = new EnumValue (id, value, get_src (value_begin), comment);
3473 5 : ev.access = SymbolAccessibility.PUBLIC;
3474 5 : set_attributes (ev, value_attrs);
3475 :
3476 5 : en.add_value (ev);
3477 5 : if (expect_separator ()) {
3478 5 : accept (TokenType.EOL);
3479 : }
3480 : } while (true);
3481 :
3482 2 : expect (TokenType.DEDENT);
3483 :
3484 2 : Symbol result = en;
3485 2 : while (sym.inner != null) {
3486 0 : sym = sym.inner;
3487 0 : var ns = new Namespace (sym.name, en.source_reference);
3488 0 : if (result is Namespace) {
3489 0 : ns.add_namespace ((Namespace) result);
3490 : } else {
3491 0 : ns.add_enum ((Enum) result);
3492 : }
3493 0 : result = ns;
3494 : }
3495 2 : return result;
3496 : }
3497 :
3498 1 : Symbol parse_errordomain_declaration (List<Attribute>? attrs) throws ParseError {
3499 1 : var begin = get_location ();
3500 1 : expect (TokenType.EXCEPTION);
3501 1 : var flags = parse_type_declaration_modifiers ();
3502 :
3503 1 : var sym = parse_symbol_name ();
3504 1 : var ed = new ErrorDomain (sym.name, get_src (begin), comment);
3505 1 : if (ModifierFlags.PRIVATE in flags) {
3506 0 : ed.access = SymbolAccessibility.PRIVATE;
3507 1 : } else if (ModifierFlags.PROTECTED in flags) {
3508 0 : ed.access = SymbolAccessibility.PROTECTED;
3509 : } else {
3510 1 : ed.access = get_default_accessibility (sym.name);
3511 : }
3512 :
3513 1 : set_attributes (ed, attrs);
3514 :
3515 1 : expect (TokenType.EOL);
3516 1 : expect (TokenType.INDENT);
3517 :
3518 4 : do {
3519 4 : if (current () == TokenType.DEDENT && ed.get_codes ().size > 0) {
3520 : // allow trailing comma
3521 : break;
3522 : }
3523 3 : var code_attrs = parse_attributes ();
3524 3 : var code_begin = get_location ();
3525 3 : string id = parse_identifier ();
3526 3 : comment = scanner.pop_comment ();
3527 3 : var ec = new ErrorCode (id, get_src (code_begin), comment);
3528 3 : ec.access = SymbolAccessibility.PUBLIC;
3529 3 : set_attributes (ec, code_attrs);
3530 3 : if (accept (TokenType.ASSIGN)) {
3531 0 : ec.value = parse_expression ();
3532 : }
3533 3 : ed.add_code (ec);
3534 3 : accept (TokenType.EOL);
3535 : } while (true);
3536 :
3537 :
3538 1 : expect (TokenType.DEDENT);
3539 :
3540 1 : Symbol result = ed;
3541 1 : while (sym.inner != null) {
3542 0 : sym = sym.inner;
3543 0 : var ns = new Namespace (sym.name, ed.source_reference);
3544 :
3545 0 : if (result is Namespace) {
3546 0 : ns.add_namespace ((Namespace) result);
3547 : } else {
3548 0 : ns.add_error_domain ((ErrorDomain) result);
3549 : }
3550 0 : result = ns;
3551 : }
3552 1 : return result;
3553 : }
3554 :
3555 17 : ModifierFlags parse_type_declaration_modifiers () {
3556 : ModifierFlags flags = 0;
3557 19 : while (true) {
3558 19 : switch (current ()) {
3559 : case TokenType.ABSTRACT:
3560 2 : next ();
3561 2 : flags |= ModifierFlags.ABSTRACT;
3562 2 : break;
3563 :
3564 : case TokenType.EXTERN:
3565 0 : next ();
3566 0 : flags |= ModifierFlags.EXTERN;
3567 0 : break;
3568 :
3569 : case TokenType.STATIC:
3570 0 : next ();
3571 0 : flags |= ModifierFlags.STATIC;
3572 0 : break;
3573 :
3574 : case TokenType.PRIVATE:
3575 0 : next ();
3576 0 : flags |= ModifierFlags.PRIVATE;
3577 0 : break;
3578 :
3579 : case TokenType.PUBLIC:
3580 0 : next ();
3581 0 : flags |= ModifierFlags.PUBLIC;
3582 0 : break;
3583 :
3584 : case TokenType.PROTECTED:
3585 0 : next ();
3586 0 : flags |= ModifierFlags.PROTECTED;
3587 0 : break;
3588 :
3589 : default:
3590 : return flags;
3591 : }
3592 : }
3593 : }
3594 :
3595 40 : ModifierFlags parse_member_declaration_modifiers () {
3596 : ModifierFlags flags = 0;
3597 48 : while (true) {
3598 48 : switch (current ()) {
3599 : case TokenType.ABSTRACT:
3600 1 : next ();
3601 1 : flags |= ModifierFlags.ABSTRACT;
3602 1 : break;
3603 : case TokenType.ASYNC:
3604 1 : next ();
3605 1 : flags |= ModifierFlags.ASYNC;
3606 1 : break;
3607 : case TokenType.CLASS:
3608 2 : next ();
3609 2 : flags |= ModifierFlags.CLASS;
3610 2 : break;
3611 : case TokenType.EXTERN:
3612 0 : next ();
3613 0 : flags |= ModifierFlags.EXTERN;
3614 0 : break;
3615 : case TokenType.INLINE:
3616 0 : next ();
3617 0 : flags |= ModifierFlags.INLINE;
3618 0 : break;
3619 : case TokenType.NEW:
3620 0 : next ();
3621 0 : flags |= ModifierFlags.NEW;
3622 0 : break;
3623 : case TokenType.OVERRIDE:
3624 0 : next ();
3625 0 : flags |= ModifierFlags.OVERRIDE;
3626 0 : break;
3627 : case TokenType.SEALED:
3628 0 : next ();
3629 0 : flags |= ModifierFlags.SEALED;
3630 0 : break;
3631 : case TokenType.STATIC:
3632 2 : next ();
3633 2 : flags |= ModifierFlags.STATIC;
3634 2 : break;
3635 : case TokenType.VIRTUAL:
3636 0 : next ();
3637 0 : flags |= ModifierFlags.VIRTUAL;
3638 0 : break;
3639 : case TokenType.PRIVATE:
3640 0 : next ();
3641 0 : flags |= ModifierFlags.PRIVATE;
3642 0 : break;
3643 : case TokenType.PUBLIC:
3644 0 : next ();
3645 0 : flags |= ModifierFlags.PUBLIC;
3646 0 : break;
3647 : case TokenType.PROTECTED:
3648 2 : next ();
3649 2 : flags |= ModifierFlags.PROTECTED;
3650 2 : break;
3651 : default:
3652 : return flags;
3653 : }
3654 : }
3655 : }
3656 :
3657 9 : Parameter parse_parameter () throws ParseError {
3658 9 : var attrs = parse_attributes ();
3659 9 : var begin = get_location ();
3660 9 : if (accept (TokenType.ELLIPSIS)) {
3661 : // varargs
3662 0 : return new Parameter.with_ellipsis (get_src (begin));
3663 : }
3664 9 : bool params_array = accept (TokenType.PARAMS);
3665 9 : var direction = ParameterDirection.IN;
3666 9 : if (accept (TokenType.OUT)) {
3667 : direction = ParameterDirection.OUT;
3668 9 : } else if (accept (TokenType.REF)) {
3669 0 : direction = ParameterDirection.REF;
3670 : }
3671 :
3672 9 : string id = parse_identifier ();
3673 :
3674 9 : expect (TokenType.COLON);
3675 :
3676 : DataType type;
3677 9 : if (direction == ParameterDirection.IN) {
3678 9 : type = parse_type (false, false);
3679 0 : } else if (direction == ParameterDirection.REF) {
3680 : // ref parameters own the value by default
3681 0 : type = parse_type (true, true);
3682 : } else {
3683 : // out parameters own the value by default
3684 0 : type = parse_type (true, false);
3685 : }
3686 :
3687 9 : var param = new Parameter (id, type, get_src (begin));
3688 9 : set_attributes (param, attrs);
3689 9 : param.direction = direction;
3690 9 : param.params_array = params_array;
3691 13 : if (accept (TokenType.ASSIGN)) {
3692 4 : param.initializer = parse_expression ();
3693 : }
3694 9 : return param;
3695 : }
3696 :
3697 4 : CreationMethod parse_creation_method_declaration (List<Attribute>? attrs) throws ParseError {
3698 4 : var begin = get_location ();
3699 : CreationMethod method;
3700 :
3701 4 : expect (TokenType.CONSTRUCT);
3702 4 : var flags = parse_member_declaration_modifiers ();
3703 :
3704 4 : if (accept (TokenType.OPEN_PARENS)) {
3705 : /* create default name using class name */
3706 4 : method = new CreationMethod (class_name, null, get_src (begin), comment);
3707 : } else {
3708 0 : var sym = parse_symbol_name ();
3709 0 : if (sym.inner == null) {
3710 :
3711 0 : if (sym.name != class_name) {
3712 0 : method = new CreationMethod (class_name, sym.name, get_src (begin), comment);
3713 : } else {
3714 0 : method = new CreationMethod (sym.name, null, get_src (begin), comment);
3715 : }
3716 : } else {
3717 0 : method = new CreationMethod (sym.inner.name, sym.name, get_src (begin), comment);
3718 : }
3719 0 : expect (TokenType.OPEN_PARENS);
3720 : }
3721 :
3722 4 : if (current () != TokenType.CLOSE_PARENS) {
3723 0 : do {
3724 0 : var param = parse_parameter ();
3725 0 : method.add_parameter (param);
3726 0 : } while (accept (TokenType.COMMA));
3727 : }
3728 4 : expect (TokenType.CLOSE_PARENS);
3729 4 : if (accept (TokenType.RAISES)) {
3730 0 : do {
3731 0 : method.add_error_type (parse_type (true, false));
3732 0 : } while (accept (TokenType.COMMA));
3733 : }
3734 :
3735 4 : if (ModifierFlags.PRIVATE in flags) {
3736 0 : method.access = SymbolAccessibility.PRIVATE;
3737 4 : } else if (ModifierFlags.PROTECTED in flags) {
3738 2 : method.access = SymbolAccessibility.PROTECTED;
3739 : } else {
3740 2 : method.access = SymbolAccessibility.PUBLIC;
3741 : }
3742 :
3743 4 : set_attributes (method, attrs);
3744 :
3745 4 : if (ModifierFlags.ASYNC in flags) {
3746 1 : method.coroutine = true;
3747 : }
3748 :
3749 8 : if (accept_block ()) {
3750 4 : method.body = parse_block ();
3751 4 : method.external = false;
3752 : }
3753 :
3754 : return method;
3755 : }
3756 :
3757 1 : Symbol parse_delegate_declaration (List<Attribute>? attrs) throws ParseError {
3758 1 : var begin = get_location ();
3759 : DataType type;
3760 :
3761 1 : expect (TokenType.DELEGATE);
3762 :
3763 1 : var flags = parse_member_declaration_modifiers ();
3764 :
3765 1 : var sym = parse_symbol_name ();
3766 :
3767 1 : var type_param_list = parse_type_parameter_list ();
3768 :
3769 1 : if (ModifierFlags.NEW in flags) {
3770 0 : throw new ParseError.SYNTAX ("`new' modifier not allowed on delegates");
3771 : }
3772 :
3773 1 : var params = new ArrayList<Parameter> ();
3774 :
3775 1 : expect (TokenType.OPEN_PARENS);
3776 1 : if (current () != TokenType.CLOSE_PARENS) {
3777 0 : do {
3778 0 : var param = parse_parameter ();
3779 0 : params.add (param);
3780 0 : } while (accept (TokenType.COMMA));
3781 : }
3782 1 : expect (TokenType.CLOSE_PARENS);
3783 :
3784 1 : if (accept (TokenType.COLON)) {
3785 1 : type = parse_type (true, false);
3786 : } else {
3787 0 : type = new VoidType ();
3788 : }
3789 :
3790 1 : var d = new Delegate (sym.name, type, get_src (begin), comment);
3791 :
3792 1 : if (accept (TokenType.RAISES)) {
3793 0 : do {
3794 0 : d.add_error_type (parse_type (true, false));
3795 0 : } while (accept (TokenType.COMMA));
3796 : }
3797 :
3798 1 : expect_terminator ();
3799 :
3800 :
3801 1 : if (ModifierFlags.PRIVATE in flags) {
3802 0 : d.access = SymbolAccessibility.PRIVATE;
3803 1 : } else if (ModifierFlags.PROTECTED in flags) {
3804 0 : d.access = SymbolAccessibility.PROTECTED;
3805 : } else {
3806 1 : d.access = get_default_accessibility (sym.name);
3807 : }
3808 :
3809 1 : if (ModifierFlags.STATIC in flags) {
3810 0 : d.has_target = false;
3811 : }
3812 1 : if (ModifierFlags.EXTERN in flags) {
3813 0 : d.is_extern = true;
3814 : }
3815 :
3816 1 : set_attributes (d, attrs);
3817 :
3818 1 : foreach (TypeParameter type_param in type_param_list) {
3819 0 : d.add_type_parameter (type_param);
3820 : }
3821 :
3822 1 : foreach (Parameter formal_param in params) {
3823 0 : d.add_parameter (formal_param);
3824 : }
3825 :
3826 :
3827 :
3828 1 : Symbol result = d;
3829 1 : while (sym.inner != null) {
3830 0 : sym = sym.inner;
3831 0 : var ns = new Namespace (sym.name, d.source_reference);
3832 :
3833 0 : if (result is Namespace) {
3834 0 : ns.add_namespace ((Namespace) result);
3835 : } else {
3836 0 : ns.add_delegate ((Delegate) result);
3837 : }
3838 0 : result = ns;
3839 : }
3840 1 : return result;
3841 : }
3842 :
3843 28 : List<TypeParameter> parse_type_parameter_list () throws ParseError {
3844 28 : if (accept (TokenType.OF)) {
3845 0 : var list = new ArrayList<TypeParameter> ();
3846 0 : do {
3847 0 : var begin = get_location ();
3848 0 : string id = parse_identifier ();
3849 0 : list.add (new TypeParameter (id, get_src (begin)));
3850 0 : } while (accept (TokenType.COMMA));
3851 0 : return list;
3852 : } else {
3853 28 : if (_empty_type_parameter_list == null) {
3854 17 : _empty_type_parameter_list = new ArrayList<TypeParameter> ();
3855 : }
3856 28 : return _empty_type_parameter_list;
3857 : }
3858 : }
3859 :
3860 104 : void skip_type_argument_list () throws ParseError {
3861 104 : if (accept (TokenType.OF)) {
3862 0 : if (accept (TokenType.OPEN_PARENS)) {
3863 0 : do {
3864 0 : skip_type ();
3865 0 : } while (accept (TokenType.COMMA));
3866 0 : expect (TokenType.CLOSE_PARENS);
3867 : } else {
3868 0 : do {
3869 0 : skip_type ();
3870 0 : } while (accept (TokenType.COMMA));
3871 : }
3872 : }
3873 : }
3874 :
3875 :
3876 : // try to parse type argument list
3877 365 : List<DataType>? parse_type_argument_list (bool maybe_expression) throws ParseError {
3878 365 : var begin = get_location ();
3879 365 : if (accept (TokenType.OF)) {
3880 0 : var list = new ArrayList<DataType> ();
3881 0 : var inParens = false;
3882 :
3883 : // Optional parens allow multi arg types in function signature: "dict of (int, string)"
3884 : // See: https://bugzilla.gnome.org/show_bug.cgi?id=611191
3885 0 : if (accept (TokenType.OPEN_PARENS)) {
3886 0 : inParens = true;
3887 : }
3888 :
3889 0 : do {
3890 0 : switch (current ()) {
3891 : case TokenType.VOID:
3892 : case TokenType.DYNAMIC:
3893 : case TokenType.UNOWNED:
3894 : case TokenType.WEAK:
3895 : case TokenType.IDENTIFIER:
3896 0 : var type = parse_type (true, true);
3897 :
3898 0 : list.add (type);
3899 0 : break;
3900 : default:
3901 0 : rollback (begin);
3902 0 : return null;
3903 : }
3904 0 : } while (accept (TokenType.COMMA));
3905 :
3906 0 : if (inParens) {
3907 0 : expect (TokenType.CLOSE_PARENS);
3908 : }
3909 :
3910 0 : return list;
3911 : }
3912 365 : return null;
3913 : }
3914 :
3915 11 : MemberAccess parse_member_name (Expression? base_expr = null) throws ParseError {
3916 11 : var begin = get_location ();
3917 11 : MemberAccess expr = null;
3918 24 : do {
3919 13 : string id = parse_identifier ();
3920 13 : List<DataType> type_arg_list = parse_type_argument_list (false);
3921 13 : expr = new MemberAccess (expr != null ? expr : base_expr, id, get_src (begin));
3922 13 : if (type_arg_list != null) {
3923 0 : foreach (DataType type_arg in type_arg_list) {
3924 0 : expr.add_type_argument (type_arg);
3925 : }
3926 : }
3927 13 : } while (accept (TokenType.DOT));
3928 11 : return expr;
3929 : }
3930 : }
3931 :
|