3 * Copyright (C) 2006-2009 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;
45 public TokenType type
;
46 public SourceLocation begin
;
47 public SourceLocation end
;
64 tokens
= new TokenInfo
[BUFFER_SIZE
];
68 * Parses all .vala and .vapi source files in the specified code
69 * context and builds a code tree.
71 * @param context a code context
73 public void parse (CodeContext context
) {
74 this
.context
= context
;
75 context
.accept (this
);
78 public override void visit_source_file (SourceFile source_file
) {
79 if (source_file
.filename
.has_suffix (".vala") || source_file
.filename
.has_suffix (".vapi")) {
80 parse_file (source_file
);
85 index
= (index
+ 1) % BUFFER_SIZE
;
88 SourceLocation begin
, end
;
89 TokenType type
= scanner
.read_token (out begin
, out end
);
90 tokens
[index
].type
= type
;
91 tokens
[index
].begin
= begin
;
92 tokens
[index
].end
= end
;
95 return (tokens
[index
].type
!= TokenType
.EOF
);
99 index
= (index
- 1 + BUFFER_SIZE
) % BUFFER_SIZE
;
101 assert (size
<= BUFFER_SIZE
);
104 inline TokenType
current () {
105 return tokens
[index
].type
;
108 inline
bool accept (TokenType type
) {
109 if (current () == type
) {
116 string get_error (string msg
) {
117 var begin
= get_location ();
119 Report
.error (get_src (begin
), "syntax error, " + msg
);
123 inline
bool expect (TokenType type
) throws ParseError
{
128 throw new ParseError
.SYNTAX (get_error ("expected %s".printf (type
.to_string ())));
131 inline SourceLocation
get_location () {
132 return tokens
[index
].begin
;
135 string get_current_string () {
136 return ((string) tokens
[index
].begin
.pos
).ndup ((tokens
[index
].end
.pos
- tokens
[index
].begin
.pos
));
139 string get_last_string () {
140 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
141 return ((string) tokens
[last_index
].begin
.pos
).ndup ((tokens
[last_index
].end
.pos
- tokens
[last_index
].begin
.pos
));
144 SourceReference
get_src (SourceLocation begin
) {
145 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
147 return new
SourceReference (scanner
.source_file
, begin
.line
, begin
.column
, tokens
[last_index
].end
.line
, tokens
[last_index
].end
.column
);
150 SourceReference
get_current_src () {
151 return new
SourceReference (scanner
.source_file
, tokens
[index
].begin
.line
, tokens
[index
].begin
.column
, tokens
[index
].end
.line
, tokens
[index
].end
.column
);
154 SourceReference
get_last_src () {
155 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
157 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
);
160 void rollback (SourceLocation location
) {
161 while (tokens
[index
].begin
.pos
!= location
.pos
) {
166 void skip_identifier () throws ParseError
{
167 // also accept keywords as identifiers where there is no conflict
168 switch (current ()) {
169 case TokenType
.ABSTRACT
:
171 case TokenType
.ASYNC
:
173 case TokenType
.BREAK
:
175 case TokenType
.CATCH
:
176 case TokenType
.CLASS
:
177 case TokenType
.CONST
:
178 case TokenType
.CONSTRUCT
:
179 case TokenType
.CONTINUE
:
180 case TokenType
.DEFAULT
:
181 case TokenType
.DELEGATE
:
182 case TokenType
.DELETE
:
184 case TokenType
.DYNAMIC
:
187 case TokenType
.ENSURES
:
188 case TokenType
.ERRORDOMAIN
:
189 case TokenType
.EXTERN
:
190 case TokenType
.FALSE
:
191 case TokenType
.FINALLY
:
193 case TokenType
.FOREACH
:
195 case TokenType
.IDENTIFIER
:
198 case TokenType
.INLINE
:
199 case TokenType
.INTERFACE
:
200 case TokenType
.INTERNAL
:
203 case TokenType
.NAMESPACE
:
207 case TokenType
.OVERRIDE
:
208 case TokenType
.OWNED
:
209 case TokenType
.PARAMS
:
210 case TokenType
.PRIVATE
:
211 case TokenType
.PROTECTED
:
212 case TokenType
.PUBLIC
:
214 case TokenType
.REQUIRES
:
215 case TokenType
.RETURN
:
217 case TokenType
.SIGNAL
:
218 case TokenType
.SIZEOF
:
219 case TokenType
.STATIC
:
220 case TokenType
.STRUCT
:
221 case TokenType
.SWITCH
:
223 case TokenType
.THROW
:
224 case TokenType
.THROWS
:
227 case TokenType
.TYPEOF
:
228 case TokenType
.UNOWNED
:
229 case TokenType
.USING
:
231 case TokenType
.VIRTUAL
:
233 case TokenType
.VOLATILE
:
235 case TokenType
.WHILE
:
236 case TokenType
.YIELD
:
239 case TokenType
.INTEGER_LITERAL
:
240 case TokenType
.REAL_LITERAL
:
241 // also accept integer and real literals
242 // as long as they contain at least one character
243 // and no decimal point
244 // for example, 2D and 3D
245 string id
= get_current_string ();
246 if (id
[id
.length
- 1].isalpha () && !("." in id
)) {
252 throw new ParseError
.SYNTAX (get_error ("expected identifier"));
256 string parse_identifier () throws ParseError
{
258 return get_last_string ();
261 Expression
parse_literal () throws ParseError
{
262 var begin
= get_location ();
264 switch (current ()) {
267 return new
BooleanLiteral (true, get_src (begin
));
268 case TokenType
.FALSE
:
270 return new
BooleanLiteral (false, get_src (begin
));
271 case TokenType
.INTEGER_LITERAL
:
273 return new
IntegerLiteral (get_last_string (), get_src (begin
));
274 case TokenType
.REAL_LITERAL
:
276 return new
RealLiteral (get_last_string (), get_src (begin
));
277 case TokenType
.CHARACTER_LITERAL
:
279 // FIXME validate and unescape here and just pass unichar to CharacterLiteral
280 var lit
= new
CharacterLiteral (get_last_string (), get_src (begin
));
282 Report
.error (lit
.source_reference
, "invalid character literal");
285 case TokenType
.STRING_LITERAL
:
287 return new
StringLiteral (get_last_string (), get_src (begin
));
288 case TokenType
.TEMPLATE_STRING_LITERAL
:
290 return new
StringLiteral ("\"%s\"".printf (get_last_string ()), get_src (begin
));
291 case TokenType
.VERBATIM_STRING_LITERAL
:
293 string raw_string
= get_last_string ();
294 string escaped_string
= raw_string
.substring (3, raw_string
.len () - 6).escape ("");
295 return new
StringLiteral ("\"%s\"".printf (escaped_string
), get_src (begin
));
298 return new
NullLiteral (get_src (begin
));
300 throw new ParseError
.SYNTAX (get_error ("expected literal"));
304 public void parse_file (SourceFile source_file
) {
305 scanner
= new
Scanner (source_file
);
306 parse_file_comments ();
315 parse_using_directives (context
.root
);
316 parse_declarations (context
.root
, true);
317 if (accept (TokenType
.CLOSE_BRACE
)) {
318 // only report error if it's not a secondary error
319 if (context
.report
.get_errors () == 0) {
320 Report
.error (get_last_src (), "unexpected `}'");
323 } catch (ParseError e
) {
330 void parse_file_comments () {
331 scanner
.parse_file_comments ();
334 void skip_symbol_name () throws ParseError
{
337 } while (accept (TokenType
.DOT
) || accept (TokenType
.DOUBLE_COLON
));
340 UnresolvedSymbol
parse_symbol_name () throws ParseError
{
341 var begin
= get_location ();
342 UnresolvedSymbol sym
= null;
344 string name
= parse_identifier ();
345 if (name
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
347 // qualified access to global symbol
348 name
= parse_identifier ();
349 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
350 sym
.qualified
= true;
353 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
354 } while (accept (TokenType
.DOT
));
358 void skip_type () throws ParseError
{
359 if (accept (TokenType
.VOID
)) {
360 while (accept (TokenType
.STAR
)) {
364 accept (TokenType
.DYNAMIC
);
365 accept (TokenType
.OWNED
);
366 accept (TokenType
.UNOWNED
);
367 accept (TokenType
.WEAK
);
369 skip_type_argument_list ();
370 while (accept (TokenType
.STAR
)) {
372 accept (TokenType
.INTERR
);
373 while (accept (TokenType
.OPEN_BRACKET
)) {
375 // required for decision between expression and declaration statement
376 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
379 } while (accept (TokenType
.COMMA
));
380 expect (TokenType
.CLOSE_BRACKET
);
381 accept (TokenType
.INTERR
);
383 accept (TokenType
.OP_NEG
);
384 accept (TokenType
.HASH
);
387 DataType
parse_type (bool owned_by_default
= true) throws ParseError
{
388 var begin
= get_location ();
390 if (accept (TokenType
.VOID
)) {
391 DataType type
= new
VoidType (get_src (begin
));
392 while (accept (TokenType
.STAR
)) {
393 type
= new
PointerType (type
);
398 bool is_dynamic
= accept (TokenType
.DYNAMIC
);
400 bool value_owned
= owned_by_default
;
402 if (owned_by_default
) {
403 if (accept (TokenType
.UNOWNED
)
404 || accept (TokenType
.WEAK
)) {
408 value_owned
= accept (TokenType
.OWNED
);
411 var sym
= parse_symbol_name ();
412 List
<DataType
> type_arg_list
= parse_type_argument_list (false);
414 DataType type
= new UnresolvedType
.from_symbol (sym
, get_src (begin
));
415 if (type_arg_list
!= null) {
416 foreach (DataType type_arg
in type_arg_list
) {
417 type
.add_type_argument (type_arg
);
421 while (accept (TokenType
.STAR
)) {
422 type
= new
PointerType (type
, get_src (begin
));
425 if (!(type is PointerType
)) {
426 type
.nullable
= accept (TokenType
.INTERR
);
429 // array brackets in types are read from right to left,
430 // this is more logical, especially when nullable arrays
431 // or pointers are involved
432 while (accept (TokenType
.OPEN_BRACKET
)) {
433 bool invalid_array
= false;
437 // required for decision between expression and declaration statement
438 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
440 // only used for parsing, reject use as real type
441 invalid_array
= true;
443 } while (accept (TokenType
.COMMA
));
444 expect (TokenType
.CLOSE_BRACKET
);
446 // arrays contain strong references by default
447 type
.value_owned
= true;
449 var array_type
= new
ArrayType (type
, array_rank
, get_src (begin
));
450 array_type
.nullable
= accept (TokenType
.INTERR
);
451 array_type
.invalid_syntax
= invalid_array
;
456 if (accept (TokenType
.OP_NEG
)) {
457 Report
.warning (get_last_src (), "obsolete syntax, types are non-null by default");
460 if (!owned_by_default
) {
461 if (accept (TokenType
.HASH
)) {
462 if (!context
.deprecated
) {
463 Report
.warning (get_last_src (), "deprecated syntax, use `owned` modifier");
469 type
.is_dynamic
= is_dynamic
;
470 type
.value_owned
= value_owned
;
474 DataType?
parse_inline_array_type (DataType? type
) throws ParseError
{
475 var begin
= get_location ();
477 // inline-allocated array
478 if (type
!= null && accept (TokenType
.OPEN_BRACKET
)) {
479 int array_length
= -1;
481 if (current () != TokenType
.CLOSE_BRACKET
) {
482 if (current () != TokenType
.INTEGER_LITERAL
) {
483 throw new ParseError
.SYNTAX (get_error ("expected `]' or integer literal"));
486 var length_literal
= (IntegerLiteral
) parse_literal ();
487 array_length
= length_literal
.value
.to_int ();
489 expect (TokenType
.CLOSE_BRACKET
);
491 var array_type
= new
ArrayType (type
, 1, get_src (begin
));
492 array_type
.inline_allocated
= true;
493 if (array_length
> 0) {
494 array_type
.fixed_length
= true;
495 array_type
.length
= array_length
;
503 List
<Expression
> parse_argument_list () throws ParseError
{
504 var list
= new ArrayList
<Expression
> ();
505 if (current () != TokenType
.CLOSE_PARENS
) {
507 list
.add (parse_argument ());
508 } while (accept (TokenType
.COMMA
));
513 Expression
parse_argument () throws ParseError
{
514 var begin
= get_location ();
516 if (accept (TokenType
.REF
)) {
517 var inner
= parse_expression ();
518 return new
UnaryExpression (UnaryOperator
.REF
, inner
, get_src (begin
));
519 } else if (accept (TokenType
.OUT
)) {
520 var inner
= parse_expression ();
521 return new
UnaryExpression (UnaryOperator
.OUT
, inner
, get_src (begin
));
523 var expr
= parse_expression ();
524 var ma
= expr as MemberAccess
;
525 if (ma
!= null && ma
.inner
== null && accept (TokenType
.COLON
)) {
527 expr
= parse_expression ();
528 return new
NamedArgument (ma
.member_name
, expr
, get_src (begin
));
535 Expression
parse_primary_expression () throws ParseError
{
536 var begin
= get_location ();
540 switch (current ()) {
542 case TokenType
.FALSE
:
543 case TokenType
.INTEGER_LITERAL
:
544 case TokenType
.REAL_LITERAL
:
545 case TokenType
.CHARACTER_LITERAL
:
546 case TokenType
.STRING_LITERAL
:
547 case TokenType
.TEMPLATE_STRING_LITERAL
:
548 case TokenType
.VERBATIM_STRING_LITERAL
:
550 expr
= parse_literal ();
552 case TokenType
.OPEN_BRACE
:
553 expr
= parse_initializer ();
555 case TokenType
.OPEN_PARENS
:
556 expr
= parse_tuple ();
558 case TokenType
.OPEN_TEMPLATE
:
559 expr
= parse_template ();
562 expr
= parse_this_access ();
565 expr
= parse_base_access ();
568 expr
= parse_object_or_array_creation_expression ();
570 case TokenType
.YIELD
:
571 expr
= parse_yield_expression ();
573 case TokenType
.SIZEOF
:
574 expr
= parse_sizeof_expression ();
576 case TokenType
.TYPEOF
:
577 expr
= parse_typeof_expression ();
580 expr
= parse_simple_name ();
584 // process primary expressions that start with an inner primary expression
587 switch (current ()) {
589 expr
= parse_member_access (begin
, expr
);
591 case TokenType
.OP_PTR
:
592 expr
= parse_pointer_member_access (begin
, expr
);
594 case TokenType
.OPEN_PARENS
:
595 expr
= parse_method_call (begin
, expr
);
597 case TokenType
.OPEN_BRACKET
:
598 expr
= parse_element_access (begin
, expr
);
600 case TokenType
.OP_INC
:
601 expr
= parse_post_increment_expression (begin
, expr
);
603 case TokenType
.OP_DEC
:
604 expr
= parse_post_decrement_expression (begin
, expr
);
615 Expression
parse_simple_name () throws ParseError
{
616 var begin
= get_location ();
617 string id
= parse_identifier ();
618 bool qualified
= false;
619 if (id
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
620 id
= parse_identifier ();
623 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
624 var expr
= new
MemberAccess (null, id
, get_src (begin
));
625 expr
.qualified
= qualified
;
626 if (type_arg_list
!= null) {
627 foreach (DataType type_arg
in type_arg_list
) {
628 expr
.add_type_argument (type_arg
);
634 Expression
parse_tuple () throws ParseError
{
635 expect (TokenType
.OPEN_PARENS
);
636 var expr_list
= new ArrayList
<Expression
> ();
637 if (current () != TokenType
.CLOSE_PARENS
) {
639 expr_list
.add (parse_expression ());
640 } while (accept (TokenType
.COMMA
));
642 expect (TokenType
.CLOSE_PARENS
);
643 if (expr_list
.size
!= 1) {
644 var tuple
= new
Tuple ();
645 foreach (Expression expr
in expr_list
) {
646 tuple
.add_expression (expr
);
650 return expr_list
.get (0);
653 Expression
parse_template () throws ParseError
{
654 var begin
= get_location ();
655 var template
= new
Template ();
657 expect (TokenType
.OPEN_TEMPLATE
);
658 while (current () != TokenType
.CLOSE_TEMPLATE
) {
659 template
.add_expression (parse_expression ());
660 expect (TokenType
.COMMA
);
662 expect (TokenType
.CLOSE_TEMPLATE
);
664 template
.source_reference
= get_src (begin
);
668 Expression
parse_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
669 expect (TokenType
.DOT
);
670 string id
= parse_identifier ();
671 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
672 var expr
= new
MemberAccess (inner
, id
, get_src (begin
));
673 if (type_arg_list
!= null) {
674 foreach (DataType type_arg
in type_arg_list
) {
675 expr
.add_type_argument (type_arg
);
681 Expression
parse_pointer_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
682 expect (TokenType
.OP_PTR
);
683 string id
= parse_identifier ();
684 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
685 var expr
= new MemberAccess
.pointer (inner
, id
, get_src (begin
));
686 if (type_arg_list
!= null) {
687 foreach (DataType type_arg
in type_arg_list
) {
688 expr
.add_type_argument (type_arg
);
694 Expression
parse_method_call (SourceLocation begin
, Expression inner
) throws ParseError
{
695 expect (TokenType
.OPEN_PARENS
);
696 var arg_list
= parse_argument_list ();
697 expect (TokenType
.CLOSE_PARENS
);
698 var init_list
= parse_object_initializer ();
700 if (init_list
.size
> 0 && inner is MemberAccess
) {
701 // struct creation expression
702 var member
= (MemberAccess
) inner
;
703 member
.creation_member
= true;
705 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
706 expr
.struct_creation
= true;
707 foreach (Expression arg
in arg_list
) {
708 expr
.add_argument (arg
);
710 foreach (MemberInitializer initializer
in init_list
) {
711 expr
.add_member_initializer (initializer
);
715 var expr
= new
MethodCall (inner
, get_src (begin
));
716 foreach (Expression arg
in arg_list
) {
717 expr
.add_argument (arg
);
723 Expression
parse_element_access (SourceLocation begin
, Expression inner
) throws ParseError
{
724 expect (TokenType
.OPEN_BRACKET
);
725 var index_list
= parse_expression_list ();
726 expect (TokenType
.CLOSE_BRACKET
);
728 var expr
= new
ElementAccess (inner
, get_src (begin
));
729 foreach (Expression index
in index_list
) {
730 expr
.append_index (index
);
735 List
<Expression
> parse_expression_list () throws ParseError
{
736 var list
= new ArrayList
<Expression
> ();
738 list
.add (parse_expression ());
739 } while (accept (TokenType
.COMMA
));
743 Expression
parse_this_access () throws ParseError
{
744 var begin
= get_location ();
745 expect (TokenType
.THIS
);
746 return new
MemberAccess (null, "this", get_src (begin
));
749 Expression
parse_base_access () throws ParseError
{
750 var begin
= get_location ();
751 expect (TokenType
.BASE
);
752 return new
BaseAccess (get_src (begin
));
755 Expression
parse_post_increment_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
756 expect (TokenType
.OP_INC
);
757 return new
PostfixExpression (inner
, true, get_src (begin
));
760 Expression
parse_post_decrement_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
761 expect (TokenType
.OP_DEC
);
762 return new
PostfixExpression (inner
, false, get_src (begin
));
765 Expression
parse_object_or_array_creation_expression () throws ParseError
{
766 var begin
= get_location ();
767 expect (TokenType
.NEW
);
768 var member
= parse_member_name ();
769 if (accept (TokenType
.OPEN_PARENS
)) {
770 var expr
= parse_object_creation_expression (begin
, member
);
772 } else if (accept (TokenType
.OPEN_BRACKET
)) {
773 var expr
= parse_array_creation_expression (begin
, member
);
776 throw new ParseError
.SYNTAX (get_error ("expected ( or ["));
780 Expression
parse_object_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
781 member
.creation_member
= true;
782 var arg_list
= parse_argument_list ();
783 expect (TokenType
.CLOSE_PARENS
);
784 var init_list
= parse_object_initializer ();
786 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
787 foreach (Expression arg
in arg_list
) {
788 expr
.add_argument (arg
);
790 foreach (MemberInitializer initializer
in init_list
) {
791 expr
.add_member_initializer (initializer
);
796 Expression
parse_array_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
797 bool size_specified
= false;
798 List
<Expression
> size_specifier_list
= null;
800 DataType element_type
= UnresolvedType
.new_from_expression (member
);
803 // array of arrays: new T[][42]
804 element_type
= new
ArrayType (element_type
, size_specifier_list
.size
, element_type
.source_reference
);
809 size_specifier_list
= new ArrayList
<Expression
> ();
811 Expression size
= null;
812 if (current () != TokenType
.CLOSE_BRACKET
&& current () != TokenType
.COMMA
) {
813 size
= parse_expression ();
814 size_specified
= true;
816 size_specifier_list
.add (size
);
817 } while (accept (TokenType
.COMMA
));
818 expect (TokenType
.CLOSE_BRACKET
);
819 } while (accept (TokenType
.OPEN_BRACKET
));
821 InitializerList initializer
= null;
822 if (current () == TokenType
.OPEN_BRACE
) {
823 initializer
= parse_initializer ();
825 var expr
= new
ArrayCreationExpression (element_type
, size_specifier_list
.size
, initializer
, get_src (begin
));
826 if (size_specified
) {
827 foreach (Expression size
in size_specifier_list
) {
828 expr
.append_size (size
);
834 List
<MemberInitializer
> parse_object_initializer () throws ParseError
{
835 var list
= new ArrayList
<MemberInitializer
> ();
836 if (accept (TokenType
.OPEN_BRACE
)) {
838 list
.add (parse_member_initializer ());
839 } while (accept (TokenType
.COMMA
));
840 expect (TokenType
.CLOSE_BRACE
);
845 MemberInitializer
parse_member_initializer () throws ParseError
{
846 var begin
= get_location ();
847 string id
= parse_identifier ();
848 expect (TokenType
.ASSIGN
);
849 var expr
= parse_expression ();
851 return new
MemberInitializer (id
, expr
, get_src (begin
));
854 Expression
parse_yield_expression () throws ParseError
{
855 var begin
= get_location ();
856 expect (TokenType
.YIELD
);
857 var member
= parse_member_name ();
858 var call
= (MethodCall
) parse_method_call (begin
, member
);
859 call
.is_yield_expression
= true;
863 Expression
parse_sizeof_expression () throws ParseError
{
864 var begin
= get_location ();
865 expect (TokenType
.SIZEOF
);
866 expect (TokenType
.OPEN_PARENS
);
867 var type
= parse_type ();
868 expect (TokenType
.CLOSE_PARENS
);
870 return new
SizeofExpression (type
, get_src (begin
));
873 Expression
parse_typeof_expression () throws ParseError
{
874 var begin
= get_location ();
875 expect (TokenType
.TYPEOF
);
876 expect (TokenType
.OPEN_PARENS
);
877 var type
= parse_type ();
878 expect (TokenType
.CLOSE_PARENS
);
880 return new
TypeofExpression (type
, get_src (begin
));
883 UnaryOperator
get_unary_operator (TokenType token_type
) {
884 switch (token_type
) {
885 case TokenType
.PLUS
: return UnaryOperator
.PLUS
;
886 case TokenType
.MINUS
: return UnaryOperator
.MINUS
;
887 case TokenType
.OP_NEG
: return UnaryOperator
.LOGICAL_NEGATION
;
888 case TokenType
.TILDE
: return UnaryOperator
.BITWISE_COMPLEMENT
;
889 case TokenType
.OP_INC
: return UnaryOperator
.INCREMENT
;
890 case TokenType
.OP_DEC
: return UnaryOperator
.DECREMENT
;
891 default: return UnaryOperator
.NONE
;
895 Expression
parse_unary_expression () throws ParseError
{
896 var begin
= get_location ();
897 var operator
= get_unary_operator (current ());
898 if (operator
!= UnaryOperator
.NONE
) {
900 var op
= parse_unary_expression ();
901 return new
UnaryExpression (operator
, op
, get_src (begin
));
903 switch (current ()) {
905 if (!context
.deprecated
) {
906 Report
.warning (get_last_src (), "deprecated syntax, use `(owned)` cast");
909 var op
= parse_unary_expression ();
910 return new
ReferenceTransferExpression (op
, get_src (begin
));
911 case TokenType
.OPEN_PARENS
:
913 switch (current ()) {
914 case TokenType
.OWNED
:
917 if (accept (TokenType
.CLOSE_PARENS
)) {
918 var op
= parse_unary_expression ();
919 return new
ReferenceTransferExpression (op
, get_src (begin
));
923 case TokenType
.DYNAMIC
:
924 case TokenType
.IDENTIFIER
:
925 var type
= parse_type ();
926 if (accept (TokenType
.CLOSE_PARENS
)) {
927 // check follower to decide whether to create cast expression
928 switch (current ()) {
929 case TokenType
.OP_NEG
:
930 case TokenType
.TILDE
:
931 case TokenType
.OPEN_PARENS
:
933 case TokenType
.FALSE
:
934 case TokenType
.INTEGER_LITERAL
:
935 case TokenType
.REAL_LITERAL
:
936 case TokenType
.CHARACTER_LITERAL
:
937 case TokenType
.STRING_LITERAL
:
938 case TokenType
.TEMPLATE_STRING_LITERAL
:
939 case TokenType
.VERBATIM_STRING_LITERAL
:
944 case TokenType
.SIZEOF
:
945 case TokenType
.TYPEOF
:
946 case TokenType
.IDENTIFIER
:
947 case TokenType
.PARAMS
:
948 var inner
= parse_unary_expression ();
949 return new
CastExpression (inner
, type
, get_src (begin
), false);
955 case TokenType
.OP_NEG
:
957 if (accept (TokenType
.CLOSE_PARENS
)) {
959 var inner
= parse_unary_expression ();
960 return new CastExpression
.non_null (inner
, get_src (begin
));
966 // no cast expression
971 var op
= parse_unary_expression ();
972 return new
PointerIndirection (op
, get_src (begin
));
973 case TokenType
.BITWISE_AND
:
975 var op
= parse_unary_expression ();
976 return new
AddressofExpression (op
, get_src (begin
));
981 var expr
= parse_primary_expression ();
985 BinaryOperator
get_binary_operator (TokenType token_type
) {
986 switch (token_type
) {
987 case TokenType
.STAR
: return BinaryOperator
.MUL
;
988 case TokenType
.DIV
: return BinaryOperator
.DIV
;
989 case TokenType
.PERCENT
: return BinaryOperator
.MOD
;
990 case TokenType
.PLUS
: return BinaryOperator
.PLUS
;
991 case TokenType
.MINUS
: return BinaryOperator
.MINUS
;
992 case TokenType
.OP_LT
: return BinaryOperator
.LESS_THAN
;
993 case TokenType
.OP_GT
: return BinaryOperator
.GREATER_THAN
;
994 case TokenType
.OP_LE
: return BinaryOperator
.LESS_THAN_OR_EQUAL
;
995 case TokenType
.OP_GE
: return BinaryOperator
.GREATER_THAN_OR_EQUAL
;
996 case TokenType
.OP_EQ
: return BinaryOperator
.EQUALITY
;
997 case TokenType
.OP_NE
: return BinaryOperator
.INEQUALITY
;
998 default: return BinaryOperator
.NONE
;
1002 Expression
parse_multiplicative_expression () throws ParseError
{
1003 var begin
= get_location ();
1004 var left
= parse_unary_expression ();
1007 var operator
= get_binary_operator (current ());
1009 case BinaryOperator
.MUL
:
1010 case BinaryOperator
.DIV
:
1011 case BinaryOperator
.MOD
:
1013 var right
= parse_unary_expression ();
1014 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1024 Expression
parse_additive_expression () throws ParseError
{
1025 var begin
= get_location ();
1026 var left
= parse_multiplicative_expression ();
1029 var operator
= get_binary_operator (current ());
1031 case BinaryOperator
.PLUS
:
1032 case BinaryOperator
.MINUS
:
1034 var right
= parse_multiplicative_expression ();
1035 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1045 Expression
parse_shift_expression () throws ParseError
{
1046 var begin
= get_location ();
1047 var left
= parse_additive_expression ();
1050 switch (current ()) {
1051 case TokenType
.OP_SHIFT_LEFT
:
1053 var right
= parse_additive_expression ();
1054 left
= new
BinaryExpression (BinaryOperator
.SHIFT_LEFT
, left
, right
, get_src (begin
));
1056 // don't use OP_SHIFT_RIGHT to support >> for nested generics
1057 case TokenType
.OP_GT
:
1058 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1060 // only accept >> when there is no space between the two > signs
1061 if (current () == TokenType
.OP_GT
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1063 var right
= parse_additive_expression ();
1064 left
= new
BinaryExpression (BinaryOperator
.SHIFT_RIGHT
, left
, right
, get_src (begin
));
1078 Expression
parse_relational_expression () throws ParseError
{
1079 var begin
= get_location ();
1080 var left
= parse_shift_expression ();
1083 var operator
= get_binary_operator (current ());
1085 case BinaryOperator
.LESS_THAN
:
1086 case BinaryOperator
.LESS_THAN_OR_EQUAL
:
1087 case BinaryOperator
.GREATER_THAN_OR_EQUAL
:
1089 var right
= parse_shift_expression ();
1090 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1092 case BinaryOperator
.GREATER_THAN
:
1094 // ignore >> and >>= (two tokens due to generics)
1095 if (current () != TokenType
.OP_GT
&& current () != TokenType
.OP_GE
) {
1096 var right
= parse_shift_expression ();
1097 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1104 switch (current ()) {
1107 var type
= parse_type ();
1108 left
= new
TypeCheck (left
, type
, get_src (begin
));
1112 var type
= parse_type ();
1113 left
= new
CastExpression (left
, type
, get_src (begin
), true);
1125 Expression
parse_equality_expression () throws ParseError
{
1126 var begin
= get_location ();
1127 var left
= parse_relational_expression ();
1130 var operator
= get_binary_operator (current ());
1132 case BinaryOperator
.EQUALITY
:
1133 case BinaryOperator
.INEQUALITY
:
1135 var right
= parse_relational_expression ();
1136 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1146 Expression
parse_and_expression () throws ParseError
{
1147 var begin
= get_location ();
1148 var left
= parse_equality_expression ();
1149 while (accept (TokenType
.BITWISE_AND
)) {
1150 var right
= parse_equality_expression ();
1151 left
= new
BinaryExpression (BinaryOperator
.BITWISE_AND
, left
, right
, get_src (begin
));
1156 Expression
parse_exclusive_or_expression () throws ParseError
{
1157 var begin
= get_location ();
1158 var left
= parse_and_expression ();
1159 while (accept (TokenType
.CARRET
)) {
1160 var right
= parse_and_expression ();
1161 left
= new
BinaryExpression (BinaryOperator
.BITWISE_XOR
, left
, right
, get_src (begin
));
1166 Expression
parse_inclusive_or_expression () throws ParseError
{
1167 var begin
= get_location ();
1168 var left
= parse_exclusive_or_expression ();
1169 while (accept (TokenType
.BITWISE_OR
)) {
1170 var right
= parse_exclusive_or_expression ();
1171 left
= new
BinaryExpression (BinaryOperator
.BITWISE_OR
, left
, right
, get_src (begin
));
1176 Expression
parse_in_expression () throws ParseError
{
1177 var begin
= get_location ();
1178 var left
= parse_inclusive_or_expression ();
1179 while (accept (TokenType
.IN
)) {
1180 var right
= parse_inclusive_or_expression ();
1181 left
= new
BinaryExpression (BinaryOperator
.IN
, left
, right
, get_src (begin
));
1186 Expression
parse_conditional_and_expression () throws ParseError
{
1187 var begin
= get_location ();
1188 var left
= parse_in_expression ();
1189 while (accept (TokenType
.OP_AND
)) {
1190 var right
= parse_in_expression ();
1191 left
= new
BinaryExpression (BinaryOperator
.AND
, left
, right
, get_src (begin
));
1196 Expression
parse_conditional_or_expression () throws ParseError
{
1197 var begin
= get_location ();
1198 var left
= parse_conditional_and_expression ();
1199 while (accept (TokenType
.OP_OR
)) {
1200 var right
= parse_conditional_and_expression ();
1201 left
= new
BinaryExpression (BinaryOperator
.OR
, left
, right
, get_src (begin
));
1206 Expression
parse_conditional_expression () throws ParseError
{
1207 var begin
= get_location ();
1208 var condition
= parse_conditional_or_expression ();
1209 if (accept (TokenType
.INTERR
)) {
1210 var true_expr
= parse_expression ();
1211 expect (TokenType
.COLON
);
1212 var false_expr
= parse_expression ();
1213 return new
ConditionalExpression (condition
, true_expr
, false_expr
, get_src (begin
));
1219 Expression
parse_lambda_expression () throws ParseError
{
1220 var begin
= get_location ();
1221 List
<string> params
= new ArrayList
<string> ();
1222 if (accept (TokenType
.OPEN_PARENS
)) {
1223 if (current () != TokenType
.CLOSE_PARENS
) {
1225 params
.add (parse_identifier ());
1226 } while (accept (TokenType
.COMMA
));
1228 expect (TokenType
.CLOSE_PARENS
);
1230 params
.add (parse_identifier ());
1232 expect (TokenType
.LAMBDA
);
1234 LambdaExpression lambda
;
1235 if (current () == TokenType
.OPEN_BRACE
) {
1236 var block
= parse_block ();
1237 lambda
= new LambdaExpression
.with_statement_body (block
, get_src (begin
));
1239 var expr
= parse_expression ();
1240 lambda
= new
LambdaExpression (expr
, get_src (begin
));
1242 foreach (string param
in params
) {
1243 lambda
.add_parameter (param
);
1248 AssignmentOperator
get_assignment_operator (TokenType token_type
) {
1249 switch (token_type
) {
1250 case TokenType
.ASSIGN
: return AssignmentOperator
.SIMPLE
;
1251 case TokenType
.ASSIGN_ADD
: return AssignmentOperator
.ADD
;
1252 case TokenType
.ASSIGN_SUB
: return AssignmentOperator
.SUB
;
1253 case TokenType
.ASSIGN_BITWISE_OR
: return AssignmentOperator
.BITWISE_OR
;
1254 case TokenType
.ASSIGN_BITWISE_AND
: return AssignmentOperator
.BITWISE_AND
;
1255 case TokenType
.ASSIGN_BITWISE_XOR
: return AssignmentOperator
.BITWISE_XOR
;
1256 case TokenType
.ASSIGN_DIV
: return AssignmentOperator
.DIV
;
1257 case TokenType
.ASSIGN_MUL
: return AssignmentOperator
.MUL
;
1258 case TokenType
.ASSIGN_PERCENT
: return AssignmentOperator
.PERCENT
;
1259 case TokenType
.ASSIGN_SHIFT_LEFT
: return AssignmentOperator
.SHIFT_LEFT
;
1260 default: return AssignmentOperator
.NONE
;
1264 Expression
parse_expression () throws ParseError
{
1265 var begin
= get_location ();
1266 Expression expr
= parse_conditional_expression ();
1268 if (current () == TokenType
.LAMBDA
) {
1270 var lambda
= parse_lambda_expression ();
1275 var operator
= get_assignment_operator (current ());
1276 if (operator
!= AssignmentOperator
.NONE
) {
1278 var rhs
= parse_expression ();
1279 expr
= new
Assignment (expr
, rhs
, operator
, get_src (begin
));
1280 } else if (current () == TokenType
.OP_GT
) { // >>=
1281 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1283 // only accept >>= when there is no space between the two > signs
1284 if (current () == TokenType
.OP_GE
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1286 var rhs
= parse_expression ();
1287 expr
= new
Assignment (expr
, rhs
, AssignmentOperator
.SHIFT_RIGHT
, get_src (begin
));
1300 void parse_statements (Block block
) throws ParseError
{
1301 while (current () != TokenType
.CLOSE_BRACE
1302 && current () != TokenType
.CASE
1303 && current () != TokenType
.DEFAULT
) {
1305 Statement stmt
= null;
1306 bool is_decl
= false;
1308 comment
= scanner
.pop_comment ();
1309 switch (current ()) {
1310 case TokenType
.OPEN_BRACE
:
1311 stmt
= parse_block ();
1313 case TokenType
.SEMICOLON
:
1314 stmt
= parse_empty_statement ();
1317 stmt
= parse_if_statement ();
1319 case TokenType
.SWITCH
:
1320 stmt
= parse_switch_statement ();
1322 case TokenType
.WHILE
:
1323 stmt
= parse_while_statement ();
1326 stmt
= parse_do_statement ();
1329 stmt
= parse_for_statement ();
1331 case TokenType
.FOREACH
:
1332 stmt
= parse_foreach_statement ();
1334 case TokenType
.BREAK
:
1335 stmt
= parse_break_statement ();
1337 case TokenType
.CONTINUE
:
1338 stmt
= parse_continue_statement ();
1340 case TokenType
.RETURN
:
1341 stmt
= parse_return_statement ();
1343 case TokenType
.YIELD
:
1344 stmt
= parse_yield_statement ();
1346 case TokenType
.THROW
:
1347 stmt
= parse_throw_statement ();
1350 stmt
= parse_try_statement ();
1352 case TokenType
.LOCK
:
1353 stmt
= parse_lock_statement ();
1355 case TokenType
.DELETE
:
1356 stmt
= parse_delete_statement ();
1360 parse_local_variable_declarations (block
);
1362 case TokenType
.OP_INC
:
1363 case TokenType
.OP_DEC
:
1364 case TokenType
.BASE
:
1365 case TokenType
.THIS
:
1366 case TokenType
.OPEN_PARENS
:
1367 case TokenType
.STAR
:
1369 stmt
= parse_expression_statement ();
1372 bool is_expr
= is_expression ();
1374 stmt
= parse_expression_statement ();
1377 parse_local_variable_declarations (block
);
1383 block
.add_statement (stmt
);
1385 } catch (ParseError e
) {
1386 if (recover () != RecoveryState
.STATEMENT_BEGIN
) {
1387 // beginning of next declaration or end of file reached
1388 // return what we have so far
1395 bool is_expression () throws ParseError
{
1396 var begin
= get_location ();
1398 // decide between declaration and expression statement
1400 switch (current ()) {
1401 // invocation expression
1402 case TokenType
.OPEN_PARENS
:
1403 // postfix increment
1404 case TokenType
.OP_INC
:
1405 // postfix decrement
1406 case TokenType
.OP_DEC
:
1408 case TokenType
.ASSIGN
:
1409 case TokenType
.ASSIGN_ADD
:
1410 case TokenType
.ASSIGN_BITWISE_AND
:
1411 case TokenType
.ASSIGN_BITWISE_OR
:
1412 case TokenType
.ASSIGN_BITWISE_XOR
:
1413 case TokenType
.ASSIGN_DIV
:
1414 case TokenType
.ASSIGN_MUL
:
1415 case TokenType
.ASSIGN_PERCENT
:
1416 case TokenType
.ASSIGN_SHIFT_LEFT
:
1417 case TokenType
.ASSIGN_SUB
:
1418 case TokenType
.OP_GT
: // >>=
1421 // pointer member access
1422 case TokenType
.OP_PTR
:
1431 Block
parse_embedded_statement () throws ParseError
{
1432 if (current () == TokenType
.OPEN_BRACE
) {
1433 var block
= parse_block ();
1437 comment
= scanner
.pop_comment ();
1439 var block
= new
Block (get_src (get_location ()));
1440 block
.add_statement (parse_embedded_statement_without_block ());
1445 Statement
parse_embedded_statement_without_block () throws ParseError
{
1446 switch (current ()) {
1447 case TokenType
.SEMICOLON
: return parse_empty_statement ();
1448 case TokenType
.IF
: return parse_if_statement ();
1449 case TokenType
.SWITCH
: return parse_switch_statement ();
1450 case TokenType
.WHILE
: return parse_while_statement ();
1451 case TokenType
.DO
: return parse_do_statement ();
1452 case TokenType
.FOR
: return parse_for_statement ();
1453 case TokenType
.FOREACH
: return parse_foreach_statement ();
1454 case TokenType
.BREAK
: return parse_break_statement ();
1455 case TokenType
.CONTINUE
: return parse_continue_statement ();
1456 case TokenType
.RETURN
: return parse_return_statement ();
1457 case TokenType
.YIELD
: return parse_yield_statement ();
1458 case TokenType
.THROW
: return parse_throw_statement ();
1459 case TokenType
.TRY
: return parse_try_statement ();
1460 case TokenType
.LOCK
: return parse_lock_statement ();
1461 case TokenType
.DELETE
: return parse_delete_statement ();
1462 default: return parse_expression_statement ();
1466 Block
parse_block () throws ParseError
{
1467 var begin
= get_location ();
1468 expect (TokenType
.OPEN_BRACE
);
1469 var block
= new
Block (get_src (begin
));
1470 parse_statements (block
);
1471 if (!accept (TokenType
.CLOSE_BRACE
)) {
1472 // only report error if it's not a secondary error
1473 if (context
.report
.get_errors () == 0) {
1474 Report
.error (get_current_src (), "expected `}'");
1478 block
.source_reference
.last_line
= get_current_src ().last_line
;
1479 block
.source_reference
.last_column
= get_current_src ().last_column
;
1484 Statement
parse_empty_statement () throws ParseError
{
1485 var begin
= get_location ();
1486 expect (TokenType
.SEMICOLON
);
1487 return new
EmptyStatement (get_src (begin
));
1490 void parse_local_variable_declarations (Block block
) throws ParseError
{
1491 DataType variable_type
;
1492 if (accept (TokenType
.VAR
)) {
1493 variable_type
= null;
1495 variable_type
= parse_type ();
1498 DataType type_copy
= null;
1499 if (variable_type
!= null) {
1500 type_copy
= variable_type
.copy ();
1502 var local
= parse_local_variable (type_copy
);
1503 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1504 } while (accept (TokenType
.COMMA
));
1505 expect (TokenType
.SEMICOLON
);
1508 LocalVariable
parse_local_variable (DataType? variable_type
) throws ParseError
{
1509 var begin
= get_location ();
1510 string id
= parse_identifier ();
1512 var type
= parse_inline_array_type (variable_type
);
1514 Expression initializer
= null;
1515 if (accept (TokenType
.ASSIGN
)) {
1516 initializer
= parse_expression ();
1518 return new
LocalVariable (type
, id
, initializer
, get_src (begin
));
1521 Statement
parse_expression_statement () throws ParseError
{
1522 var begin
= get_location ();
1523 var expr
= parse_statement_expression ();
1524 expect (TokenType
.SEMICOLON
);
1525 return new
ExpressionStatement (expr
, get_src (begin
));
1528 Expression
parse_statement_expression () throws ParseError
{
1529 // invocation expression, assignment,
1530 // or pre/post increment/decrement expression
1531 var expr
= parse_expression ();
1535 Statement
parse_if_statement () throws ParseError
{
1536 var begin
= get_location ();
1537 expect (TokenType
.IF
);
1538 expect (TokenType
.OPEN_PARENS
);
1539 var condition
= parse_expression ();
1540 expect (TokenType
.CLOSE_PARENS
);
1541 var src
= get_src (begin
);
1542 var true_stmt
= parse_embedded_statement ();
1543 Block false_stmt
= null;
1544 if (accept (TokenType
.ELSE
)) {
1545 false_stmt
= parse_embedded_statement ();
1547 return new
IfStatement (condition
, true_stmt
, false_stmt
, src
);
1550 Statement
parse_switch_statement () throws ParseError
{
1551 var begin
= get_location ();
1552 expect (TokenType
.SWITCH
);
1553 expect (TokenType
.OPEN_PARENS
);
1554 var condition
= parse_expression ();
1555 expect (TokenType
.CLOSE_PARENS
);
1556 var stmt
= new
SwitchStatement (condition
, get_src (begin
));
1557 expect (TokenType
.OPEN_BRACE
);
1558 while (current () != TokenType
.CLOSE_BRACE
) {
1559 var section
= new
SwitchSection (get_src (begin
));
1561 if (accept (TokenType
.CASE
)) {
1562 section
.add_label (new
SwitchLabel (parse_expression (), get_src (begin
)));
1564 expect (TokenType
.DEFAULT
);
1565 section
.add_label (new SwitchLabel
.with_default (get_src (begin
)));
1567 expect (TokenType
.COLON
);
1568 } while (current () == TokenType
.CASE
|| current () == TokenType
.DEFAULT
);
1569 parse_statements (section
);
1570 stmt
.add_section (section
);
1572 expect (TokenType
.CLOSE_BRACE
);
1576 Statement
parse_while_statement () throws ParseError
{
1577 var begin
= get_location ();
1578 expect (TokenType
.WHILE
);
1579 expect (TokenType
.OPEN_PARENS
);
1580 var condition
= parse_expression ();
1581 expect (TokenType
.CLOSE_PARENS
);
1582 var body
= parse_embedded_statement ();
1583 return new
WhileStatement (condition
, body
, get_src (begin
));
1586 Statement
parse_do_statement () throws ParseError
{
1587 var begin
= get_location ();
1588 expect (TokenType
.DO
);
1589 var body
= parse_embedded_statement ();
1590 expect (TokenType
.WHILE
);
1591 expect (TokenType
.OPEN_PARENS
);
1592 var condition
= parse_expression ();
1593 expect (TokenType
.CLOSE_PARENS
);
1594 expect (TokenType
.SEMICOLON
);
1595 return new
DoStatement (body
, condition
, get_src (begin
));
1598 Statement
parse_for_statement () throws ParseError
{
1599 var begin
= get_location ();
1601 expect (TokenType
.FOR
);
1602 expect (TokenType
.OPEN_PARENS
);
1603 var initializer_list
= new ArrayList
<Expression
> ();
1604 if (!accept (TokenType
.SEMICOLON
)) {
1606 switch (current ()) {
1610 case TokenType
.OP_INC
:
1611 case TokenType
.OP_DEC
:
1615 is_expr
= is_expression ();
1621 initializer_list
.add (parse_statement_expression ());
1622 } while (accept (TokenType
.COMMA
));
1624 block
= new
Block (get_src (begin
));
1625 DataType variable_type
;
1626 if (accept (TokenType
.VAR
)) {
1627 variable_type
= null;
1629 variable_type
= parse_type ();
1631 var local
= parse_local_variable (variable_type
);
1632 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1634 expect (TokenType
.SEMICOLON
);
1636 Expression condition
= null;
1637 if (current () != TokenType
.SEMICOLON
) {
1638 condition
= parse_expression ();
1640 expect (TokenType
.SEMICOLON
);
1641 var iterator_list
= new ArrayList
<Expression
> ();
1642 if (current () != TokenType
.CLOSE_PARENS
) {
1644 iterator_list
.add (parse_statement_expression ());
1645 } while (accept (TokenType
.COMMA
));
1647 expect (TokenType
.CLOSE_PARENS
);
1648 var src
= get_src (begin
);
1649 var body
= parse_embedded_statement ();
1650 var stmt
= new
ForStatement (condition
, body
, src
);
1651 foreach (Expression init
in initializer_list
) {
1652 stmt
.add_initializer (init
);
1654 foreach (Expression iter
in iterator_list
) {
1655 stmt
.add_iterator (iter
);
1657 if (block
!= null) {
1658 block
.add_statement (stmt
);
1665 Statement
parse_foreach_statement () throws ParseError
{
1666 var begin
= get_location ();
1667 expect (TokenType
.FOREACH
);
1668 expect (TokenType
.OPEN_PARENS
);
1669 DataType type
= null;
1670 if (!accept (TokenType
.VAR
)) {
1671 type
= parse_type ();
1673 string id
= parse_identifier ();
1674 expect (TokenType
.IN
);
1675 var collection
= parse_expression ();
1676 expect (TokenType
.CLOSE_PARENS
);
1677 var src
= get_src (begin
);
1678 var body
= parse_embedded_statement ();
1679 return new
ForeachStatement (type
, id
, collection
, body
, src
);
1682 Statement
parse_break_statement () throws ParseError
{
1683 var begin
= get_location ();
1684 expect (TokenType
.BREAK
);
1685 expect (TokenType
.SEMICOLON
);
1686 return new
BreakStatement (get_src (begin
));
1689 Statement
parse_continue_statement () throws ParseError
{
1690 var begin
= get_location ();
1691 expect (TokenType
.CONTINUE
);
1692 expect (TokenType
.SEMICOLON
);
1693 return new
ContinueStatement (get_src (begin
));
1696 Statement
parse_return_statement () throws ParseError
{
1697 var begin
= get_location ();
1698 expect (TokenType
.RETURN
);
1699 Expression expr
= null;
1700 if (current () != TokenType
.SEMICOLON
) {
1701 expr
= parse_expression ();
1703 expect (TokenType
.SEMICOLON
);
1704 return new
ReturnStatement (expr
, get_src (begin
));
1707 Statement
parse_yield_statement () throws ParseError
{
1708 var begin
= get_location ();
1709 expect (TokenType
.YIELD
);
1710 if (current () != TokenType
.SEMICOLON
&& current () != TokenType
.RETURN
) {
1713 return parse_expression_statement ();
1715 Expression expr
= null;
1716 if (accept (TokenType
.RETURN
)) {
1717 expr
= parse_expression ();
1719 expect (TokenType
.SEMICOLON
);
1720 return new
YieldStatement (expr
, get_src (begin
));
1723 Statement
parse_throw_statement () throws ParseError
{
1724 var begin
= get_location ();
1725 expect (TokenType
.THROW
);
1726 var expr
= parse_expression ();
1727 expect (TokenType
.SEMICOLON
);
1728 return new
ThrowStatement (expr
, get_src (begin
));
1731 Statement
parse_try_statement () throws ParseError
{
1732 var begin
= get_location ();
1733 expect (TokenType
.TRY
);
1734 var try_block
= parse_block ();
1735 Block finally_clause
= null;
1736 var catch_clauses
= new ArrayList
<CatchClause
> ();
1737 if (current () == TokenType
.CATCH
) {
1738 parse_catch_clauses (catch_clauses
);
1739 if (current () == TokenType
.FINALLY
) {
1740 finally_clause
= parse_finally_clause ();
1743 finally_clause
= parse_finally_clause ();
1745 var stmt
= new
TryStatement (try_block
, finally_clause
, get_src (begin
));
1746 foreach (CatchClause clause
in catch_clauses
) {
1747 stmt
.add_catch_clause (clause
);
1752 void parse_catch_clauses (List
<CatchClause
> catch_clauses
) throws ParseError
{
1753 while (accept (TokenType
.CATCH
)) {
1754 var begin
= get_location ();
1755 DataType type
= null;
1757 if (accept (TokenType
.OPEN_PARENS
)) {
1758 type
= parse_type ();
1759 id
= parse_identifier ();
1760 expect (TokenType
.CLOSE_PARENS
);
1762 var block
= parse_block ();
1763 catch_clauses
.add (new
CatchClause (type
, id
, block
, get_src (begin
)));
1767 Block
parse_finally_clause () throws ParseError
{
1768 expect (TokenType
.FINALLY
);
1769 var block
= parse_block ();
1773 Statement
parse_lock_statement () throws ParseError
{
1774 var begin
= get_location ();
1775 expect (TokenType
.LOCK
);
1776 expect (TokenType
.OPEN_PARENS
);
1777 var expr
= parse_expression ();
1778 expect (TokenType
.CLOSE_PARENS
);
1779 var stmt
= parse_embedded_statement ();
1780 return new
LockStatement (expr
, stmt
, get_src (begin
));
1783 Statement
parse_delete_statement () throws ParseError
{
1784 var begin
= get_location ();
1785 expect (TokenType
.DELETE
);
1786 var expr
= parse_expression ();
1787 expect (TokenType
.SEMICOLON
);
1788 return new
DeleteStatement (expr
, get_src (begin
));
1791 List
<Attribute
>?
parse_attributes () throws ParseError
{
1792 if (current () != TokenType
.OPEN_BRACKET
) {
1795 var attrs
= new ArrayList
<Attribute
> ();
1796 while (accept (TokenType
.OPEN_BRACKET
)) {
1798 var begin
= get_location ();
1799 string id
= parse_identifier ();
1800 var attr
= new
Attribute (id
, get_src (begin
));
1801 if (accept (TokenType
.OPEN_PARENS
)) {
1802 if (current () != TokenType
.CLOSE_PARENS
) {
1804 id
= parse_identifier ();
1805 expect (TokenType
.ASSIGN
);
1806 var expr
= parse_expression ();
1807 attr
.add_argument (id
, expr
);
1808 } while (accept (TokenType
.COMMA
));
1810 expect (TokenType
.CLOSE_PARENS
);
1813 } while (accept (TokenType
.COMMA
));
1814 expect (TokenType
.CLOSE_BRACKET
);
1819 void set_attributes (CodeNode node
, List
<Attribute
>? attributes
) {
1820 if (attributes
!= null) {
1821 foreach (Attribute attr
in (List
<Attribute
>) attributes
) {
1822 node
.attributes
.append (attr
);
1827 Symbol
parse_declaration () throws ParseError
{
1828 comment
= scanner
.pop_comment ();
1829 var attrs
= parse_attributes ();
1831 var begin
= get_location ();
1833 TokenType last_keyword
= current ();
1835 while (is_declaration_keyword (current ())) {
1836 last_keyword
= current ();
1840 switch (current ()) {
1841 case TokenType
.CONSTRUCT
:
1842 if (context
.profile
== Profile
.GOBJECT
) {
1844 return parse_constructor_declaration (attrs
);
1847 case TokenType
.TILDE
:
1849 return parse_destructor_declaration (attrs
);
1852 switch (current ()) {
1853 case TokenType
.OPEN_BRACE
:
1854 case TokenType
.SEMICOLON
:
1855 case TokenType
.COLON
:
1857 switch (last_keyword
) {
1858 case TokenType
.CLASS
: return parse_class_declaration (attrs
);
1859 case TokenType
.ENUM
: return parse_enum_declaration (attrs
);
1860 case TokenType
.ERRORDOMAIN
: return parse_errordomain_declaration (attrs
);
1861 case TokenType
.INTERFACE
: return parse_interface_declaration (attrs
);
1862 case TokenType
.NAMESPACE
: return parse_namespace_declaration (attrs
);
1863 case TokenType
.STRUCT
: return parse_struct_declaration (attrs
);
1867 case TokenType
.OPEN_PARENS
:
1869 return parse_creation_method_declaration (attrs
);
1871 skip_type (); // might contain type parameter list
1872 switch (current ()) {
1873 case TokenType
.OPEN_PARENS
:
1875 switch (last_keyword
) {
1876 case TokenType
.DELEGATE
: return parse_delegate_declaration (attrs
);
1877 case TokenType
.SIGNAL
: return parse_signal_declaration (attrs
);
1878 default: return parse_method_declaration (attrs
);
1880 case TokenType
.ASSIGN
:
1881 case TokenType
.SEMICOLON
:
1883 switch (last_keyword
) {
1884 case TokenType
.CONST
: return parse_constant_declaration (attrs
);
1885 default: return parse_field_declaration (attrs
);
1887 case TokenType
.OPEN_BRACE
:
1888 case TokenType
.THROWS
:
1890 return parse_property_declaration (attrs
);
1901 throw new ParseError
.SYNTAX (get_error ("expected declaration"));
1904 void parse_declarations (Symbol parent
, bool root
= false) throws ParseError
{
1906 expect (TokenType
.OPEN_BRACE
);
1908 while (current () != TokenType
.CLOSE_BRACE
&& current () != TokenType
.EOF
) {
1910 if (parent is Namespace
) {
1911 parse_namespace_member ((Namespace
) parent
);
1912 } else if (parent is Class
) {
1913 parse_class_member ((Class
) parent
);
1914 } else if (parent is Struct
) {
1915 parse_struct_member ((Struct
) parent
);
1916 } else if (parent is Interface
) {
1917 parse_interface_member ((Interface
) parent
);
1919 } catch (ParseError e
) {
1923 if (r
== RecoveryState
.STATEMENT_BEGIN
) {
1929 if (r
== RecoveryState
.EOF
) {
1935 if (!accept (TokenType
.CLOSE_BRACE
)) {
1936 // only report error if it's not a secondary error
1937 if (context
.report
.get_errors () == 0) {
1938 Report
.error (get_current_src (), "expected `}'");
1944 enum RecoveryState
{
1950 RecoveryState
recover () {
1951 while (current () != TokenType
.EOF
) {
1952 switch (current ()) {
1953 case TokenType
.ABSTRACT
:
1954 case TokenType
.CLASS
:
1955 case TokenType
.CONST
:
1956 case TokenType
.CONSTRUCT
:
1957 case TokenType
.DELEGATE
:
1958 case TokenType
.ENUM
:
1959 case TokenType
.ERRORDOMAIN
:
1960 case TokenType
.EXTERN
:
1961 case TokenType
.INLINE
:
1962 case TokenType
.INTERFACE
:
1963 case TokenType
.INTERNAL
:
1964 case TokenType
.NAMESPACE
:
1966 case TokenType
.OVERRIDE
:
1967 case TokenType
.PRIVATE
:
1968 case TokenType
.PROTECTED
:
1969 case TokenType
.PUBLIC
:
1970 case TokenType
.SIGNAL
:
1971 case TokenType
.STATIC
:
1972 case TokenType
.STRUCT
:
1973 case TokenType
.VIRTUAL
:
1974 case TokenType
.VOLATILE
:
1975 return RecoveryState
.DECLARATION_BEGIN
;
1976 case TokenType
.BREAK
:
1977 case TokenType
.CONTINUE
:
1978 case TokenType
.DELETE
:
1981 case TokenType
.FOREACH
:
1983 case TokenType
.LOCK
:
1984 case TokenType
.RETURN
:
1985 case TokenType
.SWITCH
:
1986 case TokenType
.THROW
:
1989 case TokenType
.WHILE
:
1990 case TokenType
.YIELD
:
1991 return RecoveryState
.STATEMENT_BEGIN
;
1997 return RecoveryState
.EOF
;
2000 Namespace
parse_namespace_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2001 var begin
= get_location ();
2002 expect (TokenType
.NAMESPACE
);
2003 var sym
= parse_symbol_name ();
2004 var ns
= new
Namespace (sym
.name
, get_src (begin
));
2005 if (comment
!= null) {
2006 ns
.add_comment (comment
);
2010 set_attributes (ns
, attrs
);
2012 expect (TokenType
.OPEN_BRACE
);
2014 var old_using_directives
= scanner
.source_file
.current_using_directives
;
2015 parse_using_directives (ns
);
2017 parse_declarations (ns
, true);
2019 scanner
.source_file
.current_using_directives
= old_using_directives
;
2021 if (!accept (TokenType
.CLOSE_BRACE
)) {
2022 // only report error if it's not a secondary error
2023 if (context
.report
.get_errors () == 0) {
2024 Report
.error (get_current_src (), "expected `}'");
2028 Namespace result
= ns
;
2029 while (sym
.inner
!= null) {
2031 ns
= new
Namespace (sym
.name
, result
.source_reference
);
2032 ns
.add_namespace ((Namespace
) result
);
2038 void parse_namespace_member (Namespace ns
) throws ParseError
{
2039 var sym
= parse_declaration ();
2041 if (sym is Namespace
) {
2042 ns
.add_namespace ((Namespace
) sym
);
2043 } else if (sym is Class
) {
2044 ns
.add_class ((Class
) sym
);
2045 } else if (sym is Interface
) {
2046 ns
.add_interface ((Interface
) sym
);
2047 } else if (sym is Struct
) {
2048 ns
.add_struct ((Struct
) sym
);
2049 } else if (sym is Enum
) {
2050 ns
.add_enum ((Enum
) sym
);
2051 } else if (sym is ErrorDomain
) {
2052 ns
.add_error_domain ((ErrorDomain
) sym
);
2053 } else if (sym is Delegate
) {
2054 ns
.add_delegate ((Delegate
) sym
);
2055 } else if (sym is Method
) {
2056 var method
= (Method
) sym
;
2057 if (method
.binding
== MemberBinding
.INSTANCE
) {
2058 // default to static member binding
2059 method
.binding
= MemberBinding
.STATIC
;
2061 ns
.add_method (method
);
2062 } else if (sym is Field
) {
2063 var field
= (Field
) sym
;
2064 if (field
.binding
== MemberBinding
.INSTANCE
) {
2065 // default to static member binding
2066 field
.binding
= MemberBinding
.STATIC
;
2068 ns
.add_field (field
);
2069 } else if (sym is Constant
) {
2070 ns
.add_constant ((Constant
) sym
);
2072 Report
.error (sym
.source_reference
, "unexpected declaration in namespace");
2074 scanner
.source_file
.add_node (sym
);
2077 void parse_using_directives (Namespace ns
) throws ParseError
{
2078 while (accept (TokenType
.USING
)) {
2080 var begin
= get_location ();
2081 var sym
= parse_symbol_name ();
2082 var ns_ref
= new
UsingDirective (sym
, get_src (begin
));
2083 scanner
.source_file
.add_using_directive (ns_ref
);
2084 ns
.add_using_directive (ns_ref
);
2085 } while (accept (TokenType
.COMMA
));
2086 expect (TokenType
.SEMICOLON
);
2090 Symbol
parse_class_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2091 var begin
= get_location ();
2092 var access
= parse_access_modifier ();
2093 var flags
= parse_type_declaration_modifiers ();
2094 expect (TokenType
.CLASS
);
2095 var sym
= parse_symbol_name ();
2096 var type_param_list
= parse_type_parameter_list ();
2097 var base_types
= new ArrayList
<DataType
> ();
2098 if (accept (TokenType
.COLON
)) {
2100 base_types
.add (parse_type ());
2101 } while (accept (TokenType
.COMMA
));
2104 var cl
= new
Class (sym
.name
, get_src (begin
), comment
);
2106 if (ModifierFlags
.ABSTRACT
in flags
) {
2107 cl
.is_abstract
= true;
2109 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2112 set_attributes (cl
, attrs
);
2113 foreach (TypeParameter type_param
in type_param_list
) {
2114 cl
.add_type_parameter (type_param
);
2116 foreach (DataType base_type
in base_types
) {
2117 cl
.add_base_type (base_type
);
2120 parse_declarations (cl
);
2122 // ensure there is always a default construction method
2123 if (!scanner
.source_file
.external_package
2124 && cl
.default_construction_method
== null) {
2125 var m
= new
CreationMethod (cl
.name
, null, cl
.source_reference
);
2126 m
.access
= SymbolAccessibility
.PUBLIC
;
2127 m
.body
= new
Block (cl
.source_reference
);
2132 while (sym
.inner
!= null) {
2134 var ns
= new
Namespace (sym
.name
, cl
.source_reference
);
2135 if (result is Namespace
) {
2136 ns
.add_namespace ((Namespace
) result
);
2138 ns
.add_class ((Class
) result
);
2139 scanner
.source_file
.add_node (result
);
2146 void parse_class_member (Class cl
) throws ParseError
{
2147 var sym
= parse_declaration ();
2149 cl
.add_class ((Class
) sym
);
2150 } else if (sym is Struct
) {
2151 cl
.add_struct ((Struct
) sym
);
2152 } else if (sym is Enum
) {
2153 cl
.add_enum ((Enum
) sym
);
2154 } else if (sym is Delegate
) {
2155 cl
.add_delegate ((Delegate
) sym
);
2156 } else if (sym is Method
) {
2157 cl
.add_method ((Method
) sym
);
2158 } else if (sym is Signal
) {
2159 cl
.add_signal ((Signal
) sym
);
2160 } else if (sym is Field
) {
2161 cl
.add_field ((Field
) sym
);
2162 } else if (sym is Constant
) {
2163 cl
.add_constant ((Constant
) sym
);
2164 } else if (sym is Property
) {
2165 cl
.add_property ((Property
) sym
);
2166 } else if (sym is Constructor
) {
2167 var c
= (Constructor
) sym
;
2168 if (c
.binding
== MemberBinding
.INSTANCE
) {
2170 } else if (c
.binding
== MemberBinding
.CLASS
) {
2171 cl
.class_constructor
= c
;
2173 cl
.static_constructor
= c
;
2175 } else if (sym is Destructor
) {
2176 var d
= (Destructor
) sym
;
2177 if (d
.binding
== MemberBinding
.STATIC
) {
2178 cl
.static_destructor
= (Destructor
) d
;
2179 } else if (d
.binding
== MemberBinding
.CLASS
) {
2180 cl
.class_destructor
= (Destructor
) d
;
2182 cl
.destructor
= (Destructor
) d
;
2185 Report
.error (sym
.source_reference
, "unexpected declaration in class");
2189 Constant
parse_constant_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2190 var begin
= get_location ();
2191 var access
= parse_access_modifier ();
2192 var flags
= parse_member_declaration_modifiers ();
2193 expect (TokenType
.CONST
);
2194 var type
= parse_type (false);
2195 string id
= parse_identifier ();
2197 type
= parse_inline_array_type (type
);
2199 Expression initializer
= null;
2200 if (accept (TokenType
.ASSIGN
)) {
2201 initializer
= parse_expression ();
2203 expect (TokenType
.SEMICOLON
);
2205 // constant arrays don't own their element
2206 var array_type
= type as ArrayType
;
2207 if (array_type
!= null) {
2208 array_type
.element_type
.value_owned
= false;
2211 var c
= new
Constant (id
, type
, initializer
, get_src (begin
), comment
);
2213 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2216 if (ModifierFlags
.NEW
in flags
) {
2219 set_attributes (c
, attrs
);
2223 Field
parse_field_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2224 var begin
= get_location ();
2225 var access
= parse_access_modifier ();
2226 var flags
= parse_member_declaration_modifiers ();
2227 var type
= parse_type ();
2228 string id
= parse_identifier ();
2230 type
= parse_inline_array_type (type
);
2232 var f
= new
Field (id
, type
, null, get_src (begin
), comment
);
2234 set_attributes (f
, attrs
);
2235 if (ModifierFlags
.STATIC
in flags
) {
2236 f
.binding
= MemberBinding
.STATIC
;
2237 } else if (ModifierFlags
.CLASS
in flags
) {
2238 f
.binding
= MemberBinding
.CLASS
;
2240 if (ModifierFlags
.ABSTRACT
in flags
2241 || ModifierFlags
.VIRTUAL
in flags
2242 || ModifierFlags
.OVERRIDE
in flags
) {
2243 Report
.error (f
.source_reference
, "abstract, virtual, and override modifiers are not applicable to fields");
2245 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2248 if (ModifierFlags
.NEW
in flags
) {
2251 if (accept (TokenType
.ASSIGN
)) {
2252 f
.initializer
= parse_expression ();
2254 expect (TokenType
.SEMICOLON
);
2258 InitializerList
parse_initializer () throws ParseError
{
2259 var begin
= get_location ();
2260 expect (TokenType
.OPEN_BRACE
);
2261 var initializer
= new
InitializerList (get_src (begin
));
2262 if (current () != TokenType
.CLOSE_BRACE
) {
2264 var init
= parse_argument ();
2265 initializer
.append (init
);
2266 } while (accept (TokenType
.COMMA
));
2268 expect (TokenType
.CLOSE_BRACE
);
2272 Method
parse_method_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2273 var begin
= get_location ();
2274 var access
= parse_access_modifier ();
2275 var flags
= parse_member_declaration_modifiers ();
2276 var type
= parse_type ();
2277 string id
= parse_identifier ();
2278 var type_param_list
= parse_type_parameter_list ();
2279 var method
= new
Method (id
, type
, get_src (begin
), comment
);
2280 method
.access
= access
;
2281 set_attributes (method
, attrs
);
2282 foreach (TypeParameter type_param
in type_param_list
) {
2283 method
.add_type_parameter (type_param
);
2285 if (ModifierFlags
.STATIC
in flags
) {
2286 method
.binding
= MemberBinding
.STATIC
;
2287 } else if (ModifierFlags
.CLASS
in flags
) {
2288 method
.binding
= MemberBinding
.CLASS
;
2290 if (ModifierFlags
.ASYNC
in flags
) {
2291 method
.coroutine
= true;
2293 if (ModifierFlags
.NEW
in flags
) {
2294 method
.hides
= true;
2297 if (method
.binding
== MemberBinding
.INSTANCE
) {
2298 if (ModifierFlags
.ABSTRACT
in flags
) {
2299 method
.is_abstract
= true;
2301 if (ModifierFlags
.VIRTUAL
in flags
) {
2302 method
.is_virtual
= true;
2304 if (ModifierFlags
.OVERRIDE
in flags
) {
2305 method
.overrides
= true;
2307 if ((method
.is_abstract
&& method
.is_virtual
)
2308 || (method
.is_abstract
&& method
.overrides
)
2309 || (method
.is_virtual
&& method
.overrides
)) {
2310 throw new ParseError
.SYNTAX (get_error ("only one of `abstract', `virtual', or `override' may be specified"));
2313 if (ModifierFlags
.ABSTRACT
in flags
2314 || ModifierFlags
.VIRTUAL
in flags
2315 || ModifierFlags
.OVERRIDE
in flags
) {
2316 throw new ParseError
.SYNTAX (get_error ("the modifiers `abstract', `virtual', and `override' are not valid for static methods"));
2320 if (ModifierFlags
.INLINE
in flags
) {
2321 method
.is_inline
= true;
2323 if (ModifierFlags
.EXTERN
in flags
) {
2324 method
.external
= true;
2326 expect (TokenType
.OPEN_PARENS
);
2327 if (current () != TokenType
.CLOSE_PARENS
) {
2329 var param
= parse_parameter ();
2330 method
.add_parameter (param
);
2331 } while (accept (TokenType
.COMMA
));
2333 expect (TokenType
.CLOSE_PARENS
);
2334 if (accept (TokenType
.THROWS
)) {
2336 method
.add_error_type (parse_type ());
2337 } while (accept (TokenType
.COMMA
));
2339 while (accept (TokenType
.REQUIRES
)) {
2340 expect (TokenType
.OPEN_PARENS
);
2341 method
.add_precondition (parse_expression ());
2342 expect (TokenType
.CLOSE_PARENS
);
2344 while (accept (TokenType
.ENSURES
)) {
2345 expect (TokenType
.OPEN_PARENS
);
2346 method
.add_postcondition (parse_expression ());
2347 expect (TokenType
.CLOSE_PARENS
);
2349 if (!accept (TokenType
.SEMICOLON
)) {
2350 method
.body
= parse_block ();
2351 } else if (scanner
.source_file
.external_package
) {
2352 method
.external
= true;
2357 Property
parse_property_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2358 var begin
= get_location ();
2359 var access
= parse_access_modifier ();
2360 var flags
= parse_member_declaration_modifiers ();
2361 var type
= parse_type ();
2363 bool getter_owned
= false;
2364 if (accept (TokenType
.HASH
)) {
2365 if (!context
.deprecated
) {
2366 Report
.warning (get_last_src (), "deprecated syntax, use `owned` modifier before `get'");
2368 getter_owned
= true;
2371 string id
= parse_identifier ();
2372 var prop
= new
Property (id
, type
, null, null, get_src (begin
), comment
);
2373 prop
.access
= access
;
2374 set_attributes (prop
, attrs
);
2375 if (ModifierFlags
.STATIC
in flags
) {
2376 prop
.binding
= MemberBinding
.STATIC
;
2377 } else if (ModifierFlags
.CLASS
in flags
) {
2378 prop
.binding
= MemberBinding
.CLASS
;
2380 if (ModifierFlags
.ABSTRACT
in flags
) {
2381 prop
.is_abstract
= true;
2383 if (ModifierFlags
.VIRTUAL
in flags
) {
2384 prop
.is_virtual
= true;
2386 if (ModifierFlags
.OVERRIDE
in flags
) {
2387 prop
.overrides
= true;
2389 if (ModifierFlags
.NEW
in flags
) {
2392 if (ModifierFlags
.ASYNC
in flags
) {
2393 Report
.error (prop
.source_reference
, "async properties are not supported yet");
2395 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2396 prop
.external
= true;
2398 if (accept (TokenType
.THROWS
)) {
2400 prop
.add_error_type (parse_type ());
2401 } while (accept (TokenType
.COMMA
));
2402 Report
.error (prop
.source_reference
, "properties throwing errors are not supported yet");
2404 expect (TokenType
.OPEN_BRACE
);
2405 while (current () != TokenType
.CLOSE_BRACE
) {
2406 if (accept (TokenType
.DEFAULT
)) {
2407 if (prop
.default_expression
!= null) {
2408 throw new ParseError
.SYNTAX (get_error ("property default value already defined"));
2410 expect (TokenType
.ASSIGN
);
2411 prop
.default_expression
= parse_expression ();
2412 expect (TokenType
.SEMICOLON
);
2414 var accessor_begin
= get_location ();
2415 var accessor_attrs
= parse_attributes ();
2416 var accessor_access
= parse_access_modifier (SymbolAccessibility
.PUBLIC
);
2418 var value_type
= type
.copy ();
2419 value_type
.value_owned
= accept (TokenType
.OWNED
);
2421 if (accept (TokenType
.GET
)) {
2422 if (prop
.get_accessor
!= null) {
2423 throw new ParseError
.SYNTAX (get_error ("property get accessor already defined"));
2427 value_type
.value_owned
= true;
2431 if (!accept (TokenType
.SEMICOLON
)) {
2432 block
= parse_block ();
2433 prop
.external
= false;
2435 prop
.get_accessor
= new
PropertyAccessor (true, false, false, value_type
, block
, get_src (accessor_begin
));
2436 set_attributes (prop
.get_accessor
, accessor_attrs
);
2437 prop
.get_accessor
.access
= accessor_access
;
2439 bool writable
, _construct
;
2440 if (accept (TokenType
.SET
)) {
2442 _construct
= (context
.profile
== Profile
.GOBJECT
) && accept (TokenType
.CONSTRUCT
);
2443 } else if (context
.profile
== Profile
.GOBJECT
&& accept (TokenType
.CONSTRUCT
)) {
2445 writable
= accept (TokenType
.SET
);
2447 throw new ParseError
.SYNTAX (get_error ("expected get, set, or construct"));
2449 if (prop
.set_accessor
!= null) {
2450 throw new ParseError
.SYNTAX (get_error ("property set accessor already defined"));
2453 if (!accept (TokenType
.SEMICOLON
)) {
2454 block
= parse_block ();
2455 prop
.external
= false;
2457 prop
.set_accessor
= new
PropertyAccessor (false, writable
, _construct
, value_type
, block
, get_src (accessor_begin
));
2458 set_attributes (prop
.set_accessor
, accessor_attrs
);
2459 prop
.set_accessor
.access
= accessor_access
;
2463 expect (TokenType
.CLOSE_BRACE
);
2465 if (!prop
.is_abstract
&& !prop
.external
) {
2466 bool empty_get
= (prop
.get_accessor
!= null && prop
.get_accessor
.body
== null);
2467 bool empty_set
= (prop
.set_accessor
!= null && prop
.set_accessor
.body
== null);
2469 if (empty_get
!= empty_set
) {
2471 Report
.error (prop
.source_reference
, "property getter must have a body");
2472 } else if (empty_set
) {
2473 Report
.error (prop
.source_reference
, "property setter must have a body");
2478 if (empty_get
&& empty_set
) {
2479 /* automatic property accessor body generation */
2480 var field_type
= prop
.property_type
.copy ();
2481 prop
.field
= new
Field ("_%s".printf (prop
.name
), field_type
, prop
.default_expression
, prop
.source_reference
);
2482 prop
.field
.access
= SymbolAccessibility
.PRIVATE
;
2483 prop
.field
.binding
= prop
.binding
;
2490 Signal
parse_signal_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2491 var begin
= get_location ();
2492 var access
= parse_access_modifier ();
2493 var flags
= parse_member_declaration_modifiers ();
2494 expect (TokenType
.SIGNAL
);
2495 var type
= parse_type ();
2496 string id
= parse_identifier ();
2497 var sig
= new
Signal (id
, type
, get_src (begin
), comment
);
2498 sig
.access
= access
;
2499 set_attributes (sig
, attrs
);
2500 if (ModifierFlags
.STATIC
in flags
) {
2501 throw new ParseError
.SYNTAX (get_error ("`static' modifier not allowed on signals"));
2502 } else if (ModifierFlags
.CLASS
in flags
) {
2503 throw new ParseError
.SYNTAX (get_error ("`class' modifier not allowed on signals"));
2505 if (ModifierFlags
.VIRTUAL
in flags
) {
2506 sig
.is_virtual
= true;
2508 if (ModifierFlags
.NEW
in flags
) {
2511 expect (TokenType
.OPEN_PARENS
);
2512 if (current () != TokenType
.CLOSE_PARENS
) {
2514 var param
= parse_parameter ();
2515 sig
.add_parameter (param
);
2516 } while (accept (TokenType
.COMMA
));
2518 expect (TokenType
.CLOSE_PARENS
);
2519 if (!accept (TokenType
.SEMICOLON
)) {
2520 sig
.body
= parse_block ();
2526 Constructor
parse_constructor_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2527 var begin
= get_location ();
2528 var flags
= parse_member_declaration_modifiers ();
2529 expect (TokenType
.CONSTRUCT
);
2530 if (ModifierFlags
.NEW
in flags
) {
2531 throw new ParseError
.SYNTAX (get_error ("`new' modifier not allowed on constructor"));
2533 var c
= new
Constructor (get_src (begin
));
2534 if (ModifierFlags
.STATIC
in flags
) {
2535 c
.binding
= MemberBinding
.STATIC
;
2536 } else if (ModifierFlags
.CLASS
in flags
) {
2537 c
.binding
= MemberBinding
.CLASS
;
2539 c
.body
= parse_block ();
2543 Destructor
parse_destructor_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2544 var begin
= get_location ();
2545 var flags
= parse_member_declaration_modifiers ();
2546 expect (TokenType
.TILDE
);
2547 parse_identifier ();
2548 expect (TokenType
.OPEN_PARENS
);
2549 expect (TokenType
.CLOSE_PARENS
);
2550 if (ModifierFlags
.NEW
in flags
) {
2551 throw new ParseError
.SYNTAX (get_error ("`new' modifier not allowed on destructor"));
2553 var d
= new
Destructor (get_src (begin
));
2554 if (ModifierFlags
.STATIC
in flags
) {
2555 d
.binding
= MemberBinding
.STATIC
;
2556 } else if (ModifierFlags
.CLASS
in flags
) {
2557 d
.binding
= MemberBinding
.CLASS
;
2559 d
.body
= parse_block ();
2563 Symbol
parse_struct_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2564 var begin
= get_location ();
2565 var access
= parse_access_modifier ();
2566 var flags
= parse_type_declaration_modifiers ();
2567 expect (TokenType
.STRUCT
);
2568 var sym
= parse_symbol_name ();
2569 var type_param_list
= parse_type_parameter_list ();
2570 DataType base_type
= null;
2571 if (accept (TokenType
.COLON
)) {
2572 base_type
= parse_type ();
2574 var st
= new
Struct (sym
.name
, get_src (begin
), comment
);
2576 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2579 set_attributes (st
, attrs
);
2580 foreach (TypeParameter type_param
in type_param_list
) {
2581 st
.add_type_parameter (type_param
);
2583 if (base_type
!= null) {
2584 st
.base_type
= base_type
;
2587 parse_declarations (st
);
2590 while (sym
.inner
!= null) {
2593 var ns
= new
Namespace (sym
.name
, st
.source_reference
);
2594 if (result is Namespace
) {
2595 ns
.add_namespace ((Namespace
) result
);
2597 ns
.add_struct ((Struct
) result
);
2598 scanner
.source_file
.add_node (result
);
2605 void parse_struct_member (Struct st
) throws ParseError
{
2606 var sym
= parse_declaration ();
2607 if (sym is Method
) {
2608 st
.add_method ((Method
) sym
);
2609 } else if (sym is Field
) {
2610 st
.add_field ((Field
) sym
);
2611 } else if (sym is Constant
) {
2612 st
.add_constant ((Constant
) sym
);
2613 } else if (sym is Property
) {
2614 st
.add_property ((Property
) sym
);
2616 Report
.error (sym
.source_reference
, "unexpected declaration in struct");
2620 Symbol
parse_interface_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2621 var begin
= get_location ();
2622 var access
= parse_access_modifier ();
2623 var flags
= parse_type_declaration_modifiers ();
2624 expect (TokenType
.INTERFACE
);
2625 var sym
= parse_symbol_name ();
2626 var type_param_list
= parse_type_parameter_list ();
2627 var base_types
= new ArrayList
<DataType
> ();
2628 if (accept (TokenType
.COLON
)) {
2630 var type
= parse_type ();
2631 base_types
.add (type
);
2632 } while (accept (TokenType
.COMMA
));
2634 var iface
= new
Interface (sym
.name
, get_src (begin
), comment
);
2635 iface
.access
= access
;
2636 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2637 iface
.external
= true;
2639 set_attributes (iface
, attrs
);
2640 foreach (TypeParameter type_param
in type_param_list
) {
2641 iface
.add_type_parameter (type_param
);
2643 foreach (DataType base_type
in base_types
) {
2644 iface
.add_prerequisite (base_type
);
2647 parse_declarations (iface
);
2649 Symbol result
= iface
;
2650 while (sym
.inner
!= null) {
2652 var ns
= new
Namespace (sym
.name
, iface
.source_reference
);
2653 if (result is Namespace
) {
2654 ns
.add_namespace ((Namespace
) result
);
2656 ns
.add_interface ((Interface
) result
);
2657 scanner
.source_file
.add_node (result
);
2664 void parse_interface_member (Interface iface
) throws ParseError
{
2665 var sym
= parse_declaration ();
2667 iface
.add_class ((Class
) sym
);
2668 } else if (sym is Struct
) {
2669 iface
.add_struct ((Struct
) sym
);
2670 } else if (sym is Enum
) {
2671 iface
.add_enum ((Enum
) sym
);
2672 } else if (sym is Delegate
) {
2673 iface
.add_delegate ((Delegate
) sym
);
2674 } else if (sym is Method
) {
2675 iface
.add_method ((Method
) sym
);
2676 } else if (sym is Signal
) {
2677 iface
.add_signal ((Signal
) sym
);
2678 } else if (sym is Field
) {
2679 iface
.add_field ((Field
) sym
);
2680 } else if (sym is Constant
) {
2681 iface
.add_constant ((Constant
) sym
);
2682 } else if (sym is Property
) {
2683 iface
.add_property ((Property
) sym
);
2685 Report
.error (sym
.source_reference
, "unexpected declaration in interface");
2689 Symbol
parse_enum_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2690 var begin
= get_location ();
2691 var access
= parse_access_modifier ();
2692 var flags
= parse_type_declaration_modifiers ();
2693 expect (TokenType
.ENUM
);
2694 var sym
= parse_symbol_name ();
2695 var en
= new
Enum (sym
.name
, get_src (begin
), comment
);
2697 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2700 set_attributes (en
, attrs
);
2702 expect (TokenType
.OPEN_BRACE
);
2704 if (current () == TokenType
.CLOSE_BRACE
2705 && en
.get_values ().size
> 0) {
2706 // allow trailing comma
2709 var value_attrs
= parse_attributes ();
2710 var value_begin
= get_location ();
2711 string id
= parse_identifier ();
2712 comment
= scanner
.pop_comment ();
2713 var ev
= new
EnumValue (id
, get_src (value_begin
), comment
);
2714 set_attributes (ev
, value_attrs
);
2715 if (accept (TokenType
.ASSIGN
)) {
2716 ev
.value
= parse_expression ();
2719 } while (accept (TokenType
.COMMA
));
2720 if (accept (TokenType
.SEMICOLON
)) {
2722 while (current () != TokenType
.CLOSE_BRACE
) {
2723 var member_sym
= parse_declaration ();
2724 if (member_sym is Method
) {
2725 en
.add_method ((Method
) member_sym
);
2727 Report
.error (member_sym
.source_reference
, "unexpected declaration in enum");
2731 expect (TokenType
.CLOSE_BRACE
);
2734 while (sym
.inner
!= null) {
2736 var ns
= new
Namespace (sym
.name
, en
.source_reference
);
2737 if (result is Namespace
) {
2738 ns
.add_namespace ((Namespace
) result
);
2740 ns
.add_enum ((Enum
) result
);
2741 scanner
.source_file
.add_node (result
);
2748 Symbol
parse_errordomain_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2749 var begin
= get_location ();
2750 var access
= parse_access_modifier ();
2751 var flags
= parse_type_declaration_modifiers ();
2752 expect (TokenType
.ERRORDOMAIN
);
2753 var sym
= parse_symbol_name ();
2754 var ed
= new
ErrorDomain (sym
.name
, get_src (begin
), comment
);
2756 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2759 set_attributes (ed
, attrs
);
2761 expect (TokenType
.OPEN_BRACE
);
2763 if (current () == TokenType
.CLOSE_BRACE
2764 && ed
.get_codes ().size
> 0) {
2765 // allow trailing comma
2768 var code_attrs
= parse_attributes ();
2769 var code_begin
= get_location ();
2770 string id
= parse_identifier ();
2771 comment
= scanner
.pop_comment ();
2772 var ec
= new
ErrorCode (id
, get_src (code_begin
), comment
);
2773 set_attributes (ec
, code_attrs
);
2774 if (accept (TokenType
.ASSIGN
)) {
2775 ec
.value
= parse_expression ();
2778 } while (accept (TokenType
.COMMA
));
2779 if (accept (TokenType
.SEMICOLON
)) {
2780 // errordomain methods
2781 while (current () != TokenType
.CLOSE_BRACE
) {
2782 var member_sym
= parse_declaration ();
2783 if (member_sym is Method
) {
2784 ed
.add_method ((Method
) member_sym
);
2786 Report
.error (member_sym
.source_reference
, "unexpected declaration in errordomain");
2790 expect (TokenType
.CLOSE_BRACE
);
2793 while (sym
.inner
!= null) {
2795 var ns
= new
Namespace (sym
.name
, ed
.source_reference
);
2796 if (result is Namespace
) {
2797 ns
.add_namespace ((Namespace
) result
);
2799 ns
.add_error_domain ((ErrorDomain
) result
);
2800 scanner
.source_file
.add_node (result
);
2807 SymbolAccessibility
parse_access_modifier (SymbolAccessibility default_access
= SymbolAccessibility
.PRIVATE
) {
2808 switch (current ()) {
2809 case TokenType
.PRIVATE
:
2811 return SymbolAccessibility
.PRIVATE
;
2812 case TokenType
.PROTECTED
:
2814 return SymbolAccessibility
.PROTECTED
;
2815 case TokenType
.INTERNAL
:
2817 return SymbolAccessibility
.INTERNAL
;
2818 case TokenType
.PUBLIC
:
2820 return SymbolAccessibility
.PUBLIC
;
2822 return default_access
;
2826 ModifierFlags
parse_type_declaration_modifiers () {
2827 ModifierFlags flags
= 0;
2829 switch (current ()) {
2830 case TokenType
.ABSTRACT
:
2832 flags
|= ModifierFlags
.ABSTRACT
;
2834 case TokenType
.EXTERN
:
2836 flags
|= ModifierFlags
.EXTERN
;
2838 case TokenType
.STATIC
:
2840 flags
|= ModifierFlags
.STATIC
;
2848 ModifierFlags
parse_member_declaration_modifiers () {
2849 ModifierFlags flags
= 0;
2851 switch (current ()) {
2852 case TokenType
.ABSTRACT
:
2854 flags
|= ModifierFlags
.ABSTRACT
;
2856 case TokenType
.ASYNC
:
2858 flags
|= ModifierFlags
.ASYNC
;
2860 case TokenType
.CLASS
:
2862 flags
|= ModifierFlags
.CLASS
;
2864 case TokenType
.EXTERN
:
2866 flags
|= ModifierFlags
.EXTERN
;
2868 case TokenType
.INLINE
:
2870 flags
|= ModifierFlags
.INLINE
;
2874 flags
|= ModifierFlags
.NEW
;
2876 case TokenType
.OVERRIDE
:
2878 flags
|= ModifierFlags
.OVERRIDE
;
2880 case TokenType
.STATIC
:
2882 flags
|= ModifierFlags
.STATIC
;
2884 case TokenType
.VIRTUAL
:
2886 flags
|= ModifierFlags
.VIRTUAL
;
2894 FormalParameter
parse_parameter () throws ParseError
{
2895 var attrs
= parse_attributes ();
2896 var begin
= get_location ();
2897 if (accept (TokenType
.ELLIPSIS
)) {
2899 return new FormalParameter
.with_ellipsis (get_src (begin
));
2901 bool params_array
= accept (TokenType
.PARAMS
);
2902 var direction
= ParameterDirection
.IN
;
2903 if (accept (TokenType
.OUT
)) {
2904 direction
= ParameterDirection
.OUT
;
2905 } else if (accept (TokenType
.REF
)) {
2906 direction
= ParameterDirection
.REF
;
2910 if (direction
== ParameterDirection
.IN
) {
2911 // in parameters are weak by default
2912 type
= parse_type (false);
2914 // out parameters own the value by default
2915 type
= parse_type (true);
2917 string id
= parse_identifier ();
2918 var param
= new
FormalParameter (id
, type
, get_src (begin
));
2919 set_attributes (param
, attrs
);
2920 param
.direction
= direction
;
2921 param
.params_array
= params_array
;
2922 if (accept (TokenType
.ASSIGN
)) {
2923 param
.default_expression
= parse_expression ();
2928 CreationMethod
parse_creation_method_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2929 var begin
= get_location ();
2930 var access
= parse_access_modifier ();
2931 var flags
= parse_member_declaration_modifiers ();
2932 var sym
= parse_symbol_name ();
2933 if (ModifierFlags
.NEW
in flags
) {
2934 throw new ParseError
.SYNTAX (get_error ("`new' modifier not allowed on creation method"));
2936 CreationMethod method
;
2937 if (sym
.inner
== null) {
2938 method
= new
CreationMethod (sym
.name
, null, get_src (begin
), comment
);
2940 method
= new
CreationMethod (sym
.inner
.name
, sym
.name
, get_src (begin
), comment
);
2942 if (ModifierFlags
.EXTERN
in flags
) {
2943 method
.external
= true;
2945 if (ModifierFlags
.ABSTRACT
in flags
2946 || ModifierFlags
.VIRTUAL
in flags
2947 || ModifierFlags
.OVERRIDE
in flags
) {
2948 Report
.error (method
.source_reference
, "abstract, virtual, and override modifiers are not applicable to creation methods");
2950 if (ModifierFlags
.ASYNC
in flags
) {
2951 method
.coroutine
= true;
2953 expect (TokenType
.OPEN_PARENS
);
2954 if (current () != TokenType
.CLOSE_PARENS
) {
2956 var param
= parse_parameter ();
2957 method
.add_parameter (param
);
2958 } while (accept (TokenType
.COMMA
));
2960 expect (TokenType
.CLOSE_PARENS
);
2961 if (accept (TokenType
.THROWS
)) {
2963 method
.add_error_type (parse_type ());
2964 } while (accept (TokenType
.COMMA
));
2966 method
.access
= access
;
2967 set_attributes (method
, attrs
);
2968 if (!accept (TokenType
.SEMICOLON
)) {
2969 method
.body
= parse_block ();
2970 } else if (scanner
.source_file
.external_package
) {
2971 method
.external
= true;
2976 Symbol
parse_delegate_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2977 var begin
= get_location ();
2978 var access
= parse_access_modifier ();
2979 var flags
= parse_member_declaration_modifiers ();
2980 expect (TokenType
.DELEGATE
);
2981 if (ModifierFlags
.NEW
in flags
) {
2982 throw new ParseError
.SYNTAX (get_error ("`new' modifier not allowed on delegates"));
2984 var type
= parse_type ();
2985 var sym
= parse_symbol_name ();
2986 var type_param_list
= parse_type_parameter_list ();
2987 var d
= new
Delegate (sym
.name
, type
, get_src (begin
), comment
);
2989 set_attributes (d
, attrs
);
2990 if (ModifierFlags
.STATIC
in flags
) {
2991 if (!context
.deprecated
) {
2992 // TODO enable warning in future releases
2993 // Report.warning (get_last_src (), "deprecated syntax, use [CCode (has_target = false)]");
2996 d
.has_target
= true;
2998 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
3001 foreach (TypeParameter type_param
in type_param_list
) {
3002 d
.add_type_parameter (type_param
);
3004 expect (TokenType
.OPEN_PARENS
);
3005 if (current () != TokenType
.CLOSE_PARENS
) {
3007 var param
= parse_parameter ();
3008 d
.add_parameter (param
);
3009 } while (accept (TokenType
.COMMA
));
3011 expect (TokenType
.CLOSE_PARENS
);
3012 if (accept (TokenType
.THROWS
)) {
3014 d
.add_error_type (parse_type ());
3015 } while (accept (TokenType
.COMMA
));
3017 expect (TokenType
.SEMICOLON
);
3020 while (sym
.inner
!= null) {
3022 var ns
= new
Namespace (sym
.name
, d
.source_reference
);
3023 if (result is Namespace
) {
3024 ns
.add_namespace ((Namespace
) result
);
3026 ns
.add_delegate ((Delegate
) result
);
3027 scanner
.source_file
.add_node (result
);
3034 List
<TypeParameter
> parse_type_parameter_list () throws ParseError
{
3035 var list
= new ArrayList
<TypeParameter
> ();
3036 if (accept (TokenType
.OP_LT
)) {
3038 var begin
= get_location ();
3039 string id
= parse_identifier ();
3040 list
.add (new
TypeParameter (id
, get_src (begin
)));
3041 } while (accept (TokenType
.COMMA
));
3042 expect (TokenType
.OP_GT
);
3047 void skip_type_argument_list () throws ParseError
{
3048 if (accept (TokenType
.OP_LT
)) {
3051 } while (accept (TokenType
.COMMA
));
3052 expect (TokenType
.OP_GT
);
3056 // try to parse type argument list
3057 List
<DataType
>?
parse_type_argument_list (bool maybe_expression
) throws ParseError
{
3058 var begin
= get_location ();
3059 if (accept (TokenType
.OP_LT
)) {
3060 var list
= new ArrayList
<DataType
> ();
3062 switch (current ()) {
3063 case TokenType
.VOID
:
3064 case TokenType
.DYNAMIC
:
3065 case TokenType
.UNOWNED
:
3066 case TokenType
.WEAK
:
3067 case TokenType
.IDENTIFIER
:
3068 var type
= parse_type ();
3075 } while (accept (TokenType
.COMMA
));
3076 if (!accept (TokenType
.OP_GT
)) {
3080 if (maybe_expression
) {
3081 // check follower to decide whether to keep type argument list
3082 switch (current ()) {
3083 case TokenType
.OPEN_PARENS
:
3084 case TokenType
.CLOSE_PARENS
:
3085 case TokenType
.CLOSE_BRACKET
:
3086 case TokenType
.COLON
:
3087 case TokenType
.SEMICOLON
:
3088 case TokenType
.COMMA
:
3090 case TokenType
.INTERR
:
3091 case TokenType
.OP_EQ
:
3092 case TokenType
.OP_NE
:
3093 // keep type argument list
3096 // interpret tokens as expression
3106 MemberAccess
parse_member_name () throws ParseError
{
3107 var begin
= get_location ();
3108 MemberAccess expr
= null;
3111 string id
= parse_identifier ();
3113 // The first member access can be global:: qualified
3114 bool qualified
= false;
3115 if (first
&& id
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
3116 id
= parse_identifier ();
3120 List
<DataType
> type_arg_list
= parse_type_argument_list (false);
3121 expr
= new
MemberAccess (expr
, id
, get_src (begin
));
3122 expr
.qualified
= qualified
;
3123 if (type_arg_list
!= null) {
3124 foreach (DataType type_arg
in type_arg_list
) {
3125 expr
.add_type_argument (type_arg
);
3130 } while (accept (TokenType
.DOT
));
3134 bool is_declaration_keyword (TokenType type
) {
3136 case TokenType
.ABSTRACT
:
3137 case TokenType
.ASYNC
:
3138 case TokenType
.CLASS
:
3139 case TokenType
.CONST
:
3140 case TokenType
.DELEGATE
:
3141 case TokenType
.ENUM
:
3142 case TokenType
.ERRORDOMAIN
:
3143 case TokenType
.EXTERN
:
3144 case TokenType
.INLINE
:
3145 case TokenType
.INTERFACE
:
3146 case TokenType
.INTERNAL
:
3147 case TokenType
.NAMESPACE
:
3149 case TokenType
.OVERRIDE
:
3150 case TokenType
.PRIVATE
:
3151 case TokenType
.PROTECTED
:
3152 case TokenType
.PUBLIC
:
3153 case TokenType
.SIGNAL
:
3154 case TokenType
.STATIC
:
3155 case TokenType
.STRUCT
:
3156 case TokenType
.VIRTUAL
:
3157 case TokenType
.VOLATILE
:
3165 public errordomain Vala
.ParseError
{