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
);
2428 if (context
.profile
== Profile
.GOBJECT
) {
2430 return parse_constructor_declaration (attrs
);
2433 case TokenType
.DELEGATE
:
2434 return parse_delegate_declaration (attrs
);
2436 return parse_method_declaration (attrs
);
2437 case TokenType
.ENUM
:
2438 return parse_enum_declaration (attrs
);
2439 case TokenType
.ERRORDOMAIN
:
2440 return parse_errordomain_declaration (attrs
);
2441 case TokenType
.FINAL
:
2442 return parse_destructor_declaration (attrs
);
2443 case TokenType
.INTERFACE
:
2444 return parse_interface_declaration (attrs
);
2445 case TokenType
.NAMESPACE
:
2446 return parse_namespace_declaration (attrs
);
2447 case TokenType
.PROP
:
2448 return parse_property_declaration (attrs
);
2449 case TokenType
.EVENT
:
2450 return parse_signal_declaration (attrs
);
2451 case TokenType
.STRUCT
:
2452 return parse_struct_declaration (attrs
);
2455 while (current () != TokenType
.EOL
&& current () != TokenType
.SEMICOLON
&& current () != TokenType
.EOF
) {
2456 if (current () == TokenType
.COLON
) {
2458 return parse_field_declaration (attrs
);
2468 TokenType cur
= current ();
2469 TokenType pre
= tokens
[index
-1].type
;
2471 throw new ParseError
.SYNTAX ("expected declaration but got %s with previous %s", cur
.to_string (), pre
.to_string());
2474 void parse_declarations (Symbol parent
, bool root
= false) throws ParseError
{
2476 expect (TokenType
.INDENT
);
2478 while (current () != TokenType
.DEDENT
&& current () != TokenType
.EOF
) {
2480 if (parent is Namespace
) {
2481 parse_namespace_member ((Namespace
) parent
);
2482 } else if (parent is Class
) {
2483 parse_class_member ((Class
) parent
);
2484 } else if (parent is Struct
) {
2485 parse_struct_member ((Struct
) parent
);
2486 } else if (parent is Interface
) {
2487 parse_interface_member ((Interface
) parent
);
2489 } catch (ParseError e
) {
2490 report_parse_error (e
);
2494 if (r
== RecoveryState
.STATEMENT_BEGIN
) {
2500 if (r
== RecoveryState
.EOF
) {
2506 if (!accept (TokenType
.DEDENT
)) {
2507 // only report error if it's not a secondary error
2508 if (context
.report
.get_errors () == 0) {
2509 Report
.error (get_current_src (), "expected dedent");
2515 enum RecoveryState
{
2521 RecoveryState
recover () {
2522 while (current () != TokenType
.EOF
) {
2523 switch (current ()) {
2524 case TokenType
.CLASS
:
2525 case TokenType
.CONST
:
2526 case TokenType
.CONSTRUCT
:
2527 case TokenType
.INIT
:
2529 case TokenType
.DELEGATE
:
2530 case TokenType
.ENUM
:
2531 case TokenType
.ERRORDOMAIN
:
2532 case TokenType
.FINAL
:
2533 case TokenType
.INTERFACE
:
2534 case TokenType
.NAMESPACE
:
2535 case TokenType
.PROP
:
2536 case TokenType
.EVENT
:
2537 case TokenType
.STRUCT
:
2538 return RecoveryState
.DECLARATION_BEGIN
;
2539 case TokenType
.BREAK
:
2540 case TokenType
.CASE
:
2541 case TokenType
.CONTINUE
:
2542 case TokenType
.DELETE
:
2546 case TokenType
.LOCK
:
2547 case TokenType
.RETURN
:
2548 case TokenType
.RAISE
:
2551 case TokenType
.WHILE
:
2552 case TokenType
.YIELD
:
2553 return RecoveryState
.STATEMENT_BEGIN
;
2559 return RecoveryState
.EOF
;
2562 Namespace
parse_namespace_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2563 var begin
= get_location ();
2564 expect (TokenType
.NAMESPACE
);
2565 var sym
= parse_symbol_name ();
2566 var ns
= new
Namespace (sym
.name
, get_src (begin
));
2567 if (comment
!= null) {
2568 ns
.add_comment (comment
);
2571 set_attributes (ns
, attrs
);
2572 expect (TokenType
.EOL
);
2573 parse_declarations (ns
);
2575 Namespace result
= ns
;
2576 while (sym
.inner
!= null) {
2578 ns
= new
Namespace (sym
.name
, result
.source_reference
);
2579 ns
.add_namespace ((Namespace
) result
);
2585 void parse_namespace_member (Namespace ns
) throws ParseError
{
2587 var sym
= parse_declaration ((ns
== context
.root
));
2588 if (sym is Namespace
) {
2589 ns
.add_namespace ((Namespace
) sym
);
2590 } else if (sym is Class
) {
2591 ns
.add_class ((Class
) sym
);
2592 } else if (sym is Interface
) {
2593 ns
.add_interface ((Interface
) sym
);
2594 } else if (sym is Struct
) {
2595 ns
.add_struct ((Struct
) sym
);
2596 } else if (sym is Enum
) {
2597 ns
.add_enum ((Enum
) sym
);
2598 } else if (sym is ErrorDomain
) {
2599 ns
.add_error_domain ((ErrorDomain
) sym
);
2600 } else if (sym is Delegate
) {
2601 ns
.add_delegate ((Delegate
) sym
);
2602 } else if (sym is Method
) {
2603 var method
= (Method
) sym
;
2604 if (method
.binding
== MemberBinding
.INSTANCE
) {
2605 method
.binding
= MemberBinding
.STATIC
;
2607 ns
.add_method (method
);
2608 } else if (sym is Field
) {
2609 var field
= (Field
) sym
;
2610 if (field
.binding
== MemberBinding
.INSTANCE
) {
2611 field
.binding
= MemberBinding
.STATIC
;
2613 ns
.add_field (field
);
2614 } else if (sym is Constant
) {
2615 ns
.add_constant ((Constant
) sym
);
2617 Report
.error (sym
.source_reference
, "unexpected declaration in namespace");
2622 void add_uses_clause (Namespace ns
) throws ParseError
{
2623 var begin
= get_location ();
2624 var sym
= parse_symbol_name ();
2625 var ns_ref
= new
UsingDirective (sym
, get_src (begin
));
2627 scanner
.source_file
.add_using_directive (ns_ref
);
2628 ns
.add_using_directive (ns_ref
);
2631 void parse_using_directives (Namespace ns
) throws ParseError
{
2632 while (accept (TokenType
.USES
)) {
2633 if (accept_block ()) {
2634 expect (TokenType
.INDENT
);
2636 while (current () != TokenType
.DEDENT
&& current () != TokenType
.EOF
) {
2637 add_uses_clause (ns
);
2638 expect (TokenType
.EOL
);
2641 expect (TokenType
.DEDENT
);
2644 add_uses_clause (ns
);
2645 } while (accept (TokenType
.COMMA
));
2647 expect_terminator ();
2653 Symbol
parse_class_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2654 var begin
= get_location ();
2655 expect (TokenType
.CLASS
);
2657 var flags
= parse_type_declaration_modifiers ();
2659 var sym
= parse_symbol_name ();
2660 var type_param_list
= parse_type_parameter_list ();
2661 var base_types
= new ArrayList
<DataType
> ();
2662 if (accept (TokenType
.COLON
)) {
2663 var type1
= parse_type (true, false);
2664 base_types
.add (type1
);
2666 if (accept (TokenType
.IMPLEMENTS
)) {
2668 var type2
= parse_type (true, true);
2669 base_types
.add (type2
);
2670 } while (accept (TokenType
.COMMA
));
2674 accept (TokenType
.EOL
);
2676 var cl
= new
Class (sym
.name
, get_src (begin
), comment
);
2678 if (ModifierFlags
.PRIVATE
in flags
) {
2679 cl
.access
= SymbolAccessibility
.PRIVATE
;
2681 /* class must always be Public unless its name starts with underscore */
2682 if (sym
.name
[0] == '_') {
2683 cl
.access
= SymbolAccessibility
.PRIVATE
;
2685 cl
.access
= SymbolAccessibility
.PUBLIC
;
2689 if (ModifierFlags
.ABSTRACT
in flags
) {
2690 cl
.is_abstract
= true;
2692 set_attributes (cl
, attrs
);
2693 foreach (TypeParameter type_param
in type_param_list
) {
2694 cl
.add_type_parameter (type_param
);
2696 foreach (DataType base_type
in base_types
) {
2697 cl
.add_base_type (base_type
);
2700 class_name
= cl
.name
;
2702 parse_declarations (cl
);
2704 // ensure there is always a default construction method
2705 if (scanner
.source_file
.file_type
== SourceFileType
.SOURCE
2706 && cl
.default_construction_method
== null) {
2707 var m
= new
CreationMethod (cl
.name
, null, cl
.source_reference
);
2708 m
.access
= SymbolAccessibility
.PUBLIC
;
2709 m
.body
= new
Block (cl
.source_reference
);
2714 while (sym
.inner
!= null) {
2716 var ns
= new
Namespace (sym
.name
, cl
.source_reference
);
2717 if (result is Namespace
) {
2718 ns
.add_namespace ((Namespace
) result
);
2720 ns
.add_class ((Class
) result
);
2727 void parse_class_member (Class cl
) throws ParseError
{
2728 var sym
= parse_declaration ();
2730 cl
.add_class ((Class
) sym
);
2731 } else if (sym is Struct
) {
2732 cl
.add_struct ((Struct
) sym
);
2733 } else if (sym is Enum
) {
2734 cl
.add_enum ((Enum
) sym
);
2735 } else if (sym is Delegate
) {
2736 cl
.add_delegate ((Delegate
) sym
);
2737 } else if (sym is Method
) {
2738 cl
.add_method ((Method
) sym
);
2739 } else if (sym is Vala
.Signal
) {
2740 cl
.add_signal ((Vala
.Signal
) sym
);
2741 } else if (sym is Field
) {
2742 cl
.add_field ((Field
) sym
);
2743 } else if (sym is Constant
) {
2744 cl
.add_constant ((Constant
) sym
);
2745 } else if (sym is Property
) {
2746 cl
.add_property ((Property
) sym
);
2747 } else if (sym is Constructor
) {
2748 var c
= (Constructor
) sym
;
2749 if (c
.binding
== MemberBinding
.INSTANCE
) {
2750 if (cl
.constructor
!= null) {
2751 Report
.error (c
.source_reference
, "class already contains a constructor");
2754 } else if (c
.binding
== MemberBinding
.CLASS
) {
2755 if (cl
.class_constructor
!= null) {
2756 Report
.error (c
.source_reference
, "class already contains a class constructor");
2758 cl
.class_constructor
= c
;
2760 if (cl
.static_constructor
!= null) {
2761 Report
.error (c
.source_reference
, "class already contains a static constructor");
2763 cl
.static_constructor
= c
;
2766 } else if (sym is Destructor
) {
2767 var d
= (Destructor
) sym
;
2768 if (d
.binding
== MemberBinding
.STATIC
) {
2769 if (cl
.static_destructor
!= null) {
2770 Report
.error (d
.source_reference
, "class already contains a static destructor");
2772 cl
.static_destructor
= (Destructor
) d
;
2773 } else if (d
.binding
== MemberBinding
.CLASS
) {
2774 if (cl
.class_destructor
!= null) {
2775 Report
.error (d
.source_reference
, "class already contains a class destructor");
2777 cl
.class_destructor
= (Destructor
) d
;
2779 if (cl
.destructor
!= null) {
2780 Report
.error (d
.source_reference
, "class already contains a destructor");
2782 cl
.destructor
= (Destructor
) d
;
2786 Report
.error (sym
.source_reference
, "unexpected declaration in class");
2790 Constant
parse_constant_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2791 var begin
= get_location ();
2793 expect (TokenType
.CONST
);
2795 var flags
= parse_member_declaration_modifiers ();
2797 string id
= parse_identifier ();
2799 expect (TokenType
.COLON
);
2800 var type
= parse_type (false, false);
2801 type
= parse_inline_array_type (type
);
2803 Expression initializer
= null;
2804 if (accept (TokenType
.ASSIGN
)) {
2805 initializer
= parse_expression ();
2807 expect_terminator ();
2809 // constant arrays don't own their element
2810 var array_type
= type as ArrayType
;
2811 if (array_type
!= null) {
2812 array_type
.element_type
.value_owned
= false;
2815 var c
= new
Constant (id
, type
, initializer
, get_src (begin
), comment
);
2816 c
.access
= get_access (id
);
2818 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2821 if (ModifierFlags
.NEW
in flags
) {
2825 set_attributes (c
, attrs
);
2827 if (ModifierFlags
.STATIC
in flags
) {
2828 Report
.warning (c
.source_reference
, "the modifier `static' is not applicable to constants");
2834 Field
parse_field_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2835 var begin
= get_location ();
2836 string id
= parse_identifier ();
2837 expect (TokenType
.COLON
);
2839 var flags
= parse_member_declaration_modifiers ();
2841 var type
= parse_type (true, true);
2843 type
= parse_inline_array_type (type
);
2845 var f
= new
Field (id
, type
, null, get_src (begin
), comment
);
2847 if (ModifierFlags
.ABSTRACT
in flags
|| ModifierFlags
.VIRTUAL
in flags
|| ModifierFlags
.OVERRIDE
in flags
) {
2848 Report
.error (f
.source_reference
, "abstract, virtual, and override modifiers are not applicable to fields");
2851 if (ModifierFlags
.PRIVATE
in flags
) {
2852 f
.access
= SymbolAccessibility
.PRIVATE
;
2854 f
.access
= get_access (id
);
2857 set_attributes (f
, attrs
);
2859 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2862 if (ModifierFlags
.NEW
in flags
) {
2866 if (accept (TokenType
.ASSIGN
)) {
2867 f
.initializer
= parse_expression ();
2870 if (ModifierFlags
.STATIC
in flags
) {
2871 f
.binding
= MemberBinding
.STATIC
;
2872 } else if (ModifierFlags
.CLASS
in flags
) {
2873 f
.binding
= MemberBinding
.CLASS
;
2876 expect_terminator ();
2881 InitializerList
parse_initializer () throws ParseError
{
2882 var begin
= get_location ();
2883 if (!accept (TokenType
.OPEN_PARENS
)) {
2884 expect (TokenType
.OPEN_BRACE
);
2886 var initializer
= new
InitializerList (get_src (begin
));
2887 if (current () != TokenType
.DEDENT
) {
2889 var init
= parse_argument ();
2890 initializer
.append (init
);
2891 } while (accept (TokenType
.COMMA
));
2893 if (!accept (TokenType
.CLOSE_PARENS
)) {
2894 expect (TokenType
.CLOSE_BRACE
);
2902 Method
parse_main_method_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2904 var begin
= get_location ();
2905 DataType type
= new
VoidType ();
2906 expect (TokenType
.INIT
);
2908 var method
= new
Method (id
, type
, get_src (begin
), comment
);
2909 method
.access
= SymbolAccessibility
.PUBLIC
;
2911 set_attributes (method
, attrs
);
2913 method
.binding
= MemberBinding
.STATIC
;
2915 var sym
= new
UnresolvedSymbol (null, "string", get_src (begin
));
2916 type
= new UnresolvedType
.from_symbol (sym
, get_src (begin
));
2917 type
.value_owned
= true;
2918 type
= new
ArrayType (type
, 1, get_src (begin
));
2919 type
.nullable
= false;
2921 var param
= new
Parameter ("args", type
, get_src (begin
));
2922 method
.add_parameter (param
);
2925 expect (TokenType
.EOL
);
2927 if (accept_block ()) {
2928 method
.body
= parse_block ();
2934 Method
parse_method_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2935 var begin
= get_location ();
2936 DataType type
= new
VoidType ();
2937 expect (TokenType
.DEF
);
2938 var flags
= parse_member_declaration_modifiers ();
2940 string id
= parse_identifier ();
2942 var params
= new ArrayList
<Parameter
> ();
2943 expect (TokenType
.OPEN_PARENS
);
2945 if (current () != TokenType
.CLOSE_PARENS
) {
2947 var param
= parse_parameter ();
2949 } while (accept (TokenType
.COMMA
));
2952 expect (TokenType
.CLOSE_PARENS
);
2955 /* deal with return value */
2956 if (accept (TokenType
.COLON
)) {
2957 type
= parse_type (true, false);
2960 var type_param_list
= parse_type_parameter_list ();
2962 var method
= new
Method (id
, type
, get_src (begin
), comment
);
2963 if (ModifierFlags
.PRIVATE
in flags
) {
2964 method
.access
= SymbolAccessibility
.PRIVATE
;
2966 method
.access
= get_access (id
);
2970 set_attributes (method
, attrs
);
2972 foreach (TypeParameter type_param
in type_param_list
) {
2973 method
.add_type_parameter (type_param
);
2977 foreach (Parameter param
in params
) {
2978 method
.add_parameter (param
);
2981 if (accept (TokenType
.RAISES
)) {
2983 method
.add_error_type (parse_type (true, false));
2984 } while (accept (TokenType
.COMMA
));
2988 if (ModifierFlags
.STATIC
in flags
|| id
== "main") {
2989 method
.binding
= MemberBinding
.STATIC
;
2990 } else if (ModifierFlags
.CLASS
in flags
) {
2991 method
.binding
= MemberBinding
.CLASS
;
2993 if (ModifierFlags
.ASYNC
in flags
) {
2994 method
.coroutine
= true;
2997 if (ModifierFlags
.NEW
in flags
) {
2998 method
.hides
= true;
3001 if (method
.binding
== MemberBinding
.INSTANCE
) {
3002 if (ModifierFlags
.ABSTRACT
in flags
) {
3003 method
.is_abstract
= true;
3005 if (ModifierFlags
.VIRTUAL
in flags
) {
3006 method
.is_virtual
= true;
3008 if (ModifierFlags
.OVERRIDE
in flags
) {
3009 method
.overrides
= true;
3011 if ((method
.is_abstract
&& method
.is_virtual
)
3012 || (method
.is_abstract
&& method
.overrides
)
3013 || (method
.is_virtual
&& method
.overrides
)) {
3014 throw new ParseError
.SYNTAX ("only one of `abstract', `virtual', or `override' may be specified");
3017 if (ModifierFlags
.ABSTRACT
in flags
3018 || ModifierFlags
.VIRTUAL
in flags
3019 || ModifierFlags
.OVERRIDE
in flags
) {
3020 throw new ParseError
.SYNTAX ("the modifiers `abstract', `virtual', and `override' are not valid for static methods");
3024 if (ModifierFlags
.INLINE
in flags
) {
3025 method
.is_inline
= true;
3027 if (ModifierFlags
.EXTERN
in flags
) {
3028 method
.external
= true;
3031 expect (TokenType
.EOL
);
3033 var body_location
= get_location ();
3036 /* "requires" and "ensures" if present will be at start of the method body */
3037 if (accept (TokenType
.INDENT
)) {
3038 if (accept (TokenType
.REQUIRES
)) {
3040 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
3041 while (current() != TokenType
.DEDENT
) {
3042 method
.add_precondition (parse_expression ());
3043 expect (TokenType
.EOL
);
3046 expect (TokenType
.DEDENT
);
3047 accept_terminator ();
3050 method
.add_precondition (parse_expression ());
3051 expect_terminator ();
3057 if (accept (TokenType
.ENSURES
)) {
3058 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
3059 while (current() != TokenType
.DEDENT
) {
3060 method
.add_postcondition (parse_expression ());
3061 expect (TokenType
.EOL
);
3064 expect (TokenType
.DEDENT
);
3065 accept_terminator ();
3067 method
.add_postcondition (parse_expression ());
3068 expect_terminator ();
3073 rollback (body_location
);
3076 if (accept_block ()) {
3077 method
.body
= parse_block ();
3078 } else if (scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3079 method
.external
= true;
3084 Property
parse_property_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3085 var begin
= get_location ();
3086 var readonly = false;
3088 expect (TokenType
.PROP
);
3090 var flags
= parse_member_declaration_modifiers ();
3092 readonly = accept (TokenType
.READONLY
);
3094 string id
= parse_identifier ();
3095 expect (TokenType
.COLON
);
3097 var type
= parse_type (true, true);
3099 var prop
= new
Property (id
, type
, null, null, get_src (begin
), comment
);
3100 if (ModifierFlags
.PRIVATE
in flags
) {
3101 prop
.access
= SymbolAccessibility
.PRIVATE
;
3103 prop
.access
= get_access (id
);
3106 set_attributes (prop
, attrs
);
3108 if (ModifierFlags
.STATIC
in flags
) {
3109 prop
.binding
= MemberBinding
.STATIC
;
3110 } else if (ModifierFlags
.CLASS
in flags
) {
3111 prop
.binding
= MemberBinding
.CLASS
;
3113 if (ModifierFlags
.ABSTRACT
in flags
) {
3114 prop
.is_abstract
= true;
3116 if (ModifierFlags
.VIRTUAL
in flags
) {
3117 prop
.is_virtual
= true;
3119 if (ModifierFlags
.OVERRIDE
in flags
) {
3120 prop
.overrides
= true;
3123 if (ModifierFlags
.NEW
in flags
) {
3126 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3127 prop
.external
= true;
3130 if (ModifierFlags
.ASYNC
in flags
) {
3131 Report
.error (prop
.source_reference
, "async properties are not supported yet");
3134 if (accept (TokenType
.ASSIGN
)) {
3135 prop
.initializer
= parse_expression ();
3139 if (accept_block ()) {
3140 expect (TokenType
.INDENT
);
3141 while (current () != TokenType
.DEDENT
) {
3142 var accessor_begin
= get_location ();
3143 var attribs
= parse_attributes (false);
3145 var value_type
= type
.copy ();
3146 value_type
.value_owned
= accept (TokenType
.OWNED
);
3148 if (accept (TokenType
.GET
)) {
3149 if (prop
.get_accessor
!= null) {
3150 throw new ParseError
.SYNTAX ("property get accessor already defined");
3153 if (accept_block ()) {
3154 block
= parse_block ();
3155 prop
.external
= false;
3157 prop
.get_accessor
= new
PropertyAccessor (true, false, false, value_type
, block
, get_src (accessor_begin
));
3158 set_attributes (prop
.get_accessor
, attribs
);
3159 prop
.get_accessor
.access
= SymbolAccessibility
.PUBLIC
;
3161 bool _construct
= false;
3162 if (accept (TokenType
.SET
)) {
3164 throw new ParseError
.SYNTAX ("set block not allowed for a read only property");
3166 _construct
= (context
.profile
== Profile
.GOBJECT
) && accept (TokenType
.CONSTRUCT
);
3167 } else if (context
.profile
== Profile
.GOBJECT
&& accept (TokenType
.CONSTRUCT
)) {
3169 } else if (!accept (TokenType
.EOL
)) {
3170 throw new ParseError
.SYNTAX ("expected get, set, or construct");
3173 if (prop
.set_accessor
!= null) {
3174 throw new ParseError
.SYNTAX ("property set accessor already defined");
3178 if (accept_block ()) {
3179 block
= parse_block ();
3180 prop
.external
= false;
3182 prop
.set_accessor
= new
PropertyAccessor (false, !readonly, _construct
, value_type
, block
, get_src (accessor_begin
));
3183 set_attributes (prop
.set_accessor
, attribs
);
3184 prop
.set_accessor
.access
= SymbolAccessibility
.PUBLIC
;
3187 accept (TokenType
.EOL
);
3188 expect (TokenType
.DEDENT
);
3190 var value_type
= type
.copy ();
3191 value_type
.value_owned
= false;
3193 prop
.get_accessor
= new
PropertyAccessor (true, false, false, value_type
, null, get_src (begin
));
3194 prop
.get_accessor
.access
= SymbolAccessibility
.PUBLIC
;
3197 value_type
= type
.copy ();
3198 value_type
.value_owned
= false;
3200 prop
.set_accessor
= new
PropertyAccessor (false, true, false, value_type
, null, get_src (begin
));
3201 prop
.set_accessor
.access
= SymbolAccessibility
.PUBLIC
;
3205 expect_terminator ();
3211 Vala
.Signal
parse_signal_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3212 var begin
= get_location ();
3215 expect (TokenType
.EVENT
);
3216 var flags
= parse_member_declaration_modifiers ();
3217 string id
= parse_identifier ();
3220 var params
= new ArrayList
<Parameter
> ();
3222 expect (TokenType
.OPEN_PARENS
);
3223 if (current () != TokenType
.CLOSE_PARENS
) {
3225 var param
= parse_parameter ();
3227 } while (accept (TokenType
.COMMA
));
3229 expect (TokenType
.CLOSE_PARENS
);
3231 if (accept (TokenType
.COLON
)) {
3232 type
= parse_type (true, false);
3234 type
= new
VoidType ();
3237 var sig
= new Vala
.Signal (id
, type
, get_src (begin
), comment
);
3238 if (ModifierFlags
.PRIVATE
in flags
) {
3239 sig
.access
= SymbolAccessibility
.PRIVATE
;
3241 sig
.access
= get_access (id
);
3244 if (ModifierFlags
.VIRTUAL
in flags
) {
3245 sig
.is_virtual
= true;
3247 if (ModifierFlags
.NEW
in flags
) {
3251 if (ModifierFlags
.STATIC
in flags
) {
3252 throw new ParseError
.SYNTAX ("`static' modifier not allowed on signals");
3253 } else if (ModifierFlags
.CLASS
in flags
) {
3254 throw new ParseError
.SYNTAX ("`class' modifier not allowed on signals");
3257 set_attributes (sig
, attrs
);
3259 foreach (Parameter formal_param
in params
) {
3260 sig
.add_parameter (formal_param
);
3263 if (!accept_terminator ()) {
3264 sig
.body
= parse_block ();
3269 Constructor
parse_constructor_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3270 var begin
= get_location ();
3272 expect (TokenType
.INIT
);
3273 var flags
= parse_member_declaration_modifiers ();
3275 var c
= new
Constructor (get_src (begin
));
3276 if (ModifierFlags
.STATIC
in flags
) {
3277 c
.binding
= MemberBinding
.STATIC
;
3278 } else if (ModifierFlags
.CLASS
in flags
) {
3279 c
.binding
= MemberBinding
.CLASS
;
3283 c
.body
= parse_block ();
3287 Destructor
parse_destructor_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3288 var begin
= get_location ();
3289 expect (TokenType
.FINAL
);
3290 var d
= new
Destructor (get_src (begin
));
3292 d
.body
= parse_block ();
3296 Symbol
parse_struct_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3297 var begin
= get_location ();
3299 expect (TokenType
.STRUCT
);
3300 var flags
= parse_type_declaration_modifiers ();
3301 var sym
= parse_symbol_name ();
3302 var type_param_list
= parse_type_parameter_list ();
3303 DataType base_type
= null;
3304 if (accept (TokenType
.COLON
)) {
3305 base_type
= parse_type (true, false);
3308 var st
= new
Struct (sym
.name
, get_src (begin
), comment
);
3309 if (ModifierFlags
.PRIVATE
in flags
) {
3310 st
.access
= SymbolAccessibility
.PRIVATE
;
3312 st
.access
= get_access (sym
.name
);
3314 set_attributes (st
, attrs
);
3315 foreach (TypeParameter type_param
in type_param_list
) {
3316 st
.add_type_parameter (type_param
);
3318 if (base_type
!= null) {
3319 st
.base_type
= base_type
;
3322 expect (TokenType
.EOL
);
3324 parse_declarations (st
);
3327 while (sym
.inner
!= null) {
3329 var ns
= new
Namespace (sym
.name
, st
.source_reference
);
3330 if (result is Namespace
) {
3331 ns
.add_namespace ((Namespace
) result
);
3333 ns
.add_struct ((Struct
) result
);
3340 void parse_struct_member (Struct st
) throws ParseError
{
3341 var sym
= parse_declaration ();
3342 if (sym is Method
) {
3343 st
.add_method ((Method
) sym
);
3344 } else if (sym is Field
) {
3345 st
.add_field ((Field
) sym
);
3346 } else if (sym is Constant
) {
3347 st
.add_constant ((Constant
) sym
);
3348 } else if (sym is Property
) {
3349 st
.add_property ((Property
) sym
);
3351 Report
.error (sym
.source_reference
, "unexpected declaration in struct");
3355 Symbol
parse_interface_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3356 var begin
= get_location ();
3358 expect (TokenType
.INTERFACE
);
3359 var flags
= parse_type_declaration_modifiers ();
3360 var sym
= parse_symbol_name ();
3361 var type_param_list
= parse_type_parameter_list ();
3362 var base_types
= new ArrayList
<DataType
> ();
3363 if (accept (TokenType
.COLON
)) {
3365 var type
= parse_type (true, false);
3366 base_types
.add (type
);
3367 } while (accept (TokenType
.COMMA
));
3370 var iface
= new
Interface (sym
.name
, get_src (begin
), comment
);
3371 if (ModifierFlags
.PRIVATE
in flags
) {
3372 iface
.access
= SymbolAccessibility
.PRIVATE
;
3374 iface
.access
= get_access (sym
.name
);
3376 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3377 iface
.external
= true;
3379 set_attributes (iface
, attrs
);
3380 foreach (TypeParameter type_param
in type_param_list
) {
3381 iface
.add_type_parameter (type_param
);
3383 foreach (DataType base_type
in base_types
) {
3384 iface
.add_prerequisite (base_type
);
3388 expect (TokenType
.EOL
);
3390 parse_declarations (iface
);
3393 Symbol result
= iface
;
3394 while (sym
.inner
!= null) {
3396 var ns
= new
Namespace (sym
.name
, iface
.source_reference
);
3397 if (result is Namespace
) {
3398 ns
.add_namespace ((Namespace
) result
);
3400 ns
.add_interface ((Interface
) result
);
3407 void parse_interface_member (Interface iface
) throws ParseError
{
3408 var sym
= parse_declaration ();
3410 iface
.add_class ((Class
) sym
);
3411 } else if (sym is Struct
) {
3412 iface
.add_struct ((Struct
) sym
);
3413 } else if (sym is Enum
) {
3414 iface
.add_enum ((Enum
) sym
);
3415 } else if (sym is Delegate
) {
3416 iface
.add_delegate ((Delegate
) sym
);
3417 } else if (sym is Method
) {
3418 iface
.add_method ((Method
) sym
);
3419 } else if (sym is Vala
.Signal
) {
3420 iface
.add_signal ((Vala
.Signal
) sym
);
3421 } else if (sym is Field
) {
3422 iface
.add_field ((Field
) sym
);
3423 } else if (sym is Constant
) {
3424 iface
.add_constant ((Constant
) sym
);
3425 } else if (sym is Property
) {
3426 iface
.add_property ((Property
) sym
);
3428 Report
.error (sym
.source_reference
, "unexpected declaration in interface");
3432 Symbol
parse_enum_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3433 var begin
= get_location ();
3434 expect (TokenType
.ENUM
);
3435 var flags
= parse_type_declaration_modifiers ();
3437 var sym
= parse_symbol_name ();
3438 var en
= new
Enum (sym
.name
, get_src (begin
), comment
);
3439 if (ModifierFlags
.PRIVATE
in flags
) {
3440 en
.access
= SymbolAccessibility
.PRIVATE
;
3442 en
.access
= get_access (sym
.name
);
3444 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3447 set_attributes (en
, attrs
);
3449 expect (TokenType
.EOL
);
3450 expect (TokenType
.INDENT
);
3452 if (current () == TokenType
.DEDENT
&& en
.get_values ().size
> 0) {
3453 // allow trailing comma
3456 var value_attrs
= parse_attributes (false);
3457 var value_begin
= get_location ();
3458 string id
= parse_identifier ();
3459 comment
= scanner
.pop_comment ();
3461 Expression value
= null;
3462 if (accept (TokenType
.ASSIGN
)) {
3463 value
= parse_expression ();
3466 var ev
= new
EnumValue (id
, value
, get_src (value_begin
), comment
);
3467 ev
.access
= SymbolAccessibility
.PUBLIC
;
3468 set_attributes (ev
, value_attrs
);
3471 if (expect_separator ()) {
3472 accept (TokenType
.EOL
);
3476 expect (TokenType
.DEDENT
);
3479 while (sym
.inner
!= null) {
3481 var ns
= new
Namespace (sym
.name
, en
.source_reference
);
3482 if (result is Namespace
) {
3483 ns
.add_namespace ((Namespace
) result
);
3485 ns
.add_enum ((Enum
) result
);
3492 Symbol
parse_errordomain_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3493 var begin
= get_location ();
3494 expect (TokenType
.ERRORDOMAIN
);
3495 var flags
= parse_type_declaration_modifiers ();
3497 var sym
= parse_symbol_name ();
3498 var ed
= new
ErrorDomain (sym
.name
, get_src (begin
), comment
);
3499 if (ModifierFlags
.PRIVATE
in flags
) {
3500 ed
.access
= SymbolAccessibility
.PRIVATE
;
3502 ed
.access
= get_access (sym
.name
);
3505 set_attributes (ed
, attrs
);
3507 expect (TokenType
.EOL
);
3508 expect (TokenType
.INDENT
);
3511 if (current () == TokenType
.DEDENT
&& ed
.get_codes ().size
> 0) {
3512 // allow trailing comma
3515 var code_attrs
= parse_attributes (false);
3516 var code_begin
= get_location ();
3517 string id
= parse_identifier ();
3518 comment
= scanner
.pop_comment ();
3519 var ec
= new
ErrorCode (id
, get_src (code_begin
), comment
);
3520 set_attributes (ec
, code_attrs
);
3521 if (accept (TokenType
.ASSIGN
)) {
3522 ec
.value
= parse_expression ();
3525 accept (TokenType
.EOL
);
3529 expect (TokenType
.DEDENT
);
3532 while (sym
.inner
!= null) {
3534 var ns
= new
Namespace (sym
.name
, ed
.source_reference
);
3536 if (result is Namespace
) {
3537 ns
.add_namespace ((Namespace
) result
);
3539 ns
.add_error_domain ((ErrorDomain
) result
);
3546 ModifierFlags
parse_type_declaration_modifiers () {
3547 ModifierFlags flags
= 0;
3549 switch (current ()) {
3550 case TokenType
.ABSTRACT
:
3552 flags
|= ModifierFlags
.ABSTRACT
;
3555 case TokenType
.EXTERN
:
3557 flags
|= ModifierFlags
.EXTERN
;
3560 case TokenType
.STATIC
:
3562 flags
|= ModifierFlags
.STATIC
;
3565 case TokenType
.PRIVATE
:
3567 flags
|= ModifierFlags
.PRIVATE
;
3576 ModifierFlags
parse_member_declaration_modifiers () {
3577 ModifierFlags flags
= 0;
3579 switch (current ()) {
3580 case TokenType
.ABSTRACT
:
3582 flags
|= ModifierFlags
.ABSTRACT
;
3584 case TokenType
.ASYNC
:
3586 flags
|= ModifierFlags
.ASYNC
;
3588 case TokenType
.CLASS
:
3590 flags
|= ModifierFlags
.CLASS
;
3592 case TokenType
.EXTERN
:
3594 flags
|= ModifierFlags
.EXTERN
;
3596 case TokenType
.INLINE
:
3598 flags
|= ModifierFlags
.INLINE
;
3602 flags
|= ModifierFlags
.NEW
;
3604 case TokenType
.OVERRIDE
:
3606 flags
|= ModifierFlags
.OVERRIDE
;
3608 case TokenType
.SEALED
:
3610 flags
|= ModifierFlags
.SEALED
;
3612 case TokenType
.STATIC
:
3614 flags
|= ModifierFlags
.STATIC
;
3616 case TokenType
.VIRTUAL
:
3618 flags
|= ModifierFlags
.VIRTUAL
;
3620 case TokenType
.PRIVATE
:
3622 flags
|= ModifierFlags
.PRIVATE
;
3630 Parameter
parse_parameter () throws ParseError
{
3631 var attrs
= parse_attributes (true);
3632 var begin
= get_location ();
3633 if (accept (TokenType
.ELLIPSIS
)) {
3635 return new Parameter
.with_ellipsis (get_src (begin
));
3637 bool params_array
= accept (TokenType
.PARAMS
);
3638 var direction
= ParameterDirection
.IN
;
3639 if (accept (TokenType
.OUT
)) {
3640 direction
= ParameterDirection
.OUT
;
3641 } else if (accept (TokenType
.REF
)) {
3642 direction
= ParameterDirection
.REF
;
3645 string id
= parse_identifier ();
3647 expect (TokenType
.COLON
);
3650 if (direction
== ParameterDirection
.IN
) {
3651 type
= parse_type (false, false);
3652 } else if (direction
== ParameterDirection
.REF
) {
3653 // ref parameters own the value by default
3654 type
= parse_type (true, true);
3656 // out parameters own the value by default
3657 type
= parse_type (true, false);
3660 var param
= new
Parameter (id
, type
, get_src (begin
));
3661 set_attributes (param
, attrs
);
3662 param
.direction
= direction
;
3663 param
.params_array
= params_array
;
3664 if (accept (TokenType
.ASSIGN
)) {
3665 param
.initializer
= parse_expression ();
3670 CreationMethod
parse_creation_method_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3671 var begin
= get_location ();
3672 CreationMethod method
;
3674 expect (TokenType
.CONSTRUCT
);
3675 parse_member_declaration_modifiers ();
3677 if (accept (TokenType
.OPEN_PARENS
)) {
3678 /* create default name using class name */
3679 method
= new
CreationMethod (class_name
, null, get_src (begin
), comment
);
3681 var sym
= parse_symbol_name ();
3682 if (sym
.inner
== null) {
3684 if (sym
.name
!= class_name
) {
3685 method
= new
CreationMethod (class_name
, sym
.name
, get_src (begin
), comment
);
3687 method
= new
CreationMethod (sym
.name
, null, get_src (begin
), comment
);
3690 method
= new
CreationMethod (sym
.inner
.name
, sym
.name
, get_src (begin
), comment
);
3692 expect (TokenType
.OPEN_PARENS
);
3695 if (current () != TokenType
.CLOSE_PARENS
) {
3697 var param
= parse_parameter ();
3698 method
.add_parameter (param
);
3699 } while (accept (TokenType
.COMMA
));
3701 expect (TokenType
.CLOSE_PARENS
);
3702 if (accept (TokenType
.RAISES
)) {
3704 method
.add_error_type (parse_type (true, false));
3705 } while (accept (TokenType
.COMMA
));
3707 method
.access
= SymbolAccessibility
.PUBLIC
;
3708 set_attributes (method
, attrs
);
3709 method
.binding
= MemberBinding
.STATIC
;
3711 if (accept_block ()) {
3712 method
.body
= parse_block ();
3713 } else if (scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3714 method
.external
= true;
3720 Symbol
parse_delegate_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3721 var begin
= get_location ();
3724 expect (TokenType
.DELEGATE
);
3726 var flags
= parse_member_declaration_modifiers ();
3728 var sym
= parse_symbol_name ();
3730 var type_param_list
= parse_type_parameter_list ();
3732 if (ModifierFlags
.NEW
in flags
) {
3733 throw new ParseError
.SYNTAX ("`new' modifier not allowed on delegates");
3736 var params
= new ArrayList
<Parameter
> ();
3738 expect (TokenType
.OPEN_PARENS
);
3739 if (current () != TokenType
.CLOSE_PARENS
) {
3741 var param
= parse_parameter ();
3743 } while (accept (TokenType
.COMMA
));
3745 expect (TokenType
.CLOSE_PARENS
);
3747 if (accept (TokenType
.COLON
)) {
3748 type
= parse_type (true, false);
3751 type
= new
VoidType ();
3754 var d
= new
Delegate (sym
.name
, type
, get_src (begin
), comment
);
3756 if (accept (TokenType
.RAISES
)) {
3758 d
.add_error_type (parse_type (true, false));
3759 } while (accept (TokenType
.COMMA
));
3762 expect_terminator ();
3765 if (ModifierFlags
.PRIVATE
in flags
) {
3766 d
.access
= SymbolAccessibility
.PRIVATE
;
3768 d
.access
= get_access (sym
.name
);
3771 if (ModifierFlags
.STATIC
in flags
) {
3772 d
.has_target
= false;
3774 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3778 set_attributes (d
, attrs
);
3780 foreach (TypeParameter type_param
in type_param_list
) {
3781 d
.add_type_parameter (type_param
);
3784 foreach (Parameter formal_param
in params
) {
3785 d
.add_parameter (formal_param
);
3791 while (sym
.inner
!= null) {
3793 var ns
= new
Namespace (sym
.name
, d
.source_reference
);
3795 if (result is Namespace
) {
3796 ns
.add_namespace ((Namespace
) result
);
3798 ns
.add_delegate ((Delegate
) result
);
3805 List
<TypeParameter
> parse_type_parameter_list () throws ParseError
{
3806 if (accept (TokenType
.OF
)) {
3807 var list
= new ArrayList
<TypeParameter
> ();
3809 var begin
= get_location ();
3810 string id
= parse_identifier ();
3811 list
.add (new
TypeParameter (id
, get_src (begin
)));
3812 } while (accept (TokenType
.COMMA
));
3815 if (_empty_type_parameter_list
== null) {
3816 _empty_type_parameter_list
= new ArrayList
<TypeParameter
> ();
3818 return _empty_type_parameter_list
;
3822 void skip_type_argument_list () throws ParseError
{
3823 if (accept (TokenType
.OF
)) {
3824 if (accept (TokenType
.OPEN_PARENS
)) {
3827 } while (accept (TokenType
.COMMA
));
3828 expect (TokenType
.CLOSE_PARENS
);
3832 } while (accept (TokenType
.COMMA
));
3838 // try to parse type argument list
3839 List
<DataType
>?
parse_type_argument_list (bool maybe_expression
) throws ParseError
{
3840 var begin
= get_location ();
3841 if (accept (TokenType
.OF
)) {
3842 var list
= new ArrayList
<DataType
> ();
3843 var inParens
= false;
3845 // Optional parens allow multi arg types in function signature: "dict of (int, string)"
3846 // See: https://bugzilla.gnome.org/show_bug.cgi?id=611191
3847 if (accept (TokenType
.OPEN_PARENS
)) {
3852 switch (current ()) {
3853 case TokenType
.VOID
:
3854 case TokenType
.DYNAMIC
:
3855 case TokenType
.UNOWNED
:
3856 case TokenType
.WEAK
:
3857 case TokenType
.IDENTIFIER
:
3858 var type
= parse_type (true, true);
3866 } while (accept (TokenType
.COMMA
));
3869 expect (TokenType
.CLOSE_PARENS
);
3877 MemberAccess
parse_member_name (Expression? base_expr
= null) throws ParseError
{
3878 var begin
= get_location ();
3879 MemberAccess expr
= null;
3881 string id
= parse_identifier ();
3882 List
<DataType
> type_arg_list
= parse_type_argument_list (false);
3883 expr
= new
MemberAccess (expr
!= null ? expr
: base_expr
, id
, get_src (begin
));
3884 if (type_arg_list
!= null) {
3885 foreach (DataType type_arg
in type_arg_list
) {
3886 expr
.add_type_argument (type_arg
);
3889 } while (accept (TokenType
.DOT
));