1 /* valagenieparser.vala
3 * Copyright (C) 2008 Jamie McCracken, Jürg Billeter
4 * Based on code by Jürg Billeter
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * Jamie McCracken jamiemcc gnome org
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;
52 public TokenType type
;
53 public SourceLocation begin
;
54 public SourceLocation end
;
72 tokens
= new TokenInfo
[BUFFER_SIZE
];
74 current_expr_is_lambda
= false;
78 * Parses all .gs source files in the specified code context and
81 * @param context a code context
83 public void parse (CodeContext context
) {
84 this
.context
= context
;
85 context
.accept (this
);
88 public override void visit_source_file (SourceFile source_file
) {
89 if (source_file
.filename
.has_suffix (".gs")) {
90 parse_file (source_file
);
95 index
= (index
+ 1) % BUFFER_SIZE
;
98 SourceLocation begin
, end
;
99 TokenType type
= scanner
.read_token (out begin
, out end
);
100 tokens
[index
].type
= type
;
101 tokens
[index
].begin
= begin
;
102 tokens
[index
].end
= end
;
105 return (tokens
[index
].type
!= TokenType
.EOF
);
108 inline
void prev () {
109 index
= (index
- 1 + BUFFER_SIZE
) % BUFFER_SIZE
;
111 assert (size
<= BUFFER_SIZE
);
114 inline TokenType
current () {
115 return tokens
[index
].type
;
118 inline
bool accept (TokenType type
) {
119 if (current () == type
) {
126 inline
bool accept_terminator () {
127 if (current () == TokenType
.SEMICOLON
|| current () == TokenType
.EOL
) {
134 inline
bool accept_block () {
136 bool has_term
= accept_terminator ();
138 if (accept (TokenType
.INDENT
)) {
150 string get_error (string msg
) {
151 var begin
= get_location ();
153 Report
.error (get_src (begin
), "syntax error, " + msg
);
157 inline
bool expect (TokenType type
) throws ParseError
{
162 TokenType cur
= current ();
163 TokenType pre
= tokens
[index
- 1].type
;
165 throw new ParseError
.SYNTAX (get_error ("expected %s but got %s with previous %s".printf (type
.to_string (), cur
.to_string (), pre
.to_string())));
168 inline
bool expect_terminator () throws ParseError
{
169 if (accept_terminator ()) {
173 TokenType cur
= current ();
175 throw new ParseError
.SYNTAX (get_error ("expected line end or semicolon but got %s".printf (cur
.to_string())));
178 inline SourceLocation
get_location () {
179 return tokens
[index
].begin
;
182 string get_current_string () {
183 return ((string) tokens
[index
].begin
.pos
).ndup ((tokens
[index
].end
.pos
- tokens
[index
].begin
.pos
));
186 string get_last_string () {
187 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
188 return ((string) tokens
[last_index
].begin
.pos
).ndup ((tokens
[last_index
].end
.pos
- tokens
[last_index
].begin
.pos
));
191 SourceReference
get_src (SourceLocation begin
) {
192 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
194 return new
SourceReference (scanner
.source_file
, begin
.line
, begin
.column
, tokens
[last_index
].end
.line
, tokens
[last_index
].end
.column
);
197 SourceReference
get_current_src () {
198 return new
SourceReference (scanner
.source_file
, tokens
[index
].begin
.line
, tokens
[index
].begin
.column
, tokens
[index
].end
.line
, tokens
[index
].end
.column
);
201 void rollback (SourceLocation location
) {
202 while (tokens
[index
].begin
.pos
!= location
.pos
) {
207 inline SymbolAccessibility
get_access (string s
) {
209 return SymbolAccessibility
.PRIVATE
;
212 return SymbolAccessibility
.PUBLIC
;
215 void skip_identifier () throws ParseError
{
216 // also accept keywords as identifiers where there is no conflict
217 switch (current ()) {
218 case TokenType
.ABSTRACT
:
220 case TokenType
.ASSERT
:
221 case TokenType
.ASYNC
:
222 case TokenType
.BREAK
:
223 case TokenType
.CLASS
:
224 case TokenType
.CONST
:
225 case TokenType
.CONTINUE
:
226 case TokenType
.DEDENT
:
228 case TokenType
.DEFAULT
:
229 case TokenType
.DELEGATE
:
230 case TokenType
.DELETE
:
232 case TokenType
.DOWNTO
:
233 case TokenType
.DYNAMIC
:
237 case TokenType
.ENSURES
:
238 case TokenType
.ERRORDOMAIN
:
239 case TokenType
.EVENT
:
240 case TokenType
.EXCEPT
:
241 case TokenType
.EXTERN
:
242 case TokenType
.FALSE
:
243 case TokenType
.FINAL
:
244 case TokenType
.FINALLY
:
247 case TokenType
.IDENTIFIER
:
250 case TokenType
.INDENT
:
252 case TokenType
.INLINE
:
253 case TokenType
.INTERFACE
:
254 case TokenType
.INTERNAL
:
258 case TokenType
.NAMESPACE
:
263 case TokenType
.OVERRIDE
:
264 case TokenType
.OWNED
:
266 case TokenType
.PRINT
:
267 case TokenType
.PRIVATE
:
269 case TokenType
.RAISE
:
270 case TokenType
.RAISES
:
272 case TokenType
.REQUIRES
:
273 case TokenType
.RETURN
:
275 case TokenType
.SIZEOF
:
276 case TokenType
.STATIC
:
277 case TokenType
.STRUCT
:
278 case TokenType
.SUPER
:
283 case TokenType
.TYPEOF
:
284 case TokenType
.UNOWNED
:
287 case TokenType
.VIRTUAL
:
289 case TokenType
.VOLATILE
:
292 case TokenType
.WHILE
:
293 case TokenType
.YIELD
:
296 case TokenType
.INTEGER_LITERAL
:
297 case TokenType
.REAL_LITERAL
:
298 // also accept integer and real literals
299 // as long as they contain at least one character
300 // and no decimal point
301 // for example, 2D and 3D
302 string id
= get_current_string ();
303 if (id
[id
.length
- 1].isalpha () && !("." in id
)) {
309 throw new ParseError
.SYNTAX (get_error ("expected identifier"));
313 string parse_identifier () throws ParseError
{
315 return get_last_string ();
318 Expression
parse_literal () throws ParseError
{
319 var begin
= get_location ();
321 switch (current ()) {
324 return new
BooleanLiteral (true, get_src (begin
));
325 case TokenType
.FALSE
:
327 return new
BooleanLiteral (false, get_src (begin
));
328 case TokenType
.INTEGER_LITERAL
:
330 return new
IntegerLiteral (get_last_string (), get_src (begin
));
331 case TokenType
.REAL_LITERAL
:
333 return new
RealLiteral (get_last_string (), get_src (begin
));
334 case TokenType
.CHARACTER_LITERAL
:
336 // FIXME validate and unescape here and just pass unichar to CharacterLiteral
337 var lit
= new
CharacterLiteral (get_last_string (), get_src (begin
));
339 Report
.error (lit
.source_reference
, "invalid character literal");
342 case TokenType
.STRING_LITERAL
:
344 return new
StringLiteral (get_last_string (), get_src (begin
));
345 case TokenType
.VERBATIM_STRING_LITERAL
:
347 string raw_string
= get_last_string ();
348 string escaped_string
= raw_string
.substring (3, raw_string
.len () - 6).escape ("");
349 return new
StringLiteral ("\"%s\"".printf (escaped_string
), get_src (begin
));
352 return new
NullLiteral (get_src (begin
));
354 throw new ParseError
.SYNTAX (get_error ("expected literal"));
358 public void parse_file (SourceFile source_file
) {
359 scanner
= new
Scanner (source_file
);
360 scanner
.parse_file_comments ();
361 scanner
.indent_spaces
= 0;
368 var begin
= get_location ();
369 /* see if there is an indent attribute */
370 if (accept (TokenType
.OPEN_BRACKET
)) {
371 var id
= parse_identifier ();
372 if (id
== "indent") {
373 expect (TokenType
.ASSIGN
);
374 expect (TokenType
.INTEGER_LITERAL
);
375 scanner
.indent_spaces
= get_last_string().to_int();
376 expect (TokenType
.CLOSE_BRACKET
);
377 expect (TokenType
.EOL
);
383 parse_using_directives (context
.root
);
384 parse_declarations (context
.root
, true);
385 } catch (ParseError e
) {
392 void skip_symbol_name () throws ParseError
{
395 } while (accept (TokenType
.DOT
));
398 UnresolvedSymbol
parse_symbol_name () throws ParseError
{
399 var begin
= get_location ();
400 UnresolvedSymbol sym
= null;
402 string name
= parse_identifier ();
403 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
404 } while (accept (TokenType
.DOT
));
408 void skip_type () throws ParseError
{
409 if (accept (TokenType
.VOID
)) {
410 while (accept (TokenType
.STAR
)) {
414 accept (TokenType
.DYNAMIC
);
415 accept (TokenType
.OWNED
);
416 accept (TokenType
.UNOWNED
);
417 accept (TokenType
.WEAK
);
418 if (accept (TokenType
.ARRAY
) || accept (TokenType
.LIST
) || accept (TokenType
.DICT
)) {
419 accept (TokenType
.OF
);
423 skip_type_argument_list ();
424 while (accept (TokenType
.OPEN_BRACKET
)) {
426 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
429 } while (accept (TokenType
.COMMA
));
430 expect (TokenType
.CLOSE_BRACKET
);
432 accept (TokenType
.OP_NEG
);
433 accept (TokenType
.INTERR
);
434 accept (TokenType
.HASH
);
437 DataType
parse_type (bool owned_by_default
= true) throws ParseError
{
438 var begin
= get_location ();
440 if (accept (TokenType
.VOID
)) {
441 DataType type
= new
VoidType ();
442 while (accept (TokenType
.STAR
)) {
443 type
= new
PointerType (type
);
448 List
<DataType
> type_arg_list
= null;
449 UnresolvedSymbol sym
= null;
451 bool is_dynamic
= accept (TokenType
.DYNAMIC
);
452 bool value_owned
= owned_by_default
;
453 if (owned_by_default
) {
454 if (accept (TokenType
.UNOWNED
)
455 || accept (TokenType
.WEAK
)) {
459 value_owned
= accept (TokenType
.OWNED
);
463 bool is_array
= false;
465 if (accept (TokenType
.ARRAY
)) {
466 expect (TokenType
.OF
);
471 bool is_list
= false;
473 if (accept (TokenType
.LIST
)) {
474 expect (TokenType
.OF
);
480 bool is_dict
= false;
482 if (accept (TokenType
.DICT
)) {
483 expect (TokenType
.OF
);
489 var sym_parent
= new
UnresolvedSymbol (null, "Gee", get_src (begin
));
490 sym
= new
UnresolvedSymbol (sym_parent
, "ArrayList", get_src (begin
));
491 } else if (is_dict
) {
492 var sym_parent
= new
UnresolvedSymbol (null, "Gee", get_src (begin
));
493 sym
= new
UnresolvedSymbol (sym_parent
, "HashMap", get_src (begin
));
495 sym
= parse_symbol_name ();
498 type_arg_list
= parse_type_argument_list (false);
500 DataType type
= new UnresolvedType
.from_symbol (sym
, get_src (begin
));
501 if (type_arg_list
!= null) {
502 foreach (DataType type_arg
in type_arg_list
) {
503 type
.add_type_argument (type_arg
);
507 while (accept (TokenType
.STAR
)) {
508 type
= new
PointerType (type
, get_src (begin
));
511 if (!(type is PointerType
)) {
512 type
.nullable
= accept (TokenType
.INTERR
);
517 if (!accept (TokenType
.OPEN_BRACKET
)) {
518 type
.value_owned
= true;
519 type
= new
ArrayType (type
, 1, get_src (begin
));
520 type
.nullable
= accept (TokenType
.INTERR
);
525 while (accept (TokenType
.OPEN_BRACKET
)) {
526 bool invalid_array
= false;
530 // required for decision between expression and declaration statement
531 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
533 // only used for parsing, reject use as real type
534 invalid_array
= true;
537 while (accept (TokenType
.COMMA
));
538 expect (TokenType
.CLOSE_BRACKET
);
540 type
.value_owned
= true;
541 var array_type
= new
ArrayType (type
, array_rank
, get_src (begin
));
542 array_type
.nullable
= accept (TokenType
.INTERR
);
544 array_type
.invalid_syntax
= invalid_array
;
551 if (!owned_by_default
) {
552 value_owned
= accept (TokenType
.HASH
);
555 type
.is_dynamic
= is_dynamic
;
556 type
.value_owned
= value_owned
;
560 DataType?
parse_inline_array_type (DataType? type
) throws ParseError
{
561 var begin
= get_location ();
563 // inline-allocated array
564 if (type
!= null && accept (TokenType
.OPEN_BRACKET
)) {
565 int array_length
= -1;
567 if (current () != TokenType
.CLOSE_BRACKET
) {
568 if (current () != TokenType
.INTEGER_LITERAL
) {
569 throw new ParseError
.SYNTAX (get_error ("expected `]' or integer literal"));
572 var length_literal
= (IntegerLiteral
) parse_literal ();
573 array_length
= length_literal
.value
.to_int ();
575 expect (TokenType
.CLOSE_BRACKET
);
577 var array_type
= new
ArrayType (type
, 1, get_src (begin
));
578 array_type
.inline_allocated
= true;
579 if (array_length
> 0) {
580 array_type
.fixed_length
= true;
581 array_type
.length
= array_length
;
590 List
<Expression
> parse_argument_list () throws ParseError
{
591 var list
= new ArrayList
<Expression
> ();
592 if (current () != TokenType
.CLOSE_PARENS
) {
594 list
.add (parse_argument ());
595 } while (accept (TokenType
.COMMA
));
600 Expression
parse_argument () throws ParseError
{
601 var begin
= get_location ();
603 if (accept (TokenType
.REF
)) {
604 var inner
= parse_expression ();
605 return new
UnaryExpression (UnaryOperator
.REF
, inner
, get_src (begin
));
606 } else if (accept (TokenType
.OUT
)) {
607 var inner
= parse_expression ();
608 return new
UnaryExpression (UnaryOperator
.OUT
, inner
, get_src (begin
));
610 return parse_expression ();
614 Expression
parse_primary_expression () throws ParseError
{
615 var begin
= get_location ();
619 switch (current ()) {
621 case TokenType
.FALSE
:
622 case TokenType
.INTEGER_LITERAL
:
623 case TokenType
.REAL_LITERAL
:
624 case TokenType
.CHARACTER_LITERAL
:
625 case TokenType
.STRING_LITERAL
:
626 case TokenType
.VERBATIM_STRING_LITERAL
:
628 expr
= parse_literal ();
630 case TokenType
.ASSERT
:
631 return parse_assert_expression ();
632 case TokenType
.OPEN_BRACE
:
633 expr
= parse_initializer ();
635 case TokenType
.OPEN_PARENS
:
636 expr
= parse_tuple ();
639 expr
= parse_this_access ();
641 case TokenType
.SUPER
:
642 expr
= parse_base_access ();
645 expr
= parse_object_or_array_creation_expression ();
647 case TokenType
.PRINT
:
648 return parse_print_expression ();
649 case TokenType
.SIZEOF
:
650 expr
= parse_sizeof_expression ();
652 case TokenType
.TYPEOF
:
653 expr
= parse_typeof_expression ();
655 case TokenType
.YIELD
:
656 expr
= parse_yield_expression ();
659 expr
= parse_simple_name ();
663 // process primary expressions that start with an inner primary expression
666 switch (current ()) {
668 expr
= parse_member_access (begin
, expr
);
670 case TokenType
.OP_PTR
:
671 expr
= parse_pointer_member_access (begin
, expr
);
673 case TokenType
.OPEN_PARENS
:
674 expr
= parse_method_call (begin
, expr
);
676 case TokenType
.OPEN_BRACKET
:
677 expr
= parse_element_access (begin
, expr
);
679 case TokenType
.OP_INC
:
680 expr
= parse_post_increment_expression (begin
, expr
);
682 case TokenType
.OP_DEC
:
683 expr
= parse_post_decrement_expression (begin
, expr
);
695 Expression
parse_simple_name () throws ParseError
{
696 var begin
= get_location ();
697 string id
= parse_identifier ();
698 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
699 var expr
= new
MemberAccess (null, id
, get_src (begin
));
700 if (type_arg_list
!= null) {
701 foreach (DataType type_arg
in type_arg_list
) {
702 expr
.add_type_argument (type_arg
);
708 Expression
parse_tuple () throws ParseError
{
709 expect (TokenType
.OPEN_PARENS
);
710 var expr_list
= new ArrayList
<Expression
> ();
711 if (current () != TokenType
.CLOSE_PARENS
) {
713 expr_list
.add (parse_expression ());
714 } while (accept (TokenType
.COMMA
));
716 expect (TokenType
.CLOSE_PARENS
);
717 if (expr_list
.size
!= 1) {
718 var tuple
= new
Tuple ();
719 foreach (Expression expr
in expr_list
) {
720 tuple
.add_expression (expr
);
724 return expr_list
.get (0);
727 Expression
parse_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
728 expect (TokenType
.DOT
);
729 string id
= parse_identifier ();
730 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
731 var expr
= new
MemberAccess (inner
, id
, get_src (begin
));
732 if (type_arg_list
!= null) {
733 foreach (DataType type_arg
in type_arg_list
) {
734 expr
.add_type_argument (type_arg
);
740 Expression
parse_pointer_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
741 expect (TokenType
.OP_PTR
);
742 string id
= parse_identifier ();
743 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
744 var expr
= new MemberAccess
.pointer (inner
, id
, get_src (begin
));
745 if (type_arg_list
!= null) {
746 foreach (DataType type_arg
in type_arg_list
) {
747 expr
.add_type_argument (type_arg
);
754 List
<Expression
> parse_print_argument_list () throws ParseError
{
755 var list
= new ArrayList
<Expression
> ();
757 var begin
= get_location ();
759 if (current () != TokenType
.CLOSE_PARENS
) {
761 var p_expr
= parse_expression ();
765 if (p_expr
!= null) {
768 if (p_expr is StringLiteral
) {
769 var s_exp
= (StringLiteral
) p_expr
;
770 var len
= s_exp
.value
.size ();
774 var st
= s_exp
.value
.ndup (len
-1);
779 string s
= "\"\\n\"";
780 var rhs
= new
StringLiteral (s
, get_src (begin
));
781 p_expr
= new
BinaryExpression (BinaryOperator
.PLUS
, p_expr
, rhs
, get_src (begin
));
788 } while (accept (TokenType
.COMMA
));
793 Expression
parse_print_expression () throws ParseError
{
794 var begin
= get_location ();
796 expect (TokenType
.PRINT
);
797 accept (TokenType
.OPEN_PARENS
);
799 var expr
= new
MemberAccess (null, "print", get_src (begin
));
801 var arg_list
= parse_print_argument_list ();
803 accept (TokenType
.CLOSE_PARENS
);
805 var print_expr
= new
MethodCall (expr
, get_src (begin
));
807 foreach (Expression arg
in arg_list
) {
808 print_expr
.add_argument (arg
);
815 Expression
parse_assert_expression () throws ParseError
{
816 var begin
= get_location ();
818 expect (TokenType
.ASSERT
);
819 accept (TokenType
.OPEN_PARENS
);
821 var expr
= new
MemberAccess (null, "assert", get_src (begin
));
823 var arg_list
= parse_argument_list ();
825 accept (TokenType
.CLOSE_PARENS
);
827 var assert_expr
= new
MethodCall (expr
, get_src (begin
));
829 foreach (Expression arg
in arg_list
) {
830 assert_expr
.add_argument (arg
);
837 Expression
parse_method_call (SourceLocation begin
, Expression inner
) throws ParseError
{
838 expect (TokenType
.OPEN_PARENS
);
839 var arg_list
= parse_argument_list ();
840 expect (TokenType
.CLOSE_PARENS
);
841 var init_list
= parse_object_initializer ();
843 if (init_list
.size
> 0 && inner is MemberAccess
) {
844 // struct creation expression
845 var member
= (MemberAccess
) inner
;
846 member
.creation_member
= true;
848 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
849 expr
.struct_creation
= true;
850 foreach (Expression arg
in arg_list
) {
851 expr
.add_argument (arg
);
853 foreach (MemberInitializer initializer
in init_list
) {
854 expr
.add_member_initializer (initializer
);
858 var expr
= new
MethodCall (inner
, get_src (begin
));
859 foreach (Expression arg
in arg_list
) {
860 expr
.add_argument (arg
);
866 Expression
parse_element_access (SourceLocation begin
, Expression inner
) throws ParseError
{
867 expect (TokenType
.OPEN_BRACKET
);
868 var index_list
= parse_expression_list ();
869 expect (TokenType
.CLOSE_BRACKET
);
871 var expr
= new
ElementAccess (inner
, get_src (begin
));
872 foreach (Expression index
in index_list
) {
873 expr
.append_index (index
);
878 List
<Expression
> parse_expression_list () throws ParseError
{
879 var list
= new ArrayList
<Expression
> ();
881 list
.add (parse_expression ());
882 } while (accept (TokenType
.COMMA
));
886 Expression
parse_this_access () throws ParseError
{
887 var begin
= get_location ();
888 expect (TokenType
.THIS
);
889 return new
MemberAccess (null, "this", get_src (begin
));
892 Expression
parse_base_access () throws ParseError
{
893 var begin
= get_location ();
894 expect (TokenType
.SUPER
);
895 return new
BaseAccess (get_src (begin
));
898 Expression
parse_post_increment_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
899 expect (TokenType
.OP_INC
);
900 return new
PostfixExpression (inner
, true, get_src (begin
));
903 Expression
parse_post_decrement_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
904 expect (TokenType
.OP_DEC
);
905 return new
PostfixExpression (inner
, false, get_src (begin
));
908 Expression
parse_object_or_array_creation_expression () throws ParseError
{
909 var begin
= get_location ();
910 expect (TokenType
.NEW
);
912 if (accept (TokenType
.ARRAY
)) {
913 expect (TokenType
.OF
);
914 var mtype
= parse_type ();
915 var expr
= parse_array_creation_expression (begin
, mtype
);
919 if (accept (TokenType
.LIST
)) {
920 expect (TokenType
.OF
);
921 var mtype
= parse_type ();
922 var expr
= parse_list_creation_expression (begin
, mtype
);
926 if (accept (TokenType
.DICT
)) {
927 expect (TokenType
.OF
);
928 var mtype1
= parse_type ();
929 expect (TokenType
.COMMA
);
930 var mtype2
= parse_type ();
931 var expr
= parse_dict_creation_expression (begin
, mtype1
, mtype2
);
936 var member
= parse_member_name ();
937 var expr
= parse_object_creation_expression (begin
, member
);
942 Expression
parse_object_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
943 member
.creation_member
= true;
944 List
<Expression
> arg_list
;
945 if (accept (TokenType
.OPEN_PARENS
)) {
946 arg_list
= parse_argument_list ();
947 expect (TokenType
.CLOSE_PARENS
);
949 arg_list
= new ArrayList
<Expression
> ();
952 var init_list
= parse_object_initializer ();
954 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
955 foreach (Expression arg
in arg_list
) {
956 expr
.add_argument (arg
);
958 foreach (MemberInitializer initializer
in init_list
) {
959 expr
.add_member_initializer (initializer
);
964 Expression
parse_array_creation_expression (SourceLocation begin
, DataType element_type
) throws ParseError
{
965 bool size_specified
= false;
966 List
<Expression
> size_specifier_list
= null;
968 DataType etype
= element_type
.copy ();
970 var has_bracket
= accept (TokenType
.OPEN_BRACKET
);
974 // array of arrays: new T[][42]
975 etype
= new
ArrayType (etype
, size_specifier_list
.size
, etype
.source_reference
);
980 size_specifier_list
= new ArrayList
<Expression
> ();
982 Expression size
= null;
983 if (has_bracket
&& current () != TokenType
.CLOSE_BRACKET
&& current () != TokenType
.COMMA
) {
984 size
= parse_expression ();
985 size_specified
= true;
987 size_specifier_list
.add (size
);
988 } while (accept (TokenType
.COMMA
));
991 expect (TokenType
.CLOSE_BRACKET
);
993 } while (accept (TokenType
.OPEN_BRACKET
));
995 InitializerList initializer
= null;
996 if (accept (TokenType
.ASSIGN
)) {
997 initializer
= parse_initializer ();
1000 var expr
= new
ArrayCreationExpression (etype
, size_specifier_list
.size
, initializer
, get_src (begin
));
1001 if (size_specified
) {
1002 foreach (Expression size
in size_specifier_list
) {
1003 expr
.append_size (size
);
1010 Expression
parse_list_creation_expression (SourceLocation begin
, DataType element_type
) throws ParseError
{
1012 MemberAccess list_member
= null, parent_member
= null;
1014 parent_member
= new
MemberAccess (null, "Gee", get_src (begin
));
1015 list_member
= new
MemberAccess (parent_member
, "ArrayList", get_src (begin
));
1016 list_member
.add_type_argument (element_type
);
1018 list_member
.creation_member
= true;
1020 var expr
= new
ObjectCreationExpression (list_member
, get_src (begin
));
1021 var t
= element_type
.to_qualified_string ();
1022 if (t
== "string") {
1023 parent_member
= new
MemberAccess (null, "GLib", get_src (begin
));
1024 expr
.add_argument (new
MemberAccess (parent_member
, "str_equal", get_src (begin
)));
1026 } else if (t
== "int") {
1027 parent_member
= new
MemberAccess (null, "GLib", get_src (begin
));
1028 expr
.add_argument (new
MemberAccess (parent_member
, "int_equal", get_src (begin
)));
1034 Expression
parse_dict_creation_expression (SourceLocation begin
, DataType key_type
, DataType value_type
) throws ParseError
{
1036 MemberAccess dict_member
= null, parent_member
= null, dict_hash
= null, dict_equal
= null;
1038 parent_member
= new
MemberAccess (null, "Gee", get_src (begin
));
1039 dict_member
= new
MemberAccess (parent_member
, "HashMap", get_src (begin
));
1040 dict_member
.add_type_argument (key_type
);
1041 dict_member
.add_type_argument (value_type
);
1043 var key_type_name
= key_type
.to_qualified_string ();
1044 if (key_type_name
== "string") {
1045 parent_member
= new
MemberAccess (null, "GLib", get_src (begin
));
1046 dict_hash
= new
MemberAccess (parent_member
, "str_hash", get_src (begin
));
1047 dict_equal
= new
MemberAccess (parent_member
, "str_equal", get_src (begin
));
1049 } else if (key_type_name
== "int") {
1050 parent_member
= new
MemberAccess (null, "GLib", get_src (begin
));
1051 dict_hash
= new
MemberAccess (parent_member
, "int_hash", get_src (begin
));
1052 dict_equal
= new
MemberAccess (parent_member
, "int_equal", get_src (begin
));
1055 dict_member
.creation_member
= true;
1057 var expr
= new
ObjectCreationExpression (dict_member
, get_src (begin
));
1059 if (dict_hash
!= null && dict_equal
!= null) {
1060 expr
.add_argument (dict_hash
);
1061 expr
.add_argument (dict_equal
);
1069 List
<MemberInitializer
> parse_object_initializer () throws ParseError
{
1070 var list
= new ArrayList
<MemberInitializer
> ();
1071 if (accept (TokenType
.OPEN_BRACE
)) {
1073 list
.add (parse_member_initializer ());
1074 } while (accept (TokenType
.COMMA
));
1075 expect (TokenType
.CLOSE_BRACE
);
1080 MemberInitializer
parse_member_initializer () throws ParseError
{
1081 var begin
= get_location ();
1082 string id
= parse_identifier ();
1083 expect (TokenType
.ASSIGN
);
1084 var expr
= parse_expression ();
1086 return new
MemberInitializer (id
, expr
, get_src (begin
));
1089 Expression
parse_yield_expression () throws ParseError
{
1090 var begin
= get_location ();
1091 expect (TokenType
.YIELD
);
1092 var member
= parse_member_name ();
1093 var call
= (MethodCall
) parse_method_call (begin
, member
);
1094 call
.is_yield_expression
= true;
1098 Expression
parse_sizeof_expression () throws ParseError
{
1099 var begin
= get_location ();
1100 expect (TokenType
.SIZEOF
);
1101 expect (TokenType
.OPEN_PARENS
);
1102 var type
= parse_type ();
1103 expect (TokenType
.CLOSE_PARENS
);
1105 return new
SizeofExpression (type
, get_src (begin
));
1108 Expression
parse_typeof_expression () throws ParseError
{
1109 var begin
= get_location ();
1110 expect (TokenType
.TYPEOF
);
1111 expect (TokenType
.OPEN_PARENS
);
1112 var type
= parse_type ();
1113 expect (TokenType
.CLOSE_PARENS
);
1115 return new
TypeofExpression (type
, get_src (begin
));
1118 UnaryOperator
get_unary_operator (TokenType token_type
) {
1119 switch (token_type
) {
1120 case TokenType
.PLUS
: return UnaryOperator
.PLUS
;
1121 case TokenType
.MINUS
: return UnaryOperator
.MINUS
;
1122 case TokenType
.OP_NEG
: return UnaryOperator
.LOGICAL_NEGATION
;
1123 case TokenType
.TILDE
: return UnaryOperator
.BITWISE_COMPLEMENT
;
1124 case TokenType
.OP_INC
: return UnaryOperator
.INCREMENT
;
1125 case TokenType
.OP_DEC
: return UnaryOperator
.DECREMENT
;
1126 default: return UnaryOperator
.NONE
;
1130 Expression
parse_unary_expression () throws ParseError
{
1131 var begin
= get_location ();
1132 var operator
= get_unary_operator (current ());
1133 if (operator
!= UnaryOperator
.NONE
) {
1135 var op
= parse_unary_expression ();
1136 return new
UnaryExpression (operator
, op
, get_src (begin
));
1138 switch (current ()) {
1139 case TokenType
.HASH
:
1141 var op
= parse_unary_expression ();
1142 return new
ReferenceTransferExpression (op
, get_src (begin
));
1143 case TokenType
.OPEN_PARENS
:
1145 switch (current ()) {
1146 case TokenType
.OWNED
:
1149 if (accept (TokenType
.CLOSE_PARENS
)) {
1150 var op
= parse_unary_expression ();
1151 return new
ReferenceTransferExpression (op
, get_src (begin
));
1154 case TokenType
.VOID
:
1155 case TokenType
.DYNAMIC
:
1156 case TokenType
.IDENTIFIER
:
1157 case TokenType
.ARRAY
:
1158 case TokenType
.LIST
:
1159 case TokenType
.DICT
:
1160 var type
= parse_type ();
1161 if (accept (TokenType
.CLOSE_PARENS
)) {
1162 // check follower to decide whether to create cast expression
1163 switch (current ()) {
1164 case TokenType
.OP_NEG
:
1165 case TokenType
.TILDE
:
1166 case TokenType
.OPEN_PARENS
:
1167 case TokenType
.TRUE
:
1168 case TokenType
.FALSE
:
1169 case TokenType
.INTEGER_LITERAL
:
1170 case TokenType
.REAL_LITERAL
:
1171 case TokenType
.CHARACTER_LITERAL
:
1172 case TokenType
.STRING_LITERAL
:
1173 case TokenType
.VERBATIM_STRING_LITERAL
:
1174 case TokenType
.NULL
:
1175 case TokenType
.THIS
:
1176 case TokenType
.SUPER
:
1178 case TokenType
.SIZEOF
:
1179 case TokenType
.TYPEOF
:
1180 case TokenType
.IDENTIFIER
:
1181 case TokenType
.PARAMS
:
1182 var inner
= parse_unary_expression ();
1183 return new
CastExpression (inner
, type
, get_src (begin
), false);
1192 // no cast expression
1195 case TokenType
.STAR
:
1197 var op
= parse_unary_expression ();
1198 return new
PointerIndirection (op
, get_src (begin
));
1199 case TokenType
.BITWISE_AND
:
1201 var op
= parse_unary_expression ();
1202 return new
AddressofExpression (op
, get_src (begin
));
1207 var expr
= parse_primary_expression ();
1211 BinaryOperator
get_binary_operator (TokenType token_type
) {
1212 switch (token_type
) {
1213 case TokenType
.STAR
: return BinaryOperator
.MUL
;
1214 case TokenType
.DIV
: return BinaryOperator
.DIV
;
1215 case TokenType
.PERCENT
: return BinaryOperator
.MOD
;
1216 case TokenType
.PLUS
: return BinaryOperator
.PLUS
;
1217 case TokenType
.MINUS
: return BinaryOperator
.MINUS
;
1218 case TokenType
.OP_LT
: return BinaryOperator
.LESS_THAN
;
1219 case TokenType
.OP_GT
: return BinaryOperator
.GREATER_THAN
;
1220 case TokenType
.OP_LE
: return BinaryOperator
.LESS_THAN_OR_EQUAL
;
1221 case TokenType
.OP_GE
: return BinaryOperator
.GREATER_THAN_OR_EQUAL
;
1222 case TokenType
.OP_EQ
: return BinaryOperator
.EQUALITY
;
1225 if (current () == TokenType
.OP_NEG
) {
1227 return BinaryOperator
.INEQUALITY
;
1230 return BinaryOperator
.EQUALITY
;
1231 case TokenType
.OP_NE
: return BinaryOperator
.INEQUALITY
;
1232 default: return BinaryOperator
.NONE
;
1236 Expression
parse_multiplicative_expression () throws ParseError
{
1237 var begin
= get_location ();
1238 var left
= parse_unary_expression ();
1241 var operator
= get_binary_operator (current ());
1243 case BinaryOperator
.MUL
:
1244 case BinaryOperator
.DIV
:
1245 case BinaryOperator
.MOD
:
1247 var right
= parse_unary_expression ();
1248 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1258 Expression
parse_additive_expression () throws ParseError
{
1259 var begin
= get_location ();
1260 var left
= parse_multiplicative_expression ();
1263 var operator
= get_binary_operator (current ());
1265 case BinaryOperator
.PLUS
:
1266 case BinaryOperator
.MINUS
:
1268 var right
= parse_multiplicative_expression ();
1269 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1279 Expression
parse_shift_expression () throws ParseError
{
1280 var begin
= get_location ();
1281 var left
= parse_additive_expression ();
1284 switch (current ()) {
1285 case TokenType
.OP_SHIFT_LEFT
:
1287 var right
= parse_additive_expression ();
1288 left
= new
BinaryExpression (BinaryOperator
.SHIFT_LEFT
, left
, right
, get_src (begin
));
1290 // don't use OP_SHIFT_RIGHT to support >> for nested generics
1291 case TokenType
.OP_GT
:
1292 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1294 // only accept >> when there is no space between the two > signs
1295 if (current () == TokenType
.OP_GT
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1297 var right
= parse_additive_expression ();
1298 left
= new
BinaryExpression (BinaryOperator
.SHIFT_RIGHT
, left
, right
, get_src (begin
));
1312 Expression
parse_relational_expression () throws ParseError
{
1313 var begin
= get_location ();
1314 var left
= parse_shift_expression ();
1317 var operator
= get_binary_operator (current ());
1319 case BinaryOperator
.LESS_THAN
:
1320 case BinaryOperator
.LESS_THAN_OR_EQUAL
:
1321 case BinaryOperator
.GREATER_THAN_OR_EQUAL
:
1323 var right
= parse_shift_expression ();
1324 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1326 case BinaryOperator
.GREATER_THAN
:
1328 // ignore >> and >>= (two tokens due to generics)
1329 if (current () != TokenType
.OP_GT
&& current () != TokenType
.OP_GE
) {
1330 var right
= parse_shift_expression ();
1331 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1338 switch (current ()) {
1341 var type
= parse_type ();
1342 left
= new
TypeCheck (left
, type
, get_src (begin
));
1346 var type
= parse_type ();
1347 left
= new
CastExpression (left
, type
, get_src (begin
), true);
1359 Expression
parse_equality_expression () throws ParseError
{
1360 var begin
= get_location ();
1361 var left
= parse_relational_expression ();
1364 var operator
= get_binary_operator (current ());
1366 case BinaryOperator
.INEQUALITY
:
1367 case BinaryOperator
.EQUALITY
:
1368 if ((operator
== BinaryOperator
.INEQUALITY
) && (current () == TokenType
.IS
)) {
1372 var right
= parse_relational_expression ();
1373 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1383 Expression
parse_and_expression () throws ParseError
{
1384 var begin
= get_location ();
1385 var left
= parse_equality_expression ();
1386 while (accept (TokenType
.BITWISE_AND
)) {
1387 var right
= parse_equality_expression ();
1388 left
= new
BinaryExpression (BinaryOperator
.BITWISE_AND
, left
, right
, get_src (begin
));
1393 Expression
parse_exclusive_or_expression () throws ParseError
{
1394 var begin
= get_location ();
1395 var left
= parse_and_expression ();
1396 while (accept (TokenType
.CARRET
)) {
1397 var right
= parse_and_expression ();
1398 left
= new
BinaryExpression (BinaryOperator
.BITWISE_XOR
, left
, right
, get_src (begin
));
1403 Expression
parse_inclusive_or_expression () throws ParseError
{
1404 var begin
= get_location ();
1405 var left
= parse_exclusive_or_expression ();
1406 while (accept (TokenType
.BITWISE_OR
)) {
1407 var right
= parse_exclusive_or_expression ();
1408 left
= new
BinaryExpression (BinaryOperator
.BITWISE_OR
, left
, right
, get_src (begin
));
1413 Expression
parse_in_expression () throws ParseError
{
1414 var begin
= get_location ();
1415 var left
= parse_inclusive_or_expression ();
1416 while (accept (TokenType
.IN
)) {
1417 var right
= parse_inclusive_or_expression ();
1418 left
= new
BinaryExpression (BinaryOperator
.IN
, left
, right
, get_src (begin
));
1423 Expression
parse_conditional_and_expression () throws ParseError
{
1424 var begin
= get_location ();
1425 var left
= parse_in_expression ();
1426 while (accept (TokenType
.OP_AND
)) {
1427 var right
= parse_in_expression ();
1428 left
= new
BinaryExpression (BinaryOperator
.AND
, left
, right
, get_src (begin
));
1433 Expression
parse_conditional_or_expression () throws ParseError
{
1434 var begin
= get_location ();
1435 var left
= parse_conditional_and_expression ();
1436 while (accept (TokenType
.OP_OR
)) {
1437 var right
= parse_conditional_and_expression ();
1438 left
= new
BinaryExpression (BinaryOperator
.OR
, left
, right
, get_src (begin
));
1443 Expression
parse_conditional_expression () throws ParseError
{
1444 var begin
= get_location ();
1445 var condition
= parse_conditional_or_expression ();
1446 if (accept (TokenType
.INTERR
)) {
1447 var true_expr
= parse_expression ();
1448 expect (TokenType
.COLON
);
1449 var false_expr
= parse_expression ();
1450 return new
ConditionalExpression (condition
, true_expr
, false_expr
, get_src (begin
));
1456 Expression
parse_lambda_expression () throws ParseError
{
1457 var begin
= get_location ();
1458 List
<string> params
= new ArrayList
<string> ();
1460 expect (TokenType
.DEF
);
1462 if (accept (TokenType
.OPEN_PARENS
)) {
1463 if (current () != TokenType
.CLOSE_PARENS
) {
1465 params
.add (parse_identifier ());
1466 } while (accept (TokenType
.COMMA
));
1468 expect (TokenType
.CLOSE_PARENS
);
1470 params
.add (parse_identifier ());
1474 LambdaExpression lambda
;
1475 if (accept_block ()) {
1476 var block
= parse_block ();
1477 lambda
= new LambdaExpression
.with_statement_body (block
, get_src (begin
));
1479 var expr
= parse_expression ();
1480 lambda
= new
LambdaExpression (expr
, get_src (begin
));
1481 expect_terminator ();
1486 foreach (string param
in params
) {
1487 lambda
.add_parameter (param
);
1492 AssignmentOperator
get_assignment_operator (TokenType token_type
) {
1493 switch (token_type
) {
1494 case TokenType
.ASSIGN
: return AssignmentOperator
.SIMPLE
;
1495 case TokenType
.ASSIGN_ADD
: return AssignmentOperator
.ADD
;
1496 case TokenType
.ASSIGN_SUB
: return AssignmentOperator
.SUB
;
1497 case TokenType
.ASSIGN_BITWISE_OR
: return AssignmentOperator
.BITWISE_OR
;
1498 case TokenType
.ASSIGN_BITWISE_AND
: return AssignmentOperator
.BITWISE_AND
;
1499 case TokenType
.ASSIGN_BITWISE_XOR
: return AssignmentOperator
.BITWISE_XOR
;
1500 case TokenType
.ASSIGN_DIV
: return AssignmentOperator
.DIV
;
1501 case TokenType
.ASSIGN_MUL
: return AssignmentOperator
.MUL
;
1502 case TokenType
.ASSIGN_PERCENT
: return AssignmentOperator
.PERCENT
;
1503 case TokenType
.ASSIGN_SHIFT_LEFT
: return AssignmentOperator
.SHIFT_LEFT
;
1504 default: return AssignmentOperator
.NONE
;
1508 Expression
parse_expression () throws ParseError
{
1509 if (current () == TokenType
.DEF
) {
1510 var lambda
= parse_lambda_expression ();
1511 current_expr_is_lambda
= true;
1515 var begin
= get_location ();
1516 Expression expr
= parse_conditional_expression ();
1519 var operator
= get_assignment_operator (current ());
1520 if (operator
!= AssignmentOperator
.NONE
) {
1522 var rhs
= parse_expression ();
1523 expr
= new
Assignment (expr
, rhs
, operator
, get_src (begin
));
1524 } else if (current () == TokenType
.OP_GT
) { // >>=
1525 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1527 // only accept >>= when there is no space between the two > signs
1528 if (current () == TokenType
.OP_GE
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1530 var rhs
= parse_expression ();
1531 expr
= new
Assignment (expr
, rhs
, AssignmentOperator
.SHIFT_RIGHT
, get_src (begin
));
1545 Statement
get_for_statement_type () throws ParseError
{
1547 var begin
= get_location ();
1548 bool is_foreach
= false;
1550 while (current () != TokenType
.EOL
&& current () != TokenType
.DO
) {
1552 if (accept (TokenType
.IN
)) {
1561 return parse_foreach_statement ();
1563 return parse_for_statement ();
1568 void parse_statements (Block block
) throws ParseError
{
1569 while (current () != TokenType
.DEDENT
1570 && current () != TokenType
.WHEN
1571 && current () != TokenType
.DEFAULT
) {
1573 Statement stmt
= null;
1574 bool is_decl
= false;
1575 comment
= scanner
.pop_comment ();
1576 switch (current ()) {
1578 /* skip over requires and ensures as we handled them in method declaration */
1579 case TokenType
.REQUIRES
:
1580 case TokenType
.ENSURES
:
1581 var begin
= get_location ();
1584 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
1585 while (current () != TokenType
.DEDENT
) {
1589 expect (TokenType
.DEDENT
);
1591 while (current () != TokenType
.EOL
) {
1595 expect (TokenType
.EOL
);
1598 stmt
= new
EmptyStatement (get_src (begin
));
1602 case TokenType
.INDENT
:
1603 stmt
= parse_block ();
1605 case TokenType
.SEMICOLON
:
1606 case TokenType
.PASS
:
1607 stmt
= parse_empty_statement ();
1609 case TokenType
.PRINT
:
1610 case TokenType
.ASSERT
:
1611 stmt
= parse_expression_statement ();
1614 stmt
= parse_if_statement ();
1616 case TokenType
.CASE
:
1617 stmt
= parse_switch_statement ();
1619 case TokenType
.WHILE
:
1620 stmt
= parse_while_statement ();
1623 stmt
= parse_do_statement ();
1626 stmt
= get_for_statement_type ();
1628 case TokenType
.BREAK
:
1629 stmt
= parse_break_statement ();
1631 case TokenType
.CONTINUE
:
1632 stmt
= parse_continue_statement ();
1634 case TokenType
.RETURN
:
1635 stmt
= parse_return_statement ();
1637 case TokenType
.RAISE
:
1638 stmt
= parse_throw_statement ();
1641 stmt
= parse_try_statement ();
1643 case TokenType
.LOCK
:
1644 stmt
= parse_lock_statement ();
1646 case TokenType
.DELETE
:
1647 stmt
= parse_delete_statement ();
1651 parse_local_variable_declarations (block
);
1653 case TokenType
.YIELD
:
1654 stmt
= parse_yield_statement ();
1657 case TokenType
.OP_INC
:
1658 case TokenType
.OP_DEC
:
1659 case TokenType
.SUPER
:
1660 case TokenType
.THIS
:
1661 case TokenType
.OPEN_PARENS
:
1662 case TokenType
.STAR
:
1664 stmt
= parse_expression_statement ();
1667 bool is_expr
= is_expression ();
1669 stmt
= parse_expression_statement ();
1672 parse_local_variable_declarations (block
);
1678 block
.add_statement (stmt
);
1680 } catch (ParseError e
) {
1681 if (recover () != RecoveryState
.STATEMENT_BEGIN
) {
1682 // beginning of next declaration or end of file reached
1683 // return what we have so far
1690 bool is_expression () throws ParseError
{
1691 var begin
= get_location ();
1693 // decide between declaration and expression statement
1695 switch (current ()) {
1696 // invocation expression
1697 case TokenType
.OPEN_PARENS
:
1698 // postfix increment
1699 case TokenType
.OP_INC
:
1700 // postfix decrement
1701 case TokenType
.OP_DEC
:
1703 case TokenType
.ASSIGN
:
1704 case TokenType
.ASSIGN_ADD
:
1705 case TokenType
.ASSIGN_BITWISE_AND
:
1706 case TokenType
.ASSIGN_BITWISE_OR
:
1707 case TokenType
.ASSIGN_BITWISE_XOR
:
1708 case TokenType
.ASSIGN_DIV
:
1709 case TokenType
.ASSIGN_MUL
:
1710 case TokenType
.ASSIGN_PERCENT
:
1711 case TokenType
.ASSIGN_SHIFT_LEFT
:
1712 case TokenType
.ASSIGN_SUB
:
1713 case TokenType
.OP_GT
: // >>=
1716 // pointer member access
1717 case TokenType
.OP_PTR
:
1726 Block
parse_embedded_statement () throws ParseError
{
1727 if (current () == TokenType
.INDENT
) {
1728 var block
= parse_block ();
1732 comment
= scanner
.pop_comment ();
1734 var block
= new
Block (get_src (get_location ()));
1735 block
.add_statement (parse_embedded_statement_without_block ());
1740 Statement
parse_embedded_statement_without_block () throws ParseError
{
1741 switch (current ()) {
1742 case TokenType
.PASS
:
1743 case TokenType
.SEMICOLON
: return parse_empty_statement ();
1744 case TokenType
.IF
: return parse_if_statement ();
1745 case TokenType
.CASE
: return parse_switch_statement ();
1746 case TokenType
.WHILE
: return parse_while_statement ();
1747 case TokenType
.DO
: return parse_do_statement ();
1748 case TokenType
.FOR
: return get_for_statement_type ();
1749 case TokenType
.BREAK
: return parse_break_statement ();
1750 case TokenType
.CONTINUE
: return parse_continue_statement ();
1751 case TokenType
.RETURN
: return parse_return_statement ();
1752 case TokenType
.YIELD
: return parse_yield_statement ();
1753 case TokenType
.RAISE
: return parse_throw_statement ();
1754 case TokenType
.TRY
: return parse_try_statement ();
1755 case TokenType
.LOCK
: return parse_lock_statement ();
1756 case TokenType
.DELETE
: return parse_delete_statement ();
1757 default: return parse_expression_statement ();
1761 Block
parse_block () throws ParseError
{
1762 var begin
= get_location ();
1763 expect (TokenType
.INDENT
);
1764 var block
= new
Block (get_src (begin
));
1765 parse_statements (block
);
1766 if (!accept (TokenType
.DEDENT
)) {
1767 // only report error if it's not a secondary error
1768 if (context
.report
.get_errors () == 0) {
1769 Report
.error (get_current_src (), "tab indentation is incorrect");
1773 block
.source_reference
.last_line
= get_current_src ().last_line
;
1774 block
.source_reference
.last_column
= get_current_src ().last_column
;
1779 Statement
parse_empty_statement () throws ParseError
{
1780 var begin
= get_location ();
1782 accept (TokenType
.PASS
);
1783 accept (TokenType
.SEMICOLON
);
1784 expect_terminator ();
1786 return new
EmptyStatement (get_src (begin
));
1789 void add_local_var_variable (Block block
, string id
) throws ParseError
{
1790 DataType type_copy
= null;
1791 var local
= parse_local_variable (type_copy
, id
);
1792 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1795 void parse_local_variable_declarations (Block block
) throws ParseError
{
1796 if (accept (TokenType
.VAR
)) {
1797 /* support block vars */
1798 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
1799 while (current () != TokenType
.DEDENT
) {
1800 var s
= parse_identifier ();
1801 add_local_var_variable (block
, s
);
1802 accept (TokenType
.EOL
);
1803 accept (TokenType
.SEMICOLON
);
1806 expect (TokenType
.DEDENT
);
1808 var s
= parse_identifier ();
1809 add_local_var_variable (block
, s
);
1810 expect_terminator ();
1816 var id_list
= new ArrayList
<string> ();
1817 DataType variable_type
= null;
1820 id_list
.add (parse_identifier ());
1821 } while (accept (TokenType
.COMMA
));
1823 expect (TokenType
.COLON
);
1825 variable_type
= parse_type ();
1826 var type
= parse_inline_array_type (variable_type
);
1828 foreach (string id
in id_list
) {
1829 DataType type_copy
= null;
1831 type_copy
= type
.copy ();
1833 var local
= parse_local_variable (type_copy
, id
);
1834 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1837 expect_terminator ();
1840 LocalVariable
parse_local_variable (DataType? variable_type
, string id
) throws ParseError
{
1841 var begin
= get_location ();
1842 Expression initializer
= null;
1843 if (accept (TokenType
.ASSIGN
)) {
1844 initializer
= parse_expression ();
1846 return new
LocalVariable (variable_type
, id
, initializer
, get_src (begin
));
1849 Statement
parse_expression_statement () throws ParseError
{
1850 var begin
= get_location ();
1851 var expr
= parse_statement_expression ();
1853 if (current_expr_is_lambda
) {
1854 current_expr_is_lambda
= false;
1856 expect_terminator ();
1859 return new
ExpressionStatement (expr
, get_src (begin
));
1862 Expression
parse_statement_expression () throws ParseError
{
1863 // invocation expression, assignment,
1864 // or pre/post increment/decrement expression
1865 var expr
= parse_expression ();
1869 Statement
parse_if_statement () throws ParseError
{
1870 var begin
= get_location ();
1872 expect (TokenType
.IF
);
1874 var condition
= parse_expression ();
1876 if (!accept (TokenType
.DO
)) {
1877 expect (TokenType
.EOL
);
1879 accept (TokenType
.EOL
);
1882 var src
= get_src (begin
);
1883 var true_stmt
= parse_embedded_statement ();
1884 Block false_stmt
= null;
1885 if (accept (TokenType
.ELSE
)) {
1886 // allow `else if' on the same line without `do'
1887 if (!accept (TokenType
.DO
) && current () != TokenType
.IF
) {
1888 expect (TokenType
.EOL
);
1890 accept (TokenType
.EOL
);
1893 false_stmt
= parse_embedded_statement ();
1895 return new
IfStatement (condition
, true_stmt
, false_stmt
, src
);
1898 Statement
parse_switch_statement () throws ParseError
{
1899 var begin
= get_location ();
1900 expect (TokenType
.CASE
);
1901 var condition
= parse_expression ();
1903 expect (TokenType
.EOL
);
1905 var stmt
= new
SwitchStatement (condition
, get_src (begin
));
1906 expect (TokenType
.INDENT
);
1907 while (current () != TokenType
.DEDENT
) {
1908 var section
= new
SwitchSection (get_src (begin
));
1910 if (accept (TokenType
.WHEN
)) {
1912 section
.add_label (new
SwitchLabel (parse_expression (), get_src (begin
)));
1914 while (accept (TokenType
.COMMA
));
1916 expect (TokenType
.DEFAULT
);
1917 section
.add_label (new SwitchLabel
.with_default (get_src (begin
)));
1920 if (!accept (TokenType
.EOL
)) {
1921 expect (TokenType
.DO
);
1924 parse_statements (section
);
1926 /* add break statement for each block */
1927 var break_stmt
= new
BreakStatement (get_src (begin
));
1928 section
.add_statement (break_stmt
);
1930 stmt
.add_section (section
);
1932 expect (TokenType
.DEDENT
);
1936 Statement
parse_while_statement () throws ParseError
{
1937 var begin
= get_location ();
1938 expect (TokenType
.WHILE
);
1939 var condition
= parse_expression ();
1941 if (!accept (TokenType
.DO
)) {
1942 expect (TokenType
.EOL
);
1944 accept (TokenType
.EOL
);
1947 var body
= parse_embedded_statement ();
1948 return new
WhileStatement (condition
, body
, get_src (begin
));
1951 Statement
parse_do_statement () throws ParseError
{
1952 var begin
= get_location ();
1953 expect (TokenType
.DO
);
1954 expect (TokenType
.EOL
);
1955 var body
= parse_embedded_statement ();
1956 expect (TokenType
.WHILE
);
1958 var condition
= parse_expression ();
1960 expect_terminator ();
1962 return new
DoStatement (body
, condition
, get_src (begin
));
1966 Statement
parse_for_statement () throws ParseError
{
1967 var begin
= get_location ();
1969 Expression initializer
= null;
1970 Expression condition
= null;
1971 Expression iterator
= null;
1975 expect (TokenType
.FOR
);
1977 switch (current ()) {
1983 bool local_is_expr
= is_expression ();
1984 is_expr
= local_is_expr
;
1989 var expr_begin
= get_location ();
1990 id
= parse_identifier ();
1991 rollback (expr_begin
);
1992 initializer
= parse_statement_expression ();
1994 block
= new
Block (get_src (begin
));
1995 DataType variable_type
;
1996 if (accept (TokenType
.VAR
)) {
1997 variable_type
= null;
1998 id
= parse_identifier ();
2000 id
= parse_identifier ();
2001 expect (TokenType
.COLON
);
2002 variable_type
= parse_type ();
2005 DataType type_copy
= null;
2006 if (variable_type
!= null) {
2007 type_copy
= variable_type
.copy ();
2009 var local
= parse_local_variable (type_copy
, id
);
2011 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
2016 if (accept (TokenType
.TO
)) {
2017 /* create expression for condition and incrementing iterator */
2018 var to_begin
= get_location ();
2019 var to_src
= get_src (to_begin
);
2020 var left
= new
MemberAccess (null, id
, to_src
);
2021 var right
= parse_primary_expression ();
2023 condition
= new
BinaryExpression (BinaryOperator
.LESS_THAN_OR_EQUAL
, left
, right
, to_src
);
2025 iterator
= new
PostfixExpression (left
, true, to_src
);
2027 expect (TokenType
.DOWNTO
);
2028 var downto_begin
= get_location ();
2029 var downto_src
= get_src (downto_begin
);
2030 /* create expression for condition and decrementing iterator */
2031 var left
= new
MemberAccess (null, id
, downto_src
);
2032 var right
= parse_primary_expression ();
2034 condition
= new
BinaryExpression (BinaryOperator
.GREATER_THAN_OR_EQUAL
, left
, right
, downto_src
);
2036 iterator
= new
PostfixExpression (left
, false, downto_src
);
2039 if (!accept (TokenType
.EOL
)) {
2040 expect (TokenType
.DO
);
2043 var src
= get_src (begin
);
2044 var body
= parse_embedded_statement ();
2045 var stmt
= new
ForStatement (condition
, body
, src
);
2047 if (initializer
!= null) stmt
.add_initializer (initializer
);
2049 stmt
.add_iterator (iterator
);
2052 if (block
!= null) {
2053 block
.add_statement (stmt
);
2060 Statement
parse_foreach_statement () throws ParseError
{
2061 var begin
= get_location ();
2062 DataType type
= null;
2065 expect (TokenType
.FOR
);
2067 if (accept (TokenType
.VAR
)) {
2068 id
= parse_identifier ();
2070 id
= parse_identifier ();
2071 if (accept (TokenType
.COLON
)) {
2072 type
= parse_type ();
2076 expect (TokenType
.IN
);
2077 var collection
= parse_expression ();
2078 if (!accept (TokenType
.EOL
)) {
2079 expect (TokenType
.DO
);
2081 var src
= get_src (begin
);
2082 var body
= parse_embedded_statement ();
2083 return new
ForeachStatement (type
, id
, collection
, body
, src
);
2086 Statement
parse_break_statement () throws ParseError
{
2087 var begin
= get_location ();
2088 expect (TokenType
.BREAK
);
2089 expect_terminator ();
2090 return new
BreakStatement (get_src (begin
));
2093 Statement
parse_continue_statement () throws ParseError
{
2094 var begin
= get_location ();
2095 expect (TokenType
.CONTINUE
);
2096 expect_terminator ();
2097 return new
ContinueStatement (get_src (begin
));
2100 Statement
parse_return_statement () throws ParseError
{
2101 var begin
= get_location ();
2102 expect (TokenType
.RETURN
);
2103 Expression expr
= null;
2104 if (current () != TokenType
.SEMICOLON
&& current () != TokenType
.EOL
) {
2105 expr
= parse_expression ();
2107 expect_terminator ();
2108 return new
ReturnStatement (expr
, get_src (begin
));
2111 Statement
parse_yield_statement () throws ParseError
{
2112 var begin
= get_location ();
2113 expect (TokenType
.YIELD
);
2114 if (current () != TokenType
.SEMICOLON
&& current () != TokenType
.EOL
&& current () != TokenType
.RETURN
) {
2116 return parse_expression_statement ();
2118 Expression expr
= null;
2119 if (accept (TokenType
.RETURN
)) {
2120 expr
= parse_expression ();
2122 expect_terminator ();
2123 return new
YieldStatement (expr
, get_src (begin
));
2126 Statement
parse_throw_statement () throws ParseError
{
2127 var begin
= get_location ();
2128 expect (TokenType
.RAISE
);
2129 var expr
= parse_expression ();
2130 expect_terminator ();
2131 return new
ThrowStatement (expr
, get_src (begin
));
2134 Statement
parse_try_statement () throws ParseError
{
2135 var begin
= get_location ();
2136 expect (TokenType
.TRY
);
2137 expect (TokenType
.EOL
);
2138 var try_block
= parse_block ();
2139 Block finally_clause
= null;
2140 var catch_clauses
= new ArrayList
<CatchClause
> ();
2141 if (current () == TokenType
.EXCEPT
) {
2142 parse_catch_clauses (catch_clauses
);
2143 if (current () == TokenType
.FINALLY
) {
2144 finally_clause
= parse_finally_clause ();
2147 finally_clause
= parse_finally_clause ();
2149 var stmt
= new
TryStatement (try_block
, finally_clause
, get_src (begin
));
2150 foreach (CatchClause clause
in catch_clauses
) {
2151 stmt
.add_catch_clause (clause
);
2156 void parse_catch_clauses (List
<CatchClause
> catch_clauses
) throws ParseError
{
2157 while (accept (TokenType
.EXCEPT
)) {
2158 var begin
= get_location ();
2159 DataType type
= null;
2161 if (!accept (TokenType
.EOL
)) {
2162 id
= parse_identifier ();
2163 expect (TokenType
.COLON
);
2164 type
= parse_type ();
2165 expect (TokenType
.EOL
);
2168 var block
= parse_block ();
2169 catch_clauses
.add (new
CatchClause (type
, id
, block
, get_src (begin
)));
2173 Block
parse_finally_clause () throws ParseError
{
2174 expect (TokenType
.FINALLY
);
2176 var block
= parse_block ();
2180 Statement
parse_lock_statement () throws ParseError
{
2181 var begin
= get_location ();
2182 expect (TokenType
.LOCK
);
2183 expect (TokenType
.OPEN_PARENS
);
2184 var expr
= parse_expression ();
2185 expect (TokenType
.CLOSE_PARENS
);
2186 var stmt
= parse_embedded_statement ();
2187 return new
LockStatement (expr
, stmt
, get_src (begin
));
2190 Statement
parse_delete_statement () throws ParseError
{
2191 var begin
= get_location ();
2192 expect (TokenType
.DELETE
);
2193 var expr
= parse_expression ();
2194 expect_terminator ();
2195 return new
DeleteStatement (expr
, get_src (begin
));
2198 List
<Attribute
>?
parse_attributes () throws ParseError
{
2199 if (current () != TokenType
.OPEN_BRACKET
) {
2202 var attrs
= new ArrayList
<Attribute
> ();
2203 while (accept (TokenType
.OPEN_BRACKET
)) {
2205 var begin
= get_location ();
2206 string id
= parse_identifier ();
2207 var attr
= new
Attribute (id
, get_src (begin
));
2208 if (accept (TokenType
.OPEN_PARENS
)) {
2209 if (current () != TokenType
.CLOSE_PARENS
) {
2211 id
= parse_identifier ();
2212 expect (TokenType
.ASSIGN
);
2213 var expr
= parse_expression ();
2214 attr
.add_argument (id
, expr
);
2215 } while (accept (TokenType
.COMMA
));
2217 expect (TokenType
.CLOSE_PARENS
);
2220 } while (accept (TokenType
.COMMA
));
2221 expect (TokenType
.CLOSE_BRACKET
);
2223 expect (TokenType
.EOL
);
2228 void set_attributes (CodeNode node
, List
<Attribute
>? attributes
) {
2229 if (attributes
!= null) {
2230 foreach (Attribute attr
in (List
<Attribute
>) attributes
) {
2231 node
.attributes
.append (attr
);
2236 Symbol
parse_declaration (bool is_root
= false) throws ParseError
{
2237 comment
= scanner
.pop_comment ();
2238 var attrs
= parse_attributes ();
2239 var begin
= get_location ();
2241 switch (current ()) {
2242 case TokenType
.CONST
:
2243 return parse_constant_declaration (attrs
);
2244 case TokenType
.CONSTRUCT
:
2245 return parse_creation_method_declaration (attrs
);
2246 case TokenType
.CLASS
:
2247 return parse_class_declaration (attrs
);
2248 case TokenType
.INIT
:
2250 return parse_main_method_declaration (attrs
);
2252 if (context
.profile
== Profile
.GOBJECT
) {
2254 return parse_constructor_declaration (attrs
);
2257 case TokenType
.DELEGATE
:
2258 return parse_delegate_declaration (attrs
);
2260 return parse_method_declaration (attrs
);
2261 case TokenType
.ENUM
:
2262 return parse_enum_declaration (attrs
);
2263 case TokenType
.ERRORDOMAIN
:
2264 return parse_errordomain_declaration (attrs
);
2265 case TokenType
.FINAL
:
2266 return parse_destructor_declaration (attrs
);
2267 case TokenType
.INTERFACE
:
2268 return parse_interface_declaration (attrs
);
2269 case TokenType
.NAMESPACE
:
2270 return parse_namespace_declaration (attrs
);
2271 case TokenType
.PROP
:
2272 return parse_property_declaration (attrs
);
2273 case TokenType
.EVENT
:
2274 return parse_signal_declaration (attrs
);
2275 case TokenType
.STRUCT
:
2276 return parse_struct_declaration (attrs
);
2279 while (current () != TokenType
.EOL
&& current () != TokenType
.SEMICOLON
&& current () != TokenType
.EOF
) {
2280 if (current () == TokenType
.COLON
) {
2282 return parse_field_declaration (attrs
);
2292 TokenType cur
= current ();
2293 TokenType pre
= tokens
[index
-1].type
;
2295 throw new ParseError
.SYNTAX (get_error ("expected declaration but got %s with previous %s".printf (cur
.to_string (), pre
.to_string())));
2298 void parse_declarations (Symbol parent
, bool root
= false) throws ParseError
{
2300 expect (TokenType
.INDENT
);
2302 while (current () != TokenType
.DEDENT
&& current () != TokenType
.EOF
) {
2304 if (parent is Namespace
) {
2305 parse_namespace_member ((Namespace
) parent
);
2306 } else if (parent is Class
) {
2307 parse_class_member ((Class
) parent
);
2308 } else if (parent is Struct
) {
2309 parse_struct_member ((Struct
) parent
);
2310 } else if (parent is Interface
) {
2311 parse_interface_member ((Interface
) parent
);
2313 } catch (ParseError e
) {
2317 if (r
== RecoveryState
.STATEMENT_BEGIN
) {
2323 if (r
== RecoveryState
.EOF
) {
2329 if (!accept (TokenType
.DEDENT
)) {
2330 // only report error if it's not a secondary error
2331 if (context
.report
.get_errors () == 0) {
2332 Report
.error (get_current_src (), "expected dedent");
2338 enum RecoveryState
{
2344 RecoveryState
recover () {
2345 while (current () != TokenType
.EOF
) {
2346 switch (current ()) {
2347 case TokenType
.CLASS
:
2348 case TokenType
.CONST
:
2349 case TokenType
.CONSTRUCT
:
2350 case TokenType
.INIT
:
2352 case TokenType
.DELEGATE
:
2353 case TokenType
.ENUM
:
2354 case TokenType
.ERRORDOMAIN
:
2355 case TokenType
.FINAL
:
2356 case TokenType
.INTERFACE
:
2357 case TokenType
.NAMESPACE
:
2358 case TokenType
.PROP
:
2359 case TokenType
.EVENT
:
2360 case TokenType
.STRUCT
:
2361 return RecoveryState
.DECLARATION_BEGIN
;
2362 case TokenType
.BREAK
:
2363 case TokenType
.CASE
:
2364 case TokenType
.CONTINUE
:
2365 case TokenType
.DELETE
:
2368 case TokenType
.FOREACH
:
2370 case TokenType
.LOCK
:
2371 case TokenType
.RETURN
:
2372 case TokenType
.RAISE
:
2375 case TokenType
.WHILE
:
2376 case TokenType
.YIELD
:
2377 return RecoveryState
.STATEMENT_BEGIN
;
2383 return RecoveryState
.EOF
;
2386 Namespace
parse_namespace_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2387 var begin
= get_location ();
2388 expect (TokenType
.NAMESPACE
);
2389 var sym
= parse_symbol_name ();
2390 var ns
= new
Namespace (sym
.name
, get_src (begin
));
2391 if (comment
!= null) {
2392 ns
.add_comment (comment
);
2395 set_attributes (ns
, attrs
);
2396 expect (TokenType
.EOL
);
2397 parse_declarations (ns
);
2399 Namespace result
= ns
;
2400 while (sym
.inner
!= null) {
2402 ns
= new
Namespace (sym
.name
, result
.source_reference
);
2403 ns
.add_namespace ((Namespace
) result
);
2409 void parse_namespace_member (Namespace ns
) throws ParseError
{
2411 var sym
= parse_declaration ((ns
== context
.root
));
2412 if (sym is Namespace
) {
2413 ns
.add_namespace ((Namespace
) sym
);
2414 } else if (sym is Class
) {
2415 ns
.add_class ((Class
) sym
);
2416 } else if (sym is Interface
) {
2417 ns
.add_interface ((Interface
) sym
);
2418 } else if (sym is Struct
) {
2419 ns
.add_struct ((Struct
) sym
);
2420 } else if (sym is Enum
) {
2421 ns
.add_enum ((Enum
) sym
);
2422 } else if (sym is ErrorDomain
) {
2423 ns
.add_error_domain ((ErrorDomain
) sym
);
2424 } else if (sym is Delegate
) {
2425 ns
.add_delegate ((Delegate
) sym
);
2426 } else if (sym is Method
) {
2427 var method
= (Method
) sym
;
2428 if (method
.binding
== MemberBinding
.INSTANCE
) {
2429 method
.binding
= MemberBinding
.STATIC
;
2431 ns
.add_method (method
);
2432 } else if (sym is Field
) {
2433 var field
= (Field
) sym
;
2434 if (field
.binding
== MemberBinding
.INSTANCE
) {
2435 field
.binding
= MemberBinding
.STATIC
;
2437 ns
.add_field (field
);
2438 } else if (sym is Constant
) {
2439 ns
.add_constant ((Constant
) sym
);
2441 Report
.error (sym
.source_reference
, "unexpected declaration in namespace");
2443 scanner
.source_file
.add_node (sym
);
2447 void add_uses_clause (Namespace ns
) throws ParseError
{
2448 var begin
= get_location ();
2449 var sym
= parse_symbol_name ();
2450 var ns_ref
= new
UsingDirective (sym
, get_src (begin
));
2452 scanner
.source_file
.add_using_directive (ns_ref
);
2453 ns
.add_using_directive (ns_ref
);
2456 void parse_using_directives (Namespace ns
) throws ParseError
{
2457 while (accept (TokenType
.USES
)) {
2458 if (accept_block ()) {
2459 expect (TokenType
.INDENT
);
2461 while (current () != TokenType
.DEDENT
&& current () != TokenType
.EOF
) {
2462 add_uses_clause (ns
);
2463 expect (TokenType
.EOL
);
2466 expect (TokenType
.DEDENT
);
2469 add_uses_clause (ns
);
2470 } while (accept (TokenType
.COMMA
));
2472 expect_terminator ();
2478 Symbol
parse_class_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2479 var begin
= get_location ();
2480 expect (TokenType
.CLASS
);
2482 var flags
= parse_type_declaration_modifiers ();
2484 var sym
= parse_symbol_name ();
2485 var type_param_list
= parse_type_parameter_list ();
2486 var base_types
= new ArrayList
<DataType
> ();
2487 if (accept (TokenType
.COLON
)) {
2488 var type1
= parse_type ();
2489 base_types
.add (type1
);
2491 if (accept (TokenType
.IMPLEMENTS
)) {
2493 var type2
= parse_type ();
2494 base_types
.add (type2
);
2495 } while (accept (TokenType
.COMMA
));
2499 accept (TokenType
.EOL
);
2501 var cl
= new
Class (sym
.name
, get_src (begin
), comment
);
2503 if (ModifierFlags
.PRIVATE
in flags
) {
2504 cl
.access
= SymbolAccessibility
.PRIVATE
;
2506 /* class must always be Public unless its name starts wtih underscore */
2507 if (sym
.name
[0] == '_') {
2508 cl
.access
= SymbolAccessibility
.PRIVATE
;
2510 cl
.access
= SymbolAccessibility
.PUBLIC
;
2514 if (ModifierFlags
.ABSTRACT
in flags
) {
2515 cl
.is_abstract
= true;
2517 set_attributes (cl
, attrs
);
2518 foreach (TypeParameter type_param
in type_param_list
) {
2519 cl
.add_type_parameter (type_param
);
2521 foreach (DataType base_type
in base_types
) {
2522 cl
.add_base_type (base_type
);
2525 class_name
= cl
.name
;
2527 parse_declarations (cl
);
2529 // ensure there is always a default construction method
2530 if (!scanner
.source_file
.external_package
2531 && cl
.default_construction_method
== null) {
2532 var m
= new
CreationMethod (cl
.name
, null, cl
.source_reference
);
2533 m
.access
= SymbolAccessibility
.PUBLIC
;
2534 m
.body
= new
Block (cl
.source_reference
);
2539 while (sym
.inner
!= null) {
2541 var ns
= new
Namespace (sym
.name
, cl
.source_reference
);
2542 if (result is Namespace
) {
2543 ns
.add_namespace ((Namespace
) result
);
2545 ns
.add_class ((Class
) result
);
2546 scanner
.source_file
.add_node (result
);
2553 void parse_class_member (Class cl
) throws ParseError
{
2554 var sym
= parse_declaration ();
2556 cl
.add_class ((Class
) sym
);
2557 } else if (sym is Struct
) {
2558 cl
.add_struct ((Struct
) sym
);
2559 } else if (sym is Enum
) {
2560 cl
.add_enum ((Enum
) sym
);
2561 } else if (sym is Delegate
) {
2562 cl
.add_delegate ((Delegate
) sym
);
2563 } else if (sym is Method
) {
2564 cl
.add_method ((Method
) sym
);
2565 } else if (sym is Vala
.Signal
) {
2566 cl
.add_signal ((Vala
.Signal
) sym
);
2567 } else if (sym is Field
) {
2568 cl
.add_field ((Field
) sym
);
2569 } else if (sym is Constant
) {
2570 cl
.add_constant ((Constant
) sym
);
2571 } else if (sym is Property
) {
2572 cl
.add_property ((Property
) sym
);
2573 } else if (sym is Constructor
) {
2574 var c
= (Constructor
) sym
;
2575 if (c
.binding
== MemberBinding
.INSTANCE
) {
2577 } else if (c
.binding
== MemberBinding
.CLASS
) {
2578 cl
.class_constructor
= c
;
2580 cl
.static_constructor
= c
;
2582 } else if (sym is Destructor
) {
2583 var d
= (Destructor
) sym
;
2584 if (d
.binding
== MemberBinding
.STATIC
) {
2585 cl
.static_destructor
= (Destructor
) d
;
2586 } else if (d
.binding
== MemberBinding
.CLASS
) {
2587 cl
.class_destructor
= (Destructor
) d
;
2589 cl
.destructor
= (Destructor
) d
;
2592 Report
.error (sym
.source_reference
, "unexpected declaration in class");
2596 Constant
parse_constant_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2597 var begin
= get_location ();
2599 expect (TokenType
.CONST
);
2601 var flags
= parse_member_declaration_modifiers ();
2603 string id
= parse_identifier ();
2605 expect (TokenType
.COLON
);
2606 var type
= parse_type (false);
2607 type
= parse_inline_array_type (type
);
2609 Expression initializer
= null;
2610 if (accept (TokenType
.ASSIGN
)) {
2611 initializer
= parse_expression ();
2613 expect_terminator ();
2615 // constant arrays don't own their element
2616 var array_type
= type as ArrayType
;
2617 if (array_type
!= null) {
2618 array_type
.element_type
.value_owned
= false;
2621 var c
= new
Constant (id
, type
, initializer
, get_src (begin
), comment
);
2622 c
.access
= get_access (id
);
2624 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2627 if (ModifierFlags
.NEW
in flags
) {
2631 set_attributes (c
, attrs
);
2635 Field
parse_field_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2636 var begin
= get_location ();
2637 string id
= parse_identifier ();
2638 expect (TokenType
.COLON
);
2640 var flags
= parse_member_declaration_modifiers ();
2642 var type
= parse_type ();
2644 type
= parse_inline_array_type (type
);
2646 var f
= new
Field (id
, type
, null, get_src (begin
), comment
);
2648 if (ModifierFlags
.ABSTRACT
in flags
|| ModifierFlags
.VIRTUAL
in flags
|| ModifierFlags
.OVERRIDE
in flags
) {
2649 Report
.error (f
.source_reference
, "abstract, virtual, and override modifiers are not applicable to fields");
2652 if (ModifierFlags
.PRIVATE
in flags
) {
2653 f
.access
= SymbolAccessibility
.PRIVATE
;
2655 f
.access
= get_access (id
);
2658 set_attributes (f
, attrs
);
2660 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2663 if (ModifierFlags
.NEW
in flags
) {
2667 if (accept (TokenType
.ASSIGN
)) {
2668 f
.initializer
= parse_expression ();
2671 if (ModifierFlags
.STATIC
in flags
) {
2672 f
.binding
= MemberBinding
.STATIC
;
2673 } else if (ModifierFlags
.CLASS
in flags
) {
2674 f
.binding
= MemberBinding
.CLASS
;
2677 expect_terminator ();
2682 InitializerList
parse_initializer () throws ParseError
{
2683 var begin
= get_location ();
2684 if (!accept (TokenType
.OPEN_PARENS
)) {
2685 expect (TokenType
.OPEN_BRACE
);
2687 var initializer
= new
InitializerList (get_src (begin
));
2688 if (current () != TokenType
.DEDENT
) {
2690 var init
= parse_argument ();
2691 initializer
.append (init
);
2692 } while (accept (TokenType
.COMMA
));
2694 if (!accept (TokenType
.CLOSE_PARENS
)) {
2695 expect (TokenType
.CLOSE_BRACE
);
2703 Method
parse_main_method_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2705 var begin
= get_location ();
2706 DataType type
= new
VoidType ();
2707 expect (TokenType
.INIT
);
2709 var method
= new
Method (id
, type
, get_src (begin
), comment
);
2710 method
.access
= SymbolAccessibility
.PUBLIC
;
2712 set_attributes (method
, attrs
);
2714 method
.binding
= MemberBinding
.STATIC
;
2716 var sym
= new
UnresolvedSymbol (null, "string", get_src (begin
));
2717 type
= new UnresolvedType
.from_symbol (sym
, get_src (begin
));
2718 type
.value_owned
= true;
2719 type
= new
ArrayType (type
, 1, get_src (begin
));
2720 type
.nullable
= false;
2722 var param
= new
FormalParameter ("args", type
, get_src (begin
));
2723 method
.add_parameter (param
);
2726 expect (TokenType
.EOL
);
2728 if (accept_block ()) {
2729 method
.body
= parse_block ();
2735 Method
parse_method_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2736 var begin
= get_location ();
2737 DataType type
= new
VoidType ();
2738 expect (TokenType
.DEF
);
2739 var flags
= parse_member_declaration_modifiers ();
2741 string id
= parse_identifier ();
2743 var params
= new ArrayList
<FormalParameter
> ();
2744 expect (TokenType
.OPEN_PARENS
);
2746 if (current () != TokenType
.CLOSE_PARENS
) {
2748 var param
= parse_parameter ();
2750 } while (accept (TokenType
.COMMA
));
2753 expect (TokenType
.CLOSE_PARENS
);
2756 /* deal with return value */
2757 if (accept (TokenType
.COLON
)) {
2758 type
= parse_type ();
2761 var type_param_list
= parse_type_parameter_list ();
2763 var method
= new
Method (id
, type
, get_src (begin
), comment
);
2764 if (ModifierFlags
.PRIVATE
in flags
) {
2765 method
.access
= SymbolAccessibility
.PRIVATE
;
2767 method
.access
= get_access (id
);
2771 set_attributes (method
, attrs
);
2773 foreach (TypeParameter type_param
in type_param_list
) {
2774 method
.add_type_parameter (type_param
);
2778 foreach (FormalParameter param
in params
) {
2779 method
.add_parameter (param
);
2782 if (accept (TokenType
.RAISES
)) {
2784 method
.add_error_type (parse_type ());
2785 } while (accept (TokenType
.COMMA
));
2789 if (ModifierFlags
.STATIC
in flags
|| id
== "main") {
2790 method
.binding
= MemberBinding
.STATIC
;
2791 } else if (ModifierFlags
.CLASS
in flags
) {
2792 method
.binding
= MemberBinding
.CLASS
;
2794 if (ModifierFlags
.ASYNC
in flags
) {
2795 method
.coroutine
= true;
2798 if (ModifierFlags
.NEW
in flags
) {
2799 method
.hides
= true;
2802 if (method
.binding
== MemberBinding
.INSTANCE
) {
2803 if (ModifierFlags
.ABSTRACT
in flags
) {
2804 method
.is_abstract
= true;
2806 if (ModifierFlags
.VIRTUAL
in flags
) {
2807 method
.is_virtual
= true;
2809 if (ModifierFlags
.OVERRIDE
in flags
) {
2810 method
.overrides
= true;
2812 if ((method
.is_abstract
&& method
.is_virtual
)
2813 || (method
.is_abstract
&& method
.overrides
)
2814 || (method
.is_virtual
&& method
.overrides
)) {
2815 throw new ParseError
.SYNTAX (get_error ("only one of `abstract', `virtual', or `override' may be specified"));
2818 if (ModifierFlags
.ABSTRACT
in flags
2819 || ModifierFlags
.VIRTUAL
in flags
2820 || ModifierFlags
.OVERRIDE
in flags
) {
2821 throw new ParseError
.SYNTAX (get_error ("the modifiers `abstract', `virtual', and `override' are not valid for static methods"));
2825 if (ModifierFlags
.INLINE
in flags
) {
2826 method
.is_inline
= true;
2828 if (ModifierFlags
.EXTERN
in flags
) {
2829 method
.external
= true;
2832 expect (TokenType
.EOL
);
2834 var body_location
= get_location ();
2837 /* "requires" and "ensures" if present will be at start of the method body */
2838 if (accept (TokenType
.INDENT
)) {
2839 if (accept (TokenType
.REQUIRES
)) {
2841 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
2842 while (current() != TokenType
.DEDENT
) {
2843 method
.add_precondition (parse_expression ());
2844 expect (TokenType
.EOL
);
2847 expect (TokenType
.DEDENT
);
2848 accept_terminator ();
2851 method
.add_precondition (parse_expression ());
2852 expect_terminator ();
2858 if (accept (TokenType
.ENSURES
)) {
2859 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
2860 while (current() != TokenType
.DEDENT
) {
2861 method
.add_postcondition (parse_expression ());
2862 expect (TokenType
.EOL
);
2865 expect (TokenType
.DEDENT
);
2866 accept_terminator ();
2868 method
.add_postcondition (parse_expression ());
2869 expect_terminator ();
2874 rollback (body_location
);
2877 if (accept_block ()) {
2878 method
.body
= parse_block ();
2879 } else if (scanner
.source_file
.external_package
) {
2880 method
.external
= true;
2885 Property
parse_property_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2886 var begin
= get_location ();
2887 var readonly = false;
2889 expect (TokenType
.PROP
);
2891 var flags
= parse_member_declaration_modifiers ();
2893 readonly = accept (TokenType
.READONLY
);
2895 string id
= parse_identifier ();
2896 expect (TokenType
.COLON
);
2898 var type
= parse_type (false);
2900 var prop
= new
Property (id
, type
, null, null, get_src (begin
), comment
);
2901 if (ModifierFlags
.PRIVATE
in flags
) {
2902 prop
.access
= SymbolAccessibility
.PRIVATE
;
2904 prop
.access
= get_access (id
);
2907 set_attributes (prop
, attrs
);
2909 if (ModifierFlags
.STATIC
in flags
) {
2910 prop
.binding
= MemberBinding
.STATIC
;
2911 } else if (ModifierFlags
.CLASS
in flags
) {
2912 prop
.binding
= MemberBinding
.CLASS
;
2914 if (ModifierFlags
.ABSTRACT
in flags
) {
2915 prop
.is_abstract
= true;
2917 if (ModifierFlags
.VIRTUAL
in flags
) {
2918 prop
.is_virtual
= true;
2920 if (ModifierFlags
.OVERRIDE
in flags
) {
2921 prop
.overrides
= true;
2924 if (ModifierFlags
.NEW
in flags
) {
2927 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2928 prop
.external
= true;
2931 if (ModifierFlags
.ASYNC
in flags
) {
2932 Report
.error (prop
.source_reference
, "async properties are not supported yet");
2935 if (accept (TokenType
.ASSIGN
)) {
2936 prop
.default_expression
= parse_expression ();
2940 if (accept_block ()) {
2941 expect (TokenType
.INDENT
);
2942 while (current () != TokenType
.DEDENT
) {
2943 var accessor_begin
= get_location ();
2944 var attribs
= parse_attributes ();
2946 var value_type
= type
.copy ();
2947 value_type
.value_owned
= accept (TokenType
.OWNED
);
2949 if (accept (TokenType
.GET
)) {
2950 if (prop
.get_accessor
!= null) {
2951 throw new ParseError
.SYNTAX (get_error ("property get accessor already defined"));
2954 if (accept_block ()) {
2955 block
= parse_block ();
2956 prop
.external
= false;
2958 prop
.get_accessor
= new
PropertyAccessor (true, false, false, value_type
, block
, get_src (accessor_begin
));
2959 set_attributes (prop
.get_accessor
, attribs
);
2960 prop
.get_accessor
.access
= SymbolAccessibility
.PUBLIC
;
2962 bool _construct
= false;
2963 if (accept (TokenType
.SET
)) {
2965 throw new ParseError
.SYNTAX (get_error ("set block not allowed for a read only property"));
2967 _construct
= (context
.profile
== Profile
.GOBJECT
) && accept (TokenType
.CONSTRUCT
);
2968 } else if (context
.profile
== Profile
.GOBJECT
&& accept (TokenType
.CONSTRUCT
)) {
2970 } else if (!accept (TokenType
.EOL
)) {
2971 throw new ParseError
.SYNTAX (get_error ("expected get, set, or construct"));
2974 if (prop
.set_accessor
!= null) {
2975 throw new ParseError
.SYNTAX (get_error ("property set accessor already defined"));
2979 if (accept_block ()) {
2980 block
= parse_block ();
2981 prop
.external
= false;
2983 prop
.set_accessor
= new
PropertyAccessor (false, !readonly, _construct
, value_type
, block
, get_src (accessor_begin
));
2984 set_attributes (prop
.set_accessor
, attribs
);
2985 prop
.set_accessor
.access
= SymbolAccessibility
.PUBLIC
;
2988 accept (TokenType
.EOL
);
2989 expect (TokenType
.DEDENT
);
2991 var value_type
= type
.copy ();
2992 value_type
.value_owned
= false;
2994 prop
.get_accessor
= new
PropertyAccessor (true, false, false, value_type
, null, get_src (begin
));
2995 prop
.get_accessor
.access
= SymbolAccessibility
.PUBLIC
;
2998 value_type
= type
.copy ();
2999 value_type
.value_owned
= false;
3001 prop
.set_accessor
= new
PropertyAccessor (false, true, false, value_type
, null, get_src (begin
));
3002 prop
.set_accessor
.access
= SymbolAccessibility
.PUBLIC
;
3006 expect_terminator ();
3009 if (!prop
.is_abstract
&& !scanner
.source_file
.external_package
) {
3010 var needs_var
= (readonly && (prop
.get_accessor
!= null && prop
.get_accessor
.body
== null));
3013 needs_var
= (prop
.get_accessor
!= null && prop
.get_accessor
.body
== null) || (prop
.set_accessor
!= null && prop
.set_accessor
.body
== null);
3017 /* automatic property accessor body generation */
3018 var field_type
= prop
.property_type
.copy ();
3019 prop
.field
= new
Field ("_%s".printf (prop
.name
), field_type
, prop
.default_expression
, prop
.source_reference
);
3020 prop
.field
.access
= SymbolAccessibility
.PRIVATE
;
3021 prop
.field
.binding
= prop
.binding
;
3028 Vala
.Signal
parse_signal_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3029 var begin
= get_location ();
3032 expect (TokenType
.EVENT
);
3033 var flags
= parse_member_declaration_modifiers ();
3034 string id
= parse_identifier ();
3037 var params
= new ArrayList
<FormalParameter
> ();
3039 expect (TokenType
.OPEN_PARENS
);
3040 if (current () != TokenType
.CLOSE_PARENS
) {
3042 var param
= parse_parameter ();
3044 } while (accept (TokenType
.COMMA
));
3046 expect (TokenType
.CLOSE_PARENS
);
3048 if (accept (TokenType
.COLON
)) {
3049 type
= parse_type ();
3051 type
= new
VoidType ();
3054 var sig
= new Vala
.Signal (id
, type
, get_src (begin
), comment
);
3055 if (ModifierFlags
.PRIVATE
in flags
) {
3056 sig
.access
= SymbolAccessibility
.PRIVATE
;
3058 sig
.access
= get_access (id
);
3061 if (ModifierFlags
.VIRTUAL
in flags
) {
3062 sig
.is_virtual
= true;
3064 if (ModifierFlags
.NEW
in flags
) {
3067 set_attributes (sig
, attrs
);
3069 if (ModifierFlags
.STATIC
in flags
) {
3070 throw new ParseError
.SYNTAX (get_error ("`static' modifier not allowed on signals"));
3071 } else if (ModifierFlags
.CLASS
in flags
) {
3072 throw new ParseError
.SYNTAX (get_error ("`class' modifier not allowed on signals"));
3075 foreach (FormalParameter formal_param
in params
) {
3076 sig
.add_parameter (formal_param
);
3079 if (!accept_terminator ()) {
3080 sig
.body
= parse_block ();
3085 Constructor
parse_constructor_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3086 var begin
= get_location ();
3088 expect (TokenType
.INIT
);
3089 var flags
= parse_member_declaration_modifiers ();
3091 var c
= new
Constructor (get_src (begin
));
3092 if (ModifierFlags
.STATIC
in flags
) {
3093 c
.binding
= MemberBinding
.STATIC
;
3094 } else if (ModifierFlags
.CLASS
in flags
) {
3095 c
.binding
= MemberBinding
.CLASS
;
3099 c
.body
= parse_block ();
3103 Destructor
parse_destructor_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3104 var begin
= get_location ();
3105 expect (TokenType
.FINAL
);
3106 var d
= new
Destructor (get_src (begin
));
3108 d
.body
= parse_block ();
3112 Symbol
parse_struct_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3113 var begin
= get_location ();
3115 expect (TokenType
.STRUCT
);
3116 var flags
= parse_type_declaration_modifiers ();
3117 var sym
= parse_symbol_name ();
3118 var type_param_list
= parse_type_parameter_list ();
3119 DataType base_type
= null;
3120 if (accept (TokenType
.COLON
)) {
3121 base_type
= parse_type ();
3124 var st
= new
Struct (sym
.name
, get_src (begin
), comment
);
3125 if (ModifierFlags
.PRIVATE
in flags
) {
3126 st
.access
= SymbolAccessibility
.PRIVATE
;
3128 st
.access
= get_access (sym
.name
);
3130 set_attributes (st
, attrs
);
3131 foreach (TypeParameter type_param
in type_param_list
) {
3132 st
.add_type_parameter (type_param
);
3134 if (base_type
!= null) {
3135 st
.base_type
= base_type
;
3138 expect (TokenType
.EOL
);
3140 parse_declarations (st
);
3143 while (sym
.inner
!= null) {
3145 var ns
= new
Namespace (sym
.name
, st
.source_reference
);
3146 if (result is Namespace
) {
3147 ns
.add_namespace ((Namespace
) result
);
3149 ns
.add_struct ((Struct
) result
);
3150 scanner
.source_file
.add_node (result
);
3157 void parse_struct_member (Struct st
) throws ParseError
{
3158 var sym
= parse_declaration ();
3159 if (sym is Method
) {
3160 st
.add_method ((Method
) sym
);
3161 } else if (sym is Field
) {
3162 st
.add_field ((Field
) sym
);
3163 } else if (sym is Constant
) {
3164 st
.add_constant ((Constant
) sym
);
3166 Report
.error (sym
.source_reference
, "unexpected declaration in struct");
3170 Symbol
parse_interface_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3171 var begin
= get_location ();
3173 expect (TokenType
.INTERFACE
);
3174 var flags
= parse_type_declaration_modifiers ();
3175 var sym
= parse_symbol_name ();
3176 var type_param_list
= parse_type_parameter_list ();
3177 var base_types
= new ArrayList
<DataType
> ();
3178 if (accept (TokenType
.COLON
)) {
3180 var type
= parse_type ();
3181 base_types
.add (type
);
3182 } while (accept (TokenType
.COMMA
));
3185 var iface
= new
Interface (sym
.name
, get_src (begin
), comment
);
3186 if (ModifierFlags
.PRIVATE
in flags
) {
3187 iface
.access
= SymbolAccessibility
.PRIVATE
;
3189 iface
.access
= get_access (sym
.name
);
3191 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
3192 iface
.external
= true;
3194 set_attributes (iface
, attrs
);
3195 foreach (TypeParameter type_param
in type_param_list
) {
3196 iface
.add_type_parameter (type_param
);
3198 foreach (DataType base_type
in base_types
) {
3199 iface
.add_prerequisite (base_type
);
3203 expect (TokenType
.EOL
);
3205 parse_declarations (iface
);
3208 Symbol result
= iface
;
3209 while (sym
.inner
!= null) {
3211 var ns
= new
Namespace (sym
.name
, iface
.source_reference
);
3212 if (result is Namespace
) {
3213 ns
.add_namespace ((Namespace
) result
);
3215 ns
.add_interface ((Interface
) result
);
3216 scanner
.source_file
.add_node (result
);
3223 void parse_interface_member (Interface iface
) throws ParseError
{
3224 var sym
= parse_declaration ();
3226 iface
.add_class ((Class
) sym
);
3227 } else if (sym is Struct
) {
3228 iface
.add_struct ((Struct
) sym
);
3229 } else if (sym is Enum
) {
3230 iface
.add_enum ((Enum
) sym
);
3231 } else if (sym is Delegate
) {
3232 iface
.add_delegate ((Delegate
) sym
);
3233 } else if (sym is Method
) {
3234 iface
.add_method ((Method
) sym
);
3235 } else if (sym is Vala
.Signal
) {
3236 iface
.add_signal ((Vala
.Signal
) sym
);
3237 } else if (sym is Field
) {
3238 iface
.add_field ((Field
) sym
);
3239 } else if (sym is Constant
) {
3240 iface
.add_constant ((Constant
) sym
);
3241 } else if (sym is Property
) {
3242 iface
.add_property ((Property
) sym
);
3244 Report
.error (sym
.source_reference
, "unexpected declaration in interface");
3248 Symbol
parse_enum_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3249 var begin
= get_location ();
3250 expect (TokenType
.ENUM
);
3251 var flags
= parse_type_declaration_modifiers ();
3253 var sym
= parse_symbol_name ();
3254 var en
= new
Enum (sym
.name
, get_src (begin
), comment
);
3255 if (ModifierFlags
.PRIVATE
in flags
) {
3256 en
.access
= SymbolAccessibility
.PRIVATE
;
3258 en
.access
= get_access (sym
.name
);
3260 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
3263 set_attributes (en
, attrs
);
3265 expect (TokenType
.EOL
);
3266 expect (TokenType
.INDENT
);
3268 if (current () == TokenType
.DEDENT
) {
3269 // allow trailing comma
3272 var value_attrs
= parse_attributes ();
3273 var value_begin
= get_location ();
3274 string id
= parse_identifier ();
3275 comment
= scanner
.pop_comment ();
3276 var ev
= new
EnumValue (id
, get_src (value_begin
), comment
);
3277 set_attributes (ev
, value_attrs
);
3279 if (accept (TokenType
.ASSIGN
)) {
3280 ev
.value
= parse_expression ();
3283 expect (TokenType
.EOL
);
3286 expect (TokenType
.DEDENT
);
3289 while (sym
.inner
!= null) {
3291 var ns
= new
Namespace (sym
.name
, en
.source_reference
);
3292 if (result is Namespace
) {
3293 ns
.add_namespace ((Namespace
) result
);
3295 ns
.add_enum ((Enum
) result
);
3296 scanner
.source_file
.add_node (result
);
3303 Symbol
parse_errordomain_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3304 var begin
= get_location ();
3305 expect (TokenType
.ERRORDOMAIN
);
3306 var flags
= parse_type_declaration_modifiers ();
3308 var sym
= parse_symbol_name ();
3309 var ed
= new
ErrorDomain (sym
.name
, get_src (begin
), comment
);
3310 if (ModifierFlags
.PRIVATE
in flags
) {
3311 ed
.access
= SymbolAccessibility
.PRIVATE
;
3313 ed
.access
= get_access (sym
.name
);
3316 set_attributes (ed
, attrs
);
3318 expect (TokenType
.EOL
);
3319 expect (TokenType
.INDENT
);
3322 if (current () == TokenType
.DEDENT
) {
3323 // allow trailing comma
3326 var code_attrs
= parse_attributes ();
3327 var code_begin
= get_location ();
3328 string id
= parse_identifier ();
3329 comment
= scanner
.pop_comment ();
3330 var ec
= new
ErrorCode (id
, get_src (code_begin
), comment
);
3331 set_attributes (ec
, code_attrs
);
3332 if (accept (TokenType
.ASSIGN
)) {
3333 ec
.value
= parse_expression ();
3336 accept (TokenType
.EOL
);
3340 expect (TokenType
.DEDENT
);
3343 while (sym
.inner
!= null) {
3345 var ns
= new
Namespace (sym
.name
, ed
.source_reference
);
3347 if (result is Namespace
) {
3348 ns
.add_namespace ((Namespace
) result
);
3350 ns
.add_error_domain ((ErrorDomain
) result
);
3351 scanner
.source_file
.add_node (result
);
3358 ModifierFlags
parse_type_declaration_modifiers () {
3359 ModifierFlags flags
= 0;
3361 switch (current ()) {
3362 case TokenType
.ABSTRACT
:
3364 flags
|= ModifierFlags
.ABSTRACT
;
3367 case TokenType
.EXTERN
:
3369 flags
|= ModifierFlags
.EXTERN
;
3372 case TokenType
.STATIC
:
3374 flags
|= ModifierFlags
.STATIC
;
3377 case TokenType
.PRIVATE
:
3379 flags
|= ModifierFlags
.PRIVATE
;
3388 ModifierFlags
parse_member_declaration_modifiers () {
3389 ModifierFlags flags
= 0;
3391 switch (current ()) {
3392 case TokenType
.ABSTRACT
:
3394 flags
|= ModifierFlags
.ABSTRACT
;
3396 case TokenType
.ASYNC
:
3398 flags
|= ModifierFlags
.ASYNC
;
3400 case TokenType
.CLASS
:
3402 flags
|= ModifierFlags
.CLASS
;
3404 case TokenType
.EXTERN
:
3406 flags
|= ModifierFlags
.EXTERN
;
3408 case TokenType
.INLINE
:
3410 flags
|= ModifierFlags
.INLINE
;
3414 flags
|= ModifierFlags
.NEW
;
3416 case TokenType
.OVERRIDE
:
3418 flags
|= ModifierFlags
.OVERRIDE
;
3420 case TokenType
.STATIC
:
3422 flags
|= ModifierFlags
.STATIC
;
3424 case TokenType
.VIRTUAL
:
3426 flags
|= ModifierFlags
.VIRTUAL
;
3428 case TokenType
.PRIVATE
:
3430 flags
|= ModifierFlags
.PRIVATE
;
3438 FormalParameter
parse_parameter () throws ParseError
{
3439 var attrs
= parse_attributes ();
3440 var begin
= get_location ();
3441 if (accept (TokenType
.ELLIPSIS
)) {
3443 return new FormalParameter
.with_ellipsis (get_src (begin
));
3445 bool params_array
= accept (TokenType
.PARAMS
);
3446 var direction
= ParameterDirection
.IN
;
3447 if (accept (TokenType
.OUT
)) {
3448 direction
= ParameterDirection
.OUT
;
3449 } else if (accept (TokenType
.REF
)) {
3450 direction
= ParameterDirection
.REF
;
3453 string id
= parse_identifier ();
3455 expect (TokenType
.COLON
);
3458 if (direction
== ParameterDirection
.IN
) {
3459 type
= parse_type (false);
3461 type
= parse_type (true);
3464 var param
= new
FormalParameter (id
, type
, get_src (begin
));
3465 set_attributes (param
, attrs
);
3466 param
.direction
= direction
;
3467 param
.params_array
= params_array
;
3468 if (accept (TokenType
.ASSIGN
)) {
3469 param
.default_expression
= parse_expression ();
3474 CreationMethod
parse_creation_method_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3475 var begin
= get_location ();
3476 CreationMethod method
;
3478 expect (TokenType
.CONSTRUCT
);
3479 parse_member_declaration_modifiers ();
3481 if (accept (TokenType
.OPEN_PARENS
)) {
3482 /* create default name using class name */
3483 method
= new
CreationMethod (class_name
, null, get_src (begin
), comment
);
3485 var sym
= parse_symbol_name ();
3486 if (sym
.inner
== null) {
3488 if (sym
.name
!= class_name
) {
3489 method
= new
CreationMethod (class_name
, sym
.name
, get_src (begin
), comment
);
3491 method
= new
CreationMethod (sym
.name
, null, get_src (begin
), comment
);
3494 method
= new
CreationMethod (sym
.inner
.name
, sym
.name
, get_src (begin
), comment
);
3496 expect (TokenType
.OPEN_PARENS
);
3499 if (current () != TokenType
.CLOSE_PARENS
) {
3501 var param
= parse_parameter ();
3502 method
.add_parameter (param
);
3503 } while (accept (TokenType
.COMMA
));
3505 expect (TokenType
.CLOSE_PARENS
);
3506 if (accept (TokenType
.RAISES
)) {
3508 method
.add_error_type (parse_type ());
3509 } while (accept (TokenType
.COMMA
));
3511 method
.access
= SymbolAccessibility
.PUBLIC
;
3512 set_attributes (method
, attrs
);
3513 method
.binding
= MemberBinding
.STATIC
;
3515 if (accept_block ()) {
3516 method
.body
= parse_block ();
3517 } else if (scanner
.source_file
.external_package
) {
3518 method
.external
= true;
3524 Symbol
parse_delegate_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3525 var begin
= get_location ();
3528 expect (TokenType
.DELEGATE
);
3530 var flags
= parse_member_declaration_modifiers ();
3532 var sym
= parse_symbol_name ();
3534 var type_param_list
= parse_type_parameter_list ();
3536 if (ModifierFlags
.NEW
in flags
) {
3537 throw new ParseError
.SYNTAX (get_error ("`new' modifier not allowed on delegates"));
3540 var params
= new ArrayList
<FormalParameter
> ();
3542 expect (TokenType
.OPEN_PARENS
);
3543 if (current () != TokenType
.CLOSE_PARENS
) {
3545 var param
= parse_parameter ();
3547 } while (accept (TokenType
.COMMA
));
3549 expect (TokenType
.CLOSE_PARENS
);
3551 if (accept (TokenType
.COLON
)) {
3552 type
= parse_type ();
3555 type
= new
VoidType ();
3558 var d
= new
Delegate (sym
.name
, type
, get_src (begin
), comment
);
3560 if (accept (TokenType
.RAISES
)) {
3562 d
.add_error_type (parse_type ());
3563 } while (accept (TokenType
.COMMA
));
3566 expect_terminator ();
3569 if (ModifierFlags
.PRIVATE
in flags
) {
3570 d
.access
= SymbolAccessibility
.PRIVATE
;
3572 d
.access
= get_access (sym
.name
);
3575 if (!(ModifierFlags
.STATIC
in flags
)) {
3576 d
.has_target
= true;
3578 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
3582 set_attributes (d
, attrs
);
3584 foreach (TypeParameter type_param
in type_param_list
) {
3585 d
.add_type_parameter (type_param
);
3588 foreach (FormalParameter formal_param
in params
) {
3589 d
.add_parameter (formal_param
);
3595 while (sym
.inner
!= null) {
3597 var ns
= new
Namespace (sym
.name
, d
.source_reference
);
3599 if (result is Namespace
) {
3600 ns
.add_namespace ((Namespace
) result
);
3602 ns
.add_delegate ((Delegate
) result
);
3603 scanner
.source_file
.add_node (result
);
3610 List
<TypeParameter
> parse_type_parameter_list () throws ParseError
{
3611 var list
= new ArrayList
<TypeParameter
> ();
3612 if (accept (TokenType
.OF
)) {
3614 var begin
= get_location ();
3615 string id
= parse_identifier ();
3616 list
.add (new
TypeParameter (id
, get_src (begin
)));
3617 } while (accept (TokenType
.COMMA
));
3623 void skip_type_argument_list () throws ParseError
{
3624 if (accept (TokenType
.OF
)) {
3627 } while (accept (TokenType
.COMMA
));
3631 // try to parse type argument list
3632 List
<DataType
>?
parse_type_argument_list (bool maybe_expression
) throws ParseError
{
3633 var begin
= get_location ();
3634 if (accept (TokenType
.OF
)) {
3635 var list
= new ArrayList
<DataType
> ();
3637 switch (current ()) {
3638 case TokenType
.VOID
:
3639 case TokenType
.DYNAMIC
:
3640 case TokenType
.UNOWNED
:
3641 case TokenType
.WEAK
:
3642 case TokenType
.IDENTIFIER
:
3643 var type
= parse_type ();
3651 } while (accept (TokenType
.COMMA
));
3658 MemberAccess
parse_member_name () throws ParseError
{
3659 var begin
= get_location ();
3660 MemberAccess expr
= null;
3662 string id
= parse_identifier ();
3663 List
<DataType
> type_arg_list
= parse_type_argument_list (false);
3664 expr
= new
MemberAccess (expr
, id
, get_src (begin
));
3665 if (type_arg_list
!= null) {
3666 foreach (DataType type_arg
in type_arg_list
) {
3667 expr
.add_type_argument (type_arg
);
3670 } while (accept (TokenType
.DOT
));