1 /* valagenieparser.vala
3 * Copyright (C) 2008 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
29 * Code visitor parsing all Genie source files.
31 public class Vala
.Genie
.Parser
: CodeVisitor
{
38 // index of current token in buffer
40 // number of tokens in buffer
47 /* hack needed to know if any part of an expression is a lambda one */
48 bool current_expr_is_lambda
;
50 const int BUFFER_SIZE
= 32;
53 public TokenType type
;
54 public SourceLocation begin
;
55 public SourceLocation end
;
71 tokens
= new TokenInfo
[BUFFER_SIZE
];
73 current_expr_is_lambda
= false;
77 * Parses all .gs source files in the specified code context and
80 * @param context a code context
82 public void parse (CodeContext context
) {
83 this
.context
= context
;
84 context
.accept (this
);
87 public override void visit_source_file (SourceFile source_file
) {
88 if (source_file
.filename
.has_suffix (".gs")) {
89 parse_file (source_file
);
94 index
= (index
+ 1) % BUFFER_SIZE
;
97 SourceLocation begin
, end
;
98 TokenType type
= scanner
.read_token (out begin
, out end
);
99 tokens
[index
].type
= type
;
100 tokens
[index
].begin
= begin
;
101 tokens
[index
].end
= end
;
104 return (tokens
[index
].type
!= TokenType
.EOF
);
107 inline
void prev () {
108 index
= (index
- 1 + BUFFER_SIZE
) % BUFFER_SIZE
;
110 assert (size
<= BUFFER_SIZE
);
113 inline TokenType
current () {
114 return tokens
[index
].type
;
117 inline
bool accept (TokenType type
) {
118 if (current () == type
) {
125 inline
bool accept_terminator () {
126 if (current () == TokenType
.SEMICOLON
|| current () == TokenType
.EOL
) {
133 inline
bool accept_block () {
135 bool has_term
= accept_terminator ();
137 if (accept (TokenType
.INDENT
)) {
149 string get_error (string msg
) {
150 var begin
= get_location ();
152 Report
.error (get_src (begin
), "syntax error, " + msg
);
156 inline
bool expect (TokenType type
) throws ParseError
{
161 TokenType cur
= current ();
162 TokenType pre
= tokens
[index
- 1].type
;
164 throw new ParseError
.SYNTAX (get_error ("expected %s but got %s with previous %s".printf (type
.to_string (), cur
.to_string (), pre
.to_string())));
167 inline
bool expect_terminator () throws ParseError
{
168 if (accept_terminator ()) {
172 TokenType cur
= current ();
174 throw new ParseError
.SYNTAX (get_error ("expected line end or semicolon but got %s".printf (cur
.to_string())));
177 inline SourceLocation
get_location () {
178 return tokens
[index
].begin
;
181 string get_last_string () {
182 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
183 return ((string) tokens
[last_index
].begin
.pos
).ndup ((tokens
[last_index
].end
.pos
- tokens
[last_index
].begin
.pos
));
186 SourceReference
get_src (SourceLocation begin
) {
187 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
189 return new
SourceReference (scanner
.source_file
, begin
.line
, begin
.column
, tokens
[last_index
].end
.line
, tokens
[last_index
].end
.column
);
192 SourceReference
get_src_com (SourceLocation begin
) {
193 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
195 var src
= new SourceReference
.with_comment (scanner
.source_file
, begin
.line
, begin
.column
, tokens
[last_index
].end
.line
, tokens
[last_index
].end
.column
, comment
);
200 SourceReference
get_current_src () {
201 return new
SourceReference (scanner
.source_file
, tokens
[index
].begin
.line
, tokens
[index
].begin
.column
, tokens
[index
].end
.line
, tokens
[index
].end
.column
);
204 void rollback (SourceLocation location
) {
205 while (tokens
[index
].begin
.pos
!= location
.pos
) {
210 inline SymbolAccessibility
get_access (string s
) {
212 return SymbolAccessibility
.PRIVATE
;
215 return SymbolAccessibility
.PUBLIC
;
218 void skip_identifier () throws ParseError
{
219 // also accept keywords as identifiers where there is no conflict
220 switch (current ()) {
221 case TokenType
.ABSTRACT
:
223 case TokenType
.ASSERT
:
224 case TokenType
.BREAK
:
225 case TokenType
.CLASS
:
226 case TokenType
.CONST
:
227 case TokenType
.CONTINUE
:
228 case TokenType
.DEDENT
:
230 case TokenType
.DEFAULT
:
231 case TokenType
.DELEGATE
:
232 case TokenType
.DELETE
:
234 case TokenType
.DOWNTO
:
235 case TokenType
.DYNAMIC
:
239 case TokenType
.ENSURES
:
240 case TokenType
.ERRORDOMAIN
:
241 case TokenType
.EVENT
:
242 case TokenType
.EXCEPT
:
243 case TokenType
.EXTERN
:
244 case TokenType
.FALSE
:
245 case TokenType
.FINAL
:
246 case TokenType
.FINALLY
:
249 case TokenType
.IDENTIFIER
:
252 case TokenType
.INDENT
:
254 case TokenType
.INLINE
:
255 case TokenType
.INTERFACE
:
259 case TokenType
.NAMESPACE
:
264 case TokenType
.OVERRIDE
:
266 case TokenType
.PRINT
:
267 case TokenType
.PRIVATE
:
269 case TokenType
.RAISE
:
270 case TokenType
.RAISES
:
272 case TokenType
.REQUIRES
:
273 case TokenType
.RETURN
:
275 case TokenType
.SIZEOF
:
276 case TokenType
.STATIC
:
277 case TokenType
.STRUCT
:
278 case TokenType
.SUPER
:
283 case TokenType
.TYPEOF
:
286 case TokenType
.VIRTUAL
:
288 case TokenType
.VOLATILE
:
291 case TokenType
.WHILE
:
295 throw new ParseError
.SYNTAX (get_error ("expected identifier"));
299 string parse_identifier () throws ParseError
{
301 return get_last_string ();
304 Expression
parse_literal () throws ParseError
{
305 var begin
= get_location ();
307 switch (current ()) {
310 return new
BooleanLiteral (true, get_src (begin
));
311 case TokenType
.FALSE
:
313 return new
BooleanLiteral (false, get_src (begin
));
314 case TokenType
.INTEGER_LITERAL
:
316 return new
IntegerLiteral (get_last_string (), get_src (begin
));
317 case TokenType
.REAL_LITERAL
:
319 return new
RealLiteral (get_last_string (), get_src (begin
));
320 case TokenType
.CHARACTER_LITERAL
:
322 return new
CharacterLiteral (get_last_string (), get_src (begin
));
323 case TokenType
.STRING_LITERAL
:
325 return new
StringLiteral (get_last_string (), get_src (begin
));
328 return new
NullLiteral (get_src (begin
));
330 throw new ParseError
.SYNTAX (get_error ("expected literal"));
334 public void parse_file (SourceFile source_file
) {
335 scanner
= new
Scanner (source_file
);
336 scanner
.indent_spaces
= 0;
343 var begin
= get_location ();
344 /* see if there is an indent attribute */
345 if (accept (TokenType
.OPEN_BRACKET
)) {
346 var id
= parse_identifier ();
347 if (id
== "indent") {
348 expect (TokenType
.ASSIGN
);
349 expect (TokenType
.INTEGER_LITERAL
);
350 scanner
.indent_spaces
= get_last_string().to_int();
351 expect (TokenType
.CLOSE_BRACKET
);
352 expect (TokenType
.EOL
);
358 parse_using_directives ();
359 parse_declarations (context
.root
, true);
360 } catch (ParseError e
) {
367 void skip_symbol_name () throws ParseError
{
370 } while (accept (TokenType
.DOT
));
373 UnresolvedSymbol
parse_symbol_name () throws ParseError
{
374 var begin
= get_location ();
375 UnresolvedSymbol sym
= null;
377 string name
= parse_identifier ();
378 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
379 } while (accept (TokenType
.DOT
));
383 void skip_type () throws ParseError
{
384 if (accept (TokenType
.VOID
)) {
385 while (accept (TokenType
.STAR
)) {
389 accept (TokenType
.DYNAMIC
);
391 accept (TokenType
.WEAK
);
393 if (accept (TokenType
.ARRAY
) || accept (TokenType
.LIST
) || accept (TokenType
.DICT
)) {
394 accept (TokenType
.OF
);
398 skip_type_argument_list ();
399 while (accept (TokenType
.OPEN_BRACKET
)) {
401 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
404 } while (accept (TokenType
.COMMA
));
405 expect (TokenType
.CLOSE_BRACKET
);
407 accept (TokenType
.OP_NEG
);
408 accept (TokenType
.INTERR
);
409 accept (TokenType
.HASH
);
412 DataType
parse_type (bool owned_by_default
= true) throws ParseError
{
413 var begin
= get_location ();
415 if (accept (TokenType
.VOID
)) {
416 DataType type
= new
VoidType ();
417 while (accept (TokenType
.STAR
)) {
418 type
= new
PointerType (type
);
423 Gee
.List
<DataType
> type_arg_list
= null;
424 UnresolvedSymbol sym
= null;
426 bool is_dynamic
= accept (TokenType
.DYNAMIC
);
427 bool value_owned
= owned_by_default
;
428 if (owned_by_default
) {
429 value_owned
= !accept (TokenType
.WEAK
);
433 bool is_array
= false;
435 if (accept (TokenType
.ARRAY
)) {
436 expect (TokenType
.OF
);
441 bool is_list
= false;
443 if (accept (TokenType
.LIST
)) {
444 expect (TokenType
.OF
);
450 bool is_dict
= false;
452 if (accept (TokenType
.DICT
)) {
453 expect (TokenType
.OF
);
459 var sym_parent
= new
UnresolvedSymbol (null, "Gee", get_src (begin
));
460 sym
= new
UnresolvedSymbol (sym_parent
, "ArrayList", get_src (begin
));
461 } else if (is_dict
) {
462 var sym_parent
= new
UnresolvedSymbol (null, "Gee", get_src (begin
));
463 sym
= new
UnresolvedSymbol (sym_parent
, "HashMap", get_src (begin
));
465 sym
= parse_symbol_name ();
468 type_arg_list
= parse_type_argument_list (false);
470 DataType type
= new UnresolvedType
.from_symbol (sym
, get_src (begin
));
471 if (type_arg_list
!= null) {
472 foreach (DataType type_arg
in type_arg_list
) {
473 type
.add_type_argument (type_arg
);
477 while (accept (TokenType
.STAR
)) {
478 type
= new
PointerType (type
, get_src (begin
));
481 if (!(type is PointerType
)) {
482 type
.nullable
= accept (TokenType
.INTERR
);
487 if (!accept (TokenType
.OPEN_BRACKET
)) {
488 type
.value_owned
= true;
489 type
= new
ArrayType (type
, 1, get_src (begin
));
490 type
.nullable
= accept (TokenType
.INTERR
);
495 while (accept (TokenType
.OPEN_BRACKET
)) {
499 // support for stack-allocated arrays
500 // also required for decision between expression and declaration statement
501 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
505 while (accept (TokenType
.COMMA
));
506 expect (TokenType
.CLOSE_BRACKET
);
508 type
.value_owned
= true;
509 type
= new
ArrayType (type
, array_rank
, get_src (begin
));
510 type
.nullable
= accept (TokenType
.INTERR
);
515 if (!owned_by_default
) {
516 value_owned
= accept (TokenType
.HASH
);
519 type
.is_dynamic
= is_dynamic
;
520 type
.value_owned
= value_owned
;
524 Gee
.List
<Expression
> parse_argument_list () throws ParseError
{
525 var list
= new ArrayList
<Expression
> ();
526 if (current () != TokenType
.CLOSE_PARENS
) {
528 list
.add (parse_expression ());
529 } while (accept (TokenType
.COMMA
));
534 Expression
parse_primary_expression () throws ParseError
{
535 var begin
= get_location ();
539 switch (current ()) {
541 case TokenType
.FALSE
:
542 case TokenType
.INTEGER_LITERAL
:
543 case TokenType
.REAL_LITERAL
:
544 case TokenType
.CHARACTER_LITERAL
:
545 case TokenType
.STRING_LITERAL
:
547 expr
= parse_literal ();
549 case TokenType
.ASSERT
:
550 return parse_assert_expression ();
551 case TokenType
.OPEN_PARENS
:
552 expr
= parse_tuple ();
555 expr
= parse_this_access ();
557 case TokenType
.SUPER
:
558 expr
= parse_base_access ();
561 expr
= parse_object_or_array_creation_expression ();
563 case TokenType
.PRINT
:
564 return parse_print_expression ();
565 case TokenType
.SIZEOF
:
566 expr
= parse_sizeof_expression ();
568 case TokenType
.TYPEOF
:
569 expr
= parse_typeof_expression ();
572 expr
= parse_simple_name ();
576 // process primary expressions that start with an inner primary expression
579 switch (current ()) {
581 expr
= parse_member_access (begin
, expr
);
583 case TokenType
.OP_PTR
:
584 expr
= parse_pointer_member_access (begin
, expr
);
586 case TokenType
.OPEN_PARENS
:
587 expr
= parse_method_call (begin
, expr
);
589 case TokenType
.OPEN_BRACKET
:
590 expr
= parse_element_access (begin
, expr
);
592 case TokenType
.OP_INC
:
593 expr
= parse_post_increment_expression (begin
, expr
);
595 case TokenType
.OP_DEC
:
596 expr
= parse_post_decrement_expression (begin
, expr
);
608 Expression
parse_simple_name () throws ParseError
{
609 var begin
= get_location ();
610 string id
= parse_identifier ();
611 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (true);
612 var expr
= new
MemberAccess (null, id
, get_src (begin
));
613 if (type_arg_list
!= null) {
614 foreach (DataType type_arg
in type_arg_list
) {
615 expr
.add_type_argument (type_arg
);
621 Expression
parse_tuple () throws ParseError
{
622 var begin
= get_location ();
623 expect (TokenType
.OPEN_PARENS
);
624 var expr_list
= new ArrayList
<Expression
> ();
625 if (current () != TokenType
.CLOSE_PARENS
) {
627 expr_list
.add (parse_expression ());
628 } while (accept (TokenType
.COMMA
));
630 expect (TokenType
.CLOSE_PARENS
);
631 if (expr_list
.size
!= 1) {
632 var tuple
= new
Tuple ();
633 foreach (Expression expr
in expr_list
) {
634 tuple
.add_expression (expr
);
638 return new
ParenthesizedExpression (expr_list
.get (0), get_src (begin
));
641 Expression
parse_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
642 expect (TokenType
.DOT
);
643 string id
= parse_identifier ();
644 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (true);
645 var expr
= new
MemberAccess (inner
, id
, get_src (begin
));
646 if (type_arg_list
!= null) {
647 foreach (DataType type_arg
in type_arg_list
) {
648 expr
.add_type_argument (type_arg
);
654 Expression
parse_pointer_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
655 expect (TokenType
.OP_PTR
);
656 string id
= parse_identifier ();
657 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (true);
658 var expr
= new MemberAccess
.pointer (inner
, id
, get_src (begin
));
659 if (type_arg_list
!= null) {
660 foreach (DataType type_arg
in type_arg_list
) {
661 expr
.add_type_argument (type_arg
);
668 Gee
.List
<Expression
> parse_print_argument_list () throws ParseError
{
669 var list
= new ArrayList
<Expression
> ();
671 var begin
= get_location ();
673 if (current () != TokenType
.CLOSE_PARENS
) {
675 var p_expr
= parse_expression ();
679 if (p_expr
!= null) {
682 if (p_expr is StringLiteral
) {
683 var s_exp
= (StringLiteral
) p_expr
;
684 var len
= s_exp
.value
.size ();
687 var st
= s_exp
.value
.ndup (len
-1);
692 var rhs
= new
StringLiteral (s
, get_src (begin
));
693 p_expr
= new
BinaryExpression (BinaryOperator
.PLUS
, p_expr
, rhs
, get_src (begin
));
700 } while (accept (TokenType
.COMMA
));
705 Expression
parse_print_expression () throws ParseError
{
706 var begin
= get_location ();
708 expect (TokenType
.PRINT
);
709 accept (TokenType
.OPEN_PARENS
);
711 var expr
= new
MemberAccess (null, "print", get_src (begin
));
713 var arg_list
= parse_print_argument_list ();
715 accept (TokenType
.CLOSE_PARENS
);
717 var print_expr
= new
MethodCall (expr
, get_src (begin
));
719 foreach (Expression arg
in arg_list
) {
720 print_expr
.add_argument (arg
);
727 Expression
parse_assert_expression () throws ParseError
{
728 var begin
= get_location ();
730 expect (TokenType
.ASSERT
);
731 accept (TokenType
.OPEN_PARENS
);
733 var expr
= new
MemberAccess (null, "assert", get_src (begin
));
735 var arg_list
= parse_argument_list ();
737 accept (TokenType
.CLOSE_PARENS
);
739 var assert_expr
= new
MethodCall (expr
, get_src (begin
));
741 foreach (Expression arg
in arg_list
) {
742 assert_expr
.add_argument (arg
);
749 Expression
parse_method_call (SourceLocation begin
, Expression inner
) throws ParseError
{
750 expect (TokenType
.OPEN_PARENS
);
751 var arg_list
= parse_argument_list ();
752 expect (TokenType
.CLOSE_PARENS
);
753 var init_list
= parse_object_initializer ();
755 if (init_list
.size
> 0 && inner is MemberAccess
) {
756 // struct creation expression
757 var member
= (MemberAccess
) inner
;
758 member
.creation_member
= true;
760 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
761 expr
.struct_creation
= true;
762 foreach (Expression arg
in arg_list
) {
763 expr
.add_argument (arg
);
765 foreach (MemberInitializer initializer
in init_list
) {
766 expr
.add_member_initializer (initializer
);
770 var expr
= new
MethodCall (inner
, get_src (begin
));
771 foreach (Expression arg
in arg_list
) {
772 expr
.add_argument (arg
);
778 Expression
parse_element_access (SourceLocation begin
, Expression inner
) throws ParseError
{
779 expect (TokenType
.OPEN_BRACKET
);
780 var index_list
= parse_expression_list ();
781 expect (TokenType
.CLOSE_BRACKET
);
783 var expr
= new
ElementAccess (inner
, get_src (begin
));
784 foreach (Expression index
in index_list
) {
785 expr
.append_index (index
);
790 Gee
.List
<Expression
> parse_expression_list () throws ParseError
{
791 var list
= new ArrayList
<Expression
> ();
793 list
.add (parse_expression ());
794 } while (accept (TokenType
.COMMA
));
798 Expression
parse_this_access () throws ParseError
{
799 var begin
= get_location ();
800 expect (TokenType
.THIS
);
801 return new
MemberAccess (null, "this", get_src (begin
));
804 Expression
parse_base_access () throws ParseError
{
805 var begin
= get_location ();
806 expect (TokenType
.SUPER
);
807 return new
BaseAccess (get_src (begin
));
810 Expression
parse_post_increment_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
811 expect (TokenType
.OP_INC
);
812 return new
PostfixExpression (inner
, true, get_src (begin
));
815 Expression
parse_post_decrement_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
816 expect (TokenType
.OP_DEC
);
817 return new
PostfixExpression (inner
, false, get_src (begin
));
820 Expression
parse_object_or_array_creation_expression () throws ParseError
{
821 var begin
= get_location ();
822 expect (TokenType
.NEW
);
824 if (accept (TokenType
.ARRAY
)) {
825 expect (TokenType
.OF
);
826 var m
= parse_member_name ();
827 var expr
= parse_array_creation_expression (begin
, m
);
831 if (accept (TokenType
.LIST
)) {
832 expect (TokenType
.OF
);
833 var m
= parse_member_name ();
834 var expr
= parse_list_creation_expression (begin
, m
);
838 if (accept (TokenType
.DICT
)) {
839 expect (TokenType
.OF
);
840 var m1
= parse_member_name ();
841 expect (TokenType
.COMMA
);
842 var m2
= parse_member_name ();
843 var expr
= parse_dict_creation_expression (begin
, m1
, m2
);
848 var member
= parse_member_name ();
849 var expr
= parse_object_creation_expression (begin
, member
);
854 Expression
parse_object_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
855 member
.creation_member
= true;
856 Gee
.List
<Expression
> arg_list
;
857 if (accept (TokenType
.OPEN_PARENS
)) {
858 arg_list
= parse_argument_list ();
859 expect (TokenType
.CLOSE_PARENS
);
861 arg_list
= new ArrayList
<Expression
> ();
864 var init_list
= parse_object_initializer ();
866 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
867 foreach (Expression arg
in arg_list
) {
868 expr
.add_argument (arg
);
870 foreach (MemberInitializer initializer
in init_list
) {
871 expr
.add_member_initializer (initializer
);
876 Expression
parse_array_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
877 bool size_specified
= false;
878 Gee
.List
<Expression
> size_specifier_list
= null;
880 DataType element_type
= UnresolvedType
.new_from_expression (member
);
882 var has_bracket
= accept (TokenType
.OPEN_BRACKET
);
886 // array of arrays: new T[][42]
887 element_type
= new
ArrayType (element_type
, size_specifier_list
.size
, element_type
.source_reference
);
892 size_specifier_list
= new ArrayList
<Expression
> ();
894 Expression size
= null;
895 if (has_bracket
&& current () != TokenType
.CLOSE_BRACKET
&& current () != TokenType
.COMMA
) {
896 size
= parse_expression ();
897 size_specified
= true;
899 size_specifier_list
.add (size
);
900 } while (accept (TokenType
.COMMA
));
903 expect (TokenType
.CLOSE_BRACKET
);
905 } while (accept (TokenType
.OPEN_BRACKET
));
907 InitializerList initializer
= null;
908 if (accept (TokenType
.ASSIGN
)) {
910 initializer
= parse_initializer ();
912 var expr
= new
ArrayCreationExpression (element_type
, size_specifier_list
.size
, initializer
, get_src (begin
));
913 if (size_specified
) {
914 foreach (Expression size
in size_specifier_list
) {
915 expr
.append_size (size
);
922 Expression
parse_list_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
924 DataType element_type
= UnresolvedType
.new_from_expression (member
);
925 MemberAccess list_member
= null, parent_member
= null;
927 parent_member
= new
MemberAccess (null, "Gee", get_src (begin
));
928 list_member
= new
MemberAccess (parent_member
, "ArrayList", get_src (begin
));
929 list_member
.add_type_argument (element_type
);
931 list_member
.creation_member
= true;
933 var expr
= new
ObjectCreationExpression (list_member
, get_src (begin
));
935 if (member
.member_name
== "string") {
936 parent_member
= new
MemberAccess (null, "GLib", get_src (begin
));
937 expr
.add_argument (new
MemberAccess (parent_member
, "str_equal", get_src (begin
)));
939 } else if (member
.member_name
== "int") {
940 parent_member
= new
MemberAccess (null, "GLib", get_src (begin
));
941 expr
.add_argument (new
MemberAccess (parent_member
, "int_equal", get_src (begin
)));
947 Expression
parse_dict_creation_expression (SourceLocation begin
, MemberAccess member_key
, MemberAccess member_value
) throws ParseError
{
949 DataType key_type
= UnresolvedType
.new_from_expression (member_key
);
950 DataType value_type
= UnresolvedType
.new_from_expression (member_value
);
952 MemberAccess dict_member
= null, parent_member
= null, dict_hash
= null, dict_equal
= null;
954 parent_member
= new
MemberAccess (null, "Gee", get_src (begin
));
955 dict_member
= new
MemberAccess (parent_member
, "HashMap", get_src (begin
));
956 dict_member
.add_type_argument (key_type
);
957 dict_member
.add_type_argument (value_type
);
959 if (member_key
.member_name
== "string") {
960 parent_member
= new
MemberAccess (null, "GLib", get_src (begin
));
961 dict_hash
= new
MemberAccess (parent_member
, "str_hash", get_src (begin
));
962 dict_equal
= new
MemberAccess (parent_member
, "str_equal", get_src (begin
));
964 } else if (member_key
.member_name
== "int") {
965 parent_member
= new
MemberAccess (null, "GLib", get_src (begin
));
966 dict_hash
= new
MemberAccess (parent_member
, "int_hash", get_src (begin
));
967 dict_equal
= new
MemberAccess (parent_member
, "int_equal", get_src (begin
));
970 dict_member
.creation_member
= true;
972 var expr
= new
ObjectCreationExpression (dict_member
, get_src (begin
));
974 if (dict_hash
!= null && dict_equal
!= null) {
975 expr
.add_argument (dict_hash
);
976 expr
.add_argument (dict_equal
);
984 Gee
.List
<MemberInitializer
> parse_object_initializer () throws ParseError
{
985 var list
= new ArrayList
<MemberInitializer
> ();
986 if (accept (TokenType
.OPEN_BRACE
)) {
988 list
.add (parse_member_initializer ());
989 } while (accept (TokenType
.COMMA
));
990 expect (TokenType
.CLOSE_BRACE
);
995 MemberInitializer
parse_member_initializer () throws ParseError
{
996 var begin
= get_location ();
997 string id
= parse_identifier ();
998 expect (TokenType
.ASSIGN
);
999 var expr
= parse_expression ();
1001 return new
MemberInitializer (id
, expr
, get_src (begin
));
1004 Expression
parse_sizeof_expression () throws ParseError
{
1005 var begin
= get_location ();
1006 expect (TokenType
.SIZEOF
);
1007 expect (TokenType
.OPEN_PARENS
);
1008 var type
= parse_type ();
1009 expect (TokenType
.CLOSE_PARENS
);
1011 return new
SizeofExpression (type
, get_src (begin
));
1014 Expression
parse_typeof_expression () throws ParseError
{
1015 var begin
= get_location ();
1016 expect (TokenType
.TYPEOF
);
1017 expect (TokenType
.OPEN_PARENS
);
1018 var type
= parse_type ();
1019 expect (TokenType
.CLOSE_PARENS
);
1021 return new
TypeofExpression (type
, get_src (begin
));
1024 UnaryOperator
get_unary_operator (TokenType token_type
) {
1025 switch (token_type
) {
1026 case TokenType
.PLUS
: return UnaryOperator
.PLUS
;
1027 case TokenType
.MINUS
: return UnaryOperator
.MINUS
;
1028 case TokenType
.OP_NEG
: return UnaryOperator
.LOGICAL_NEGATION
;
1029 case TokenType
.TILDE
: return UnaryOperator
.BITWISE_COMPLEMENT
;
1030 case TokenType
.OP_INC
: return UnaryOperator
.INCREMENT
;
1031 case TokenType
.OP_DEC
: return UnaryOperator
.DECREMENT
;
1032 case TokenType
.REF
: return UnaryOperator
.REF
;
1033 case TokenType
.OUT
: return UnaryOperator
.OUT
;
1034 default: return UnaryOperator
.NONE
;
1038 Expression
parse_unary_expression () throws ParseError
{
1039 var begin
= get_location ();
1040 var operator
= get_unary_operator (current ());
1041 if (operator
!= UnaryOperator
.NONE
) {
1043 var op
= parse_unary_expression ();
1044 return new
UnaryExpression (operator
, op
, get_src (begin
));
1046 switch (current ()) {
1047 case TokenType
.HASH
:
1049 var op
= parse_unary_expression ();
1050 return new
ReferenceTransferExpression (op
, get_src (begin
));
1051 case TokenType
.OPEN_PARENS
:
1053 switch (current ()) {
1054 case TokenType
.VOID
:
1055 case TokenType
.DYNAMIC
:
1056 case TokenType
.WEAK
:
1057 case TokenType
.IDENTIFIER
:
1058 var type
= parse_type ();
1059 if (accept (TokenType
.CLOSE_PARENS
)) {
1060 // check follower to decide whether to create cast expression
1061 switch (current ()) {
1062 case TokenType
.OP_NEG
:
1063 case TokenType
.TILDE
:
1064 case TokenType
.OPEN_PARENS
:
1065 case TokenType
.TRUE
:
1066 case TokenType
.FALSE
:
1067 case TokenType
.INTEGER_LITERAL
:
1068 case TokenType
.REAL_LITERAL
:
1069 case TokenType
.CHARACTER_LITERAL
:
1070 case TokenType
.STRING_LITERAL
:
1071 case TokenType
.NULL
:
1072 case TokenType
.THIS
:
1073 case TokenType
.SUPER
:
1075 case TokenType
.SIZEOF
:
1076 case TokenType
.TYPEOF
:
1077 case TokenType
.IDENTIFIER
:
1078 if (!(type is PointerType
) && !type
.value_owned
) {
1079 Report
.warning (get_src (begin
), "obsolete syntax, weak type modifier unused in cast expressions");
1081 var inner
= parse_unary_expression ();
1082 return new
CastExpression (inner
, type
, get_src (begin
), false);
1091 // no cast expression
1094 case TokenType
.STAR
:
1096 var op
= parse_unary_expression ();
1097 return new
PointerIndirection (op
, get_src (begin
));
1098 case TokenType
.BITWISE_AND
:
1100 var op
= parse_unary_expression ();
1101 return new
AddressofExpression (op
, get_src (begin
));
1106 var expr
= parse_primary_expression ();
1110 BinaryOperator
get_binary_operator (TokenType token_type
) {
1111 switch (token_type
) {
1112 case TokenType
.STAR
: return BinaryOperator
.MUL
;
1113 case TokenType
.DIV
: return BinaryOperator
.DIV
;
1114 case TokenType
.PERCENT
: return BinaryOperator
.MOD
;
1115 case TokenType
.PLUS
: return BinaryOperator
.PLUS
;
1116 case TokenType
.MINUS
: return BinaryOperator
.MINUS
;
1117 case TokenType
.OP_LT
: return BinaryOperator
.LESS_THAN
;
1118 case TokenType
.OP_GT
: return BinaryOperator
.GREATER_THAN
;
1119 case TokenType
.OP_LE
: return BinaryOperator
.LESS_THAN_OR_EQUAL
;
1120 case TokenType
.OP_GE
: return BinaryOperator
.GREATER_THAN_OR_EQUAL
;
1121 case TokenType
.OP_EQ
: return BinaryOperator
.EQUALITY
;
1124 if (current () == TokenType
.OP_NEG
) {
1126 return BinaryOperator
.INEQUALITY
;
1129 return BinaryOperator
.EQUALITY
;
1130 case TokenType
.OP_NE
: return BinaryOperator
.INEQUALITY
;
1131 default: return BinaryOperator
.NONE
;
1135 Expression
parse_multiplicative_expression () throws ParseError
{
1136 var begin
= get_location ();
1137 var left
= parse_unary_expression ();
1140 var operator
= get_binary_operator (current ());
1142 case BinaryOperator
.MUL
:
1143 case BinaryOperator
.DIV
:
1144 case BinaryOperator
.MOD
:
1146 var right
= parse_unary_expression ();
1147 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1157 Expression
parse_additive_expression () throws ParseError
{
1158 var begin
= get_location ();
1159 var left
= parse_multiplicative_expression ();
1162 var operator
= get_binary_operator (current ());
1164 case BinaryOperator
.PLUS
:
1165 case BinaryOperator
.MINUS
:
1167 var right
= parse_multiplicative_expression ();
1168 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1178 Expression
parse_shift_expression () throws ParseError
{
1179 var begin
= get_location ();
1180 var left
= parse_additive_expression ();
1183 switch (current ()) {
1184 case TokenType
.OP_SHIFT_LEFT
:
1186 var right
= parse_additive_expression ();
1187 left
= new
BinaryExpression (BinaryOperator
.SHIFT_LEFT
, left
, right
, get_src (begin
));
1189 // don't use OP_SHIFT_RIGHT to support >> for nested generics
1190 case TokenType
.OP_GT
:
1191 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1193 // only accept >> when there is no space between the two > signs
1194 if (current () == TokenType
.OP_GT
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1196 var right
= parse_additive_expression ();
1197 left
= new
BinaryExpression (BinaryOperator
.SHIFT_RIGHT
, left
, right
, get_src (begin
));
1211 Expression
parse_relational_expression () throws ParseError
{
1212 var begin
= get_location ();
1213 var left
= parse_shift_expression ();
1216 var operator
= get_binary_operator (current ());
1218 case BinaryOperator
.LESS_THAN
:
1219 case BinaryOperator
.LESS_THAN_OR_EQUAL
:
1220 case BinaryOperator
.GREATER_THAN_OR_EQUAL
:
1222 var right
= parse_shift_expression ();
1223 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1225 case BinaryOperator
.GREATER_THAN
:
1227 // ignore >> and >>= (two tokens due to generics)
1228 if (current () != TokenType
.OP_GT
&& current () != TokenType
.OP_GE
) {
1229 var right
= parse_shift_expression ();
1230 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1237 switch (current ()) {
1240 var type
= parse_type ();
1241 left
= new
TypeCheck (left
, type
, get_src (begin
));
1245 var type
= parse_type ();
1246 left
= new
CastExpression (left
, type
, get_src (begin
), true);
1258 Expression
parse_equality_expression () throws ParseError
{
1259 var begin
= get_location ();
1260 var left
= parse_relational_expression ();
1263 var operator
= get_binary_operator (current ());
1265 case BinaryOperator
.INEQUALITY
:
1266 case BinaryOperator
.EQUALITY
:
1267 if ((operator
== BinaryOperator
.INEQUALITY
) && (current () == TokenType
.IS
)) {
1271 var right
= parse_relational_expression ();
1272 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1282 Expression
parse_and_expression () throws ParseError
{
1283 var begin
= get_location ();
1284 var left
= parse_equality_expression ();
1285 while (accept (TokenType
.BITWISE_AND
)) {
1286 var right
= parse_equality_expression ();
1287 left
= new
BinaryExpression (BinaryOperator
.BITWISE_AND
, left
, right
, get_src (begin
));
1292 Expression
parse_exclusive_or_expression () throws ParseError
{
1293 var begin
= get_location ();
1294 var left
= parse_and_expression ();
1295 while (accept (TokenType
.CARRET
)) {
1296 var right
= parse_and_expression ();
1297 left
= new
BinaryExpression (BinaryOperator
.BITWISE_XOR
, left
, right
, get_src (begin
));
1302 Expression
parse_inclusive_or_expression () throws ParseError
{
1303 var begin
= get_location ();
1304 var left
= parse_exclusive_or_expression ();
1305 while (accept (TokenType
.BITWISE_OR
)) {
1306 var right
= parse_exclusive_or_expression ();
1307 left
= new
BinaryExpression (BinaryOperator
.BITWISE_OR
, left
, right
, get_src (begin
));
1312 Expression
parse_in_expression () throws ParseError
{
1313 var begin
= get_location ();
1314 var left
= parse_inclusive_or_expression ();
1315 while (accept (TokenType
.IN
)) {
1316 var right
= parse_inclusive_or_expression ();
1317 left
= new
BinaryExpression (BinaryOperator
.IN
, left
, right
, get_src (begin
));
1322 Expression
parse_conditional_and_expression () throws ParseError
{
1323 var begin
= get_location ();
1324 var left
= parse_in_expression ();
1325 while (accept (TokenType
.OP_AND
)) {
1326 var right
= parse_in_expression ();
1327 left
= new
BinaryExpression (BinaryOperator
.AND
, left
, right
, get_src (begin
));
1332 Expression
parse_conditional_or_expression () throws ParseError
{
1333 var begin
= get_location ();
1334 var left
= parse_conditional_and_expression ();
1335 while (accept (TokenType
.OP_OR
)) {
1336 var right
= parse_conditional_and_expression ();
1337 left
= new
BinaryExpression (BinaryOperator
.OR
, left
, right
, get_src (begin
));
1342 Expression
parse_conditional_expression () throws ParseError
{
1343 var begin
= get_location ();
1344 var condition
= parse_conditional_or_expression ();
1345 if (accept (TokenType
.INTERR
)) {
1346 var true_expr
= parse_expression ();
1347 expect (TokenType
.COLON
);
1348 var false_expr
= parse_expression ();
1349 return new
ConditionalExpression (condition
, true_expr
, false_expr
, get_src (begin
));
1355 Expression
parse_lambda_expression () throws ParseError
{
1356 var begin
= get_location ();
1357 Gee
.List
<string> params
= new ArrayList
<string> ();
1359 expect (TokenType
.DEF
);
1361 if (accept (TokenType
.OPEN_PARENS
)) {
1362 if (current () != TokenType
.CLOSE_PARENS
) {
1364 params
.add (parse_identifier ());
1365 } while (accept (TokenType
.COMMA
));
1367 expect (TokenType
.CLOSE_PARENS
);
1369 params
.add (parse_identifier ());
1373 LambdaExpression lambda
;
1374 if (accept_block ()) {
1375 var block
= parse_block ();
1376 lambda
= new LambdaExpression
.with_statement_body (block
, get_src (begin
));
1378 var expr
= parse_expression ();
1379 lambda
= new
LambdaExpression (expr
, get_src (begin
));
1380 expect_terminator ();
1385 foreach (string param
in params
) {
1386 lambda
.add_parameter (param
);
1391 AssignmentOperator
get_assignment_operator (TokenType token_type
) {
1392 switch (token_type
) {
1393 case TokenType
.ASSIGN
: return AssignmentOperator
.SIMPLE
;
1394 case TokenType
.ASSIGN_ADD
: return AssignmentOperator
.ADD
;
1395 case TokenType
.ASSIGN_SUB
: return AssignmentOperator
.SUB
;
1396 case TokenType
.ASSIGN_BITWISE_OR
: return AssignmentOperator
.BITWISE_OR
;
1397 case TokenType
.ASSIGN_BITWISE_AND
: return AssignmentOperator
.BITWISE_AND
;
1398 case TokenType
.ASSIGN_BITWISE_XOR
: return AssignmentOperator
.BITWISE_XOR
;
1399 case TokenType
.ASSIGN_DIV
: return AssignmentOperator
.DIV
;
1400 case TokenType
.ASSIGN_MUL
: return AssignmentOperator
.MUL
;
1401 case TokenType
.ASSIGN_PERCENT
: return AssignmentOperator
.PERCENT
;
1402 case TokenType
.ASSIGN_SHIFT_LEFT
: return AssignmentOperator
.SHIFT_LEFT
;
1403 default: return AssignmentOperator
.NONE
;
1407 Expression
parse_expression () throws ParseError
{
1408 if (current () == TokenType
.DEF
) {
1409 var lambda
= parse_lambda_expression ();
1410 current_expr_is_lambda
= true;
1414 var begin
= get_location ();
1415 Expression expr
= parse_conditional_expression ();
1418 var operator
= get_assignment_operator (current ());
1419 if (operator
!= AssignmentOperator
.NONE
) {
1421 var rhs
= parse_expression ();
1422 expr
= new
Assignment (expr
, rhs
, operator
, get_src (begin
));
1423 } else if (current () == TokenType
.OP_GT
) { // >>=
1424 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1426 // only accept >>= when there is no space between the two > signs
1427 if (current () == TokenType
.OP_GE
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1429 var rhs
= parse_expression ();
1430 expr
= new
Assignment (expr
, rhs
, AssignmentOperator
.SHIFT_RIGHT
, get_src (begin
));
1444 Statement
get_for_statement_type () throws ParseError
{
1446 var begin
= get_location ();
1447 bool is_foreach
= false;
1449 while (current () != TokenType
.EOL
&& current () != TokenType
.DO
) {
1451 if (accept (TokenType
.IN
)) {
1460 return parse_foreach_statement ();
1462 return parse_for_statement ();
1467 void parse_statements (Block block
) throws ParseError
{
1468 while (current () != TokenType
.DEDENT
1469 && current () != TokenType
.WHEN
1470 && current () != TokenType
.DEFAULT
) {
1472 Statement stmt
= null;
1473 bool is_decl
= false;
1474 comment
= scanner
.pop_comment ();
1475 switch (current ()) {
1477 /* skip over requires and ensures as we handled them in method declaration */
1478 case TokenType
.REQUIRES
:
1479 case TokenType
.ENSURES
:
1480 var begin
= get_location ();
1483 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
1484 while (current () != TokenType
.DEDENT
) {
1488 expect (TokenType
.DEDENT
);
1490 while (current () != TokenType
.EOL
) {
1494 expect (TokenType
.EOL
);
1497 stmt
= new
EmptyStatement (get_src_com (begin
));
1501 case TokenType
.INDENT
:
1502 stmt
= parse_block ();
1504 case TokenType
.SEMICOLON
:
1505 case TokenType
.PASS
:
1506 stmt
= parse_empty_statement ();
1508 case TokenType
.PRINT
:
1509 case TokenType
.ASSERT
:
1510 stmt
= parse_expression_statement ();
1513 stmt
= parse_if_statement ();
1515 case TokenType
.CASE
:
1516 stmt
= parse_switch_statement ();
1518 case TokenType
.WHILE
:
1519 stmt
= parse_while_statement ();
1522 stmt
= parse_do_statement ();
1525 stmt
= get_for_statement_type ();
1527 case TokenType
.BREAK
:
1528 stmt
= parse_break_statement ();
1530 case TokenType
.CONTINUE
:
1531 stmt
= parse_continue_statement ();
1533 case TokenType
.RETURN
:
1534 stmt
= parse_return_statement ();
1536 case TokenType
.RAISE
:
1537 stmt
= parse_throw_statement ();
1540 stmt
= parse_try_statement ();
1542 case TokenType
.LOCK
:
1543 stmt
= parse_lock_statement ();
1545 case TokenType
.DELETE
:
1546 stmt
= parse_delete_statement ();
1550 parse_local_variable_declarations (block
);
1554 case TokenType
.OP_INC
:
1555 case TokenType
.OP_DEC
:
1556 case TokenType
.SUPER
:
1557 case TokenType
.THIS
:
1558 case TokenType
.OPEN_PARENS
:
1559 case TokenType
.STAR
:
1561 stmt
= parse_expression_statement ();
1564 bool is_expr
= is_expression ();
1566 stmt
= parse_expression_statement ();
1569 parse_local_variable_declarations (block
);
1575 block
.add_statement (stmt
);
1577 } catch (ParseError e
) {
1578 if (recover () != RecoveryState
.STATEMENT_BEGIN
) {
1579 // beginning of next declaration or end of file reached
1580 // return what we have so far
1587 bool is_expression () throws ParseError
{
1588 var begin
= get_location ();
1590 // decide between declaration and expression statement
1592 switch (current ()) {
1593 // invocation expression
1594 case TokenType
.OPEN_PARENS
:
1595 // postfix increment
1596 case TokenType
.OP_INC
:
1597 // postfix decrement
1598 case TokenType
.OP_DEC
:
1600 case TokenType
.ASSIGN
:
1601 case TokenType
.ASSIGN_ADD
:
1602 case TokenType
.ASSIGN_BITWISE_AND
:
1603 case TokenType
.ASSIGN_BITWISE_OR
:
1604 case TokenType
.ASSIGN_BITWISE_XOR
:
1605 case TokenType
.ASSIGN_DIV
:
1606 case TokenType
.ASSIGN_MUL
:
1607 case TokenType
.ASSIGN_PERCENT
:
1608 case TokenType
.ASSIGN_SHIFT_LEFT
:
1609 case TokenType
.ASSIGN_SUB
:
1610 case TokenType
.OP_GT
: // >>=
1613 // pointer member access
1614 case TokenType
.OP_PTR
:
1623 Block
parse_embedded_statement () throws ParseError
{
1624 if (current () == TokenType
.INDENT
) {
1625 var block
= parse_block ();
1629 comment
= scanner
.pop_comment ();
1631 var block
= new
Block (get_src_com (get_location ()));
1632 block
.add_statement (parse_embedded_statement_without_block ());
1637 Statement
parse_embedded_statement_without_block () throws ParseError
{
1638 switch (current ()) {
1639 case TokenType
.PASS
:
1640 case TokenType
.SEMICOLON
: return parse_empty_statement ();
1641 case TokenType
.IF
: return parse_if_statement ();
1642 case TokenType
.CASE
: return parse_switch_statement ();
1643 case TokenType
.WHILE
: return parse_while_statement ();
1644 case TokenType
.DO
: return parse_do_statement ();
1645 case TokenType
.FOR
: return get_for_statement_type ();
1646 case TokenType
.BREAK
: return parse_break_statement ();
1647 case TokenType
.CONTINUE
: return parse_continue_statement ();
1648 case TokenType
.RETURN
: return parse_return_statement ();
1649 case TokenType
.RAISE
: return parse_throw_statement ();
1650 case TokenType
.TRY
: return parse_try_statement ();
1651 case TokenType
.LOCK
: return parse_lock_statement ();
1652 case TokenType
.DELETE
: return parse_delete_statement ();
1653 default: return parse_expression_statement ();
1657 Block
parse_block () throws ParseError
{
1658 var begin
= get_location ();
1659 expect (TokenType
.INDENT
);
1660 var block
= new
Block (get_src_com (begin
));
1661 parse_statements (block
);
1662 if (!accept (TokenType
.DEDENT
)) {
1663 // only report error if it's not a secondary error
1664 if (Report
.get_errors () == 0) {
1665 Report
.error (get_current_src (), "tab indentation is incorrect");
1672 Statement
parse_empty_statement () throws ParseError
{
1673 var begin
= get_location ();
1675 accept (TokenType
.PASS
);
1676 accept (TokenType
.SEMICOLON
);
1677 expect_terminator ();
1679 return new
EmptyStatement (get_src_com (begin
));
1682 void add_local_var_variable (Block block
, string id
) throws ParseError
{
1683 DataType type_copy
= null;
1684 var local
= parse_local_variable (type_copy
, id
);
1685 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1688 void parse_local_variable_declarations (Block block
) throws ParseError
{
1689 if (accept (TokenType
.VAR
)) {
1690 /* support block vars */
1691 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
1692 while (current () != TokenType
.DEDENT
) {
1693 var s
= parse_identifier ();
1694 add_local_var_variable (block
, s
);
1695 accept (TokenType
.EOL
);
1696 accept (TokenType
.SEMICOLON
);
1699 expect (TokenType
.DEDENT
);
1701 var s
= parse_identifier ();
1702 add_local_var_variable (block
, s
);
1703 expect_terminator ();
1709 var id_list
= new ArrayList
<string> ();
1710 DataType variable_type
= null;
1713 id_list
.add (parse_identifier ());
1714 } while (accept (TokenType
.COMMA
));
1716 expect (TokenType
.COLON
);
1718 variable_type
= parse_type ();
1720 foreach (string id
in id_list
) {
1721 DataType type_copy
= null;
1722 if (variable_type
!= null) {
1723 type_copy
= variable_type
.copy ();
1725 var local
= parse_local_variable (type_copy
, id
);
1726 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1729 expect_terminator ();
1732 LocalVariable
parse_local_variable (DataType? variable_type
, string id
) throws ParseError
{
1733 var begin
= get_location ();
1734 Expression initializer
= null;
1735 if (accept (TokenType
.ASSIGN
)) {
1736 initializer
= parse_variable_initializer ();
1738 return new
LocalVariable (variable_type
, id
, initializer
, get_src_com (begin
));
1741 Statement
parse_expression_statement () throws ParseError
{
1742 var begin
= get_location ();
1743 var expr
= parse_statement_expression ();
1745 if (current_expr_is_lambda
) {
1746 current_expr_is_lambda
= false;
1748 expect_terminator ();
1751 return new
ExpressionStatement (expr
, get_src_com (begin
));
1754 Expression
parse_statement_expression () throws ParseError
{
1755 // invocation expression, assignment,
1756 // or pre/post increment/decrement expression
1757 var expr
= parse_expression ();
1761 Statement
parse_if_statement () throws ParseError
{
1762 var begin
= get_location ();
1764 expect (TokenType
.IF
);
1766 var condition
= parse_expression ();
1768 if (!accept (TokenType
.DO
)) {
1769 expect (TokenType
.EOL
);
1771 accept (TokenType
.EOL
);
1774 var src
= get_src_com (begin
);
1775 var true_stmt
= parse_embedded_statement ();
1776 Block false_stmt
= null;
1777 if (accept (TokenType
.ELSE
)) {
1778 false_stmt
= parse_embedded_statement ();
1780 return new
IfStatement (condition
, true_stmt
, false_stmt
, src
);
1783 Statement
parse_switch_statement () throws ParseError
{
1784 var begin
= get_location ();
1785 expect (TokenType
.CASE
);
1786 var condition
= parse_expression ();
1788 expect (TokenType
.EOL
);
1790 var stmt
= new
SwitchStatement (condition
, get_src_com (begin
));
1791 expect (TokenType
.INDENT
);
1792 while (current () != TokenType
.DEDENT
) {
1793 var section
= new
SwitchSection (get_src_com (begin
));
1795 if (accept (TokenType
.WHEN
)) {
1797 section
.add_label (new
SwitchLabel (parse_expression (), get_src_com (begin
)));
1799 while (accept (TokenType
.COMMA
));
1801 expect (TokenType
.DEFAULT
);
1802 section
.add_label (new SwitchLabel
.with_default (get_src_com (begin
)));
1805 if (!accept (TokenType
.EOL
)) {
1806 expect (TokenType
.DO
);
1809 parse_statements (section
);
1811 /* add break statement for each block */
1812 var break_stmt
= new
BreakStatement (get_src_com (begin
));
1813 section
.add_statement (break_stmt
);
1815 stmt
.add_section (section
);
1817 expect (TokenType
.DEDENT
);
1821 Statement
parse_while_statement () throws ParseError
{
1822 var begin
= get_location ();
1823 expect (TokenType
.WHILE
);
1824 var condition
= parse_expression ();
1826 if (!accept (TokenType
.DO
)) {
1827 expect (TokenType
.EOL
);
1829 accept (TokenType
.EOL
);
1832 var body
= parse_embedded_statement ();
1833 return new
WhileStatement (condition
, body
, get_src_com (begin
));
1836 Statement
parse_do_statement () throws ParseError
{
1837 var begin
= get_location ();
1838 expect (TokenType
.DO
);
1839 expect (TokenType
.EOL
);
1840 var body
= parse_embedded_statement ();
1841 expect (TokenType
.WHILE
);
1843 var condition
= parse_expression ();
1845 expect_terminator ();
1847 return new
DoStatement (body
, condition
, get_src_com (begin
));
1851 Statement
parse_for_statement () throws ParseError
{
1852 var begin
= get_location ();
1854 Expression initializer
= null;
1855 Expression condition
= null;
1856 Expression iterator
= null;
1860 expect (TokenType
.FOR
);
1862 switch (current ()) {
1868 bool local_is_expr
= is_expression ();
1869 is_expr
= local_is_expr
;
1874 var expr_begin
= get_location ();
1875 id
= parse_identifier ();
1876 rollback (expr_begin
);
1877 initializer
= parse_statement_expression ();
1879 block
= new
Block (get_src (begin
));
1880 DataType variable_type
;
1881 if (accept (TokenType
.VAR
)) {
1882 variable_type
= null;
1883 id
= parse_identifier ();
1885 id
= parse_identifier ();
1886 expect (TokenType
.COLON
);
1887 variable_type
= parse_type ();
1890 DataType type_copy
= null;
1891 if (variable_type
!= null) {
1892 type_copy
= variable_type
.copy ();
1894 var local
= parse_local_variable (type_copy
, id
);
1896 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1901 if (accept (TokenType
.TO
)) {
1902 /* create expression for condition and incrementing iterator */
1903 var to_begin
= get_location ();
1904 var to_src
= get_src (to_begin
);
1905 var left
= new
MemberAccess (null, id
, to_src
);
1906 var right
= parse_primary_expression ();
1908 condition
= new
BinaryExpression (BinaryOperator
.LESS_THAN_OR_EQUAL
, left
, right
, to_src
);
1910 iterator
= new
PostfixExpression (left
, true, to_src
);
1912 expect (TokenType
.DOWNTO
);
1913 var downto_begin
= get_location ();
1914 var downto_src
= get_src (downto_begin
);
1915 /* create expression for condition and decrementing iterator */
1916 var left
= new
MemberAccess (null, id
, downto_src
);
1917 var right
= parse_primary_expression ();
1919 condition
= new
BinaryExpression (BinaryOperator
.GREATER_THAN_OR_EQUAL
, left
, right
, downto_src
);
1921 iterator
= new
PostfixExpression (left
, false, downto_src
);
1924 if (!accept (TokenType
.EOL
)) {
1925 expect (TokenType
.DO
);
1928 var src
= get_src_com (begin
);
1929 var body
= parse_embedded_statement ();
1930 var stmt
= new
ForStatement (condition
, body
, src
);
1932 if (initializer
!= null) stmt
.add_initializer (initializer
);
1934 stmt
.add_iterator (iterator
);
1937 if (block
!= null) {
1938 block
.add_statement (stmt
);
1945 Statement
parse_foreach_statement () throws ParseError
{
1946 var begin
= get_location ();
1947 DataType type
= null;
1950 expect (TokenType
.FOR
);
1952 if (accept (TokenType
.VAR
)) {
1953 id
= parse_identifier ();
1955 id
= parse_identifier ();
1956 if (accept (TokenType
.COLON
)) {
1957 type
= parse_type ();
1961 expect (TokenType
.IN
);
1962 var collection
= parse_expression ();
1963 if (!accept (TokenType
.EOL
)) {
1964 expect (TokenType
.DO
);
1966 var src
= get_src_com (begin
);
1967 var body
= parse_embedded_statement ();
1968 return new
ForeachStatement (type
, id
, collection
, body
, src
);
1971 Statement
parse_break_statement () throws ParseError
{
1972 var begin
= get_location ();
1973 expect (TokenType
.BREAK
);
1974 expect_terminator ();
1975 return new
BreakStatement (get_src_com (begin
));
1978 Statement
parse_continue_statement () throws ParseError
{
1979 var begin
= get_location ();
1980 expect (TokenType
.CONTINUE
);
1981 expect_terminator ();
1982 return new
ContinueStatement (get_src_com (begin
));
1985 Statement
parse_return_statement () throws ParseError
{
1986 var begin
= get_location ();
1987 expect (TokenType
.RETURN
);
1988 Expression expr
= null;
1989 if (current () != TokenType
.SEMICOLON
&& current () != TokenType
.EOL
) {
1990 expr
= parse_expression ();
1992 expect_terminator ();
1993 return new
ReturnStatement (expr
, get_src_com (begin
));
1996 Statement
parse_throw_statement () throws ParseError
{
1997 var begin
= get_location ();
1998 expect (TokenType
.RAISE
);
1999 var expr
= parse_expression ();
2000 expect_terminator ();
2001 return new
ThrowStatement (expr
, get_src_com (begin
));
2004 Statement
parse_try_statement () throws ParseError
{
2005 var begin
= get_location ();
2006 expect (TokenType
.TRY
);
2007 expect (TokenType
.EOL
);
2008 var try_block
= parse_block ();
2009 Block finally_clause
= null;
2010 var catch_clauses
= new ArrayList
<CatchClause
> ();
2011 if (current () == TokenType
.EXCEPT
) {
2012 parse_catch_clauses (catch_clauses
);
2013 if (current () == TokenType
.FINALLY
) {
2014 finally_clause
= parse_finally_clause ();
2017 finally_clause
= parse_finally_clause ();
2019 var stmt
= new
TryStatement (try_block
, finally_clause
, get_src_com (begin
));
2020 foreach (CatchClause clause
in catch_clauses
) {
2021 stmt
.add_catch_clause (clause
);
2026 void parse_catch_clauses (Gee
.List
<CatchClause
> catch_clauses
) throws ParseError
{
2027 while (accept (TokenType
.EXCEPT
)) {
2028 var begin
= get_location ();
2029 DataType type
= null;
2031 if (!accept (TokenType
.EOL
)) {
2032 id
= parse_identifier ();
2033 expect (TokenType
.COLON
);
2034 type
= parse_type ();
2035 expect (TokenType
.EOL
);
2038 var block
= parse_block ();
2039 catch_clauses
.add (new
CatchClause (type
, id
, block
, get_src (begin
)));
2043 Block
parse_finally_clause () throws ParseError
{
2044 expect (TokenType
.FINALLY
);
2046 var block
= parse_block ();
2050 Statement
parse_lock_statement () throws ParseError
{
2051 var begin
= get_location ();
2052 expect (TokenType
.LOCK
);
2053 expect (TokenType
.OPEN_PARENS
);
2054 var expr
= parse_expression ();
2055 expect (TokenType
.CLOSE_PARENS
);
2056 var stmt
= parse_embedded_statement ();
2057 return new
LockStatement (expr
, stmt
, get_src_com (begin
));
2060 Statement
parse_delete_statement () throws ParseError
{
2061 var begin
= get_location ();
2062 expect (TokenType
.DELETE
);
2063 var expr
= parse_expression ();
2064 expect_terminator ();
2065 return new
DeleteStatement (expr
, get_src_com (begin
));
2068 Gee
.List
<Attribute
>?
parse_attributes () throws ParseError
{
2069 if (current () != TokenType
.OPEN_BRACKET
) {
2072 var attrs
= new ArrayList
<Attribute
> ();
2073 while (accept (TokenType
.OPEN_BRACKET
)) {
2075 var begin
= get_location ();
2076 string id
= parse_identifier ();
2077 var attr
= new
Attribute (id
, get_src (begin
));
2078 if (accept (TokenType
.OPEN_PARENS
)) {
2079 if (current () != TokenType
.CLOSE_PARENS
) {
2081 id
= parse_identifier ();
2082 expect (TokenType
.ASSIGN
);
2083 var expr
= parse_expression ();
2084 attr
.add_argument (id
, expr
);
2085 } while (accept (TokenType
.COMMA
));
2087 expect (TokenType
.CLOSE_PARENS
);
2090 } while (accept (TokenType
.COMMA
));
2091 expect (TokenType
.CLOSE_BRACKET
);
2093 expect (TokenType
.EOL
);
2098 void set_attributes (CodeNode node
, Gee
.List
<Attribute
>? attributes
) {
2099 if (attributes
!= null) {
2100 foreach (Attribute attr
in (Gee
.List
<Attribute
>) attributes
) {
2101 node
.attributes
.append (attr
);
2106 Symbol
parse_declaration (bool is_root
= false) throws ParseError
{
2107 comment
= scanner
.pop_comment ();
2108 var attrs
= parse_attributes ();
2110 switch (current ()) {
2111 case TokenType
.CONST
:
2112 return parse_constant_declaration (attrs
);
2113 case TokenType
.CONSTRUCT
:
2114 return parse_creation_method_declaration (attrs
);
2115 case TokenType
.CLASS
:
2116 return parse_class_declaration (attrs
);
2117 case TokenType
.INIT
:
2119 return parse_main_method_declaration (attrs
);
2121 return parse_constructor_declaration (attrs
);
2122 case TokenType
.DELEGATE
:
2123 return parse_delegate_declaration (attrs
);
2125 return parse_method_declaration (attrs
);
2126 case TokenType
.ENUM
:
2127 return parse_enum_declaration (attrs
);
2128 case TokenType
.ERRORDOMAIN
:
2129 return parse_errordomain_declaration (attrs
);
2130 case TokenType
.FINAL
:
2131 return parse_destructor_declaration (attrs
);
2132 case TokenType
.INTERFACE
:
2133 return parse_interface_declaration (attrs
);
2134 case TokenType
.NAMESPACE
:
2135 return parse_namespace_declaration (attrs
);
2136 case TokenType
.PROP
:
2137 return parse_property_declaration (attrs
);
2138 case TokenType
.EVENT
:
2139 return parse_signal_declaration (attrs
);
2140 case TokenType
.STRUCT
:
2141 return parse_struct_declaration (attrs
);
2143 var begin
= get_location ();
2144 while (current () != TokenType
.EOL
&& current () != TokenType
.SEMICOLON
&& current () != TokenType
.EOF
) {
2145 if (current () == TokenType
.COLON
) {
2147 return parse_field_declaration (attrs
);
2157 TokenType cur
= current ();
2158 TokenType pre
= tokens
[index
-1].type
;
2160 throw new ParseError
.SYNTAX (get_error ("expected declaration but got %s with previous %s".printf (cur
.to_string (), pre
.to_string())));
2163 void parse_declarations (Symbol parent
, bool root
= false) throws ParseError
{
2165 expect (TokenType
.INDENT
);
2167 while (current () != TokenType
.DEDENT
&& current () != TokenType
.EOF
) {
2169 if (parent is Namespace
) {
2170 parse_namespace_member ((Namespace
) parent
);
2171 } else if (parent is Class
) {
2172 parse_class_member ((Class
) parent
);
2173 } else if (parent is Struct
) {
2174 parse_struct_member ((Struct
) parent
);
2175 } else if (parent is Interface
) {
2176 parse_interface_member ((Interface
) parent
);
2178 } catch (ParseError e
) {
2182 if (r
== RecoveryState
.STATEMENT_BEGIN
) {
2188 if (r
== RecoveryState
.EOF
) {
2194 if (!accept (TokenType
.DEDENT
)) {
2195 // only report error if it's not a secondary error
2196 if (Report
.get_errors () == 0) {
2197 Report
.error (get_current_src (), "expected dedent");
2203 enum RecoveryState
{
2209 RecoveryState
recover () {
2210 while (current () != TokenType
.EOF
) {
2211 switch (current ()) {
2212 case TokenType
.CLASS
:
2213 case TokenType
.CONST
:
2214 case TokenType
.CONSTRUCT
:
2215 case TokenType
.INIT
:
2217 case TokenType
.DELEGATE
:
2218 case TokenType
.ENUM
:
2219 case TokenType
.ERRORDOMAIN
:
2220 case TokenType
.FINAL
:
2221 case TokenType
.INTERFACE
:
2222 case TokenType
.NAMESPACE
:
2223 case TokenType
.PROP
:
2224 case TokenType
.EVENT
:
2225 case TokenType
.STRUCT
:
2226 return RecoveryState
.DECLARATION_BEGIN
;
2227 case TokenType
.BREAK
:
2228 case TokenType
.CASE
:
2229 case TokenType
.CONTINUE
:
2230 case TokenType
.DELETE
:
2234 case TokenType
.LOCK
:
2235 case TokenType
.RETURN
:
2236 case TokenType
.RAISE
:
2239 case TokenType
.WHILE
:
2240 return RecoveryState
.STATEMENT_BEGIN
;
2246 return RecoveryState
.EOF
;
2249 Namespace
parse_namespace_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2250 var begin
= get_location ();
2251 expect (TokenType
.NAMESPACE
);
2252 var sym
= parse_symbol_name ();
2253 var ns
= new
Namespace (sym
.name
, get_src_com (begin
));
2254 set_attributes (ns
, attrs
);
2255 expect (TokenType
.EOL
);
2256 parse_declarations (ns
);
2260 void parse_namespace_member (Namespace ns
) throws ParseError
{
2262 var sym
= parse_declaration ((ns
== context
.root
));
2263 if (sym is Namespace
) {
2264 ns
.add_namespace ((Namespace
) sym
);
2265 } else if (sym is Class
) {
2266 ns
.add_class ((Class
) sym
);
2267 } else if (sym is Interface
) {
2268 ns
.add_interface ((Interface
) sym
);
2269 } else if (sym is Struct
) {
2270 ns
.add_struct ((Struct
) sym
);
2271 } else if (sym is Enum
) {
2272 ns
.add_enum ((Enum
) sym
);
2273 } else if (sym is ErrorDomain
) {
2274 ns
.add_error_domain ((ErrorDomain
) sym
);
2275 } else if (sym is Delegate
) {
2276 ns
.add_delegate ((Delegate
) sym
);
2277 } else if (sym is Method
) {
2278 var method
= (Method
) sym
;
2279 if (method
.binding
== MemberBinding
.INSTANCE
) {
2280 method
.binding
= MemberBinding
.STATIC
;
2282 ns
.add_method (method
);
2283 } else if (sym is Field
) {
2284 var field
= (Field
) sym
;
2285 if (field
.binding
== MemberBinding
.INSTANCE
) {
2286 field
.binding
= MemberBinding
.STATIC
;
2288 ns
.add_field (field
);
2289 } else if (sym is Constant
) {
2290 ns
.add_constant ((Constant
) sym
);
2292 Report
.error (sym
.source_reference
, "unexpected declaration in namespace");
2294 scanner
.source_file
.add_node (sym
);
2298 void add_uses_clause () throws ParseError
{
2299 var begin
= get_location ();
2300 var sym
= parse_symbol_name ();
2301 var ns_ref
= new
UsingDirective (sym
, get_src (begin
));
2303 scanner
.source_file
.add_using_directive (ns_ref
);
2306 void parse_using_directives () throws ParseError
{
2307 while (accept (TokenType
.USES
)) {
2308 if (accept_block ()) {
2309 expect (TokenType
.INDENT
);
2311 while (current () != TokenType
.DEDENT
&& current () != TokenType
.EOF
) {
2313 expect (TokenType
.EOL
);
2316 expect (TokenType
.DEDENT
);
2320 } while (accept (TokenType
.COMMA
));
2322 expect_terminator ();
2328 Symbol
parse_class_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2329 var begin
= get_location ();
2330 expect (TokenType
.CLASS
);
2332 var flags
= parse_type_declaration_modifiers ();
2334 var sym
= parse_symbol_name ();
2335 var type_param_list
= parse_type_parameter_list ();
2336 var base_types
= new ArrayList
<DataType
> ();
2337 if (accept (TokenType
.COLON
)) {
2338 base_types
.add (parse_type ());
2340 if (accept (TokenType
.IMPLEMENTS
)) {
2342 base_types
.add (parse_type ());
2343 } while (accept (TokenType
.COMMA
));
2347 accept (TokenType
.EOL
);
2349 var cl
= new
Class (sym
.name
, get_src_com (begin
));
2351 if (ModifierFlags
.PRIVATE
in flags
) {
2352 cl
.access
= SymbolAccessibility
.PRIVATE
;
2354 /* class must always be Public unless its name starts wtih underscore */
2355 if (sym
.name
[0] == '_') {
2356 cl
.access
= SymbolAccessibility
.PRIVATE
;
2358 cl
.access
= SymbolAccessibility
.PUBLIC
;
2362 if (ModifierFlags
.ABSTRACT
in flags
) {
2363 cl
.is_abstract
= true;
2365 set_attributes (cl
, attrs
);
2366 foreach (TypeParameter type_param
in type_param_list
) {
2367 cl
.add_type_parameter (type_param
);
2369 foreach (DataType base_type
in base_types
) {
2370 cl
.add_base_type (base_type
);
2373 class_name
= cl
.name
;
2375 parse_declarations (cl
);
2377 // ensure there is always a default construction method
2378 if (!scanner
.source_file
.external_package
2380 && cl
.default_construction_method
== null) {
2381 var m
= new
CreationMethod (cl
.name
, null, cl
.source_reference
);
2382 m
.binding
= MemberBinding
.STATIC
;
2383 m
.access
= SymbolAccessibility
.PUBLIC
;
2384 m
.body
= new
Block (cl
.source_reference
);
2389 while (sym
.inner
!= null) {
2391 var ns
= new
Namespace (sym
.name
, cl
.source_reference
);
2392 if (result is Namespace
) {
2393 ns
.add_namespace ((Namespace
) result
);
2395 ns
.add_class ((Class
) result
);
2396 scanner
.source_file
.add_node (result
);
2403 void parse_class_member (Class cl
) throws ParseError
{
2404 var sym
= parse_declaration ();
2406 cl
.add_class ((Class
) sym
);
2407 } else if (sym is Struct
) {
2408 cl
.add_struct ((Struct
) sym
);
2409 } else if (sym is Enum
) {
2410 cl
.add_enum ((Enum
) sym
);
2411 } else if (sym is Delegate
) {
2412 cl
.add_delegate ((Delegate
) sym
);
2413 } else if (sym is Method
) {
2414 cl
.add_method ((Method
) sym
);
2415 } else if (sym is Vala
.Signal
) {
2416 cl
.add_signal ((Vala
.Signal
) sym
);
2417 } else if (sym is Field
) {
2418 cl
.add_field ((Field
) sym
);
2419 } else if (sym is Constant
) {
2420 cl
.add_constant ((Constant
) sym
);
2421 } else if (sym is Property
) {
2422 cl
.add_property ((Property
) sym
);
2423 } else if (sym is Constructor
) {
2424 var c
= (Constructor
) sym
;
2425 if (c
.binding
== MemberBinding
.INSTANCE
) {
2427 } else if (c
.binding
== MemberBinding
.CLASS
) {
2428 cl
.class_constructor
= c
;
2430 cl
.static_constructor
= c
;
2432 } else if (sym is Destructor
) {
2433 cl
.destructor
= (Destructor
) sym
;
2435 Report
.error (sym
.source_reference
, "unexpected declaration in class");
2439 Constant
parse_constant_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2440 var begin
= get_location ();
2442 expect (TokenType
.CONST
);
2444 parse_member_declaration_modifiers ();
2446 string id
= parse_identifier ();
2447 expect (TokenType
.COLON
);
2448 var type
= parse_type (false);
2450 Expression initializer
= null;
2451 if (accept (TokenType
.ASSIGN
)) {
2452 initializer
= parse_variable_initializer ();
2454 expect_terminator ();
2456 // constant arrays don't own their element
2457 var array_type
= type as ArrayType
;
2458 if (array_type
!= null) {
2459 array_type
.element_type
.value_owned
= false;
2462 var c
= new
Constant (id
, type
, initializer
, get_src_com (begin
));
2463 c
.access
= get_access (id
);
2464 set_attributes (c
, attrs
);
2468 Field
parse_field_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2469 var begin
= get_location ();
2470 string id
= parse_identifier ();
2471 expect (TokenType
.COLON
);
2473 var flags
= parse_member_declaration_modifiers ();
2475 var type
= parse_type ();
2477 var f
= new
Field (id
, type
, null, get_src_com (begin
));
2479 if (ModifierFlags
.ABSTRACT
in flags
|| ModifierFlags
.VIRTUAL
in flags
|| ModifierFlags
.OVERRIDE
in flags
) {
2480 Report
.error (f
.source_reference
, "abstract, virtual, and override modifiers are not applicable to fields");
2483 if (ModifierFlags
.PRIVATE
in flags
) {
2484 f
.access
= SymbolAccessibility
.PRIVATE
;
2486 f
.access
= get_access (id
);
2489 set_attributes (f
, attrs
);
2491 if (accept (TokenType
.ASSIGN
)) {
2492 f
.initializer
= parse_expression ();
2495 if (ModifierFlags
.STATIC
in flags
) {
2496 f
.binding
= MemberBinding
.STATIC
;
2497 } else if (ModifierFlags
.CLASS
in flags
) {
2498 f
.binding
= MemberBinding
.CLASS
;
2501 expect_terminator ();
2506 InitializerList
parse_initializer () throws ParseError
{
2507 var begin
= get_location ();
2508 if (!accept (TokenType
.OPEN_PARENS
)) {
2509 expect (TokenType
.OPEN_BRACE
);
2511 var initializer
= new
InitializerList (get_src (begin
));
2512 if (current () != TokenType
.DEDENT
) {
2514 var init
= parse_variable_initializer ();
2515 initializer
.append (init
);
2516 } while (accept (TokenType
.COMMA
));
2518 if (!accept (TokenType
.CLOSE_PARENS
)) {
2519 expect (TokenType
.CLOSE_BRACE
);
2524 bool is_initializer () throws ParseError
{
2525 if (current () == TokenType
.OPEN_BRACE
) {
2530 if (current () == TokenType.OPEN_PARENS) {
2531 var begin = get_location ();
2532 var is_array = false;
2536 var expr = parse_expression ();
2537 is_array = (accept (TokenType.COMMA));
2549 Expression
parse_variable_initializer () throws ParseError
{
2550 if (is_initializer ()) {
2551 var expr
= parse_initializer ();
2554 var expr
= parse_expression ();
2560 Method
parse_main_method_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2562 var begin
= get_location ();
2563 DataType type
= new
VoidType ();
2564 expect (TokenType
.INIT
);
2566 var method
= new
Method (id
, type
, get_src_com (begin
));
2567 method
.access
= SymbolAccessibility
.PUBLIC
;
2569 set_attributes (method
, attrs
);
2571 method
.binding
= MemberBinding
.STATIC
;
2573 var sym
= new
UnresolvedSymbol (null, "string", get_src (begin
));
2574 type
= new UnresolvedType
.from_symbol (sym
, get_src (begin
));
2575 type
.value_owned
= true;
2576 type
= new
ArrayType (type
, 1, get_src (begin
));
2577 type
.nullable
= false;
2579 var param
= new
FormalParameter ("args", type
, get_src (begin
));
2580 method
.add_parameter (param
);
2583 expect (TokenType
.EOL
);
2585 if (accept_block ()) {
2586 method
.body
= parse_block ();
2592 Method
parse_method_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2593 var begin
= get_location ();
2594 DataType type
= new
VoidType ();
2595 expect (TokenType
.DEF
);
2596 var flags
= parse_member_declaration_modifiers ();
2598 string id
= parse_identifier ();
2600 var params
= new ArrayList
<FormalParameter
> ();
2601 expect (TokenType
.OPEN_PARENS
);
2603 if (current () != TokenType
.CLOSE_PARENS
) {
2605 var param
= parse_parameter ();
2607 } while (accept (TokenType
.COMMA
));
2610 expect (TokenType
.CLOSE_PARENS
);
2613 /* deal with return value */
2614 if (accept (TokenType
.COLON
)) {
2615 type
= parse_type ();
2616 parse_type_parameter_list ();
2620 var method
= new
Method (id
, type
, get_src_com (begin
));
2621 if (ModifierFlags
.PRIVATE
in flags
) {
2622 method
.access
= SymbolAccessibility
.PRIVATE
;
2624 method
.access
= get_access (id
);
2628 set_attributes (method
, attrs
);
2630 foreach (FormalParameter param
in params
) {
2631 method
.add_parameter (param
);
2634 if (accept (TokenType
.RAISES
)) {
2636 method
.add_error_type (parse_type ());
2637 } while (accept (TokenType
.COMMA
));
2641 if (ModifierFlags
.STATIC
in flags
|| id
== "main") {
2642 method
.binding
= MemberBinding
.STATIC
;
2644 if (ModifierFlags
.ABSTRACT
in flags
) {
2645 method
.is_abstract
= true;
2647 if (ModifierFlags
.VIRTUAL
in flags
) {
2648 method
.is_virtual
= true;
2650 if (ModifierFlags
.OVERRIDE
in flags
) {
2651 method
.overrides
= true;
2653 if (ModifierFlags
.INLINE
in flags
) {
2654 method
.is_inline
= true;
2657 expect (TokenType
.EOL
);
2659 var body_location
= get_location ();
2662 /* "requires" and "ensures" if present will be at start of the method body */
2663 if (accept (TokenType
.INDENT
)) {
2664 if (accept (TokenType
.REQUIRES
)) {
2666 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
2667 while (current() != TokenType
.DEDENT
) {
2668 method
.add_precondition (parse_expression ());
2669 expect (TokenType
.EOL
);
2672 expect (TokenType
.DEDENT
);
2673 accept_terminator ();
2676 method
.add_precondition (parse_expression ());
2677 expect_terminator ();
2683 if (accept (TokenType
.ENSURES
)) {
2684 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
2685 while (current() != TokenType
.DEDENT
) {
2686 method
.add_postcondition (parse_expression ());
2687 expect (TokenType
.EOL
);
2690 expect (TokenType
.DEDENT
);
2691 accept_terminator ();
2693 method
.add_postcondition (parse_expression ());
2694 expect_terminator ();
2699 rollback (body_location
);
2702 if (accept_block ()) {
2703 method
.body
= parse_block ();
2708 Property
parse_property_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2709 var begin
= get_location ();
2710 var readonly = false;
2712 expect (TokenType
.PROP
);
2714 var flags
= parse_member_declaration_modifiers ();
2716 readonly = accept (TokenType
.READONLY
);
2718 string id
= parse_identifier ();
2719 expect (TokenType
.COLON
);
2721 bool is_weak
= accept (TokenType
.WEAK
);
2722 var type
= parse_type (false);
2724 var prop
= new
Property (id
, type
, null, null, get_src_com (begin
));
2725 if (ModifierFlags
.PRIVATE
in flags
) {
2726 prop
.access
= SymbolAccessibility
.PRIVATE
;
2728 prop
.access
= get_access (id
);
2731 set_attributes (prop
, attrs
);
2732 if (ModifierFlags
.ABSTRACT
in flags
) {
2733 prop
.is_abstract
= true;
2735 if (ModifierFlags
.VIRTUAL
in flags
) {
2736 prop
.is_virtual
= true;
2738 if (ModifierFlags
.OVERRIDE
in flags
) {
2739 prop
.overrides
= true;
2742 if (accept (TokenType
.ASSIGN
)) {
2743 prop
.default_expression
= parse_expression ();
2747 if (accept_block ()) {
2748 expect (TokenType
.INDENT
);
2749 while (current () != TokenType
.DEDENT
) {
2750 var accessor_begin
= get_location ();
2751 parse_attributes ();
2752 if (accept (TokenType
.GET
)) {
2753 if (prop
.get_accessor
!= null) {
2754 throw new ParseError
.SYNTAX (get_error ("property get accessor already defined"));
2757 if (accept_block ()) {
2758 block
= parse_block ();
2760 prop
.get_accessor
= new
PropertyAccessor (true, false, false, block
, get_src (accessor_begin
));
2761 prop
.get_accessor
.access
= SymbolAccessibility
.PUBLIC
;
2763 bool _construct
= false;
2764 if (accept (TokenType
.SET
)) {
2766 throw new ParseError
.SYNTAX (get_error ("set block not allowed for a read only property"));
2768 _construct
= accept (TokenType
.CONSTRUCT
);
2769 } else if (accept (TokenType
.CONSTRUCT
)) {
2771 } else if (!accept (TokenType
.EOL
)) {
2772 throw new ParseError
.SYNTAX (get_error ("expected get, set, or construct"));
2775 if (prop
.set_accessor
!= null) {
2776 throw new ParseError
.SYNTAX (get_error ("property set accessor already defined"));
2780 if (accept_block ()) {
2781 block
= parse_block ();
2783 prop
.set_accessor
= new
PropertyAccessor (false, !readonly, _construct
, block
, get_src (accessor_begin
));
2784 prop
.set_accessor
.access
= SymbolAccessibility
.PUBLIC
;
2787 accept (TokenType
.EOL
);
2788 expect (TokenType
.DEDENT
);
2790 prop
.get_accessor
= new
PropertyAccessor (true, false, false, null, get_src (begin
));
2791 prop
.get_accessor
.access
= SymbolAccessibility
.PUBLIC
;
2794 prop
.set_accessor
= new
PropertyAccessor (false, true, false, null, get_src (begin
));
2795 prop
.set_accessor
.access
= SymbolAccessibility
.PUBLIC
;
2799 expect_terminator ();
2802 if (!prop
.is_abstract
&& !scanner
.source_file
.external_package
) {
2803 var needs_var
= (readonly && (prop
.get_accessor
!= null && prop
.get_accessor
.body
== null));
2806 needs_var
= (prop
.get_accessor
!= null && prop
.get_accessor
.body
== null) || (prop
.set_accessor
!= null && prop
.set_accessor
.body
== null);
2810 /* automatic property accessor body generation */
2811 var field_type
= prop
.property_type
.copy ();
2812 field_type
.value_owned
= !is_weak
;
2813 prop
.field
= new
Field ("_%s".printf (prop
.name
), field_type
, prop
.default_expression
, prop
.source_reference
);
2814 prop
.field
.access
= SymbolAccessibility
.PRIVATE
;
2821 Vala
.Signal
parse_signal_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2822 var begin
= get_location ();
2825 expect (TokenType
.EVENT
);
2826 var flags
= parse_member_declaration_modifiers ();
2827 string id
= parse_identifier ();
2830 var params
= new ArrayList
<FormalParameter
> ();
2832 expect (TokenType
.OPEN_PARENS
);
2833 if (current () != TokenType
.CLOSE_PARENS
) {
2835 var param
= parse_parameter ();
2837 } while (accept (TokenType
.COMMA
));
2839 expect (TokenType
.CLOSE_PARENS
);
2841 if (accept (TokenType
.COLON
)) {
2842 type
= parse_type ();
2844 type
= new
VoidType ();
2847 var sig
= new Vala
.Signal (id
, type
, get_src_com (begin
));
2848 if (ModifierFlags
.PRIVATE
in flags
) {
2849 sig
.access
= SymbolAccessibility
.PRIVATE
;
2851 sig
.access
= get_access (id
);
2854 if (ModifierFlags
.VIRTUAL
in flags
) {
2855 sig
.is_virtual
= true;
2858 set_attributes (sig
, attrs
);
2860 foreach (FormalParameter formal_param
in params
) {
2861 sig
.add_parameter (formal_param
);
2864 expect_terminator ();
2868 Constructor
parse_constructor_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2869 var begin
= get_location ();
2871 expect (TokenType
.INIT
);
2872 var flags
= parse_member_declaration_modifiers ();
2874 var c
= new
Constructor (get_src_com (begin
));
2875 if (ModifierFlags
.STATIC
in flags
) {
2876 c
.binding
= MemberBinding
.STATIC
;
2877 } else if (ModifierFlags
.CLASS
in flags
) {
2878 c
.binding
= MemberBinding
.CLASS
;
2882 c
.body
= parse_block ();
2886 Destructor
parse_destructor_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2887 var begin
= get_location ();
2888 expect (TokenType
.FINAL
);
2889 var d
= new
Destructor (get_src_com (begin
));
2891 d
.body
= parse_block ();
2895 Symbol
parse_struct_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2896 var begin
= get_location ();
2898 expect (TokenType
.STRUCT
);
2899 var flags
= parse_type_declaration_modifiers ();
2900 var sym
= parse_symbol_name ();
2901 var type_param_list
= parse_type_parameter_list ();
2902 var base_types
= new ArrayList
<DataType
> ();
2903 if (accept (TokenType
.COLON
)) {
2905 base_types
.add (parse_type ());
2906 } while (accept (TokenType
.COMMA
));
2908 var st
= new
Struct (sym
.name
, get_src_com (begin
));
2909 if (ModifierFlags
.PRIVATE
in flags
) {
2910 st
.access
= SymbolAccessibility
.PRIVATE
;
2912 st
.access
= get_access (sym
.name
);
2914 set_attributes (st
, attrs
);
2915 foreach (TypeParameter type_param
in type_param_list
) {
2916 st
.add_type_parameter (type_param
);
2918 foreach (DataType base_type
in base_types
) {
2919 st
.add_base_type (base_type
);
2922 expect (TokenType
.EOL
);
2924 parse_declarations (st
);
2927 while (sym
.inner
!= null) {
2929 var ns
= new
Namespace (sym
.name
, st
.source_reference
);
2930 if (result is Namespace
) {
2931 ns
.add_namespace ((Namespace
) result
);
2933 ns
.add_struct ((Struct
) result
);
2934 scanner
.source_file
.add_node (result
);
2941 void parse_struct_member (Struct st
) throws ParseError
{
2942 var sym
= parse_declaration ();
2943 if (sym is Method
) {
2944 st
.add_method ((Method
) sym
);
2945 } else if (sym is Field
) {
2946 st
.add_field ((Field
) sym
);
2947 } else if (sym is Constant
) {
2948 st
.add_constant ((Constant
) sym
);
2950 Report
.error (sym
.source_reference
, "unexpected declaration in struct");
2954 Symbol
parse_interface_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2955 var begin
= get_location ();
2957 expect (TokenType
.INTERFACE
);
2958 var flags
= parse_type_declaration_modifiers ();
2959 var sym
= parse_symbol_name ();
2960 var type_param_list
= parse_type_parameter_list ();
2961 var base_types
= new ArrayList
<DataType
> ();
2962 if (accept (TokenType
.COLON
)) {
2964 base_types
.add (parse_type ());
2965 } while (accept (TokenType
.COMMA
));
2967 var iface
= new
Interface (sym
.name
, get_src_com (begin
));
2968 if (ModifierFlags
.PRIVATE
in flags
) {
2969 iface
.access
= SymbolAccessibility
.PRIVATE
;
2971 iface
.access
= get_access (sym
.name
);
2974 set_attributes (iface
, attrs
);
2975 foreach (TypeParameter type_param
in type_param_list
) {
2976 iface
.add_type_parameter (type_param
);
2978 foreach (DataType base_type
in base_types
) {
2979 iface
.add_prerequisite (base_type
);
2983 expect (TokenType
.EOL
);
2985 parse_declarations (iface
);
2988 Symbol result
= iface
;
2989 while (sym
.inner
!= null) {
2991 var ns
= new
Namespace (sym
.name
, iface
.source_reference
);
2992 if (result is Namespace
) {
2993 ns
.add_namespace ((Namespace
) result
);
2995 ns
.add_interface ((Interface
) result
);
2996 scanner
.source_file
.add_node (result
);
3003 void parse_interface_member (Interface iface
) throws ParseError
{
3004 var sym
= parse_declaration ();
3006 iface
.add_class ((Class
) sym
);
3007 } else if (sym is Struct
) {
3008 iface
.add_struct ((Struct
) sym
);
3009 } else if (sym is Enum
) {
3010 iface
.add_enum ((Enum
) sym
);
3011 } else if (sym is Delegate
) {
3012 iface
.add_delegate ((Delegate
) sym
);
3013 } else if (sym is Method
) {
3014 iface
.add_method ((Method
) sym
);
3015 } else if (sym is Vala
.Signal
) {
3016 iface
.add_signal ((Vala
.Signal
) sym
);
3017 } else if (sym is Field
) {
3018 iface
.add_field ((Field
) sym
);
3019 } else if (sym is Property
) {
3020 iface
.add_property ((Property
) sym
);
3022 Report
.error (sym
.source_reference
, "unexpected declaration in interface");
3026 Symbol
parse_enum_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
3027 var begin
= get_location ();
3028 expect (TokenType
.ENUM
);
3029 var flags
= parse_type_declaration_modifiers ();
3031 var sym
= parse_symbol_name ();
3032 var en
= new
Enum (sym
.name
, get_src_com (begin
));
3033 if (ModifierFlags
.PRIVATE
in flags
) {
3034 en
.access
= SymbolAccessibility
.PRIVATE
;
3036 en
.access
= get_access (sym
.name
);
3038 set_attributes (en
, attrs
);
3040 expect (TokenType
.EOL
);
3041 expect (TokenType
.INDENT
);
3043 if (current () == TokenType
.DEDENT
) {
3044 // allow trailing comma
3047 var value_attrs
= parse_attributes ();
3048 var value_begin
= get_location ();
3049 string id
= parse_identifier ();
3051 var ev
= new
EnumValue (id
, get_src (value_begin
));
3052 set_attributes (ev
, value_attrs
);
3054 if (accept (TokenType
.ASSIGN
)) {
3055 ev
.value
= parse_expression ();
3058 expect (TokenType
.EOL
);
3061 expect (TokenType
.DEDENT
);
3064 while (sym
.inner
!= null) {
3066 var ns
= new
Namespace (sym
.name
, en
.source_reference
);
3067 if (result is Namespace
) {
3068 ns
.add_namespace ((Namespace
) result
);
3070 ns
.add_enum ((Enum
) result
);
3071 scanner
.source_file
.add_node (result
);
3078 Symbol
parse_errordomain_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
3079 var begin
= get_location ();
3080 expect (TokenType
.ERRORDOMAIN
);
3081 var flags
= parse_type_declaration_modifiers ();
3083 var sym
= parse_symbol_name ();
3084 var ed
= new
ErrorDomain (sym
.name
, get_src_com (begin
));
3085 if (ModifierFlags
.PRIVATE
in flags
) {
3086 ed
.access
= SymbolAccessibility
.PRIVATE
;
3088 ed
.access
= get_access (sym
.name
);
3091 set_attributes (ed
, attrs
);
3093 expect (TokenType
.EOL
);
3094 expect (TokenType
.INDENT
);
3097 if (current () == TokenType
.DEDENT
) {
3098 // allow trailing comma
3101 var code_attrs
= parse_attributes ();
3102 string id
= parse_identifier ();
3104 var ec
= new
ErrorCode (id
);
3105 set_attributes (ec
, code_attrs
);
3106 if (accept (TokenType
.ASSIGN
)) {
3107 ec
.value
= parse_expression ();
3110 accept (TokenType
.EOL
);
3114 expect (TokenType
.DEDENT
);
3117 while (sym
.inner
!= null) {
3119 var ns
= new
Namespace (sym
.name
, ed
.source_reference
);
3121 if (result is Namespace
) {
3122 ns
.add_namespace ((Namespace
) result
);
3124 ns
.add_error_domain ((ErrorDomain
) result
);
3125 scanner
.source_file
.add_node (result
);
3132 ModifierFlags
parse_type_declaration_modifiers () {
3133 ModifierFlags flags
= 0;
3135 switch (current ()) {
3136 case TokenType
.ABSTRACT
:
3138 flags
|= ModifierFlags
.ABSTRACT
;
3141 case TokenType
.EXTERN
:
3143 flags
|= ModifierFlags
.EXTERN
;
3146 case TokenType
.STATIC
:
3148 flags
|= ModifierFlags
.STATIC
;
3151 case TokenType
.PRIVATE
:
3153 flags
|= ModifierFlags
.PRIVATE
;
3162 ModifierFlags
parse_member_declaration_modifiers () {
3163 ModifierFlags flags
= 0;
3165 switch (current ()) {
3166 case TokenType
.ABSTRACT
:
3168 flags
|= ModifierFlags
.ABSTRACT
;
3170 case TokenType
.CLASS
:
3172 flags
|= ModifierFlags
.CLASS
;
3174 case TokenType
.EXTERN
:
3176 flags
|= ModifierFlags
.EXTERN
;
3178 case TokenType
.INLINE
:
3180 flags
|= ModifierFlags
.INLINE
;
3182 case TokenType
.OVERRIDE
:
3184 flags
|= ModifierFlags
.OVERRIDE
;
3186 case TokenType
.STATIC
:
3188 flags
|= ModifierFlags
.STATIC
;
3190 case TokenType
.VIRTUAL
:
3192 flags
|= ModifierFlags
.VIRTUAL
;
3194 case TokenType
.PRIVATE
:
3196 flags
|= ModifierFlags
.PRIVATE
;
3204 FormalParameter
parse_parameter () throws ParseError
{
3205 var attrs
= parse_attributes ();
3206 var begin
= get_location ();
3207 if (accept (TokenType
.ELLIPSIS
)) {
3209 return new FormalParameter
.with_ellipsis (get_src (begin
));
3212 var direction
= ParameterDirection
.IN
;
3213 if (accept (TokenType
.OUT
)) {
3214 direction
= ParameterDirection
.OUT
;
3215 } else if (accept (TokenType
.REF
)) {
3216 direction
= ParameterDirection
.REF
;
3219 string id
= parse_identifier ();
3221 expect (TokenType
.COLON
);
3224 if (direction
== ParameterDirection
.IN
) {
3225 type
= parse_type (false);
3227 type
= parse_type (true);
3230 var param
= new
FormalParameter (id
, type
, get_src (begin
));
3231 set_attributes (param
, attrs
);
3232 param
.direction
= direction
;
3233 if (accept (TokenType
.ASSIGN
)) {
3234 param
.default_expression
= parse_expression ();
3239 CreationMethod
parse_creation_method_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
3240 var begin
= get_location ();
3241 CreationMethod method
;
3243 expect (TokenType
.CONSTRUCT
);
3245 parse_member_declaration_modifiers ();
3248 if (accept (TokenType
.OPEN_PARENS
)) {
3249 /* create default name using class name */
3250 method
= new
CreationMethod (class_name
, null, get_src_com (begin
));
3252 var sym
= parse_symbol_name ();
3253 if (sym
.inner
== null) {
3255 if (sym
.name
!= class_name
) {
3256 method
= new
CreationMethod (class_name
, sym
.name
, get_src_com (begin
));
3258 method
= new
CreationMethod (sym
.name
, null, get_src_com (begin
));
3261 method
= new
CreationMethod (sym
.inner
.name
, sym
.name
, get_src_com (begin
));
3263 expect (TokenType
.OPEN_PARENS
);
3267 if (current () != TokenType
.CLOSE_PARENS
) {
3269 var param
= parse_parameter ();
3270 method
.add_parameter (param
);
3271 } while (accept (TokenType
.COMMA
));
3273 expect (TokenType
.CLOSE_PARENS
);
3274 if (accept (TokenType
.RAISES
)) {
3276 method
.add_error_type (parse_type ());
3277 } while (accept (TokenType
.COMMA
));
3279 method
.access
= SymbolAccessibility
.PUBLIC
;
3280 set_attributes (method
, attrs
);
3281 method
.binding
= MemberBinding
.STATIC
;
3283 if (accept_block ()) {
3284 method
.body
= parse_block ();
3290 Symbol
parse_delegate_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
3291 var begin
= get_location ();
3294 expect (TokenType
.DELEGATE
);
3296 var flags
= parse_member_declaration_modifiers ();
3298 var sym
= parse_symbol_name ();
3300 var type_param_list
= parse_type_parameter_list ();
3303 var params
= new ArrayList
<FormalParameter
> ();
3305 expect (TokenType
.OPEN_PARENS
);
3306 if (current () != TokenType
.CLOSE_PARENS
) {
3308 var param
= parse_parameter ();
3310 } while (accept (TokenType
.COMMA
));
3312 expect (TokenType
.CLOSE_PARENS
);
3314 if (accept (TokenType
.COLON
)) {
3315 type
= parse_type ();
3318 type
= new
VoidType ();
3321 if (accept (TokenType
.RAISES
)) {
3324 } while (accept (TokenType
.COMMA
));
3327 expect_terminator ();
3329 var d
= new
Delegate (sym
.name
, type
, get_src_com (begin
));
3330 if (ModifierFlags
.PRIVATE
in flags
) {
3331 d
.access
= SymbolAccessibility
.PRIVATE
;
3333 d
.access
= get_access (sym
.name
);
3336 set_attributes (d
, attrs
);
3338 foreach (TypeParameter type_param
in type_param_list
) {
3339 d
.add_type_parameter (type_param
);
3342 foreach (FormalParameter formal_param
in params
) {
3343 d
.add_parameter (formal_param
);
3346 if (!(ModifierFlags
.STATIC
in flags
)) {
3347 d
.has_target
= true;
3352 while (sym
.inner
!= null) {
3354 var ns
= new
Namespace (sym
.name
, d
.source_reference
);
3356 if (result is Namespace
) {
3357 ns
.add_namespace ((Namespace
) result
);
3359 ns
.add_delegate ((Delegate
) result
);
3360 scanner
.source_file
.add_node (result
);
3367 Gee
.List
<TypeParameter
> parse_type_parameter_list () throws ParseError
{
3368 var list
= new ArrayList
<TypeParameter
> ();
3369 if (accept (TokenType
.OF
)) {
3371 var begin
= get_location ();
3372 string id
= parse_identifier ();
3373 list
.add (new
TypeParameter (id
, get_src (begin
)));
3374 } while (accept (TokenType
.COMMA
));
3380 void skip_type_argument_list () throws ParseError
{
3381 if (accept (TokenType
.OF
)) {
3384 } while (accept (TokenType
.COMMA
));
3388 // try to parse type argument list
3389 Gee
.List
<DataType
>?
parse_type_argument_list (bool maybe_expression
) throws ParseError
{
3390 var begin
= get_location ();
3391 if (accept (TokenType
.OF
)) {
3392 var list
= new ArrayList
<DataType
> ();
3394 switch (current ()) {
3395 case TokenType
.VOID
:
3396 case TokenType
.DYNAMIC
:
3397 case TokenType
.WEAK
:
3398 case TokenType
.IDENTIFIER
:
3399 var type
= parse_type ();
3407 } while (accept (TokenType
.COMMA
));
3414 MemberAccess
parse_member_name () throws ParseError
{
3415 var begin
= get_location ();
3416 MemberAccess expr
= null;
3418 string id
= parse_identifier ();
3419 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (false);
3420 expr
= new
MemberAccess (expr
, id
, get_src (begin
));
3421 if (type_arg_list
!= null) {
3422 foreach (DataType type_arg
in type_arg_list
) {
3423 expr
.add_type_argument (type_arg
);
3426 } while (accept (TokenType
.DOT
));