3 * Copyright (C) 2006-2013 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Jürg Billeter <j@bitron.ch>
26 * Code visitor parsing all Vala source files.
28 public class Vala
.Parser
: CodeVisitor
{
35 // index of current token in buffer
37 // number of tokens in buffer
42 const int BUFFER_SIZE
= 32;
44 static List
<TypeParameter
> _empty_type_parameter_list
;
47 public TokenType type
;
48 public SourceLocation begin
;
49 public SourceLocation end
;
67 tokens
= new TokenInfo
[BUFFER_SIZE
];
71 * Parses all .vala and .vapi source files in the specified code
72 * context and builds a code tree.
74 * @param context a code context
76 public void parse (CodeContext context
) {
77 this
.context
= context
;
78 context
.accept (this
);
82 public override void visit_source_file (SourceFile source_file
) {
83 if ((context
!= null && context
.run_output
) || source_file
.filename
.has_suffix (".vala") || source_file
.filename
.has_suffix (".vapi")) {
84 parse_file (source_file
);
89 index
= (index
+ 1) % BUFFER_SIZE
;
92 SourceLocation begin
, end
;
93 TokenType type
= scanner
.read_token (out begin
, out end
);
94 tokens
[index
] = { type
, begin
, end
};
97 return (tokens
[index
].type
!= TokenType
.EOF
);
100 inline
void prev () {
101 index
= (index
- 1 + BUFFER_SIZE
) % BUFFER_SIZE
;
103 assert (size
<= BUFFER_SIZE
);
106 inline TokenType
current () {
107 return tokens
[index
].type
;
110 inline
bool accept (TokenType type
) {
111 if (current () == type
) {
118 void report_parse_error (ParseError e
) {
119 var begin
= get_location ();
121 Report
.error (get_src (begin
), "syntax error, " + e
.message
);
124 inline
bool expect (TokenType type
) throws ParseError
{
129 throw new ParseError
.SYNTAX ("expected %s", type
.to_string ());
132 inline SourceLocation
get_location () {
133 return tokens
[index
].begin
;
136 string get_current_string () {
137 var token
= tokens
[index
];
138 return ((string) token
.begin
.pos
).substring (0, (int) (token
.end
.pos
- token
.begin
.pos
));
141 string get_last_string () {
142 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
143 var token
= tokens
[last_index
];
144 return ((string) token
.begin
.pos
).substring (0, (int) (token
.end
.pos
- token
.begin
.pos
));
147 SourceReference
get_src (SourceLocation begin
) {
148 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
150 return new
SourceReference (scanner
.source_file
, begin
, tokens
[last_index
].end
);
153 SourceReference
get_current_src () {
154 var token
= tokens
[index
];
155 return new
SourceReference (scanner
.source_file
, token
.begin
, token
.end
);
158 SourceReference
get_last_src () {
159 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
160 var token
= tokens
[last_index
];
161 return new
SourceReference (scanner
.source_file
, token
.begin
, token
.end
);
164 void rollback (SourceLocation location
) {
165 while (tokens
[index
].begin
.pos
!= location
.pos
) {
166 index
= (index
- 1 + BUFFER_SIZE
) % BUFFER_SIZE
;
168 if (size
> BUFFER_SIZE
) {
169 scanner
.seek (location
);
178 void skip_identifier () throws ParseError
{
179 // also accept keywords as identifiers where there is no conflict
180 switch (current ()) {
181 case TokenType
.ABSTRACT
:
183 case TokenType
.ASYNC
:
185 case TokenType
.BREAK
:
187 case TokenType
.CATCH
:
188 case TokenType
.CLASS
:
189 case TokenType
.CONST
:
190 case TokenType
.CONSTRUCT
:
191 case TokenType
.CONTINUE
:
192 case TokenType
.DEFAULT
:
193 case TokenType
.DELEGATE
:
194 case TokenType
.DELETE
:
196 case TokenType
.DYNAMIC
:
199 case TokenType
.ENSURES
:
200 case TokenType
.ERRORDOMAIN
:
201 case TokenType
.EXTERN
:
202 case TokenType
.FALSE
:
203 case TokenType
.FINALLY
:
205 case TokenType
.FOREACH
:
207 case TokenType
.IDENTIFIER
:
210 case TokenType
.INLINE
:
211 case TokenType
.INTERFACE
:
212 case TokenType
.INTERNAL
:
215 case TokenType
.NAMESPACE
:
219 case TokenType
.OVERRIDE
:
220 case TokenType
.OWNED
:
221 case TokenType
.PARAMS
:
222 case TokenType
.PRIVATE
:
223 case TokenType
.PROTECTED
:
224 case TokenType
.PUBLIC
:
226 case TokenType
.REQUIRES
:
227 case TokenType
.RETURN
:
228 case TokenType
.SEALED
:
230 case TokenType
.SIGNAL
:
231 case TokenType
.SIZEOF
:
232 case TokenType
.STATIC
:
233 case TokenType
.STRUCT
:
234 case TokenType
.SWITCH
:
236 case TokenType
.THROW
:
237 case TokenType
.THROWS
:
240 case TokenType
.TYPEOF
:
241 case TokenType
.UNLOCK
:
242 case TokenType
.UNOWNED
:
243 case TokenType
.USING
:
245 case TokenType
.VIRTUAL
:
247 case TokenType
.VOLATILE
:
249 case TokenType
.WHILE
:
250 case TokenType
.YIELD
:
253 case TokenType
.INTEGER_LITERAL
:
254 case TokenType
.REAL_LITERAL
:
255 // also accept integer and real literals
256 // as long as they contain at least one character
257 // and no decimal point
258 // for example, 2D and 3D
259 string id
= get_current_string ();
260 if (id
[id
.length
- 1].isalpha () && !("." in id
)) {
266 throw new ParseError
.SYNTAX ("expected identifier");
270 string parse_identifier () throws ParseError
{
272 return get_last_string ();
275 Expression
parse_literal () throws ParseError
{
276 var begin
= get_location ();
278 switch (current ()) {
281 return new
BooleanLiteral (true, get_src (begin
));
282 case TokenType
.FALSE
:
284 return new
BooleanLiteral (false, get_src (begin
));
285 case TokenType
.INTEGER_LITERAL
:
287 return new
IntegerLiteral (get_last_string (), get_src (begin
));
288 case TokenType
.REAL_LITERAL
:
290 return new
RealLiteral (get_last_string (), get_src (begin
));
291 case TokenType
.CHARACTER_LITERAL
:
293 // FIXME validate and unescape here and just pass unichar to CharacterLiteral
294 var lit
= new
CharacterLiteral (get_last_string (), get_src (begin
));
296 Report
.error (lit
.source_reference
, "invalid character literal");
299 case TokenType
.REGEX_LITERAL
:
301 string match_part
= get_last_string ();
302 SourceReference src_begin
= get_src (begin
);
303 expect (TokenType
.CLOSE_REGEX_LITERAL
);
304 string close_token
= get_last_string ();
305 return new
RegexLiteral ("%s/%s".printf (close_token
, match_part
), src_begin
);
306 case TokenType
.STRING_LITERAL
:
308 return new
StringLiteral (get_last_string (), get_src (begin
));
309 case TokenType
.TEMPLATE_STRING_LITERAL
:
311 return new
StringLiteral ("\"%s\"".printf (get_last_string ()), get_src (begin
));
312 case TokenType
.VERBATIM_STRING_LITERAL
:
314 string raw_string
= get_last_string ();
315 string escaped_string
= raw_string
.substring (3, raw_string
.length
- 6).escape ("");
316 return new
StringLiteral ("\"%s\"".printf (escaped_string
), get_src (begin
));
319 return new
NullLiteral (get_src (begin
));
321 throw new ParseError
.SYNTAX ("expected literal");
325 public void parse_file (SourceFile source_file
) {
326 var has_global_context
= (context
!= null);
327 if (!has_global_context
) {
328 context
= source_file
.context
;
331 scanner
= new
Scanner (source_file
);
332 parse_file_comments ();
341 parse_using_directives (context
.root
);
342 parse_declarations (context
.root
, true);
343 if (accept (TokenType
.CLOSE_BRACE
)) {
344 // only report error if it's not a secondary error
345 if (context
.report
.get_errors () == 0) {
346 Report
.error (get_last_src (), "unexpected `}'");
349 } catch (ParseError e
) {
350 report_parse_error (e
);
354 if (!has_global_context
) {
359 void parse_file_comments () {
360 scanner
.parse_file_comments ();
363 void skip_symbol_name () throws ParseError
{
366 } while (accept (TokenType
.DOT
) || accept (TokenType
.DOUBLE_COLON
));
369 UnresolvedSymbol
parse_symbol_name () throws ParseError
{
370 var begin
= get_location ();
371 UnresolvedSymbol sym
= null;
373 string name
= parse_identifier ();
374 if (name
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
376 // qualified access to global symbol
377 name
= parse_identifier ();
378 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
379 sym
.qualified
= true;
382 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
383 } while (accept (TokenType
.DOT
));
387 void skip_type () throws ParseError
{
388 accept (TokenType
.DYNAMIC
);
389 accept (TokenType
.OWNED
);
390 accept (TokenType
.UNOWNED
);
391 accept (TokenType
.WEAK
);
393 if (is_inner_array_type ()) {
394 expect (TokenType
.OPEN_PARENS
);
395 expect (TokenType
.UNOWNED
);
397 expect (TokenType
.CLOSE_PARENS
);
398 expect (TokenType
.OPEN_BRACKET
);
401 if (accept (TokenType
.VOID
)) {
404 skip_type_argument_list ();
406 while (accept (TokenType
.STAR
)) {
408 accept (TokenType
.INTERR
);
411 while (accept (TokenType
.OPEN_BRACKET
)) {
413 // required for decision between expression and declaration statement
414 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
417 } while (accept (TokenType
.COMMA
));
418 expect (TokenType
.CLOSE_BRACKET
);
419 accept (TokenType
.INTERR
);
421 accept (TokenType
.OP_NEG
);
422 accept (TokenType
.HASH
);
425 bool is_inner_array_type () {
426 var begin
= get_location ();
428 var result
= accept (TokenType
.OPEN_PARENS
) && accept (TokenType
.UNOWNED
) && current() != TokenType
.CLOSE_PARENS
;
433 DataType
parse_type (bool owned_by_default
, bool can_weak_ref
, bool require_unowned
= false) throws ParseError
{
434 var begin
= get_location ();
436 bool is_dynamic
= accept (TokenType
.DYNAMIC
);
438 bool value_owned
= owned_by_default
;
440 if (require_unowned
) {
441 expect (TokenType
.UNOWNED
);
443 if (owned_by_default
) {
444 if (accept (TokenType
.UNOWNED
)) {
446 } else if (accept (TokenType
.WEAK
)) {
447 if (!can_weak_ref
&& !context
.deprecated
) {
448 Report
.warning (get_last_src (), "deprecated syntax, use `unowned` modifier");
451 } else if (accept (TokenType
.OWNED
)) {
452 Report
.warning (get_last_src (), "`owned' is default in this context");
455 if (accept (TokenType
.OWNED
)) {
459 if (accept (TokenType
.UNOWNED
)) {
460 Report
.warning (get_last_src (), "`unowned' is default in this context");
468 bool inner_type_owned
= true;
469 if (accept (TokenType
.OPEN_PARENS
)) {
470 type
= parse_type (false, false, true);
471 expect (TokenType
.CLOSE_PARENS
);
473 inner_type_owned
= false;
475 expect (TokenType
.OPEN_BRACKET
);
478 if (!is_dynamic
&& value_owned
== owned_by_default
&& accept (TokenType
.VOID
)) {
479 type
= new
VoidType (get_src (begin
));
481 var sym
= parse_symbol_name ();
482 List
<DataType
> type_arg_list
= parse_type_argument_list (false);
484 type
= new UnresolvedType
.from_symbol (sym
, get_src (begin
));
485 if (type_arg_list
!= null) {
486 foreach (DataType type_arg
in type_arg_list
) {
487 type
.add_type_argument (type_arg
);
492 while (accept (TokenType
.STAR
)) {
493 type
= new
PointerType (type
, get_src (begin
));
496 if (!(type is PointerType
)) {
497 type
.nullable
= accept (TokenType
.INTERR
);
501 // array brackets in types are read from right to left,
502 // this is more logical, especially when nullable arrays
503 // or pointers are involved
504 while (accept (TokenType
.OPEN_BRACKET
)) {
505 bool invalid_array
= false;
509 // required for decision between expression and declaration statement
510 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
512 // only used for parsing, reject use as real type
513 invalid_array
= true;
515 } while (accept (TokenType
.COMMA
));
516 expect (TokenType
.CLOSE_BRACKET
);
518 type
.value_owned
= inner_type_owned
;
520 var array_type
= new
ArrayType (type
, array_rank
, get_src (begin
));
521 array_type
.nullable
= accept (TokenType
.INTERR
);
522 array_type
.invalid_syntax
= invalid_array
;
527 if (accept (TokenType
.OP_NEG
)) {
528 Report
.warning (get_last_src (), "obsolete syntax, types are non-null by default");
531 if (!owned_by_default
) {
532 if (accept (TokenType
.HASH
)) {
533 if (!context
.deprecated
) {
534 Report
.warning (get_last_src (), "deprecated syntax, use `owned` modifier");
540 if (type is PointerType
) {
544 type
.is_dynamic
= is_dynamic
;
545 type
.value_owned
= value_owned
;
549 DataType?
parse_inline_array_type (DataType? type
) throws ParseError
{
550 var begin
= get_location ();
552 // inline-allocated array
553 if (type
!= null && accept (TokenType
.OPEN_BRACKET
)) {
554 Expression array_length
= null;
556 if (current () != TokenType
.CLOSE_BRACKET
) {
557 array_length
= parse_expression ();
559 expect (TokenType
.CLOSE_BRACKET
);
561 var array_type
= new
ArrayType (type
, 1, get_src (begin
));
562 array_type
.inline_allocated
= true;
563 if (array_length
!= null) {
564 array_type
.fixed_length
= true;
565 array_type
.length
= array_length
;
567 array_type
.value_owned
= type
.value_owned
;
574 List
<Expression
> parse_argument_list () throws ParseError
{
575 var list
= new ArrayList
<Expression
> ();
576 if (current () != TokenType
.CLOSE_PARENS
) {
578 list
.add (parse_argument ());
579 } while (accept (TokenType
.COMMA
));
584 Expression
parse_argument () throws ParseError
{
585 var begin
= get_location ();
587 if (accept (TokenType
.REF
)) {
588 var inner
= parse_expression ();
589 return new
UnaryExpression (UnaryOperator
.REF
, inner
, get_src (begin
));
590 } else if (accept (TokenType
.OUT
)) {
591 var inner
= parse_expression ();
592 return new
UnaryExpression (UnaryOperator
.OUT
, inner
, get_src (begin
));
594 var expr
= parse_expression ();
595 var ma
= expr as MemberAccess
;
596 if (ma
!= null && ma
.inner
== null && accept (TokenType
.COLON
)) {
598 expr
= parse_expression ();
599 return new
NamedArgument (ma
.member_name
, expr
, get_src (begin
));
606 Expression
parse_primary_expression () throws ParseError
{
607 var begin
= get_location ();
611 switch (current ()) {
613 case TokenType
.FALSE
:
614 case TokenType
.INTEGER_LITERAL
:
615 case TokenType
.REAL_LITERAL
:
616 case TokenType
.CHARACTER_LITERAL
:
617 case TokenType
.STRING_LITERAL
:
618 case TokenType
.REGEX_LITERAL
:
619 case TokenType
.TEMPLATE_STRING_LITERAL
:
620 case TokenType
.VERBATIM_STRING_LITERAL
:
622 expr
= parse_literal ();
624 case TokenType
.OPEN_BRACE
:
625 expr
= parse_initializer ();
627 case TokenType
.OPEN_BRACKET
:
628 expr
= parse_simple_name ();
630 case TokenType
.OPEN_PARENS
:
631 expr
= parse_tuple ();
633 case TokenType
.OPEN_TEMPLATE
:
634 expr
= parse_template ();
636 case TokenType
.OPEN_REGEX_LITERAL
:
637 expr
= parse_regex_literal ();
640 expr
= parse_this_access ();
643 expr
= parse_base_access ();
646 expr
= parse_object_or_array_creation_expression ();
648 case TokenType
.YIELD
:
649 expr
= parse_yield_expression ();
651 case TokenType
.SIZEOF
:
652 expr
= parse_sizeof_expression ();
654 case TokenType
.TYPEOF
:
655 expr
= parse_typeof_expression ();
658 expr
= parse_simple_name ();
662 // process primary expressions that start with an inner primary expression
665 switch (current ()) {
667 expr
= parse_member_access (begin
, expr
);
669 case TokenType
.OP_PTR
:
670 expr
= parse_pointer_member_access (begin
, expr
);
672 case TokenType
.OPEN_PARENS
:
673 expr
= parse_method_call (begin
, expr
);
675 case TokenType
.OPEN_BRACKET
:
676 expr
= parse_element_access (begin
, expr
);
678 case TokenType
.OP_INC
:
679 expr
= parse_post_increment_expression (begin
, expr
);
681 case TokenType
.OP_DEC
:
682 expr
= parse_post_decrement_expression (begin
, expr
);
693 Expression
parse_simple_name () throws ParseError
{
694 var begin
= get_location ();
695 string id
= parse_identifier ();
696 bool qualified
= false;
697 if (id
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
698 id
= parse_identifier ();
701 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
702 var expr
= new
MemberAccess (null, id
, get_src (begin
));
703 expr
.qualified
= qualified
;
704 if (type_arg_list
!= null) {
705 foreach (DataType type_arg
in type_arg_list
) {
706 expr
.add_type_argument (type_arg
);
712 Expression
parse_tuple () throws ParseError
{
713 var begin
= get_location ();
715 expect (TokenType
.OPEN_PARENS
);
716 var expr_list
= new ArrayList
<Expression
> ();
717 if (current () != TokenType
.CLOSE_PARENS
) {
719 expr_list
.add (parse_expression ());
720 } while (accept (TokenType
.COMMA
));
722 expect (TokenType
.CLOSE_PARENS
);
723 if (expr_list
.size
!= 1) {
724 var tuple
= new
Tuple (get_src (begin
));
725 foreach (Expression expr
in expr_list
) {
726 tuple
.add_expression (expr
);
730 return expr_list
.get (0);
733 Expression
parse_template () throws ParseError
{
734 var begin
= get_location ();
735 var template
= new
Template ();
737 expect (TokenType
.OPEN_TEMPLATE
);
738 while (current () != TokenType
.CLOSE_TEMPLATE
) {
739 template
.add_expression (parse_expression ());
740 expect (TokenType
.COMMA
);
742 expect (TokenType
.CLOSE_TEMPLATE
);
744 template
.source_reference
= get_src (begin
);
748 Expression
parse_regex_literal () throws ParseError
{
749 expect (TokenType
.OPEN_REGEX_LITERAL
);
751 var expr
= parse_literal ();
756 Expression
parse_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
757 expect (TokenType
.DOT
);
758 string id
= parse_identifier ();
759 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
760 var expr
= new
MemberAccess (inner
, id
, get_src (begin
));
761 if (type_arg_list
!= null) {
762 foreach (DataType type_arg
in type_arg_list
) {
763 expr
.add_type_argument (type_arg
);
769 Expression
parse_pointer_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
770 expect (TokenType
.OP_PTR
);
771 string id
= parse_identifier ();
772 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
773 var expr
= new MemberAccess
.pointer (inner
, id
, get_src (begin
));
774 if (type_arg_list
!= null) {
775 foreach (DataType type_arg
in type_arg_list
) {
776 expr
.add_type_argument (type_arg
);
782 Expression
parse_method_call (SourceLocation begin
, Expression inner
) throws ParseError
{
783 expect (TokenType
.OPEN_PARENS
);
784 var arg_list
= parse_argument_list ();
785 expect (TokenType
.CLOSE_PARENS
);
786 var init_list
= parse_object_initializer ();
788 if (init_list
.size
> 0 && inner is MemberAccess
) {
789 // struct creation expression
790 var member
= (MemberAccess
) inner
;
791 member
.creation_member
= true;
793 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
794 expr
.struct_creation
= true;
795 foreach (Expression arg
in arg_list
) {
796 expr
.add_argument (arg
);
798 foreach (MemberInitializer initializer
in init_list
) {
799 expr
.add_member_initializer (initializer
);
803 var expr
= new
MethodCall (inner
, get_src (begin
));
804 foreach (Expression arg
in arg_list
) {
805 expr
.add_argument (arg
);
811 Expression
parse_element_access (SourceLocation begin
, Expression inner
) throws ParseError
{
812 expect (TokenType
.OPEN_BRACKET
);
813 var index_list
= parse_expression_list ();
814 Expression? stop
= null;
815 if (index_list
.size
== 1 && accept (TokenType
.COLON
)) {
817 stop
= parse_expression ();
819 expect (TokenType
.CLOSE_BRACKET
);
822 var expr
= new
ElementAccess (inner
, get_src (begin
));
823 foreach (Expression index
in index_list
) {
824 expr
.append_index (index
);
828 return new
SliceExpression (inner
, index_list
[0], stop
, get_src (begin
));
832 List
<Expression
> parse_expression_list () throws ParseError
{
833 var list
= new ArrayList
<Expression
> ();
835 list
.add (parse_expression ());
836 } while (accept (TokenType
.COMMA
));
840 Expression
parse_this_access () throws ParseError
{
841 var begin
= get_location ();
842 expect (TokenType
.THIS
);
843 return new
MemberAccess (null, "this", get_src (begin
));
846 Expression
parse_base_access () throws ParseError
{
847 var begin
= get_location ();
848 expect (TokenType
.BASE
);
849 return new
BaseAccess (get_src (begin
));
852 Expression
parse_post_increment_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
853 expect (TokenType
.OP_INC
);
854 return new
PostfixExpression (inner
, true, get_src (begin
));
857 Expression
parse_post_decrement_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
858 expect (TokenType
.OP_DEC
);
859 return new
PostfixExpression (inner
, false, get_src (begin
));
862 Expression
parse_object_or_array_creation_expression () throws ParseError
{
863 var begin
= get_location ();
864 expect (TokenType
.NEW
);
866 if (is_inner_array_type ()) {
868 return parse_array_creation_expression ();
871 var member
= parse_member_name ();
872 if (accept (TokenType
.OPEN_PARENS
)) {
873 var expr
= parse_object_creation_expression (begin
, member
);
876 bool is_pointer_type
= false;
877 while (accept (TokenType
.STAR
)) {
878 is_pointer_type
= true;
880 if (!is_pointer_type
) {
881 accept (TokenType
.INTERR
);
883 if (accept (TokenType
.OPEN_BRACKET
)) {
885 var expr
= parse_array_creation_expression ();
888 throw new ParseError
.SYNTAX ("expected ( or [");
893 Expression
parse_object_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
894 member
.creation_member
= true;
895 var arg_list
= parse_argument_list ();
896 expect (TokenType
.CLOSE_PARENS
);
897 var init_list
= parse_object_initializer ();
899 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
900 foreach (Expression arg
in arg_list
) {
901 expr
.add_argument (arg
);
903 foreach (MemberInitializer initializer
in init_list
) {
904 expr
.add_member_initializer (initializer
);
909 Expression
parse_array_creation_expression () throws ParseError
{
910 var begin
= get_location ();
911 expect (TokenType
.NEW
);
913 bool inner_array_type
= is_inner_array_type ();
914 if (inner_array_type
) {
915 expect (TokenType
.OPEN_PARENS
);
916 expect (TokenType
.UNOWNED
);
919 var member
= parse_member_name ();
920 DataType element_type
= UnresolvedType
.new_from_expression (member
);
921 bool is_pointer_type
= false;
922 while (accept (TokenType
.STAR
)) {
923 element_type
= new
PointerType (element_type
, get_src (begin
));
924 is_pointer_type
= true;
926 if (!is_pointer_type
) {
927 if (accept (TokenType
.INTERR
)) {
928 element_type
.nullable
= true;
932 if (inner_array_type
) {
933 expect (TokenType
.CLOSE_PARENS
);
934 element_type
.value_owned
= false;
936 element_type
.value_owned
= true;
939 expect (TokenType
.OPEN_BRACKET
);
941 bool size_specified
= false;
942 List
<Expression
> size_specifier_list
= null;
946 // array of arrays: new T[][42]
948 if (size_specified
) {
949 throw new ParseError
.SYNTAX ("size of inner arrays must not be specified in array creation expression");
952 element_type
= new
ArrayType (element_type
, size_specifier_list
.size
, element_type
.source_reference
);
957 size_specifier_list
= new ArrayList
<Expression
> ();
959 Expression size
= null;
960 if (current () != TokenType
.CLOSE_BRACKET
&& current () != TokenType
.COMMA
) {
961 size
= parse_expression ();
962 size_specified
= true;
964 size_specifier_list
.add (size
);
965 } while (accept (TokenType
.COMMA
));
966 expect (TokenType
.CLOSE_BRACKET
);
967 } while (accept (TokenType
.OPEN_BRACKET
));
969 InitializerList initializer
= null;
970 if (current () == TokenType
.OPEN_BRACE
) {
971 initializer
= parse_initializer ();
973 var expr
= new
ArrayCreationExpression (element_type
, size_specifier_list
.size
, initializer
, get_src (begin
));
974 if (size_specified
) {
975 foreach (Expression size
in size_specifier_list
) {
976 expr
.append_size (size
);
982 List
<MemberInitializer
> parse_object_initializer () throws ParseError
{
983 var list
= new ArrayList
<MemberInitializer
> ();
984 if (accept (TokenType
.OPEN_BRACE
)) {
986 list
.add (parse_member_initializer ());
987 } while (accept (TokenType
.COMMA
));
988 expect (TokenType
.CLOSE_BRACE
);
993 MemberInitializer
parse_member_initializer () throws ParseError
{
994 var begin
= get_location ();
995 string id
= parse_identifier ();
996 expect (TokenType
.ASSIGN
);
997 var expr
= parse_expression ();
999 return new
MemberInitializer (id
, expr
, get_src (begin
));
1002 Expression
parse_yield_expression () throws ParseError
{
1003 expect (TokenType
.YIELD
);
1005 var expr
= parse_expression ();
1007 var call
= expr as MethodCall
;
1008 var object_creation
= expr as ObjectCreationExpression
;
1009 if (call
== null && object_creation
== null) {
1010 Report
.error (expr
.source_reference
, "syntax error, expected method call");
1011 throw new ParseError
.SYNTAX ("expected method call");
1015 call
.is_yield_expression
= true;
1016 } else if (object_creation
!= null) {
1017 object_creation
.is_yield_expression
= true;
1023 Expression
parse_sizeof_expression () throws ParseError
{
1024 var begin
= get_location ();
1025 expect (TokenType
.SIZEOF
);
1026 expect (TokenType
.OPEN_PARENS
);
1027 var type
= parse_type (true, false);
1028 expect (TokenType
.CLOSE_PARENS
);
1030 return new
SizeofExpression (type
, get_src (begin
));
1033 Expression
parse_typeof_expression () throws ParseError
{
1034 var begin
= get_location ();
1035 expect (TokenType
.TYPEOF
);
1036 expect (TokenType
.OPEN_PARENS
);
1037 var type
= parse_type (true, false);
1038 expect (TokenType
.CLOSE_PARENS
);
1040 return new
TypeofExpression (type
, get_src (begin
));
1043 UnaryOperator
get_unary_operator (TokenType token_type
) {
1044 switch (token_type
) {
1045 case TokenType
.PLUS
: return UnaryOperator
.PLUS
;
1046 case TokenType
.MINUS
: return UnaryOperator
.MINUS
;
1047 case TokenType
.OP_NEG
: return UnaryOperator
.LOGICAL_NEGATION
;
1048 case TokenType
.TILDE
: return UnaryOperator
.BITWISE_COMPLEMENT
;
1049 case TokenType
.OP_INC
: return UnaryOperator
.INCREMENT
;
1050 case TokenType
.OP_DEC
: return UnaryOperator
.DECREMENT
;
1051 default: return UnaryOperator
.NONE
;
1055 Expression
parse_unary_expression () throws ParseError
{
1056 var begin
= get_location ();
1057 var operator
= get_unary_operator (current ());
1058 if (operator
!= UnaryOperator
.NONE
) {
1060 var op
= parse_unary_expression ();
1061 var lit
= op as IntegerLiteral
;
1063 if (operator
== UnaryOperator
.PLUS
) {
1065 } else if (operator
== UnaryOperator
.MINUS
) {
1066 return new
IntegerLiteral ("-"+lit
.value
, get_src (begin
));
1069 return new
UnaryExpression (operator
, op
, get_src (begin
));
1071 switch (current ()) {
1072 case TokenType
.HASH
:
1073 if (!context
.deprecated
) {
1074 Report
.warning (get_last_src (), "deprecated syntax, use `(owned)` cast");
1077 var op
= parse_unary_expression ();
1078 return new
ReferenceTransferExpression (op
, get_src (begin
));
1079 case TokenType
.OPEN_PARENS
:
1081 switch (current ()) {
1082 case TokenType
.UNOWNED
:
1085 case TokenType
.OWNED
:
1088 if (accept (TokenType
.CLOSE_PARENS
)) {
1089 var op
= parse_unary_expression ();
1090 return new
ReferenceTransferExpression (op
, get_src (begin
));
1093 case TokenType
.VOID
:
1094 case TokenType
.DYNAMIC
:
1095 case TokenType
.OPEN_PARENS
:
1096 case TokenType
.IDENTIFIER
:
1097 if (current () != TokenType
.OPEN_PARENS
|| is_inner_array_type ()) {
1098 var type
= parse_type (true, false);
1099 if (accept (TokenType
.CLOSE_PARENS
)) {
1100 // check follower to decide whether to create cast expression
1101 switch (current ()) {
1102 case TokenType
.OP_NEG
:
1103 case TokenType
.TILDE
:
1104 case TokenType
.OPEN_PARENS
:
1105 case TokenType
.TRUE
:
1106 case TokenType
.FALSE
:
1107 case TokenType
.INTEGER_LITERAL
:
1108 case TokenType
.REAL_LITERAL
:
1109 case TokenType
.CHARACTER_LITERAL
:
1110 case TokenType
.STRING_LITERAL
:
1111 case TokenType
.TEMPLATE_STRING_LITERAL
:
1112 case TokenType
.VERBATIM_STRING_LITERAL
:
1113 case TokenType
.REGEX_LITERAL
:
1114 case TokenType
.NULL
:
1115 case TokenType
.THIS
:
1116 case TokenType
.BASE
:
1118 case TokenType
.YIELD
:
1119 case TokenType
.SIZEOF
:
1120 case TokenType
.TYPEOF
:
1121 case TokenType
.IDENTIFIER
:
1122 case TokenType
.PARAMS
:
1123 var inner
= parse_unary_expression ();
1124 return new
CastExpression (inner
, type
, get_src (begin
));
1125 case TokenType
.STAR
:
1127 var op
= parse_unary_expression ();
1128 var inner
= new
PointerIndirection (op
, get_src (begin
));
1129 return new
CastExpression (inner
, type
, get_src (begin
));
1130 case TokenType
.BITWISE_AND
:
1132 var op
= parse_unary_expression ();
1133 var inner
= new
AddressofExpression (op
, get_src (begin
));
1134 return new
CastExpression (inner
, type
, get_src (begin
));
1141 case TokenType
.OP_NEG
:
1143 if (accept (TokenType
.CLOSE_PARENS
)) {
1144 // (!) non-null cast
1145 var inner
= parse_unary_expression ();
1146 return new CastExpression
.non_null (inner
, get_src (begin
));
1152 // no cast expression
1155 case TokenType
.STAR
:
1157 var op
= parse_unary_expression ();
1158 return new
PointerIndirection (op
, get_src (begin
));
1159 case TokenType
.BITWISE_AND
:
1161 var op
= parse_unary_expression ();
1162 return new
AddressofExpression (op
, get_src (begin
));
1167 var expr
= parse_primary_expression ();
1171 BinaryOperator
get_binary_operator (TokenType token_type
) {
1172 switch (token_type
) {
1173 case TokenType
.STAR
: return BinaryOperator
.MUL
;
1174 case TokenType
.DIV
: return BinaryOperator
.DIV
;
1175 case TokenType
.PERCENT
: return BinaryOperator
.MOD
;
1176 case TokenType
.PLUS
: return BinaryOperator
.PLUS
;
1177 case TokenType
.MINUS
: return BinaryOperator
.MINUS
;
1178 case TokenType
.OP_LT
: return BinaryOperator
.LESS_THAN
;
1179 case TokenType
.OP_GT
: return BinaryOperator
.GREATER_THAN
;
1180 case TokenType
.OP_LE
: return BinaryOperator
.LESS_THAN_OR_EQUAL
;
1181 case TokenType
.OP_GE
: return BinaryOperator
.GREATER_THAN_OR_EQUAL
;
1182 case TokenType
.OP_EQ
: return BinaryOperator
.EQUALITY
;
1183 case TokenType
.OP_NE
: return BinaryOperator
.INEQUALITY
;
1184 default: return BinaryOperator
.NONE
;
1188 Expression
parse_multiplicative_expression () throws ParseError
{
1189 var begin
= get_location ();
1190 var left
= parse_unary_expression ();
1193 var operator
= get_binary_operator (current ());
1195 case BinaryOperator
.MUL
:
1196 case BinaryOperator
.DIV
:
1197 case BinaryOperator
.MOD
:
1199 var right
= parse_unary_expression ();
1200 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1210 Expression
parse_additive_expression () throws ParseError
{
1211 var begin
= get_location ();
1212 var left
= parse_multiplicative_expression ();
1215 var operator
= get_binary_operator (current ());
1217 case BinaryOperator
.PLUS
:
1218 case BinaryOperator
.MINUS
:
1220 var right
= parse_multiplicative_expression ();
1221 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1231 Expression
parse_shift_expression () throws ParseError
{
1232 var begin
= get_location ();
1233 var left
= parse_additive_expression ();
1236 switch (current ()) {
1237 case TokenType
.OP_SHIFT_LEFT
:
1239 var right
= parse_additive_expression ();
1240 left
= new
BinaryExpression (BinaryOperator
.SHIFT_LEFT
, left
, right
, get_src (begin
));
1242 // don't use OP_SHIFT_RIGHT to support >> for nested generics
1243 case TokenType
.OP_GT
:
1244 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1246 // only accept >> when there is no space between the two > signs
1247 if (current () == TokenType
.OP_GT
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1249 var right
= parse_additive_expression ();
1250 left
= new
BinaryExpression (BinaryOperator
.SHIFT_RIGHT
, left
, right
, get_src (begin
));
1264 Expression
parse_relational_expression () throws ParseError
{
1265 var begin
= get_location ();
1266 var left
= parse_shift_expression ();
1271 var operator
= get_binary_operator (current ());
1273 case BinaryOperator
.LESS_THAN
:
1274 case BinaryOperator
.LESS_THAN_OR_EQUAL
:
1275 case BinaryOperator
.GREATER_THAN_OR_EQUAL
:
1277 var right
= parse_shift_expression ();
1279 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1281 left
= new BinaryExpression
.chained (operator
, left
, right
, get_src (begin
));
1285 case BinaryOperator
.GREATER_THAN
:
1287 // ignore >> and >>= (two tokens due to generics)
1288 if (current () != TokenType
.OP_GT
&& current () != TokenType
.OP_GE
) {
1289 var right
= parse_shift_expression ();
1291 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1293 left
= new BinaryExpression
.chained (operator
, left
, right
, get_src (begin
));
1302 switch (current ()) {
1305 var type
= parse_type (true, false);
1306 left
= new
TypeCheck (left
, type
, get_src (begin
));
1310 var type
= parse_type (true, false);
1311 left
= new CastExpression
.silent (left
, type
, get_src (begin
));
1323 Expression
parse_equality_expression () throws ParseError
{
1324 var begin
= get_location ();
1325 var left
= parse_relational_expression ();
1328 var operator
= get_binary_operator (current ());
1330 case BinaryOperator
.EQUALITY
:
1331 case BinaryOperator
.INEQUALITY
:
1333 var right
= parse_relational_expression ();
1334 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1344 Expression
parse_and_expression () throws ParseError
{
1345 var begin
= get_location ();
1346 var left
= parse_equality_expression ();
1347 while (accept (TokenType
.BITWISE_AND
)) {
1348 var right
= parse_equality_expression ();
1349 left
= new
BinaryExpression (BinaryOperator
.BITWISE_AND
, left
, right
, get_src (begin
));
1354 Expression
parse_exclusive_or_expression () throws ParseError
{
1355 var begin
= get_location ();
1356 var left
= parse_and_expression ();
1357 while (accept (TokenType
.CARRET
)) {
1358 var right
= parse_and_expression ();
1359 left
= new
BinaryExpression (BinaryOperator
.BITWISE_XOR
, left
, right
, get_src (begin
));
1364 Expression
parse_inclusive_or_expression () throws ParseError
{
1365 var begin
= get_location ();
1366 var left
= parse_exclusive_or_expression ();
1367 while (accept (TokenType
.BITWISE_OR
)) {
1368 var right
= parse_exclusive_or_expression ();
1369 left
= new
BinaryExpression (BinaryOperator
.BITWISE_OR
, left
, right
, get_src (begin
));
1374 Expression
parse_in_expression () throws ParseError
{
1375 var begin
= get_location ();
1376 var left
= parse_inclusive_or_expression ();
1377 while (accept (TokenType
.IN
)) {
1378 var right
= parse_inclusive_or_expression ();
1379 left
= new
BinaryExpression (BinaryOperator
.IN
, left
, right
, get_src (begin
));
1384 Expression
parse_conditional_and_expression () throws ParseError
{
1385 var begin
= get_location ();
1386 var left
= parse_in_expression ();
1387 while (accept (TokenType
.OP_AND
)) {
1388 var right
= parse_in_expression ();
1389 left
= new
BinaryExpression (BinaryOperator
.AND
, left
, right
, get_src (begin
));
1394 Expression
parse_conditional_or_expression () throws ParseError
{
1395 var begin
= get_location ();
1396 var left
= parse_conditional_and_expression ();
1397 while (accept (TokenType
.OP_OR
)) {
1398 var right
= parse_conditional_and_expression ();
1399 left
= new
BinaryExpression (BinaryOperator
.OR
, left
, right
, get_src (begin
));
1404 Expression
parse_coalescing_expression () throws ParseError
{
1405 var begin
= get_location ();
1406 var left
= parse_conditional_or_expression ();
1407 if (accept (TokenType
.OP_COALESCING
)) {
1408 var right
= parse_coalescing_expression ();
1409 return new
BinaryExpression (BinaryOperator
.COALESCE
, left
, right
, get_src (begin
));
1415 Expression
parse_conditional_expression () throws ParseError
{
1416 var begin
= get_location ();
1417 var condition
= parse_coalescing_expression ();
1418 if (accept (TokenType
.INTERR
)) {
1419 var true_expr
= parse_expression ();
1420 expect (TokenType
.COLON
);
1421 var false_expr
= parse_expression ();
1422 return new
ConditionalExpression (condition
, true_expr
, false_expr
, get_src (begin
));
1428 Parameter
parse_lambda_parameter () throws ParseError
{
1429 var begin
= get_location ();
1430 var direction
= ParameterDirection
.IN
;
1431 if (accept (TokenType
.OUT
)) {
1432 direction
= ParameterDirection
.OUT
;
1433 } else if (accept (TokenType
.REF
)) {
1434 direction
= ParameterDirection
.REF
;
1437 string id
= parse_identifier ();
1439 var param
= new
Parameter (id
, null, get_src (begin
));
1440 param
.direction
= direction
;
1444 Expression
parse_lambda_expression () throws ParseError
{
1445 var begin
= get_location ();
1446 List
<Parameter
> params
= new ArrayList
<Parameter
> ();
1447 if (accept (TokenType
.OPEN_PARENS
)) {
1448 if (current () != TokenType
.CLOSE_PARENS
) {
1450 params
.add (parse_lambda_parameter ());
1451 } while (accept (TokenType
.COMMA
));
1453 expect (TokenType
.CLOSE_PARENS
);
1455 params
.add (parse_lambda_parameter ());
1457 expect (TokenType
.LAMBDA
);
1459 LambdaExpression lambda
;
1460 if (current () == TokenType
.OPEN_BRACE
) {
1461 var block
= parse_block ();
1462 lambda
= new LambdaExpression
.with_statement_body (block
, get_src (begin
));
1464 var expr
= parse_expression ();
1465 lambda
= new
LambdaExpression (expr
, get_src (begin
));
1467 foreach (var param
in params
) {
1468 lambda
.add_parameter (param
);
1473 AssignmentOperator
get_assignment_operator (TokenType token_type
) {
1474 switch (token_type
) {
1475 case TokenType
.ASSIGN
: return AssignmentOperator
.SIMPLE
;
1476 case TokenType
.ASSIGN_ADD
: return AssignmentOperator
.ADD
;
1477 case TokenType
.ASSIGN_SUB
: return AssignmentOperator
.SUB
;
1478 case TokenType
.ASSIGN_BITWISE_OR
: return AssignmentOperator
.BITWISE_OR
;
1479 case TokenType
.ASSIGN_BITWISE_AND
: return AssignmentOperator
.BITWISE_AND
;
1480 case TokenType
.ASSIGN_BITWISE_XOR
: return AssignmentOperator
.BITWISE_XOR
;
1481 case TokenType
.ASSIGN_DIV
: return AssignmentOperator
.DIV
;
1482 case TokenType
.ASSIGN_MUL
: return AssignmentOperator
.MUL
;
1483 case TokenType
.ASSIGN_PERCENT
: return AssignmentOperator
.PERCENT
;
1484 case TokenType
.ASSIGN_SHIFT_LEFT
: return AssignmentOperator
.SHIFT_LEFT
;
1485 default: return AssignmentOperator
.NONE
;
1489 Expression
parse_expression () throws ParseError
{
1490 if (is_lambda_expression ()) {
1491 return parse_lambda_expression ();
1494 var begin
= get_location ();
1496 Expression expr
= parse_conditional_expression ();
1499 var operator
= get_assignment_operator (current ());
1500 if (operator
!= AssignmentOperator
.NONE
) {
1502 var rhs
= parse_expression ();
1503 expr
= new
Assignment (expr
, rhs
, operator
, get_src (begin
));
1504 } else if (current () == TokenType
.OP_GT
) { // >>=
1505 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1507 // only accept >>= when there is no space between the two > signs
1508 if (current () == TokenType
.OP_GE
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1510 var rhs
= parse_expression ();
1511 expr
= new
Assignment (expr
, rhs
, AssignmentOperator
.SHIFT_RIGHT
, get_src (begin
));
1524 void parse_statements (Block block
) throws ParseError
{
1525 while (current () != TokenType
.CLOSE_BRACE
1526 && current () != TokenType
.CASE
1527 && current () != TokenType
.DEFAULT
1528 && current () != TokenType
.EOF
) {
1530 Statement stmt
= null;
1531 bool is_decl
= false;
1533 comment
= scanner
.pop_comment ();
1534 switch (current ()) {
1535 case TokenType
.OPEN_BRACE
:
1536 stmt
= parse_block ();
1538 case TokenType
.SEMICOLON
:
1539 stmt
= parse_empty_statement ();
1542 stmt
= parse_if_statement ();
1544 case TokenType
.SWITCH
:
1545 stmt
= parse_switch_statement ();
1547 case TokenType
.WHILE
:
1548 stmt
= parse_while_statement ();
1551 stmt
= parse_do_statement ();
1554 stmt
= parse_for_statement ();
1556 case TokenType
.FOREACH
:
1557 stmt
= parse_foreach_statement ();
1559 case TokenType
.BREAK
:
1560 stmt
= parse_break_statement ();
1562 case TokenType
.CONTINUE
:
1563 stmt
= parse_continue_statement ();
1565 case TokenType
.RETURN
:
1566 stmt
= parse_return_statement ();
1568 case TokenType
.YIELD
:
1569 stmt
= parse_yield_statement ();
1571 case TokenType
.THROW
:
1572 stmt
= parse_throw_statement ();
1575 stmt
= parse_try_statement ();
1577 case TokenType
.LOCK
:
1578 stmt
= parse_lock_statement ();
1580 case TokenType
.UNLOCK
:
1581 stmt
= parse_unlock_statement ();
1583 case TokenType
.DELETE
:
1584 stmt
= parse_delete_statement ();
1588 parse_local_variable_declarations (block
);
1590 case TokenType
.CONST
:
1592 parse_local_constant_declarations (block
);
1594 case TokenType
.OP_INC
:
1595 case TokenType
.OP_DEC
:
1596 case TokenType
.BASE
:
1597 case TokenType
.THIS
:
1598 case TokenType
.STAR
:
1600 stmt
= parse_expression_statement ();
1603 bool is_expr
= is_expression ();
1605 stmt
= parse_expression_statement ();
1608 parse_local_variable_declarations (block
);
1614 block
.add_statement (stmt
);
1616 } catch (ParseError e
) {
1617 report_parse_error (e
);
1618 if (recover () != RecoveryState
.STATEMENT_BEGIN
) {
1619 // beginning of next declaration or end of file reached
1620 // return what we have so far
1627 bool is_expression () throws ParseError
{
1628 if (current () == TokenType
.OPEN_PARENS
) {
1629 return !is_inner_array_type ();
1632 var begin
= get_location ();
1634 // decide between declaration and expression statement
1636 switch (current ()) {
1637 // invocation expression
1638 case TokenType
.OPEN_PARENS
:
1639 // postfix increment
1640 case TokenType
.OP_INC
:
1641 // postfix decrement
1642 case TokenType
.OP_DEC
:
1644 case TokenType
.ASSIGN
:
1645 case TokenType
.ASSIGN_ADD
:
1646 case TokenType
.ASSIGN_BITWISE_AND
:
1647 case TokenType
.ASSIGN_BITWISE_OR
:
1648 case TokenType
.ASSIGN_BITWISE_XOR
:
1649 case TokenType
.ASSIGN_DIV
:
1650 case TokenType
.ASSIGN_MUL
:
1651 case TokenType
.ASSIGN_PERCENT
:
1652 case TokenType
.ASSIGN_SHIFT_LEFT
:
1653 case TokenType
.ASSIGN_SUB
:
1654 case TokenType
.OP_GT
: // >>=
1657 // pointer member access
1658 case TokenType
.OP_PTR
:
1667 bool is_lambda_expression () {
1668 var begin
= get_location ();
1670 switch (current ()) {
1674 if (accept (TokenType
.IDENTIFIER
) && accept (TokenType
.LAMBDA
)) {
1679 case TokenType
.IDENTIFIER
:
1681 if (accept (TokenType
.LAMBDA
)) {
1686 case TokenType
.OPEN_PARENS
:
1688 if (current () != TokenType
.CLOSE_PARENS
) {
1690 if (current () == TokenType
.OUT
|| current () == TokenType
.REF
) {
1693 if (!accept (TokenType
.IDENTIFIER
)) {
1697 } while (accept (TokenType
.COMMA
));
1699 if (accept (TokenType
.CLOSE_PARENS
) && accept (TokenType
.LAMBDA
)) {
1710 Block
parse_embedded_statement (string statement_name
, bool accept_empty_body
= true) throws ParseError
{
1711 if (current () == TokenType
.OPEN_BRACE
) {
1712 var block
= parse_block ();
1716 comment
= scanner
.pop_comment ();
1718 var block
= new
Block (get_src (get_location ()));
1720 var stmt
= parse_embedded_statement_without_block (statement_name
, accept_empty_body
);
1721 block
.add_statement (stmt
);
1727 Statement
parse_embedded_statement_without_block (string statement_name
, bool accept_empty_body
) throws ParseError
{
1728 switch (current ()) {
1729 case TokenType
.SEMICOLON
:
1730 if (!accept_empty_body
) {
1731 Report
.warning (get_current_src (), "%s-statement without body".printf (statement_name
));
1733 return parse_empty_statement ();
1734 case TokenType
.IF
: return parse_if_statement ();
1735 case TokenType
.SWITCH
: return parse_switch_statement ();
1736 case TokenType
.WHILE
: return parse_while_statement ();
1737 case TokenType
.DO
: return parse_do_statement ();
1738 case TokenType
.FOR
: return parse_for_statement ();
1739 case TokenType
.FOREACH
: return parse_foreach_statement ();
1740 case TokenType
.BREAK
: return parse_break_statement ();
1741 case TokenType
.CONTINUE
: return parse_continue_statement ();
1742 case TokenType
.RETURN
: return parse_return_statement ();
1743 case TokenType
.YIELD
: return parse_yield_statement ();
1744 case TokenType
.THROW
: return parse_throw_statement ();
1745 case TokenType
.TRY
: return parse_try_statement ();
1746 case TokenType
.LOCK
: return parse_lock_statement ();
1747 case TokenType
.UNLOCK
: return parse_unlock_statement ();
1748 case TokenType
.DELETE
: return parse_delete_statement ();
1750 case TokenType
.CONST
:
1751 throw new ParseError
.SYNTAX ("embedded statement cannot be declaration ");
1752 case TokenType
.OP_INC
:
1753 case TokenType
.OP_DEC
:
1754 case TokenType
.BASE
:
1755 case TokenType
.THIS
:
1756 case TokenType
.OPEN_PARENS
:
1757 case TokenType
.STAR
:
1759 return parse_expression_statement ();
1761 if (is_expression ()) {
1762 return parse_expression_statement ();
1764 throw new ParseError
.SYNTAX ("embedded statement cannot be declaration");
1769 Block
parse_block () throws ParseError
{
1770 var begin
= get_location ();
1771 expect (TokenType
.OPEN_BRACE
);
1772 var block
= new
Block (get_src (begin
));
1773 parse_statements (block
);
1774 if (!accept (TokenType
.CLOSE_BRACE
)) {
1775 // only report error if it's not a secondary error
1776 if (context
.report
.get_errors () == 0) {
1777 Report
.error (get_current_src (), "expected `}'");
1781 block
.source_reference
.end
= get_current_src ().end
;
1786 Statement
parse_empty_statement () throws ParseError
{
1787 var begin
= get_location ();
1788 expect (TokenType
.SEMICOLON
);
1789 return new
EmptyStatement (get_src (begin
));
1792 void parse_local_variable_declarations (Block block
) throws ParseError
{
1793 DataType variable_type
;
1794 if (accept (TokenType
.VAR
)) {
1795 variable_type
= null;
1797 variable_type
= parse_type (true, true);
1800 if (variable_type
== null && accept (TokenType
.OPEN_PARENS
)) {
1802 var begin
= get_location ();
1804 string[] identifiers
= {};
1806 identifiers
+= parse_identifier ();
1807 } while (accept (TokenType
.COMMA
));
1808 expect (TokenType
.CLOSE_PARENS
);
1810 expect (TokenType
.ASSIGN
);
1811 var tuple
= parse_expression ();
1812 var tuple_local
= new
LocalVariable (null, CodeNode
.get_temp_name (), tuple
, get_src (begin
));
1813 block
.add_statement (new
DeclarationStatement (tuple_local
, tuple_local
.source_reference
));
1815 for (int i
= 0; i
< identifiers
.length
; i
++) {
1816 var temp_access
= new MemberAccess
.simple (tuple_local
.name
, tuple_local
.source_reference
);
1817 var ea
= new
ElementAccess (temp_access
, tuple_local
.source_reference
);
1818 ea
.append_index (new
IntegerLiteral (i
.to_string ()));
1819 var local
= new
LocalVariable (null, identifiers
[i
], ea
, tuple_local
.source_reference
);
1820 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1826 DataType type_copy
= null;
1827 if (variable_type
!= null) {
1828 type_copy
= variable_type
.copy ();
1830 var local
= parse_local_variable (type_copy
);
1831 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1832 } while (accept (TokenType
.COMMA
));
1833 expect (TokenType
.SEMICOLON
);
1836 LocalVariable
parse_local_variable (DataType? variable_type
) throws ParseError
{
1837 var begin
= get_location ();
1838 string id
= parse_identifier ();
1840 var type
= parse_inline_array_type (variable_type
);
1842 Expression initializer
= null;
1843 if (accept (TokenType
.ASSIGN
)) {
1844 initializer
= parse_expression ();
1846 return new
LocalVariable (type
, id
, initializer
, get_src (begin
));
1849 void parse_local_constant_declarations (Block block
) throws ParseError
{
1850 expect (TokenType
.CONST
);
1851 var constant_type
= parse_type (false, false);
1853 // constant arrays don't own their element
1854 var array_type
= constant_type as ArrayType
;
1855 if (array_type
!= null) {
1856 array_type
.element_type
.value_owned
= false;
1860 DataType type_copy
= constant_type
.copy ();
1861 var local
= parse_local_constant (type_copy
);
1862 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1863 block
.add_local_constant (local
);
1864 local
.active
= false;
1865 } while (accept (TokenType
.COMMA
));
1866 expect (TokenType
.SEMICOLON
);
1869 Constant
parse_local_constant (DataType constant_type
) throws ParseError
{
1870 var begin
= get_location ();
1871 string id
= parse_identifier ();
1873 var type
= parse_inline_array_type (constant_type
);
1875 expect (TokenType
.ASSIGN
);
1876 var initializer
= parse_expression ();
1878 return new
Constant (id
, type
, initializer
, get_src (begin
));
1881 Statement
parse_expression_statement () throws ParseError
{
1882 var begin
= get_location ();
1883 var expr
= parse_statement_expression ();
1884 expect (TokenType
.SEMICOLON
);
1885 return new
ExpressionStatement (expr
, get_src (begin
));
1888 Expression
parse_statement_expression () throws ParseError
{
1889 // invocation expression, assignment,
1890 // or pre/post increment/decrement expression
1891 var expr
= parse_expression ();
1895 Statement
parse_if_statement () throws ParseError
{
1896 var begin
= get_location ();
1897 expect (TokenType
.IF
);
1898 expect (TokenType
.OPEN_PARENS
);
1899 var condition
= parse_expression ();
1900 expect (TokenType
.CLOSE_PARENS
);
1901 var src
= get_src (begin
);
1902 var true_stmt
= parse_embedded_statement ("if", false);
1903 Block false_stmt
= null;
1904 if (accept (TokenType
.ELSE
)) {
1905 false_stmt
= parse_embedded_statement ("else", false);
1907 return new
IfStatement (condition
, true_stmt
, false_stmt
, src
);
1910 Statement
parse_switch_statement () throws ParseError
{
1911 var begin
= get_location ();
1912 expect (TokenType
.SWITCH
);
1913 expect (TokenType
.OPEN_PARENS
);
1914 var condition
= parse_expression ();
1915 expect (TokenType
.CLOSE_PARENS
);
1916 var stmt
= new
SwitchStatement (condition
, get_src (begin
));
1917 expect (TokenType
.OPEN_BRACE
);
1918 while (current () != TokenType
.CLOSE_BRACE
) {
1919 begin
= get_location ();
1920 var section
= new
SwitchSection (get_src (begin
));
1922 if (accept (TokenType
.CASE
)) {
1923 section
.add_label (new
SwitchLabel (parse_expression (), get_src (begin
)));
1924 while (current () == TokenType
.COMMA
) {
1925 expect (TokenType
.COMMA
);
1926 section
.add_label (new
SwitchLabel (parse_expression (), get_src (begin
)));
1929 expect (TokenType
.DEFAULT
);
1930 section
.add_label (new SwitchLabel
.with_default (get_src (begin
)));
1932 expect (TokenType
.COLON
);
1933 } while (current () == TokenType
.CASE
|| current () == TokenType
.DEFAULT
);
1934 parse_statements (section
);
1935 stmt
.add_section (section
);
1937 expect (TokenType
.CLOSE_BRACE
);
1941 Statement
parse_while_statement () throws ParseError
{
1942 var begin
= get_location ();
1943 expect (TokenType
.WHILE
);
1944 expect (TokenType
.OPEN_PARENS
);
1945 var condition
= parse_expression ();
1946 expect (TokenType
.CLOSE_PARENS
);
1947 var body
= parse_embedded_statement ("while");
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 var body
= parse_embedded_statement ("do");
1955 expect (TokenType
.WHILE
);
1956 expect (TokenType
.OPEN_PARENS
);
1957 var condition
= parse_expression ();
1958 expect (TokenType
.CLOSE_PARENS
);
1959 expect (TokenType
.SEMICOLON
);
1960 return new
DoStatement (body
, condition
, get_src (begin
));
1963 Statement
parse_for_statement () throws ParseError
{
1964 var begin
= get_location ();
1966 expect (TokenType
.FOR
);
1967 expect (TokenType
.OPEN_PARENS
);
1968 var initializer_list
= new ArrayList
<Expression
> ();
1969 if (!accept (TokenType
.SEMICOLON
)) {
1971 switch (current ()) {
1975 case TokenType
.OP_INC
:
1976 case TokenType
.OP_DEC
:
1980 is_expr
= is_expression ();
1986 initializer_list
.add (parse_statement_expression ());
1987 } while (accept (TokenType
.COMMA
));
1988 expect (TokenType
.SEMICOLON
);
1990 // variable declaration in initializer
1991 block
= new
Block (get_src (begin
));
1992 parse_local_variable_declarations (block
);
1995 Expression condition
= null;
1996 if (current () != TokenType
.SEMICOLON
) {
1997 condition
= parse_expression ();
1999 expect (TokenType
.SEMICOLON
);
2000 var iterator_list
= new ArrayList
<Expression
> ();
2001 if (current () != TokenType
.CLOSE_PARENS
) {
2003 iterator_list
.add (parse_statement_expression ());
2004 } while (accept (TokenType
.COMMA
));
2006 expect (TokenType
.CLOSE_PARENS
);
2007 var src
= get_src (begin
);
2008 var body
= parse_embedded_statement ("for");
2009 var stmt
= new
ForStatement (condition
, body
, src
);
2010 foreach (Expression init
in initializer_list
) {
2011 stmt
.add_initializer (init
);
2013 foreach (Expression iter
in iterator_list
) {
2014 stmt
.add_iterator (iter
);
2016 if (block
!= null) {
2017 block
.add_statement (stmt
);
2024 Statement
parse_foreach_statement () throws ParseError
{
2025 var begin
= get_location ();
2026 expect (TokenType
.FOREACH
);
2027 expect (TokenType
.OPEN_PARENS
);
2028 DataType type
= null;
2029 if (!accept (TokenType
.VAR
)) {
2030 type
= parse_type (true, true);
2031 if (accept (TokenType
.IN
)) {
2032 Report
.error (type
.source_reference
, "syntax error, expected var or type");
2033 throw new ParseError
.SYNTAX ("expected var or type");
2036 string id
= parse_identifier ();
2037 expect (TokenType
.IN
);
2038 var collection
= parse_expression ();
2039 expect (TokenType
.CLOSE_PARENS
);
2040 var src
= get_src (begin
);
2041 var body
= parse_embedded_statement ("foreach");
2042 return new
ForeachStatement (type
, id
, collection
, body
, src
);
2045 Statement
parse_break_statement () throws ParseError
{
2046 var begin
= get_location ();
2047 expect (TokenType
.BREAK
);
2048 expect (TokenType
.SEMICOLON
);
2049 return new
BreakStatement (get_src (begin
));
2052 Statement
parse_continue_statement () throws ParseError
{
2053 var begin
= get_location ();
2054 expect (TokenType
.CONTINUE
);
2055 expect (TokenType
.SEMICOLON
);
2056 return new
ContinueStatement (get_src (begin
));
2059 Statement
parse_return_statement () throws ParseError
{
2060 var begin
= get_location ();
2061 expect (TokenType
.RETURN
);
2062 Expression expr
= null;
2063 if (current () != TokenType
.SEMICOLON
) {
2064 expr
= parse_expression ();
2066 expect (TokenType
.SEMICOLON
);
2067 return new
ReturnStatement (expr
, get_src (begin
));
2070 Statement
parse_yield_statement () throws ParseError
{
2071 var begin
= get_location ();
2072 expect (TokenType
.YIELD
);
2073 if (current () != TokenType
.SEMICOLON
&& current () != TokenType
.RETURN
) {
2076 return parse_expression_statement ();
2078 Expression expr
= null;
2079 if (accept (TokenType
.RETURN
)) {
2080 expr
= parse_expression ();
2082 expect (TokenType
.SEMICOLON
);
2083 return new
YieldStatement (expr
, get_src (begin
));
2086 Statement
parse_throw_statement () throws ParseError
{
2087 var begin
= get_location ();
2088 expect (TokenType
.THROW
);
2089 var expr
= parse_expression ();
2090 expect (TokenType
.SEMICOLON
);
2091 return new
ThrowStatement (expr
, get_src (begin
));
2094 Statement
parse_try_statement () throws ParseError
{
2095 var begin
= get_location ();
2096 expect (TokenType
.TRY
);
2097 var try_block
= parse_block ();
2098 Block finally_clause
= null;
2099 var catch_clauses
= new ArrayList
<CatchClause
> ();
2100 if (current () == TokenType
.CATCH
) {
2101 parse_catch_clauses (catch_clauses
);
2102 if (current () == TokenType
.FINALLY
) {
2103 finally_clause
= parse_finally_clause ();
2106 finally_clause
= parse_finally_clause ();
2108 var stmt
= new
TryStatement (try_block
, finally_clause
, get_src (begin
));
2109 foreach (CatchClause clause
in catch_clauses
) {
2110 stmt
.add_catch_clause (clause
);
2115 void parse_catch_clauses (List
<CatchClause
> catch_clauses
) throws ParseError
{
2116 while (accept (TokenType
.CATCH
)) {
2117 var begin
= get_location ();
2118 DataType type
= null;
2120 if (accept (TokenType
.OPEN_PARENS
)) {
2121 type
= parse_type (true, true);
2122 id
= parse_identifier ();
2123 expect (TokenType
.CLOSE_PARENS
);
2125 var block
= parse_block ();
2126 catch_clauses
.add (new
CatchClause (type
, id
, block
, get_src (begin
)));
2130 Block
parse_finally_clause () throws ParseError
{
2131 expect (TokenType
.FINALLY
);
2132 var block
= parse_block ();
2136 Statement
parse_lock_statement () throws ParseError
{
2137 var begin
= get_location ();
2138 expect (TokenType
.LOCK
);
2139 expect (TokenType
.OPEN_PARENS
);
2140 var expr
= parse_expression ();
2141 expect (TokenType
.CLOSE_PARENS
);
2143 if (current () != TokenType
.SEMICOLON
) {
2144 stmt
= parse_embedded_statement ("lock", false);
2146 return new
LockStatement (expr
, stmt
, get_src (begin
));
2149 Statement
parse_unlock_statement () throws ParseError
{
2150 var begin
= get_location ();
2151 expect (TokenType
.UNLOCK
);
2152 expect (TokenType
.OPEN_PARENS
);
2153 var expr
= parse_expression ();
2154 expect (TokenType
.CLOSE_PARENS
);
2155 expect (TokenType
.SEMICOLON
);
2156 return new
UnlockStatement (expr
, get_src (begin
));
2159 Statement
parse_delete_statement () throws ParseError
{
2160 var begin
= get_location ();
2161 expect (TokenType
.DELETE
);
2162 var expr
= parse_expression ();
2163 expect (TokenType
.SEMICOLON
);
2164 return new
DeleteStatement (expr
, get_src (begin
));
2167 string parse_attribute_value () throws ParseError
{
2168 switch (current ()) {
2169 case TokenType
.NULL
:
2170 case TokenType
.TRUE
:
2171 case TokenType
.FALSE
:
2172 case TokenType
.INTEGER_LITERAL
:
2173 case TokenType
.REAL_LITERAL
:
2174 case TokenType
.STRING_LITERAL
:
2176 return get_last_string ();
2177 case TokenType
.MINUS
:
2179 switch (current ()) {
2180 case TokenType
.INTEGER_LITERAL
:
2181 case TokenType
.REAL_LITERAL
:
2183 return "-" + get_last_string ();
2185 throw new ParseError
.SYNTAX ("expected number");
2188 throw new ParseError
.SYNTAX ("expected literal");
2192 List
<Attribute
>?
parse_attributes () throws ParseError
{
2193 if (current () != TokenType
.OPEN_BRACKET
) {
2196 var attrs
= new ArrayList
<Attribute
> ();
2197 while (accept (TokenType
.OPEN_BRACKET
)) {
2199 var begin
= get_location ();
2200 string id
= parse_identifier ();
2201 var attr
= new
Attribute (id
, get_src (begin
));
2202 if (accept (TokenType
.OPEN_PARENS
)) {
2203 if (current () != TokenType
.CLOSE_PARENS
) {
2205 id
= parse_identifier ();
2206 expect (TokenType
.ASSIGN
);
2207 attr
.add_argument (id
, parse_attribute_value ());
2208 } while (accept (TokenType
.COMMA
));
2210 expect (TokenType
.CLOSE_PARENS
);
2213 } while (accept (TokenType
.COMMA
));
2214 expect (TokenType
.CLOSE_BRACKET
);
2219 void set_attributes (CodeNode node
, List
<Attribute
>? attributes
) {
2220 if (attributes
!= null) {
2221 foreach (Attribute attr
in (List
<Attribute
>) attributes
) {
2222 if (node
.get_attribute (attr
.name
) != null) {
2223 Report
.error (attr
.source_reference
, "duplicate attribute `%s`".printf (attr
.name
));
2225 node
.attributes
.append (attr
);
2230 void parse_main_block (Symbol parent
) throws ParseError
{
2231 var begin
= get_location ();
2233 var method
= new
Method ("main", new
VoidType (), get_src (begin
));
2234 method
.body
= new
Block (get_src (begin
));
2235 parse_statements (method
.body
);
2236 if (current () != TokenType
.EOF
) {
2237 Report
.error (get_current_src (), "expected end of file");
2240 method
.body
.source_reference
.end
= get_current_src ().end
;
2242 if (!context
.experimental
) {
2243 Report
.warning (method
.source_reference
, "main blocks are experimental");
2246 parent
.add_method (method
);
2249 void parse_declaration (Symbol parent
, bool root
= false) throws ParseError
{
2250 comment
= scanner
.pop_comment ();
2251 var attrs
= parse_attributes ();
2253 var begin
= get_location ();
2255 TokenType last_keyword
= current ();
2257 while (is_declaration_keyword (current ())) {
2258 last_keyword
= current ();
2262 switch (current ()) {
2263 case TokenType
.CONSTRUCT
:
2264 if (context
.profile
== Profile
.GOBJECT
) {
2266 parse_constructor_declaration (parent
, attrs
);
2270 case TokenType
.TILDE
:
2272 parse_destructor_declaration (parent
, attrs
);
2274 case TokenType
.OPEN_BRACE
:
2275 case TokenType
.SEMICOLON
:
2277 case TokenType
.SWITCH
:
2278 case TokenType
.WHILE
:
2281 case TokenType
.FOREACH
:
2282 case TokenType
.BREAK
:
2283 case TokenType
.CONTINUE
:
2284 case TokenType
.RETURN
:
2285 case TokenType
.YIELD
:
2286 case TokenType
.THROW
:
2288 case TokenType
.LOCK
:
2289 case TokenType
.UNLOCK
:
2290 case TokenType
.DELETE
:
2292 case TokenType
.OP_INC
:
2293 case TokenType
.OP_DEC
:
2294 case TokenType
.BASE
:
2295 case TokenType
.THIS
:
2296 case TokenType
.STAR
:
2299 if (attrs
!= null) {
2300 // no attributes allowed before statements
2301 throw new ParseError
.SYNTAX ("expected statement");
2304 throw new ParseError
.SYNTAX ("statements outside blocks allowed only in root namespace");
2307 parse_main_block (parent
);
2311 bool is_expr
= is_expression ();
2314 parse_main_block (parent
);
2320 switch (current ()) {
2321 case TokenType
.OPEN_BRACE
:
2322 case TokenType
.SEMICOLON
:
2323 case TokenType
.COLON
:
2325 switch (last_keyword
) {
2326 case TokenType
.CLASS
:
2327 parse_class_declaration (parent
, attrs
);
2329 case TokenType
.ENUM
:
2330 parse_enum_declaration (parent
, attrs
);
2332 case TokenType
.ERRORDOMAIN
:
2333 parse_errordomain_declaration (parent
, attrs
);
2335 case TokenType
.INTERFACE
:
2336 parse_interface_declaration (parent
, attrs
);
2338 case TokenType
.NAMESPACE
:
2339 parse_namespace_declaration (parent
, attrs
);
2341 case TokenType
.STRUCT
:
2342 parse_struct_declaration (parent
, attrs
);
2348 case TokenType
.OPEN_PARENS
:
2350 parse_creation_method_declaration (parent
, attrs
);
2353 skip_type (); // might contain type parameter list
2354 switch (current ()) {
2355 case TokenType
.OPEN_PARENS
:
2357 switch (last_keyword
) {
2358 case TokenType
.DELEGATE
:
2359 parse_delegate_declaration (parent
, attrs
);
2361 case TokenType
.SIGNAL
:
2362 parse_signal_declaration (parent
, attrs
);
2365 parse_method_declaration (parent
, attrs
);
2368 case TokenType
.ASSIGN
:
2369 case TokenType
.SEMICOLON
:
2371 switch (last_keyword
) {
2372 case TokenType
.CONST
:
2373 parse_constant_declaration (parent
, attrs
);
2376 parse_field_declaration (parent
, attrs
);
2379 case TokenType
.OPEN_BRACE
:
2380 case TokenType
.THROWS
:
2382 parse_property_declaration (parent
, attrs
);
2394 throw new ParseError
.SYNTAX ("expected declaration");
2397 void parse_declarations (Symbol parent
, bool root
= false) throws ParseError
{
2399 expect (TokenType
.OPEN_BRACE
);
2401 while (current () != TokenType
.CLOSE_BRACE
&& current () != TokenType
.EOF
) {
2403 parse_declaration (parent
, (parent
== context
.root
));
2404 } catch (ParseError e
) {
2405 report_parse_error (e
);
2409 if (r
== RecoveryState
.STATEMENT_BEGIN
) {
2415 if (r
== RecoveryState
.EOF
) {
2421 if (!accept (TokenType
.CLOSE_BRACE
)) {
2422 // only report error if it's not a secondary error
2423 if (context
.report
.get_errors () == 0) {
2424 Report
.error (get_current_src (), "expected `}'");
2430 enum RecoveryState
{
2436 RecoveryState
recover () {
2437 while (current () != TokenType
.EOF
) {
2438 switch (current ()) {
2439 case TokenType
.ABSTRACT
:
2440 case TokenType
.CLASS
:
2441 case TokenType
.CONST
:
2442 case TokenType
.CONSTRUCT
:
2443 case TokenType
.DELEGATE
:
2444 case TokenType
.ENUM
:
2445 case TokenType
.ERRORDOMAIN
:
2446 case TokenType
.EXTERN
:
2447 case TokenType
.INLINE
:
2448 case TokenType
.INTERFACE
:
2449 case TokenType
.INTERNAL
:
2450 case TokenType
.NAMESPACE
:
2452 case TokenType
.OVERRIDE
:
2453 case TokenType
.PRIVATE
:
2454 case TokenType
.PROTECTED
:
2455 case TokenType
.PUBLIC
:
2456 case TokenType
.SEALED
:
2457 case TokenType
.SIGNAL
:
2458 case TokenType
.STATIC
:
2459 case TokenType
.STRUCT
:
2460 case TokenType
.VIRTUAL
:
2461 case TokenType
.VOLATILE
:
2462 return RecoveryState
.DECLARATION_BEGIN
;
2463 case TokenType
.BREAK
:
2464 case TokenType
.CONTINUE
:
2465 case TokenType
.DELETE
:
2468 case TokenType
.FOREACH
:
2470 case TokenType
.LOCK
:
2471 case TokenType
.RETURN
:
2472 case TokenType
.SWITCH
:
2473 case TokenType
.THROW
:
2475 case TokenType
.UNLOCK
:
2477 case TokenType
.WHILE
:
2478 case TokenType
.YIELD
:
2479 return RecoveryState
.STATEMENT_BEGIN
;
2485 return RecoveryState
.EOF
;
2488 void parse_namespace_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2489 var begin
= get_location ();
2490 expect (TokenType
.NAMESPACE
);
2491 var sym
= parse_symbol_name ();
2492 var ns
= new
Namespace (sym
.name
, get_src (begin
));
2493 if (comment
!= null) {
2494 ns
.add_comment (comment
);
2498 set_attributes (ns
, attrs
);
2500 expect (TokenType
.OPEN_BRACE
);
2502 var old_using_directives
= scanner
.source_file
.current_using_directives
;
2503 parse_using_directives (ns
);
2505 parse_declarations (ns
, true);
2507 scanner
.source_file
.current_using_directives
= old_using_directives
;
2509 if (!accept (TokenType
.CLOSE_BRACE
)) {
2510 // only report error if it's not a secondary error
2511 if (context
.report
.get_errors () == 0) {
2512 Report
.error (get_current_src (), "expected `}'");
2517 while (sym
!= null) {
2520 Symbol next
= (sym
!= null ? new
Namespace (sym
.name
, ns
.source_reference
) : parent
);
2521 next
.add_namespace ((Namespace
) result
);
2526 void parse_using_directives (Namespace ns
) throws ParseError
{
2527 while (accept (TokenType
.USING
)) {
2529 var begin
= get_location ();
2530 var sym
= parse_symbol_name ();
2531 var ns_ref
= new
UsingDirective (sym
, get_src (begin
));
2532 scanner
.source_file
.add_using_directive (ns_ref
);
2533 ns
.add_using_directive (ns_ref
);
2534 } while (accept (TokenType
.COMMA
));
2535 expect (TokenType
.SEMICOLON
);
2539 void parse_class_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2540 var begin
= get_location ();
2541 var access
= parse_access_modifier ();
2542 var flags
= parse_type_declaration_modifiers ();
2543 expect (TokenType
.CLASS
);
2544 var sym
= parse_symbol_name ();
2545 var type_param_list
= parse_type_parameter_list ();
2546 var base_types
= new ArrayList
<DataType
> ();
2547 if (accept (TokenType
.COLON
)) {
2549 base_types
.add (parse_type (true, false));
2550 } while (accept (TokenType
.COMMA
));
2553 var cl
= new
Class (sym
.name
, get_src (begin
), comment
);
2555 if (ModifierFlags
.ABSTRACT
in flags
) {
2556 cl
.is_abstract
= true;
2558 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2561 set_attributes (cl
, attrs
);
2562 foreach (TypeParameter type_param
in type_param_list
) {
2563 cl
.add_type_parameter (type_param
);
2565 foreach (DataType base_type
in base_types
) {
2566 cl
.add_base_type (base_type
);
2569 parse_declarations (cl
);
2571 // ensure there is always a default construction method
2572 if (scanner
.source_file
.file_type
== SourceFileType
.SOURCE
2573 && cl
.default_construction_method
== null) {
2574 var m
= new
CreationMethod (cl
.name
, null, cl
.source_reference
);
2575 m
.access
= SymbolAccessibility
.PUBLIC
;
2576 m
.body
= new
Block (cl
.source_reference
);
2581 while (sym
!= null) {
2584 Symbol next
= (sym
!= null ? new
Namespace (sym
.name
, cl
.source_reference
) : parent
);
2585 if (result is Namespace
) {
2586 next
.add_namespace ((Namespace
) result
);
2588 next
.add_class ((Class
) result
);
2594 void parse_constant_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2595 var begin
= get_location ();
2596 var access
= parse_access_modifier ();
2597 var flags
= parse_member_declaration_modifiers ();
2598 expect (TokenType
.CONST
);
2599 var type
= parse_type (false, false);
2600 string id
= parse_identifier ();
2602 type
= parse_inline_array_type (type
);
2604 Expression initializer
= null;
2605 if (accept (TokenType
.ASSIGN
)) {
2606 initializer
= parse_expression ();
2608 expect (TokenType
.SEMICOLON
);
2610 // constant arrays don't own their element
2611 var array_type
= type as ArrayType
;
2612 if (array_type
!= null) {
2613 array_type
.element_type
.value_owned
= false;
2616 var c
= new
Constant (id
, type
, initializer
, get_src (begin
), comment
);
2618 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2621 if (ModifierFlags
.NEW
in flags
) {
2624 set_attributes (c
, attrs
);
2626 if (ModifierFlags
.STATIC
in flags
) {
2627 Report
.warning (c
.source_reference
, "the modifier `static' is not applicable to constants");
2630 parent
.add_constant (c
);
2633 void parse_field_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2634 var begin
= get_location ();
2635 var access
= parse_access_modifier ((parent is Struct
) ? SymbolAccessibility
.PUBLIC
: SymbolAccessibility
.PRIVATE
);
2636 var flags
= parse_member_declaration_modifiers ();
2637 var type
= parse_type (true, true);
2638 string id
= parse_identifier ();
2639 type
= parse_inline_array_type (type
);
2641 var f
= new
Field (id
, type
, null, get_src (begin
), comment
);
2644 set_attributes (f
, attrs
);
2645 if (ModifierFlags
.STATIC
in flags
&& ModifierFlags
.CLASS
in flags
) {
2646 Report
.error (f
.source_reference
, "only one of `static' or `class' may be specified");
2647 } else if (ModifierFlags
.STATIC
in flags
) {
2648 f
.binding
= MemberBinding
.STATIC
;
2649 } else if (ModifierFlags
.CLASS
in flags
) {
2650 f
.binding
= MemberBinding
.CLASS
;
2653 if (parent is Struct
&& f
.access
!= SymbolAccessibility
.PUBLIC
&& f
.binding
== MemberBinding
.INSTANCE
) {
2654 Report
.warning (f
.source_reference
, "accessibility of struct fields can only be `public`");
2657 if (ModifierFlags
.ABSTRACT
in flags
2658 || ModifierFlags
.VIRTUAL
in flags
2659 || ModifierFlags
.OVERRIDE
in flags
) {
2660 Report
.error (f
.source_reference
, "abstract, virtual, and override modifiers are not applicable to fields");
2662 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2665 if (ModifierFlags
.NEW
in flags
) {
2668 if (accept (TokenType
.ASSIGN
)) {
2669 f
.initializer
= parse_expression ();
2671 expect (TokenType
.SEMICOLON
);
2673 parent
.add_field (f
);
2676 InitializerList
parse_initializer () throws ParseError
{
2677 var begin
= get_location ();
2678 expect (TokenType
.OPEN_BRACE
);
2679 var initializer
= new
InitializerList (get_src (begin
));
2680 while (current () != TokenType
.CLOSE_BRACE
) {
2681 var init
= parse_argument ();
2682 initializer
.append (init
);
2684 if (!accept (TokenType
.COMMA
)) {
2688 expect (TokenType
.CLOSE_BRACE
);
2692 void parse_method_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2693 var begin
= get_location ();
2694 var access
= parse_access_modifier ();
2695 var flags
= parse_member_declaration_modifiers ();
2696 var type
= parse_type (true, false);
2697 var sym
= parse_symbol_name ();
2698 var type_param_list
= parse_type_parameter_list ();
2699 var method
= new
Method (sym
.name
, type
, get_src (begin
), comment
);
2700 if (sym
.inner
!= null) {
2701 method
.base_interface_type
= new UnresolvedType
.from_symbol (sym
.inner
, sym
.inner
.source_reference
);
2703 method
.access
= access
;
2704 set_attributes (method
, attrs
);
2705 foreach (TypeParameter type_param
in type_param_list
) {
2706 method
.add_type_parameter (type_param
);
2708 if (ModifierFlags
.STATIC
in flags
&& ModifierFlags
.CLASS
in flags
) {
2709 Report
.error (method
.source_reference
, "only one of `static' or `class' may be specified");
2710 } else if (ModifierFlags
.STATIC
in flags
) {
2711 method
.binding
= MemberBinding
.STATIC
;
2712 } else if (ModifierFlags
.CLASS
in flags
) {
2713 method
.binding
= MemberBinding
.CLASS
;
2715 if (ModifierFlags
.ASYNC
in flags
) {
2716 method
.coroutine
= true;
2718 if (ModifierFlags
.NEW
in flags
) {
2719 method
.hides
= true;
2722 if (method
.binding
== MemberBinding
.INSTANCE
) {
2723 if (ModifierFlags
.ABSTRACT
in flags
) {
2724 method
.is_abstract
= true;
2726 if (ModifierFlags
.VIRTUAL
in flags
) {
2727 method
.is_virtual
= true;
2729 if (ModifierFlags
.OVERRIDE
in flags
) {
2730 method
.overrides
= true;
2732 if ((method
.is_abstract
&& method
.is_virtual
)
2733 || (method
.is_abstract
&& method
.overrides
)
2734 || (method
.is_virtual
&& method
.overrides
)) {
2735 throw new ParseError
.SYNTAX ("only one of `abstract', `virtual', or `override' may be specified");
2738 if (ModifierFlags
.ABSTRACT
in flags
2739 || ModifierFlags
.VIRTUAL
in flags
2740 || ModifierFlags
.OVERRIDE
in flags
) {
2741 throw new ParseError
.SYNTAX ("the modifiers `abstract', `virtual', and `override' are not valid for %s methods", (ModifierFlags
.CLASS
in flags
) ?
"class" : "static");
2745 if (ModifierFlags
.INLINE
in flags
) {
2746 method
.is_inline
= true;
2748 if (ModifierFlags
.EXTERN
in flags
) {
2749 method
.external
= true;
2751 expect (TokenType
.OPEN_PARENS
);
2752 if (current () != TokenType
.CLOSE_PARENS
) {
2754 var param
= parse_parameter ();
2755 method
.add_parameter (param
);
2756 } while (accept (TokenType
.COMMA
));
2758 expect (TokenType
.CLOSE_PARENS
);
2759 if (accept (TokenType
.THROWS
)) {
2761 method
.add_error_type (parse_type (true, false));
2762 } while (accept (TokenType
.COMMA
));
2764 while (accept (TokenType
.REQUIRES
)) {
2765 expect (TokenType
.OPEN_PARENS
);
2766 method
.add_precondition (parse_expression ());
2767 expect (TokenType
.CLOSE_PARENS
);
2769 while (accept (TokenType
.ENSURES
)) {
2770 expect (TokenType
.OPEN_PARENS
);
2771 method
.add_postcondition (parse_expression ());
2772 expect (TokenType
.CLOSE_PARENS
);
2774 if (!accept (TokenType
.SEMICOLON
)) {
2775 method
.body
= parse_block ();
2776 } else if (scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2777 method
.external
= true;
2780 parent
.add_method (method
);
2783 void parse_property_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2784 var begin
= get_location ();
2785 var access
= parse_access_modifier ();
2786 var flags
= parse_member_declaration_modifiers ();
2787 var type
= parse_type (true, true);
2789 bool getter_owned
= false;
2790 if (accept (TokenType
.HASH
)) {
2791 if (!context
.deprecated
) {
2792 Report
.warning (get_last_src (), "deprecated syntax, use `owned` modifier before `get'");
2794 getter_owned
= true;
2797 string id
= parse_identifier ();
2798 var prop
= new
Property (id
, type
, null, null, get_src (begin
), comment
);
2799 prop
.access
= access
;
2800 set_attributes (prop
, attrs
);
2801 if (ModifierFlags
.STATIC
in flags
&& ModifierFlags
.CLASS
in flags
) {
2802 Report
.error (prop
.source_reference
, "only one of `static' or `class' may be specified");
2803 } else if (ModifierFlags
.STATIC
in flags
) {
2804 prop
.binding
= MemberBinding
.STATIC
;
2805 } else if (ModifierFlags
.CLASS
in flags
) {
2806 prop
.binding
= MemberBinding
.CLASS
;
2808 if (ModifierFlags
.ABSTRACT
in flags
) {
2809 prop
.is_abstract
= true;
2811 if (ModifierFlags
.VIRTUAL
in flags
) {
2812 prop
.is_virtual
= true;
2814 if (ModifierFlags
.OVERRIDE
in flags
) {
2815 prop
.overrides
= true;
2817 if (ModifierFlags
.NEW
in flags
) {
2820 if (ModifierFlags
.ASYNC
in flags
) {
2821 Report
.error (prop
.source_reference
, "async properties are not supported yet");
2823 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2824 prop
.external
= true;
2826 if ((prop
.is_abstract
&& prop
.is_virtual
)
2827 || (prop
.is_abstract
&& prop
.overrides
)
2828 || (prop
.is_virtual
&& prop
.overrides
)) {
2829 throw new ParseError
.SYNTAX ("only one of `abstract', `virtual', or `override' may be specified");
2832 if (accept (TokenType
.THROWS
)) {
2834 prop
.add_error_type (parse_type (true, false));
2835 } while (accept (TokenType
.COMMA
));
2836 Report
.error (prop
.source_reference
, "properties throwing errors are not supported yet");
2838 expect (TokenType
.OPEN_BRACE
);
2839 while (current () != TokenType
.CLOSE_BRACE
) {
2840 if (accept (TokenType
.DEFAULT
)) {
2841 if (prop
.initializer
!= null) {
2842 throw new ParseError
.SYNTAX ("property default value already defined");
2844 expect (TokenType
.ASSIGN
);
2845 prop
.initializer
= parse_expression ();
2846 expect (TokenType
.SEMICOLON
);
2848 comment
= scanner
.pop_comment ();
2850 var accessor_begin
= get_location ();
2851 var accessor_attrs
= parse_attributes ();
2852 var accessor_access
= parse_access_modifier (SymbolAccessibility
.PUBLIC
);
2854 var value_type
= type
.copy ();
2855 if (accept (TokenType
.OWNED
)) {
2856 value_type
.value_owned
= true;
2858 value_type
.value_owned
= false;
2859 if (accept (TokenType
.UNOWNED
)) {
2860 Report
.warning (get_last_src (), "property getters are `unowned' by default");
2864 if (accept (TokenType
.GET
)) {
2865 if (prop
.get_accessor
!= null) {
2866 throw new ParseError
.SYNTAX ("property get accessor already defined");
2870 value_type
.value_owned
= true;
2874 if (!accept (TokenType
.SEMICOLON
)) {
2875 block
= parse_block ();
2876 prop
.external
= false;
2878 prop
.get_accessor
= new
PropertyAccessor (true, false, false, value_type
, block
, get_src (accessor_begin
), comment
);
2879 set_attributes (prop
.get_accessor
, accessor_attrs
);
2880 prop
.get_accessor
.access
= accessor_access
;
2882 bool writable
, _construct
;
2883 if (accept (TokenType
.SET
)) {
2885 _construct
= (context
.profile
== Profile
.GOBJECT
) && accept (TokenType
.CONSTRUCT
);
2886 } else if (context
.profile
== Profile
.GOBJECT
&& accept (TokenType
.CONSTRUCT
)) {
2888 writable
= accept (TokenType
.SET
);
2890 throw new ParseError
.SYNTAX ("expected get, set, or construct");
2892 if (prop
.set_accessor
!= null) {
2893 throw new ParseError
.SYNTAX ("property set accessor already defined");
2896 if (!accept (TokenType
.SEMICOLON
)) {
2897 block
= parse_block ();
2898 prop
.external
= false;
2900 prop
.set_accessor
= new
PropertyAccessor (false, writable
, _construct
, value_type
, block
, get_src (accessor_begin
), comment
);
2901 set_attributes (prop
.set_accessor
, accessor_attrs
);
2902 prop
.set_accessor
.access
= accessor_access
;
2906 expect (TokenType
.CLOSE_BRACE
);
2908 parent
.add_property (prop
);
2911 void parse_signal_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2912 var begin
= get_location ();
2913 var access
= parse_access_modifier ();
2914 var flags
= parse_member_declaration_modifiers ();
2915 expect (TokenType
.SIGNAL
);
2916 var type
= parse_type (true, false);
2917 string id
= parse_identifier ();
2918 var sig
= new
Signal (id
, type
, get_src (begin
), comment
);
2919 sig
.access
= access
;
2920 set_attributes (sig
, attrs
);
2921 if (ModifierFlags
.STATIC
in flags
) {
2922 throw new ParseError
.SYNTAX ("`static' modifier not allowed on signals");
2923 } else if (ModifierFlags
.CLASS
in flags
) {
2924 throw new ParseError
.SYNTAX ("`class' modifier not allowed on signals");
2926 if (ModifierFlags
.VIRTUAL
in flags
) {
2927 sig
.is_virtual
= true;
2929 if (ModifierFlags
.NEW
in flags
) {
2932 expect (TokenType
.OPEN_PARENS
);
2933 if (current () != TokenType
.CLOSE_PARENS
) {
2935 var param
= parse_parameter ();
2936 sig
.add_parameter (param
);
2937 } while (accept (TokenType
.COMMA
));
2939 expect (TokenType
.CLOSE_PARENS
);
2940 if (!accept (TokenType
.SEMICOLON
)) {
2941 sig
.body
= parse_block ();
2944 parent
.add_signal (sig
);
2947 void parse_constructor_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2948 var begin
= get_location ();
2949 var flags
= parse_member_declaration_modifiers ();
2950 expect (TokenType
.CONSTRUCT
);
2951 if (ModifierFlags
.NEW
in flags
) {
2952 throw new ParseError
.SYNTAX ("`new' modifier not allowed on constructor");
2954 var c
= new
Constructor (get_src (begin
));
2955 if (ModifierFlags
.STATIC
in flags
&& ModifierFlags
.CLASS
in flags
) {
2956 Report
.error (c
.source_reference
, "only one of `static' or `class' may be specified");
2957 } else if (ModifierFlags
.STATIC
in flags
) {
2958 c
.binding
= MemberBinding
.STATIC
;
2959 } else if (ModifierFlags
.CLASS
in flags
) {
2960 c
.binding
= MemberBinding
.CLASS
;
2962 c
.body
= parse_block ();
2964 parent
.add_constructor (c
);
2967 void parse_destructor_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2968 var begin
= get_location ();
2969 var flags
= parse_member_declaration_modifiers ();
2970 expect (TokenType
.TILDE
);
2971 string identifier
= parse_identifier ();
2972 expect (TokenType
.OPEN_PARENS
);
2973 expect (TokenType
.CLOSE_PARENS
);
2974 if (ModifierFlags
.NEW
in flags
) {
2975 throw new ParseError
.SYNTAX ("`new' modifier not allowed on destructor");
2977 var d
= new
Destructor (get_src (begin
));
2978 if (identifier
!= parent
.name
) {
2979 Report
.error (d
.source_reference
, "destructor and parent symbol name do not match");
2981 if (ModifierFlags
.STATIC
in flags
&& ModifierFlags
.CLASS
in flags
) {
2982 Report
.error (d
.source_reference
, "only one of `static' or `class' may be specified");
2983 } else if (ModifierFlags
.STATIC
in flags
) {
2984 d
.binding
= MemberBinding
.STATIC
;
2985 } else if (ModifierFlags
.CLASS
in flags
) {
2986 d
.binding
= MemberBinding
.CLASS
;
2988 d
.body
= parse_block ();
2990 parent
.add_destructor (d
);
2993 void parse_struct_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2994 var begin
= get_location ();
2995 var access
= parse_access_modifier ();
2996 var flags
= parse_type_declaration_modifiers ();
2997 expect (TokenType
.STRUCT
);
2998 var sym
= parse_symbol_name ();
2999 var type_param_list
= parse_type_parameter_list ();
3000 DataType base_type
= null;
3001 if (accept (TokenType
.COLON
)) {
3002 base_type
= parse_type (true, false);
3004 var st
= new
Struct (sym
.name
, get_src (begin
), comment
);
3006 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3009 set_attributes (st
, attrs
);
3010 foreach (TypeParameter type_param
in type_param_list
) {
3011 st
.add_type_parameter (type_param
);
3013 if (base_type
!= null) {
3014 st
.base_type
= base_type
;
3017 parse_declarations (st
);
3020 while (sym
!= null) {
3023 Symbol next
= (sym
!= null ? new
Namespace (sym
.name
, st
.source_reference
) : parent
);
3024 if (result is Namespace
) {
3025 next
.add_namespace ((Namespace
) result
);
3027 next
.add_struct ((Struct
) result
);
3033 void parse_interface_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
3034 var begin
= get_location ();
3035 var access
= parse_access_modifier ();
3036 var flags
= parse_type_declaration_modifiers ();
3037 expect (TokenType
.INTERFACE
);
3038 var sym
= parse_symbol_name ();
3039 var type_param_list
= parse_type_parameter_list ();
3040 var base_types
= new ArrayList
<DataType
> ();
3041 if (accept (TokenType
.COLON
)) {
3043 var type
= parse_type (true, false);
3044 base_types
.add (type
);
3045 } while (accept (TokenType
.COMMA
));
3047 var iface
= new
Interface (sym
.name
, get_src (begin
), comment
);
3048 iface
.access
= access
;
3049 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3050 iface
.external
= true;
3052 set_attributes (iface
, attrs
);
3053 foreach (TypeParameter type_param
in type_param_list
) {
3054 iface
.add_type_parameter (type_param
);
3056 foreach (DataType base_type
in base_types
) {
3057 iface
.add_prerequisite (base_type
);
3060 parse_declarations (iface
);
3062 Symbol result
= iface
;
3063 while (sym
!= null) {
3066 Symbol next
= (sym
!= null ? new
Namespace (sym
.name
, iface
.source_reference
) : parent
);
3067 if (result is Namespace
) {
3068 next
.add_namespace ((Namespace
) result
);
3070 next
.add_interface ((Interface
) result
);
3076 void parse_enum_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
3077 var begin
= get_location ();
3078 var access
= parse_access_modifier ();
3079 var flags
= parse_type_declaration_modifiers ();
3080 expect (TokenType
.ENUM
);
3081 var sym
= parse_symbol_name ();
3082 var en
= new
Enum (sym
.name
, get_src (begin
), comment
);
3084 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3087 set_attributes (en
, attrs
);
3089 expect (TokenType
.OPEN_BRACE
);
3091 if (current () == TokenType
.CLOSE_BRACE
3092 && en
.get_values ().size
> 0) {
3093 // allow trailing comma
3096 var value_attrs
= parse_attributes ();
3097 var value_begin
= get_location ();
3098 string id
= parse_identifier ();
3099 comment
= scanner
.pop_comment ();
3101 Expression value
= null;
3102 if (accept (TokenType
.ASSIGN
)) {
3103 value
= parse_expression ();
3106 var ev
= new
EnumValue (id
, value
, get_src (value_begin
), comment
);
3107 ev
.access
= SymbolAccessibility
.PUBLIC
;
3108 set_attributes (ev
, value_attrs
);
3110 } while (accept (TokenType
.COMMA
));
3111 if (accept (TokenType
.SEMICOLON
)) {
3113 while (current () != TokenType
.CLOSE_BRACE
) {
3114 parse_declaration (en
);
3117 expect (TokenType
.CLOSE_BRACE
);
3120 while (sym
!= null) {
3123 Symbol next
= (sym
!= null ? new
Namespace (sym
.name
, en
.source_reference
) : parent
);
3124 if (result is Namespace
) {
3125 next
.add_namespace ((Namespace
) result
);
3127 next
.add_enum ((Enum
) result
);
3133 void parse_errordomain_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
3134 var begin
= get_location ();
3135 var access
= parse_access_modifier ();
3136 var flags
= parse_type_declaration_modifiers ();
3137 expect (TokenType
.ERRORDOMAIN
);
3138 var sym
= parse_symbol_name ();
3139 var ed
= new
ErrorDomain (sym
.name
, get_src (begin
), comment
);
3141 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3144 set_attributes (ed
, attrs
);
3146 expect (TokenType
.OPEN_BRACE
);
3148 if (current () == TokenType
.CLOSE_BRACE
3149 && ed
.get_codes ().size
> 0) {
3150 // allow trailing comma
3153 var code_attrs
= parse_attributes ();
3154 var code_begin
= get_location ();
3155 string id
= parse_identifier ();
3156 comment
= scanner
.pop_comment ();
3157 var ec
= new
ErrorCode (id
, get_src (code_begin
), comment
);
3158 set_attributes (ec
, code_attrs
);
3159 if (accept (TokenType
.ASSIGN
)) {
3160 ec
.value
= parse_expression ();
3163 } while (accept (TokenType
.COMMA
));
3164 if (accept (TokenType
.SEMICOLON
)) {
3165 // errordomain methods
3166 while (current () != TokenType
.CLOSE_BRACE
) {
3167 parse_declaration (ed
);
3170 expect (TokenType
.CLOSE_BRACE
);
3173 while (sym
!= null) {
3176 Symbol next
= (sym
!= null ? new
Namespace (sym
.name
, ed
.source_reference
) : parent
);
3177 if (result is Namespace
) {
3178 next
.add_namespace ((Namespace
) result
);
3180 next
.add_error_domain ((ErrorDomain
) result
);
3186 SymbolAccessibility
parse_access_modifier (SymbolAccessibility default_access
= SymbolAccessibility
.PRIVATE
) {
3187 switch (current ()) {
3188 case TokenType
.PRIVATE
:
3190 return SymbolAccessibility
.PRIVATE
;
3191 case TokenType
.PROTECTED
:
3193 return SymbolAccessibility
.PROTECTED
;
3194 case TokenType
.INTERNAL
:
3196 return SymbolAccessibility
.INTERNAL
;
3197 case TokenType
.PUBLIC
:
3199 return SymbolAccessibility
.PUBLIC
;
3201 return default_access
;
3205 ModifierFlags
parse_type_declaration_modifiers () {
3206 ModifierFlags flags
= 0;
3208 switch (current ()) {
3209 case TokenType
.ABSTRACT
:
3211 flags
|= ModifierFlags
.ABSTRACT
;
3213 case TokenType
.EXTERN
:
3215 flags
|= ModifierFlags
.EXTERN
;
3217 case TokenType
.SEALED
:
3219 flags
|= ModifierFlags
.SEALED
;
3227 ModifierFlags
parse_member_declaration_modifiers () {
3228 ModifierFlags flags
= 0;
3230 switch (current ()) {
3231 case TokenType
.ABSTRACT
:
3233 flags
|= ModifierFlags
.ABSTRACT
;
3235 case TokenType
.ASYNC
:
3237 flags
|= ModifierFlags
.ASYNC
;
3239 case TokenType
.CLASS
:
3241 flags
|= ModifierFlags
.CLASS
;
3243 case TokenType
.EXTERN
:
3245 flags
|= ModifierFlags
.EXTERN
;
3247 case TokenType
.INLINE
:
3249 flags
|= ModifierFlags
.INLINE
;
3253 flags
|= ModifierFlags
.NEW
;
3255 case TokenType
.OVERRIDE
:
3257 flags
|= ModifierFlags
.OVERRIDE
;
3259 case TokenType
.SEALED
:
3261 flags
|= ModifierFlags
.SEALED
;
3263 case TokenType
.STATIC
:
3265 flags
|= ModifierFlags
.STATIC
;
3267 case TokenType
.VIRTUAL
:
3269 flags
|= ModifierFlags
.VIRTUAL
;
3277 Parameter
parse_parameter () throws ParseError
{
3278 var attrs
= parse_attributes ();
3279 var begin
= get_location ();
3280 if (accept (TokenType
.ELLIPSIS
)) {
3282 return new Parameter
.with_ellipsis (get_src (begin
));
3284 bool params_array
= accept (TokenType
.PARAMS
);
3285 var direction
= ParameterDirection
.IN
;
3286 if (accept (TokenType
.OUT
)) {
3287 direction
= ParameterDirection
.OUT
;
3288 } else if (accept (TokenType
.REF
)) {
3289 direction
= ParameterDirection
.REF
;
3293 if (direction
== ParameterDirection
.IN
) {
3294 // in parameters are unowned by default
3295 type
= parse_type (false, false);
3296 } else if (direction
== ParameterDirection
.REF
) {
3297 // ref parameters own the value by default
3298 type
= parse_type (true, true);
3300 // out parameters own the value by default
3301 type
= parse_type (true, false);
3303 string id
= parse_identifier ();
3305 type
= parse_inline_array_type (type
);
3307 var param
= new
Parameter (id
, type
, get_src (begin
));
3308 set_attributes (param
, attrs
);
3309 param
.direction
= direction
;
3310 param
.params_array
= params_array
;
3311 if (accept (TokenType
.ASSIGN
)) {
3312 param
.initializer
= parse_expression ();
3317 void parse_creation_method_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
3318 var begin
= get_location ();
3319 var access
= parse_access_modifier ();
3320 var flags
= parse_member_declaration_modifiers ();
3321 var sym
= parse_symbol_name ();
3322 if (ModifierFlags
.NEW
in flags
) {
3323 throw new ParseError
.SYNTAX ("`new' modifier not allowed on creation method");
3325 CreationMethod method
;
3326 if (sym
.inner
== null) {
3327 method
= new
CreationMethod (sym
.name
, null, get_src (begin
), comment
);
3329 method
= new
CreationMethod (sym
.inner
.name
, sym
.name
, get_src (begin
), comment
);
3331 if (ModifierFlags
.EXTERN
in flags
) {
3332 method
.external
= true;
3334 if (ModifierFlags
.ABSTRACT
in flags
3335 || ModifierFlags
.VIRTUAL
in flags
3336 || ModifierFlags
.OVERRIDE
in flags
) {
3337 Report
.error (method
.source_reference
, "abstract, virtual, and override modifiers are not applicable to creation methods");
3339 if (ModifierFlags
.ASYNC
in flags
) {
3340 method
.coroutine
= true;
3342 expect (TokenType
.OPEN_PARENS
);
3343 if (current () != TokenType
.CLOSE_PARENS
) {
3345 var param
= parse_parameter ();
3346 method
.add_parameter (param
);
3347 } while (accept (TokenType
.COMMA
));
3349 expect (TokenType
.CLOSE_PARENS
);
3350 if (accept (TokenType
.THROWS
)) {
3352 method
.add_error_type (parse_type (true, false));
3353 } while (accept (TokenType
.COMMA
));
3355 while (accept (TokenType
.REQUIRES
)) {
3356 expect (TokenType
.OPEN_PARENS
);
3357 method
.add_precondition (parse_expression ());
3358 expect (TokenType
.CLOSE_PARENS
);
3360 while (accept (TokenType
.ENSURES
)) {
3361 expect (TokenType
.OPEN_PARENS
);
3362 method
.add_postcondition (parse_expression ());
3363 expect (TokenType
.CLOSE_PARENS
);
3365 method
.access
= access
;
3366 set_attributes (method
, attrs
);
3367 if (!accept (TokenType
.SEMICOLON
)) {
3368 method
.body
= parse_block ();
3369 } else if (scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3370 method
.external
= true;
3373 parent
.add_method (method
);
3376 void parse_delegate_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
3377 var begin
= get_location ();
3378 var access
= parse_access_modifier ();
3379 var flags
= parse_member_declaration_modifiers ();
3380 expect (TokenType
.DELEGATE
);
3381 if (ModifierFlags
.NEW
in flags
) {
3382 throw new ParseError
.SYNTAX ("`new' modifier not allowed on delegates");
3384 var type
= parse_type (true, false);
3385 var sym
= parse_symbol_name ();
3386 var type_param_list
= parse_type_parameter_list ();
3387 var d
= new
Delegate (sym
.name
, type
, get_src (begin
), comment
);
3389 set_attributes (d
, attrs
);
3390 if (ModifierFlags
.STATIC
in flags
) {
3391 if (!context
.deprecated
) {
3392 // TODO enable warning in future releases
3393 Report
.warning (get_last_src (), "deprecated syntax, use [CCode (has_target = false)]");
3395 d
.has_target
= false;
3397 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3400 if (!d
.get_attribute_bool ("CCode", "has_typedef", true)) {
3402 Report
.error (get_last_src (), "Delegates without definition must be external");
3406 foreach (TypeParameter type_param
in type_param_list
) {
3407 d
.add_type_parameter (type_param
);
3409 expect (TokenType
.OPEN_PARENS
);
3410 if (current () != TokenType
.CLOSE_PARENS
) {
3412 var param
= parse_parameter ();
3413 d
.add_parameter (param
);
3414 } while (accept (TokenType
.COMMA
));
3416 expect (TokenType
.CLOSE_PARENS
);
3417 if (accept (TokenType
.THROWS
)) {
3419 d
.add_error_type (parse_type (true, false));
3420 } while (accept (TokenType
.COMMA
));
3422 expect (TokenType
.SEMICOLON
);
3425 while (sym
!= null) {
3428 Symbol next
= (sym
!= null ? new
Namespace (sym
.name
, d
.source_reference
) : parent
);
3429 if (result is Namespace
) {
3430 next
.add_namespace ((Namespace
) result
);
3432 next
.add_delegate ((Delegate
) result
);
3438 List
<TypeParameter
> parse_type_parameter_list () throws ParseError
{
3439 if (accept (TokenType
.OP_LT
)) {
3440 var list
= new ArrayList
<TypeParameter
> ();
3442 var begin
= get_location ();
3443 string id
= parse_identifier ();
3444 list
.add (new
TypeParameter (id
, get_src (begin
)));
3445 } while (accept (TokenType
.COMMA
));
3446 expect (TokenType
.OP_GT
);
3449 if (_empty_type_parameter_list
== null) {
3450 _empty_type_parameter_list
= new ArrayList
<TypeParameter
> ();
3452 return _empty_type_parameter_list
;
3456 void skip_type_argument_list () throws ParseError
{
3457 if (accept (TokenType
.OP_LT
)) {
3460 } while (accept (TokenType
.COMMA
));
3461 expect (TokenType
.OP_GT
);
3465 // try to parse type argument list
3466 List
<DataType
>?
parse_type_argument_list (bool maybe_expression
) throws ParseError
{
3467 var begin
= get_location ();
3468 if (accept (TokenType
.OP_LT
)) {
3469 var list
= new ArrayList
<DataType
> ();
3471 switch (current ()) {
3472 case TokenType
.VOID
:
3473 case TokenType
.DYNAMIC
:
3474 case TokenType
.UNOWNED
:
3475 case TokenType
.WEAK
:
3476 case TokenType
.IDENTIFIER
:
3477 var type
= parse_type (true, true);
3484 } while (accept (TokenType
.COMMA
));
3485 if (!accept (TokenType
.OP_GT
)) {
3489 if (maybe_expression
) {
3490 // check follower to decide whether to keep type argument list
3491 switch (current ()) {
3492 case TokenType
.OPEN_PARENS
:
3493 case TokenType
.CLOSE_PARENS
:
3494 case TokenType
.CLOSE_BRACKET
:
3495 case TokenType
.OPEN_BRACE
:
3496 case TokenType
.COLON
:
3497 case TokenType
.SEMICOLON
:
3498 case TokenType
.COMMA
:
3500 case TokenType
.INTERR
:
3501 case TokenType
.OP_EQ
:
3502 case TokenType
.OP_NE
:
3503 // keep type argument list
3506 // interpret tokens as expression
3516 MemberAccess
parse_member_name (Expression? base_expr
= null) throws ParseError
{
3517 var begin
= get_location ();
3518 MemberAccess expr
= null;
3521 string id
= parse_identifier ();
3523 // The first member access can be global:: qualified
3524 bool qualified
= false;
3525 if (first
&& id
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
3526 id
= parse_identifier ();
3530 List
<DataType
> type_arg_list
= parse_type_argument_list (false);
3531 expr
= new
MemberAccess (expr
!= null ? expr
: base_expr
, id
, get_src (begin
));
3532 expr
.qualified
= qualified
;
3533 if (type_arg_list
!= null) {
3534 foreach (DataType type_arg
in type_arg_list
) {
3535 expr
.add_type_argument (type_arg
);
3540 } while (accept (TokenType
.DOT
));
3544 bool is_declaration_keyword (TokenType type
) {
3546 case TokenType
.ABSTRACT
:
3547 case TokenType
.ASYNC
:
3548 case TokenType
.CLASS
:
3549 case TokenType
.CONST
:
3550 case TokenType
.DELEGATE
:
3551 case TokenType
.ENUM
:
3552 case TokenType
.ERRORDOMAIN
:
3553 case TokenType
.EXTERN
:
3554 case TokenType
.INLINE
:
3555 case TokenType
.INTERFACE
:
3556 case TokenType
.INTERNAL
:
3557 case TokenType
.NAMESPACE
:
3559 case TokenType
.OVERRIDE
:
3560 case TokenType
.PRIVATE
:
3561 case TokenType
.PROTECTED
:
3562 case TokenType
.PUBLIC
:
3563 case TokenType
.SEALED
:
3564 case TokenType
.SIGNAL
:
3565 case TokenType
.STATIC
:
3566 case TokenType
.STRUCT
:
3567 case TokenType
.VIRTUAL
:
3568 case TokenType
.VOLATILE
:
3576 public errordomain Vala
.ParseError
{