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