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