1
/* valagenieparser.vala
3
* Copyright (C) 2008-2012 Jamie McCracken, JĆ¼rg Billeter
4
* Based on code by JĆ¼rg Billeter
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.
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.
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
21
* Jamie McCracken jamiemcc gnome org
28
* Code visitor parsing all Genie source files.
30
public class Vala.Genie.Parser : CodeVisitor {
37
// index of current token in buffer
39
// number of tokens in buffer
46
/* hack needed to know if any part of an expression is a lambda one */
47
bool current_expr_is_lambda;
49
const int BUFFER_SIZE = 32;
51
static List<TypeParameter> _empty_type_parameter_list;
54
public TokenType type;
55
public SourceLocation begin;
56
public SourceLocation end;
75
tokens = new TokenInfo[BUFFER_SIZE];
77
current_expr_is_lambda = false;
81
* Parses all .gs source files in the specified code context and
84
* @param context a code context
86
public void parse (CodeContext context) {
87
this.context = context;
88
context.accept (this);
91
public override void visit_source_file (SourceFile source_file) {
92
if (source_file.filename.has_suffix (".gs")) {
93
parse_file (source_file);
98
index = (index + 1) % BUFFER_SIZE;
101
SourceLocation begin, end;
102
TokenType type = scanner.read_token (out begin, out end);
103
tokens[index].type = type;
104
tokens[index].begin = begin;
105
tokens[index].end = end;
108
return (tokens[index].type != TokenType.EOF);
111
inline void prev () {
112
index = (index - 1 + BUFFER_SIZE) % BUFFER_SIZE;
114
assert (size <= BUFFER_SIZE);
117
inline TokenType current () {
118
return tokens[index].type;
121
inline bool accept (TokenType type) {
122
if (current () == type) {
129
inline bool accept_terminator () {
130
if (current () == TokenType.SEMICOLON || current () == TokenType.EOL) {
137
inline bool accept_block () {
139
bool has_term = accept_terminator ();
141
if (accept (TokenType.INDENT)) {
153
string get_error (string msg) {
154
var begin = get_location ();
156
Report.error (get_src (begin), "syntax error, " + msg);
160
inline bool expect (TokenType type) throws ParseError {
165
TokenType cur = current ();
166
TokenType pre = tokens[index - 1].type;
168
throw new ParseError.SYNTAX (get_error ("expected %s but got %s with previous %s".printf (type.to_string (), cur.to_string (), pre.to_string())));
171
inline bool expect_terminator () throws ParseError {
172
if (accept_terminator ()) {
176
TokenType cur = current ();
178
throw new ParseError.SYNTAX (get_error ("expected line end or semicolon but got %s".printf (cur.to_string())));
181
inline SourceLocation get_location () {
182
return tokens[index].begin;
185
string get_current_string () {
186
return ((string) tokens[index].begin.pos).substring (0, (int) (tokens[index].end.pos - tokens[index].begin.pos));
189
string get_last_string () {
190
int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE;
191
return ((string) tokens[last_index].begin.pos).substring (0, (int) (tokens[last_index].end.pos - tokens[last_index].begin.pos));
194
SourceReference get_src (SourceLocation begin) {
195
int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE;
197
return new SourceReference (scanner.source_file, begin, tokens[last_index].end);
200
SourceReference get_current_src () {
201
return new SourceReference (scanner.source_file, tokens[index].begin, tokens[index].end);
204
void rollback (SourceLocation location) {
205
while (tokens[index].begin.pos != location.pos) {
206
index = (index - 1 + BUFFER_SIZE) % BUFFER_SIZE;
208
if (size > BUFFER_SIZE) {
209
scanner.seek (location);
218
inline SymbolAccessibility get_access (string s) {
220
return SymbolAccessibility.PRIVATE;
223
return SymbolAccessibility.PUBLIC;
226
void skip_identifier () throws ParseError {
227
// also accept keywords as identifiers where there is no conflict
228
switch (current ()) {
229
case TokenType.ABSTRACT:
231
case TokenType.ASSERT:
232
case TokenType.ASYNC:
233
case TokenType.BREAK:
234
case TokenType.CLASS:
235
case TokenType.CONST:
236
case TokenType.CONTINUE:
237
case TokenType.DEDENT:
239
case TokenType.DEFAULT:
240
case TokenType.DELEGATE:
241
case TokenType.DELETE:
243
case TokenType.DOWNTO:
244
case TokenType.DYNAMIC:
248
case TokenType.ENSURES:
249
case TokenType.ERRORDOMAIN:
250
case TokenType.EVENT:
251
case TokenType.EXCEPT:
252
case TokenType.EXTERN:
253
case TokenType.FALSE:
254
case TokenType.FINAL:
255
case TokenType.FINALLY:
258
case TokenType.IDENTIFIER:
261
case TokenType.INDENT:
263
case TokenType.INLINE:
264
case TokenType.INTERFACE:
265
case TokenType.INTERNAL:
269
case TokenType.NAMESPACE:
274
case TokenType.OVERRIDE:
275
case TokenType.OWNED:
277
case TokenType.PRINT:
278
case TokenType.PRIVATE:
280
case TokenType.RAISE:
281
case TokenType.RAISES:
283
case TokenType.REQUIRES:
284
case TokenType.RETURN:
285
case TokenType.SEALED:
287
case TokenType.SIZEOF:
288
case TokenType.STATIC:
289
case TokenType.STRUCT:
290
case TokenType.SUPER:
295
case TokenType.TYPEOF:
296
case TokenType.UNOWNED:
299
case TokenType.VIRTUAL:
301
case TokenType.VOLATILE:
304
case TokenType.WHILE:
305
case TokenType.YIELD:
308
case TokenType.INTEGER_LITERAL:
309
case TokenType.REAL_LITERAL:
310
// also accept integer and real literals
311
// as long as they contain at least one character
312
// and no decimal point
313
// for example, 2D and 3D
314
string id = get_current_string ();
315
if (id[id.length - 1].isalpha () && !("." in id)) {
321
throw new ParseError.SYNTAX (get_error ("expected identifier"));
325
string parse_identifier () throws ParseError {
327
return get_last_string ();
330
Expression parse_literal () throws ParseError {
331
var begin = get_location ();
333
switch (current ()) {
336
return new BooleanLiteral (true, get_src (begin));
337
case TokenType.FALSE:
339
return new BooleanLiteral (false, get_src (begin));
340
case TokenType.INTEGER_LITERAL:
342
return new IntegerLiteral (get_last_string (), get_src (begin));
343
case TokenType.REAL_LITERAL:
345
return new RealLiteral (get_last_string (), get_src (begin));
346
case TokenType.CHARACTER_LITERAL:
348
// FIXME validate and unescape here and just pass unichar to CharacterLiteral
349
var lit = new CharacterLiteral (get_last_string (), get_src (begin));
351
Report.error (lit.source_reference, "invalid character literal");
354
case TokenType.REGEX_LITERAL:
356
string match_part = get_last_string ();
357
SourceReference src_begin = get_src (begin);
358
expect (TokenType.CLOSE_REGEX_LITERAL);
359
string close_token = get_last_string ();
360
return new RegexLiteral ("%s/%s".printf (close_token, match_part), src_begin);
361
case TokenType.STRING_LITERAL:
363
return new StringLiteral (get_last_string (), get_src (begin));
364
case TokenType.TEMPLATE_STRING_LITERAL:
366
return new StringLiteral ("\"%s\"".printf (get_last_string ()), get_src (begin));
367
case TokenType.VERBATIM_STRING_LITERAL:
369
string raw_string = get_last_string ();
370
string escaped_string = raw_string.substring (3, raw_string.length - 6).escape ("");
371
return new StringLiteral ("\"%s\"".printf (escaped_string), get_src (begin));
374
return new NullLiteral (get_src (begin));
376
throw new ParseError.SYNTAX (get_error ("expected literal"));
380
public void parse_file (SourceFile source_file) {
381
scanner = new Scanner (source_file);
382
scanner.parse_file_comments ();
383
scanner.indent_spaces = 0;
390
var begin = get_location ();
391
/* see if there is an indent attribute */
392
if (accept (TokenType.OPEN_BRACKET)) {
393
var id = parse_identifier ();
394
if (id == "indent") {
395
expect (TokenType.ASSIGN);
396
expect (TokenType.INTEGER_LITERAL);
397
scanner.indent_spaces = int.parse (get_last_string());
398
expect (TokenType.CLOSE_BRACKET);
399
expect (TokenType.EOL);
405
parse_using_directives (context.root);
406
parse_declarations (context.root, true);
407
} catch (ParseError e) {
414
void skip_symbol_name () throws ParseError {
417
} while (accept (TokenType.DOT));
420
UnresolvedSymbol parse_symbol_name () throws ParseError {
421
var begin = get_location ();
422
UnresolvedSymbol sym = null;
424
string name = parse_identifier ();
425
sym = new UnresolvedSymbol (sym, name, get_src (begin));
426
} while (accept (TokenType.DOT));
430
void skip_type () throws ParseError {
432
accept (TokenType.DYNAMIC);
433
accept (TokenType.OWNED);
434
accept (TokenType.UNOWNED);
435
accept (TokenType.WEAK);
438
if (accept (TokenType.ARRAY) || accept (TokenType.LIST) || accept (TokenType.DICT)) {
439
accept (TokenType.OF);
442
if (accept (TokenType.VOID)) {
445
skip_type_argument_list ();
448
while (accept (TokenType.OPEN_BRACKET)) {
450
if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
453
} while (accept (TokenType.COMMA));
454
expect (TokenType.CLOSE_BRACKET);
456
accept (TokenType.OP_NEG);
457
accept (TokenType.INTERR);
458
accept (TokenType.HASH);
462
Expression parse_regex_literal () throws ParseError {
463
expect (TokenType.OPEN_REGEX_LITERAL);
465
var expr = parse_literal ();
470
DataType parse_type (bool owned_by_default, bool can_weak_ref) throws ParseError {
471
var begin = get_location ();
473
List<DataType> type_arg_list = null;
474
UnresolvedSymbol sym = null;
476
bool is_dynamic = accept (TokenType.DYNAMIC);
477
bool value_owned = owned_by_default;
479
if (owned_by_default) {
480
if (accept (TokenType.UNOWNED)) {
482
} else if (accept (TokenType.WEAK)) {
483
if (!can_weak_ref && !context.deprecated) {
484
Report.warning (get_src (begin), "deprecated syntax, use `unowned` modifier");
489
value_owned = accept (TokenType.OWNED);
493
bool is_array = false;
495
if (accept (TokenType.ARRAY)) {
496
expect (TokenType.OF);
501
bool is_list = false;
503
if (accept (TokenType.LIST)) {
504
expect (TokenType.OF);
510
bool is_dict = false;
512
if (accept (TokenType.DICT)) {
513
expect (TokenType.OF);
520
if (!is_dynamic && value_owned == owned_by_default && accept (TokenType.VOID)) {
521
type = new VoidType (get_src (begin));
525
var sym_parent = new UnresolvedSymbol (null, "Gee", get_src (begin));
526
sym = new UnresolvedSymbol (sym_parent, "ArrayList", get_src (begin));
527
} else if (is_dict) {
528
var sym_parent = new UnresolvedSymbol (null, "Gee", get_src (begin));
529
sym = new UnresolvedSymbol (sym_parent, "HashMap", get_src (begin));
531
sym = parse_symbol_name ();
534
type_arg_list = parse_type_argument_list (false);
536
type = new UnresolvedType.from_symbol (sym, get_src (begin));
537
if (type_arg_list != null) {
538
foreach (DataType type_arg in type_arg_list) {
539
type.add_type_argument (type_arg);
544
while (accept (TokenType.STAR)) {
545
type = new PointerType (type, get_src (begin));
548
if (!(type is PointerType)) {
549
type.nullable = accept (TokenType.INTERR);
554
if (!accept (TokenType.OPEN_BRACKET)) {
555
type.value_owned = true;
556
type = new ArrayType (type, 1, get_src (begin));
557
type.nullable = accept (TokenType.INTERR);
562
while (accept (TokenType.OPEN_BRACKET)) {
563
bool invalid_array = false;
567
// required for decision between expression and declaration statement
568
if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
570
// only used for parsing, reject use as real type
571
invalid_array = true;
573
} while (accept (TokenType.COMMA));
574
expect (TokenType.CLOSE_BRACKET);
576
type.value_owned = true;
577
var array_type = new ArrayType (type, array_rank, get_src (begin));
578
array_type.nullable = accept (TokenType.INTERR);
580
array_type.invalid_syntax = invalid_array;
587
if (!owned_by_default) {
588
value_owned = accept (TokenType.HASH);
591
if (type is PointerType) {
595
type.is_dynamic = is_dynamic;
596
type.value_owned = value_owned;
600
DataType? parse_inline_array_type (DataType? type) throws ParseError {
601
var begin = get_location ();
603
// inline-allocated array
604
if (type != null && accept (TokenType.OPEN_BRACKET)) {
605
int array_length = -1;
607
if (current () != TokenType.CLOSE_BRACKET) {
608
if (current () != TokenType.INTEGER_LITERAL) {
609
throw new ParseError.SYNTAX (get_error ("expected `]' or integer literal"));
612
var length_literal = (IntegerLiteral) parse_literal ();
613
array_length = int.parse (length_literal.value);
615
expect (TokenType.CLOSE_BRACKET);
617
var array_type = new ArrayType (type, 1, get_src (begin));
618
array_type.inline_allocated = true;
619
if (array_length > 0) {
620
array_type.fixed_length = true;
621
array_type.length = array_length;
623
array_type.value_owned = type.value_owned;
630
List<Expression> parse_argument_list () throws ParseError {
631
var list = new ArrayList<Expression> ();
632
if (current () != TokenType.CLOSE_PARENS) {
634
list.add (parse_argument ());
635
} while (accept (TokenType.COMMA));
640
Expression parse_argument () throws ParseError {
641
var begin = get_location ();
643
if (accept (TokenType.REF)) {
644
var inner = parse_expression ();
645
return new UnaryExpression (UnaryOperator.REF, inner, get_src (begin));
646
} else if (accept (TokenType.OUT)) {
647
var inner = parse_expression ();
648
return new UnaryExpression (UnaryOperator.OUT, inner, get_src (begin));
650
var expr = parse_expression ();
651
var ma = expr as MemberAccess;
652
if (ma != null && ma.inner == null && accept (TokenType.COLON)) {
654
expr = parse_expression ();
655
return new NamedArgument (ma.member_name, expr, get_src (begin));
663
Expression parse_primary_expression () throws ParseError {
664
var begin = get_location ();
668
switch (current ()) {
670
case TokenType.FALSE:
671
case TokenType.INTEGER_LITERAL:
672
case TokenType.REAL_LITERAL:
673
case TokenType.CHARACTER_LITERAL:
674
case TokenType.REGEX_LITERAL:
675
case TokenType.STRING_LITERAL:
676
case TokenType.TEMPLATE_STRING_LITERAL:
677
case TokenType.VERBATIM_STRING_LITERAL:
679
expr = parse_literal ();
681
case TokenType.ASSERT:
682
return parse_assert_expression ();
683
case TokenType.OPEN_BRACE:
684
expr = parse_initializer ();
686
case TokenType.OPEN_PARENS:
687
expr = parse_tuple ();
689
case TokenType.OPEN_REGEX_LITERAL:
690
expr = parse_regex_literal ();
692
case TokenType.OPEN_TEMPLATE:
693
expr = parse_template ();
696
expr = parse_this_access ();
698
case TokenType.SUPER:
699
expr = parse_base_access ();
702
expr = parse_object_or_array_creation_expression ();
704
case TokenType.PRINT:
705
return parse_print_expression ();
706
case TokenType.SIZEOF:
707
expr = parse_sizeof_expression ();
709
case TokenType.TYPEOF:
710
expr = parse_typeof_expression ();
712
case TokenType.YIELD:
713
expr = parse_yield_expression ();
716
expr = parse_simple_name ();
720
// process primary expressions that start with an inner primary expression
723
switch (current ()) {
725
expr = parse_member_access (begin, expr);
727
case TokenType.OP_PTR:
728
expr = parse_pointer_member_access (begin, expr);
730
case TokenType.OPEN_PARENS:
731
expr = parse_method_call (begin, expr);
733
case TokenType.OPEN_BRACKET:
734
expr = parse_element_access (begin, expr);
736
case TokenType.OP_INC:
737
expr = parse_post_increment_expression (begin, expr);
739
case TokenType.OP_DEC:
740
expr = parse_post_decrement_expression (begin, expr);
752
Expression parse_simple_name () throws ParseError {
753
var begin = get_location ();
754
string id = parse_identifier ();
755
List<DataType> type_arg_list = parse_type_argument_list (true);
756
var expr = new MemberAccess (null, id, get_src (begin));
757
if (type_arg_list != null) {
758
foreach (DataType type_arg in type_arg_list) {
759
expr.add_type_argument (type_arg);
765
Expression parse_template () throws ParseError {
766
var begin = get_location ();
767
var template = new Template ();
769
expect (TokenType.OPEN_TEMPLATE);
770
while (current () != TokenType.CLOSE_TEMPLATE) {
771
template.add_expression (parse_expression ());
772
expect (TokenType.COMMA);
774
expect (TokenType.CLOSE_TEMPLATE);
776
template.source_reference = get_src (begin);
780
Expression parse_tuple () throws ParseError {
781
expect (TokenType.OPEN_PARENS);
782
var expr_list = new ArrayList<Expression> ();
783
if (current () != TokenType.CLOSE_PARENS) {
785
expr_list.add (parse_expression ());
786
} while (accept (TokenType.COMMA));
788
expect (TokenType.CLOSE_PARENS);
789
if (expr_list.size != 1) {
790
var tuple = new Tuple ();
791
foreach (Expression expr in expr_list) {
792
tuple.add_expression (expr);
796
return expr_list.get (0);
799
Expression parse_member_access (SourceLocation begin, Expression inner) throws ParseError {
800
expect (TokenType.DOT);
801
string id = parse_identifier ();
802
List<DataType> type_arg_list = parse_type_argument_list (true);
803
var expr = new MemberAccess (inner, id, get_src (begin));
804
if (type_arg_list != null) {
805
foreach (DataType type_arg in type_arg_list) {
806
expr.add_type_argument (type_arg);
812
Expression parse_pointer_member_access (SourceLocation begin, Expression inner) throws ParseError {
813
expect (TokenType.OP_PTR);
814
string id = parse_identifier ();
815
List<DataType> type_arg_list = parse_type_argument_list (true);
816
var expr = new MemberAccess.pointer (inner, id, get_src (begin));
817
if (type_arg_list != null) {
818
foreach (DataType type_arg in type_arg_list) {
819
expr.add_type_argument (type_arg);
826
List<Expression> parse_print_argument_list () throws ParseError {
827
var list = new ArrayList<Expression> ();
829
var begin = get_location ();
831
if (current () != TokenType.CLOSE_PARENS) {
833
var p_expr = parse_expression ();
837
if (p_expr != null) {
840
if (p_expr is StringLiteral) {
841
var s_exp = (StringLiteral) p_expr;
842
var len = s_exp.value.length;
846
var st = s_exp.value.substring (0, len-1);
851
string s = "\"\\n\"";
852
var rhs = new StringLiteral (s, get_src (begin));
853
p_expr = new BinaryExpression (BinaryOperator.PLUS, p_expr, rhs, get_src (begin));
860
} while (accept (TokenType.COMMA));
865
Expression parse_print_expression () throws ParseError {
866
var begin = get_location ();
868
expect (TokenType.PRINT);
869
bool parens = accept (TokenType.OPEN_PARENS);
871
var expr = new MemberAccess (null, "print", get_src (begin));
873
var arg_list = parse_print_argument_list ();
876
expect (TokenType.CLOSE_PARENS);
879
var print_expr = new MethodCall (expr, get_src (begin));
881
foreach (Expression arg in arg_list) {
882
print_expr.add_argument (arg);
889
Expression parse_assert_expression () throws ParseError {
890
var begin = get_location ();
892
expect (TokenType.ASSERT);
893
bool parens = accept (TokenType.OPEN_PARENS);
895
var expr = new MemberAccess (null, "assert", get_src (begin));
897
var arg_list = parse_argument_list ();
900
expect (TokenType.CLOSE_PARENS);
903
var assert_expr = new MethodCall (expr, get_src (begin));
905
foreach (Expression arg in arg_list) {
906
assert_expr.add_argument (arg);
913
Expression parse_method_call (SourceLocation begin, Expression inner) throws ParseError {
914
expect (TokenType.OPEN_PARENS);
915
var arg_list = parse_argument_list ();
916
expect (TokenType.CLOSE_PARENS);
918
var init_list = parse_object_initializer ();
920
if (init_list.size > 0 && inner is MemberAccess) {
921
// struct creation expression
922
var member = (MemberAccess) inner;
923
member.creation_member = true;
925
var expr = new ObjectCreationExpression (member, get_src (begin));
926
expr.struct_creation = true;
927
foreach (Expression arg in arg_list) {
928
expr.add_argument (arg);
930
foreach (MemberInitializer initializer in init_list) {
931
expr.add_member_initializer (initializer);
935
var expr = new MethodCall (inner, get_src (begin));
936
foreach (Expression arg in arg_list) {
937
expr.add_argument (arg);
943
Expression parse_element_access (SourceLocation begin, Expression inner) throws ParseError {
944
expect (TokenType.OPEN_BRACKET);
945
var index_list = parse_expression_list ();
946
Expression? stop = null;
947
if (index_list.size == 1 && accept (TokenType.COLON)) {
949
stop = parse_expression ();
951
expect (TokenType.CLOSE_BRACKET);
954
var expr = new ElementAccess (inner, get_src (begin));
955
foreach (Expression index in index_list) {
956
expr.append_index (index);
960
return new SliceExpression (inner, index_list[0], stop, get_src (begin));
964
List<Expression> parse_expression_list () throws ParseError {
965
var list = new ArrayList<Expression> ();
967
list.add (parse_expression ());
968
} while (accept (TokenType.COMMA));
972
Expression parse_this_access () throws ParseError {
973
var begin = get_location ();
974
expect (TokenType.THIS);
975
return new MemberAccess (null, "this", get_src (begin));
978
Expression parse_base_access () throws ParseError {
979
var begin = get_location ();
980
expect (TokenType.SUPER);
981
return new BaseAccess (get_src (begin));
984
Expression parse_post_increment_expression (SourceLocation begin, Expression inner) throws ParseError {
985
expect (TokenType.OP_INC);
986
return new PostfixExpression (inner, true, get_src (begin));
989
Expression parse_post_decrement_expression (SourceLocation begin, Expression inner) throws ParseError {
990
expect (TokenType.OP_DEC);
991
return new PostfixExpression (inner, false, get_src (begin));
994
Expression parse_object_or_array_creation_expression () throws ParseError {
995
var begin = get_location ();
996
expect (TokenType.NEW);
998
if (accept (TokenType.ARRAY)) {
999
expect (TokenType.OF);
1000
var mtype = parse_type (true, false);
1001
var expr = parse_array_creation_expression (begin, mtype);
1005
if (accept (TokenType.LIST)) {
1006
expect (TokenType.OF);
1007
var mtype = parse_type (true, false);
1008
var expr = parse_list_creation_expression (begin, mtype);
1012
if (accept (TokenType.DICT)) {
1013
expect (TokenType.OF);
1014
var mtype1 = parse_type (true, false);
1015
expect (TokenType.COMMA);
1016
var mtype2 = parse_type (true, false);
1017
var expr = parse_dict_creation_expression (begin, mtype1, mtype2);
1022
var member = parse_member_name ();
1023
var expr = parse_object_creation_expression (begin, member);
1028
Expression parse_object_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError {
1029
member.creation_member = true;
1030
List<Expression> arg_list;
1031
if (accept (TokenType.OPEN_PARENS)) {
1032
arg_list = parse_argument_list ();
1033
expect (TokenType.CLOSE_PARENS);
1035
arg_list = new ArrayList<Expression> ();
1038
var init_list = parse_object_initializer ();
1040
var expr = new ObjectCreationExpression (member, get_src (begin));
1041
foreach (Expression arg in arg_list) {
1042
expr.add_argument (arg);
1044
foreach (MemberInitializer initializer in init_list) {
1045
expr.add_member_initializer (initializer);
1050
Expression parse_array_creation_expression (SourceLocation begin, DataType element_type) throws ParseError {
1051
bool size_specified = false;
1052
List<Expression> size_specifier_list = null;
1054
DataType etype = element_type.copy ();
1056
var has_bracket = accept (TokenType.OPEN_BRACKET);
1060
// array of arrays: new T[][42]
1062
if (size_specified) {
1063
throw new ParseError.SYNTAX (get_error ("size of inner arrays must not be specified in array creation expression"));
1066
etype = new ArrayType (etype, size_specifier_list.size, etype.source_reference);
1071
size_specifier_list = new ArrayList<Expression> ();
1073
Expression size = null;
1074
if (has_bracket && current () != TokenType.CLOSE_BRACKET && current () != TokenType.COMMA) {
1075
size = parse_expression ();
1076
size_specified = true;
1078
size_specifier_list.add (size);
1079
} while (accept (TokenType.COMMA));
1082
expect (TokenType.CLOSE_BRACKET);
1084
} while (accept (TokenType.OPEN_BRACKET));
1086
InitializerList initializer = null;
1087
if (accept (TokenType.ASSIGN)) {
1088
initializer = parse_initializer ();
1091
var expr = new ArrayCreationExpression (etype, size_specifier_list.size, initializer, get_src (begin));
1092
if (size_specified) {
1093
foreach (Expression size in size_specifier_list) {
1094
expr.append_size (size);
1101
Expression parse_list_creation_expression (SourceLocation begin, DataType element_type) throws ParseError {
1103
MemberAccess list_member = null, parent_member = null;
1105
parent_member = new MemberAccess (null, "Gee", get_src (begin));
1106
list_member = new MemberAccess (parent_member, "ArrayList", get_src (begin));
1107
list_member.add_type_argument (element_type);
1109
list_member.creation_member = true;
1111
var expr = new ObjectCreationExpression (list_member, get_src (begin));
1115
Expression parse_dict_creation_expression (SourceLocation begin, DataType key_type, DataType value_type) throws ParseError {
1117
MemberAccess dict_member = null, parent_member = null;
1119
parent_member = new MemberAccess (null, "Gee", get_src (begin));
1120
dict_member = new MemberAccess (parent_member, "HashMap", get_src (begin));
1121
dict_member.add_type_argument (key_type);
1122
dict_member.add_type_argument (value_type);
1124
dict_member.creation_member = true;
1126
var expr = new ObjectCreationExpression (dict_member, get_src (begin));
1132
List<MemberInitializer> parse_object_initializer () throws ParseError {
1133
var list = new ArrayList<MemberInitializer> ();
1134
if (accept (TokenType.OPEN_BRACE)) {
1136
list.add (parse_member_initializer ());
1137
} while (accept (TokenType.COMMA));
1138
expect (TokenType.CLOSE_BRACE);
1143
MemberInitializer parse_member_initializer () throws ParseError {
1144
var begin = get_location ();
1145
string id = parse_identifier ();
1146
expect (TokenType.ASSIGN);
1147
var expr = parse_expression ();
1149
return new MemberInitializer (id, expr, get_src (begin));
1152
Expression parse_yield_expression () throws ParseError {
1153
expect (TokenType.YIELD);
1155
var expr = parse_expression ();
1157
var call = expr as MethodCall;
1158
var object_creation = expr as ObjectCreationExpression;
1159
if (call == null && object_creation == null) {
1160
Report.error (expr.source_reference, "syntax error, expected method call");
1161
throw new ParseError.SYNTAX ("expected method call");
1165
call.is_yield_expression = true;
1166
} else if (object_creation != null) {
1167
object_creation.is_yield_expression = true;
1173
Expression parse_sizeof_expression () throws ParseError {
1174
var begin = get_location ();
1175
expect (TokenType.SIZEOF);
1176
expect (TokenType.OPEN_PARENS);
1177
var type = parse_type (true, false);
1178
expect (TokenType.CLOSE_PARENS);
1180
return new SizeofExpression (type, get_src (begin));
1183
Expression parse_typeof_expression () throws ParseError {
1184
var begin = get_location ();
1185
expect (TokenType.TYPEOF);
1186
expect (TokenType.OPEN_PARENS);
1187
var type = parse_type (true, false);
1188
expect (TokenType.CLOSE_PARENS);
1190
return new TypeofExpression (type, get_src (begin));
1193
UnaryOperator get_unary_operator (TokenType token_type) {
1194
switch (token_type) {
1195
case TokenType.PLUS: return UnaryOperator.PLUS;
1196
case TokenType.MINUS: return UnaryOperator.MINUS;
1197
case TokenType.OP_NEG: return UnaryOperator.LOGICAL_NEGATION;
1198
case TokenType.TILDE: return UnaryOperator.BITWISE_COMPLEMENT;
1199
case TokenType.OP_INC: return UnaryOperator.INCREMENT;
1200
case TokenType.OP_DEC: return UnaryOperator.DECREMENT;
1201
default: return UnaryOperator.NONE;
1205
Expression parse_unary_expression () throws ParseError {
1206
var begin = get_location ();
1207
var operator = get_unary_operator (current ());
1208
if (operator != UnaryOperator.NONE) {
1210
var op = parse_unary_expression ();
1211
return new UnaryExpression (operator, op, get_src (begin));
1213
switch (current ()) {
1214
case TokenType.HASH:
1215
if (!context.deprecated) {
1216
Report.warning (get_src (begin), "deprecated syntax, use `(owned)` cast");
1219
var op = parse_unary_expression ();
1220
return new ReferenceTransferExpression (op, get_src (begin));
1221
case TokenType.OPEN_PARENS:
1223
switch (current ()) {
1224
case TokenType.OWNED:
1227
if (accept (TokenType.CLOSE_PARENS)) {
1228
var op = parse_unary_expression ();
1229
return new ReferenceTransferExpression (op, get_src (begin));
1232
case TokenType.VOID:
1233
case TokenType.DYNAMIC:
1234
case TokenType.IDENTIFIER:
1235
case TokenType.ARRAY:
1236
case TokenType.LIST:
1237
case TokenType.DICT:
1238
var type = parse_type (true, false);
1239
if (accept (TokenType.CLOSE_PARENS)) {
1240
// check follower to decide whether to create cast expression
1241
switch (current ()) {
1242
case TokenType.OP_NEG:
1243
case TokenType.TILDE:
1244
case TokenType.OPEN_PARENS:
1245
case TokenType.TRUE:
1246
case TokenType.FALSE:
1247
case TokenType.INTEGER_LITERAL:
1248
case TokenType.REAL_LITERAL:
1249
case TokenType.CHARACTER_LITERAL:
1250
case TokenType.REGEX_LITERAL:
1251
case TokenType.STRING_LITERAL:
1252
case TokenType.TEMPLATE_STRING_LITERAL:
1253
case TokenType.VERBATIM_STRING_LITERAL:
1254
case TokenType.NULL:
1255
case TokenType.THIS:
1256
case TokenType.SUPER:
1258
case TokenType.SIZEOF:
1259
case TokenType.TYPEOF:
1260
case TokenType.IDENTIFIER:
1261
case TokenType.PARAMS:
1262
case TokenType.YIELD:
1263
var inner = parse_unary_expression ();
1264
return new CastExpression (inner, type, get_src (begin), false);
1270
case TokenType.OP_NEG:
1272
if (accept (TokenType.CLOSE_PARENS)) {
1273
// (!) non-null cast
1274
var inner = parse_unary_expression ();
1275
return new CastExpression.non_null (inner, get_src (begin));
1282
// no cast expression
1285
case TokenType.STAR:
1287
var op = parse_unary_expression ();
1288
return new PointerIndirection (op, get_src (begin));
1289
case TokenType.BITWISE_AND:
1291
var op = parse_unary_expression ();
1292
return new AddressofExpression (op, get_src (begin));
1297
var expr = parse_primary_expression ();
1301
BinaryOperator get_binary_operator (TokenType token_type) {
1302
switch (token_type) {
1303
case TokenType.STAR: return BinaryOperator.MUL;
1304
case TokenType.DIV: return BinaryOperator.DIV;
1305
case TokenType.PERCENT: return BinaryOperator.MOD;
1306
case TokenType.PLUS: return BinaryOperator.PLUS;
1307
case TokenType.MINUS: return BinaryOperator.MINUS;
1308
case TokenType.OP_LT: return BinaryOperator.LESS_THAN;
1309
case TokenType.OP_GT: return BinaryOperator.GREATER_THAN;
1310
case TokenType.OP_LE: return BinaryOperator.LESS_THAN_OR_EQUAL;
1311
case TokenType.OP_GE: return BinaryOperator.GREATER_THAN_OR_EQUAL;
1312
case TokenType.OP_EQ: return BinaryOperator.EQUALITY;
1315
if (current () == TokenType.OP_NEG) {
1317
return BinaryOperator.INEQUALITY;
1320
return BinaryOperator.EQUALITY;
1321
case TokenType.OP_NE: return BinaryOperator.INEQUALITY;
1322
default: return BinaryOperator.NONE;
1326
Expression parse_multiplicative_expression () throws ParseError {
1327
var begin = get_location ();
1328
var left = parse_unary_expression ();
1331
var operator = get_binary_operator (current ());
1333
case BinaryOperator.MUL:
1334
case BinaryOperator.DIV:
1335
case BinaryOperator.MOD:
1337
var right = parse_unary_expression ();
1338
left = new BinaryExpression (operator, left, right, get_src (begin));
1348
Expression parse_additive_expression () throws ParseError {
1349
var begin = get_location ();
1350
var left = parse_multiplicative_expression ();
1353
var operator = get_binary_operator (current ());
1355
case BinaryOperator.PLUS:
1356
case BinaryOperator.MINUS:
1358
var right = parse_multiplicative_expression ();
1359
left = new BinaryExpression (operator, left, right, get_src (begin));
1369
Expression parse_shift_expression () throws ParseError {
1370
var begin = get_location ();
1371
var left = parse_additive_expression ();
1374
switch (current ()) {
1375
case TokenType.OP_SHIFT_LEFT:
1377
var right = parse_additive_expression ();
1378
left = new BinaryExpression (BinaryOperator.SHIFT_LEFT, left, right, get_src (begin));
1380
// don't use OP_SHIFT_RIGHT to support >> for nested generics
1381
case TokenType.OP_GT:
1382
char* first_gt_pos = tokens[index].begin.pos;
1384
// only accept >> when there is no space between the two > signs
1385
if (current () == TokenType.OP_GT && tokens[index].begin.pos == first_gt_pos + 1) {
1387
var right = parse_additive_expression ();
1388
left = new BinaryExpression (BinaryOperator.SHIFT_RIGHT, left, right, get_src (begin));
1402
Expression parse_relational_expression () throws ParseError {
1403
var begin = get_location ();
1404
var left = parse_shift_expression ();
1407
var operator = get_binary_operator (current ());
1409
case BinaryOperator.LESS_THAN:
1410
case BinaryOperator.LESS_THAN_OR_EQUAL:
1411
case BinaryOperator.GREATER_THAN_OR_EQUAL:
1413
var right = parse_shift_expression ();
1414
left = new BinaryExpression (operator, left, right, get_src (begin));
1416
case BinaryOperator.GREATER_THAN:
1418
// ignore >> and >>= (two tokens due to generics)
1419
if (current () != TokenType.OP_GT && current () != TokenType.OP_GE) {
1420
var right = parse_shift_expression ();
1421
left = new BinaryExpression (operator, left, right, get_src (begin));
1428
switch (current ()) {
1431
var type = parse_type (true, false);
1432
left = new TypeCheck (left, type, get_src (begin));
1436
var type = parse_type (true, false);
1437
left = new CastExpression (left, type, get_src (begin), true);
1449
Expression parse_equality_expression () throws ParseError {
1450
var begin = get_location ();
1451
var left = parse_relational_expression ();
1454
var operator = get_binary_operator (current ());
1456
case BinaryOperator.INEQUALITY:
1457
case BinaryOperator.EQUALITY:
1458
if ((operator == BinaryOperator.INEQUALITY) && (current () == TokenType.IS)) {
1462
var right = parse_relational_expression ();
1463
left = new BinaryExpression (operator, left, right, get_src (begin));
1473
Expression parse_and_expression () throws ParseError {
1474
var begin = get_location ();
1475
var left = parse_equality_expression ();
1476
while (accept (TokenType.BITWISE_AND)) {
1477
var right = parse_equality_expression ();
1478
left = new BinaryExpression (BinaryOperator.BITWISE_AND, left, right, get_src (begin));
1483
Expression parse_exclusive_or_expression () throws ParseError {
1484
var begin = get_location ();
1485
var left = parse_and_expression ();
1486
while (accept (TokenType.CARRET)) {
1487
var right = parse_and_expression ();
1488
left = new BinaryExpression (BinaryOperator.BITWISE_XOR, left, right, get_src (begin));
1493
Expression parse_inclusive_or_expression () throws ParseError {
1494
var begin = get_location ();
1495
var left = parse_exclusive_or_expression ();
1496
while (accept (TokenType.BITWISE_OR)) {
1497
var right = parse_exclusive_or_expression ();
1498
left = new BinaryExpression (BinaryOperator.BITWISE_OR, left, right, get_src (begin));
1503
Expression parse_in_expression () throws ParseError {
1504
var begin = get_location ();
1505
var left = parse_inclusive_or_expression ();
1506
while (accept (TokenType.IN)) {
1507
var right = parse_inclusive_or_expression ();
1508
left = new BinaryExpression (BinaryOperator.IN, left, right, get_src (begin));
1513
Expression parse_conditional_and_expression () throws ParseError {
1514
var begin = get_location ();
1515
var left = parse_in_expression ();
1516
while (accept (TokenType.OP_AND)) {
1517
var right = parse_in_expression ();
1518
left = new BinaryExpression (BinaryOperator.AND, left, right, get_src (begin));
1523
Expression parse_conditional_or_expression () throws ParseError {
1524
var begin = get_location ();
1525
var left = parse_conditional_and_expression ();
1526
while (accept (TokenType.OP_OR)) {
1527
var right = parse_conditional_and_expression ();
1528
left = new BinaryExpression (BinaryOperator.OR, left, right, get_src (begin));
1533
Expression parse_conditional_expression () throws ParseError {
1534
var begin = get_location ();
1535
var condition = parse_conditional_or_expression ();
1536
if (accept (TokenType.INTERR)) {
1537
var true_expr = parse_expression ();
1538
expect (TokenType.COLON);
1539
var false_expr = parse_expression ();
1540
return new ConditionalExpression (condition, true_expr, false_expr, get_src (begin));
1546
Parameter parse_lambda_parameter () throws ParseError {
1547
var begin = get_location ();
1548
var direction = ParameterDirection.IN;
1549
if (accept (TokenType.OUT)) {
1550
direction = ParameterDirection.OUT;
1551
} else if (accept (TokenType.REF)) {
1552
direction = ParameterDirection.REF;
1555
string id = parse_identifier ();
1557
var param = new Parameter (id, null, get_src (begin));
1558
param.direction = direction;
1562
Expression parse_lambda_expression () throws ParseError {
1563
var begin = get_location ();
1564
List<Parameter> params = new ArrayList<Parameter> ();
1566
expect (TokenType.DEF);
1568
if (accept (TokenType.OPEN_PARENS)) {
1569
if (current () != TokenType.CLOSE_PARENS) {
1571
params.add (parse_lambda_parameter ());
1572
} while (accept (TokenType.COMMA));
1574
expect (TokenType.CLOSE_PARENS);
1576
params.add (parse_lambda_parameter ());
1579
LambdaExpression lambda;
1581
if (accept_block ()) {
1582
var block = parse_block ();
1583
lambda = new LambdaExpression.with_statement_body (block, get_src (begin));
1585
var expr = parse_expression ();
1586
lambda = new LambdaExpression (expr, get_src (begin));
1587
expect_terminator ();
1592
foreach (var param in params) {
1593
lambda.add_parameter (param);
1598
AssignmentOperator get_assignment_operator (TokenType token_type) {
1599
switch (token_type) {
1600
case TokenType.ASSIGN: return AssignmentOperator.SIMPLE;
1601
case TokenType.ASSIGN_ADD: return AssignmentOperator.ADD;
1602
case TokenType.ASSIGN_SUB: return AssignmentOperator.SUB;
1603
case TokenType.ASSIGN_BITWISE_OR: return AssignmentOperator.BITWISE_OR;
1604
case TokenType.ASSIGN_BITWISE_AND: return AssignmentOperator.BITWISE_AND;
1605
case TokenType.ASSIGN_BITWISE_XOR: return AssignmentOperator.BITWISE_XOR;
1606
case TokenType.ASSIGN_DIV: return AssignmentOperator.DIV;
1607
case TokenType.ASSIGN_MUL: return AssignmentOperator.MUL;
1608
case TokenType.ASSIGN_PERCENT: return AssignmentOperator.PERCENT;
1609
case TokenType.ASSIGN_SHIFT_LEFT: return AssignmentOperator.SHIFT_LEFT;
1610
default: return AssignmentOperator.NONE;
1614
Expression parse_expression () throws ParseError {
1615
if (current () == TokenType.DEF) {
1616
var lambda = parse_lambda_expression ();
1617
current_expr_is_lambda = true;
1620
current_expr_is_lambda = false;
1623
var begin = get_location ();
1624
Expression expr = parse_conditional_expression ();
1627
var operator = get_assignment_operator (current ());
1628
if (operator != AssignmentOperator.NONE) {
1630
var rhs = parse_expression ();
1631
expr = new Assignment (expr, rhs, operator, get_src (begin));
1632
} else if (current () == TokenType.OP_GT) { // >>=
1633
char* first_gt_pos = tokens[index].begin.pos;
1635
// only accept >>= when there is no space between the two > signs
1636
if (current () == TokenType.OP_GE && tokens[index].begin.pos == first_gt_pos + 1) {
1638
var rhs = parse_expression ();
1639
expr = new Assignment (expr, rhs, AssignmentOperator.SHIFT_RIGHT, get_src (begin));
1653
Statement get_for_statement_type () throws ParseError {
1655
var begin = get_location ();
1656
bool is_foreach = false;
1658
while (current () != TokenType.EOL && current () != TokenType.DO) {
1660
if (accept (TokenType.IN)) {
1669
return parse_foreach_statement ();
1671
return parse_for_statement ();
1676
void parse_statements (Block block) throws ParseError {
1677
while (current () != TokenType.DEDENT
1678
&& current () != TokenType.WHEN
1679
&& current () != TokenType.DEFAULT) {
1681
Statement stmt = null;
1682
bool is_decl = false;
1683
comment = scanner.pop_comment ();
1684
switch (current ()) {
1686
/* skip over requires and ensures as we handled them in method declaration */
1687
case TokenType.REQUIRES:
1688
case TokenType.ENSURES:
1689
var begin = get_location ();
1692
if (accept (TokenType.EOL) && accept (TokenType.INDENT)) {
1693
while (current () != TokenType.DEDENT) {
1697
expect (TokenType.DEDENT);
1699
while (current () != TokenType.EOL) {
1703
expect (TokenType.EOL);
1706
stmt = new EmptyStatement (get_src (begin));
1710
case TokenType.INDENT:
1711
stmt = parse_block ();
1713
case TokenType.SEMICOLON:
1714
case TokenType.PASS:
1715
stmt = parse_empty_statement ();
1717
case TokenType.PRINT:
1718
case TokenType.ASSERT:
1719
stmt = parse_expression_statement ();
1722
stmt = parse_if_statement ();
1724
case TokenType.CASE:
1725
stmt = parse_switch_statement ();
1727
case TokenType.WHILE:
1728
stmt = parse_while_statement ();
1731
stmt = parse_do_statement ();
1734
stmt = get_for_statement_type ();
1736
case TokenType.BREAK:
1737
stmt = parse_break_statement ();
1739
case TokenType.CONTINUE:
1740
stmt = parse_continue_statement ();
1742
case TokenType.RETURN:
1743
stmt = parse_return_statement ();
1745
case TokenType.RAISE:
1746
stmt = parse_throw_statement ();
1749
stmt = parse_try_statement ();
1751
case TokenType.LOCK:
1752
stmt = parse_lock_statement ();
1754
case TokenType.DELETE:
1755
stmt = parse_delete_statement ();
1759
parse_local_variable_declarations (block);
1761
case TokenType.YIELD:
1762
stmt = parse_yield_statement ();
1765
case TokenType.OP_INC:
1766
case TokenType.OP_DEC:
1767
case TokenType.SUPER:
1768
case TokenType.THIS:
1769
case TokenType.OPEN_PARENS:
1770
case TokenType.STAR:
1772
stmt = parse_expression_statement ();
1775
bool is_expr = is_expression ();
1777
stmt = parse_expression_statement ();
1780
parse_local_variable_declarations (block);
1786
block.add_statement (stmt);
1788
} catch (ParseError e) {
1789
if (recover () != RecoveryState.STATEMENT_BEGIN) {
1790
// beginning of next declaration or end of file reached
1791
// return what we have so far
1798
bool is_expression () throws ParseError {
1799
var begin = get_location ();
1801
// decide between declaration and expression statement
1803
switch (current ()) {
1804
// invocation expression
1805
case TokenType.OPEN_PARENS:
1806
// postfix increment
1807
case TokenType.OP_INC:
1808
// postfix decrement
1809
case TokenType.OP_DEC:
1811
case TokenType.ASSIGN:
1812
case TokenType.ASSIGN_ADD:
1813
case TokenType.ASSIGN_BITWISE_AND:
1814
case TokenType.ASSIGN_BITWISE_OR:
1815
case TokenType.ASSIGN_BITWISE_XOR:
1816
case TokenType.ASSIGN_DIV:
1817
case TokenType.ASSIGN_MUL:
1818
case TokenType.ASSIGN_PERCENT:
1819
case TokenType.ASSIGN_SHIFT_LEFT:
1820
case TokenType.ASSIGN_SUB:
1821
case TokenType.OP_GT: // >>=
1824
// pointer member access
1825
case TokenType.OP_PTR:
1834
Block parse_embedded_statement () throws ParseError {
1835
if (current () == TokenType.INDENT) {
1836
var block = parse_block ();
1840
comment = scanner.pop_comment ();
1842
var block = new Block (get_src (get_location ()));
1843
block.add_statement (parse_embedded_statement_without_block ());
1848
Statement parse_embedded_statement_without_block () throws ParseError {
1849
switch (current ()) {
1850
case TokenType.PASS:
1851
case TokenType.SEMICOLON: return parse_empty_statement ();
1852
case TokenType.IF: return parse_if_statement ();
1853
case TokenType.CASE: return parse_switch_statement ();
1854
case TokenType.WHILE: return parse_while_statement ();
1855
case TokenType.DO: return parse_do_statement ();
1856
case TokenType.FOR: return get_for_statement_type ();
1857
case TokenType.BREAK: return parse_break_statement ();
1858
case TokenType.CONTINUE: return parse_continue_statement ();
1859
case TokenType.RETURN: return parse_return_statement ();
1860
case TokenType.YIELD: return parse_yield_statement ();
1861
case TokenType.RAISE: return parse_throw_statement ();
1862
case TokenType.TRY: return parse_try_statement ();
1863
case TokenType.LOCK: return parse_lock_statement ();
1864
case TokenType.DELETE: return parse_delete_statement ();
1866
case TokenType.CONST:
1867
throw new ParseError.SYNTAX (get_error ("embedded statement cannot be declaration "));
1868
case TokenType.OP_INC:
1869
case TokenType.OP_DEC:
1870
case TokenType.SUPER:
1871
case TokenType.THIS:
1872
case TokenType.OPEN_PARENS:
1873
case TokenType.STAR:
1875
return parse_expression_statement ();
1877
if (is_expression ()) {
1878
return parse_expression_statement ();
1880
throw new ParseError.SYNTAX (get_error ("embedded statement cannot be declaration"));
1885
Block parse_block () throws ParseError {
1886
var begin = get_location ();
1887
expect (TokenType.INDENT);
1888
var block = new Block (get_src (begin));
1889
parse_statements (block);
1890
if (!accept (TokenType.DEDENT)) {
1891
// only report error if it's not a secondary error
1892
if (context.report.get_errors () == 0) {
1893
Report.error (get_current_src (), "tab indentation is incorrect");
1897
block.source_reference.end = get_current_src ().end;
1902
Statement parse_empty_statement () throws ParseError {
1903
var begin = get_location ();
1905
accept (TokenType.PASS);
1906
accept (TokenType.SEMICOLON);
1907
expect_terminator ();
1909
return new EmptyStatement (get_src (begin));
1912
void add_local_var_variable (Block block, string id) throws ParseError {
1913
DataType type_copy = null;
1914
var local = parse_local_variable (type_copy, id);
1915
block.add_statement (new DeclarationStatement (local, local.source_reference));
1918
void parse_local_variable_declarations (Block block) throws ParseError {
1919
if (accept (TokenType.VAR)) {
1920
/* support block vars */
1921
if (accept (TokenType.EOL) && accept (TokenType.INDENT)) {
1922
while (current () != TokenType.DEDENT) {
1923
var s = parse_identifier ();
1924
add_local_var_variable (block, s);
1925
accept (TokenType.EOL);
1926
accept (TokenType.SEMICOLON);
1929
expect (TokenType.DEDENT);
1931
var s = parse_identifier ();
1932
add_local_var_variable (block, s);
1933
expect_terminator ();
1939
var id_list = new ArrayList<string> ();
1940
DataType variable_type = null;
1943
id_list.add (parse_identifier ());
1944
} while (accept (TokenType.COMMA));
1946
expect (TokenType.COLON);
1948
variable_type = parse_type (true, true);
1949
var type = parse_inline_array_type (variable_type);
1951
foreach (string id in id_list) {
1952
DataType type_copy = null;
1954
type_copy = type.copy ();
1956
var local = parse_local_variable (type_copy, id);
1957
block.add_statement (new DeclarationStatement (local, local.source_reference));
1960
expect_terminator ();
1963
LocalVariable parse_local_variable (DataType? variable_type, string id) throws ParseError {
1964
var begin = get_location ();
1965
Expression initializer = null;
1966
if (accept (TokenType.ASSIGN)) {
1967
initializer = parse_expression ();
1969
return new LocalVariable (variable_type, id, initializer, get_src (begin));
1972
Statement parse_expression_statement () throws ParseError {
1973
var begin = get_location ();
1974
var expr = parse_statement_expression ();
1976
if (current_expr_is_lambda) {
1977
current_expr_is_lambda = false;
1979
expect_terminator ();
1982
return new ExpressionStatement (expr, get_src (begin));
1985
Expression parse_statement_expression () throws ParseError {
1986
// invocation expression, assignment,
1987
// or pre/post increment/decrement expression
1988
var expr = parse_expression ();
1992
Statement parse_if_statement () throws ParseError {
1993
var begin = get_location ();
1995
expect (TokenType.IF);
1997
var condition = parse_expression ();
1999
if (!accept (TokenType.DO)) {
2000
expect (TokenType.EOL);
2002
accept (TokenType.EOL);
2005
var src = get_src (begin);
2006
var true_stmt = parse_embedded_statement ();
2007
Block false_stmt = null;
2008
if (accept (TokenType.ELSE)) {
2009
// allow `else if' on the same line without `do'
2010
if (!accept (TokenType.DO) && current () != TokenType.IF) {
2011
expect (TokenType.EOL);
2013
accept (TokenType.EOL);
2016
false_stmt = parse_embedded_statement ();
2018
return new IfStatement (condition, true_stmt, false_stmt, src);
2021
Statement parse_switch_statement () throws ParseError {
2022
var begin = get_location ();
2023
expect (TokenType.CASE);
2024
var condition = parse_expression ();
2026
expect (TokenType.EOL);
2028
var stmt = new SwitchStatement (condition, get_src (begin));
2029
expect (TokenType.INDENT);
2030
while (current () != TokenType.DEDENT) {
2031
var section = new SwitchSection (get_src (begin));
2033
if (accept (TokenType.WHEN)) {
2035
section.add_label (new SwitchLabel (parse_expression (), get_src (begin)));
2037
while (accept (TokenType.COMMA));
2039
expect (TokenType.DEFAULT);
2040
section.add_label (new SwitchLabel.with_default (get_src (begin)));
2043
if (!accept (TokenType.EOL)) {
2044
expect (TokenType.DO);
2047
parse_statements (section);
2049
/* add break statement for each block */
2050
var break_stmt = new BreakStatement (get_src (begin));
2051
section.add_statement (break_stmt);
2053
stmt.add_section (section);
2055
expect (TokenType.DEDENT);
2059
Statement parse_while_statement () throws ParseError {
2060
var begin = get_location ();
2061
expect (TokenType.WHILE);
2062
var condition = parse_expression ();
2064
if (!accept (TokenType.DO)) {
2065
expect (TokenType.EOL);
2067
accept (TokenType.EOL);
2070
var body = parse_embedded_statement ();
2071
return new WhileStatement (condition, body, get_src (begin));
2074
Statement parse_do_statement () throws ParseError {
2075
var begin = get_location ();
2076
expect (TokenType.DO);
2077
expect (TokenType.EOL);
2078
var body = parse_embedded_statement ();
2079
expect (TokenType.WHILE);
2081
var condition = parse_expression ();
2083
expect_terminator ();
2085
return new DoStatement (body, condition, get_src (begin));
2089
Statement parse_for_statement () throws ParseError {
2090
var begin = get_location ();
2092
Expression initializer = null;
2093
Expression condition = null;
2094
Expression iterator = null;
2098
expect (TokenType.FOR);
2100
switch (current ()) {
2106
bool local_is_expr = is_expression ();
2107
is_expr = local_is_expr;
2112
var expr_begin = get_location ();
2113
id = parse_identifier ();
2114
rollback (expr_begin);
2115
initializer = parse_statement_expression ();
2117
block = new Block (get_src (begin));
2118
DataType variable_type;
2119
if (accept (TokenType.VAR)) {
2120
variable_type = null;
2121
id = parse_identifier ();
2123
id = parse_identifier ();
2124
expect (TokenType.COLON);
2125
variable_type = parse_type (true, true);
2128
DataType type_copy = null;
2129
if (variable_type != null) {
2130
type_copy = variable_type.copy ();
2132
var local = parse_local_variable (type_copy, id);
2134
block.add_statement (new DeclarationStatement (local, local.source_reference));
2139
if (accept (TokenType.TO)) {
2140
/* create expression for condition and incrementing iterator */
2141
var to_begin = get_location ();
2142
var to_src = get_src (to_begin);
2143
var left = new MemberAccess (null, id, to_src);
2144
var right = parse_primary_expression ();
2146
condition = new BinaryExpression (BinaryOperator.LESS_THAN_OR_EQUAL, left, right, to_src);
2148
iterator = new PostfixExpression (left, true, to_src);
2150
expect (TokenType.DOWNTO);
2151
var downto_begin = get_location ();
2152
var downto_src = get_src (downto_begin);
2153
/* create expression for condition and decrementing iterator */
2154
var left = new MemberAccess (null, id, downto_src);
2155
var right = parse_primary_expression ();
2157
condition = new BinaryExpression (BinaryOperator.GREATER_THAN_OR_EQUAL, left, right, downto_src);
2159
iterator = new PostfixExpression (left, false, downto_src);
2162
if (!accept (TokenType.EOL)) {
2163
expect (TokenType.DO);
2166
var src = get_src (begin);
2167
var body = parse_embedded_statement ();
2168
var stmt = new ForStatement (condition, body, src);
2170
if (initializer != null) stmt.add_initializer (initializer);
2172
stmt.add_iterator (iterator);
2175
if (block != null) {
2176
block.add_statement (stmt);
2183
Statement parse_foreach_statement () throws ParseError {
2184
var begin = get_location ();
2185
DataType type = null;
2188
expect (TokenType.FOR);
2190
if (accept (TokenType.VAR)) {
2191
id = parse_identifier ();
2193
id = parse_identifier ();
2194
if (accept (TokenType.COLON)) {
2195
type = parse_type (true, true);
2199
expect (TokenType.IN);
2200
var collection = parse_expression ();
2201
if (!accept (TokenType.EOL)) {
2202
expect (TokenType.DO);
2204
var src = get_src (begin);
2205
var body = parse_embedded_statement ();
2206
return new ForeachStatement (type, id, collection, body, src);
2209
Statement parse_break_statement () throws ParseError {
2210
var begin = get_location ();
2211
expect (TokenType.BREAK);
2212
expect_terminator ();
2213
return new BreakStatement (get_src (begin));
2216
Statement parse_continue_statement () throws ParseError {
2217
var begin = get_location ();
2218
expect (TokenType.CONTINUE);
2219
expect_terminator ();
2220
return new ContinueStatement (get_src (begin));
2223
Statement parse_return_statement () throws ParseError {
2224
var begin = get_location ();
2225
expect (TokenType.RETURN);
2226
Expression expr = null;
2227
if (current () != TokenType.SEMICOLON && current () != TokenType.EOL) {
2228
expr = parse_expression ();
2230
expect_terminator ();
2231
return new ReturnStatement (expr, get_src (begin));
2234
Statement parse_yield_statement () throws ParseError {
2235
var begin = get_location ();
2236
expect (TokenType.YIELD);
2237
if (current () != TokenType.SEMICOLON && current () != TokenType.EOL && current () != TokenType.RETURN) {
2239
return parse_expression_statement ();
2241
Expression expr = null;
2242
if (accept (TokenType.RETURN)) {
2243
expr = parse_expression ();
2245
expect_terminator ();
2246
return new YieldStatement (expr, get_src (begin));
2249
Statement parse_throw_statement () throws ParseError {
2250
var begin = get_location ();
2251
expect (TokenType.RAISE);
2252
var expr = parse_expression ();
2253
expect_terminator ();
2254
return new ThrowStatement (expr, get_src (begin));
2257
Statement parse_try_statement () throws ParseError {
2258
var begin = get_location ();
2259
expect (TokenType.TRY);
2260
expect (TokenType.EOL);
2261
var try_block = parse_block ();
2262
Block finally_clause = null;
2263
var catch_clauses = new ArrayList<CatchClause> ();
2264
if (current () == TokenType.EXCEPT) {
2265
parse_catch_clauses (catch_clauses);
2266
if (current () == TokenType.FINALLY) {
2267
finally_clause = parse_finally_clause ();
2270
finally_clause = parse_finally_clause ();
2272
var stmt = new TryStatement (try_block, finally_clause, get_src (begin));
2273
foreach (CatchClause clause in catch_clauses) {
2274
stmt.add_catch_clause (clause);
2279
void parse_catch_clauses (List<CatchClause> catch_clauses) throws ParseError {
2280
while (accept (TokenType.EXCEPT)) {
2281
var begin = get_location ();
2282
DataType type = null;
2284
if (!accept (TokenType.EOL)) {
2285
id = parse_identifier ();
2286
expect (TokenType.COLON);
2287
type = parse_type (true, true);
2288
expect (TokenType.EOL);
2291
var block = parse_block ();
2292
catch_clauses.add (new CatchClause (type, id, block, get_src (begin)));
2296
Block parse_finally_clause () throws ParseError {
2297
expect (TokenType.FINALLY);
2299
var block = parse_block ();
2303
Statement parse_lock_statement () throws ParseError {
2304
var begin = get_location ();
2305
expect (TokenType.LOCK);
2306
expect (TokenType.OPEN_PARENS);
2307
var expr = parse_expression ();
2308
expect (TokenType.CLOSE_PARENS);
2309
var stmt = parse_embedded_statement ();
2310
return new LockStatement (expr, stmt, get_src (begin));
2313
Statement parse_delete_statement () throws ParseError {
2314
var begin = get_location ();
2315
expect (TokenType.DELETE);
2316
var expr = parse_expression ();
2317
expect_terminator ();
2318
return new DeleteStatement (expr, get_src (begin));
2321
string parse_attribute_value () throws ParseError {
2322
switch (current ()) {
2323
case TokenType.NULL:
2324
case TokenType.TRUE:
2325
case TokenType.FALSE:
2326
case TokenType.INTEGER_LITERAL:
2327
case TokenType.REAL_LITERAL:
2328
case TokenType.STRING_LITERAL:
2330
return get_last_string ();
2331
case TokenType.MINUS:
2333
switch (current ()) {
2334
case TokenType.INTEGER_LITERAL:
2335
case TokenType.REAL_LITERAL:
2337
return "-" + get_last_string ();
2339
throw new ParseError.SYNTAX (get_error ("expected number"));
2342
throw new ParseError.SYNTAX (get_error ("expected literal"));
2346
List<Attribute>? parse_attributes (bool parameter) throws ParseError {
2347
if (current () != TokenType.OPEN_BRACKET) {
2350
var attrs = new ArrayList<Attribute> ();
2351
while (accept (TokenType.OPEN_BRACKET)) {
2353
var begin = get_location ();
2354
string id = parse_identifier ();
2355
var attr = new Attribute (id, get_src (begin));
2356
if (accept (TokenType.OPEN_PARENS)) {
2357
if (current () != TokenType.CLOSE_PARENS) {
2359
id = parse_identifier ();
2360
expect (TokenType.ASSIGN);
2361
attr.add_argument (id, parse_attribute_value ());
2362
} while (accept (TokenType.COMMA));
2364
expect (TokenType.CLOSE_PARENS);
2367
} while (accept (TokenType.COMMA));
2368
expect (TokenType.CLOSE_BRACKET);
2371
expect (TokenType.EOL);
2375
void set_attributes (CodeNode node, List<Attribute>? attributes) {
2376
if (attributes != null) {
2377
foreach (Attribute attr in (List<Attribute>) attributes) {
2378
if (node.get_attribute (attr.name) != null) {
2379
Report.error (attr.source_reference, "duplicate attribute `%s`".printf (attr.name));
2381
node.attributes.append (attr);
2386
Symbol parse_declaration (bool is_root = false) throws ParseError {
2387
comment = scanner.pop_comment ();
2388
var attrs = parse_attributes (false);
2389
var begin = get_location ();
2391
switch (current ()) {
2392
case TokenType.CONST:
2393
return parse_constant_declaration (attrs);
2394
case TokenType.CONSTRUCT:
2395
return parse_creation_method_declaration (attrs);
2396
case TokenType.CLASS:
2397
return parse_class_declaration (attrs);
2398
case TokenType.INIT:
2400
return parse_main_method_declaration (attrs);
2403
return parse_constructor_declaration (attrs);
2404
case TokenType.DELEGATE:
2405
return parse_delegate_declaration (attrs);
2407
return parse_method_declaration (attrs);
2408
case TokenType.ENUM:
2409
return parse_enum_declaration (attrs);
2410
case TokenType.ERRORDOMAIN:
2411
return parse_errordomain_declaration (attrs);
2412
case TokenType.FINAL:
2413
return parse_destructor_declaration (attrs);
2414
case TokenType.INTERFACE:
2415
return parse_interface_declaration (attrs);
2416
case TokenType.NAMESPACE:
2417
return parse_namespace_declaration (attrs);
2418
case TokenType.PROP:
2419
return parse_property_declaration (attrs);
2420
case TokenType.EVENT:
2421
return parse_signal_declaration (attrs);
2422
case TokenType.STRUCT:
2423
return parse_struct_declaration (attrs);
2426
while (current () != TokenType.EOL && current () != TokenType.SEMICOLON && current () != TokenType.EOF) {
2427
if (current () == TokenType.COLON) {
2429
return parse_field_declaration (attrs);
2439
TokenType cur = current ();
2440
TokenType pre = tokens[index-1].type;
2442
throw new ParseError.SYNTAX (get_error ("expected declaration but got %s with previous %s".printf (cur.to_string (), pre.to_string())));
2445
void parse_declarations (Symbol parent, bool root = false) throws ParseError {
2447
expect (TokenType.INDENT);
2449
while (current () != TokenType.DEDENT && current () != TokenType.EOF) {
2451
if (parent is Namespace) {
2452
parse_namespace_member ((Namespace) parent);
2453
} else if (parent is Class) {
2454
parse_class_member ((Class) parent);
2455
} else if (parent is Struct) {
2456
parse_struct_member ((Struct) parent);
2457
} else if (parent is Interface) {
2458
parse_interface_member ((Interface) parent);
2460
} catch (ParseError e) {
2464
if (r == RecoveryState.STATEMENT_BEGIN) {
2470
if (r == RecoveryState.EOF) {
2476
if (!accept (TokenType.DEDENT)) {
2477
// only report error if it's not a secondary error
2478
if (context.report.get_errors () == 0) {
2479
Report.error (get_current_src (), "expected dedent");
2485
enum RecoveryState {
2491
RecoveryState recover () {
2492
while (current () != TokenType.EOF) {
2493
switch (current ()) {
2494
case TokenType.CLASS:
2495
case TokenType.CONST:
2496
case TokenType.CONSTRUCT:
2497
case TokenType.INIT:
2499
case TokenType.DELEGATE:
2500
case TokenType.ENUM:
2501
case TokenType.ERRORDOMAIN:
2502
case TokenType.FINAL:
2503
case TokenType.INTERFACE:
2504
case TokenType.NAMESPACE:
2505
case TokenType.PROP:
2506
case TokenType.EVENT:
2507
case TokenType.STRUCT:
2508
return RecoveryState.DECLARATION_BEGIN;
2509
case TokenType.BREAK:
2510
case TokenType.CASE:
2511
case TokenType.CONTINUE:
2512
case TokenType.DELETE:
2516
case TokenType.LOCK:
2517
case TokenType.RETURN:
2518
case TokenType.RAISE:
2521
case TokenType.WHILE:
2522
case TokenType.YIELD:
2523
return RecoveryState.STATEMENT_BEGIN;
2529
return RecoveryState.EOF;
2532
Namespace parse_namespace_declaration (List<Attribute>? attrs) throws ParseError {
2533
var begin = get_location ();
2534
expect (TokenType.NAMESPACE);
2535
var sym = parse_symbol_name ();
2536
var ns = new Namespace (sym.name, get_src (begin));
2537
if (comment != null) {
2538
ns.add_comment (comment);
2541
set_attributes (ns, attrs);
2542
expect (TokenType.EOL);
2543
parse_declarations (ns);
2545
Namespace result = ns;
2546
while (sym.inner != null) {
2548
ns = new Namespace (sym.name, result.source_reference);
2549
ns.add_namespace ((Namespace) result);
2555
void parse_namespace_member (Namespace ns) throws ParseError {
2557
var sym = parse_declaration ((ns == context.root));
2558
if (sym is Namespace) {
2559
ns.add_namespace ((Namespace) sym);
2560
} else if (sym is Class) {
2561
ns.add_class ((Class) sym);
2562
} else if (sym is Interface) {
2563
ns.add_interface ((Interface) sym);
2564
} else if (sym is Struct) {
2565
ns.add_struct ((Struct) sym);
2566
} else if (sym is Enum) {
2567
ns.add_enum ((Enum) sym);
2568
} else if (sym is ErrorDomain) {
2569
ns.add_error_domain ((ErrorDomain) sym);
2570
} else if (sym is Delegate) {
2571
ns.add_delegate ((Delegate) sym);
2572
} else if (sym is Method) {
2573
var method = (Method) sym;
2574
if (method.binding == MemberBinding.INSTANCE) {
2575
method.binding = MemberBinding.STATIC;
2577
ns.add_method (method);
2578
} else if (sym is Field) {
2579
var field = (Field) sym;
2580
if (field.binding == MemberBinding.INSTANCE) {
2581
field.binding = MemberBinding.STATIC;
2583
ns.add_field (field);
2584
} else if (sym is Constant) {
2585
ns.add_constant ((Constant) sym);
2587
Report.error (sym.source_reference, "unexpected declaration in namespace");
2592
void add_uses_clause (Namespace ns) throws ParseError {
2593
var begin = get_location ();
2594
var sym = parse_symbol_name ();
2595
var ns_ref = new UsingDirective (sym, get_src (begin));
2597
scanner.source_file.add_using_directive (ns_ref);
2598
ns.add_using_directive (ns_ref);
2601
void parse_using_directives (Namespace ns) throws ParseError {
2602
while (accept (TokenType.USES)) {
2603
if (accept_block ()) {
2604
expect (TokenType.INDENT);
2606
while (current () != TokenType.DEDENT && current () != TokenType.EOF) {
2607
add_uses_clause (ns);
2608
expect (TokenType.EOL);
2611
expect (TokenType.DEDENT);
2614
add_uses_clause (ns);
2615
} while (accept (TokenType.COMMA));
2617
expect_terminator ();
2623
Symbol parse_class_declaration (List<Attribute>? attrs) throws ParseError {
2624
var begin = get_location ();
2625
expect (TokenType.CLASS);
2627
var flags = parse_type_declaration_modifiers ();
2629
var sym = parse_symbol_name ();
2630
var type_param_list = parse_type_parameter_list ();
2631
var base_types = new ArrayList<DataType> ();
2632
if (accept (TokenType.COLON)) {
2633
var type1 = parse_type (true, false);
2634
base_types.add (type1);
2636
if (accept (TokenType.IMPLEMENTS)) {
2638
var type2 = parse_type (true, true);
2639
base_types.add (type2);
2640
} while (accept (TokenType.COMMA));
2644
accept (TokenType.EOL);
2646
var cl = new Class (sym.name, get_src (begin), comment);
2648
if (ModifierFlags.PRIVATE in flags) {
2649
cl.access = SymbolAccessibility.PRIVATE;
2651
/* class must always be Public unless its name starts wtih underscore */
2652
if (sym.name[0] == '_') {
2653
cl.access = SymbolAccessibility.PRIVATE;
2655
cl.access = SymbolAccessibility.PUBLIC;
2659
if (ModifierFlags.ABSTRACT in flags) {
2660
cl.is_abstract = true;
2662
set_attributes (cl, attrs);
2663
foreach (TypeParameter type_param in type_param_list) {
2664
cl.add_type_parameter (type_param);
2666
foreach (DataType base_type in base_types) {
2667
cl.add_base_type (base_type);
2670
class_name = cl.name;
2672
parse_declarations (cl);
2674
// ensure there is always a default construction method
2675
if (scanner.source_file.file_type == SourceFileType.SOURCE
2676
&& cl.default_construction_method == null) {
2677
var m = new CreationMethod (cl.name, null, cl.source_reference);
2678
m.access = SymbolAccessibility.PUBLIC;
2679
m.body = new Block (cl.source_reference);
2684
while (sym.inner != null) {
2686
var ns = new Namespace (sym.name, cl.source_reference);
2687
if (result is Namespace) {
2688
ns.add_namespace ((Namespace) result);
2690
ns.add_class ((Class) result);
2697
void parse_class_member (Class cl) throws ParseError {
2698
var sym = parse_declaration ();
2700
cl.add_class ((Class) sym);
2701
} else if (sym is Struct) {
2702
cl.add_struct ((Struct) sym);
2703
} else if (sym is Enum) {
2704
cl.add_enum ((Enum) sym);
2705
} else if (sym is Delegate) {
2706
cl.add_delegate ((Delegate) sym);
2707
} else if (sym is Method) {
2708
cl.add_method ((Method) sym);
2709
} else if (sym is Vala.Signal) {
2710
cl.add_signal ((Vala.Signal) sym);
2711
} else if (sym is Field) {
2712
cl.add_field ((Field) sym);
2713
} else if (sym is Constant) {
2714
cl.add_constant ((Constant) sym);
2715
} else if (sym is Property) {
2716
cl.add_property ((Property) sym);
2717
} else if (sym is Constructor) {
2718
var c = (Constructor) sym;
2719
if (c.binding == MemberBinding.INSTANCE) {
2720
if (cl.constructor != null) {
2721
Report.error (c.source_reference, "class already contains a constructor");
2724
} else if (c.binding == MemberBinding.CLASS) {
2725
if (cl.class_constructor != null) {
2726
Report.error (c.source_reference, "class already contains a class constructor");
2728
cl.class_constructor = c;
2730
if (cl.static_constructor != null) {
2731
Report.error (c.source_reference, "class already contains a static constructor");
2733
cl.static_constructor = c;
2736
} else if (sym is Destructor) {
2737
var d = (Destructor) sym;
2738
if (d.binding == MemberBinding.STATIC) {
2739
if (cl.static_destructor != null) {
2740
Report.error (d.source_reference, "class already contains a static destructor");
2742
cl.static_destructor = (Destructor) d;
2743
} else if (d.binding == MemberBinding.CLASS) {
2744
if (cl.class_destructor != null) {
2745
Report.error (d.source_reference, "class already contains a class destructor");
2747
cl.class_destructor = (Destructor) d;
2749
if (cl.destructor != null) {
2750
Report.error (d.source_reference, "class already contains a destructor");
2752
cl.destructor = (Destructor) d;
2756
Report.error (sym.source_reference, "unexpected declaration in class");
2760
Constant parse_constant_declaration (List<Attribute>? attrs) throws ParseError {
2761
var begin = get_location ();
2763
expect (TokenType.CONST);
2765
var flags = parse_member_declaration_modifiers ();
2767
string id = parse_identifier ();
2769
expect (TokenType.COLON);
2770
var type = parse_type (false, false);
2771
type = parse_inline_array_type (type);
2773
Expression initializer = null;
2774
if (accept (TokenType.ASSIGN)) {
2775
initializer = parse_expression ();
2777
expect_terminator ();
2779
// constant arrays don't own their element
2780
var array_type = type as ArrayType;
2781
if (array_type != null) {
2782
array_type.element_type.value_owned = false;
2785
var c = new Constant (id, type, initializer, get_src (begin), comment);
2786
c.access = get_access (id);
2788
if (ModifierFlags.EXTERN in flags || scanner.source_file.file_type == SourceFileType.PACKAGE) {
2791
if (ModifierFlags.NEW in flags) {
2795
set_attributes (c, attrs);
2799
Field parse_field_declaration (List<Attribute>? attrs) throws ParseError {
2800
var begin = get_location ();
2801
string id = parse_identifier ();
2802
expect (TokenType.COLON);
2804
var flags = parse_member_declaration_modifiers ();
2806
var type = parse_type (true, true);
2808
type = parse_inline_array_type (type);
2810
var f = new Field (id, type, null, get_src (begin), comment);
2812
if (ModifierFlags.ABSTRACT in flags || ModifierFlags.VIRTUAL in flags || ModifierFlags.OVERRIDE in flags) {
2813
Report.error (f.source_reference, "abstract, virtual, and override modifiers are not applicable to fields");
2816
if (ModifierFlags.PRIVATE in flags) {
2817
f.access = SymbolAccessibility.PRIVATE;
2819
f.access = get_access (id);
2822
set_attributes (f, attrs);
2824
if (ModifierFlags.EXTERN in flags || scanner.source_file.file_type == SourceFileType.PACKAGE) {
2827
if (ModifierFlags.NEW in flags) {
2831
if (accept (TokenType.ASSIGN)) {
2832
f.initializer = parse_expression ();
2835
if (ModifierFlags.STATIC in flags) {
2836
f.binding = MemberBinding.STATIC;
2837
} else if (ModifierFlags.CLASS in flags) {
2838
f.binding = MemberBinding.CLASS;
2841
expect_terminator ();
2846
InitializerList parse_initializer () throws ParseError {
2847
var begin = get_location ();
2848
if (!accept (TokenType.OPEN_PARENS)) {
2849
expect (TokenType.OPEN_BRACE);
2851
var initializer = new InitializerList (get_src (begin));
2852
if (current () != TokenType.DEDENT) {
2854
var init = parse_argument ();
2855
initializer.append (init);
2856
} while (accept (TokenType.COMMA));
2858
if (!accept (TokenType.CLOSE_PARENS)) {
2859
expect (TokenType.CLOSE_BRACE);
2867
Method parse_main_method_declaration (List<Attribute>? attrs) throws ParseError {
2869
var begin = get_location ();
2870
DataType type = new VoidType ();
2871
expect (TokenType.INIT);
2873
var method = new Method (id, type, get_src (begin), comment);
2874
method.access = SymbolAccessibility.PUBLIC;
2876
set_attributes (method, attrs);
2878
method.binding = MemberBinding.STATIC;
2880
var sym = new UnresolvedSymbol (null, "string", get_src (begin));
2881
type = new UnresolvedType.from_symbol (sym, get_src (begin));
2882
type.value_owned = true;
2883
type = new ArrayType (type, 1, get_src (begin));
2884
type.nullable = false;
2886
var param = new Parameter ("args", type, get_src (begin));
2887
method.add_parameter (param);
2890
expect (TokenType.EOL);
2892
if (accept_block ()) {
2893
method.body = parse_block ();
2899
Method parse_method_declaration (List<Attribute>? attrs) throws ParseError {
2900
var begin = get_location ();
2901
DataType type = new VoidType ();
2902
expect (TokenType.DEF);
2903
var flags = parse_member_declaration_modifiers ();
2905
string id = parse_identifier ();
2907
var params = new ArrayList<Parameter> ();
2908
expect (TokenType.OPEN_PARENS);
2910
if (current () != TokenType.CLOSE_PARENS) {
2912
var param = parse_parameter ();
2914
} while (accept (TokenType.COMMA));
2917
expect (TokenType.CLOSE_PARENS);
2920
/* deal with return value */
2921
if (accept (TokenType.COLON)) {
2922
type = parse_type (true, false);
2925
var type_param_list = parse_type_parameter_list ();
2927
var method = new Method (id, type, get_src (begin), comment);
2928
if (ModifierFlags.PRIVATE in flags) {
2929
method.access = SymbolAccessibility.PRIVATE;
2931
method.access = get_access (id);
2935
set_attributes (method, attrs);
2937
foreach (TypeParameter type_param in type_param_list) {
2938
method.add_type_parameter (type_param);
2942
foreach (Parameter param in params) {
2943
method.add_parameter (param);
2946
if (accept (TokenType.RAISES)) {
2948
method.add_error_type (parse_type (true, false));
2949
} while (accept (TokenType.COMMA));
2953
if (ModifierFlags.STATIC in flags || id == "main") {
2954
method.binding = MemberBinding.STATIC;
2955
} else if (ModifierFlags.CLASS in flags) {
2956
method.binding = MemberBinding.CLASS;
2958
if (ModifierFlags.ASYNC in flags) {
2959
method.coroutine = true;
2962
if (ModifierFlags.NEW in flags) {
2963
method.hides = true;
2966
if (method.binding == MemberBinding.INSTANCE) {
2967
if (ModifierFlags.ABSTRACT in flags) {
2968
method.is_abstract = true;
2970
if (ModifierFlags.VIRTUAL in flags) {
2971
method.is_virtual = true;
2973
if (ModifierFlags.OVERRIDE in flags) {
2974
method.overrides = true;
2976
if ((method.is_abstract && method.is_virtual)
2977
|| (method.is_abstract && method.overrides)
2978
|| (method.is_virtual && method.overrides)) {
2979
throw new ParseError.SYNTAX (get_error ("only one of `abstract', `virtual', or `override' may be specified"));
2982
if (ModifierFlags.ABSTRACT in flags
2983
|| ModifierFlags.VIRTUAL in flags
2984
|| ModifierFlags.OVERRIDE in flags) {
2985
throw new ParseError.SYNTAX (get_error ("the modifiers `abstract', `virtual', and `override' are not valid for static methods"));
2989
if (ModifierFlags.INLINE in flags) {
2990
method.is_inline = true;
2992
if (ModifierFlags.EXTERN in flags) {
2993
method.external = true;
2996
expect (TokenType.EOL);
2998
var body_location = get_location ();
3001
/* "requires" and "ensures" if present will be at start of the method body */
3002
if (accept (TokenType.INDENT)) {
3003
if (accept (TokenType.REQUIRES)) {
3005
if (accept (TokenType.EOL) && accept (TokenType.INDENT)) {
3006
while (current() != TokenType.DEDENT) {
3007
method.add_precondition (parse_expression ());
3008
expect (TokenType.EOL);
3011
expect (TokenType.DEDENT);
3012
accept_terminator ();
3015
method.add_precondition (parse_expression ());
3016
expect_terminator ();
3022
if (accept (TokenType.ENSURES)) {
3023
if (accept (TokenType.EOL) && accept (TokenType.INDENT)) {
3024
while (current() != TokenType.DEDENT) {
3025
method.add_postcondition (parse_expression ());
3026
expect (TokenType.EOL);
3029
expect (TokenType.DEDENT);
3030
accept_terminator ();
3032
method.add_postcondition (parse_expression ());
3033
expect_terminator ();
3038
rollback (body_location);
3041
if (accept_block ()) {
3042
method.body = parse_block ();
3043
} else if (scanner.source_file.file_type == SourceFileType.PACKAGE) {
3044
method.external = true;
3049
Property parse_property_declaration (List<Attribute>? attrs) throws ParseError {
3050
var begin = get_location ();
3051
var readonly = false;
3053
expect (TokenType.PROP);
3055
var flags = parse_member_declaration_modifiers ();
3057
readonly = accept (TokenType.READONLY);
3059
string id = parse_identifier ();
3060
expect (TokenType.COLON);
3062
var type = parse_type (true, true);
3064
var prop = new Property (id, type, null, null, get_src (begin), comment);
3065
if (ModifierFlags.PRIVATE in flags) {
3066
prop.access = SymbolAccessibility.PRIVATE;
3068
prop.access = get_access (id);
3071
set_attributes (prop, attrs);
3073
if (ModifierFlags.STATIC in flags) {
3074
prop.binding = MemberBinding.STATIC;
3075
} else if (ModifierFlags.CLASS in flags) {
3076
prop.binding = MemberBinding.CLASS;
3078
if (ModifierFlags.ABSTRACT in flags) {
3079
prop.is_abstract = true;
3081
if (ModifierFlags.VIRTUAL in flags) {
3082
prop.is_virtual = true;
3084
if (ModifierFlags.OVERRIDE in flags) {
3085
prop.overrides = true;
3088
if (ModifierFlags.NEW in flags) {
3091
if (ModifierFlags.EXTERN in flags || scanner.source_file.file_type == SourceFileType.PACKAGE) {
3092
prop.external = true;
3095
if (ModifierFlags.ASYNC in flags) {
3096
Report.error (prop.source_reference, "async properties are not supported yet");
3099
if (accept (TokenType.ASSIGN)) {
3100
prop.initializer = parse_expression ();
3104
if (accept_block ()) {
3105
expect (TokenType.INDENT);
3106
while (current () != TokenType.DEDENT) {
3107
var accessor_begin = get_location ();
3108
var attribs = parse_attributes (false);
3110
var value_type = type.copy ();
3111
value_type.value_owned = accept (TokenType.OWNED);
3113
if (accept (TokenType.GET)) {
3114
if (prop.get_accessor != null) {
3115
throw new ParseError.SYNTAX (get_error ("property get accessor already defined"));
3118
if (accept_block ()) {
3119
block = parse_block ();
3120
prop.external = false;
3122
prop.get_accessor = new PropertyAccessor (true, false, false, value_type, block, get_src (accessor_begin));
3123
set_attributes (prop.get_accessor, attribs);
3124
prop.get_accessor.access = SymbolAccessibility.PUBLIC;
3126
bool _construct = false;
3127
if (accept (TokenType.SET)) {
3129
throw new ParseError.SYNTAX (get_error ("set block not allowed for a read only property"));
3131
_construct = accept (TokenType.CONSTRUCT);
3132
} else if (accept (TokenType.CONSTRUCT)) {
3134
} else if (!accept (TokenType.EOL)) {
3135
throw new ParseError.SYNTAX (get_error ("expected get, set, or construct"));
3138
if (prop.set_accessor != null) {
3139
throw new ParseError.SYNTAX (get_error ("property set accessor already defined"));
3143
if (accept_block ()) {
3144
block = parse_block ();
3145
prop.external = false;
3147
prop.set_accessor = new PropertyAccessor (false, !readonly, _construct, value_type, block, get_src (accessor_begin));
3148
set_attributes (prop.set_accessor, attribs);
3149
prop.set_accessor.access = SymbolAccessibility.PUBLIC;
3152
accept (TokenType.EOL);
3153
expect (TokenType.DEDENT);
3155
var value_type = type.copy ();
3156
value_type.value_owned = false;
3158
prop.get_accessor = new PropertyAccessor (true, false, false, value_type, null, get_src (begin));
3159
prop.get_accessor.access = SymbolAccessibility.PUBLIC;
3162
value_type = type.copy ();
3163
value_type.value_owned = false;
3165
prop.set_accessor = new PropertyAccessor (false, true, false, value_type, null, get_src (begin));
3166
prop.set_accessor.access = SymbolAccessibility.PUBLIC;
3170
expect_terminator ();
3173
if (!prop.is_abstract && scanner.source_file.file_type == SourceFileType.SOURCE) {
3174
var needs_var = (readonly && (prop.get_accessor != null && prop.get_accessor.body == null));
3177
needs_var = (prop.get_accessor != null && prop.get_accessor.body == null) || (prop.set_accessor != null && prop.set_accessor.body == null);
3181
/* automatic property accessor body generation */
3182
var variable_type = prop.property_type.copy ();
3183
prop.field = new Field ("_%s".printf (prop.name), variable_type, prop.initializer, prop.source_reference);
3184
prop.field.access = SymbolAccessibility.PRIVATE;
3185
prop.field.binding = prop.binding;
3192
Vala.Signal parse_signal_declaration (List<Attribute>? attrs) throws ParseError {
3193
var begin = get_location ();
3196
expect (TokenType.EVENT);
3197
var flags = parse_member_declaration_modifiers ();
3198
string id = parse_identifier ();
3201
var params = new ArrayList<Parameter> ();
3203
expect (TokenType.OPEN_PARENS);
3204
if (current () != TokenType.CLOSE_PARENS) {
3206
var param = parse_parameter ();
3208
} while (accept (TokenType.COMMA));
3210
expect (TokenType.CLOSE_PARENS);
3212
if (accept (TokenType.COLON)) {
3213
type = parse_type (true, false);
3215
type = new VoidType ();
3218
var sig = new Vala.Signal (id, type, get_src (begin), comment);
3219
if (ModifierFlags.PRIVATE in flags) {
3220
sig.access = SymbolAccessibility.PRIVATE;
3222
sig.access = get_access (id);
3225
if (ModifierFlags.VIRTUAL in flags) {
3226
sig.is_virtual = true;
3228
if (ModifierFlags.NEW in flags) {
3232
if (ModifierFlags.STATIC in flags) {
3233
throw new ParseError.SYNTAX (get_error ("`static' modifier not allowed on signals"));
3234
} else if (ModifierFlags.CLASS in flags) {
3235
throw new ParseError.SYNTAX (get_error ("`class' modifier not allowed on signals"));
3238
set_attributes (sig, attrs);
3240
foreach (Parameter formal_param in params) {
3241
sig.add_parameter (formal_param);
3244
if (!accept_terminator ()) {
3245
sig.body = parse_block ();
3250
Constructor parse_constructor_declaration (List<Attribute>? attrs) throws ParseError {
3251
var begin = get_location ();
3253
expect (TokenType.INIT);
3254
var flags = parse_member_declaration_modifiers ();
3256
var c = new Constructor (get_src (begin));
3257
if (ModifierFlags.STATIC in flags) {
3258
c.binding = MemberBinding.STATIC;
3259
} else if (ModifierFlags.CLASS in flags) {
3260
c.binding = MemberBinding.CLASS;
3264
c.body = parse_block ();
3268
Destructor parse_destructor_declaration (List<Attribute>? attrs) throws ParseError {
3269
var begin = get_location ();
3270
expect (TokenType.FINAL);
3271
var d = new Destructor (get_src (begin));
3273
d.body = parse_block ();
3277
Symbol parse_struct_declaration (List<Attribute>? attrs) throws ParseError {
3278
var begin = get_location ();
3280
expect (TokenType.STRUCT);
3281
var flags = parse_type_declaration_modifiers ();
3282
var sym = parse_symbol_name ();
3283
var type_param_list = parse_type_parameter_list ();
3284
DataType base_type = null;
3285
if (accept (TokenType.COLON)) {
3286
base_type = parse_type (true, false);
3289
var st = new Struct (sym.name, get_src (begin), comment);
3290
if (ModifierFlags.PRIVATE in flags) {
3291
st.access = SymbolAccessibility.PRIVATE;
3293
st.access = get_access (sym.name);
3295
set_attributes (st, attrs);
3296
foreach (TypeParameter type_param in type_param_list) {
3297
st.add_type_parameter (type_param);
3299
if (base_type != null) {
3300
st.base_type = base_type;
3303
expect (TokenType.EOL);
3305
parse_declarations (st);
3308
while (sym.inner != null) {
3310
var ns = new Namespace (sym.name, st.source_reference);
3311
if (result is Namespace) {
3312
ns.add_namespace ((Namespace) result);
3314
ns.add_struct ((Struct) result);
3321
void parse_struct_member (Struct st) throws ParseError {
3322
var sym = parse_declaration ();
3323
if (sym is Method) {
3324
st.add_method ((Method) sym);
3325
} else if (sym is Field) {
3326
st.add_field ((Field) sym);
3327
} else if (sym is Constant) {
3328
st.add_constant ((Constant) sym);
3329
} else if (sym is Property) {
3330
st.add_property ((Property) sym);
3332
Report.error (sym.source_reference, "unexpected declaration in struct");
3336
Symbol parse_interface_declaration (List<Attribute>? attrs) throws ParseError {
3337
var begin = get_location ();
3339
expect (TokenType.INTERFACE);
3340
var flags = parse_type_declaration_modifiers ();
3341
var sym = parse_symbol_name ();
3342
var type_param_list = parse_type_parameter_list ();
3343
var base_types = new ArrayList<DataType> ();
3344
if (accept (TokenType.COLON)) {
3346
var type = parse_type (true, false);
3347
base_types.add (type);
3348
} while (accept (TokenType.COMMA));
3351
var iface = new Interface (sym.name, get_src (begin), comment);
3352
if (ModifierFlags.PRIVATE in flags) {
3353
iface.access = SymbolAccessibility.PRIVATE;
3355
iface.access = get_access (sym.name);
3357
if (ModifierFlags.EXTERN in flags || scanner.source_file.file_type == SourceFileType.PACKAGE) {
3358
iface.external = true;
3360
set_attributes (iface, attrs);
3361
foreach (TypeParameter type_param in type_param_list) {
3362
iface.add_type_parameter (type_param);
3364
foreach (DataType base_type in base_types) {
3365
iface.add_prerequisite (base_type);
3369
expect (TokenType.EOL);
3371
parse_declarations (iface);
3374
Symbol result = iface;
3375
while (sym.inner != null) {
3377
var ns = new Namespace (sym.name, iface.source_reference);
3378
if (result is Namespace) {
3379
ns.add_namespace ((Namespace) result);
3381
ns.add_interface ((Interface) result);
3388
void parse_interface_member (Interface iface) throws ParseError {
3389
var sym = parse_declaration ();
3391
iface.add_class ((Class) sym);
3392
} else if (sym is Struct) {
3393
iface.add_struct ((Struct) sym);
3394
} else if (sym is Enum) {
3395
iface.add_enum ((Enum) sym);
3396
} else if (sym is Delegate) {
3397
iface.add_delegate ((Delegate) sym);
3398
} else if (sym is Method) {
3399
iface.add_method ((Method) sym);
3400
} else if (sym is Vala.Signal) {
3401
iface.add_signal ((Vala.Signal) sym);
3402
} else if (sym is Field) {
3403
iface.add_field ((Field) sym);
3404
} else if (sym is Constant) {
3405
iface.add_constant ((Constant) sym);
3406
} else if (sym is Property) {
3407
iface.add_property ((Property) sym);
3409
Report.error (sym.source_reference, "unexpected declaration in interface");
3413
Symbol parse_enum_declaration (List<Attribute>? attrs) throws ParseError {
3414
var begin = get_location ();
3415
expect (TokenType.ENUM);
3416
var flags = parse_type_declaration_modifiers ();
3418
var sym = parse_symbol_name ();
3419
var en = new Enum (sym.name, get_src (begin), comment);
3420
if (ModifierFlags.PRIVATE in flags) {
3421
en.access = SymbolAccessibility.PRIVATE;
3423
en.access = get_access (sym.name);
3425
if (ModifierFlags.EXTERN in flags || scanner.source_file.file_type == SourceFileType.PACKAGE) {
3428
set_attributes (en, attrs);
3430
expect (TokenType.EOL);
3431
expect (TokenType.INDENT);
3433
if (current () == TokenType.DEDENT && en.get_values ().size > 0) {
3434
// allow trailing comma
3437
var value_attrs = parse_attributes (false);
3438
var value_begin = get_location ();
3439
string id = parse_identifier ();
3440
comment = scanner.pop_comment ();
3442
Expression value = null;
3443
if (accept (TokenType.ASSIGN)) {
3444
value = parse_expression ();
3447
var ev = new EnumValue (id, value, get_src (value_begin), comment);
3448
ev.access = SymbolAccessibility.PUBLIC;
3449
set_attributes (ev, value_attrs);
3452
expect (TokenType.EOL);
3455
expect (TokenType.DEDENT);
3458
while (sym.inner != null) {
3460
var ns = new Namespace (sym.name, en.source_reference);
3461
if (result is Namespace) {
3462
ns.add_namespace ((Namespace) result);
3464
ns.add_enum ((Enum) result);
3471
Symbol parse_errordomain_declaration (List<Attribute>? attrs) throws ParseError {
3472
var begin = get_location ();
3473
expect (TokenType.ERRORDOMAIN);
3474
var flags = parse_type_declaration_modifiers ();
3476
var sym = parse_symbol_name ();
3477
var ed = new ErrorDomain (sym.name, get_src (begin), comment);
3478
if (ModifierFlags.PRIVATE in flags) {
3479
ed.access = SymbolAccessibility.PRIVATE;
3481
ed.access = get_access (sym.name);
3484
set_attributes (ed, attrs);
3486
expect (TokenType.EOL);
3487
expect (TokenType.INDENT);
3490
if (current () == TokenType.DEDENT && ed.get_codes ().size > 0) {
3491
// allow trailing comma
3494
var code_attrs = parse_attributes (false);
3495
var code_begin = get_location ();
3496
string id = parse_identifier ();
3497
comment = scanner.pop_comment ();
3498
var ec = new ErrorCode (id, get_src (code_begin), comment);
3499
set_attributes (ec, code_attrs);
3500
if (accept (TokenType.ASSIGN)) {
3501
ec.value = parse_expression ();
3504
accept (TokenType.EOL);
3508
expect (TokenType.DEDENT);
3511
while (sym.inner != null) {
3513
var ns = new Namespace (sym.name, ed.source_reference);
3515
if (result is Namespace) {
3516
ns.add_namespace ((Namespace) result);
3518
ns.add_error_domain ((ErrorDomain) result);
3525
ModifierFlags parse_type_declaration_modifiers () {
3526
ModifierFlags flags = 0;
3528
switch (current ()) {
3529
case TokenType.ABSTRACT:
3531
flags |= ModifierFlags.ABSTRACT;
3534
case TokenType.EXTERN:
3536
flags |= ModifierFlags.EXTERN;
3539
case TokenType.STATIC:
3541
flags |= ModifierFlags.STATIC;
3544
case TokenType.PRIVATE:
3546
flags |= ModifierFlags.PRIVATE;
3555
ModifierFlags parse_member_declaration_modifiers () {
3556
ModifierFlags flags = 0;
3558
switch (current ()) {
3559
case TokenType.ABSTRACT:
3561
flags |= ModifierFlags.ABSTRACT;
3563
case TokenType.ASYNC:
3565
flags |= ModifierFlags.ASYNC;
3567
case TokenType.CLASS:
3569
flags |= ModifierFlags.CLASS;
3571
case TokenType.EXTERN:
3573
flags |= ModifierFlags.EXTERN;
3575
case TokenType.INLINE:
3577
flags |= ModifierFlags.INLINE;
3581
flags |= ModifierFlags.NEW;
3583
case TokenType.OVERRIDE:
3585
flags |= ModifierFlags.OVERRIDE;
3587
case TokenType.SEALED:
3589
flags |= ModifierFlags.SEALED;
3591
case TokenType.STATIC:
3593
flags |= ModifierFlags.STATIC;
3595
case TokenType.VIRTUAL:
3597
flags |= ModifierFlags.VIRTUAL;
3599
case TokenType.PRIVATE:
3601
flags |= ModifierFlags.PRIVATE;
3609
Parameter parse_parameter () throws ParseError {
3610
var attrs = parse_attributes (true);
3611
var begin = get_location ();
3612
if (accept (TokenType.ELLIPSIS)) {
3614
return new Parameter.with_ellipsis (get_src (begin));
3616
bool params_array = accept (TokenType.PARAMS);
3617
var direction = ParameterDirection.IN;
3618
if (accept (TokenType.OUT)) {
3619
direction = ParameterDirection.OUT;
3620
} else if (accept (TokenType.REF)) {
3621
direction = ParameterDirection.REF;
3624
string id = parse_identifier ();
3626
expect (TokenType.COLON);
3629
if (direction == ParameterDirection.IN) {
3630
type = parse_type (false, false);
3631
} else if (direction == ParameterDirection.REF) {
3632
// ref parameters own the value by default
3633
type = parse_type (true, true);
3635
// out parameters own the value by default
3636
type = parse_type (true, false);
3639
var param = new Parameter (id, type, get_src (begin));
3640
set_attributes (param, attrs);
3641
param.direction = direction;
3642
param.params_array = params_array;
3643
if (accept (TokenType.ASSIGN)) {
3644
param.initializer = parse_expression ();
3649
CreationMethod parse_creation_method_declaration (List<Attribute>? attrs) throws ParseError {
3650
var begin = get_location ();
3651
CreationMethod method;
3653
expect (TokenType.CONSTRUCT);
3654
parse_member_declaration_modifiers ();
3656
if (accept (TokenType.OPEN_PARENS)) {
3657
/* create default name using class name */
3658
method = new CreationMethod (class_name, null, get_src (begin), comment);
3660
var sym = parse_symbol_name ();
3661
if (sym.inner == null) {
3663
if (sym.name != class_name) {
3664
method = new CreationMethod (class_name, sym.name, get_src (begin), comment);
3666
method = new CreationMethod (sym.name, null, get_src (begin), comment);
3669
method = new CreationMethod (sym.inner.name, sym.name, get_src (begin), comment);
3671
expect (TokenType.OPEN_PARENS);
3674
if (current () != TokenType.CLOSE_PARENS) {
3676
var param = parse_parameter ();
3677
method.add_parameter (param);
3678
} while (accept (TokenType.COMMA));
3680
expect (TokenType.CLOSE_PARENS);
3681
if (accept (TokenType.RAISES)) {
3683
method.add_error_type (parse_type (true, false));
3684
} while (accept (TokenType.COMMA));
3686
method.access = SymbolAccessibility.PUBLIC;
3687
set_attributes (method, attrs);
3688
method.binding = MemberBinding.STATIC;
3690
if (accept_block ()) {
3691
method.body = parse_block ();
3692
} else if (scanner.source_file.file_type == SourceFileType.PACKAGE) {
3693
method.external = true;
3699
Symbol parse_delegate_declaration (List<Attribute>? attrs) throws ParseError {
3700
var begin = get_location ();
3703
expect (TokenType.DELEGATE);
3705
var flags = parse_member_declaration_modifiers ();
3707
var sym = parse_symbol_name ();
3709
var type_param_list = parse_type_parameter_list ();
3711
if (ModifierFlags.NEW in flags) {
3712
throw new ParseError.SYNTAX (get_error ("`new' modifier not allowed on delegates"));
3715
var params = new ArrayList<Parameter> ();
3717
expect (TokenType.OPEN_PARENS);
3718
if (current () != TokenType.CLOSE_PARENS) {
3720
var param = parse_parameter ();
3722
} while (accept (TokenType.COMMA));
3724
expect (TokenType.CLOSE_PARENS);
3726
if (accept (TokenType.COLON)) {
3727
type = parse_type (true, false);
3730
type = new VoidType ();
3733
var d = new Delegate (sym.name, type, get_src (begin), comment);
3735
if (accept (TokenType.RAISES)) {
3737
d.add_error_type (parse_type (true, false));
3738
} while (accept (TokenType.COMMA));
3741
expect_terminator ();
3744
if (ModifierFlags.PRIVATE in flags) {
3745
d.access = SymbolAccessibility.PRIVATE;
3747
d.access = get_access (sym.name);
3750
if (ModifierFlags.STATIC in flags) {
3751
d.has_target = false;
3753
if (ModifierFlags.EXTERN in flags || scanner.source_file.file_type == SourceFileType.PACKAGE) {
3757
set_attributes (d, attrs);
3759
foreach (TypeParameter type_param in type_param_list) {
3760
d.add_type_parameter (type_param);
3763
foreach (Parameter formal_param in params) {
3764
d.add_parameter (formal_param);
3770
while (sym.inner != null) {
3772
var ns = new Namespace (sym.name, d.source_reference);
3774
if (result is Namespace) {
3775
ns.add_namespace ((Namespace) result);
3777
ns.add_delegate ((Delegate) result);
3784
List<TypeParameter> parse_type_parameter_list () throws ParseError {
3785
if (accept (TokenType.OF)) {
3786
var list = new ArrayList<TypeParameter> ();
3788
var begin = get_location ();
3789
string id = parse_identifier ();
3790
list.add (new TypeParameter (id, get_src (begin)));
3791
} while (accept (TokenType.COMMA));
3794
if (_empty_type_parameter_list == null) {
3795
_empty_type_parameter_list = new ArrayList<TypeParameter> ();
3797
return _empty_type_parameter_list;
3801
void skip_type_argument_list () throws ParseError {
3802
if (accept (TokenType.OF)) {
3803
if (accept (TokenType.OPEN_PARENS)) {
3806
} while (accept (TokenType.COMMA));
3807
expect (TokenType.CLOSE_PARENS);
3811
} while (accept (TokenType.COMMA));
3817
// try to parse type argument list
3818
List<DataType>? parse_type_argument_list (bool maybe_expression) throws ParseError {
3819
var begin = get_location ();
3820
if (accept (TokenType.OF)) {
3821
var list = new ArrayList<DataType> ();
3822
var inParens = false;
3824
// Optional parens allow multi arg types in function signature: "dict of (int, string)"
3825
// See: https://bugzilla.gnome.org/show_bug.cgi?id=611191
3826
if (accept (TokenType.OPEN_PARENS)) {
3831
switch (current ()) {
3832
case TokenType.VOID:
3833
case TokenType.DYNAMIC:
3834
case TokenType.UNOWNED:
3835
case TokenType.WEAK:
3836
case TokenType.IDENTIFIER:
3837
var type = parse_type (true, true);
3845
} while (accept (TokenType.COMMA));
3848
expect (TokenType.CLOSE_PARENS);
3856
MemberAccess parse_member_name (Expression? base_expr = null) throws ParseError {
3857
var begin = get_location ();
3858
MemberAccess expr = null;
3860
string id = parse_identifier ();
3861
List<DataType> type_arg_list = parse_type_argument_list (false);
3862
expr = new MemberAccess (expr != null ? expr : base_expr, id, get_src (begin));
3863
if (type_arg_list != null) {
3864
foreach (DataType type_arg in type_arg_list) {
3865
expr.add_type_argument (type_arg);
3868
} while (accept (TokenType.DOT));