~ubuntu-branches/ubuntu/raring/vala-0.20/raring-proposed

« back to all changes in this revision

Viewing changes to vala/valagenieparser.vala

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher
  • Date: 2013-04-05 13:45:05 UTC
  • Revision ID: package-import@ubuntu.com-20130405134505-yyk3rec9904i7p8o
Tags: upstream-0.20.1
ImportĀ upstreamĀ versionĀ 0.20.1

Show diffs side-by-side

added added

removed removed

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