3 * Copyright (C) 2006-2011 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
);
81 public override void visit_source_file (SourceFile source_file
) {
82 if (context
.run_output
|| source_file
.filename
.has_suffix (".vala") || source_file
.filename
.has_suffix (".vapi")) {
83 parse_file (source_file
);
88 index
= (index
+ 1) % BUFFER_SIZE
;
91 SourceLocation begin
, end
;
92 TokenType type
= scanner
.read_token (out begin
, out end
);
93 tokens
[index
].type
= type
;
94 tokens
[index
].begin
= begin
;
95 tokens
[index
].end
= end
;
98 return (tokens
[index
].type
!= TokenType
.EOF
);
101 inline
void prev () {
102 index
= (index
- 1 + BUFFER_SIZE
) % BUFFER_SIZE
;
104 assert (size
<= BUFFER_SIZE
);
107 inline TokenType
current () {
108 return tokens
[index
].type
;
111 inline
bool accept (TokenType type
) {
112 if (current () == type
) {
119 string get_error (string msg
) {
120 var begin
= get_location ();
122 Report
.error (get_src (begin
), "syntax error, " + msg
);
126 inline
bool expect (TokenType type
) throws ParseError
{
131 throw new ParseError
.SYNTAX (get_error ("expected %s".printf (type
.to_string ())));
134 inline SourceLocation
get_location () {
135 return tokens
[index
].begin
;
138 string get_current_string () {
139 return ((string) tokens
[index
].begin
.pos
).substring (0, (int) (tokens
[index
].end
.pos
- tokens
[index
].begin
.pos
));
142 string get_last_string () {
143 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
144 return ((string) tokens
[last_index
].begin
.pos
).substring (0, (int) (tokens
[last_index
].end
.pos
- tokens
[last_index
].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
.line
, begin
.column
, tokens
[last_index
].end
.line
, tokens
[last_index
].end
.column
);
153 SourceReference
get_current_src () {
154 return new
SourceReference (scanner
.source_file
, tokens
[index
].begin
.line
, tokens
[index
].begin
.column
, tokens
[index
].end
.line
, tokens
[index
].end
.column
);
157 SourceReference
get_last_src () {
158 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
160 return new
SourceReference (scanner
.source_file
, tokens
[last_index
].begin
.line
, tokens
[last_index
].begin
.column
, tokens
[last_index
].end
.line
, tokens
[last_index
].end
.column
);
163 void rollback (SourceLocation location
) {
164 while (tokens
[index
].begin
.pos
!= location
.pos
) {
165 index
= (index
- 1 + BUFFER_SIZE
) % BUFFER_SIZE
;
167 if (size
> BUFFER_SIZE
) {
168 scanner
.seek (location
);
177 void skip_identifier () throws ParseError
{
178 // also accept keywords as identifiers where there is no conflict
179 switch (current ()) {
180 case TokenType
.ABSTRACT
:
182 case TokenType
.ASYNC
:
184 case TokenType
.BREAK
:
186 case TokenType
.CATCH
:
187 case TokenType
.CLASS
:
188 case TokenType
.CONST
:
189 case TokenType
.CONSTRUCT
:
190 case TokenType
.CONTINUE
:
191 case TokenType
.DEFAULT
:
192 case TokenType
.DELEGATE
:
193 case TokenType
.DELETE
:
195 case TokenType
.DYNAMIC
:
198 case TokenType
.ENSURES
:
199 case TokenType
.ERRORDOMAIN
:
200 case TokenType
.EXTERN
:
201 case TokenType
.FALSE
:
202 case TokenType
.FINALLY
:
204 case TokenType
.FOREACH
:
206 case TokenType
.IDENTIFIER
:
209 case TokenType
.INLINE
:
210 case TokenType
.INTERFACE
:
211 case TokenType
.INTERNAL
:
214 case TokenType
.NAMESPACE
:
218 case TokenType
.OVERRIDE
:
219 case TokenType
.OWNED
:
220 case TokenType
.PARAMS
:
221 case TokenType
.PRIVATE
:
222 case TokenType
.PROTECTED
:
223 case TokenType
.PUBLIC
:
225 case TokenType
.REQUIRES
:
226 case TokenType
.RETURN
:
227 case TokenType
.SEALED
:
229 case TokenType
.SIGNAL
:
230 case TokenType
.SIZEOF
:
231 case TokenType
.STATIC
:
232 case TokenType
.STRUCT
:
233 case TokenType
.SWITCH
:
235 case TokenType
.THROW
:
236 case TokenType
.THROWS
:
239 case TokenType
.TYPEOF
:
240 case TokenType
.UNOWNED
:
241 case TokenType
.USING
:
243 case TokenType
.VIRTUAL
:
245 case TokenType
.VOLATILE
:
247 case TokenType
.WHILE
:
248 case TokenType
.YIELD
:
251 case TokenType
.INTEGER_LITERAL
:
252 case TokenType
.REAL_LITERAL
:
253 // also accept integer and real literals
254 // as long as they contain at least one character
255 // and no decimal point
256 // for example, 2D and 3D
257 string id
= get_current_string ();
258 if (id
[id
.length
- 1].isalpha () && !("." in id
)) {
264 throw new ParseError
.SYNTAX (get_error ("expected identifier"));
268 string parse_identifier () throws ParseError
{
270 return get_last_string ();
273 Expression
parse_literal () throws ParseError
{
274 var begin
= get_location ();
276 switch (current ()) {
279 return new
BooleanLiteral (true, get_src (begin
));
280 case TokenType
.FALSE
:
282 return new
BooleanLiteral (false, get_src (begin
));
283 case TokenType
.INTEGER_LITERAL
:
285 return new
IntegerLiteral (get_last_string (), get_src (begin
));
286 case TokenType
.REAL_LITERAL
:
288 return new
RealLiteral (get_last_string (), get_src (begin
));
289 case TokenType
.CHARACTER_LITERAL
:
291 // FIXME validate and unescape here and just pass unichar to CharacterLiteral
292 var lit
= new
CharacterLiteral (get_last_string (), get_src (begin
));
294 Report
.error (lit
.source_reference
, "invalid character literal");
297 case TokenType
.REGEX_LITERAL
:
299 string match_part
= get_last_string ();
300 SourceReference src_begin
= get_src (begin
);
301 expect (TokenType
.CLOSE_REGEX_LITERAL
);
302 string close_token
= get_last_string ();
303 return new
RegexLiteral ("%s/%s".printf (close_token
, match_part
), src_begin
);
304 case TokenType
.STRING_LITERAL
:
306 return new
StringLiteral (get_last_string (), get_src (begin
));
307 case TokenType
.TEMPLATE_STRING_LITERAL
:
309 return new
StringLiteral ("\"%s\"".printf (get_last_string ()), get_src (begin
));
310 case TokenType
.VERBATIM_STRING_LITERAL
:
312 string raw_string
= get_last_string ();
313 string escaped_string
= raw_string
.substring (3, raw_string
.length
- 6).escape ("");
314 return new
StringLiteral ("\"%s\"".printf (escaped_string
), get_src (begin
));
317 return new
NullLiteral (get_src (begin
));
319 throw new ParseError
.SYNTAX (get_error ("expected literal"));
323 public void parse_file (SourceFile source_file
) {
324 scanner
= new
Scanner (source_file
);
325 parse_file_comments ();
334 parse_using_directives (context
.root
);
335 parse_declarations (context
.root
, true);
336 if (accept (TokenType
.CLOSE_BRACE
)) {
337 // only report error if it's not a secondary error
338 if (context
.report
.get_errors () == 0) {
339 Report
.error (get_last_src (), "unexpected `}'");
342 } catch (ParseError e
) {
349 void parse_file_comments () {
350 scanner
.parse_file_comments ();
353 void skip_symbol_name () throws ParseError
{
356 } while (accept (TokenType
.DOT
) || accept (TokenType
.DOUBLE_COLON
));
359 UnresolvedSymbol
parse_symbol_name () throws ParseError
{
360 var begin
= get_location ();
361 UnresolvedSymbol sym
= null;
363 string name
= parse_identifier ();
364 if (name
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
366 // qualified access to global symbol
367 name
= parse_identifier ();
368 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
369 sym
.qualified
= true;
372 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
373 } while (accept (TokenType
.DOT
));
377 void skip_type () throws ParseError
{
378 if (accept (TokenType
.VOID
)) {
379 while (accept (TokenType
.STAR
)) {
383 accept (TokenType
.DYNAMIC
);
384 accept (TokenType
.OWNED
);
385 accept (TokenType
.UNOWNED
);
386 accept (TokenType
.WEAK
);
388 skip_type_argument_list ();
389 while (accept (TokenType
.STAR
)) {
391 accept (TokenType
.INTERR
);
392 while (accept (TokenType
.OPEN_BRACKET
)) {
394 // required for decision between expression and declaration statement
395 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
398 } while (accept (TokenType
.COMMA
));
399 expect (TokenType
.CLOSE_BRACKET
);
400 accept (TokenType
.INTERR
);
402 accept (TokenType
.OP_NEG
);
403 accept (TokenType
.HASH
);
406 DataType
parse_type (bool owned_by_default
, bool can_weak_ref
) throws ParseError
{
407 var begin
= get_location ();
409 if (accept (TokenType
.VOID
)) {
410 DataType type
= new
VoidType (get_src (begin
));
411 while (accept (TokenType
.STAR
)) {
412 type
= new
PointerType (type
);
417 bool is_dynamic
= accept (TokenType
.DYNAMIC
);
419 bool value_owned
= owned_by_default
;
421 if (owned_by_default
) {
422 if (context
.profile
== Profile
.DOVA
) {
423 if (can_weak_ref
&& accept (TokenType
.WEAK
)) {
426 } else if (accept (TokenType
.UNOWNED
)) {
428 } else if (accept (TokenType
.WEAK
)) {
429 if (!can_weak_ref
&& !context
.deprecated
) {
430 Report
.warning (get_last_src (), "deprecated syntax, use `unowned` modifier");
435 value_owned
= (context
.profile
!= Profile
.DOVA
&& accept (TokenType
.OWNED
));
438 var sym
= parse_symbol_name ();
439 List
<DataType
> type_arg_list
= parse_type_argument_list (false);
441 DataType type
= new UnresolvedType
.from_symbol (sym
, get_src (begin
));
442 if (type_arg_list
!= null) {
443 foreach (DataType type_arg
in type_arg_list
) {
444 type
.add_type_argument (type_arg
);
448 while (accept (TokenType
.STAR
)) {
449 type
= new
PointerType (type
, get_src (begin
));
452 if (!(type is PointerType
)) {
453 type
.nullable
= accept (TokenType
.INTERR
);
456 // array brackets in types are read from right to left,
457 // this is more logical, especially when nullable arrays
458 // or pointers are involved
459 while (accept (TokenType
.OPEN_BRACKET
)) {
460 bool invalid_array
= false;
464 // required for decision between expression and declaration statement
465 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
467 // only used for parsing, reject use as real type
468 invalid_array
= true;
470 } while (context
.profile
!= Profile
.DOVA
&& accept (TokenType
.COMMA
));
471 expect (TokenType
.CLOSE_BRACKET
);
473 // arrays contain strong references by default
474 type
.value_owned
= true;
476 var array_type
= new
ArrayType (type
, array_rank
, get_src (begin
));
477 array_type
.nullable
= accept (TokenType
.INTERR
);
478 array_type
.invalid_syntax
= invalid_array
;
483 if (accept (TokenType
.OP_NEG
)) {
484 Report
.warning (get_last_src (), "obsolete syntax, types are non-null by default");
487 if (!owned_by_default
) {
488 if (context
.profile
!= Profile
.DOVA
&& accept (TokenType
.HASH
)) {
489 if (!context
.deprecated
) {
490 Report
.warning (get_last_src (), "deprecated syntax, use `owned` modifier");
496 type
.is_dynamic
= is_dynamic
;
497 type
.value_owned
= value_owned
;
501 DataType?
parse_inline_array_type (DataType? type
) throws ParseError
{
502 var begin
= get_location ();
504 // inline-allocated array
505 if (type
!= null && accept (TokenType
.OPEN_BRACKET
)) {
506 int array_length
= -1;
508 if (current () != TokenType
.CLOSE_BRACKET
) {
509 if (current () != TokenType
.INTEGER_LITERAL
) {
510 throw new ParseError
.SYNTAX (get_error ("expected `]' or integer literal"));
513 var length_literal
= (IntegerLiteral
) parse_literal ();
514 array_length
= int.parse (length_literal
.value
);
516 expect (TokenType
.CLOSE_BRACKET
);
518 var array_type
= new
ArrayType (type
, 1, get_src (begin
));
519 array_type
.inline_allocated
= true;
520 if (array_length
> 0) {
521 array_type
.fixed_length
= true;
522 array_type
.length
= array_length
;
524 array_type
.value_owned
= type
.value_owned
;
531 List
<Expression
> parse_argument_list () throws ParseError
{
532 var list
= new ArrayList
<Expression
> ();
533 if (current () != TokenType
.CLOSE_PARENS
) {
535 list
.add (parse_argument ());
536 } while (accept (TokenType
.COMMA
));
541 Expression
parse_argument () throws ParseError
{
542 var begin
= get_location ();
544 if (accept (TokenType
.REF
)) {
545 var inner
= parse_expression ();
546 return new
UnaryExpression (UnaryOperator
.REF
, inner
, get_src (begin
));
547 } else if (accept (TokenType
.OUT
)) {
548 var inner
= parse_expression ();
549 return new
UnaryExpression (UnaryOperator
.OUT
, inner
, get_src (begin
));
551 var expr
= parse_expression ();
552 var ma
= expr as MemberAccess
;
553 if (ma
!= null && ma
.inner
== null && accept (TokenType
.COLON
)) {
555 expr
= parse_expression ();
556 return new
NamedArgument (ma
.member_name
, expr
, get_src (begin
));
563 Expression
parse_primary_expression () throws ParseError
{
564 var begin
= get_location ();
568 switch (current ()) {
570 case TokenType
.FALSE
:
571 case TokenType
.INTEGER_LITERAL
:
572 case TokenType
.REAL_LITERAL
:
573 case TokenType
.CHARACTER_LITERAL
:
574 case TokenType
.STRING_LITERAL
:
575 case TokenType
.REGEX_LITERAL
:
576 case TokenType
.TEMPLATE_STRING_LITERAL
:
577 case TokenType
.VERBATIM_STRING_LITERAL
:
579 expr
= parse_literal ();
581 case TokenType
.OPEN_BRACE
:
582 if (context
.profile
== Profile
.DOVA
) {
583 expr
= parse_set_literal ();
585 expr
= parse_initializer ();
588 case TokenType
.OPEN_BRACKET
:
589 if (context
.profile
== Profile
.DOVA
) {
590 expr
= parse_list_literal ();
592 expr
= parse_simple_name ();
595 case TokenType
.OPEN_PARENS
:
596 expr
= parse_tuple ();
598 case TokenType
.OPEN_TEMPLATE
:
599 expr
= parse_template ();
601 case TokenType
.OPEN_REGEX_LITERAL
:
602 expr
= parse_regex_literal ();
605 expr
= parse_this_access ();
608 expr
= parse_base_access ();
611 expr
= parse_object_or_array_creation_expression ();
613 case TokenType
.YIELD
:
614 expr
= parse_yield_expression ();
616 case TokenType
.SIZEOF
:
617 expr
= parse_sizeof_expression ();
619 case TokenType
.TYPEOF
:
620 expr
= parse_typeof_expression ();
623 expr
= parse_simple_name ();
627 // process primary expressions that start with an inner primary expression
630 switch (current ()) {
632 expr
= parse_member_access (begin
, expr
);
634 case TokenType
.OP_PTR
:
635 if (context
.profile
== Profile
.DOVA
) {
638 expr
= parse_pointer_member_access (begin
, expr
);
641 case TokenType
.OPEN_PARENS
:
642 expr
= parse_method_call (begin
, expr
);
644 case TokenType
.OPEN_BRACKET
:
645 expr
= parse_element_access (begin
, expr
);
647 case TokenType
.OPEN_BRACE
:
648 var ma
= expr as MemberAccess
;
649 if (context
.profile
== Profile
.DOVA
&& ma
!= null) {
650 expr
= parse_object_literal (begin
, ma
);
655 case TokenType
.OP_INC
:
656 expr
= parse_post_increment_expression (begin
, expr
);
658 case TokenType
.OP_DEC
:
659 expr
= parse_post_decrement_expression (begin
, expr
);
670 Expression
parse_simple_name () throws ParseError
{
671 var begin
= get_location ();
672 string id
= parse_identifier ();
673 bool qualified
= false;
674 if (id
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
675 id
= parse_identifier ();
678 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
679 var expr
= new
MemberAccess (null, id
, get_src (begin
));
680 expr
.qualified
= qualified
;
681 if (type_arg_list
!= null) {
682 foreach (DataType type_arg
in type_arg_list
) {
683 expr
.add_type_argument (type_arg
);
689 Expression
parse_tuple () throws ParseError
{
690 var begin
= get_location ();
692 expect (TokenType
.OPEN_PARENS
);
693 var expr_list
= new ArrayList
<Expression
> ();
694 if (current () != TokenType
.CLOSE_PARENS
) {
696 expr_list
.add (parse_expression ());
697 } while (accept (TokenType
.COMMA
));
699 expect (TokenType
.CLOSE_PARENS
);
700 if (expr_list
.size
!= 1) {
701 var tuple
= new
Tuple (get_src (begin
));
702 foreach (Expression expr
in expr_list
) {
703 tuple
.add_expression (expr
);
707 return expr_list
.get (0);
710 Expression
parse_template () throws ParseError
{
711 var begin
= get_location ();
712 var template
= new
Template ();
714 expect (TokenType
.OPEN_TEMPLATE
);
715 while (current () != TokenType
.CLOSE_TEMPLATE
) {
716 template
.add_expression (parse_expression ());
717 expect (TokenType
.COMMA
);
719 expect (TokenType
.CLOSE_TEMPLATE
);
721 template
.source_reference
= get_src (begin
);
725 Expression
parse_regex_literal () throws ParseError
{
726 expect (TokenType
.OPEN_REGEX_LITERAL
);
728 var expr
= parse_literal ();
733 Expression
parse_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
734 expect (TokenType
.DOT
);
735 string id
= parse_identifier ();
736 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
737 var expr
= new
MemberAccess (inner
, id
, get_src (begin
));
738 if (type_arg_list
!= null) {
739 foreach (DataType type_arg
in type_arg_list
) {
740 expr
.add_type_argument (type_arg
);
746 Expression
parse_pointer_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
747 expect (TokenType
.OP_PTR
);
748 string id
= parse_identifier ();
749 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
750 var expr
= new MemberAccess
.pointer (inner
, id
, get_src (begin
));
751 if (type_arg_list
!= null) {
752 foreach (DataType type_arg
in type_arg_list
) {
753 expr
.add_type_argument (type_arg
);
759 Expression
parse_method_call (SourceLocation begin
, Expression inner
) throws ParseError
{
760 expect (TokenType
.OPEN_PARENS
);
761 var arg_list
= parse_argument_list ();
762 expect (TokenType
.CLOSE_PARENS
);
763 var init_list
= parse_object_initializer ();
765 if (init_list
.size
> 0 && inner is MemberAccess
) {
766 // struct creation expression
767 var member
= (MemberAccess
) inner
;
768 member
.creation_member
= true;
770 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
771 expr
.struct_creation
= true;
772 foreach (Expression arg
in arg_list
) {
773 expr
.add_argument (arg
);
775 foreach (MemberInitializer initializer
in init_list
) {
776 expr
.add_member_initializer (initializer
);
780 var expr
= new
MethodCall (inner
, get_src (begin
));
781 foreach (Expression arg
in arg_list
) {
782 expr
.add_argument (arg
);
788 Expression
parse_element_access (SourceLocation begin
, Expression inner
) throws ParseError
{
789 expect (TokenType
.OPEN_BRACKET
);
790 var index_list
= parse_expression_list ();
791 Expression? stop
= null;
792 if (index_list
.size
== 1 && accept (TokenType
.COLON
)) {
794 stop
= parse_expression ();
796 expect (TokenType
.CLOSE_BRACKET
);
799 var expr
= new
ElementAccess (inner
, get_src (begin
));
800 foreach (Expression index
in index_list
) {
801 expr
.append_index (index
);
805 return new
SliceExpression (inner
, index_list
[0], stop
, get_src (begin
));
809 List
<Expression
> parse_expression_list () throws ParseError
{
810 var list
= new ArrayList
<Expression
> ();
812 list
.add (parse_expression ());
813 } while (accept (TokenType
.COMMA
));
817 Expression
parse_this_access () throws ParseError
{
818 var begin
= get_location ();
819 expect (TokenType
.THIS
);
820 return new
MemberAccess (null, "this", get_src (begin
));
823 Expression
parse_base_access () throws ParseError
{
824 var begin
= get_location ();
825 expect (TokenType
.BASE
);
826 return new
BaseAccess (get_src (begin
));
829 Expression
parse_post_increment_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
830 expect (TokenType
.OP_INC
);
831 return new
PostfixExpression (inner
, true, get_src (begin
));
834 Expression
parse_post_decrement_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
835 expect (TokenType
.OP_DEC
);
836 return new
PostfixExpression (inner
, false, get_src (begin
));
839 Expression
parse_object_or_array_creation_expression () throws ParseError
{
840 var begin
= get_location ();
841 expect (TokenType
.NEW
);
842 var member
= parse_member_name ();
843 if (accept (TokenType
.OPEN_PARENS
)) {
844 var expr
= parse_object_creation_expression (begin
, member
);
846 } else if (accept (TokenType
.OPEN_BRACKET
)) {
847 var expr
= parse_array_creation_expression (begin
, member
);
850 throw new ParseError
.SYNTAX (get_error ("expected ( or ["));
854 Expression
parse_object_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
855 member
.creation_member
= true;
856 var arg_list
= parse_argument_list ();
857 expect (TokenType
.CLOSE_PARENS
);
858 var init_list
= parse_object_initializer ();
860 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
861 foreach (Expression arg
in arg_list
) {
862 expr
.add_argument (arg
);
864 foreach (MemberInitializer initializer
in init_list
) {
865 expr
.add_member_initializer (initializer
);
870 Expression
parse_object_literal (SourceLocation begin
, MemberAccess member
) throws ParseError
{
871 member
.creation_member
= true;
873 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
875 expect (TokenType
.OPEN_BRACE
);
878 var member_begin
= get_location ();
879 string id
= parse_identifier ();
880 expect (TokenType
.COLON
);
881 var member_expr
= parse_expression ();
883 expr
.add_member_initializer (new
MemberInitializer (id
, member_expr
, get_src (member_begin
)));
884 } while (accept (TokenType
.COMMA
));
886 expect (TokenType
.CLOSE_BRACE
);
891 Expression
parse_array_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
892 bool size_specified
= false;
893 List
<Expression
> size_specifier_list
= null;
895 DataType element_type
= UnresolvedType
.new_from_expression (member
);
898 // array of arrays: new T[][42]
900 if (size_specified
) {
901 throw new ParseError
.SYNTAX (get_error ("size of inner arrays must not be specified in array creation expression"));
904 element_type
= new
ArrayType (element_type
, size_specifier_list
.size
, element_type
.source_reference
);
909 size_specifier_list
= new ArrayList
<Expression
> ();
911 Expression size
= null;
912 if (current () != TokenType
.CLOSE_BRACKET
&& current () != TokenType
.COMMA
) {
913 size
= parse_expression ();
914 size_specified
= true;
916 size_specifier_list
.add (size
);
917 } while (context
.profile
!= Profile
.DOVA
&& accept (TokenType
.COMMA
));
918 expect (TokenType
.CLOSE_BRACKET
);
919 } while (accept (TokenType
.OPEN_BRACKET
));
921 InitializerList initializer
= null;
922 if (context
.profile
!= Profile
.DOVA
&& current () == TokenType
.OPEN_BRACE
) {
923 initializer
= parse_initializer ();
925 var expr
= new
ArrayCreationExpression (element_type
, size_specifier_list
.size
, initializer
, get_src (begin
));
926 if (size_specified
) {
927 foreach (Expression size
in size_specifier_list
) {
928 expr
.append_size (size
);
934 List
<MemberInitializer
> parse_object_initializer () throws ParseError
{
935 var list
= new ArrayList
<MemberInitializer
> ();
936 if (context
.profile
!= Profile
.DOVA
&& accept (TokenType
.OPEN_BRACE
)) {
938 list
.add (parse_member_initializer ());
939 } while (accept (TokenType
.COMMA
));
940 expect (TokenType
.CLOSE_BRACE
);
945 MemberInitializer
parse_member_initializer () throws ParseError
{
946 var begin
= get_location ();
947 string id
= parse_identifier ();
948 expect (TokenType
.ASSIGN
);
949 var expr
= parse_expression ();
951 return new
MemberInitializer (id
, expr
, get_src (begin
));
954 Expression
parse_yield_expression () throws ParseError
{
955 expect (TokenType
.YIELD
);
956 var expr
= parse_expression ();
958 var call
= expr as MethodCall
;
960 Report
.error (expr
.source_reference
, "syntax error, expected method call");
961 throw new ParseError
.SYNTAX ("expected method call");
964 call
.is_yield_expression
= true;
968 Expression
parse_sizeof_expression () throws ParseError
{
969 var begin
= get_location ();
970 expect (TokenType
.SIZEOF
);
971 expect (TokenType
.OPEN_PARENS
);
972 var type
= parse_type (true, false);
973 expect (TokenType
.CLOSE_PARENS
);
975 return new
SizeofExpression (type
, get_src (begin
));
978 Expression
parse_typeof_expression () throws ParseError
{
979 var begin
= get_location ();
980 expect (TokenType
.TYPEOF
);
981 expect (TokenType
.OPEN_PARENS
);
982 var type
= parse_type (true, false);
983 expect (TokenType
.CLOSE_PARENS
);
985 return new
TypeofExpression (type
, get_src (begin
));
988 UnaryOperator
get_unary_operator (TokenType token_type
) {
989 switch (token_type
) {
990 case TokenType
.PLUS
: return UnaryOperator
.PLUS
;
991 case TokenType
.MINUS
: return UnaryOperator
.MINUS
;
992 case TokenType
.OP_NEG
: return UnaryOperator
.LOGICAL_NEGATION
;
993 case TokenType
.TILDE
: return UnaryOperator
.BITWISE_COMPLEMENT
;
994 case TokenType
.OP_INC
: return UnaryOperator
.INCREMENT
;
995 case TokenType
.OP_DEC
: return UnaryOperator
.DECREMENT
;
996 default: return UnaryOperator
.NONE
;
1000 Expression
parse_unary_expression () throws ParseError
{
1001 var begin
= get_location ();
1002 var operator
= get_unary_operator (current ());
1003 if (operator
!= UnaryOperator
.NONE
) {
1005 var op
= parse_unary_expression ();
1006 return new
UnaryExpression (operator
, op
, get_src (begin
));
1008 switch (current ()) {
1009 case TokenType
.HASH
:
1010 if (!context
.deprecated
) {
1011 Report
.warning (get_last_src (), "deprecated syntax, use `(owned)` cast");
1014 var op
= parse_unary_expression ();
1015 return new
ReferenceTransferExpression (op
, get_src (begin
));
1016 case TokenType
.OPEN_PARENS
:
1018 switch (current ()) {
1019 case TokenType
.OWNED
:
1022 if (accept (TokenType
.CLOSE_PARENS
)) {
1023 var op
= parse_unary_expression ();
1024 return new
ReferenceTransferExpression (op
, get_src (begin
));
1027 case TokenType
.VOID
:
1028 case TokenType
.DYNAMIC
:
1029 case TokenType
.IDENTIFIER
:
1030 var type
= parse_type (true, false);
1031 if (accept (TokenType
.CLOSE_PARENS
)) {
1032 // check follower to decide whether to create cast expression
1033 switch (current ()) {
1034 case TokenType
.OP_NEG
:
1035 case TokenType
.TILDE
:
1036 case TokenType
.OPEN_PARENS
:
1037 case TokenType
.TRUE
:
1038 case TokenType
.FALSE
:
1039 case TokenType
.INTEGER_LITERAL
:
1040 case TokenType
.REAL_LITERAL
:
1041 case TokenType
.CHARACTER_LITERAL
:
1042 case TokenType
.STRING_LITERAL
:
1043 case TokenType
.TEMPLATE_STRING_LITERAL
:
1044 case TokenType
.VERBATIM_STRING_LITERAL
:
1045 case TokenType
.REGEX_LITERAL
:
1046 case TokenType
.NULL
:
1047 case TokenType
.THIS
:
1048 case TokenType
.BASE
:
1050 case TokenType
.YIELD
:
1051 case TokenType
.SIZEOF
:
1052 case TokenType
.TYPEOF
:
1053 case TokenType
.IDENTIFIER
:
1054 case TokenType
.PARAMS
:
1055 var inner
= parse_unary_expression ();
1056 return new
CastExpression (inner
, type
, get_src (begin
), false);
1062 case TokenType
.OP_NEG
:
1064 if (accept (TokenType
.CLOSE_PARENS
)) {
1065 // (!) non-null cast
1066 var inner
= parse_unary_expression ();
1067 return new CastExpression
.non_null (inner
, get_src (begin
));
1073 // no cast expression
1076 case TokenType
.STAR
:
1078 var op
= parse_unary_expression ();
1079 return new
PointerIndirection (op
, get_src (begin
));
1080 case TokenType
.BITWISE_AND
:
1082 var op
= parse_unary_expression ();
1083 return new
AddressofExpression (op
, get_src (begin
));
1088 var expr
= parse_primary_expression ();
1092 BinaryOperator
get_binary_operator (TokenType token_type
) {
1093 switch (token_type
) {
1094 case TokenType
.STAR
: return BinaryOperator
.MUL
;
1095 case TokenType
.DIV
: return BinaryOperator
.DIV
;
1096 case TokenType
.PERCENT
: return BinaryOperator
.MOD
;
1097 case TokenType
.PLUS
: return BinaryOperator
.PLUS
;
1098 case TokenType
.MINUS
: return BinaryOperator
.MINUS
;
1099 case TokenType
.OP_LT
: return BinaryOperator
.LESS_THAN
;
1100 case TokenType
.OP_GT
: return BinaryOperator
.GREATER_THAN
;
1101 case TokenType
.OP_LE
: return BinaryOperator
.LESS_THAN_OR_EQUAL
;
1102 case TokenType
.OP_GE
: return BinaryOperator
.GREATER_THAN_OR_EQUAL
;
1103 case TokenType
.OP_EQ
: return BinaryOperator
.EQUALITY
;
1104 case TokenType
.OP_NE
: return BinaryOperator
.INEQUALITY
;
1105 default: return BinaryOperator
.NONE
;
1109 Expression
parse_multiplicative_expression () throws ParseError
{
1110 var begin
= get_location ();
1111 var left
= parse_unary_expression ();
1114 var operator
= get_binary_operator (current ());
1116 case BinaryOperator
.MUL
:
1117 case BinaryOperator
.DIV
:
1118 case BinaryOperator
.MOD
:
1120 var right
= parse_unary_expression ();
1121 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1131 Expression
parse_additive_expression () throws ParseError
{
1132 var begin
= get_location ();
1133 var left
= parse_multiplicative_expression ();
1136 var operator
= get_binary_operator (current ());
1138 case BinaryOperator
.PLUS
:
1139 case BinaryOperator
.MINUS
:
1141 var right
= parse_multiplicative_expression ();
1142 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1152 Expression
parse_shift_expression () throws ParseError
{
1153 var begin
= get_location ();
1154 var left
= parse_additive_expression ();
1157 switch (current ()) {
1158 case TokenType
.OP_SHIFT_LEFT
:
1160 var right
= parse_additive_expression ();
1161 left
= new
BinaryExpression (BinaryOperator
.SHIFT_LEFT
, left
, right
, get_src (begin
));
1163 // don't use OP_SHIFT_RIGHT to support >> for nested generics
1164 case TokenType
.OP_GT
:
1165 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1167 // only accept >> when there is no space between the two > signs
1168 if (current () == TokenType
.OP_GT
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1170 var right
= parse_additive_expression ();
1171 left
= new
BinaryExpression (BinaryOperator
.SHIFT_RIGHT
, left
, right
, get_src (begin
));
1185 Expression
parse_relational_expression () throws ParseError
{
1186 var begin
= get_location ();
1187 var left
= parse_shift_expression ();
1192 var operator
= get_binary_operator (current ());
1194 case BinaryOperator
.LESS_THAN
:
1195 case BinaryOperator
.LESS_THAN_OR_EQUAL
:
1196 case BinaryOperator
.GREATER_THAN_OR_EQUAL
:
1198 var right
= parse_shift_expression ();
1199 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1201 var be
= (BinaryExpression
) left
;
1203 if (!context
.experimental
) {
1204 Report
.warning (left
.source_reference
, "chained relational expressions are experimental");
1209 case BinaryOperator
.GREATER_THAN
:
1211 // ignore >> and >>= (two tokens due to generics)
1212 if (current () != TokenType
.OP_GT
&& current () != TokenType
.OP_GE
) {
1213 var right
= parse_shift_expression ();
1214 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1216 var be
= (BinaryExpression
) left
;
1218 if (!context
.experimental
) {
1219 Report
.warning (left
.source_reference
, "chained relational expressions are experimental");
1229 switch (current ()) {
1232 var type
= parse_type (true, false);
1233 left
= new
TypeCheck (left
, type
, get_src (begin
));
1237 var type
= parse_type (true, false);
1238 left
= new
CastExpression (left
, type
, get_src (begin
), true);
1250 Expression
parse_equality_expression () throws ParseError
{
1251 var begin
= get_location ();
1252 var left
= parse_relational_expression ();
1255 var operator
= get_binary_operator (current ());
1257 case BinaryOperator
.EQUALITY
:
1258 case BinaryOperator
.INEQUALITY
:
1260 var right
= parse_relational_expression ();
1261 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1271 Expression
parse_and_expression () throws ParseError
{
1272 var begin
= get_location ();
1273 var left
= parse_equality_expression ();
1274 while (accept (TokenType
.BITWISE_AND
)) {
1275 var right
= parse_equality_expression ();
1276 left
= new
BinaryExpression (BinaryOperator
.BITWISE_AND
, left
, right
, get_src (begin
));
1281 Expression
parse_exclusive_or_expression () throws ParseError
{
1282 var begin
= get_location ();
1283 var left
= parse_and_expression ();
1284 while (accept (TokenType
.CARRET
)) {
1285 var right
= parse_and_expression ();
1286 left
= new
BinaryExpression (BinaryOperator
.BITWISE_XOR
, left
, right
, get_src (begin
));
1291 Expression
parse_inclusive_or_expression () throws ParseError
{
1292 var begin
= get_location ();
1293 var left
= parse_exclusive_or_expression ();
1294 while (accept (TokenType
.BITWISE_OR
)) {
1295 var right
= parse_exclusive_or_expression ();
1296 left
= new
BinaryExpression (BinaryOperator
.BITWISE_OR
, left
, right
, get_src (begin
));
1301 Expression
parse_in_expression () throws ParseError
{
1302 var begin
= get_location ();
1303 var left
= parse_inclusive_or_expression ();
1304 while (accept (TokenType
.IN
)) {
1305 var right
= parse_inclusive_or_expression ();
1306 left
= new
BinaryExpression (BinaryOperator
.IN
, left
, right
, get_src (begin
));
1311 Expression
parse_conditional_and_expression () throws ParseError
{
1312 var begin
= get_location ();
1313 var left
= parse_in_expression ();
1314 while (accept (TokenType
.OP_AND
)) {
1315 var right
= parse_in_expression ();
1316 left
= new
BinaryExpression (BinaryOperator
.AND
, left
, right
, get_src (begin
));
1321 Expression
parse_conditional_or_expression () throws ParseError
{
1322 var begin
= get_location ();
1323 var left
= parse_conditional_and_expression ();
1324 while (accept (TokenType
.OP_OR
)) {
1325 var right
= parse_conditional_and_expression ();
1326 left
= new
BinaryExpression (BinaryOperator
.OR
, left
, right
, get_src (begin
));
1331 Expression
parse_coalescing_expression () throws ParseError
{
1332 var begin
= get_location ();
1333 var left
= parse_conditional_or_expression ();
1334 if (accept (TokenType
.OP_COALESCING
)) {
1335 var right
= parse_coalescing_expression ();
1336 return new
BinaryExpression (BinaryOperator
.COALESCE
, left
, right
, get_src (begin
));
1342 Expression
parse_conditional_expression () throws ParseError
{
1343 var begin
= get_location ();
1344 var condition
= parse_coalescing_expression ();
1345 if (accept (TokenType
.INTERR
)) {
1346 var true_expr
= parse_expression ();
1347 expect (TokenType
.COLON
);
1348 var false_expr
= parse_expression ();
1349 return new
ConditionalExpression (condition
, true_expr
, false_expr
, get_src (begin
));
1355 Expression
parse_lambda_expression () throws ParseError
{
1356 var begin
= get_location ();
1357 List
<string> params
= new ArrayList
<string> ();
1358 if (accept (TokenType
.OPEN_PARENS
)) {
1359 if (current () != TokenType
.CLOSE_PARENS
) {
1361 params
.add (parse_identifier ());
1362 } while (accept (TokenType
.COMMA
));
1364 expect (TokenType
.CLOSE_PARENS
);
1366 params
.add (parse_identifier ());
1368 expect (TokenType
.LAMBDA
);
1370 LambdaExpression lambda
;
1371 if (current () == TokenType
.OPEN_BRACE
) {
1372 var block
= parse_block ();
1373 lambda
= new LambdaExpression
.with_statement_body (block
, get_src (begin
));
1375 var expr
= parse_expression ();
1376 lambda
= new
LambdaExpression (expr
, get_src (begin
));
1378 foreach (string param
in params
) {
1379 lambda
.add_parameter (param
);
1384 AssignmentOperator
get_assignment_operator (TokenType token_type
) {
1385 switch (token_type
) {
1386 case TokenType
.ASSIGN
: return AssignmentOperator
.SIMPLE
;
1387 case TokenType
.ASSIGN_ADD
: return AssignmentOperator
.ADD
;
1388 case TokenType
.ASSIGN_SUB
: return AssignmentOperator
.SUB
;
1389 case TokenType
.ASSIGN_BITWISE_OR
: return AssignmentOperator
.BITWISE_OR
;
1390 case TokenType
.ASSIGN_BITWISE_AND
: return AssignmentOperator
.BITWISE_AND
;
1391 case TokenType
.ASSIGN_BITWISE_XOR
: return AssignmentOperator
.BITWISE_XOR
;
1392 case TokenType
.ASSIGN_DIV
: return AssignmentOperator
.DIV
;
1393 case TokenType
.ASSIGN_MUL
: return AssignmentOperator
.MUL
;
1394 case TokenType
.ASSIGN_PERCENT
: return AssignmentOperator
.PERCENT
;
1395 case TokenType
.ASSIGN_SHIFT_LEFT
: return AssignmentOperator
.SHIFT_LEFT
;
1396 default: return AssignmentOperator
.NONE
;
1400 Expression
parse_expression () throws ParseError
{
1401 var begin
= get_location ();
1402 Expression expr
= parse_conditional_expression ();
1404 if (current () == TokenType
.LAMBDA
) {
1406 var lambda
= parse_lambda_expression ();
1411 var operator
= get_assignment_operator (current ());
1412 if (operator
!= AssignmentOperator
.NONE
) {
1414 var rhs
= parse_expression ();
1415 expr
= new
Assignment (expr
, rhs
, operator
, get_src (begin
));
1416 } else if (current () == TokenType
.OP_GT
) { // >>=
1417 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1419 // only accept >>= when there is no space between the two > signs
1420 if (current () == TokenType
.OP_GE
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1422 var rhs
= parse_expression ();
1423 expr
= new
Assignment (expr
, rhs
, AssignmentOperator
.SHIFT_RIGHT
, get_src (begin
));
1436 void parse_statements (Block block
) throws ParseError
{
1437 while (current () != TokenType
.CLOSE_BRACE
1438 && current () != TokenType
.CASE
1439 && current () != TokenType
.DEFAULT
1440 && current () != TokenType
.EOF
) {
1442 Statement stmt
= null;
1443 bool is_decl
= false;
1445 comment
= scanner
.pop_comment ();
1446 switch (current ()) {
1447 case TokenType
.OPEN_BRACE
:
1448 stmt
= parse_block ();
1450 case TokenType
.SEMICOLON
:
1451 stmt
= parse_empty_statement ();
1454 stmt
= parse_if_statement ();
1456 case TokenType
.SWITCH
:
1457 stmt
= parse_switch_statement ();
1459 case TokenType
.WHILE
:
1460 stmt
= parse_while_statement ();
1463 stmt
= parse_do_statement ();
1466 stmt
= parse_for_statement ();
1468 case TokenType
.FOREACH
:
1469 stmt
= parse_foreach_statement ();
1471 case TokenType
.BREAK
:
1472 stmt
= parse_break_statement ();
1474 case TokenType
.CONTINUE
:
1475 stmt
= parse_continue_statement ();
1477 case TokenType
.RETURN
:
1478 stmt
= parse_return_statement ();
1480 case TokenType
.YIELD
:
1481 stmt
= parse_yield_statement ();
1483 case TokenType
.THROW
:
1484 stmt
= parse_throw_statement ();
1487 stmt
= parse_try_statement ();
1489 case TokenType
.LOCK
:
1490 stmt
= parse_lock_statement ();
1492 case TokenType
.DELETE
:
1493 stmt
= parse_delete_statement ();
1497 parse_local_variable_declarations (block
);
1499 case TokenType
.CONST
:
1501 parse_local_constant_declarations (block
);
1503 case TokenType
.OP_INC
:
1504 case TokenType
.OP_DEC
:
1505 case TokenType
.BASE
:
1506 case TokenType
.THIS
:
1507 case TokenType
.OPEN_PARENS
:
1508 case TokenType
.STAR
:
1510 stmt
= parse_expression_statement ();
1513 bool is_expr
= is_expression ();
1515 stmt
= parse_expression_statement ();
1518 parse_local_variable_declarations (block
);
1524 if (context
.profile
== Profile
.DOVA
&& stmt is ReturnStatement
) {
1530 var ret_stmt
= (ReturnStatement
) stmt
;
1531 if (ret_stmt
.return_expression
!= null) {
1532 var assignment
= new
Assignment (new MemberAccess
.simple ("result", stmt
.source_reference
), ret_stmt
.return_expression
, AssignmentOperator
.SIMPLE
, stmt
.source_reference
);
1533 ret_stmt
.return_expression
= null;
1534 block
.add_statement (new
ExpressionStatement (assignment
, stmt
.source_reference
));
1537 block
.add_statement (stmt
);
1539 } catch (ParseError e
) {
1540 if (recover () != RecoveryState
.STATEMENT_BEGIN
) {
1541 // beginning of next declaration or end of file reached
1542 // return what we have so far
1549 bool is_expression () throws ParseError
{
1550 var begin
= get_location ();
1552 // decide between declaration and expression statement
1554 switch (current ()) {
1555 // invocation expression
1556 case TokenType
.OPEN_PARENS
:
1557 // postfix increment
1558 case TokenType
.OP_INC
:
1559 // postfix decrement
1560 case TokenType
.OP_DEC
:
1562 case TokenType
.ASSIGN
:
1563 case TokenType
.ASSIGN_ADD
:
1564 case TokenType
.ASSIGN_BITWISE_AND
:
1565 case TokenType
.ASSIGN_BITWISE_OR
:
1566 case TokenType
.ASSIGN_BITWISE_XOR
:
1567 case TokenType
.ASSIGN_DIV
:
1568 case TokenType
.ASSIGN_MUL
:
1569 case TokenType
.ASSIGN_PERCENT
:
1570 case TokenType
.ASSIGN_SHIFT_LEFT
:
1571 case TokenType
.ASSIGN_SUB
:
1572 case TokenType
.OP_GT
: // >>=
1575 // pointer member access
1576 case TokenType
.OP_PTR
:
1585 Block
parse_embedded_statement () throws ParseError
{
1586 if (current () == TokenType
.OPEN_BRACE
) {
1587 var block
= parse_block ();
1591 comment
= scanner
.pop_comment ();
1593 var block
= new
Block (get_src (get_location ()));
1595 var stmt
= parse_embedded_statement_without_block ();
1596 if (context
.profile
== Profile
.DOVA
&& stmt is ReturnStatement
) {
1602 var ret_stmt
= (ReturnStatement
) stmt
;
1603 if (ret_stmt
.return_expression
!= null) {
1604 var assignment
= new
Assignment (new MemberAccess
.simple ("result"), ret_stmt
.return_expression
);
1605 ret_stmt
.return_expression
= null;
1606 block
.add_statement (new
ExpressionStatement (assignment
));
1609 block
.add_statement (stmt
);
1615 Statement
parse_embedded_statement_without_block () throws ParseError
{
1616 switch (current ()) {
1617 case TokenType
.SEMICOLON
: return parse_empty_statement ();
1618 case TokenType
.IF
: return parse_if_statement ();
1619 case TokenType
.SWITCH
: return parse_switch_statement ();
1620 case TokenType
.WHILE
: return parse_while_statement ();
1621 case TokenType
.DO
: return parse_do_statement ();
1622 case TokenType
.FOR
: return parse_for_statement ();
1623 case TokenType
.FOREACH
: return parse_foreach_statement ();
1624 case TokenType
.BREAK
: return parse_break_statement ();
1625 case TokenType
.CONTINUE
: return parse_continue_statement ();
1626 case TokenType
.RETURN
: return parse_return_statement ();
1627 case TokenType
.YIELD
: return parse_yield_statement ();
1628 case TokenType
.THROW
: return parse_throw_statement ();
1629 case TokenType
.TRY
: return parse_try_statement ();
1630 case TokenType
.LOCK
: return parse_lock_statement ();
1631 case TokenType
.DELETE
: return parse_delete_statement ();
1633 case TokenType
.CONST
:
1634 throw new ParseError
.SYNTAX (get_error ("embedded statement cannot be declaration "));
1635 case TokenType
.OP_INC
:
1636 case TokenType
.OP_DEC
:
1637 case TokenType
.BASE
:
1638 case TokenType
.THIS
:
1639 case TokenType
.OPEN_PARENS
:
1640 case TokenType
.STAR
:
1642 return parse_expression_statement ();
1644 if (is_expression ()) {
1645 return parse_expression_statement ();
1647 throw new ParseError
.SYNTAX (get_error ("embedded statement cannot be declaration"));
1652 Block
parse_block () throws ParseError
{
1653 var begin
= get_location ();
1654 expect (TokenType
.OPEN_BRACE
);
1655 var block
= new
Block (get_src (begin
));
1656 parse_statements (block
);
1657 if (!accept (TokenType
.CLOSE_BRACE
)) {
1658 // only report error if it's not a secondary error
1659 if (context
.report
.get_errors () == 0) {
1660 Report
.error (get_current_src (), "expected `}'");
1664 block
.source_reference
.last_line
= get_current_src ().last_line
;
1665 block
.source_reference
.last_column
= get_current_src ().last_column
;
1670 Statement
parse_empty_statement () throws ParseError
{
1671 var begin
= get_location ();
1672 expect (TokenType
.SEMICOLON
);
1673 return new
EmptyStatement (get_src (begin
));
1676 void parse_local_variable_declarations (Block block
) throws ParseError
{
1677 DataType variable_type
;
1678 if (accept (TokenType
.VAR
)) {
1679 variable_type
= null;
1681 variable_type
= parse_type (true, true);
1684 if (variable_type
== null && accept (TokenType
.OPEN_PARENS
)) {
1686 var begin
= get_location ();
1688 string[] identifiers
= {};
1690 identifiers
+= parse_identifier ();
1691 } while (accept (TokenType
.COMMA
));
1692 expect (TokenType
.CLOSE_PARENS
);
1694 expect (TokenType
.ASSIGN
);
1695 var tuple
= parse_expression ();
1696 var tuple_local
= new
LocalVariable (null, CodeNode
.get_temp_name (), tuple
, get_src (begin
));
1697 block
.add_statement (new
DeclarationStatement (tuple_local
, tuple_local
.source_reference
));
1699 for (int i
= 0; i
< identifiers
.length
; i
++) {
1700 var temp_access
= new MemberAccess
.simple (tuple_local
.name
, tuple_local
.source_reference
);
1701 var ea
= new
ElementAccess (temp_access
, tuple_local
.source_reference
);
1702 ea
.append_index (new
IntegerLiteral (i
.to_string ()));
1703 var local
= new
LocalVariable (null, identifiers
[i
], ea
, tuple_local
.source_reference
);
1704 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1710 DataType type_copy
= null;
1711 if (variable_type
!= null) {
1712 type_copy
= variable_type
.copy ();
1714 var local
= parse_local_variable (type_copy
);
1715 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1716 } while (accept (TokenType
.COMMA
));
1717 expect (TokenType
.SEMICOLON
);
1720 LocalVariable
parse_local_variable (DataType? variable_type
) throws ParseError
{
1721 var begin
= get_location ();
1722 string id
= parse_identifier ();
1724 var type
= parse_inline_array_type (variable_type
);
1726 Expression initializer
= null;
1727 if (accept (TokenType
.ASSIGN
)) {
1728 initializer
= parse_expression ();
1730 return new
LocalVariable (type
, id
, initializer
, get_src (begin
));
1733 void parse_local_constant_declarations (Block block
) throws ParseError
{
1734 expect (TokenType
.CONST
);
1735 var constant_type
= parse_type (false, false);
1737 DataType type_copy
= constant_type
.copy ();
1738 var local
= parse_local_constant (type_copy
);
1739 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1740 block
.add_local_constant (local
);
1741 local
.active
= false;
1742 } while (accept (TokenType
.COMMA
));
1743 expect (TokenType
.SEMICOLON
);
1746 Constant
parse_local_constant (DataType constant_type
) throws ParseError
{
1747 var begin
= get_location ();
1748 string id
= parse_identifier ();
1750 var type
= parse_inline_array_type (constant_type
);
1752 expect (TokenType
.ASSIGN
);
1753 var initializer
= parse_expression ();
1755 return new
Constant (id
, type
, initializer
, get_src (begin
));
1758 Statement
parse_expression_statement () throws ParseError
{
1759 var begin
= get_location ();
1760 var expr
= parse_statement_expression ();
1761 expect (TokenType
.SEMICOLON
);
1762 return new
ExpressionStatement (expr
, get_src (begin
));
1765 Expression
parse_statement_expression () throws ParseError
{
1766 // invocation expression, assignment,
1767 // or pre/post increment/decrement expression
1768 var expr
= parse_expression ();
1772 Statement
parse_if_statement () throws ParseError
{
1773 var begin
= get_location ();
1774 expect (TokenType
.IF
);
1775 expect (TokenType
.OPEN_PARENS
);
1776 var condition
= parse_expression ();
1777 expect (TokenType
.CLOSE_PARENS
);
1778 var src
= get_src (begin
);
1779 var true_stmt
= parse_embedded_statement ();
1780 Block false_stmt
= null;
1781 if (accept (TokenType
.ELSE
)) {
1782 false_stmt
= parse_embedded_statement ();
1784 return new
IfStatement (condition
, true_stmt
, false_stmt
, src
);
1787 Statement
parse_switch_statement () throws ParseError
{
1788 var begin
= get_location ();
1789 expect (TokenType
.SWITCH
);
1790 expect (TokenType
.OPEN_PARENS
);
1791 var condition
= parse_expression ();
1792 expect (TokenType
.CLOSE_PARENS
);
1793 var stmt
= new
SwitchStatement (condition
, get_src (begin
));
1794 expect (TokenType
.OPEN_BRACE
);
1795 while (current () != TokenType
.CLOSE_BRACE
) {
1796 var section
= new
SwitchSection (get_src (begin
));
1798 if (accept (TokenType
.CASE
)) {
1799 section
.add_label (new
SwitchLabel (parse_expression (), get_src (begin
)));
1801 expect (TokenType
.DEFAULT
);
1802 section
.add_label (new SwitchLabel
.with_default (get_src (begin
)));
1804 expect (TokenType
.COLON
);
1805 } while (current () == TokenType
.CASE
|| current () == TokenType
.DEFAULT
);
1806 parse_statements (section
);
1807 stmt
.add_section (section
);
1809 expect (TokenType
.CLOSE_BRACE
);
1813 Statement
parse_while_statement () throws ParseError
{
1814 var begin
= get_location ();
1815 expect (TokenType
.WHILE
);
1816 expect (TokenType
.OPEN_PARENS
);
1817 var condition
= parse_expression ();
1818 expect (TokenType
.CLOSE_PARENS
);
1819 var body
= parse_embedded_statement ();
1820 return new
WhileStatement (condition
, body
, get_src (begin
));
1823 Statement
parse_do_statement () throws ParseError
{
1824 var begin
= get_location ();
1825 expect (TokenType
.DO
);
1826 var body
= parse_embedded_statement ();
1827 expect (TokenType
.WHILE
);
1828 expect (TokenType
.OPEN_PARENS
);
1829 var condition
= parse_expression ();
1830 expect (TokenType
.CLOSE_PARENS
);
1831 expect (TokenType
.SEMICOLON
);
1832 return new
DoStatement (body
, condition
, get_src (begin
));
1835 Statement
parse_for_statement () throws ParseError
{
1836 var begin
= get_location ();
1838 expect (TokenType
.FOR
);
1839 expect (TokenType
.OPEN_PARENS
);
1840 var initializer_list
= new ArrayList
<Expression
> ();
1841 if (!accept (TokenType
.SEMICOLON
)) {
1843 switch (current ()) {
1847 case TokenType
.OP_INC
:
1848 case TokenType
.OP_DEC
:
1852 is_expr
= is_expression ();
1858 initializer_list
.add (parse_statement_expression ());
1859 } while (accept (TokenType
.COMMA
));
1860 expect (TokenType
.SEMICOLON
);
1862 // variable declaration in initializer
1863 block
= new
Block (get_src (begin
));
1864 parse_local_variable_declarations (block
);
1867 Expression condition
= null;
1868 if (current () != TokenType
.SEMICOLON
) {
1869 condition
= parse_expression ();
1871 expect (TokenType
.SEMICOLON
);
1872 var iterator_list
= new ArrayList
<Expression
> ();
1873 if (current () != TokenType
.CLOSE_PARENS
) {
1875 iterator_list
.add (parse_statement_expression ());
1876 } while (accept (TokenType
.COMMA
));
1878 expect (TokenType
.CLOSE_PARENS
);
1879 var src
= get_src (begin
);
1880 var body
= parse_embedded_statement ();
1881 var stmt
= new
ForStatement (condition
, body
, src
);
1882 foreach (Expression init
in initializer_list
) {
1883 stmt
.add_initializer (init
);
1885 foreach (Expression iter
in iterator_list
) {
1886 stmt
.add_iterator (iter
);
1888 if (block
!= null) {
1889 block
.add_statement (stmt
);
1896 Statement
parse_foreach_statement () throws ParseError
{
1897 var begin
= get_location ();
1898 expect (TokenType
.FOREACH
);
1899 expect (TokenType
.OPEN_PARENS
);
1900 DataType type
= null;
1901 if (!accept (TokenType
.VAR
)) {
1902 type
= parse_type (true, true);
1903 if (accept (TokenType
.IN
)) {
1904 Report
.error (type
.source_reference
, "syntax error, expected var or type");
1905 throw new ParseError
.SYNTAX ("expected var or type");
1908 string id
= parse_identifier ();
1909 expect (TokenType
.IN
);
1910 var collection
= parse_expression ();
1911 expect (TokenType
.CLOSE_PARENS
);
1912 var src
= get_src (begin
);
1913 var body
= parse_embedded_statement ();
1914 return new
ForeachStatement (type
, id
, collection
, body
, src
);
1917 Statement
parse_break_statement () throws ParseError
{
1918 var begin
= get_location ();
1919 expect (TokenType
.BREAK
);
1920 expect (TokenType
.SEMICOLON
);
1921 return new
BreakStatement (get_src (begin
));
1924 Statement
parse_continue_statement () throws ParseError
{
1925 var begin
= get_location ();
1926 expect (TokenType
.CONTINUE
);
1927 expect (TokenType
.SEMICOLON
);
1928 return new
ContinueStatement (get_src (begin
));
1931 Statement
parse_return_statement () throws ParseError
{
1932 var begin
= get_location ();
1933 expect (TokenType
.RETURN
);
1934 Expression expr
= null;
1935 if (current () != TokenType
.SEMICOLON
) {
1936 expr
= parse_expression ();
1938 expect (TokenType
.SEMICOLON
);
1939 return new
ReturnStatement (expr
, get_src (begin
));
1942 Statement
parse_yield_statement () throws ParseError
{
1943 var begin
= get_location ();
1944 expect (TokenType
.YIELD
);
1945 if (current () != TokenType
.SEMICOLON
&& current () != TokenType
.RETURN
) {
1948 return parse_expression_statement ();
1950 Expression expr
= null;
1951 if (accept (TokenType
.RETURN
)) {
1952 expr
= parse_expression ();
1954 expect (TokenType
.SEMICOLON
);
1955 return new
YieldStatement (expr
, get_src (begin
));
1958 Statement
parse_throw_statement () throws ParseError
{
1959 var begin
= get_location ();
1960 expect (TokenType
.THROW
);
1961 var expr
= parse_expression ();
1962 expect (TokenType
.SEMICOLON
);
1963 return new
ThrowStatement (expr
, get_src (begin
));
1966 Statement
parse_try_statement () throws ParseError
{
1967 var begin
= get_location ();
1968 expect (TokenType
.TRY
);
1969 var try_block
= parse_block ();
1970 Block finally_clause
= null;
1971 var catch_clauses
= new ArrayList
<CatchClause
> ();
1972 if (current () == TokenType
.CATCH
) {
1973 parse_catch_clauses (catch_clauses
);
1974 if (current () == TokenType
.FINALLY
) {
1975 finally_clause
= parse_finally_clause ();
1978 finally_clause
= parse_finally_clause ();
1980 var stmt
= new
TryStatement (try_block
, finally_clause
, get_src (begin
));
1981 foreach (CatchClause clause
in catch_clauses
) {
1982 stmt
.add_catch_clause (clause
);
1987 void parse_catch_clauses (List
<CatchClause
> catch_clauses
) throws ParseError
{
1988 while (accept (TokenType
.CATCH
)) {
1989 var begin
= get_location ();
1990 DataType type
= null;
1992 if (accept (TokenType
.OPEN_PARENS
)) {
1993 type
= parse_type (true, true);
1994 id
= parse_identifier ();
1995 expect (TokenType
.CLOSE_PARENS
);
1997 var block
= parse_block ();
1998 catch_clauses
.add (new
CatchClause (type
, id
, block
, get_src (begin
)));
2002 Block
parse_finally_clause () throws ParseError
{
2003 expect (TokenType
.FINALLY
);
2004 var block
= parse_block ();
2008 Statement
parse_lock_statement () throws ParseError
{
2009 var begin
= get_location ();
2010 expect (TokenType
.LOCK
);
2011 expect (TokenType
.OPEN_PARENS
);
2012 var expr
= parse_expression ();
2013 expect (TokenType
.CLOSE_PARENS
);
2014 var stmt
= parse_embedded_statement ();
2015 return new
LockStatement (expr
, stmt
, get_src (begin
));
2018 Statement
parse_delete_statement () throws ParseError
{
2019 var begin
= get_location ();
2020 expect (TokenType
.DELETE
);
2021 var expr
= parse_expression ();
2022 expect (TokenType
.SEMICOLON
);
2023 return new
DeleteStatement (expr
, get_src (begin
));
2026 string parse_attribute_value () throws ParseError
{
2027 switch (current ()) {
2028 case TokenType
.NULL
:
2029 case TokenType
.TRUE
:
2030 case TokenType
.FALSE
:
2031 case TokenType
.INTEGER_LITERAL
:
2032 case TokenType
.REAL_LITERAL
:
2033 case TokenType
.STRING_LITERAL
:
2035 return get_last_string ();
2036 case TokenType
.MINUS
:
2038 switch (current ()) {
2039 case TokenType
.INTEGER_LITERAL
:
2040 case TokenType
.REAL_LITERAL
:
2042 return "-" + get_last_string ();
2044 throw new ParseError
.SYNTAX (get_error ("expected number"));
2047 throw new ParseError
.SYNTAX (get_error ("expected literal"));
2051 List
<Attribute
>?
parse_attributes () throws ParseError
{
2052 if (current () != TokenType
.OPEN_BRACKET
) {
2055 var attrs
= new ArrayList
<Attribute
> ();
2056 while (accept (TokenType
.OPEN_BRACKET
)) {
2058 var begin
= get_location ();
2059 string id
= parse_identifier ();
2060 var attr
= new
Attribute (id
, get_src (begin
));
2061 if (accept (TokenType
.OPEN_PARENS
)) {
2062 if (current () != TokenType
.CLOSE_PARENS
) {
2064 id
= parse_identifier ();
2065 expect (TokenType
.ASSIGN
);
2066 attr
.add_argument (id
, parse_attribute_value ());
2067 } while (accept (TokenType
.COMMA
));
2069 expect (TokenType
.CLOSE_PARENS
);
2072 } while (accept (TokenType
.COMMA
));
2073 expect (TokenType
.CLOSE_BRACKET
);
2078 void set_attributes (CodeNode node
, List
<Attribute
>? attributes
) {
2079 if (attributes
!= null) {
2080 foreach (Attribute attr
in (List
<Attribute
>) attributes
) {
2081 node
.attributes
.append (attr
);
2086 void parse_main_block (Symbol parent
) throws ParseError
{
2087 var begin
= get_location ();
2089 var method
= new
Method ("main", new
VoidType (), get_src (begin
));
2090 method
.body
= new
Block (get_src (begin
));
2091 parse_statements (method
.body
);
2092 if (current () != TokenType
.EOF
) {
2093 Report
.error (get_current_src (), "expected end of file");
2096 method
.body
.source_reference
.last_line
= get_current_src ().last_line
;
2097 method
.body
.source_reference
.last_column
= get_current_src ().last_column
;
2099 if (!context
.experimental
&& context
.profile
!= Profile
.DOVA
) {
2100 Report
.warning (method
.source_reference
, "main blocks are experimental");
2103 parent
.add_method (method
);
2106 void parse_declaration (Symbol parent
, bool root
= false) throws ParseError
{
2107 comment
= scanner
.pop_comment ();
2108 var attrs
= parse_attributes ();
2110 var begin
= get_location ();
2112 TokenType last_keyword
= current ();
2114 while (is_declaration_keyword (current ())) {
2115 last_keyword
= current ();
2119 switch (current ()) {
2120 case TokenType
.CONSTRUCT
:
2121 if (context
.profile
== Profile
.GOBJECT
) {
2123 parse_constructor_declaration (parent
, attrs
);
2127 case TokenType
.TILDE
:
2129 parse_destructor_declaration (parent
, attrs
);
2131 case TokenType
.OPEN_BRACE
:
2132 case TokenType
.SEMICOLON
:
2134 case TokenType
.SWITCH
:
2135 case TokenType
.WHILE
:
2138 case TokenType
.FOREACH
:
2139 case TokenType
.BREAK
:
2140 case TokenType
.CONTINUE
:
2141 case TokenType
.RETURN
:
2142 case TokenType
.YIELD
:
2143 case TokenType
.THROW
:
2145 case TokenType
.LOCK
:
2146 case TokenType
.DELETE
:
2148 case TokenType
.OP_INC
:
2149 case TokenType
.OP_DEC
:
2150 case TokenType
.BASE
:
2151 case TokenType
.THIS
:
2152 case TokenType
.OPEN_PARENS
:
2153 case TokenType
.STAR
:
2156 if (attrs
!= null) {
2157 // no attributes allowed before statements
2158 throw new ParseError
.SYNTAX (get_error ("expected statement"));
2161 throw new ParseError
.SYNTAX (get_error ("statements outside blocks allowed only in root namespace"));
2164 parse_main_block (parent
);
2168 bool is_expr
= is_expression ();
2171 parse_main_block (parent
);
2177 switch (current ()) {
2178 case TokenType
.OPEN_BRACE
:
2179 case TokenType
.SEMICOLON
:
2180 case TokenType
.COLON
:
2182 switch (last_keyword
) {
2183 case TokenType
.CLASS
:
2184 parse_class_declaration (parent
, attrs
);
2186 case TokenType
.ENUM
:
2187 parse_enum_declaration (parent
, attrs
);
2189 case TokenType
.ERRORDOMAIN
:
2190 parse_errordomain_declaration (parent
, attrs
);
2192 case TokenType
.INTERFACE
:
2193 parse_interface_declaration (parent
, attrs
);
2195 case TokenType
.NAMESPACE
:
2196 parse_namespace_declaration (parent
, attrs
);
2198 case TokenType
.STRUCT
:
2199 parse_struct_declaration (parent
, attrs
);
2205 case TokenType
.OPEN_PARENS
:
2207 parse_creation_method_declaration (parent
, attrs
);
2210 skip_type (); // might contain type parameter list
2211 switch (current ()) {
2212 case TokenType
.OPEN_PARENS
:
2214 switch (last_keyword
) {
2215 case TokenType
.DELEGATE
:
2216 parse_delegate_declaration (parent
, attrs
);
2218 case TokenType
.SIGNAL
:
2219 parse_signal_declaration (parent
, attrs
);
2222 parse_method_declaration (parent
, attrs
);
2225 case TokenType
.ASSIGN
:
2226 case TokenType
.SEMICOLON
:
2228 switch (last_keyword
) {
2229 case TokenType
.CONST
:
2230 parse_constant_declaration (parent
, attrs
);
2233 parse_field_declaration (parent
, attrs
);
2236 case TokenType
.OPEN_BRACE
:
2237 case TokenType
.THROWS
:
2239 parse_property_declaration (parent
, attrs
);
2251 throw new ParseError
.SYNTAX (get_error ("expected declaration"));
2254 void parse_declarations (Symbol parent
, bool root
= false) throws ParseError
{
2256 expect (TokenType
.OPEN_BRACE
);
2258 while (current () != TokenType
.CLOSE_BRACE
&& current () != TokenType
.EOF
) {
2260 parse_declaration (parent
, (parent
== context
.root
));
2261 } catch (ParseError e
) {
2265 if (r
== RecoveryState
.STATEMENT_BEGIN
) {
2271 if (r
== RecoveryState
.EOF
) {
2277 if (!accept (TokenType
.CLOSE_BRACE
)) {
2278 // only report error if it's not a secondary error
2279 if (context
.report
.get_errors () == 0) {
2280 Report
.error (get_current_src (), "expected `}'");
2286 enum RecoveryState
{
2292 RecoveryState
recover () {
2293 while (current () != TokenType
.EOF
) {
2294 switch (current ()) {
2295 case TokenType
.ABSTRACT
:
2296 case TokenType
.CLASS
:
2297 case TokenType
.CONST
:
2298 case TokenType
.CONSTRUCT
:
2299 case TokenType
.DELEGATE
:
2300 case TokenType
.ENUM
:
2301 case TokenType
.ERRORDOMAIN
:
2302 case TokenType
.EXTERN
:
2303 case TokenType
.INLINE
:
2304 case TokenType
.INTERFACE
:
2305 case TokenType
.INTERNAL
:
2306 case TokenType
.NAMESPACE
:
2308 case TokenType
.OVERRIDE
:
2309 case TokenType
.PRIVATE
:
2310 case TokenType
.PROTECTED
:
2311 case TokenType
.PUBLIC
:
2312 case TokenType
.SEALED
:
2313 case TokenType
.SIGNAL
:
2314 case TokenType
.STATIC
:
2315 case TokenType
.STRUCT
:
2316 case TokenType
.VIRTUAL
:
2317 case TokenType
.VOLATILE
:
2318 return RecoveryState
.DECLARATION_BEGIN
;
2319 case TokenType
.BREAK
:
2320 case TokenType
.CONTINUE
:
2321 case TokenType
.DELETE
:
2324 case TokenType
.FOREACH
:
2326 case TokenType
.LOCK
:
2327 case TokenType
.RETURN
:
2328 case TokenType
.SWITCH
:
2329 case TokenType
.THROW
:
2332 case TokenType
.WHILE
:
2333 case TokenType
.YIELD
:
2334 return RecoveryState
.STATEMENT_BEGIN
;
2340 return RecoveryState
.EOF
;
2343 void parse_namespace_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2344 var begin
= get_location ();
2345 expect (TokenType
.NAMESPACE
);
2346 var sym
= parse_symbol_name ();
2347 var ns
= new
Namespace (sym
.name
, get_src (begin
));
2348 if (comment
!= null) {
2349 ns
.add_comment (comment
);
2353 set_attributes (ns
, attrs
);
2355 expect (TokenType
.OPEN_BRACE
);
2357 var old_using_directives
= scanner
.source_file
.current_using_directives
;
2358 parse_using_directives (ns
);
2360 parse_declarations (ns
, true);
2362 scanner
.source_file
.current_using_directives
= old_using_directives
;
2364 if (!accept (TokenType
.CLOSE_BRACE
)) {
2365 // only report error if it's not a secondary error
2366 if (context
.report
.get_errors () == 0) {
2367 Report
.error (get_current_src (), "expected `}'");
2372 while (sym
!= null) {
2375 Symbol next
= (sym
!= null ? new
Namespace (sym
.name
, ns
.source_reference
) : parent
);
2376 next
.add_namespace ((Namespace
) result
);
2381 void parse_using_directives (Namespace ns
) throws ParseError
{
2382 while (accept (TokenType
.USING
)) {
2384 var begin
= get_location ();
2385 var sym
= parse_symbol_name ();
2386 var ns_ref
= new
UsingDirective (sym
, get_src (begin
));
2387 scanner
.source_file
.add_using_directive (ns_ref
);
2388 ns
.add_using_directive (ns_ref
);
2389 } while (accept (TokenType
.COMMA
));
2390 expect (TokenType
.SEMICOLON
);
2394 void parse_class_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2395 var begin
= get_location ();
2396 var access
= parse_access_modifier ();
2397 var flags
= parse_type_declaration_modifiers ();
2398 expect (TokenType
.CLASS
);
2399 var sym
= parse_symbol_name ();
2400 var type_param_list
= parse_type_parameter_list ();
2401 var base_types
= new ArrayList
<DataType
> ();
2402 if (accept (TokenType
.COLON
)) {
2404 base_types
.add (parse_type (true, false));
2405 } while (accept (TokenType
.COMMA
));
2408 var cl
= new
Class (sym
.name
, get_src (begin
), comment
);
2410 if (ModifierFlags
.ABSTRACT
in flags
) {
2411 cl
.is_abstract
= true;
2413 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2416 set_attributes (cl
, attrs
);
2417 foreach (TypeParameter type_param
in type_param_list
) {
2418 cl
.add_type_parameter (type_param
);
2420 foreach (DataType base_type
in base_types
) {
2421 cl
.add_base_type (base_type
);
2424 parse_declarations (cl
);
2426 // ensure there is always a default construction method
2427 if (scanner
.source_file
.file_type
== SourceFileType
.SOURCE
2428 && cl
.default_construction_method
== null) {
2429 var m
= new
CreationMethod (cl
.name
, null, cl
.source_reference
);
2430 m
.access
= SymbolAccessibility
.PUBLIC
;
2431 m
.body
= new
Block (cl
.source_reference
);
2436 while (sym
!= null) {
2439 Symbol next
= (sym
!= null ? new
Namespace (sym
.name
, cl
.source_reference
) : parent
);
2440 if (result is Namespace
) {
2441 next
.add_namespace ((Namespace
) result
);
2443 next
.add_class ((Class
) result
);
2449 void parse_constant_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2450 var begin
= get_location ();
2451 var access
= parse_access_modifier ();
2452 var flags
= parse_member_declaration_modifiers ();
2453 expect (TokenType
.CONST
);
2454 var type
= parse_type (false, false);
2455 string id
= parse_identifier ();
2457 type
= parse_inline_array_type (type
);
2459 Expression initializer
= null;
2460 if (accept (TokenType
.ASSIGN
)) {
2461 initializer
= parse_expression ();
2463 expect (TokenType
.SEMICOLON
);
2465 // constant arrays don't own their element
2466 var array_type
= type as ArrayType
;
2467 if (array_type
!= null) {
2468 array_type
.element_type
.value_owned
= false;
2471 var c
= new
Constant (id
, type
, initializer
, get_src (begin
), comment
);
2473 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2476 if (ModifierFlags
.NEW
in flags
) {
2479 set_attributes (c
, attrs
);
2481 parent
.add_constant (c
);
2484 void parse_field_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2485 var begin
= get_location ();
2486 var access
= parse_access_modifier ();
2487 var flags
= parse_member_declaration_modifiers ();
2488 if (context
.profile
== Profile
.DOVA
) {
2489 accept (TokenType
.VOLATILE
);
2491 var type
= parse_type (true, true);
2492 string id
= parse_identifier ();
2494 type
= parse_inline_array_type (type
);
2496 var f
= new
Field (id
, type
, null, get_src (begin
), comment
);
2498 set_attributes (f
, attrs
);
2499 if (ModifierFlags
.STATIC
in flags
) {
2500 f
.binding
= MemberBinding
.STATIC
;
2501 } else if (ModifierFlags
.CLASS
in flags
) {
2502 f
.binding
= MemberBinding
.CLASS
;
2504 if (ModifierFlags
.ABSTRACT
in flags
2505 || ModifierFlags
.VIRTUAL
in flags
2506 || ModifierFlags
.OVERRIDE
in flags
) {
2507 Report
.error (f
.source_reference
, "abstract, virtual, and override modifiers are not applicable to fields");
2509 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2512 if (ModifierFlags
.NEW
in flags
) {
2515 if (accept (TokenType
.ASSIGN
)) {
2516 f
.initializer
= parse_expression ();
2518 expect (TokenType
.SEMICOLON
);
2520 parent
.add_field (f
);
2523 InitializerList
parse_initializer () throws ParseError
{
2524 var begin
= get_location ();
2525 expect (TokenType
.OPEN_BRACE
);
2526 var initializer
= new
InitializerList (get_src (begin
));
2527 if (current () != TokenType
.CLOSE_BRACE
) {
2529 var init
= parse_argument ();
2530 initializer
.append (init
);
2531 } while (accept (TokenType
.COMMA
));
2533 expect (TokenType
.CLOSE_BRACE
);
2537 ListLiteral
parse_list_literal () throws ParseError
{
2538 var begin
= get_location ();
2539 expect (TokenType
.OPEN_BRACKET
);
2540 var initializer
= new
ListLiteral (get_src (begin
));
2541 if (current () != TokenType
.CLOSE_BRACKET
) {
2543 var init
= parse_expression ();
2544 initializer
.add_expression (init
);
2545 } while (accept (TokenType
.COMMA
));
2547 expect (TokenType
.CLOSE_BRACKET
);
2551 Expression
parse_set_literal () throws ParseError
{
2552 var begin
= get_location ();
2553 expect (TokenType
.OPEN_BRACE
);
2554 var set = new
SetLiteral (get_src (begin
));
2556 if (current () != TokenType
.CLOSE_BRACE
) {
2558 var expr
= parse_expression ();
2559 if (first
&& accept (TokenType
.COLON
)) {
2560 // found colon after expression, it's a map
2562 return parse_map_literal ();
2565 set.add_expression (expr
);
2566 } while (accept (TokenType
.COMMA
));
2568 expect (TokenType
.CLOSE_BRACE
);
2572 Expression
parse_map_literal () throws ParseError
{
2573 var begin
= get_location ();
2574 expect (TokenType
.OPEN_BRACE
);
2575 var map
= new
MapLiteral (get_src (begin
));
2576 if (current () != TokenType
.CLOSE_BRACE
) {
2578 var key
= parse_expression ();
2580 expect (TokenType
.COLON
);
2581 var value
= parse_expression ();
2582 map
.add_value (value
);
2583 } while (accept (TokenType
.COMMA
));
2585 expect (TokenType
.CLOSE_BRACE
);
2589 void parse_method_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2590 var begin
= get_location ();
2591 var access
= parse_access_modifier ();
2592 var flags
= parse_member_declaration_modifiers ();
2593 var type
= parse_type (true, false);
2594 string id
= parse_identifier ();
2595 var type_param_list
= parse_type_parameter_list ();
2596 var method
= new
Method (id
, type
, get_src (begin
), comment
);
2597 method
.access
= access
;
2598 set_attributes (method
, attrs
);
2599 foreach (TypeParameter type_param
in type_param_list
) {
2600 method
.add_type_parameter (type_param
);
2602 if (ModifierFlags
.STATIC
in flags
) {
2603 method
.binding
= MemberBinding
.STATIC
;
2604 } else if (ModifierFlags
.CLASS
in flags
) {
2605 method
.binding
= MemberBinding
.CLASS
;
2607 if (ModifierFlags
.ASYNC
in flags
) {
2608 method
.coroutine
= true;
2610 if (ModifierFlags
.NEW
in flags
) {
2611 method
.hides
= true;
2614 if (method
.binding
== MemberBinding
.INSTANCE
) {
2615 if (ModifierFlags
.ABSTRACT
in flags
) {
2616 method
.is_abstract
= true;
2618 if (ModifierFlags
.VIRTUAL
in flags
) {
2619 method
.is_virtual
= true;
2621 if (ModifierFlags
.OVERRIDE
in flags
) {
2622 method
.overrides
= true;
2624 if ((method
.is_abstract
&& method
.is_virtual
)
2625 || (method
.is_abstract
&& method
.overrides
)
2626 || (method
.is_virtual
&& method
.overrides
)) {
2627 throw new ParseError
.SYNTAX (get_error ("only one of `abstract', `virtual', or `override' may be specified"));
2630 if (ModifierFlags
.ABSTRACT
in flags
2631 || ModifierFlags
.VIRTUAL
in flags
2632 || ModifierFlags
.OVERRIDE
in flags
) {
2633 throw new ParseError
.SYNTAX (get_error ("the modifiers `abstract', `virtual', and `override' are not valid for static methods"));
2637 if (ModifierFlags
.INLINE
in flags
) {
2638 method
.is_inline
= true;
2640 if (ModifierFlags
.EXTERN
in flags
) {
2641 method
.external
= true;
2643 expect (TokenType
.OPEN_PARENS
);
2644 if (current () != TokenType
.CLOSE_PARENS
) {
2646 var param
= parse_parameter ();
2647 method
.add_parameter (param
);
2648 } while (accept (TokenType
.COMMA
));
2650 expect (TokenType
.CLOSE_PARENS
);
2651 if (context
.profile
== Profile
.DOVA
) {
2652 var error_type
= new UnresolvedType
.from_symbol (new
UnresolvedSymbol (new
UnresolvedSymbol (null, "Dova"), "Error"), method
.source_reference
);
2653 method
.add_error_type (error_type
);
2654 if (accept (TokenType
.THROWS
)) {
2656 parse_type (true, false);
2657 } while (accept (TokenType
.COMMA
));
2658 Report
.warning (method
.source_reference
, "`throws' is ignored in the Dova profile");
2661 if (accept (TokenType
.THROWS
)) {
2663 method
.add_error_type (parse_type (true, false));
2664 } while (accept (TokenType
.COMMA
));
2667 while (accept (TokenType
.REQUIRES
)) {
2668 expect (TokenType
.OPEN_PARENS
);
2669 method
.add_precondition (parse_expression ());
2670 expect (TokenType
.CLOSE_PARENS
);
2672 while (accept (TokenType
.ENSURES
)) {
2673 expect (TokenType
.OPEN_PARENS
);
2674 method
.add_postcondition (parse_expression ());
2675 expect (TokenType
.CLOSE_PARENS
);
2677 if (!accept (TokenType
.SEMICOLON
)) {
2678 method
.body
= parse_block ();
2679 } else if (scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2680 method
.external
= true;
2683 parent
.add_method (method
);
2686 void parse_property_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2687 var begin
= get_location ();
2688 var access
= parse_access_modifier ();
2689 var flags
= parse_member_declaration_modifiers ();
2690 var type
= parse_type (true, true);
2692 bool getter_owned
= false;
2693 if (context
.profile
== Profile
.DOVA
) {
2694 getter_owned
= true;
2695 } else if (accept (TokenType
.HASH
)) {
2696 if (!context
.deprecated
) {
2697 Report
.warning (get_last_src (), "deprecated syntax, use `owned` modifier before `get'");
2699 getter_owned
= true;
2702 string id
= parse_identifier ();
2703 var prop
= new
Property (id
, type
, null, null, get_src (begin
), comment
);
2704 prop
.access
= access
;
2705 set_attributes (prop
, attrs
);
2706 if (ModifierFlags
.STATIC
in flags
) {
2707 prop
.binding
= MemberBinding
.STATIC
;
2708 } else if (ModifierFlags
.CLASS
in flags
) {
2709 prop
.binding
= MemberBinding
.CLASS
;
2711 if (ModifierFlags
.ABSTRACT
in flags
) {
2712 prop
.is_abstract
= true;
2714 if (ModifierFlags
.VIRTUAL
in flags
) {
2715 prop
.is_virtual
= true;
2717 if (ModifierFlags
.OVERRIDE
in flags
) {
2718 prop
.overrides
= true;
2720 if (ModifierFlags
.NEW
in flags
) {
2723 if (ModifierFlags
.ASYNC
in flags
) {
2724 Report
.error (prop
.source_reference
, "async properties are not supported yet");
2726 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2727 prop
.external
= true;
2729 if (context
.profile
== Profile
.DOVA
) {
2731 if (accept (TokenType
.THROWS
)) {
2733 prop
.add_error_type (parse_type (true, false));
2734 } while (accept (TokenType
.COMMA
));
2735 Report
.error (prop
.source_reference
, "properties throwing errors are not supported yet");
2738 expect (TokenType
.OPEN_BRACE
);
2739 while (current () != TokenType
.CLOSE_BRACE
) {
2740 if (accept (TokenType
.DEFAULT
)) {
2741 if (prop
.initializer
!= null) {
2742 throw new ParseError
.SYNTAX (get_error ("property default value already defined"));
2744 expect (TokenType
.ASSIGN
);
2745 prop
.initializer
= parse_expression ();
2746 expect (TokenType
.SEMICOLON
);
2748 comment
= scanner
.pop_comment ();
2750 var accessor_begin
= get_location ();
2751 var accessor_attrs
= parse_attributes ();
2752 var accessor_access
= parse_access_modifier (SymbolAccessibility
.PUBLIC
);
2754 var value_type
= type
.copy ();
2755 value_type
.value_owned
= (context
.profile
!= Profile
.DOVA
&& accept (TokenType
.OWNED
));
2757 if (accept (TokenType
.GET
)) {
2758 if (prop
.get_accessor
!= null) {
2759 throw new ParseError
.SYNTAX (get_error ("property get accessor already defined"));
2763 value_type
.value_owned
= true;
2767 if (!accept (TokenType
.SEMICOLON
)) {
2768 block
= parse_block ();
2769 prop
.external
= false;
2771 prop
.get_accessor
= new
PropertyAccessor (true, false, false, value_type
, block
, get_src (accessor_begin
), comment
);
2772 set_attributes (prop
.get_accessor
, accessor_attrs
);
2773 prop
.get_accessor
.access
= accessor_access
;
2775 bool writable
, _construct
;
2776 if (accept (TokenType
.SET
)) {
2778 _construct
= (context
.profile
== Profile
.GOBJECT
) && accept (TokenType
.CONSTRUCT
);
2779 } else if (context
.profile
== Profile
.GOBJECT
&& accept (TokenType
.CONSTRUCT
)) {
2781 writable
= accept (TokenType
.SET
);
2783 throw new ParseError
.SYNTAX (get_error ("expected get, set, or construct"));
2785 if (prop
.set_accessor
!= null) {
2786 throw new ParseError
.SYNTAX (get_error ("property set accessor already defined"));
2789 if (!accept (TokenType
.SEMICOLON
)) {
2790 block
= parse_block ();
2791 prop
.external
= false;
2793 prop
.set_accessor
= new
PropertyAccessor (false, writable
, _construct
, value_type
, block
, get_src (accessor_begin
), comment
);
2794 set_attributes (prop
.set_accessor
, accessor_attrs
);
2795 prop
.set_accessor
.access
= accessor_access
;
2799 expect (TokenType
.CLOSE_BRACE
);
2801 if (!prop
.is_abstract
&& prop
.source_type
== SourceFileType
.SOURCE
) {
2802 bool empty_get
= (prop
.get_accessor
!= null && prop
.get_accessor
.body
== null);
2803 bool empty_set
= (prop
.set_accessor
!= null && prop
.set_accessor
.body
== null);
2805 if (empty_get
!= empty_set
) {
2807 Report
.error (prop
.source_reference
, "property getter must have a body");
2808 } else if (empty_set
) {
2809 Report
.error (prop
.source_reference
, "property setter must have a body");
2814 if (empty_get
&& empty_set
) {
2815 /* automatic property accessor body generation */
2816 var variable_type
= prop
.property_type
.copy ();
2817 prop
.field
= new
Field ("_%s".printf (prop
.name
), variable_type
, prop
.initializer
, prop
.source_reference
);
2818 prop
.field
.access
= SymbolAccessibility
.PRIVATE
;
2819 prop
.field
.binding
= prop
.binding
;
2820 } else if (prop
.initializer
!= null) {
2821 Report
.error (prop
.initializer
.source_reference
, "only automatic properties can have default values");
2825 parent
.add_property (prop
);
2828 void parse_signal_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2829 var begin
= get_location ();
2830 var access
= parse_access_modifier ();
2831 var flags
= parse_member_declaration_modifiers ();
2832 expect (TokenType
.SIGNAL
);
2833 var type
= parse_type (true, false);
2834 string id
= parse_identifier ();
2835 var sig
= new
Signal (id
, type
, get_src (begin
), comment
);
2836 sig
.access
= access
;
2837 set_attributes (sig
, attrs
);
2838 if (ModifierFlags
.STATIC
in flags
) {
2839 throw new ParseError
.SYNTAX (get_error ("`static' modifier not allowed on signals"));
2840 } else if (ModifierFlags
.CLASS
in flags
) {
2841 throw new ParseError
.SYNTAX (get_error ("`class' modifier not allowed on signals"));
2843 if (ModifierFlags
.VIRTUAL
in flags
) {
2844 sig
.is_virtual
= true;
2846 if (ModifierFlags
.NEW
in flags
) {
2849 expect (TokenType
.OPEN_PARENS
);
2850 if (current () != TokenType
.CLOSE_PARENS
) {
2852 var param
= parse_parameter ();
2853 sig
.add_parameter (param
);
2854 } while (accept (TokenType
.COMMA
));
2856 expect (TokenType
.CLOSE_PARENS
);
2857 if (!accept (TokenType
.SEMICOLON
)) {
2858 sig
.body
= parse_block ();
2861 parent
.add_signal (sig
);
2864 void parse_constructor_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2865 var begin
= get_location ();
2866 var flags
= parse_member_declaration_modifiers ();
2867 expect (TokenType
.CONSTRUCT
);
2868 if (ModifierFlags
.NEW
in flags
) {
2869 throw new ParseError
.SYNTAX (get_error ("`new' modifier not allowed on constructor"));
2871 var c
= new
Constructor (get_src (begin
));
2872 if (ModifierFlags
.STATIC
in flags
) {
2873 c
.binding
= MemberBinding
.STATIC
;
2874 } else if (ModifierFlags
.CLASS
in flags
) {
2875 c
.binding
= MemberBinding
.CLASS
;
2877 c
.body
= parse_block ();
2879 parent
.add_constructor (c
);
2882 void parse_destructor_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2883 var begin
= get_location ();
2884 var flags
= parse_member_declaration_modifiers ();
2885 expect (TokenType
.TILDE
);
2886 parse_identifier ();
2887 expect (TokenType
.OPEN_PARENS
);
2888 expect (TokenType
.CLOSE_PARENS
);
2889 if (ModifierFlags
.NEW
in flags
) {
2890 throw new ParseError
.SYNTAX (get_error ("`new' modifier not allowed on destructor"));
2892 var d
= new
Destructor (get_src (begin
));
2893 if (ModifierFlags
.STATIC
in flags
) {
2894 d
.binding
= MemberBinding
.STATIC
;
2895 } else if (ModifierFlags
.CLASS
in flags
) {
2896 d
.binding
= MemberBinding
.CLASS
;
2898 d
.body
= parse_block ();
2900 parent
.add_destructor (d
);
2903 void parse_struct_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2904 var begin
= get_location ();
2905 var access
= parse_access_modifier ();
2906 var flags
= parse_type_declaration_modifiers ();
2907 expect (TokenType
.STRUCT
);
2908 var sym
= parse_symbol_name ();
2909 var type_param_list
= parse_type_parameter_list ();
2910 DataType base_type
= null;
2911 if (accept (TokenType
.COLON
)) {
2912 base_type
= parse_type (true, false);
2914 var st
= new
Struct (sym
.name
, get_src (begin
), comment
);
2916 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2919 set_attributes (st
, attrs
);
2920 foreach (TypeParameter type_param
in type_param_list
) {
2921 st
.add_type_parameter (type_param
);
2923 if (base_type
!= null) {
2924 st
.base_type
= base_type
;
2927 parse_declarations (st
);
2930 while (sym
!= null) {
2933 Symbol next
= (sym
!= null ? new
Namespace (sym
.name
, st
.source_reference
) : parent
);
2934 if (result is Namespace
) {
2935 next
.add_namespace ((Namespace
) result
);
2937 next
.add_struct ((Struct
) result
);
2943 void parse_interface_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2944 var begin
= get_location ();
2945 var access
= parse_access_modifier ();
2946 var flags
= parse_type_declaration_modifiers ();
2947 expect (TokenType
.INTERFACE
);
2948 var sym
= parse_symbol_name ();
2949 var type_param_list
= parse_type_parameter_list ();
2950 var base_types
= new ArrayList
<DataType
> ();
2951 if (accept (TokenType
.COLON
)) {
2953 var type
= parse_type (true, false);
2954 base_types
.add (type
);
2955 } while (accept (TokenType
.COMMA
));
2957 var iface
= new
Interface (sym
.name
, get_src (begin
), comment
);
2958 iface
.access
= access
;
2959 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2960 iface
.external
= true;
2962 set_attributes (iface
, attrs
);
2963 foreach (TypeParameter type_param
in type_param_list
) {
2964 iface
.add_type_parameter (type_param
);
2966 foreach (DataType base_type
in base_types
) {
2967 iface
.add_prerequisite (base_type
);
2970 parse_declarations (iface
);
2972 Symbol result
= iface
;
2973 while (sym
!= null) {
2976 Symbol next
= (sym
!= null ? new
Namespace (sym
.name
, iface
.source_reference
) : parent
);
2977 if (result is Namespace
) {
2978 next
.add_namespace ((Namespace
) result
);
2980 next
.add_interface ((Interface
) result
);
2986 void parse_enum_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
2987 var begin
= get_location ();
2988 var access
= parse_access_modifier ();
2989 var flags
= parse_type_declaration_modifiers ();
2990 expect (TokenType
.ENUM
);
2991 var sym
= parse_symbol_name ();
2992 var en
= new
Enum (sym
.name
, get_src (begin
), comment
);
2994 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2997 set_attributes (en
, attrs
);
2999 expect (TokenType
.OPEN_BRACE
);
3001 if (current () == TokenType
.CLOSE_BRACE
3002 && en
.get_values ().size
> 0) {
3003 // allow trailing comma
3006 var value_attrs
= parse_attributes ();
3007 var value_begin
= get_location ();
3008 string id
= parse_identifier ();
3009 comment
= scanner
.pop_comment ();
3011 Expression value
= null;
3012 if (accept (TokenType
.ASSIGN
)) {
3013 value
= parse_expression ();
3016 var ev
= new
EnumValue (id
, value
, get_src (value_begin
), comment
);
3017 ev
.access
= SymbolAccessibility
.PUBLIC
;
3018 set_attributes (ev
, value_attrs
);
3020 } while (accept (TokenType
.COMMA
));
3021 if (accept (TokenType
.SEMICOLON
)) {
3023 while (current () != TokenType
.CLOSE_BRACE
) {
3024 parse_declaration (en
);
3027 expect (TokenType
.CLOSE_BRACE
);
3030 while (sym
!= null) {
3033 Symbol next
= (sym
!= null ? new
Namespace (sym
.name
, en
.source_reference
) : parent
);
3034 if (result is Namespace
) {
3035 next
.add_namespace ((Namespace
) result
);
3037 next
.add_enum ((Enum
) result
);
3043 void parse_errordomain_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
3044 var begin
= get_location ();
3045 var access
= parse_access_modifier ();
3046 var flags
= parse_type_declaration_modifiers ();
3047 expect (TokenType
.ERRORDOMAIN
);
3048 var sym
= parse_symbol_name ();
3049 var ed
= new
ErrorDomain (sym
.name
, get_src (begin
), comment
);
3051 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3054 set_attributes (ed
, attrs
);
3056 expect (TokenType
.OPEN_BRACE
);
3058 if (current () == TokenType
.CLOSE_BRACE
3059 && ed
.get_codes ().size
> 0) {
3060 // allow trailing comma
3063 var code_attrs
= parse_attributes ();
3064 var code_begin
= get_location ();
3065 string id
= parse_identifier ();
3066 comment
= scanner
.pop_comment ();
3067 var ec
= new
ErrorCode (id
, get_src (code_begin
), comment
);
3068 set_attributes (ec
, code_attrs
);
3069 if (accept (TokenType
.ASSIGN
)) {
3070 ec
.value
= parse_expression ();
3073 } while (accept (TokenType
.COMMA
));
3074 if (accept (TokenType
.SEMICOLON
)) {
3075 // errordomain methods
3076 while (current () != TokenType
.CLOSE_BRACE
) {
3077 parse_declaration (ed
);
3080 expect (TokenType
.CLOSE_BRACE
);
3083 while (sym
!= null) {
3086 Symbol next
= (sym
!= null ? new
Namespace (sym
.name
, ed
.source_reference
) : parent
);
3087 if (result is Namespace
) {
3088 next
.add_namespace ((Namespace
) result
);
3090 next
.add_error_domain ((ErrorDomain
) result
);
3096 SymbolAccessibility
parse_access_modifier (SymbolAccessibility default_access
= SymbolAccessibility
.PRIVATE
) {
3097 switch (current ()) {
3098 case TokenType
.PRIVATE
:
3100 return SymbolAccessibility
.PRIVATE
;
3101 case TokenType
.PROTECTED
:
3103 return SymbolAccessibility
.PROTECTED
;
3104 case TokenType
.INTERNAL
:
3106 return SymbolAccessibility
.INTERNAL
;
3107 case TokenType
.PUBLIC
:
3109 return SymbolAccessibility
.PUBLIC
;
3111 return default_access
;
3115 ModifierFlags
parse_type_declaration_modifiers () {
3116 ModifierFlags flags
= 0;
3118 switch (current ()) {
3119 case TokenType
.ABSTRACT
:
3121 flags
|= ModifierFlags
.ABSTRACT
;
3123 case TokenType
.EXTERN
:
3125 flags
|= ModifierFlags
.EXTERN
;
3127 case TokenType
.SEALED
:
3129 flags
|= ModifierFlags
.SEALED
;
3131 case TokenType
.STATIC
:
3133 flags
|= ModifierFlags
.STATIC
;
3141 ModifierFlags
parse_member_declaration_modifiers () {
3142 ModifierFlags flags
= 0;
3144 switch (current ()) {
3145 case TokenType
.ABSTRACT
:
3147 flags
|= ModifierFlags
.ABSTRACT
;
3149 case TokenType
.ASYNC
:
3151 flags
|= ModifierFlags
.ASYNC
;
3153 case TokenType
.CLASS
:
3155 flags
|= ModifierFlags
.CLASS
;
3157 case TokenType
.EXTERN
:
3159 flags
|= ModifierFlags
.EXTERN
;
3161 case TokenType
.INLINE
:
3163 flags
|= ModifierFlags
.INLINE
;
3167 flags
|= ModifierFlags
.NEW
;
3169 case TokenType
.OVERRIDE
:
3171 flags
|= ModifierFlags
.OVERRIDE
;
3173 case TokenType
.SEALED
:
3175 flags
|= ModifierFlags
.SEALED
;
3177 case TokenType
.STATIC
:
3179 flags
|= ModifierFlags
.STATIC
;
3181 case TokenType
.VIRTUAL
:
3183 flags
|= ModifierFlags
.VIRTUAL
;
3191 Parameter
parse_parameter () throws ParseError
{
3192 var attrs
= parse_attributes ();
3193 var begin
= get_location ();
3194 if (accept (TokenType
.ELLIPSIS
)) {
3196 return new Parameter
.with_ellipsis (get_src (begin
));
3198 bool params_array
= accept (TokenType
.PARAMS
);
3199 var direction
= ParameterDirection
.IN
;
3200 if (accept (TokenType
.OUT
)) {
3201 direction
= ParameterDirection
.OUT
;
3202 } else if (accept (TokenType
.REF
)) {
3203 direction
= ParameterDirection
.REF
;
3206 if (context
.profile
== Profile
.DOVA
) {
3207 accept (TokenType
.VOLATILE
);
3210 if (direction
== ParameterDirection
.IN
) {
3211 // in parameters are unowned by default
3212 type
= parse_type (false, false);
3213 } else if (direction
== ParameterDirection
.REF
) {
3214 // ref parameters own the value by default
3215 type
= parse_type (true, true);
3217 // out parameters own the value by default
3218 type
= parse_type (true, false);
3220 string id
= parse_identifier ();
3222 type
= parse_inline_array_type (type
);
3224 var param
= new
Parameter (id
, type
, get_src (begin
));
3225 set_attributes (param
, attrs
);
3226 param
.direction
= direction
;
3227 param
.params_array
= params_array
;
3228 if (accept (TokenType
.ASSIGN
)) {
3229 param
.initializer
= parse_expression ();
3234 void parse_creation_method_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
3235 var begin
= get_location ();
3236 var access
= parse_access_modifier ();
3237 var flags
= parse_member_declaration_modifiers ();
3238 var sym
= parse_symbol_name ();
3239 if (ModifierFlags
.NEW
in flags
) {
3240 throw new ParseError
.SYNTAX (get_error ("`new' modifier not allowed on creation method"));
3242 CreationMethod method
;
3243 if (sym
.inner
== null) {
3244 method
= new
CreationMethod (sym
.name
, null, get_src (begin
), comment
);
3246 method
= new
CreationMethod (sym
.inner
.name
, sym
.name
, get_src (begin
), comment
);
3248 if (ModifierFlags
.EXTERN
in flags
) {
3249 method
.external
= true;
3251 if (ModifierFlags
.ABSTRACT
in flags
3252 || ModifierFlags
.VIRTUAL
in flags
3253 || ModifierFlags
.OVERRIDE
in flags
) {
3254 Report
.error (method
.source_reference
, "abstract, virtual, and override modifiers are not applicable to creation methods");
3256 if (ModifierFlags
.ASYNC
in flags
) {
3257 method
.coroutine
= true;
3259 expect (TokenType
.OPEN_PARENS
);
3260 if (current () != TokenType
.CLOSE_PARENS
) {
3262 var param
= parse_parameter ();
3263 method
.add_parameter (param
);
3264 } while (accept (TokenType
.COMMA
));
3266 expect (TokenType
.CLOSE_PARENS
);
3267 if (context
.profile
== Profile
.DOVA
) {
3268 var error_type
= new UnresolvedType
.from_symbol (new
UnresolvedSymbol (new
UnresolvedSymbol (null, "Dova"), "Error"), method
.source_reference
);
3269 method
.add_error_type (error_type
);
3270 if (accept (TokenType
.THROWS
)) {
3272 parse_type (true, false);
3273 } while (accept (TokenType
.COMMA
));
3274 Report
.warning (method
.source_reference
, "`throws' is ignored in the Dova profile");
3277 if (accept (TokenType
.THROWS
)) {
3279 method
.add_error_type (parse_type (true, false));
3280 } while (accept (TokenType
.COMMA
));
3283 while (accept (TokenType
.REQUIRES
)) {
3284 expect (TokenType
.OPEN_PARENS
);
3285 method
.add_precondition (parse_expression ());
3286 expect (TokenType
.CLOSE_PARENS
);
3288 while (accept (TokenType
.ENSURES
)) {
3289 expect (TokenType
.OPEN_PARENS
);
3290 method
.add_postcondition (parse_expression ());
3291 expect (TokenType
.CLOSE_PARENS
);
3293 method
.access
= access
;
3294 set_attributes (method
, attrs
);
3295 if (!accept (TokenType
.SEMICOLON
)) {
3296 method
.body
= parse_block ();
3297 } else if (scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3298 method
.external
= true;
3301 parent
.add_method (method
);
3304 void parse_delegate_declaration (Symbol parent
, List
<Attribute
>? attrs
) throws ParseError
{
3305 var begin
= get_location ();
3306 var access
= parse_access_modifier ();
3307 var flags
= parse_member_declaration_modifiers ();
3308 expect (TokenType
.DELEGATE
);
3309 if (ModifierFlags
.NEW
in flags
) {
3310 throw new ParseError
.SYNTAX (get_error ("`new' modifier not allowed on delegates"));
3312 var type
= parse_type (true, false);
3313 var sym
= parse_symbol_name ();
3314 var type_param_list
= parse_type_parameter_list ();
3315 var d
= new
Delegate (sym
.name
, type
, get_src (begin
), comment
);
3317 set_attributes (d
, attrs
);
3318 if (ModifierFlags
.STATIC
in flags
) {
3319 if (!context
.deprecated
) {
3320 // TODO enable warning in future releases
3321 Report
.warning (get_last_src (), "deprecated syntax, use [CCode (has_target = false)]");
3324 d
.has_target
= true;
3326 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3329 foreach (TypeParameter type_param
in type_param_list
) {
3330 d
.add_type_parameter (type_param
);
3332 expect (TokenType
.OPEN_PARENS
);
3333 if (current () != TokenType
.CLOSE_PARENS
) {
3335 var param
= parse_parameter ();
3336 d
.add_parameter (param
);
3337 } while (accept (TokenType
.COMMA
));
3339 expect (TokenType
.CLOSE_PARENS
);
3340 if (context
.profile
== Profile
.DOVA
) {
3341 var error_type
= new UnresolvedType
.from_symbol (new
UnresolvedSymbol (new
UnresolvedSymbol (null, "Dova"), "Error"), d
.source_reference
);
3342 d
.add_error_type (error_type
);
3343 if (accept (TokenType
.THROWS
)) {
3345 parse_type (true, false);
3346 } while (accept (TokenType
.COMMA
));
3347 Report
.warning (d
.source_reference
, "`throws' is ignored in the Dova profile");
3350 if (accept (TokenType
.THROWS
)) {
3352 d
.add_error_type (parse_type (true, false));
3353 } while (accept (TokenType
.COMMA
));
3356 expect (TokenType
.SEMICOLON
);
3359 while (sym
!= null) {
3362 Symbol next
= (sym
!= null ? new
Namespace (sym
.name
, d
.source_reference
) : parent
);
3363 if (result is Namespace
) {
3364 next
.add_namespace ((Namespace
) result
);
3366 next
.add_delegate ((Delegate
) result
);
3372 List
<TypeParameter
> parse_type_parameter_list () throws ParseError
{
3373 if (accept (TokenType
.OP_LT
)) {
3374 var list
= new ArrayList
<TypeParameter
> ();
3376 var begin
= get_location ();
3377 string id
= parse_identifier ();
3378 list
.add (new
TypeParameter (id
, get_src (begin
)));
3379 } while (accept (TokenType
.COMMA
));
3380 expect (TokenType
.OP_GT
);
3383 if (_empty_type_parameter_list
== null) {
3384 _empty_type_parameter_list
= new ArrayList
<TypeParameter
> ();
3386 return _empty_type_parameter_list
;
3390 void skip_type_argument_list () throws ParseError
{
3391 if (accept (TokenType
.OP_LT
)) {
3394 } while (accept (TokenType
.COMMA
));
3395 expect (TokenType
.OP_GT
);
3399 // try to parse type argument list
3400 List
<DataType
>?
parse_type_argument_list (bool maybe_expression
) throws ParseError
{
3401 var begin
= get_location ();
3402 if (accept (TokenType
.OP_LT
)) {
3403 var list
= new ArrayList
<DataType
> ();
3405 switch (current ()) {
3406 case TokenType
.VOID
:
3407 case TokenType
.DYNAMIC
:
3408 case TokenType
.UNOWNED
:
3409 case TokenType
.WEAK
:
3410 case TokenType
.IDENTIFIER
:
3411 var type
= parse_type (true, true);
3418 } while (accept (TokenType
.COMMA
));
3419 if (!accept (TokenType
.OP_GT
)) {
3423 if (maybe_expression
) {
3424 // check follower to decide whether to keep type argument list
3425 switch (current ()) {
3426 case TokenType
.OPEN_PARENS
:
3427 case TokenType
.CLOSE_PARENS
:
3428 case TokenType
.CLOSE_BRACKET
:
3429 case TokenType
.OPEN_BRACE
:
3430 case TokenType
.COLON
:
3431 case TokenType
.SEMICOLON
:
3432 case TokenType
.COMMA
:
3434 case TokenType
.INTERR
:
3435 case TokenType
.OP_EQ
:
3436 case TokenType
.OP_NE
:
3437 // keep type argument list
3440 // interpret tokens as expression
3450 MemberAccess
parse_member_name (Expression? base_expr
= null) throws ParseError
{
3451 var begin
= get_location ();
3452 MemberAccess expr
= null;
3455 string id
= parse_identifier ();
3457 // The first member access can be global:: qualified
3458 bool qualified
= false;
3459 if (first
&& id
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
3460 id
= parse_identifier ();
3464 List
<DataType
> type_arg_list
= parse_type_argument_list (false);
3465 expr
= new
MemberAccess (expr
!= null ? expr
: base_expr
, id
, get_src (begin
));
3466 expr
.qualified
= qualified
;
3467 if (type_arg_list
!= null) {
3468 foreach (DataType type_arg
in type_arg_list
) {
3469 expr
.add_type_argument (type_arg
);
3474 } while (accept (TokenType
.DOT
));
3478 bool is_declaration_keyword (TokenType type
) {
3480 case TokenType
.ABSTRACT
:
3481 case TokenType
.ASYNC
:
3482 case TokenType
.CLASS
:
3483 case TokenType
.CONST
:
3484 case TokenType
.DELEGATE
:
3485 case TokenType
.ENUM
:
3486 case TokenType
.ERRORDOMAIN
:
3487 case TokenType
.EXTERN
:
3488 case TokenType
.INLINE
:
3489 case TokenType
.INTERFACE
:
3490 case TokenType
.INTERNAL
:
3491 case TokenType
.NAMESPACE
:
3493 case TokenType
.OVERRIDE
:
3494 case TokenType
.PRIVATE
:
3495 case TokenType
.PROTECTED
:
3496 case TokenType
.PUBLIC
:
3497 case TokenType
.SEALED
:
3498 case TokenType
.SIGNAL
:
3499 case TokenType
.STATIC
:
3500 case TokenType
.STRUCT
:
3501 case TokenType
.VIRTUAL
:
3502 case TokenType
.VOLATILE
:
3510 public errordomain Vala
.ParseError
{