LCOV - code coverage report
Current view: top level - vala - valagenieparser.vala (source / functions) Coverage Total Hit
Test: vala 0.57.0.298-a8cae1 Lines: 69.4 % 2175 1510
Test Date: 2024-04-25 11:34:36 Functions: - 0 0

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

Generated by: LCOV version 2.0-1