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
);
92 public override void visit_source_file (SourceFile source_file
) {
93 if (source_file
.filename
.has_suffix (".gs")) {
94 parse_file (source_file
);
99 index
= (index
+ 1) % BUFFER_SIZE
;
102 SourceLocation begin
, end
;
103 TokenType type
= scanner
.read_token (out begin
, out end
);
104 tokens
[index
] = { type
, begin
, end
};
107 return (tokens
[index
].type
!= TokenType
.EOF
);
110 inline
void prev () {
111 index
= (index
- 1 + BUFFER_SIZE
) % BUFFER_SIZE
;
113 assert (size
<= BUFFER_SIZE
);
116 inline TokenType
current () {
117 return tokens
[index
].type
;
120 inline
bool accept (TokenType type
) {
121 if (current () == type
) {
128 inline
bool accept_separator () {
129 if (current () == TokenType
.COMMA
|| current () == TokenType
.EOL
) {
136 inline
bool accept_terminator () {
137 if (current () == TokenType
.SEMICOLON
|| current () == TokenType
.EOL
) {
144 inline
bool accept_block () {
146 bool has_term
= accept_terminator ();
148 if (accept (TokenType
.INDENT
)) {
160 void report_parse_error (ParseError e
) {
161 var begin
= get_location ();
163 Report
.error (get_src (begin
), "syntax error, " + e
.message
);
166 inline
bool expect (TokenType type
) throws ParseError
{
171 TokenType cur
= current ();
172 TokenType pre
= tokens
[index
- 1].type
;
174 throw new ParseError
.SYNTAX ("expected %s but got %s with previous %s", type
.to_string (), cur
.to_string (), pre
.to_string());
177 inline
bool expect_separator () throws ParseError
{
178 if (accept_separator ()) {
182 TokenType cur
= current ();
184 throw new ParseError
.SYNTAX ("expected line end or comma but got %s", cur
.to_string());
187 inline
bool expect_terminator () throws ParseError
{
188 if (accept_terminator ()) {
192 TokenType cur
= current ();
194 throw new ParseError
.SYNTAX ("expected line end or semicolon but got %s", cur
.to_string());
197 inline SourceLocation
get_location () {
198 return tokens
[index
].begin
;
201 string get_current_string () {
202 var token
= tokens
[index
];
203 return ((string) token
.begin
.pos
).substring (0, (int) (token
.end
.pos
- token
.begin
.pos
));
206 string get_last_string () {
207 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
208 var token
= tokens
[last_index
];
209 return ((string) token
.begin
.pos
).substring (0, (int) (token
.end
.pos
- token
.begin
.pos
));
212 SourceReference
get_src (SourceLocation begin
) {
213 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
215 return new
SourceReference (scanner
.source_file
, begin
, tokens
[last_index
].end
);
218 SourceReference
get_current_src () {
219 var token
= tokens
[index
];
220 return new
SourceReference (scanner
.source_file
, token
.begin
, token
.end
);
223 void rollback (SourceLocation location
) {
224 while (tokens
[index
].begin
.pos
!= location
.pos
) {
225 index
= (index
- 1 + BUFFER_SIZE
) % BUFFER_SIZE
;
227 if (size
> BUFFER_SIZE
) {
228 scanner
.seek (location
);
237 inline SymbolAccessibility
get_access (string s
) {
239 return SymbolAccessibility
.PRIVATE
;
242 return SymbolAccessibility
.PUBLIC
;
245 void skip_identifier () throws ParseError
{
246 // also accept keywords as identifiers where there is no conflict
247 switch (current ()) {
248 case TokenType
.ABSTRACT
:
250 case TokenType
.ASSERT
:
251 case TokenType
.ASYNC
:
252 case TokenType
.BREAK
:
253 case TokenType
.CLASS
:
254 case TokenType
.CONST
:
255 case TokenType
.CONTINUE
:
256 case TokenType
.DEDENT
:
258 case TokenType
.DEFAULT
:
259 case TokenType
.DELEGATE
:
260 case TokenType
.DELETE
:
262 case TokenType
.DOWNTO
:
263 case TokenType
.DYNAMIC
:
267 case TokenType
.ENSURES
:
268 case TokenType
.ERRORDOMAIN
:
269 case TokenType
.EVENT
:
270 case TokenType
.EXCEPT
:
271 case TokenType
.EXTERN
:
272 case TokenType
.FALSE
:
273 case TokenType
.FINAL
:
274 case TokenType
.FINALLY
:
277 case TokenType
.IDENTIFIER
:
280 case TokenType
.INDENT
:
282 case TokenType
.INLINE
:
283 case TokenType
.INTERFACE
:
284 case TokenType
.INTERNAL
:
288 case TokenType
.NAMESPACE
:
293 case TokenType
.OVERRIDE
:
294 case TokenType
.OWNED
:
296 case TokenType
.PRINT
:
297 case TokenType
.PRIVATE
:
299 case TokenType
.RAISE
:
300 case TokenType
.RAISES
:
302 case TokenType
.REQUIRES
:
303 case TokenType
.RETURN
:
304 case TokenType
.SEALED
:
306 case TokenType
.SIZEOF
:
307 case TokenType
.STATIC
:
308 case TokenType
.STRUCT
:
309 case TokenType
.SUPER
:
314 case TokenType
.TYPEOF
:
315 case TokenType
.UNOWNED
:
318 case TokenType
.VIRTUAL
:
320 case TokenType
.VOLATILE
:
323 case TokenType
.WHILE
:
324 case TokenType
.YIELD
:
327 case TokenType
.INTEGER_LITERAL
:
328 case TokenType
.REAL_LITERAL
:
329 // also accept integer and real literals
330 // as long as they contain at least one character
331 // and no decimal point
332 // for example, 2D and 3D
333 string id
= get_current_string ();
334 if (id
[id
.length
- 1].isalpha () && !("." in id
)) {
343 throw new ParseError
.SYNTAX ("expected identifier");
346 string parse_identifier () throws ParseError
{
348 return get_last_string ();
351 Expression
parse_literal () throws ParseError
{
352 var begin
= get_location ();
354 switch (current ()) {
357 return new
BooleanLiteral (true, get_src (begin
));
358 case TokenType
.FALSE
:
360 return new
BooleanLiteral (false, get_src (begin
));
361 case TokenType
.INTEGER_LITERAL
:
363 return new
IntegerLiteral (get_last_string (), get_src (begin
));
364 case TokenType
.REAL_LITERAL
:
366 return new
RealLiteral (get_last_string (), get_src (begin
));
367 case TokenType
.CHARACTER_LITERAL
:
369 // FIXME validate and unescape here and just pass unichar to CharacterLiteral
370 var lit
= new
CharacterLiteral (get_last_string (), get_src (begin
));
372 Report
.error (lit
.source_reference
, "invalid character literal");
375 case TokenType
.REGEX_LITERAL
:
377 string match_part
= get_last_string ();
378 SourceReference src_begin
= get_src (begin
);
379 expect (TokenType
.CLOSE_REGEX_LITERAL
);
380 string close_token
= get_last_string ();
381 return new
RegexLiteral ("%s/%s".printf (close_token
, match_part
), src_begin
);
382 case TokenType
.STRING_LITERAL
:
384 return new
StringLiteral (get_last_string (), get_src (begin
));
385 case TokenType
.TEMPLATE_STRING_LITERAL
:
387 return new
StringLiteral ("\"%s\"".printf (get_last_string ()), get_src (begin
));
388 case TokenType
.VERBATIM_STRING_LITERAL
:
390 string raw_string
= get_last_string ();
391 string escaped_string
= raw_string
.substring (3, raw_string
.length
- 6).escape ("");
392 return new
StringLiteral ("\"%s\"".printf (escaped_string
), get_src (begin
));
395 return new
NullLiteral (get_src (begin
));
397 throw new ParseError
.SYNTAX ("expected literal");
401 public void parse_file (SourceFile source_file
) {
402 var has_global_context
= (context
!= null);
403 if (!has_global_context
) {
404 context
= source_file
.context
;
407 scanner
= new
Scanner (source_file
);
408 scanner
.parse_file_comments ();
409 scanner
.indent_spaces
= 0;
416 var begin
= get_location ();
417 /* see if there is an indent attribute */
418 if (accept (TokenType
.OPEN_BRACKET
)) {
419 var id
= parse_identifier ();
420 if (id
== "indent") {
421 expect (TokenType
.ASSIGN
);
422 expect (TokenType
.INTEGER_LITERAL
);
423 scanner
.indent_spaces
= int.parse (get_last_string());
424 expect (TokenType
.CLOSE_BRACKET
);
425 expect (TokenType
.EOL
);
431 parse_using_directives (context
.root
);
432 parse_declarations (context
.root
, true);
433 } catch (ParseError e
) {
434 report_parse_error (e
);
438 if (!has_global_context
) {
443 void skip_symbol_name () throws ParseError
{
446 } while (accept (TokenType
.DOT
));
449 UnresolvedSymbol
parse_symbol_name () throws ParseError
{
450 var begin
= get_location ();
451 UnresolvedSymbol sym
= null;
453 string name
= parse_identifier ();
454 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
455 } while (accept (TokenType
.DOT
));
459 void skip_type () throws ParseError
{
461 accept (TokenType
.DYNAMIC
);
462 accept (TokenType
.OWNED
);
463 accept (TokenType
.UNOWNED
);
464 accept (TokenType
.WEAK
);
467 if (accept (TokenType
.ARRAY
) || accept (TokenType
.LIST
) || accept (TokenType
.DICT
)) {
468 accept (TokenType
.OF
);
471 if (accept (TokenType
.VOID
)) {
474 skip_type_argument_list ();
477 while (accept (TokenType
.OPEN_BRACKET
)) {
479 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
482 } while (accept (TokenType
.COMMA
));
483 expect (TokenType
.CLOSE_BRACKET
);
485 accept (TokenType
.OP_NEG
);
486 accept (TokenType
.INTERR
);
487 accept (TokenType
.HASH
);
491 Expression
parse_regex_literal () throws ParseError
{
492 expect (TokenType
.OPEN_REGEX_LITERAL
);
494 var expr
= parse_literal ();
499 DataType
parse_type (bool owned_by_default
, bool can_weak_ref
) throws ParseError
{
500 var begin
= get_location ();
502 List
<DataType
> type_arg_list
= null;
503 UnresolvedSymbol sym
= null;
505 bool is_dynamic
= accept (TokenType
.DYNAMIC
);
506 bool value_owned
= owned_by_default
;
508 if (owned_by_default
) {
509 if (accept (TokenType
.UNOWNED
)) {
511 } else if (accept (TokenType
.WEAK
)) {
512 if (!can_weak_ref
&& !context
.deprecated
) {
513 Report
.warning (get_src (begin
), "deprecated syntax, use `unowned` modifier");
518 value_owned
= accept (TokenType
.OWNED
);
522 bool is_array
= false;
524 if (accept (TokenType
.ARRAY
)) {
525 expect (TokenType
.OF
);
530 bool is_list
= false;
532 if (accept (TokenType
.LIST
)) {
533 expect (TokenType
.OF
);
539 bool is_dict
= false;
541 if (accept (TokenType
.DICT
)) {
542 expect (TokenType
.OF
);
549 if (!is_dynamic
&& value_owned
== owned_by_default
&& accept (TokenType
.VOID
)) {
550 type
= new
VoidType (get_src (begin
));
554 var sym_parent
= new
UnresolvedSymbol (null, "Gee", get_src (begin
));
555 sym
= new
UnresolvedSymbol (sym_parent
, "ArrayList", get_src (begin
));
556 } else if (is_dict
) {
557 var sym_parent
= new
UnresolvedSymbol (null, "Gee", get_src (begin
));
558 sym
= new
UnresolvedSymbol (sym_parent
, "HashMap", get_src (begin
));
560 sym
= parse_symbol_name ();
563 type_arg_list
= parse_type_argument_list (false);
565 type
= new UnresolvedType
.from_symbol (sym
, get_src (begin
));
566 if (type_arg_list
!= null) {
567 foreach (DataType type_arg
in type_arg_list
) {
568 type
.add_type_argument (type_arg
);
573 while (accept (TokenType
.STAR
)) {
574 type
= new
PointerType (type
, get_src (begin
));
577 if (!(type is PointerType
)) {
578 type
.nullable
= accept (TokenType
.INTERR
);
583 if (!accept (TokenType
.OPEN_BRACKET
)) {
584 type
.value_owned
= true;
585 type
= new
ArrayType (type
, 1, get_src (begin
));
586 type
.nullable
= accept (TokenType
.INTERR
);
591 while (accept (TokenType
.OPEN_BRACKET
)) {
592 bool invalid_array
= false;
596 // required for decision between expression and declaration statement
597 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
599 // only used for parsing, reject use as real type
600 invalid_array
= true;
602 } while (accept (TokenType
.COMMA
));
603 expect (TokenType
.CLOSE_BRACKET
);
605 type
.value_owned
= true;
606 var array_type
= new
ArrayType (type
, array_rank
, get_src (begin
));
607 array_type
.nullable
= accept (TokenType
.INTERR
);
609 array_type
.invalid_syntax
= invalid_array
;
616 if (!owned_by_default
) {
617 value_owned
= accept (TokenType
.HASH
);
620 if (type is PointerType
) {
624 type
.is_dynamic
= is_dynamic
;
625 type
.value_owned
= value_owned
;
629 DataType?
parse_inline_array_type (DataType? type
) throws ParseError
{
630 var begin
= get_location ();
632 // inline-allocated array
633 if (type
!= null && accept (TokenType
.OPEN_BRACKET
)) {
634 Expression array_length
= null;
636 if (current () != TokenType
.CLOSE_BRACKET
) {
637 array_length
= parse_expression ();
639 expect (TokenType
.CLOSE_BRACKET
);
641 var array_type
= new
ArrayType (type
, 1, get_src (begin
));
642 array_type
.inline_allocated
= true;
643 if (array_length
!= null) {
644 array_type
.fixed_length
= true;
645 array_type
.length
= array_length
;
647 array_type
.value_owned
= type
.value_owned
;
654 List
<Expression
> parse_argument_list () throws ParseError
{
655 var list
= new ArrayList
<Expression
> ();
656 if (current () != TokenType
.CLOSE_PARENS
) {
658 list
.add (parse_argument ());
659 } while (accept (TokenType
.COMMA
));
664 Expression
parse_argument () throws ParseError
{
665 var begin
= get_location ();
667 if (accept (TokenType
.REF
)) {
668 var inner
= parse_expression ();
669 return new
UnaryExpression (UnaryOperator
.REF
, inner
, get_src (begin
));
670 } else if (accept (TokenType
.OUT
)) {
671 var inner
= parse_expression ();
672 return new
UnaryExpression (UnaryOperator
.OUT
, inner
, get_src (begin
));
674 var expr
= parse_expression ();
675 var ma
= expr as MemberAccess
;
676 if (ma
!= null && ma
.inner
== null && accept (TokenType
.COLON
)) {
678 expr
= parse_expression ();
679 return new
NamedArgument (ma
.member_name
, expr
, get_src (begin
));
687 Expression
parse_primary_expression () throws ParseError
{
688 var begin
= get_location ();
692 switch (current ()) {
694 case TokenType
.FALSE
:
695 case TokenType
.INTEGER_LITERAL
:
696 case TokenType
.REAL_LITERAL
:
697 case TokenType
.CHARACTER_LITERAL
:
698 case TokenType
.REGEX_LITERAL
:
699 case TokenType
.STRING_LITERAL
:
700 case TokenType
.TEMPLATE_STRING_LITERAL
:
701 case TokenType
.VERBATIM_STRING_LITERAL
:
703 expr
= parse_literal ();
705 case TokenType
.ASSERT
:
706 return parse_assert_expression ();
707 case TokenType
.OPEN_BRACE
:
708 expr
= parse_initializer ();
710 case TokenType
.OPEN_PARENS
:
711 expr
= parse_tuple ();
713 case TokenType
.OPEN_REGEX_LITERAL
:
714 expr
= parse_regex_literal ();
716 case TokenType
.OPEN_TEMPLATE
:
717 expr
= parse_template ();
720 expr
= parse_this_access ();
722 case TokenType
.SUPER
:
723 expr
= parse_base_access ();
726 expr
= parse_object_or_array_creation_expression ();
728 case TokenType
.PRINT
:
729 return parse_print_expression ();
730 case TokenType
.SIZEOF
:
731 expr
= parse_sizeof_expression ();
733 case TokenType
.TYPEOF
:
734 expr
= parse_typeof_expression ();
736 case TokenType
.YIELD
:
737 expr
= parse_yield_expression ();
740 expr
= parse_simple_name ();
744 // process primary expressions that start with an inner primary expression
747 switch (current ()) {
749 expr
= parse_member_access (begin
, expr
);
751 case TokenType
.OP_PTR
:
752 expr
= parse_pointer_member_access (begin
, expr
);
754 case TokenType
.OPEN_PARENS
:
755 expr
= parse_method_call (begin
, expr
);
757 case TokenType
.OPEN_BRACKET
:
758 expr
= parse_element_access (begin
, expr
);
760 case TokenType
.OP_INC
:
761 expr
= parse_post_increment_expression (begin
, expr
);
763 case TokenType
.OP_DEC
:
764 expr
= parse_post_decrement_expression (begin
, expr
);
776 Expression
parse_simple_name () throws ParseError
{
777 var begin
= get_location ();
778 string id
= parse_identifier ();
779 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
780 var expr
= new
MemberAccess (null, id
, get_src (begin
));
781 if (type_arg_list
!= null) {
782 foreach (DataType type_arg
in type_arg_list
) {
783 expr
.add_type_argument (type_arg
);
789 Expression
parse_template () throws ParseError
{
790 var begin
= get_location ();
791 var template
= new
Template ();
793 expect (TokenType
.OPEN_TEMPLATE
);
794 while (current () != TokenType
.CLOSE_TEMPLATE
) {
795 template
.add_expression (parse_expression ());
796 expect (TokenType
.COMMA
);
798 expect (TokenType
.CLOSE_TEMPLATE
);
800 template
.source_reference
= get_src (begin
);
804 Expression
parse_tuple () throws ParseError
{
805 expect (TokenType
.OPEN_PARENS
);
806 var expr_list
= new ArrayList
<Expression
> ();
807 if (current () != TokenType
.CLOSE_PARENS
) {
809 expr_list
.add (parse_expression ());
810 } while (accept (TokenType
.COMMA
));
812 expect (TokenType
.CLOSE_PARENS
);
813 if (expr_list
.size
!= 1) {
814 var tuple
= new
Tuple ();
815 foreach (Expression expr
in expr_list
) {
816 tuple
.add_expression (expr
);
820 return expr_list
.get (0);
823 Expression
parse_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
824 expect (TokenType
.DOT
);
825 string id
= parse_identifier ();
826 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
827 var expr
= new
MemberAccess (inner
, id
, get_src (begin
));
828 if (type_arg_list
!= null) {
829 foreach (DataType type_arg
in type_arg_list
) {
830 expr
.add_type_argument (type_arg
);
836 Expression
parse_pointer_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
837 expect (TokenType
.OP_PTR
);
838 string id
= parse_identifier ();
839 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
840 var expr
= new MemberAccess
.pointer (inner
, id
, get_src (begin
));
841 if (type_arg_list
!= null) {
842 foreach (DataType type_arg
in type_arg_list
) {
843 expr
.add_type_argument (type_arg
);
850 List
<Expression
> parse_print_argument_list () throws ParseError
{
851 var list
= new ArrayList
<Expression
> ();
853 var begin
= get_location ();
855 if (current () != TokenType
.CLOSE_PARENS
) {
857 var p_expr
= parse_expression ();
861 if (p_expr
!= null) {
862 if (p_expr is StringLiteral
) {
863 var s_exp
= (StringLiteral
) p_expr
;
864 var len
= s_exp
.value
.length
;
868 var st
= s_exp
.value
.substring (0, len
-1);
872 string s
= "\"\\n\"";
873 p_expr
= new
StringLiteral (s
, get_src (begin
));
876 string s
= "\"%s\\n\"";
877 var s_exp
= new
StringLiteral (s
, get_src (begin
));
884 } while (accept (TokenType
.COMMA
));
889 Expression
parse_print_expression () throws ParseError
{
890 var begin
= get_location ();
892 expect (TokenType
.PRINT
);
893 bool parens
= accept (TokenType
.OPEN_PARENS
);
895 var expr
= new
MemberAccess (null, "print", get_src (begin
));
897 var arg_list
= parse_print_argument_list ();
900 expect (TokenType
.CLOSE_PARENS
);
903 var print_expr
= new
MethodCall (expr
, get_src (begin
));
905 foreach (Expression arg
in arg_list
) {
906 print_expr
.add_argument (arg
);
913 Expression
parse_assert_expression () throws ParseError
{
914 var begin
= get_location ();
916 expect (TokenType
.ASSERT
);
917 bool parens
= accept (TokenType
.OPEN_PARENS
);
919 var expr
= new
MemberAccess (null, "assert", get_src (begin
));
921 var arg_list
= parse_argument_list ();
924 expect (TokenType
.CLOSE_PARENS
);
927 var assert_expr
= new
MethodCall (expr
, get_src (begin
));
929 foreach (Expression arg
in arg_list
) {
930 assert_expr
.add_argument (arg
);
937 Expression
parse_method_call (SourceLocation begin
, Expression inner
) throws ParseError
{
938 expect (TokenType
.OPEN_PARENS
);
939 var arg_list
= parse_argument_list ();
940 expect (TokenType
.CLOSE_PARENS
);
942 var init_list
= parse_object_initializer ();
944 if (init_list
.size
> 0 && inner is MemberAccess
) {
945 // struct creation expression
946 var member
= (MemberAccess
) inner
;
947 member
.creation_member
= true;
949 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
950 expr
.struct_creation
= true;
951 foreach (Expression arg
in arg_list
) {
952 expr
.add_argument (arg
);
954 foreach (MemberInitializer initializer
in init_list
) {
955 expr
.add_member_initializer (initializer
);
959 var expr
= new
MethodCall (inner
, get_src (begin
));
960 foreach (Expression arg
in arg_list
) {
961 expr
.add_argument (arg
);
967 Expression
parse_element_access (SourceLocation begin
, Expression inner
) throws ParseError
{
968 expect (TokenType
.OPEN_BRACKET
);
969 var index_list
= parse_expression_list ();
970 Expression? stop
= null;
971 if (index_list
.size
== 1 && accept (TokenType
.COLON
)) {
973 stop
= parse_expression ();
975 expect (TokenType
.CLOSE_BRACKET
);
978 var expr
= new
ElementAccess (inner
, get_src (begin
));
979 foreach (Expression index
in index_list
) {
980 expr
.append_index (index
);
984 return new
SliceExpression (inner
, index_list
[0], stop
, get_src (begin
));
988 List
<Expression
> parse_expression_list () throws ParseError
{
989 var list
= new ArrayList
<Expression
> ();
991 list
.add (parse_expression ());
992 } while (accept (TokenType
.COMMA
));
996 Expression
parse_this_access () throws ParseError
{
997 var begin
= get_location ();
998 expect (TokenType
.THIS
);
999 return new
MemberAccess (null, "this", get_src (begin
));
1002 Expression
parse_base_access () throws ParseError
{
1003 var begin
= get_location ();
1004 expect (TokenType
.SUPER
);
1005 return new
BaseAccess (get_src (begin
));
1008 Expression
parse_post_increment_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
1009 expect (TokenType
.OP_INC
);
1010 return new
PostfixExpression (inner
, true, get_src (begin
));
1013 Expression
parse_post_decrement_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
1014 expect (TokenType
.OP_DEC
);
1015 return new
PostfixExpression (inner
, false, get_src (begin
));
1018 Expression
parse_object_or_array_creation_expression () throws ParseError
{
1019 var begin
= get_location ();
1020 expect (TokenType
.NEW
);
1022 if (accept (TokenType
.ARRAY
)) {
1023 expect (TokenType
.OF
);
1024 var mtype
= parse_type (true, false);
1025 var expr
= parse_array_creation_expression (begin
, mtype
);
1029 if (accept (TokenType
.LIST
)) {
1030 expect (TokenType
.OF
);
1031 var mtype
= parse_type (true, false);
1032 var expr
= parse_list_creation_expression (begin
, mtype
);
1036 if (accept (TokenType
.DICT
)) {
1037 expect (TokenType
.OF
);
1038 var mtype1
= parse_type (true, false);
1039 expect (TokenType
.COMMA
);
1040 var mtype2
= parse_type (true, false);
1041 var expr
= parse_dict_creation_expression (begin
, mtype1
, mtype2
);
1046 var member
= parse_member_name ();
1047 var expr
= parse_object_creation_expression (begin
, member
);
1052 Expression
parse_object_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
1053 member
.creation_member
= true;
1054 List
<Expression
> arg_list
;
1055 if (accept (TokenType
.OPEN_PARENS
)) {
1056 arg_list
= parse_argument_list ();
1057 expect (TokenType
.CLOSE_PARENS
);
1059 arg_list
= new ArrayList
<Expression
> ();
1062 var init_list
= parse_object_initializer ();
1064 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
1065 foreach (Expression arg
in arg_list
) {
1066 expr
.add_argument (arg
);
1068 foreach (MemberInitializer initializer
in init_list
) {
1069 expr
.add_member_initializer (initializer
);
1074 Expression
parse_array_creation_expression (SourceLocation begin
, DataType element_type
) throws ParseError
{
1075 bool size_specified
= false;
1076 List
<Expression
> size_specifier_list
= null;
1078 DataType etype
= element_type
.copy ();
1080 var has_bracket
= accept (TokenType
.OPEN_BRACKET
);
1084 // array of arrays: new T[][42]
1086 if (size_specified
) {
1087 throw new ParseError
.SYNTAX ("size of inner arrays must not be specified in array creation expression");
1090 etype
= new
ArrayType (etype
, size_specifier_list
.size
, etype
.source_reference
);
1095 size_specifier_list
= new ArrayList
<Expression
> ();
1097 Expression size
= null;
1098 if (has_bracket
&& current () != TokenType
.CLOSE_BRACKET
&& current () != TokenType
.COMMA
) {
1099 size
= parse_expression ();
1100 size_specified
= true;
1102 size_specifier_list
.add (size
);
1103 } while (accept (TokenType
.COMMA
));
1106 expect (TokenType
.CLOSE_BRACKET
);
1108 } while (accept (TokenType
.OPEN_BRACKET
));
1110 InitializerList initializer
= null;
1111 if (accept (TokenType
.ASSIGN
)) {
1112 initializer
= parse_initializer ();
1115 var expr
= new
ArrayCreationExpression (etype
, size_specifier_list
.size
, initializer
, get_src (begin
));
1116 if (size_specified
) {
1117 foreach (Expression size
in size_specifier_list
) {
1118 expr
.append_size (size
);
1125 Expression
parse_list_creation_expression (SourceLocation begin
, DataType element_type
) throws ParseError
{
1127 MemberAccess list_member
= null, parent_member
= null;
1129 parent_member
= new
MemberAccess (null, "Gee", get_src (begin
));
1130 list_member
= new
MemberAccess (parent_member
, "ArrayList", get_src (begin
));
1131 list_member
.add_type_argument (element_type
);
1133 list_member
.creation_member
= true;
1135 var expr
= new
ObjectCreationExpression (list_member
, get_src (begin
));
1139 Expression
parse_dict_creation_expression (SourceLocation begin
, DataType key_type
, DataType value_type
) throws ParseError
{
1141 MemberAccess dict_member
= null, parent_member
= null;
1143 parent_member
= new
MemberAccess (null, "Gee", get_src (begin
));
1144 dict_member
= new
MemberAccess (parent_member
, "HashMap", get_src (begin
));
1145 dict_member
.add_type_argument (key_type
);
1146 dict_member
.add_type_argument (value_type
);
1148 dict_member
.creation_member
= true;
1150 var expr
= new
ObjectCreationExpression (dict_member
, get_src (begin
));
1156 List
<MemberInitializer
> parse_object_initializer () throws ParseError
{
1157 var list
= new ArrayList
<MemberInitializer
> ();
1158 if (accept (TokenType
.OPEN_BRACE
)) {
1160 list
.add (parse_member_initializer ());
1161 } while (accept (TokenType
.COMMA
));
1162 expect (TokenType
.CLOSE_BRACE
);
1167 MemberInitializer
parse_member_initializer () throws ParseError
{
1168 var begin
= get_location ();
1169 string id
= parse_identifier ();
1170 expect (TokenType
.ASSIGN
);
1171 var expr
= parse_expression ();
1173 return new
MemberInitializer (id
, expr
, get_src (begin
));
1176 Expression
parse_yield_expression () throws ParseError
{
1177 expect (TokenType
.YIELD
);
1179 var expr
= parse_expression ();
1181 var call
= expr as MethodCall
;
1182 var object_creation
= expr as ObjectCreationExpression
;
1183 if (call
== null && object_creation
== null) {
1184 Report
.error (expr
.source_reference
, "syntax error, expected method call");
1185 throw new ParseError
.SYNTAX ("expected method call");
1189 call
.is_yield_expression
= true;
1190 } else if (object_creation
!= null) {
1191 object_creation
.is_yield_expression
= true;
1197 Expression
parse_sizeof_expression () throws ParseError
{
1198 var begin
= get_location ();
1199 expect (TokenType
.SIZEOF
);
1200 expect (TokenType
.OPEN_PARENS
);
1201 var type
= parse_type (true, false);
1202 expect (TokenType
.CLOSE_PARENS
);
1204 return new
SizeofExpression (type
, get_src (begin
));
1207 Expression
parse_typeof_expression () throws ParseError
{
1208 var begin
= get_location ();
1209 expect (TokenType
.TYPEOF
);
1210 expect (TokenType
.OPEN_PARENS
);
1211 var type
= parse_type (true, false);
1212 expect (TokenType
.CLOSE_PARENS
);
1214 return new
TypeofExpression (type
, get_src (begin
));
1217 UnaryOperator
get_unary_operator (TokenType token_type
) {
1218 switch (token_type
) {
1219 case TokenType
.PLUS
: return UnaryOperator
.PLUS
;
1220 case TokenType
.MINUS
: return UnaryOperator
.MINUS
;
1221 case TokenType
.OP_NEG
: return UnaryOperator
.LOGICAL_NEGATION
;
1222 case TokenType
.TILDE
: return UnaryOperator
.BITWISE_COMPLEMENT
;
1223 case TokenType
.OP_INC
: return UnaryOperator
.INCREMENT
;
1224 case TokenType
.OP_DEC
: return UnaryOperator
.DECREMENT
;
1225 default: return UnaryOperator
.NONE
;
1229 Expression
parse_unary_expression () throws ParseError
{
1230 var begin
= get_location ();
1231 var operator
= get_unary_operator (current ());
1232 if (operator
!= UnaryOperator
.NONE
) {
1234 var op
= parse_unary_expression ();
1235 return new
UnaryExpression (operator
, op
, get_src (begin
));
1237 switch (current ()) {
1238 case TokenType
.HASH
:
1239 if (!context
.deprecated
) {
1240 Report
.warning (get_src (begin
), "deprecated syntax, use `(owned)` cast");
1243 var op
= parse_unary_expression ();
1244 return new
ReferenceTransferExpression (op
, get_src (begin
));
1245 case TokenType
.OPEN_PARENS
:
1247 switch (current ()) {
1248 case TokenType
.OWNED
:
1251 if (accept (TokenType
.CLOSE_PARENS
)) {
1252 var op
= parse_unary_expression ();
1253 return new
ReferenceTransferExpression (op
, get_src (begin
));
1256 case TokenType
.VOID
:
1257 case TokenType
.DYNAMIC
:
1258 case TokenType
.IDENTIFIER
:
1259 case TokenType
.ARRAY
:
1260 case TokenType
.LIST
:
1261 case TokenType
.DICT
:
1262 var type
= parse_type (true, false);
1263 if (accept (TokenType
.CLOSE_PARENS
)) {
1264 // check follower to decide whether to create cast expression
1265 switch (current ()) {
1266 case TokenType
.OP_NEG
:
1267 case TokenType
.TILDE
:
1268 case TokenType
.OPEN_PARENS
:
1269 case TokenType
.TRUE
:
1270 case TokenType
.FALSE
:
1271 case TokenType
.INTEGER_LITERAL
:
1272 case TokenType
.REAL_LITERAL
:
1273 case TokenType
.CHARACTER_LITERAL
:
1274 case TokenType
.REGEX_LITERAL
:
1275 case TokenType
.STRING_LITERAL
:
1276 case TokenType
.TEMPLATE_STRING_LITERAL
:
1277 case TokenType
.VERBATIM_STRING_LITERAL
:
1278 case TokenType
.NULL
:
1279 case TokenType
.THIS
:
1280 case TokenType
.SUPER
:
1282 case TokenType
.SIZEOF
:
1283 case TokenType
.TYPEOF
:
1284 case TokenType
.IDENTIFIER
:
1285 case TokenType
.PARAMS
:
1286 case TokenType
.YIELD
:
1287 var inner
= parse_unary_expression ();
1288 return new
CastExpression (inner
, type
, get_src (begin
));
1294 case TokenType
.OP_NEG
:
1296 if (accept (TokenType
.CLOSE_PARENS
)) {
1297 // (!) non-null cast
1298 var inner
= parse_unary_expression ();
1299 return new CastExpression
.non_null (inner
, get_src (begin
));
1306 // no cast expression
1309 case TokenType
.STAR
:
1311 var op
= parse_unary_expression ();
1312 return new
PointerIndirection (op
, get_src (begin
));
1313 case TokenType
.BITWISE_AND
:
1315 var op
= parse_unary_expression ();
1316 return new
AddressofExpression (op
, get_src (begin
));
1321 var expr
= parse_primary_expression ();
1325 BinaryOperator
get_binary_operator (TokenType token_type
) {
1326 switch (token_type
) {
1327 case TokenType
.STAR
: return BinaryOperator
.MUL
;
1328 case TokenType
.DIV
: return BinaryOperator
.DIV
;
1329 case TokenType
.PERCENT
: return BinaryOperator
.MOD
;
1330 case TokenType
.PLUS
: return BinaryOperator
.PLUS
;
1331 case TokenType
.MINUS
: return BinaryOperator
.MINUS
;
1332 case TokenType
.OP_LT
: return BinaryOperator
.LESS_THAN
;
1333 case TokenType
.OP_GT
: return BinaryOperator
.GREATER_THAN
;
1334 case TokenType
.OP_LE
: return BinaryOperator
.LESS_THAN_OR_EQUAL
;
1335 case TokenType
.OP_GE
: return BinaryOperator
.GREATER_THAN_OR_EQUAL
;
1336 case TokenType
.OP_EQ
: return BinaryOperator
.EQUALITY
;
1339 if (current () == TokenType
.OP_NEG
) {
1341 return BinaryOperator
.INEQUALITY
;
1344 return BinaryOperator
.EQUALITY
;
1345 case TokenType
.OP_NE
: return BinaryOperator
.INEQUALITY
;
1346 default: return BinaryOperator
.NONE
;
1350 Expression
parse_multiplicative_expression () throws ParseError
{
1351 var begin
= get_location ();
1352 var left
= parse_unary_expression ();
1355 var operator
= get_binary_operator (current ());
1357 case BinaryOperator
.MUL
:
1358 case BinaryOperator
.DIV
:
1359 case BinaryOperator
.MOD
:
1361 var right
= parse_unary_expression ();
1362 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1372 Expression
parse_additive_expression () throws ParseError
{
1373 var begin
= get_location ();
1374 var left
= parse_multiplicative_expression ();
1377 var operator
= get_binary_operator (current ());
1379 case BinaryOperator
.PLUS
:
1380 case BinaryOperator
.MINUS
:
1382 var right
= parse_multiplicative_expression ();
1383 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1393 Expression
parse_shift_expression () throws ParseError
{
1394 var begin
= get_location ();
1395 var left
= parse_additive_expression ();
1398 switch (current ()) {
1399 case TokenType
.OP_SHIFT_LEFT
:
1401 var right
= parse_additive_expression ();
1402 left
= new
BinaryExpression (BinaryOperator
.SHIFT_LEFT
, left
, right
, get_src (begin
));
1404 // don't use OP_SHIFT_RIGHT to support >> for nested generics
1405 case TokenType
.OP_GT
:
1406 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1408 // only accept >> when there is no space between the two > signs
1409 if (current () == TokenType
.OP_GT
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1411 var right
= parse_additive_expression ();
1412 left
= new
BinaryExpression (BinaryOperator
.SHIFT_RIGHT
, left
, right
, get_src (begin
));
1426 Expression
parse_relational_expression () throws ParseError
{
1427 var begin
= get_location ();
1428 var left
= parse_shift_expression ();
1431 var operator
= get_binary_operator (current ());
1433 case BinaryOperator
.LESS_THAN
:
1434 case BinaryOperator
.LESS_THAN_OR_EQUAL
:
1435 case BinaryOperator
.GREATER_THAN_OR_EQUAL
:
1437 var right
= parse_shift_expression ();
1438 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1440 case BinaryOperator
.GREATER_THAN
:
1442 // ignore >> and >>= (two tokens due to generics)
1443 if (current () != TokenType
.OP_GT
&& current () != TokenType
.OP_GE
) {
1444 var right
= parse_shift_expression ();
1445 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1452 switch (current ()) {
1455 var type
= parse_type (true, false);
1456 left
= new
TypeCheck (left
, type
, get_src (begin
));
1460 var type
= parse_type (true, false);
1461 left
= new CastExpression
.silent (left
, type
, get_src (begin
));
1473 Expression
parse_equality_expression () throws ParseError
{
1474 var begin
= get_location ();
1475 var left
= parse_relational_expression ();
1478 var operator
= get_binary_operator (current ());
1480 case BinaryOperator
.INEQUALITY
:
1481 case BinaryOperator
.EQUALITY
:
1482 if ((operator
== BinaryOperator
.INEQUALITY
) && (current () == TokenType
.IS
)) {
1486 var right
= parse_relational_expression ();
1487 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1497 Expression
parse_and_expression () throws ParseError
{
1498 var begin
= get_location ();
1499 var left
= parse_equality_expression ();
1500 while (accept (TokenType
.BITWISE_AND
)) {
1501 var right
= parse_equality_expression ();
1502 left
= new
BinaryExpression (BinaryOperator
.BITWISE_AND
, left
, right
, get_src (begin
));
1507 Expression
parse_exclusive_or_expression () throws ParseError
{
1508 var begin
= get_location ();
1509 var left
= parse_and_expression ();
1510 while (accept (TokenType
.CARRET
)) {
1511 var right
= parse_and_expression ();
1512 left
= new
BinaryExpression (BinaryOperator
.BITWISE_XOR
, left
, right
, get_src (begin
));
1517 Expression
parse_inclusive_or_expression () throws ParseError
{
1518 var begin
= get_location ();
1519 var left
= parse_exclusive_or_expression ();
1520 while (accept (TokenType
.BITWISE_OR
)) {
1521 var right
= parse_exclusive_or_expression ();
1522 left
= new
BinaryExpression (BinaryOperator
.BITWISE_OR
, left
, right
, get_src (begin
));
1527 Expression
parse_in_expression () throws ParseError
{
1528 var begin
= get_location ();
1529 var left
= parse_inclusive_or_expression ();
1530 while (accept (TokenType
.IN
)) {
1531 var right
= parse_inclusive_or_expression ();
1532 left
= new
BinaryExpression (BinaryOperator
.IN
, left
, right
, get_src (begin
));
1537 Expression
parse_conditional_and_expression () throws ParseError
{
1538 var begin
= get_location ();
1539 var left
= parse_in_expression ();
1540 while (accept (TokenType
.OP_AND
)) {
1541 var right
= parse_in_expression ();
1542 left
= new
BinaryExpression (BinaryOperator
.AND
, left
, right
, get_src (begin
));
1547 Expression
parse_conditional_or_expression () throws ParseError
{
1548 var begin
= get_location ();
1549 var left
= parse_conditional_and_expression ();
1550 while (accept (TokenType
.OP_OR
)) {
1551 var right
= parse_conditional_and_expression ();
1552 left
= new
BinaryExpression (BinaryOperator
.OR
, left
, right
, get_src (begin
));
1557 Expression
parse_conditional_expression () throws ParseError
{
1558 var begin
= get_location ();
1559 var condition
= parse_conditional_or_expression ();
1560 if (accept (TokenType
.INTERR
)) {
1561 var true_expr
= parse_expression ();
1562 expect (TokenType
.COLON
);
1563 var false_expr
= parse_expression ();
1564 return new
ConditionalExpression (condition
, true_expr
, false_expr
, get_src (begin
));
1570 Parameter
parse_lambda_parameter () throws ParseError
{
1571 var begin
= get_location ();
1572 var direction
= ParameterDirection
.IN
;
1573 if (accept (TokenType
.OUT
)) {
1574 direction
= ParameterDirection
.OUT
;
1575 } else if (accept (TokenType
.REF
)) {
1576 direction
= ParameterDirection
.REF
;
1579 string id
= parse_identifier ();
1581 var param
= new
Parameter (id
, null, get_src (begin
));
1582 param
.direction
= direction
;
1586 Expression
parse_lambda_expression () throws ParseError
{
1587 var begin
= get_location ();
1588 List
<Parameter
> params
= new ArrayList
<Parameter
> ();
1590 expect (TokenType
.DEF
);
1592 if (accept (TokenType
.OPEN_PARENS
)) {
1593 if (current () != TokenType
.CLOSE_PARENS
) {
1595 params
.add (parse_lambda_parameter ());
1596 } while (accept (TokenType
.COMMA
));
1598 expect (TokenType
.CLOSE_PARENS
);
1600 params
.add (parse_lambda_parameter ());
1603 LambdaExpression lambda
;
1605 if (accept_block ()) {
1606 var block
= parse_block ();
1607 lambda
= new LambdaExpression
.with_statement_body (block
, get_src (begin
));
1609 var expr
= parse_expression ();
1610 lambda
= new
LambdaExpression (expr
, get_src (begin
));
1611 expect_terminator ();
1616 foreach (var param
in params
) {
1617 lambda
.add_parameter (param
);
1622 AssignmentOperator
get_assignment_operator (TokenType token_type
) {
1623 switch (token_type
) {
1624 case TokenType
.ASSIGN
: return AssignmentOperator
.SIMPLE
;
1625 case TokenType
.ASSIGN_ADD
: return AssignmentOperator
.ADD
;
1626 case TokenType
.ASSIGN_SUB
: return AssignmentOperator
.SUB
;
1627 case TokenType
.ASSIGN_BITWISE_OR
: return AssignmentOperator
.BITWISE_OR
;
1628 case TokenType
.ASSIGN_BITWISE_AND
: return AssignmentOperator
.BITWISE_AND
;
1629 case TokenType
.ASSIGN_BITWISE_XOR
: return AssignmentOperator
.BITWISE_XOR
;
1630 case TokenType
.ASSIGN_DIV
: return AssignmentOperator
.DIV
;
1631 case TokenType
.ASSIGN_MUL
: return AssignmentOperator
.MUL
;
1632 case TokenType
.ASSIGN_PERCENT
: return AssignmentOperator
.PERCENT
;
1633 case TokenType
.ASSIGN_SHIFT_LEFT
: return AssignmentOperator
.SHIFT_LEFT
;
1634 default: return AssignmentOperator
.NONE
;
1638 Expression
parse_expression_with_terminator () throws ParseError
{
1639 var expr
= parse_expression ();
1640 if (current_expr_is_lambda
) {
1641 current_expr_is_lambda
= false;
1643 expect_terminator ();
1648 Expression
parse_expression () throws ParseError
{
1649 if (current () == TokenType
.DEF
) {
1650 var lambda
= parse_lambda_expression ();
1651 current_expr_is_lambda
= true;
1654 current_expr_is_lambda
= false;
1657 var begin
= get_location ();
1658 Expression expr
= parse_conditional_expression ();
1661 var operator
= get_assignment_operator (current ());
1662 if (operator
!= AssignmentOperator
.NONE
) {
1664 var rhs
= parse_expression ();
1665 expr
= new
Assignment (expr
, rhs
, operator
, get_src (begin
));
1666 } else if (current () == TokenType
.OP_GT
) { // >>=
1667 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1669 // only accept >>= when there is no space between the two > signs
1670 if (current () == TokenType
.OP_GE
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1672 var rhs
= parse_expression ();
1673 expr
= new
Assignment (expr
, rhs
, AssignmentOperator
.SHIFT_RIGHT
, get_src (begin
));
1687 Statement
get_for_statement_type () throws ParseError
{
1689 var begin
= get_location ();
1690 bool is_foreach
= false;
1692 while (current () != TokenType
.EOL
&& current () != TokenType
.DO
) {
1694 if (accept (TokenType
.IN
)) {
1703 return parse_foreach_statement ();
1705 return parse_for_statement ();
1710 void parse_statements (Block block
) throws ParseError
{
1711 while (current () != TokenType
.DEDENT
1712 && current () != TokenType
.WHEN
1713 && current () != TokenType
.DEFAULT
) {
1715 Statement stmt
= null;
1716 bool is_decl
= false;
1717 comment
= scanner
.pop_comment ();
1718 switch (current ()) {
1720 /* skip over requires and ensures as we handled them in method declaration */
1721 case TokenType
.REQUIRES
:
1722 case TokenType
.ENSURES
:
1723 var begin
= get_location ();
1726 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
1727 while (current () != TokenType
.DEDENT
) {
1731 expect (TokenType
.DEDENT
);
1733 while (current () != TokenType
.EOL
) {
1737 expect (TokenType
.EOL
);
1740 stmt
= new
EmptyStatement (get_src (begin
));
1744 case TokenType
.INDENT
:
1745 stmt
= parse_block ();
1747 case TokenType
.SEMICOLON
:
1748 case TokenType
.PASS
:
1749 stmt
= parse_empty_statement ();
1751 case TokenType
.PRINT
:
1752 case TokenType
.ASSERT
:
1753 stmt
= parse_expression_statement ();
1756 stmt
= parse_if_statement ();
1758 case TokenType
.CASE
:
1759 stmt
= parse_switch_statement ();
1761 case TokenType
.WHILE
:
1762 stmt
= parse_while_statement ();
1765 stmt
= parse_do_statement ();
1768 stmt
= get_for_statement_type ();
1770 case TokenType
.BREAK
:
1771 stmt
= parse_break_statement ();
1773 case TokenType
.CONTINUE
:
1774 stmt
= parse_continue_statement ();
1776 case TokenType
.RETURN
:
1777 stmt
= parse_return_statement ();
1779 case TokenType
.RAISE
:
1780 stmt
= parse_throw_statement ();
1783 stmt
= parse_try_statement ();
1785 case TokenType
.LOCK
:
1786 stmt
= parse_lock_statement ();
1788 case TokenType
.DELETE
:
1789 stmt
= parse_delete_statement ();
1793 parse_type_inference_declaration (block
);
1795 case TokenType
.YIELD
:
1796 stmt
= parse_yield_statement ();
1799 case TokenType
.OP_INC
:
1800 case TokenType
.OP_DEC
:
1801 case TokenType
.SUPER
:
1802 case TokenType
.THIS
:
1803 case TokenType
.OPEN_PARENS
:
1804 case TokenType
.STAR
:
1806 stmt
= parse_expression_statement ();
1809 bool is_expr
= is_expression ();
1811 stmt
= parse_expression_statement ();
1814 parse_local_variable_declarations (block
);
1820 block
.add_statement (stmt
);
1822 } catch (ParseError e
) {
1823 report_parse_error (e
);
1824 if (recover () != RecoveryState
.STATEMENT_BEGIN
) {
1825 // beginning of next declaration or end of file reached
1826 // return what we have so far
1833 bool is_expression () throws ParseError
{
1834 var begin
= get_location ();
1836 // decide between declaration and expression statement
1838 switch (current ()) {
1839 // invocation expression
1840 case TokenType
.OPEN_PARENS
:
1841 // postfix increment
1842 case TokenType
.OP_INC
:
1843 // postfix decrement
1844 case TokenType
.OP_DEC
:
1846 case TokenType
.ASSIGN
:
1847 case TokenType
.ASSIGN_ADD
:
1848 case TokenType
.ASSIGN_BITWISE_AND
:
1849 case TokenType
.ASSIGN_BITWISE_OR
:
1850 case TokenType
.ASSIGN_BITWISE_XOR
:
1851 case TokenType
.ASSIGN_DIV
:
1852 case TokenType
.ASSIGN_MUL
:
1853 case TokenType
.ASSIGN_PERCENT
:
1854 case TokenType
.ASSIGN_SHIFT_LEFT
:
1855 case TokenType
.ASSIGN_SUB
:
1856 case TokenType
.OP_GT
: // >>=
1859 // pointer member access
1860 case TokenType
.OP_PTR
:
1869 Block
parse_embedded_statement () throws ParseError
{
1870 if (current () == TokenType
.INDENT
) {
1871 var block
= parse_block ();
1875 comment
= scanner
.pop_comment ();
1877 var block
= new
Block (get_src (get_location ()));
1878 block
.add_statement (parse_embedded_statement_without_block ());
1883 Statement
parse_embedded_statement_without_block () throws ParseError
{
1884 switch (current ()) {
1885 case TokenType
.PASS
:
1886 case TokenType
.SEMICOLON
: return parse_empty_statement ();
1887 case TokenType
.IF
: return parse_if_statement ();
1888 case TokenType
.CASE
: return parse_switch_statement ();
1889 case TokenType
.WHILE
: return parse_while_statement ();
1890 case TokenType
.DO
: return parse_do_statement ();
1891 case TokenType
.FOR
: return get_for_statement_type ();
1892 case TokenType
.BREAK
: return parse_break_statement ();
1893 case TokenType
.CONTINUE
: return parse_continue_statement ();
1894 case TokenType
.RETURN
: return parse_return_statement ();
1895 case TokenType
.YIELD
: return parse_yield_statement ();
1896 case TokenType
.RAISE
: return parse_throw_statement ();
1897 case TokenType
.TRY
: return parse_try_statement ();
1898 case TokenType
.LOCK
: return parse_lock_statement ();
1899 case TokenType
.DELETE
: return parse_delete_statement ();
1901 case TokenType
.CONST
:
1902 throw new ParseError
.SYNTAX ("embedded statement cannot be declaration ");
1903 case TokenType
.OP_INC
:
1904 case TokenType
.OP_DEC
:
1905 case TokenType
.SUPER
:
1906 case TokenType
.THIS
:
1907 case TokenType
.OPEN_PARENS
:
1908 case TokenType
.STAR
:
1910 return parse_expression_statement ();
1912 if (is_expression ()) {
1913 return parse_expression_statement ();
1915 throw new ParseError
.SYNTAX ("embedded statement cannot be declaration");
1920 Block
parse_block () throws ParseError
{
1921 var begin
= get_location ();
1922 expect (TokenType
.INDENT
);
1923 var block
= new
Block (get_src (begin
));
1924 parse_statements (block
);
1925 if (!accept (TokenType
.DEDENT
)) {
1926 // only report error if it's not a secondary error
1927 if (context
.report
.get_errors () == 0) {
1928 Report
.error (get_current_src (), "tab indentation is incorrect");
1932 block
.source_reference
.end
= get_current_src ().end
;
1937 Statement
parse_empty_statement () throws ParseError
{
1938 var begin
= get_location ();
1940 accept (TokenType
.PASS
);
1941 accept (TokenType
.SEMICOLON
);
1942 expect_terminator ();
1944 return new
EmptyStatement (get_src (begin
));
1947 void parse_type_inference_declaration (Block block
) throws ParseError
{
1948 expect (TokenType
.VAR
);
1949 bool block_var
= false;
1950 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) { block_var
= true; }
1952 var s
= parse_identifier ();
1953 var local
= parse_local_variable (null, s
, true);
1954 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1956 while ((block_var
) && (current () != TokenType
.DEDENT
));
1957 if ( block_var
) { expect (TokenType
.DEDENT
); }
1960 void parse_local_variable_declarations (Block block
) throws ParseError
{
1961 var id_list
= new ArrayList
<string> ();
1962 id_list
.add (parse_identifier ());
1963 // Allow multiple declarations
1964 while (accept (TokenType
.COMMA
)) {
1965 id_list
.add (parse_identifier ());
1968 expect (TokenType
.COLON
);
1969 DataType variable_type
= parse_type (true, true);
1970 var type
= parse_inline_array_type (variable_type
);
1972 var iterator
= id_list
.iterator();
1974 bool expect_terminator
= false;
1975 while (!expect_terminator
) {
1976 string id
= iterator
.get();
1977 DataType type_copy
= null;
1979 type_copy
= type
.copy ();
1981 if (!iterator
.next()) {
1982 expect_terminator
= true;
1984 var local
= parse_local_variable (type_copy
, id
, expect_terminator
);
1985 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1989 LocalVariable
parse_local_variable (DataType? variable_type
, string id
, bool expect_terminator
= false) throws ParseError
{
1990 var begin
= get_location ();
1991 Expression initializer
= null;
1992 if (accept (TokenType
.ASSIGN
)) {
1993 if (expect_terminator
) {
1994 initializer
= parse_expression_with_terminator ();
1996 initializer
= parse_expression ();
1998 } else if (expect_terminator
) {
1999 this
.expect_terminator();
2001 return new
LocalVariable (variable_type
, id
, initializer
, get_src (begin
));
2004 Statement
parse_expression_statement () throws ParseError
{
2005 var begin
= get_location ();
2006 var expr
= parse_expression_with_terminator ();
2007 return new
ExpressionStatement (expr
, get_src (begin
));
2010 Expression
parse_statement_expression () throws ParseError
{
2011 // invocation expression, assignment,
2012 // or pre/post increment/decrement expression
2013 var expr
= parse_expression ();
2017 Statement
parse_if_statement () throws ParseError
{
2018 var begin
= get_location ();
2020 expect (TokenType
.IF
);
2022 var condition
= parse_expression ();
2024 if (!accept (TokenType
.DO
)) {
2025 expect (TokenType
.EOL
);
2027 accept (TokenType
.EOL
);
2030 var src
= get_src (begin
);
2031 var true_stmt
= parse_embedded_statement ();
2032 Block false_stmt
= null;
2033 if (accept (TokenType
.ELSE
)) {
2034 // allow `else if' on the same line without `do'
2035 if (!accept (TokenType
.DO
) && current () != TokenType
.IF
) {
2036 expect (TokenType
.EOL
);
2038 accept (TokenType
.EOL
);
2041 false_stmt
= parse_embedded_statement ();
2043 return new
IfStatement (condition
, true_stmt
, false_stmt
, src
);
2046 Statement
parse_switch_statement () throws ParseError
{
2047 var begin
= get_location ();
2048 expect (TokenType
.CASE
);
2049 var condition
= parse_expression ();
2051 expect (TokenType
.EOL
);
2053 var stmt
= new
SwitchStatement (condition
, get_src (begin
));
2054 expect (TokenType
.INDENT
);
2055 while (current () != TokenType
.DEDENT
) {
2056 var section
= new
SwitchSection (get_src (begin
));
2058 if (accept (TokenType
.WHEN
)) {
2060 section
.add_label (new
SwitchLabel (parse_expression (), get_src (begin
)));
2062 while (accept (TokenType
.COMMA
));
2064 expect (TokenType
.DEFAULT
);
2065 section
.add_label (new SwitchLabel
.with_default (get_src (begin
)));
2068 if (!accept (TokenType
.EOL
)) {
2069 expect (TokenType
.DO
);
2072 parse_statements (section
);
2074 /* add break statement for each block */
2075 var break_stmt
= new
BreakStatement (get_src (begin
));
2076 section
.add_statement (break_stmt
);
2078 stmt
.add_section (section
);
2080 expect (TokenType
.DEDENT
);
2084 Statement
parse_while_statement () throws ParseError
{
2085 var begin
= get_location ();
2086 expect (TokenType
.WHILE
);
2087 var condition
= parse_expression ();
2089 if (!accept (TokenType
.DO
)) {
2090 expect (TokenType
.EOL
);
2092 accept (TokenType
.EOL
);
2095 var body
= parse_embedded_statement ();
2096 return new
WhileStatement (condition
, body
, get_src (begin
));
2099 Statement
parse_do_statement () throws ParseError
{
2100 var begin
= get_location ();
2101 expect (TokenType
.DO
);
2102 expect (TokenType
.EOL
);
2103 var body
= parse_embedded_statement ();
2104 expect (TokenType
.WHILE
);
2106 var condition
= parse_expression ();
2108 expect_terminator ();
2110 return new
DoStatement (body
, condition
, get_src (begin
));
2114 Statement
parse_for_statement () throws ParseError
{
2115 var begin
= get_location ();
2117 Expression initializer
= null;
2118 Expression condition
= null;
2119 Expression iterator
= null;
2123 expect (TokenType
.FOR
);
2125 switch (current ()) {
2131 bool local_is_expr
= is_expression ();
2132 is_expr
= local_is_expr
;
2137 var expr_begin
= get_location ();
2138 id
= parse_identifier ();
2139 rollback (expr_begin
);
2140 initializer
= parse_statement_expression ();
2142 block
= new
Block (get_src (begin
));
2143 DataType variable_type
;
2144 if (accept (TokenType
.VAR
)) {
2145 variable_type
= null;
2146 id
= parse_identifier ();
2148 id
= parse_identifier ();
2149 expect (TokenType
.COLON
);
2150 variable_type
= parse_type (true, true);
2153 DataType type_copy
= null;
2154 if (variable_type
!= null) {
2155 type_copy
= variable_type
.copy ();
2157 var local
= parse_local_variable (type_copy
, id
);
2159 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
2164 if (accept (TokenType
.TO
)) {
2165 /* create expression for condition and incrementing iterator */
2166 var to_begin
= get_location ();
2167 var to_src
= get_src (to_begin
);
2168 var left
= new
MemberAccess (null, id
, to_src
);
2169 var right
= parse_primary_expression ();
2171 condition
= new
BinaryExpression (BinaryOperator
.LESS_THAN_OR_EQUAL
, left
, right
, to_src
);
2173 iterator
= new
PostfixExpression (left
, true, to_src
);
2175 expect (TokenType
.DOWNTO
);
2176 var downto_begin
= get_location ();
2177 var downto_src
= get_src (downto_begin
);
2178 /* create expression for condition and decrementing iterator */
2179 var left
= new
MemberAccess (null, id
, downto_src
);
2180 var right
= parse_primary_expression ();
2182 condition
= new
BinaryExpression (BinaryOperator
.GREATER_THAN_OR_EQUAL
, left
, right
, downto_src
);
2184 iterator
= new
PostfixExpression (left
, false, downto_src
);
2187 if (!accept (TokenType
.EOL
)) {
2188 expect (TokenType
.DO
);
2191 var src
= get_src (begin
);
2192 var body
= parse_embedded_statement ();
2193 var stmt
= new
ForStatement (condition
, body
, src
);
2195 if (initializer
!= null) stmt
.add_initializer (initializer
);
2197 stmt
.add_iterator (iterator
);
2200 if (block
!= null) {
2201 block
.add_statement (stmt
);
2208 Statement
parse_foreach_statement () throws ParseError
{
2209 var begin
= get_location ();
2210 DataType type
= null;
2213 expect (TokenType
.FOR
);
2215 if (accept (TokenType
.VAR
)) {
2216 id
= parse_identifier ();
2218 id
= parse_identifier ();
2219 if (accept (TokenType
.COLON
)) {
2220 type
= parse_type (true, true);
2224 expect (TokenType
.IN
);
2225 var collection
= parse_expression ();
2226 if (!accept (TokenType
.EOL
)) {
2227 expect (TokenType
.DO
);
2229 var src
= get_src (begin
);
2230 var body
= parse_embedded_statement ();
2231 return new
ForeachStatement (type
, id
, collection
, body
, src
);
2234 Statement
parse_break_statement () throws ParseError
{
2235 var begin
= get_location ();
2236 expect (TokenType
.BREAK
);
2237 expect_terminator ();
2238 return new
BreakStatement (get_src (begin
));
2241 Statement
parse_continue_statement () throws ParseError
{
2242 var begin
= get_location ();
2243 expect (TokenType
.CONTINUE
);
2244 expect_terminator ();
2245 return new
ContinueStatement (get_src (begin
));
2248 Statement
parse_return_statement () throws ParseError
{
2249 var begin
= get_location ();
2250 expect (TokenType
.RETURN
);
2251 Expression expr
= null;
2252 if (current () != TokenType
.SEMICOLON
&& current () != TokenType
.EOL
) {
2253 expr
= parse_expression_with_terminator ();
2255 expect_terminator ();
2257 return new
ReturnStatement (expr
, get_src (begin
));
2260 Statement
parse_yield_statement () throws ParseError
{
2261 var begin
= get_location ();
2262 expect (TokenType
.YIELD
);
2263 if (current () != TokenType
.SEMICOLON
&& current () != TokenType
.EOL
&& current () != TokenType
.RETURN
) {
2265 return parse_expression_statement ();
2267 Expression expr
= null;
2268 if (accept (TokenType
.RETURN
)) {
2269 expr
= parse_expression ();
2271 expect_terminator ();
2272 return new
YieldStatement (expr
, get_src (begin
));
2275 Statement
parse_throw_statement () throws ParseError
{
2276 var begin
= get_location ();
2277 expect (TokenType
.RAISE
);
2278 var expr
= parse_expression ();
2279 expect_terminator ();
2280 return new
ThrowStatement (expr
, get_src (begin
));
2283 Statement
parse_try_statement () throws ParseError
{
2284 var begin
= get_location ();
2285 expect (TokenType
.TRY
);
2286 expect (TokenType
.EOL
);
2287 var try_block
= parse_block ();
2288 Block finally_clause
= null;
2289 var catch_clauses
= new ArrayList
<CatchClause
> ();
2290 if (current () == TokenType
.EXCEPT
) {
2291 parse_catch_clauses (catch_clauses
);
2292 if (current () == TokenType
.FINALLY
) {
2293 finally_clause
= parse_finally_clause ();
2296 finally_clause
= parse_finally_clause ();
2298 var stmt
= new
TryStatement (try_block
, finally_clause
, get_src (begin
));
2299 foreach (CatchClause clause
in catch_clauses
) {
2300 stmt
.add_catch_clause (clause
);
2305 void parse_catch_clauses (List
<CatchClause
> catch_clauses
) throws ParseError
{
2306 while (accept (TokenType
.EXCEPT
)) {
2307 var begin
= get_location ();
2308 DataType type
= null;
2310 if (!accept (TokenType
.EOL
)) {
2311 id
= parse_identifier ();
2312 expect (TokenType
.COLON
);
2313 type
= parse_type (true, true);
2314 expect (TokenType
.EOL
);
2317 var block
= parse_block ();
2318 catch_clauses
.add (new
CatchClause (type
, id
, block
, get_src (begin
)));
2322 Block
parse_finally_clause () throws ParseError
{
2323 expect (TokenType
.FINALLY
);
2325 var block
= parse_block ();
2329 Statement
parse_lock_statement () throws ParseError
{
2330 var begin
= get_location ();
2331 expect (TokenType
.LOCK
);
2332 expect (TokenType
.OPEN_PARENS
);
2333 var expr
= parse_expression ();
2334 expect (TokenType
.CLOSE_PARENS
);
2335 var stmt
= parse_embedded_statement ();
2336 return new
LockStatement (expr
, stmt
, get_src (begin
));
2339 Statement
parse_delete_statement () throws ParseError
{
2340 var begin
= get_location ();
2341 expect (TokenType
.DELETE
);
2342 var expr
= parse_expression ();
2343 expect_terminator ();
2344 return new
DeleteStatement (expr
, get_src (begin
));
2347 string parse_attribute_value () throws ParseError
{
2348 switch (current ()) {
2349 case TokenType
.NULL
:
2350 case TokenType
.TRUE
:
2351 case TokenType
.FALSE
:
2352 case TokenType
.INTEGER_LITERAL
:
2353 case TokenType
.REAL_LITERAL
:
2354 case TokenType
.STRING_LITERAL
:
2356 return get_last_string ();
2357 case TokenType
.MINUS
:
2359 switch (current ()) {
2360 case TokenType
.INTEGER_LITERAL
:
2361 case TokenType
.REAL_LITERAL
:
2363 return "-" + get_last_string ();
2365 throw new ParseError
.SYNTAX ("expected number");
2368 throw new ParseError
.SYNTAX ("expected literal");
2372 List
<Attribute
>?
parse_attributes (bool parameter
) throws ParseError
{
2373 if (current () != TokenType
.OPEN_BRACKET
) {
2376 var attrs
= new ArrayList
<Attribute
> ();
2377 while (accept (TokenType
.OPEN_BRACKET
)) {
2379 var begin
= get_location ();
2380 string id
= parse_identifier ();
2381 var attr
= new
Attribute (id
, get_src (begin
));
2382 if (accept (TokenType
.OPEN_PARENS
)) {
2383 if (current () != TokenType
.CLOSE_PARENS
) {
2385 id
= parse_identifier ();
2386 expect (TokenType
.ASSIGN
);
2387 attr
.add_argument (id
, parse_attribute_value ());
2388 } while (accept (TokenType
.COMMA
));
2390 expect (TokenType
.CLOSE_PARENS
);
2393 } while (accept (TokenType
.COMMA
));
2394 expect (TokenType
.CLOSE_BRACKET
);
2397 expect (TokenType
.EOL
);
2401 void set_attributes (CodeNode node
, List
<Attribute
>? attributes
) {
2402 if (attributes
!= null) {
2403 foreach (Attribute attr
in (List
<Attribute
>) attributes
) {
2404 if (node
.get_attribute (attr
.name
) != null) {
2405 Report
.error (attr
.source_reference
, "duplicate attribute `%s`".printf (attr
.name
));
2407 node
.attributes
.append (attr
);
2412 Symbol
parse_declaration (bool is_root
= false) throws ParseError
{
2413 comment
= scanner
.pop_comment ();
2414 var attrs
= parse_attributes (false);
2415 var begin
= get_location ();
2417 switch (current ()) {
2418 case TokenType
.CONST
:
2419 return parse_constant_declaration (attrs
);
2420 case TokenType
.CONSTRUCT
:
2421 return parse_creation_method_declaration (attrs
);
2422 case TokenType
.CLASS
:
2423 return parse_class_declaration (attrs
);
2424 case TokenType
.INIT
:
2426 return parse_main_method_declaration (attrs
);
2429 return parse_constructor_declaration (attrs
);
2430 case TokenType
.DELEGATE
:
2431 return parse_delegate_declaration (attrs
);
2433 return parse_method_declaration (attrs
);
2434 case TokenType
.ENUM
:
2435 return parse_enum_declaration (attrs
);
2436 case TokenType
.ERRORDOMAIN
:
2437 return parse_errordomain_declaration (attrs
);
2438 case TokenType
.FINAL
:
2439 return parse_destructor_declaration (attrs
);
2440 case TokenType
.INTERFACE
:
2441 return parse_interface_declaration (attrs
);
2442 case TokenType
.NAMESPACE
:
2443 return parse_namespace_declaration (attrs
);
2444 case TokenType
.PROP
:
2445 return parse_property_declaration (attrs
);
2446 case TokenType
.EVENT
:
2447 return parse_signal_declaration (attrs
);
2448 case TokenType
.STRUCT
:
2449 return parse_struct_declaration (attrs
);
2452 while (current () != TokenType
.EOL
&& current () != TokenType
.SEMICOLON
&& current () != TokenType
.EOF
) {
2453 if (current () == TokenType
.COLON
) {
2455 return parse_field_declaration (attrs
);
2465 TokenType cur
= current ();
2466 TokenType pre
= tokens
[index
-1].type
;
2468 throw new ParseError
.SYNTAX ("expected declaration but got %s with previous %s", cur
.to_string (), pre
.to_string());
2471 void parse_declarations (Symbol parent
, bool root
= false) throws ParseError
{
2473 expect (TokenType
.INDENT
);
2475 while (current () != TokenType
.DEDENT
&& current () != TokenType
.EOF
) {
2477 if (parent is Namespace
) {
2478 parse_namespace_member ((Namespace
) parent
);
2479 } else if (parent is Class
) {
2480 parse_class_member ((Class
) parent
);
2481 } else if (parent is Struct
) {
2482 parse_struct_member ((Struct
) parent
);
2483 } else if (parent is Interface
) {
2484 parse_interface_member ((Interface
) parent
);
2486 } catch (ParseError e
) {
2487 report_parse_error (e
);
2491 if (r
== RecoveryState
.STATEMENT_BEGIN
) {
2497 if (r
== RecoveryState
.EOF
) {
2503 if (!accept (TokenType
.DEDENT
)) {
2504 // only report error if it's not a secondary error
2505 if (context
.report
.get_errors () == 0) {
2506 Report
.error (get_current_src (), "expected dedent");
2512 enum RecoveryState
{
2518 RecoveryState
recover () {
2519 while (current () != TokenType
.EOF
) {
2520 switch (current ()) {
2521 case TokenType
.CLASS
:
2522 case TokenType
.CONST
:
2523 case TokenType
.CONSTRUCT
:
2524 case TokenType
.INIT
:
2526 case TokenType
.DELEGATE
:
2527 case TokenType
.ENUM
:
2528 case TokenType
.ERRORDOMAIN
:
2529 case TokenType
.FINAL
:
2530 case TokenType
.INTERFACE
:
2531 case TokenType
.NAMESPACE
:
2532 case TokenType
.PROP
:
2533 case TokenType
.EVENT
:
2534 case TokenType
.STRUCT
:
2535 return RecoveryState
.DECLARATION_BEGIN
;
2536 case TokenType
.BREAK
:
2537 case TokenType
.CASE
:
2538 case TokenType
.CONTINUE
:
2539 case TokenType
.DELETE
:
2543 case TokenType
.LOCK
:
2544 case TokenType
.RETURN
:
2545 case TokenType
.RAISE
:
2548 case TokenType
.WHILE
:
2549 case TokenType
.YIELD
:
2550 return RecoveryState
.STATEMENT_BEGIN
;
2556 return RecoveryState
.EOF
;
2559 Namespace
parse_namespace_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2560 var begin
= get_location ();
2561 expect (TokenType
.NAMESPACE
);
2562 var sym
= parse_symbol_name ();
2563 var ns
= new
Namespace (sym
.name
, get_src (begin
));
2564 if (comment
!= null) {
2565 ns
.add_comment (comment
);
2568 set_attributes (ns
, attrs
);
2569 expect (TokenType
.EOL
);
2570 parse_declarations (ns
);
2572 Namespace result
= ns
;
2573 while (sym
.inner
!= null) {
2575 ns
= new
Namespace (sym
.name
, result
.source_reference
);
2576 ns
.add_namespace ((Namespace
) result
);
2582 void parse_namespace_member (Namespace ns
) throws ParseError
{
2584 var sym
= parse_declaration ((ns
== context
.root
));
2585 if (sym is Namespace
) {
2586 ns
.add_namespace ((Namespace
) sym
);
2587 } else if (sym is Class
) {
2588 ns
.add_class ((Class
) sym
);
2589 } else if (sym is Interface
) {
2590 ns
.add_interface ((Interface
) sym
);
2591 } else if (sym is Struct
) {
2592 ns
.add_struct ((Struct
) sym
);
2593 } else if (sym is Enum
) {
2594 ns
.add_enum ((Enum
) sym
);
2595 } else if (sym is ErrorDomain
) {
2596 ns
.add_error_domain ((ErrorDomain
) sym
);
2597 } else if (sym is Delegate
) {
2598 ns
.add_delegate ((Delegate
) sym
);
2599 } else if (sym is Method
) {
2600 var method
= (Method
) sym
;
2601 if (method
.binding
== MemberBinding
.INSTANCE
) {
2602 method
.binding
= MemberBinding
.STATIC
;
2604 ns
.add_method (method
);
2605 } else if (sym is Field
) {
2606 var field
= (Field
) sym
;
2607 if (field
.binding
== MemberBinding
.INSTANCE
) {
2608 field
.binding
= MemberBinding
.STATIC
;
2610 ns
.add_field (field
);
2611 } else if (sym is Constant
) {
2612 ns
.add_constant ((Constant
) sym
);
2614 Report
.error (sym
.source_reference
, "unexpected declaration in namespace");
2619 void add_uses_clause (Namespace ns
) throws ParseError
{
2620 var begin
= get_location ();
2621 var sym
= parse_symbol_name ();
2622 var ns_ref
= new
UsingDirective (sym
, get_src (begin
));
2624 scanner
.source_file
.add_using_directive (ns_ref
);
2625 ns
.add_using_directive (ns_ref
);
2628 void parse_using_directives (Namespace ns
) throws ParseError
{
2629 while (accept (TokenType
.USES
)) {
2630 if (accept_block ()) {
2631 expect (TokenType
.INDENT
);
2633 while (current () != TokenType
.DEDENT
&& current () != TokenType
.EOF
) {
2634 add_uses_clause (ns
);
2635 expect (TokenType
.EOL
);
2638 expect (TokenType
.DEDENT
);
2641 add_uses_clause (ns
);
2642 } while (accept (TokenType
.COMMA
));
2644 expect_terminator ();
2650 Symbol
parse_class_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2651 var begin
= get_location ();
2652 expect (TokenType
.CLASS
);
2654 var flags
= parse_type_declaration_modifiers ();
2656 var sym
= parse_symbol_name ();
2657 var type_param_list
= parse_type_parameter_list ();
2658 var base_types
= new ArrayList
<DataType
> ();
2659 if (accept (TokenType
.COLON
)) {
2660 var type1
= parse_type (true, false);
2661 base_types
.add (type1
);
2663 if (accept (TokenType
.IMPLEMENTS
)) {
2665 var type2
= parse_type (true, true);
2666 base_types
.add (type2
);
2667 } while (accept (TokenType
.COMMA
));
2671 accept (TokenType
.EOL
);
2673 var cl
= new
Class (sym
.name
, get_src (begin
), comment
);
2675 if (ModifierFlags
.PRIVATE
in flags
) {
2676 cl
.access
= SymbolAccessibility
.PRIVATE
;
2678 /* class must always be Public unless its name starts with underscore */
2679 if (sym
.name
[0] == '_') {
2680 cl
.access
= SymbolAccessibility
.PRIVATE
;
2682 cl
.access
= SymbolAccessibility
.PUBLIC
;
2686 if (ModifierFlags
.ABSTRACT
in flags
) {
2687 cl
.is_abstract
= true;
2689 set_attributes (cl
, attrs
);
2690 foreach (TypeParameter type_param
in type_param_list
) {
2691 cl
.add_type_parameter (type_param
);
2693 foreach (DataType base_type
in base_types
) {
2694 cl
.add_base_type (base_type
);
2697 class_name
= cl
.name
;
2699 parse_declarations (cl
);
2701 // ensure there is always a default construction method
2702 if (scanner
.source_file
.file_type
== SourceFileType
.SOURCE
2703 && cl
.default_construction_method
== null) {
2704 var m
= new
CreationMethod (cl
.name
, null, cl
.source_reference
);
2705 m
.access
= SymbolAccessibility
.PUBLIC
;
2706 m
.body
= new
Block (cl
.source_reference
);
2711 while (sym
.inner
!= null) {
2713 var ns
= new
Namespace (sym
.name
, cl
.source_reference
);
2714 if (result is Namespace
) {
2715 ns
.add_namespace ((Namespace
) result
);
2717 ns
.add_class ((Class
) result
);
2724 void parse_class_member (Class cl
) throws ParseError
{
2725 var sym
= parse_declaration ();
2727 cl
.add_class ((Class
) sym
);
2728 } else if (sym is Struct
) {
2729 cl
.add_struct ((Struct
) sym
);
2730 } else if (sym is Enum
) {
2731 cl
.add_enum ((Enum
) sym
);
2732 } else if (sym is Delegate
) {
2733 cl
.add_delegate ((Delegate
) sym
);
2734 } else if (sym is Method
) {
2735 cl
.add_method ((Method
) sym
);
2736 } else if (sym is Vala
.Signal
) {
2737 cl
.add_signal ((Vala
.Signal
) sym
);
2738 } else if (sym is Field
) {
2739 cl
.add_field ((Field
) sym
);
2740 } else if (sym is Constant
) {
2741 cl
.add_constant ((Constant
) sym
);
2742 } else if (sym is Property
) {
2743 cl
.add_property ((Property
) sym
);
2744 } else if (sym is Constructor
) {
2745 var c
= (Constructor
) sym
;
2746 if (c
.binding
== MemberBinding
.INSTANCE
) {
2747 if (cl
.constructor
!= null) {
2748 Report
.error (c
.source_reference
, "class already contains a constructor");
2751 } else if (c
.binding
== MemberBinding
.CLASS
) {
2752 if (cl
.class_constructor
!= null) {
2753 Report
.error (c
.source_reference
, "class already contains a class constructor");
2755 cl
.class_constructor
= c
;
2757 if (cl
.static_constructor
!= null) {
2758 Report
.error (c
.source_reference
, "class already contains a static constructor");
2760 cl
.static_constructor
= c
;
2763 } else if (sym is Destructor
) {
2764 var d
= (Destructor
) sym
;
2765 if (d
.binding
== MemberBinding
.STATIC
) {
2766 if (cl
.static_destructor
!= null) {
2767 Report
.error (d
.source_reference
, "class already contains a static destructor");
2769 cl
.static_destructor
= (Destructor
) d
;
2770 } else if (d
.binding
== MemberBinding
.CLASS
) {
2771 if (cl
.class_destructor
!= null) {
2772 Report
.error (d
.source_reference
, "class already contains a class destructor");
2774 cl
.class_destructor
= (Destructor
) d
;
2776 if (cl
.destructor
!= null) {
2777 Report
.error (d
.source_reference
, "class already contains a destructor");
2779 cl
.destructor
= (Destructor
) d
;
2783 Report
.error (sym
.source_reference
, "unexpected declaration in class");
2787 Constant
parse_constant_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2788 var begin
= get_location ();
2790 expect (TokenType
.CONST
);
2792 var flags
= parse_member_declaration_modifiers ();
2794 string id
= parse_identifier ();
2796 expect (TokenType
.COLON
);
2797 var type
= parse_type (false, false);
2798 type
= parse_inline_array_type (type
);
2800 Expression initializer
= null;
2801 if (accept (TokenType
.ASSIGN
)) {
2802 initializer
= parse_expression ();
2804 expect_terminator ();
2806 // constant arrays don't own their element
2807 var array_type
= type as ArrayType
;
2808 if (array_type
!= null) {
2809 array_type
.element_type
.value_owned
= false;
2812 var c
= new
Constant (id
, type
, initializer
, get_src (begin
), comment
);
2813 c
.access
= get_access (id
);
2815 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2818 if (ModifierFlags
.NEW
in flags
) {
2822 set_attributes (c
, attrs
);
2824 if (ModifierFlags
.STATIC
in flags
) {
2825 Report
.warning (c
.source_reference
, "the modifier `static' is not applicable to constants");
2831 Field
parse_field_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2832 var begin
= get_location ();
2833 string id
= parse_identifier ();
2834 expect (TokenType
.COLON
);
2836 var flags
= parse_member_declaration_modifiers ();
2838 var type
= parse_type (true, true);
2840 type
= parse_inline_array_type (type
);
2842 var f
= new
Field (id
, type
, null, get_src (begin
), comment
);
2844 if (ModifierFlags
.ABSTRACT
in flags
|| ModifierFlags
.VIRTUAL
in flags
|| ModifierFlags
.OVERRIDE
in flags
) {
2845 Report
.error (f
.source_reference
, "abstract, virtual, and override modifiers are not applicable to fields");
2848 if (ModifierFlags
.PRIVATE
in flags
) {
2849 f
.access
= SymbolAccessibility
.PRIVATE
;
2851 f
.access
= get_access (id
);
2854 set_attributes (f
, attrs
);
2856 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2859 if (ModifierFlags
.NEW
in flags
) {
2863 if (accept (TokenType
.ASSIGN
)) {
2864 f
.initializer
= parse_expression ();
2867 if (ModifierFlags
.STATIC
in flags
) {
2868 f
.binding
= MemberBinding
.STATIC
;
2869 } else if (ModifierFlags
.CLASS
in flags
) {
2870 f
.binding
= MemberBinding
.CLASS
;
2873 expect_terminator ();
2878 InitializerList
parse_initializer () throws ParseError
{
2879 var begin
= get_location ();
2880 if (!accept (TokenType
.OPEN_PARENS
)) {
2881 expect (TokenType
.OPEN_BRACE
);
2883 var initializer
= new
InitializerList (get_src (begin
));
2884 if (current () != TokenType
.DEDENT
) {
2886 var init
= parse_argument ();
2887 initializer
.append (init
);
2888 } while (accept (TokenType
.COMMA
));
2890 if (!accept (TokenType
.CLOSE_PARENS
)) {
2891 expect (TokenType
.CLOSE_BRACE
);
2899 Method
parse_main_method_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2901 var begin
= get_location ();
2902 DataType type
= new
VoidType ();
2903 expect (TokenType
.INIT
);
2905 var method
= new
Method (id
, type
, get_src (begin
), comment
);
2906 method
.access
= SymbolAccessibility
.PUBLIC
;
2908 set_attributes (method
, attrs
);
2910 method
.binding
= MemberBinding
.STATIC
;
2912 var sym
= new
UnresolvedSymbol (null, "string", get_src (begin
));
2913 type
= new UnresolvedType
.from_symbol (sym
, get_src (begin
));
2914 type
.value_owned
= true;
2915 type
= new
ArrayType (type
, 1, get_src (begin
));
2916 type
.nullable
= false;
2918 var param
= new
Parameter ("args", type
, get_src (begin
));
2919 method
.add_parameter (param
);
2922 expect (TokenType
.EOL
);
2924 if (accept_block ()) {
2925 method
.body
= parse_block ();
2931 Method
parse_method_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2932 var begin
= get_location ();
2933 DataType type
= new
VoidType ();
2934 expect (TokenType
.DEF
);
2935 var flags
= parse_member_declaration_modifiers ();
2937 string id
= parse_identifier ();
2939 var params
= new ArrayList
<Parameter
> ();
2940 expect (TokenType
.OPEN_PARENS
);
2942 if (current () != TokenType
.CLOSE_PARENS
) {
2944 var param
= parse_parameter ();
2946 } while (accept (TokenType
.COMMA
));
2949 expect (TokenType
.CLOSE_PARENS
);
2952 /* deal with return value */
2953 if (accept (TokenType
.COLON
)) {
2954 type
= parse_type (true, false);
2957 var type_param_list
= parse_type_parameter_list ();
2959 var method
= new
Method (id
, type
, get_src (begin
), comment
);
2960 if (ModifierFlags
.PRIVATE
in flags
) {
2961 method
.access
= SymbolAccessibility
.PRIVATE
;
2963 method
.access
= get_access (id
);
2967 set_attributes (method
, attrs
);
2969 foreach (TypeParameter type_param
in type_param_list
) {
2970 method
.add_type_parameter (type_param
);
2974 foreach (Parameter param
in params
) {
2975 method
.add_parameter (param
);
2978 if (accept (TokenType
.RAISES
)) {
2980 method
.add_error_type (parse_type (true, false));
2981 } while (accept (TokenType
.COMMA
));
2985 if (ModifierFlags
.STATIC
in flags
|| id
== "main") {
2986 method
.binding
= MemberBinding
.STATIC
;
2987 } else if (ModifierFlags
.CLASS
in flags
) {
2988 method
.binding
= MemberBinding
.CLASS
;
2990 if (ModifierFlags
.ASYNC
in flags
) {
2991 method
.coroutine
= true;
2994 if (ModifierFlags
.NEW
in flags
) {
2995 method
.hides
= true;
2998 if (method
.binding
== MemberBinding
.INSTANCE
) {
2999 if (ModifierFlags
.ABSTRACT
in flags
) {
3000 method
.is_abstract
= true;
3002 if (ModifierFlags
.VIRTUAL
in flags
) {
3003 method
.is_virtual
= true;
3005 if (ModifierFlags
.OVERRIDE
in flags
) {
3006 method
.overrides
= true;
3008 if ((method
.is_abstract
&& method
.is_virtual
)
3009 || (method
.is_abstract
&& method
.overrides
)
3010 || (method
.is_virtual
&& method
.overrides
)) {
3011 throw new ParseError
.SYNTAX ("only one of `abstract', `virtual', or `override' may be specified");
3014 if (ModifierFlags
.ABSTRACT
in flags
3015 || ModifierFlags
.VIRTUAL
in flags
3016 || ModifierFlags
.OVERRIDE
in flags
) {
3017 throw new ParseError
.SYNTAX ("the modifiers `abstract', `virtual', and `override' are not valid for static methods");
3021 if (ModifierFlags
.INLINE
in flags
) {
3022 method
.is_inline
= true;
3024 if (ModifierFlags
.EXTERN
in flags
) {
3025 method
.external
= true;
3028 expect (TokenType
.EOL
);
3030 var body_location
= get_location ();
3033 /* "requires" and "ensures" if present will be at start of the method body */
3034 if (accept (TokenType
.INDENT
)) {
3035 if (accept (TokenType
.REQUIRES
)) {
3037 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
3038 while (current() != TokenType
.DEDENT
) {
3039 method
.add_precondition (parse_expression ());
3040 expect (TokenType
.EOL
);
3043 expect (TokenType
.DEDENT
);
3044 accept_terminator ();
3047 method
.add_precondition (parse_expression ());
3048 expect_terminator ();
3054 if (accept (TokenType
.ENSURES
)) {
3055 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
3056 while (current() != TokenType
.DEDENT
) {
3057 method
.add_postcondition (parse_expression ());
3058 expect (TokenType
.EOL
);
3061 expect (TokenType
.DEDENT
);
3062 accept_terminator ();
3064 method
.add_postcondition (parse_expression ());
3065 expect_terminator ();
3070 rollback (body_location
);
3073 if (accept_block ()) {
3074 method
.body
= parse_block ();
3075 } else if (scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3076 method
.external
= true;
3081 Property
parse_property_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3082 var begin
= get_location ();
3083 var readonly = false;
3085 expect (TokenType
.PROP
);
3087 var flags
= parse_member_declaration_modifiers ();
3089 readonly = accept (TokenType
.READONLY
);
3091 string id
= parse_identifier ();
3092 expect (TokenType
.COLON
);
3094 var type
= parse_type (true, true);
3096 var prop
= new
Property (id
, type
, null, null, get_src (begin
), comment
);
3097 if (ModifierFlags
.PRIVATE
in flags
) {
3098 prop
.access
= SymbolAccessibility
.PRIVATE
;
3100 prop
.access
= get_access (id
);
3103 set_attributes (prop
, attrs
);
3105 if (ModifierFlags
.STATIC
in flags
) {
3106 prop
.binding
= MemberBinding
.STATIC
;
3107 } else if (ModifierFlags
.CLASS
in flags
) {
3108 prop
.binding
= MemberBinding
.CLASS
;
3110 if (ModifierFlags
.ABSTRACT
in flags
) {
3111 prop
.is_abstract
= true;
3113 if (ModifierFlags
.VIRTUAL
in flags
) {
3114 prop
.is_virtual
= true;
3116 if (ModifierFlags
.OVERRIDE
in flags
) {
3117 prop
.overrides
= true;
3120 if (ModifierFlags
.NEW
in flags
) {
3123 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3124 prop
.external
= true;
3127 if (ModifierFlags
.ASYNC
in flags
) {
3128 Report
.error (prop
.source_reference
, "async properties are not supported yet");
3131 if (accept (TokenType
.ASSIGN
)) {
3132 prop
.initializer
= parse_expression ();
3136 if (accept_block ()) {
3137 expect (TokenType
.INDENT
);
3138 while (current () != TokenType
.DEDENT
) {
3139 var accessor_begin
= get_location ();
3140 var attribs
= parse_attributes (false);
3142 var value_type
= type
.copy ();
3143 value_type
.value_owned
= accept (TokenType
.OWNED
);
3145 if (accept (TokenType
.GET
)) {
3146 if (prop
.get_accessor
!= null) {
3147 throw new ParseError
.SYNTAX ("property get accessor already defined");
3150 if (accept_block ()) {
3151 block
= parse_block ();
3152 prop
.external
= false;
3154 prop
.get_accessor
= new
PropertyAccessor (true, false, false, value_type
, block
, get_src (accessor_begin
));
3155 set_attributes (prop
.get_accessor
, attribs
);
3156 prop
.get_accessor
.access
= SymbolAccessibility
.PUBLIC
;
3158 bool _construct
= false;
3159 if (accept (TokenType
.SET
)) {
3161 throw new ParseError
.SYNTAX ("set block not allowed for a read only property");
3163 _construct
= accept (TokenType
.CONSTRUCT
);
3164 } else if (accept (TokenType
.CONSTRUCT
)) {
3166 } else if (!accept (TokenType
.EOL
)) {
3167 throw new ParseError
.SYNTAX ("expected get, set, or construct");
3170 if (prop
.set_accessor
!= null) {
3171 throw new ParseError
.SYNTAX ("property set accessor already defined");
3175 if (accept_block ()) {
3176 block
= parse_block ();
3177 prop
.external
= false;
3179 prop
.set_accessor
= new
PropertyAccessor (false, !readonly, _construct
, value_type
, block
, get_src (accessor_begin
));
3180 set_attributes (prop
.set_accessor
, attribs
);
3181 prop
.set_accessor
.access
= SymbolAccessibility
.PUBLIC
;
3184 accept (TokenType
.EOL
);
3185 expect (TokenType
.DEDENT
);
3187 var value_type
= type
.copy ();
3188 value_type
.value_owned
= false;
3190 prop
.get_accessor
= new
PropertyAccessor (true, false, false, value_type
, null, get_src (begin
));
3191 prop
.get_accessor
.access
= SymbolAccessibility
.PUBLIC
;
3194 value_type
= type
.copy ();
3195 value_type
.value_owned
= false;
3197 prop
.set_accessor
= new
PropertyAccessor (false, true, false, value_type
, null, get_src (begin
));
3198 prop
.set_accessor
.access
= SymbolAccessibility
.PUBLIC
;
3202 expect_terminator ();
3205 if (!prop
.is_abstract
&& scanner
.source_file
.file_type
== SourceFileType
.SOURCE
) {
3206 var needs_var
= (readonly && (prop
.get_accessor
!= null && prop
.get_accessor
.body
== null));
3209 needs_var
= (prop
.get_accessor
!= null && prop
.get_accessor
.body
== null) || (prop
.set_accessor
!= null && prop
.set_accessor
.body
== null);
3213 /* automatic property accessor body generation */
3214 var variable_type
= prop
.property_type
.copy ();
3215 prop
.field
= new
Field ("_%s".printf (prop
.name
), variable_type
, prop
.initializer
, prop
.source_reference
);
3216 prop
.field
.access
= SymbolAccessibility
.PRIVATE
;
3217 prop
.field
.binding
= prop
.binding
;
3224 Vala
.Signal
parse_signal_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3225 var begin
= get_location ();
3228 expect (TokenType
.EVENT
);
3229 var flags
= parse_member_declaration_modifiers ();
3230 string id
= parse_identifier ();
3233 var params
= new ArrayList
<Parameter
> ();
3235 expect (TokenType
.OPEN_PARENS
);
3236 if (current () != TokenType
.CLOSE_PARENS
) {
3238 var param
= parse_parameter ();
3240 } while (accept (TokenType
.COMMA
));
3242 expect (TokenType
.CLOSE_PARENS
);
3244 if (accept (TokenType
.COLON
)) {
3245 type
= parse_type (true, false);
3247 type
= new
VoidType ();
3250 var sig
= new Vala
.Signal (id
, type
, get_src (begin
), comment
);
3251 if (ModifierFlags
.PRIVATE
in flags
) {
3252 sig
.access
= SymbolAccessibility
.PRIVATE
;
3254 sig
.access
= get_access (id
);
3257 if (ModifierFlags
.VIRTUAL
in flags
) {
3258 sig
.is_virtual
= true;
3260 if (ModifierFlags
.NEW
in flags
) {
3264 if (ModifierFlags
.STATIC
in flags
) {
3265 throw new ParseError
.SYNTAX ("`static' modifier not allowed on signals");
3266 } else if (ModifierFlags
.CLASS
in flags
) {
3267 throw new ParseError
.SYNTAX ("`class' modifier not allowed on signals");
3270 set_attributes (sig
, attrs
);
3272 foreach (Parameter formal_param
in params
) {
3273 sig
.add_parameter (formal_param
);
3276 if (!accept_terminator ()) {
3277 sig
.body
= parse_block ();
3282 Constructor
parse_constructor_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3283 var begin
= get_location ();
3285 expect (TokenType
.INIT
);
3286 var flags
= parse_member_declaration_modifiers ();
3288 var c
= new
Constructor (get_src (begin
));
3289 if (ModifierFlags
.STATIC
in flags
) {
3290 c
.binding
= MemberBinding
.STATIC
;
3291 } else if (ModifierFlags
.CLASS
in flags
) {
3292 c
.binding
= MemberBinding
.CLASS
;
3296 c
.body
= parse_block ();
3300 Destructor
parse_destructor_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3301 var begin
= get_location ();
3302 expect (TokenType
.FINAL
);
3303 var d
= new
Destructor (get_src (begin
));
3305 d
.body
= parse_block ();
3309 Symbol
parse_struct_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3310 var begin
= get_location ();
3312 expect (TokenType
.STRUCT
);
3313 var flags
= parse_type_declaration_modifiers ();
3314 var sym
= parse_symbol_name ();
3315 var type_param_list
= parse_type_parameter_list ();
3316 DataType base_type
= null;
3317 if (accept (TokenType
.COLON
)) {
3318 base_type
= parse_type (true, false);
3321 var st
= new
Struct (sym
.name
, get_src (begin
), comment
);
3322 if (ModifierFlags
.PRIVATE
in flags
) {
3323 st
.access
= SymbolAccessibility
.PRIVATE
;
3325 st
.access
= get_access (sym
.name
);
3327 set_attributes (st
, attrs
);
3328 foreach (TypeParameter type_param
in type_param_list
) {
3329 st
.add_type_parameter (type_param
);
3331 if (base_type
!= null) {
3332 st
.base_type
= base_type
;
3335 expect (TokenType
.EOL
);
3337 parse_declarations (st
);
3340 while (sym
.inner
!= null) {
3342 var ns
= new
Namespace (sym
.name
, st
.source_reference
);
3343 if (result is Namespace
) {
3344 ns
.add_namespace ((Namespace
) result
);
3346 ns
.add_struct ((Struct
) result
);
3353 void parse_struct_member (Struct st
) throws ParseError
{
3354 var sym
= parse_declaration ();
3355 if (sym is Method
) {
3356 st
.add_method ((Method
) sym
);
3357 } else if (sym is Field
) {
3358 st
.add_field ((Field
) sym
);
3359 } else if (sym is Constant
) {
3360 st
.add_constant ((Constant
) sym
);
3361 } else if (sym is Property
) {
3362 st
.add_property ((Property
) sym
);
3364 Report
.error (sym
.source_reference
, "unexpected declaration in struct");
3368 Symbol
parse_interface_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3369 var begin
= get_location ();
3371 expect (TokenType
.INTERFACE
);
3372 var flags
= parse_type_declaration_modifiers ();
3373 var sym
= parse_symbol_name ();
3374 var type_param_list
= parse_type_parameter_list ();
3375 var base_types
= new ArrayList
<DataType
> ();
3376 if (accept (TokenType
.COLON
)) {
3378 var type
= parse_type (true, false);
3379 base_types
.add (type
);
3380 } while (accept (TokenType
.COMMA
));
3383 var iface
= new
Interface (sym
.name
, get_src (begin
), comment
);
3384 if (ModifierFlags
.PRIVATE
in flags
) {
3385 iface
.access
= SymbolAccessibility
.PRIVATE
;
3387 iface
.access
= get_access (sym
.name
);
3389 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3390 iface
.external
= true;
3392 set_attributes (iface
, attrs
);
3393 foreach (TypeParameter type_param
in type_param_list
) {
3394 iface
.add_type_parameter (type_param
);
3396 foreach (DataType base_type
in base_types
) {
3397 iface
.add_prerequisite (base_type
);
3401 expect (TokenType
.EOL
);
3403 parse_declarations (iface
);
3406 Symbol result
= iface
;
3407 while (sym
.inner
!= null) {
3409 var ns
= new
Namespace (sym
.name
, iface
.source_reference
);
3410 if (result is Namespace
) {
3411 ns
.add_namespace ((Namespace
) result
);
3413 ns
.add_interface ((Interface
) result
);
3420 void parse_interface_member (Interface iface
) throws ParseError
{
3421 var sym
= parse_declaration ();
3423 iface
.add_class ((Class
) sym
);
3424 } else if (sym is Struct
) {
3425 iface
.add_struct ((Struct
) sym
);
3426 } else if (sym is Enum
) {
3427 iface
.add_enum ((Enum
) sym
);
3428 } else if (sym is Delegate
) {
3429 iface
.add_delegate ((Delegate
) sym
);
3430 } else if (sym is Method
) {
3431 iface
.add_method ((Method
) sym
);
3432 } else if (sym is Vala
.Signal
) {
3433 iface
.add_signal ((Vala
.Signal
) sym
);
3434 } else if (sym is Field
) {
3435 iface
.add_field ((Field
) sym
);
3436 } else if (sym is Constant
) {
3437 iface
.add_constant ((Constant
) sym
);
3438 } else if (sym is Property
) {
3439 iface
.add_property ((Property
) sym
);
3441 Report
.error (sym
.source_reference
, "unexpected declaration in interface");
3445 Symbol
parse_enum_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3446 var begin
= get_location ();
3447 expect (TokenType
.ENUM
);
3448 var flags
= parse_type_declaration_modifiers ();
3450 var sym
= parse_symbol_name ();
3451 var en
= new
Enum (sym
.name
, get_src (begin
), comment
);
3452 if (ModifierFlags
.PRIVATE
in flags
) {
3453 en
.access
= SymbolAccessibility
.PRIVATE
;
3455 en
.access
= get_access (sym
.name
);
3457 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3460 set_attributes (en
, attrs
);
3462 expect (TokenType
.EOL
);
3463 expect (TokenType
.INDENT
);
3465 if (current () == TokenType
.DEDENT
&& en
.get_values ().size
> 0) {
3466 // allow trailing comma
3469 var value_attrs
= parse_attributes (false);
3470 var value_begin
= get_location ();
3471 string id
= parse_identifier ();
3472 comment
= scanner
.pop_comment ();
3474 Expression value
= null;
3475 if (accept (TokenType
.ASSIGN
)) {
3476 value
= parse_expression ();
3479 var ev
= new
EnumValue (id
, value
, get_src (value_begin
), comment
);
3480 ev
.access
= SymbolAccessibility
.PUBLIC
;
3481 set_attributes (ev
, value_attrs
);
3484 if (expect_separator ()) {
3485 accept (TokenType
.EOL
);
3489 expect (TokenType
.DEDENT
);
3492 while (sym
.inner
!= null) {
3494 var ns
= new
Namespace (sym
.name
, en
.source_reference
);
3495 if (result is Namespace
) {
3496 ns
.add_namespace ((Namespace
) result
);
3498 ns
.add_enum ((Enum
) result
);
3505 Symbol
parse_errordomain_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3506 var begin
= get_location ();
3507 expect (TokenType
.ERRORDOMAIN
);
3508 var flags
= parse_type_declaration_modifiers ();
3510 var sym
= parse_symbol_name ();
3511 var ed
= new
ErrorDomain (sym
.name
, get_src (begin
), comment
);
3512 if (ModifierFlags
.PRIVATE
in flags
) {
3513 ed
.access
= SymbolAccessibility
.PRIVATE
;
3515 ed
.access
= get_access (sym
.name
);
3518 set_attributes (ed
, attrs
);
3520 expect (TokenType
.EOL
);
3521 expect (TokenType
.INDENT
);
3524 if (current () == TokenType
.DEDENT
&& ed
.get_codes ().size
> 0) {
3525 // allow trailing comma
3528 var code_attrs
= parse_attributes (false);
3529 var code_begin
= get_location ();
3530 string id
= parse_identifier ();
3531 comment
= scanner
.pop_comment ();
3532 var ec
= new
ErrorCode (id
, get_src (code_begin
), comment
);
3533 set_attributes (ec
, code_attrs
);
3534 if (accept (TokenType
.ASSIGN
)) {
3535 ec
.value
= parse_expression ();
3538 accept (TokenType
.EOL
);
3542 expect (TokenType
.DEDENT
);
3545 while (sym
.inner
!= null) {
3547 var ns
= new
Namespace (sym
.name
, ed
.source_reference
);
3549 if (result is Namespace
) {
3550 ns
.add_namespace ((Namespace
) result
);
3552 ns
.add_error_domain ((ErrorDomain
) result
);
3559 ModifierFlags
parse_type_declaration_modifiers () {
3560 ModifierFlags flags
= 0;
3562 switch (current ()) {
3563 case TokenType
.ABSTRACT
:
3565 flags
|= ModifierFlags
.ABSTRACT
;
3568 case TokenType
.EXTERN
:
3570 flags
|= ModifierFlags
.EXTERN
;
3573 case TokenType
.STATIC
:
3575 flags
|= ModifierFlags
.STATIC
;
3578 case TokenType
.PRIVATE
:
3580 flags
|= ModifierFlags
.PRIVATE
;
3589 ModifierFlags
parse_member_declaration_modifiers () {
3590 ModifierFlags flags
= 0;
3592 switch (current ()) {
3593 case TokenType
.ABSTRACT
:
3595 flags
|= ModifierFlags
.ABSTRACT
;
3597 case TokenType
.ASYNC
:
3599 flags
|= ModifierFlags
.ASYNC
;
3601 case TokenType
.CLASS
:
3603 flags
|= ModifierFlags
.CLASS
;
3605 case TokenType
.EXTERN
:
3607 flags
|= ModifierFlags
.EXTERN
;
3609 case TokenType
.INLINE
:
3611 flags
|= ModifierFlags
.INLINE
;
3615 flags
|= ModifierFlags
.NEW
;
3617 case TokenType
.OVERRIDE
:
3619 flags
|= ModifierFlags
.OVERRIDE
;
3621 case TokenType
.SEALED
:
3623 flags
|= ModifierFlags
.SEALED
;
3625 case TokenType
.STATIC
:
3627 flags
|= ModifierFlags
.STATIC
;
3629 case TokenType
.VIRTUAL
:
3631 flags
|= ModifierFlags
.VIRTUAL
;
3633 case TokenType
.PRIVATE
:
3635 flags
|= ModifierFlags
.PRIVATE
;
3643 Parameter
parse_parameter () throws ParseError
{
3644 var attrs
= parse_attributes (true);
3645 var begin
= get_location ();
3646 if (accept (TokenType
.ELLIPSIS
)) {
3648 return new Parameter
.with_ellipsis (get_src (begin
));
3650 bool params_array
= accept (TokenType
.PARAMS
);
3651 var direction
= ParameterDirection
.IN
;
3652 if (accept (TokenType
.OUT
)) {
3653 direction
= ParameterDirection
.OUT
;
3654 } else if (accept (TokenType
.REF
)) {
3655 direction
= ParameterDirection
.REF
;
3658 string id
= parse_identifier ();
3660 expect (TokenType
.COLON
);
3663 if (direction
== ParameterDirection
.IN
) {
3664 type
= parse_type (false, false);
3665 } else if (direction
== ParameterDirection
.REF
) {
3666 // ref parameters own the value by default
3667 type
= parse_type (true, true);
3669 // out parameters own the value by default
3670 type
= parse_type (true, false);
3673 var param
= new
Parameter (id
, type
, get_src (begin
));
3674 set_attributes (param
, attrs
);
3675 param
.direction
= direction
;
3676 param
.params_array
= params_array
;
3677 if (accept (TokenType
.ASSIGN
)) {
3678 param
.initializer
= parse_expression ();
3683 CreationMethod
parse_creation_method_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3684 var begin
= get_location ();
3685 CreationMethod method
;
3687 expect (TokenType
.CONSTRUCT
);
3688 parse_member_declaration_modifiers ();
3690 if (accept (TokenType
.OPEN_PARENS
)) {
3691 /* create default name using class name */
3692 method
= new
CreationMethod (class_name
, null, get_src (begin
), comment
);
3694 var sym
= parse_symbol_name ();
3695 if (sym
.inner
== null) {
3697 if (sym
.name
!= class_name
) {
3698 method
= new
CreationMethod (class_name
, sym
.name
, get_src (begin
), comment
);
3700 method
= new
CreationMethod (sym
.name
, null, get_src (begin
), comment
);
3703 method
= new
CreationMethod (sym
.inner
.name
, sym
.name
, get_src (begin
), comment
);
3705 expect (TokenType
.OPEN_PARENS
);
3708 if (current () != TokenType
.CLOSE_PARENS
) {
3710 var param
= parse_parameter ();
3711 method
.add_parameter (param
);
3712 } while (accept (TokenType
.COMMA
));
3714 expect (TokenType
.CLOSE_PARENS
);
3715 if (accept (TokenType
.RAISES
)) {
3717 method
.add_error_type (parse_type (true, false));
3718 } while (accept (TokenType
.COMMA
));
3720 method
.access
= SymbolAccessibility
.PUBLIC
;
3721 set_attributes (method
, attrs
);
3722 method
.binding
= MemberBinding
.STATIC
;
3724 if (accept_block ()) {
3725 method
.body
= parse_block ();
3726 } else if (scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3727 method
.external
= true;
3733 Symbol
parse_delegate_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3734 var begin
= get_location ();
3737 expect (TokenType
.DELEGATE
);
3739 var flags
= parse_member_declaration_modifiers ();
3741 var sym
= parse_symbol_name ();
3743 var type_param_list
= parse_type_parameter_list ();
3745 if (ModifierFlags
.NEW
in flags
) {
3746 throw new ParseError
.SYNTAX ("`new' modifier not allowed on delegates");
3749 var params
= new ArrayList
<Parameter
> ();
3751 expect (TokenType
.OPEN_PARENS
);
3752 if (current () != TokenType
.CLOSE_PARENS
) {
3754 var param
= parse_parameter ();
3756 } while (accept (TokenType
.COMMA
));
3758 expect (TokenType
.CLOSE_PARENS
);
3760 if (accept (TokenType
.COLON
)) {
3761 type
= parse_type (true, false);
3764 type
= new
VoidType ();
3767 var d
= new
Delegate (sym
.name
, type
, get_src (begin
), comment
);
3769 if (accept (TokenType
.RAISES
)) {
3771 d
.add_error_type (parse_type (true, false));
3772 } while (accept (TokenType
.COMMA
));
3775 expect_terminator ();
3778 if (ModifierFlags
.PRIVATE
in flags
) {
3779 d
.access
= SymbolAccessibility
.PRIVATE
;
3781 d
.access
= get_access (sym
.name
);
3784 if (ModifierFlags
.STATIC
in flags
) {
3785 d
.has_target
= false;
3787 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3791 set_attributes (d
, attrs
);
3793 foreach (TypeParameter type_param
in type_param_list
) {
3794 d
.add_type_parameter (type_param
);
3797 foreach (Parameter formal_param
in params
) {
3798 d
.add_parameter (formal_param
);
3804 while (sym
.inner
!= null) {
3806 var ns
= new
Namespace (sym
.name
, d
.source_reference
);
3808 if (result is Namespace
) {
3809 ns
.add_namespace ((Namespace
) result
);
3811 ns
.add_delegate ((Delegate
) result
);
3818 List
<TypeParameter
> parse_type_parameter_list () throws ParseError
{
3819 if (accept (TokenType
.OF
)) {
3820 var list
= new ArrayList
<TypeParameter
> ();
3822 var begin
= get_location ();
3823 string id
= parse_identifier ();
3824 list
.add (new
TypeParameter (id
, get_src (begin
)));
3825 } while (accept (TokenType
.COMMA
));
3828 if (_empty_type_parameter_list
== null) {
3829 _empty_type_parameter_list
= new ArrayList
<TypeParameter
> ();
3831 return _empty_type_parameter_list
;
3835 void skip_type_argument_list () throws ParseError
{
3836 if (accept (TokenType
.OF
)) {
3837 if (accept (TokenType
.OPEN_PARENS
)) {
3840 } while (accept (TokenType
.COMMA
));
3841 expect (TokenType
.CLOSE_PARENS
);
3845 } while (accept (TokenType
.COMMA
));
3851 // try to parse type argument list
3852 List
<DataType
>?
parse_type_argument_list (bool maybe_expression
) throws ParseError
{
3853 var begin
= get_location ();
3854 if (accept (TokenType
.OF
)) {
3855 var list
= new ArrayList
<DataType
> ();
3856 var inParens
= false;
3858 // Optional parens allow multi arg types in function signature: "dict of (int, string)"
3859 // See: https://bugzilla.gnome.org/show_bug.cgi?id=611191
3860 if (accept (TokenType
.OPEN_PARENS
)) {
3865 switch (current ()) {
3866 case TokenType
.VOID
:
3867 case TokenType
.DYNAMIC
:
3868 case TokenType
.UNOWNED
:
3869 case TokenType
.WEAK
:
3870 case TokenType
.IDENTIFIER
:
3871 var type
= parse_type (true, true);
3879 } while (accept (TokenType
.COMMA
));
3882 expect (TokenType
.CLOSE_PARENS
);
3890 MemberAccess
parse_member_name (Expression? base_expr
= null) throws ParseError
{
3891 var begin
= get_location ();
3892 MemberAccess expr
= null;
3894 string id
= parse_identifier ();
3895 List
<DataType
> type_arg_list
= parse_type_argument_list (false);
3896 expr
= new
MemberAccess (expr
!= null ? expr
: base_expr
, id
, get_src (begin
));
3897 if (type_arg_list
!= null) {
3898 foreach (DataType type_arg
in type_arg_list
) {
3899 expr
.add_type_argument (type_arg
);
3902 } while (accept (TokenType
.DOT
));