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>
27 * Code visitor parsing all Vala source files.
29 public class Vala
.Parser
: CodeVisitor
{
36 // index of current token in buffer
38 // number of tokens in buffer
43 const int BUFFER_SIZE
= 32;
46 public TokenType type
;
47 public SourceLocation begin
;
48 public SourceLocation end
;
65 tokens
= new TokenInfo
[BUFFER_SIZE
];
69 * Parses all .vala and .vapi source files in the specified code
70 * context and builds a code tree.
72 * @param context a code context
74 public void parse (CodeContext context
) {
75 this
.context
= context
;
76 context
.accept (this
);
79 public override void visit_source_file (SourceFile source_file
) {
80 if (source_file
.filename
.has_suffix (".vala") || source_file
.filename
.has_suffix (".vapi")) {
81 parse_file (source_file
);
86 index
= (index
+ 1) % BUFFER_SIZE
;
89 SourceLocation begin
, end
;
90 TokenType type
= scanner
.read_token (out begin
, out end
);
91 tokens
[index
].type
= type
;
92 tokens
[index
].begin
= begin
;
93 tokens
[index
].end
= end
;
96 return (tokens
[index
].type
!= TokenType
.EOF
);
100 index
= (index
- 1 + BUFFER_SIZE
) % BUFFER_SIZE
;
102 assert (size
<= BUFFER_SIZE
);
105 inline TokenType
current () {
106 return tokens
[index
].type
;
109 inline
bool accept (TokenType type
) {
110 if (current () == type
) {
117 string get_error (string msg
) {
118 var begin
= get_location ();
120 Report
.error (get_src (begin
), "syntax error, " + msg
);
124 inline
bool expect (TokenType type
) throws ParseError
{
129 throw new ParseError
.SYNTAX (get_error ("expected %s".printf (type
.to_string ())));
132 inline SourceLocation
get_location () {
133 return tokens
[index
].begin
;
136 string get_current_string () {
137 return ((string) tokens
[index
].begin
.pos
).ndup ((tokens
[index
].end
.pos
- tokens
[index
].begin
.pos
));
140 string get_last_string () {
141 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
142 return ((string) tokens
[last_index
].begin
.pos
).ndup ((tokens
[last_index
].end
.pos
- tokens
[last_index
].begin
.pos
));
145 SourceReference
get_src (SourceLocation begin
) {
146 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
148 return new
SourceReference (scanner
.source_file
, begin
.line
, begin
.column
, tokens
[last_index
].end
.line
, tokens
[last_index
].end
.column
);
151 SourceReference
get_current_src () {
152 return new
SourceReference (scanner
.source_file
, tokens
[index
].begin
.line
, tokens
[index
].begin
.column
, tokens
[index
].end
.line
, tokens
[index
].end
.column
);
155 SourceReference
get_last_src () {
156 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
158 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
);
161 void rollback (SourceLocation location
) {
162 while (tokens
[index
].begin
.pos
!= location
.pos
) {
167 void skip_identifier () throws ParseError
{
168 // also accept keywords as identifiers where there is no conflict
169 switch (current ()) {
170 case TokenType
.ABSTRACT
:
172 case TokenType
.ASYNC
:
174 case TokenType
.BREAK
:
176 case TokenType
.CATCH
:
177 case TokenType
.CLASS
:
178 case TokenType
.CONST
:
179 case TokenType
.CONSTRUCT
:
180 case TokenType
.CONTINUE
:
181 case TokenType
.DEFAULT
:
182 case TokenType
.DELEGATE
:
183 case TokenType
.DELETE
:
185 case TokenType
.DYNAMIC
:
188 case TokenType
.ENSURES
:
189 case TokenType
.ERRORDOMAIN
:
190 case TokenType
.EXTERN
:
191 case TokenType
.FALSE
:
192 case TokenType
.FINALLY
:
194 case TokenType
.FOREACH
:
196 case TokenType
.IDENTIFIER
:
199 case TokenType
.INLINE
:
200 case TokenType
.INTERFACE
:
201 case TokenType
.INTERNAL
:
204 case TokenType
.NAMESPACE
:
208 case TokenType
.OVERRIDE
:
209 case TokenType
.OWNED
:
210 case TokenType
.PARAMS
:
211 case TokenType
.PRIVATE
:
212 case TokenType
.PROTECTED
:
213 case TokenType
.PUBLIC
:
215 case TokenType
.REQUIRES
:
216 case TokenType
.RETURN
:
218 case TokenType
.SIGNAL
:
219 case TokenType
.SIZEOF
:
220 case TokenType
.STATIC
:
221 case TokenType
.STRUCT
:
222 case TokenType
.SWITCH
:
224 case TokenType
.THROW
:
225 case TokenType
.THROWS
:
228 case TokenType
.TYPEOF
:
229 case TokenType
.UNOWNED
:
230 case TokenType
.USING
:
232 case TokenType
.VIRTUAL
:
234 case TokenType
.VOLATILE
:
236 case TokenType
.WHILE
:
237 case TokenType
.YIELD
:
240 case TokenType
.INTEGER_LITERAL
:
241 case TokenType
.REAL_LITERAL
:
242 // also accept integer and real literals
243 // as long as they contain at least one character
244 // and no decimal point
245 // for example, 2D and 3D
246 string id
= get_current_string ();
247 if (id
[id
.length
- 1].isalpha () && !("." in id
)) {
253 throw new ParseError
.SYNTAX (get_error ("expected identifier"));
257 string parse_identifier () throws ParseError
{
259 return get_last_string ();
262 Expression
parse_literal () throws ParseError
{
263 var begin
= get_location ();
265 switch (current ()) {
268 return new
BooleanLiteral (true, get_src (begin
));
269 case TokenType
.FALSE
:
271 return new
BooleanLiteral (false, get_src (begin
));
272 case TokenType
.INTEGER_LITERAL
:
274 return new
IntegerLiteral (get_last_string (), get_src (begin
));
275 case TokenType
.REAL_LITERAL
:
277 return new
RealLiteral (get_last_string (), get_src (begin
));
278 case TokenType
.CHARACTER_LITERAL
:
280 // FIXME validate and unescape here and just pass unichar to CharacterLiteral
281 var lit
= new
CharacterLiteral (get_last_string (), get_src (begin
));
283 Report
.error (lit
.source_reference
, "invalid character literal");
286 case TokenType
.STRING_LITERAL
:
288 return new
StringLiteral (get_last_string (), get_src (begin
));
289 case TokenType
.TEMPLATE_STRING_LITERAL
:
291 return new
StringLiteral ("\"%s\"".printf (get_last_string ()), get_src (begin
));
292 case TokenType
.VERBATIM_STRING_LITERAL
:
294 string raw_string
= get_last_string ();
295 string escaped_string
= raw_string
.substring (3, raw_string
.len () - 6).escape ("");
296 return new
StringLiteral ("\"%s\"".printf (escaped_string
), get_src (begin
));
299 return new
NullLiteral (get_src (begin
));
301 throw new ParseError
.SYNTAX (get_error ("expected literal"));
305 public void parse_file (SourceFile source_file
) {
306 scanner
= new
Scanner (source_file
);
307 parse_file_comments ();
316 parse_using_directives (context
.root
);
317 parse_declarations (context
.root
, true);
318 if (accept (TokenType
.CLOSE_BRACE
)) {
319 // only report error if it's not a secondary error
320 if (context
.report
.get_errors () == 0) {
321 Report
.error (get_last_src (), "unexpected `}'");
324 } catch (ParseError e
) {
331 void parse_file_comments () {
332 scanner
.parse_file_comments ();
335 void skip_symbol_name () throws ParseError
{
338 } while (accept (TokenType
.DOT
) || accept (TokenType
.DOUBLE_COLON
));
341 UnresolvedSymbol
parse_symbol_name () throws ParseError
{
342 var begin
= get_location ();
343 UnresolvedSymbol sym
= null;
345 string name
= parse_identifier ();
346 if (name
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
348 // qualified access to global symbol
349 name
= parse_identifier ();
350 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
351 sym
.qualified
= true;
354 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
355 } while (accept (TokenType
.DOT
));
359 void skip_type () throws ParseError
{
360 if (accept (TokenType
.VOID
)) {
361 while (accept (TokenType
.STAR
)) {
365 accept (TokenType
.DYNAMIC
);
366 accept (TokenType
.OWNED
);
367 accept (TokenType
.UNOWNED
);
368 accept (TokenType
.WEAK
);
370 skip_type_argument_list ();
371 while (accept (TokenType
.STAR
)) {
373 accept (TokenType
.INTERR
);
374 while (accept (TokenType
.OPEN_BRACKET
)) {
376 // required for decision between expression and declaration statement
377 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
380 } while (accept (TokenType
.COMMA
));
381 expect (TokenType
.CLOSE_BRACKET
);
382 accept (TokenType
.INTERR
);
384 accept (TokenType
.OP_NEG
);
385 accept (TokenType
.HASH
);
388 DataType
parse_type (bool owned_by_default
= true) throws ParseError
{
389 var begin
= get_location ();
391 if (accept (TokenType
.VOID
)) {
392 DataType type
= new
VoidType (get_src (begin
));
393 while (accept (TokenType
.STAR
)) {
394 type
= new
PointerType (type
);
399 bool is_dynamic
= accept (TokenType
.DYNAMIC
);
401 bool value_owned
= owned_by_default
;
403 if (owned_by_default
) {
404 if (accept (TokenType
.UNOWNED
)
405 || accept (TokenType
.WEAK
)) {
409 value_owned
= accept (TokenType
.OWNED
);
412 var sym
= parse_symbol_name ();
413 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (false);
415 DataType type
= new UnresolvedType
.from_symbol (sym
, get_src (begin
));
416 if (type_arg_list
!= null) {
417 foreach (DataType type_arg
in type_arg_list
) {
418 type
.add_type_argument (type_arg
);
422 while (accept (TokenType
.STAR
)) {
423 type
= new
PointerType (type
, get_src (begin
));
426 if (!(type is PointerType
)) {
427 type
.nullable
= accept (TokenType
.INTERR
);
430 // array brackets in types are read from right to left,
431 // this is more logical, especially when nullable arrays
432 // or pointers are involved
433 while (accept (TokenType
.OPEN_BRACKET
)) {
434 bool invalid_array
= false;
438 // required for decision between expression and declaration statement
439 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
441 // only used for parsing, reject use as real type
442 invalid_array
= true;
444 } while (accept (TokenType
.COMMA
));
445 expect (TokenType
.CLOSE_BRACKET
);
447 // arrays contain strong references by default
448 type
.value_owned
= true;
450 var array_type
= new
ArrayType (type
, array_rank
, get_src (begin
));
451 array_type
.nullable
= accept (TokenType
.INTERR
);
452 array_type
.invalid_syntax
= invalid_array
;
457 if (accept (TokenType
.OP_NEG
)) {
458 Report
.warning (get_last_src (), "obsolete syntax, types are non-null by default");
461 if (!owned_by_default
) {
462 if (accept (TokenType
.HASH
)) {
463 if (!context
.deprecated
) {
464 Report
.warning (get_last_src (), "deprecated syntax, use `owned` modifier");
470 type
.is_dynamic
= is_dynamic
;
471 type
.value_owned
= value_owned
;
475 DataType?
parse_inline_array_type (DataType? type
) throws ParseError
{
476 var begin
= get_location ();
478 // inline-allocated array
479 if (type
!= null && accept (TokenType
.OPEN_BRACKET
)) {
480 int array_length
= -1;
482 if (current () != TokenType
.CLOSE_BRACKET
) {
483 if (current () != TokenType
.INTEGER_LITERAL
) {
484 throw new ParseError
.SYNTAX (get_error ("expected `]' or integer literal"));
487 var length_literal
= (IntegerLiteral
) parse_literal ();
488 array_length
= length_literal
.value
.to_int ();
490 expect (TokenType
.CLOSE_BRACKET
);
492 var array_type
= new
ArrayType (type
, 1, get_src (begin
));
493 array_type
.inline_allocated
= true;
494 if (array_length
> 0) {
495 array_type
.fixed_length
= true;
496 array_type
.length
= array_length
;
504 Gee
.List
<Expression
> parse_argument_list () throws ParseError
{
505 var list
= new ArrayList
<Expression
> ();
506 if (current () != TokenType
.CLOSE_PARENS
) {
508 list
.add (parse_argument ());
509 } while (accept (TokenType
.COMMA
));
514 Expression
parse_argument () throws ParseError
{
515 var begin
= get_location ();
517 if (accept (TokenType
.REF
)) {
518 var inner
= parse_expression ();
519 return new
UnaryExpression (UnaryOperator
.REF
, inner
, get_src (begin
));
520 } else if (accept (TokenType
.OUT
)) {
521 var inner
= parse_expression ();
522 return new
UnaryExpression (UnaryOperator
.OUT
, inner
, get_src (begin
));
524 return parse_expression ();
528 Expression
parse_primary_expression () throws ParseError
{
529 var begin
= get_location ();
533 switch (current ()) {
535 case TokenType
.FALSE
:
536 case TokenType
.INTEGER_LITERAL
:
537 case TokenType
.REAL_LITERAL
:
538 case TokenType
.CHARACTER_LITERAL
:
539 case TokenType
.STRING_LITERAL
:
540 case TokenType
.TEMPLATE_STRING_LITERAL
:
541 case TokenType
.VERBATIM_STRING_LITERAL
:
543 expr
= parse_literal ();
545 case TokenType
.OPEN_BRACE
:
546 expr
= parse_initializer ();
548 case TokenType
.OPEN_PARENS
:
549 expr
= parse_tuple ();
551 case TokenType
.OPEN_TEMPLATE
:
552 expr
= parse_template ();
555 expr
= parse_this_access ();
558 expr
= parse_base_access ();
561 expr
= parse_object_or_array_creation_expression ();
563 case TokenType
.YIELD
:
564 expr
= parse_yield_expression ();
566 case TokenType
.SIZEOF
:
567 expr
= parse_sizeof_expression ();
569 case TokenType
.TYPEOF
:
570 expr
= parse_typeof_expression ();
573 expr
= parse_simple_name ();
577 // process primary expressions that start with an inner primary expression
580 switch (current ()) {
582 expr
= parse_member_access (begin
, expr
);
584 case TokenType
.OP_PTR
:
585 expr
= parse_pointer_member_access (begin
, expr
);
587 case TokenType
.OPEN_PARENS
:
588 expr
= parse_method_call (begin
, expr
);
590 case TokenType
.OPEN_BRACKET
:
591 expr
= parse_element_access (begin
, expr
);
593 case TokenType
.OP_INC
:
594 expr
= parse_post_increment_expression (begin
, expr
);
596 case TokenType
.OP_DEC
:
597 expr
= parse_post_decrement_expression (begin
, expr
);
608 Expression
parse_simple_name () throws ParseError
{
609 var begin
= get_location ();
610 string id
= parse_identifier ();
611 bool qualified
= false;
612 if (id
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
613 id
= parse_identifier ();
616 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (true);
617 var expr
= new
MemberAccess (null, id
, get_src (begin
));
618 expr
.qualified
= qualified
;
619 if (type_arg_list
!= null) {
620 foreach (DataType type_arg
in type_arg_list
) {
621 expr
.add_type_argument (type_arg
);
627 Expression
parse_tuple () throws ParseError
{
628 expect (TokenType
.OPEN_PARENS
);
629 var expr_list
= new ArrayList
<Expression
> ();
630 if (current () != TokenType
.CLOSE_PARENS
) {
632 expr_list
.add (parse_expression ());
633 } while (accept (TokenType
.COMMA
));
635 expect (TokenType
.CLOSE_PARENS
);
636 if (expr_list
.size
!= 1) {
637 var tuple
= new
Tuple ();
638 foreach (Expression expr
in expr_list
) {
639 tuple
.add_expression (expr
);
643 return expr_list
.get (0);
646 Expression
parse_template () throws ParseError
{
647 var begin
= get_location ();
648 var template
= new
Template ();
650 expect (TokenType
.OPEN_TEMPLATE
);
651 while (current () != TokenType
.CLOSE_TEMPLATE
) {
652 template
.add_expression (parse_expression ());
653 expect (TokenType
.COMMA
);
655 expect (TokenType
.CLOSE_TEMPLATE
);
657 template
.source_reference
= get_src (begin
);
661 Expression
parse_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
662 expect (TokenType
.DOT
);
663 string id
= parse_identifier ();
664 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (true);
665 var expr
= new
MemberAccess (inner
, id
, get_src (begin
));
666 if (type_arg_list
!= null) {
667 foreach (DataType type_arg
in type_arg_list
) {
668 expr
.add_type_argument (type_arg
);
674 Expression
parse_pointer_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
675 expect (TokenType
.OP_PTR
);
676 string id
= parse_identifier ();
677 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (true);
678 var expr
= new MemberAccess
.pointer (inner
, id
, get_src (begin
));
679 if (type_arg_list
!= null) {
680 foreach (DataType type_arg
in type_arg_list
) {
681 expr
.add_type_argument (type_arg
);
687 Expression
parse_method_call (SourceLocation begin
, Expression inner
) throws ParseError
{
688 expect (TokenType
.OPEN_PARENS
);
689 var arg_list
= parse_argument_list ();
690 expect (TokenType
.CLOSE_PARENS
);
691 var init_list
= parse_object_initializer ();
693 if (init_list
.size
> 0 && inner is MemberAccess
) {
694 // struct creation expression
695 var member
= (MemberAccess
) inner
;
696 member
.creation_member
= true;
698 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
699 expr
.struct_creation
= true;
700 foreach (Expression arg
in arg_list
) {
701 expr
.add_argument (arg
);
703 foreach (MemberInitializer initializer
in init_list
) {
704 expr
.add_member_initializer (initializer
);
708 var expr
= new
MethodCall (inner
, get_src (begin
));
709 foreach (Expression arg
in arg_list
) {
710 expr
.add_argument (arg
);
716 Expression
parse_element_access (SourceLocation begin
, Expression inner
) throws ParseError
{
717 expect (TokenType
.OPEN_BRACKET
);
718 var index_list
= parse_expression_list ();
719 expect (TokenType
.CLOSE_BRACKET
);
721 var expr
= new
ElementAccess (inner
, get_src (begin
));
722 foreach (Expression index
in index_list
) {
723 expr
.append_index (index
);
728 Gee
.List
<Expression
> parse_expression_list () throws ParseError
{
729 var list
= new ArrayList
<Expression
> ();
731 list
.add (parse_expression ());
732 } while (accept (TokenType
.COMMA
));
736 Expression
parse_this_access () throws ParseError
{
737 var begin
= get_location ();
738 expect (TokenType
.THIS
);
739 return new
MemberAccess (null, "this", get_src (begin
));
742 Expression
parse_base_access () throws ParseError
{
743 var begin
= get_location ();
744 expect (TokenType
.BASE
);
745 return new
BaseAccess (get_src (begin
));
748 Expression
parse_post_increment_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
749 expect (TokenType
.OP_INC
);
750 return new
PostfixExpression (inner
, true, get_src (begin
));
753 Expression
parse_post_decrement_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
754 expect (TokenType
.OP_DEC
);
755 return new
PostfixExpression (inner
, false, get_src (begin
));
758 Expression
parse_object_or_array_creation_expression () throws ParseError
{
759 var begin
= get_location ();
760 expect (TokenType
.NEW
);
761 var member
= parse_member_name ();
762 if (accept (TokenType
.OPEN_PARENS
)) {
763 var expr
= parse_object_creation_expression (begin
, member
);
765 } else if (accept (TokenType
.OPEN_BRACKET
)) {
766 var expr
= parse_array_creation_expression (begin
, member
);
769 throw new ParseError
.SYNTAX (get_error ("expected ( or ["));
773 Expression
parse_object_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
774 member
.creation_member
= true;
775 var arg_list
= parse_argument_list ();
776 expect (TokenType
.CLOSE_PARENS
);
777 var init_list
= parse_object_initializer ();
779 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
780 foreach (Expression arg
in arg_list
) {
781 expr
.add_argument (arg
);
783 foreach (MemberInitializer initializer
in init_list
) {
784 expr
.add_member_initializer (initializer
);
789 Expression
parse_array_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
790 bool size_specified
= false;
791 Gee
.List
<Expression
> size_specifier_list
= null;
793 DataType element_type
= UnresolvedType
.new_from_expression (member
);
796 // array of arrays: new T[][42]
797 element_type
= new
ArrayType (element_type
, size_specifier_list
.size
, element_type
.source_reference
);
802 size_specifier_list
= new ArrayList
<Expression
> ();
804 Expression size
= null;
805 if (current () != TokenType
.CLOSE_BRACKET
&& current () != TokenType
.COMMA
) {
806 size
= parse_expression ();
807 size_specified
= true;
809 size_specifier_list
.add (size
);
810 } while (accept (TokenType
.COMMA
));
811 expect (TokenType
.CLOSE_BRACKET
);
812 } while (accept (TokenType
.OPEN_BRACKET
));
814 InitializerList initializer
= null;
815 if (current () == TokenType
.OPEN_BRACE
) {
816 initializer
= parse_initializer ();
818 var expr
= new
ArrayCreationExpression (element_type
, size_specifier_list
.size
, initializer
, get_src (begin
));
819 if (size_specified
) {
820 foreach (Expression size
in size_specifier_list
) {
821 expr
.append_size (size
);
827 Gee
.List
<MemberInitializer
> parse_object_initializer () throws ParseError
{
828 var list
= new ArrayList
<MemberInitializer
> ();
829 if (accept (TokenType
.OPEN_BRACE
)) {
831 list
.add (parse_member_initializer ());
832 } while (accept (TokenType
.COMMA
));
833 expect (TokenType
.CLOSE_BRACE
);
838 MemberInitializer
parse_member_initializer () throws ParseError
{
839 var begin
= get_location ();
840 string id
= parse_identifier ();
841 expect (TokenType
.ASSIGN
);
842 var expr
= parse_expression ();
844 return new
MemberInitializer (id
, expr
, get_src (begin
));
847 Expression
parse_yield_expression () throws ParseError
{
848 var begin
= get_location ();
849 expect (TokenType
.YIELD
);
850 var member
= parse_member_name ();
851 var call
= (MethodCall
) parse_method_call (begin
, member
);
852 call
.is_yield_expression
= true;
856 Expression
parse_sizeof_expression () throws ParseError
{
857 var begin
= get_location ();
858 expect (TokenType
.SIZEOF
);
859 expect (TokenType
.OPEN_PARENS
);
860 var type
= parse_type ();
861 expect (TokenType
.CLOSE_PARENS
);
863 return new
SizeofExpression (type
, get_src (begin
));
866 Expression
parse_typeof_expression () throws ParseError
{
867 var begin
= get_location ();
868 expect (TokenType
.TYPEOF
);
869 expect (TokenType
.OPEN_PARENS
);
870 var type
= parse_type ();
871 expect (TokenType
.CLOSE_PARENS
);
873 return new
TypeofExpression (type
, get_src (begin
));
876 UnaryOperator
get_unary_operator (TokenType token_type
) {
877 switch (token_type
) {
878 case TokenType
.PLUS
: return UnaryOperator
.PLUS
;
879 case TokenType
.MINUS
: return UnaryOperator
.MINUS
;
880 case TokenType
.OP_NEG
: return UnaryOperator
.LOGICAL_NEGATION
;
881 case TokenType
.TILDE
: return UnaryOperator
.BITWISE_COMPLEMENT
;
882 case TokenType
.OP_INC
: return UnaryOperator
.INCREMENT
;
883 case TokenType
.OP_DEC
: return UnaryOperator
.DECREMENT
;
884 default: return UnaryOperator
.NONE
;
888 Expression
parse_unary_expression () throws ParseError
{
889 var begin
= get_location ();
890 var operator
= get_unary_operator (current ());
891 if (operator
!= UnaryOperator
.NONE
) {
893 var op
= parse_unary_expression ();
894 return new
UnaryExpression (operator
, op
, get_src (begin
));
896 switch (current ()) {
898 if (!context
.deprecated
) {
899 Report
.warning (get_last_src (), "deprecated syntax, use `(owned)` cast");
902 var op
= parse_unary_expression ();
903 return new
ReferenceTransferExpression (op
, get_src (begin
));
904 case TokenType
.OPEN_PARENS
:
906 switch (current ()) {
907 case TokenType
.OWNED
:
910 if (accept (TokenType
.CLOSE_PARENS
)) {
911 var op
= parse_unary_expression ();
912 return new
ReferenceTransferExpression (op
, get_src (begin
));
916 case TokenType
.DYNAMIC
:
917 case TokenType
.IDENTIFIER
:
918 var type
= parse_type ();
919 if (accept (TokenType
.CLOSE_PARENS
)) {
920 // check follower to decide whether to create cast expression
921 switch (current ()) {
922 case TokenType
.OP_NEG
:
923 case TokenType
.TILDE
:
924 case TokenType
.OPEN_PARENS
:
926 case TokenType
.FALSE
:
927 case TokenType
.INTEGER_LITERAL
:
928 case TokenType
.REAL_LITERAL
:
929 case TokenType
.CHARACTER_LITERAL
:
930 case TokenType
.STRING_LITERAL
:
931 case TokenType
.TEMPLATE_STRING_LITERAL
:
932 case TokenType
.VERBATIM_STRING_LITERAL
:
937 case TokenType
.SIZEOF
:
938 case TokenType
.TYPEOF
:
939 case TokenType
.IDENTIFIER
:
940 case TokenType
.PARAMS
:
941 var inner
= parse_unary_expression ();
942 return new
CastExpression (inner
, type
, get_src (begin
), false);
951 // no cast expression
956 var op
= parse_unary_expression ();
957 return new
PointerIndirection (op
, get_src (begin
));
958 case TokenType
.BITWISE_AND
:
960 var op
= parse_unary_expression ();
961 return new
AddressofExpression (op
, get_src (begin
));
966 var expr
= parse_primary_expression ();
970 BinaryOperator
get_binary_operator (TokenType token_type
) {
971 switch (token_type
) {
972 case TokenType
.STAR
: return BinaryOperator
.MUL
;
973 case TokenType
.DIV
: return BinaryOperator
.DIV
;
974 case TokenType
.PERCENT
: return BinaryOperator
.MOD
;
975 case TokenType
.PLUS
: return BinaryOperator
.PLUS
;
976 case TokenType
.MINUS
: return BinaryOperator
.MINUS
;
977 case TokenType
.OP_LT
: return BinaryOperator
.LESS_THAN
;
978 case TokenType
.OP_GT
: return BinaryOperator
.GREATER_THAN
;
979 case TokenType
.OP_LE
: return BinaryOperator
.LESS_THAN_OR_EQUAL
;
980 case TokenType
.OP_GE
: return BinaryOperator
.GREATER_THAN_OR_EQUAL
;
981 case TokenType
.OP_EQ
: return BinaryOperator
.EQUALITY
;
982 case TokenType
.OP_NE
: return BinaryOperator
.INEQUALITY
;
983 default: return BinaryOperator
.NONE
;
987 Expression
parse_multiplicative_expression () throws ParseError
{
988 var begin
= get_location ();
989 var left
= parse_unary_expression ();
992 var operator
= get_binary_operator (current ());
994 case BinaryOperator
.MUL
:
995 case BinaryOperator
.DIV
:
996 case BinaryOperator
.MOD
:
998 var right
= parse_unary_expression ();
999 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1009 Expression
parse_additive_expression () throws ParseError
{
1010 var begin
= get_location ();
1011 var left
= parse_multiplicative_expression ();
1014 var operator
= get_binary_operator (current ());
1016 case BinaryOperator
.PLUS
:
1017 case BinaryOperator
.MINUS
:
1019 var right
= parse_multiplicative_expression ();
1020 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1030 Expression
parse_shift_expression () throws ParseError
{
1031 var begin
= get_location ();
1032 var left
= parse_additive_expression ();
1035 switch (current ()) {
1036 case TokenType
.OP_SHIFT_LEFT
:
1038 var right
= parse_additive_expression ();
1039 left
= new
BinaryExpression (BinaryOperator
.SHIFT_LEFT
, left
, right
, get_src (begin
));
1041 // don't use OP_SHIFT_RIGHT to support >> for nested generics
1042 case TokenType
.OP_GT
:
1043 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1045 // only accept >> when there is no space between the two > signs
1046 if (current () == TokenType
.OP_GT
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1048 var right
= parse_additive_expression ();
1049 left
= new
BinaryExpression (BinaryOperator
.SHIFT_RIGHT
, left
, right
, get_src (begin
));
1063 Expression
parse_relational_expression () throws ParseError
{
1064 var begin
= get_location ();
1065 var left
= parse_shift_expression ();
1068 var operator
= get_binary_operator (current ());
1070 case BinaryOperator
.LESS_THAN
:
1071 case BinaryOperator
.LESS_THAN_OR_EQUAL
:
1072 case BinaryOperator
.GREATER_THAN_OR_EQUAL
:
1074 var right
= parse_shift_expression ();
1075 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1077 case BinaryOperator
.GREATER_THAN
:
1079 // ignore >> and >>= (two tokens due to generics)
1080 if (current () != TokenType
.OP_GT
&& current () != TokenType
.OP_GE
) {
1081 var right
= parse_shift_expression ();
1082 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1089 switch (current ()) {
1092 var type
= parse_type ();
1093 left
= new
TypeCheck (left
, type
, get_src (begin
));
1097 var type
= parse_type ();
1098 left
= new
CastExpression (left
, type
, get_src (begin
), true);
1110 Expression
parse_equality_expression () throws ParseError
{
1111 var begin
= get_location ();
1112 var left
= parse_relational_expression ();
1115 var operator
= get_binary_operator (current ());
1117 case BinaryOperator
.EQUALITY
:
1118 case BinaryOperator
.INEQUALITY
:
1120 var right
= parse_relational_expression ();
1121 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1131 Expression
parse_and_expression () throws ParseError
{
1132 var begin
= get_location ();
1133 var left
= parse_equality_expression ();
1134 while (accept (TokenType
.BITWISE_AND
)) {
1135 var right
= parse_equality_expression ();
1136 left
= new
BinaryExpression (BinaryOperator
.BITWISE_AND
, left
, right
, get_src (begin
));
1141 Expression
parse_exclusive_or_expression () throws ParseError
{
1142 var begin
= get_location ();
1143 var left
= parse_and_expression ();
1144 while (accept (TokenType
.CARRET
)) {
1145 var right
= parse_and_expression ();
1146 left
= new
BinaryExpression (BinaryOperator
.BITWISE_XOR
, left
, right
, get_src (begin
));
1151 Expression
parse_inclusive_or_expression () throws ParseError
{
1152 var begin
= get_location ();
1153 var left
= parse_exclusive_or_expression ();
1154 while (accept (TokenType
.BITWISE_OR
)) {
1155 var right
= parse_exclusive_or_expression ();
1156 left
= new
BinaryExpression (BinaryOperator
.BITWISE_OR
, left
, right
, get_src (begin
));
1161 Expression
parse_in_expression () throws ParseError
{
1162 var begin
= get_location ();
1163 var left
= parse_inclusive_or_expression ();
1164 while (accept (TokenType
.IN
)) {
1165 var right
= parse_inclusive_or_expression ();
1166 left
= new
BinaryExpression (BinaryOperator
.IN
, left
, right
, get_src (begin
));
1171 Expression
parse_conditional_and_expression () throws ParseError
{
1172 var begin
= get_location ();
1173 var left
= parse_in_expression ();
1174 while (accept (TokenType
.OP_AND
)) {
1175 var right
= parse_in_expression ();
1176 left
= new
BinaryExpression (BinaryOperator
.AND
, left
, right
, get_src (begin
));
1181 Expression
parse_conditional_or_expression () throws ParseError
{
1182 var begin
= get_location ();
1183 var left
= parse_conditional_and_expression ();
1184 while (accept (TokenType
.OP_OR
)) {
1185 var right
= parse_conditional_and_expression ();
1186 left
= new
BinaryExpression (BinaryOperator
.OR
, left
, right
, get_src (begin
));
1191 Expression
parse_conditional_expression () throws ParseError
{
1192 var begin
= get_location ();
1193 var condition
= parse_conditional_or_expression ();
1194 if (accept (TokenType
.INTERR
)) {
1195 var true_expr
= parse_expression ();
1196 expect (TokenType
.COLON
);
1197 var false_expr
= parse_expression ();
1198 return new
ConditionalExpression (condition
, true_expr
, false_expr
, get_src (begin
));
1204 Expression
parse_lambda_expression () throws ParseError
{
1205 var begin
= get_location ();
1206 Gee
.List
<string> params
= new ArrayList
<string> ();
1207 if (accept (TokenType
.OPEN_PARENS
)) {
1208 if (current () != TokenType
.CLOSE_PARENS
) {
1210 params
.add (parse_identifier ());
1211 } while (accept (TokenType
.COMMA
));
1213 expect (TokenType
.CLOSE_PARENS
);
1215 params
.add (parse_identifier ());
1217 expect (TokenType
.LAMBDA
);
1219 LambdaExpression lambda
;
1220 if (current () == TokenType
.OPEN_BRACE
) {
1221 var block
= parse_block ();
1222 lambda
= new LambdaExpression
.with_statement_body (block
, get_src (begin
));
1224 var expr
= parse_expression ();
1225 lambda
= new
LambdaExpression (expr
, get_src (begin
));
1227 foreach (string param
in params
) {
1228 lambda
.add_parameter (param
);
1233 AssignmentOperator
get_assignment_operator (TokenType token_type
) {
1234 switch (token_type
) {
1235 case TokenType
.ASSIGN
: return AssignmentOperator
.SIMPLE
;
1236 case TokenType
.ASSIGN_ADD
: return AssignmentOperator
.ADD
;
1237 case TokenType
.ASSIGN_SUB
: return AssignmentOperator
.SUB
;
1238 case TokenType
.ASSIGN_BITWISE_OR
: return AssignmentOperator
.BITWISE_OR
;
1239 case TokenType
.ASSIGN_BITWISE_AND
: return AssignmentOperator
.BITWISE_AND
;
1240 case TokenType
.ASSIGN_BITWISE_XOR
: return AssignmentOperator
.BITWISE_XOR
;
1241 case TokenType
.ASSIGN_DIV
: return AssignmentOperator
.DIV
;
1242 case TokenType
.ASSIGN_MUL
: return AssignmentOperator
.MUL
;
1243 case TokenType
.ASSIGN_PERCENT
: return AssignmentOperator
.PERCENT
;
1244 case TokenType
.ASSIGN_SHIFT_LEFT
: return AssignmentOperator
.SHIFT_LEFT
;
1245 default: return AssignmentOperator
.NONE
;
1249 Expression
parse_expression () throws ParseError
{
1250 var begin
= get_location ();
1251 Expression expr
= parse_conditional_expression ();
1253 if (current () == TokenType
.LAMBDA
) {
1255 var lambda
= parse_lambda_expression ();
1260 var operator
= get_assignment_operator (current ());
1261 if (operator
!= AssignmentOperator
.NONE
) {
1263 var rhs
= parse_expression ();
1264 expr
= new
Assignment (expr
, rhs
, operator
, get_src (begin
));
1265 } else if (current () == TokenType
.OP_GT
) { // >>=
1266 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1268 // only accept >>= when there is no space between the two > signs
1269 if (current () == TokenType
.OP_GE
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1271 var rhs
= parse_expression ();
1272 expr
= new
Assignment (expr
, rhs
, AssignmentOperator
.SHIFT_RIGHT
, get_src (begin
));
1285 void parse_statements (Block block
) throws ParseError
{
1286 while (current () != TokenType
.CLOSE_BRACE
1287 && current () != TokenType
.CASE
1288 && current () != TokenType
.DEFAULT
) {
1290 Statement stmt
= null;
1291 bool is_decl
= false;
1293 comment
= scanner
.pop_comment ();
1294 switch (current ()) {
1295 case TokenType
.OPEN_BRACE
:
1296 stmt
= parse_block ();
1298 case TokenType
.SEMICOLON
:
1299 stmt
= parse_empty_statement ();
1302 stmt
= parse_if_statement ();
1304 case TokenType
.SWITCH
:
1305 stmt
= parse_switch_statement ();
1307 case TokenType
.WHILE
:
1308 stmt
= parse_while_statement ();
1311 stmt
= parse_do_statement ();
1314 stmt
= parse_for_statement ();
1316 case TokenType
.FOREACH
:
1317 stmt
= parse_foreach_statement ();
1319 case TokenType
.BREAK
:
1320 stmt
= parse_break_statement ();
1322 case TokenType
.CONTINUE
:
1323 stmt
= parse_continue_statement ();
1325 case TokenType
.RETURN
:
1326 stmt
= parse_return_statement ();
1328 case TokenType
.YIELD
:
1329 stmt
= parse_yield_statement ();
1331 case TokenType
.THROW
:
1332 stmt
= parse_throw_statement ();
1335 stmt
= parse_try_statement ();
1337 case TokenType
.LOCK
:
1338 stmt
= parse_lock_statement ();
1340 case TokenType
.DELETE
:
1341 stmt
= parse_delete_statement ();
1345 parse_local_variable_declarations (block
);
1347 case TokenType
.OP_INC
:
1348 case TokenType
.OP_DEC
:
1349 case TokenType
.BASE
:
1350 case TokenType
.THIS
:
1351 case TokenType
.OPEN_PARENS
:
1352 case TokenType
.STAR
:
1354 stmt
= parse_expression_statement ();
1357 bool is_expr
= is_expression ();
1359 stmt
= parse_expression_statement ();
1362 parse_local_variable_declarations (block
);
1368 block
.add_statement (stmt
);
1370 } catch (ParseError e
) {
1371 if (recover () != RecoveryState
.STATEMENT_BEGIN
) {
1372 // beginning of next declaration or end of file reached
1373 // return what we have so far
1380 bool is_expression () throws ParseError
{
1381 var begin
= get_location ();
1383 // decide between declaration and expression statement
1385 switch (current ()) {
1386 // invocation expression
1387 case TokenType
.OPEN_PARENS
:
1388 // postfix increment
1389 case TokenType
.OP_INC
:
1390 // postfix decrement
1391 case TokenType
.OP_DEC
:
1393 case TokenType
.ASSIGN
:
1394 case TokenType
.ASSIGN_ADD
:
1395 case TokenType
.ASSIGN_BITWISE_AND
:
1396 case TokenType
.ASSIGN_BITWISE_OR
:
1397 case TokenType
.ASSIGN_BITWISE_XOR
:
1398 case TokenType
.ASSIGN_DIV
:
1399 case TokenType
.ASSIGN_MUL
:
1400 case TokenType
.ASSIGN_PERCENT
:
1401 case TokenType
.ASSIGN_SHIFT_LEFT
:
1402 case TokenType
.ASSIGN_SUB
:
1403 case TokenType
.OP_GT
: // >>=
1406 // pointer member access
1407 case TokenType
.OP_PTR
:
1416 Block
parse_embedded_statement () throws ParseError
{
1417 if (current () == TokenType
.OPEN_BRACE
) {
1418 var block
= parse_block ();
1422 comment
= scanner
.pop_comment ();
1424 var block
= new
Block (get_src (get_location ()));
1425 block
.add_statement (parse_embedded_statement_without_block ());
1430 Statement
parse_embedded_statement_without_block () throws ParseError
{
1431 switch (current ()) {
1432 case TokenType
.SEMICOLON
: return parse_empty_statement ();
1433 case TokenType
.IF
: return parse_if_statement ();
1434 case TokenType
.SWITCH
: return parse_switch_statement ();
1435 case TokenType
.WHILE
: return parse_while_statement ();
1436 case TokenType
.DO
: return parse_do_statement ();
1437 case TokenType
.FOR
: return parse_for_statement ();
1438 case TokenType
.FOREACH
: return parse_foreach_statement ();
1439 case TokenType
.BREAK
: return parse_break_statement ();
1440 case TokenType
.CONTINUE
: return parse_continue_statement ();
1441 case TokenType
.RETURN
: return parse_return_statement ();
1442 case TokenType
.YIELD
: return parse_yield_statement ();
1443 case TokenType
.THROW
: return parse_throw_statement ();
1444 case TokenType
.TRY
: return parse_try_statement ();
1445 case TokenType
.LOCK
: return parse_lock_statement ();
1446 case TokenType
.DELETE
: return parse_delete_statement ();
1447 default: return parse_expression_statement ();
1451 Block
parse_block () throws ParseError
{
1452 var begin
= get_location ();
1453 expect (TokenType
.OPEN_BRACE
);
1454 var block
= new
Block (get_src (begin
));
1455 parse_statements (block
);
1456 if (!accept (TokenType
.CLOSE_BRACE
)) {
1457 // only report error if it's not a secondary error
1458 if (context
.report
.get_errors () == 0) {
1459 Report
.error (get_current_src (), "expected `}'");
1463 block
.source_reference
.last_line
= get_current_src ().last_line
;
1464 block
.source_reference
.last_column
= get_current_src ().last_column
;
1469 Statement
parse_empty_statement () throws ParseError
{
1470 var begin
= get_location ();
1471 expect (TokenType
.SEMICOLON
);
1472 return new
EmptyStatement (get_src (begin
));
1475 void parse_local_variable_declarations (Block block
) throws ParseError
{
1476 DataType variable_type
;
1477 if (accept (TokenType
.VAR
)) {
1478 variable_type
= null;
1480 variable_type
= parse_type ();
1483 DataType type_copy
= null;
1484 if (variable_type
!= null) {
1485 type_copy
= variable_type
.copy ();
1487 var local
= parse_local_variable (type_copy
);
1488 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1489 } while (accept (TokenType
.COMMA
));
1490 expect (TokenType
.SEMICOLON
);
1493 LocalVariable
parse_local_variable (DataType? variable_type
) throws ParseError
{
1494 var begin
= get_location ();
1495 string id
= parse_identifier ();
1497 var type
= parse_inline_array_type (variable_type
);
1499 Expression initializer
= null;
1500 if (accept (TokenType
.ASSIGN
)) {
1501 initializer
= parse_expression ();
1503 return new
LocalVariable (type
, id
, initializer
, get_src (begin
));
1506 Statement
parse_expression_statement () throws ParseError
{
1507 var begin
= get_location ();
1508 var expr
= parse_statement_expression ();
1509 expect (TokenType
.SEMICOLON
);
1510 return new
ExpressionStatement (expr
, get_src (begin
));
1513 Expression
parse_statement_expression () throws ParseError
{
1514 // invocation expression, assignment,
1515 // or pre/post increment/decrement expression
1516 var expr
= parse_expression ();
1520 Statement
parse_if_statement () throws ParseError
{
1521 var begin
= get_location ();
1522 expect (TokenType
.IF
);
1523 expect (TokenType
.OPEN_PARENS
);
1524 var condition
= parse_expression ();
1525 expect (TokenType
.CLOSE_PARENS
);
1526 var src
= get_src (begin
);
1527 var true_stmt
= parse_embedded_statement ();
1528 Block false_stmt
= null;
1529 if (accept (TokenType
.ELSE
)) {
1530 false_stmt
= parse_embedded_statement ();
1532 return new
IfStatement (condition
, true_stmt
, false_stmt
, src
);
1535 Statement
parse_switch_statement () throws ParseError
{
1536 var begin
= get_location ();
1537 expect (TokenType
.SWITCH
);
1538 expect (TokenType
.OPEN_PARENS
);
1539 var condition
= parse_expression ();
1540 expect (TokenType
.CLOSE_PARENS
);
1541 var stmt
= new
SwitchStatement (condition
, get_src (begin
));
1542 expect (TokenType
.OPEN_BRACE
);
1543 while (current () != TokenType
.CLOSE_BRACE
) {
1544 var section
= new
SwitchSection (get_src (begin
));
1546 if (accept (TokenType
.CASE
)) {
1547 section
.add_label (new
SwitchLabel (parse_expression (), get_src (begin
)));
1549 expect (TokenType
.DEFAULT
);
1550 section
.add_label (new SwitchLabel
.with_default (get_src (begin
)));
1552 expect (TokenType
.COLON
);
1553 } while (current () == TokenType
.CASE
|| current () == TokenType
.DEFAULT
);
1554 parse_statements (section
);
1555 stmt
.add_section (section
);
1557 expect (TokenType
.CLOSE_BRACE
);
1561 Statement
parse_while_statement () throws ParseError
{
1562 var begin
= get_location ();
1563 expect (TokenType
.WHILE
);
1564 expect (TokenType
.OPEN_PARENS
);
1565 var condition
= parse_expression ();
1566 expect (TokenType
.CLOSE_PARENS
);
1567 var body
= parse_embedded_statement ();
1568 return new
WhileStatement (condition
, body
, get_src (begin
));
1571 Statement
parse_do_statement () throws ParseError
{
1572 var begin
= get_location ();
1573 expect (TokenType
.DO
);
1574 var body
= parse_embedded_statement ();
1575 expect (TokenType
.WHILE
);
1576 expect (TokenType
.OPEN_PARENS
);
1577 var condition
= parse_expression ();
1578 expect (TokenType
.CLOSE_PARENS
);
1579 expect (TokenType
.SEMICOLON
);
1580 return new
DoStatement (body
, condition
, get_src (begin
));
1583 Statement
parse_for_statement () throws ParseError
{
1584 var begin
= get_location ();
1586 expect (TokenType
.FOR
);
1587 expect (TokenType
.OPEN_PARENS
);
1588 var initializer_list
= new ArrayList
<Expression
> ();
1589 if (!accept (TokenType
.SEMICOLON
)) {
1591 switch (current ()) {
1595 case TokenType
.OP_INC
:
1596 case TokenType
.OP_DEC
:
1600 is_expr
= is_expression ();
1606 initializer_list
.add (parse_statement_expression ());
1607 } while (accept (TokenType
.COMMA
));
1609 block
= new
Block (get_src (begin
));
1610 DataType variable_type
;
1611 if (accept (TokenType
.VAR
)) {
1612 variable_type
= null;
1614 variable_type
= parse_type ();
1616 var local
= parse_local_variable (variable_type
);
1617 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1619 expect (TokenType
.SEMICOLON
);
1621 Expression condition
= null;
1622 if (current () != TokenType
.SEMICOLON
) {
1623 condition
= parse_expression ();
1625 expect (TokenType
.SEMICOLON
);
1626 var iterator_list
= new ArrayList
<Expression
> ();
1627 if (current () != TokenType
.CLOSE_PARENS
) {
1629 iterator_list
.add (parse_statement_expression ());
1630 } while (accept (TokenType
.COMMA
));
1632 expect (TokenType
.CLOSE_PARENS
);
1633 var src
= get_src (begin
);
1634 var body
= parse_embedded_statement ();
1635 var stmt
= new
ForStatement (condition
, body
, src
);
1636 foreach (Expression init
in initializer_list
) {
1637 stmt
.add_initializer (init
);
1639 foreach (Expression iter
in iterator_list
) {
1640 stmt
.add_iterator (iter
);
1642 if (block
!= null) {
1643 block
.add_statement (stmt
);
1650 Statement
parse_foreach_statement () throws ParseError
{
1651 var begin
= get_location ();
1652 expect (TokenType
.FOREACH
);
1653 expect (TokenType
.OPEN_PARENS
);
1654 DataType type
= null;
1655 if (!accept (TokenType
.VAR
)) {
1656 type
= parse_type ();
1658 string id
= parse_identifier ();
1659 expect (TokenType
.IN
);
1660 var collection
= parse_expression ();
1661 expect (TokenType
.CLOSE_PARENS
);
1662 var src
= get_src (begin
);
1663 var body
= parse_embedded_statement ();
1664 return new
ForeachStatement (type
, id
, collection
, body
, src
);
1667 Statement
parse_break_statement () throws ParseError
{
1668 var begin
= get_location ();
1669 expect (TokenType
.BREAK
);
1670 expect (TokenType
.SEMICOLON
);
1671 return new
BreakStatement (get_src (begin
));
1674 Statement
parse_continue_statement () throws ParseError
{
1675 var begin
= get_location ();
1676 expect (TokenType
.CONTINUE
);
1677 expect (TokenType
.SEMICOLON
);
1678 return new
ContinueStatement (get_src (begin
));
1681 Statement
parse_return_statement () throws ParseError
{
1682 var begin
= get_location ();
1683 expect (TokenType
.RETURN
);
1684 Expression expr
= null;
1685 if (current () != TokenType
.SEMICOLON
) {
1686 expr
= parse_expression ();
1688 expect (TokenType
.SEMICOLON
);
1689 return new
ReturnStatement (expr
, get_src (begin
));
1692 Statement
parse_yield_statement () throws ParseError
{
1693 var begin
= get_location ();
1694 expect (TokenType
.YIELD
);
1695 if (current () != TokenType
.SEMICOLON
&& current () != TokenType
.RETURN
) {
1698 return parse_expression_statement ();
1700 Expression expr
= null;
1701 if (accept (TokenType
.RETURN
)) {
1702 expr
= parse_expression ();
1704 expect (TokenType
.SEMICOLON
);
1705 return new
YieldStatement (expr
, get_src (begin
));
1708 Statement
parse_throw_statement () throws ParseError
{
1709 var begin
= get_location ();
1710 expect (TokenType
.THROW
);
1711 var expr
= parse_expression ();
1712 expect (TokenType
.SEMICOLON
);
1713 return new
ThrowStatement (expr
, get_src (begin
));
1716 Statement
parse_try_statement () throws ParseError
{
1717 var begin
= get_location ();
1718 expect (TokenType
.TRY
);
1719 var try_block
= parse_block ();
1720 Block finally_clause
= null;
1721 var catch_clauses
= new ArrayList
<CatchClause
> ();
1722 if (current () == TokenType
.CATCH
) {
1723 parse_catch_clauses (catch_clauses
);
1724 if (current () == TokenType
.FINALLY
) {
1725 finally_clause
= parse_finally_clause ();
1728 finally_clause
= parse_finally_clause ();
1730 var stmt
= new
TryStatement (try_block
, finally_clause
, get_src (begin
));
1731 foreach (CatchClause clause
in catch_clauses
) {
1732 stmt
.add_catch_clause (clause
);
1737 void parse_catch_clauses (Gee
.List
<CatchClause
> catch_clauses
) throws ParseError
{
1738 while (accept (TokenType
.CATCH
)) {
1739 var begin
= get_location ();
1740 DataType type
= null;
1742 if (accept (TokenType
.OPEN_PARENS
)) {
1743 type
= parse_type ();
1744 id
= parse_identifier ();
1745 expect (TokenType
.CLOSE_PARENS
);
1747 var block
= parse_block ();
1748 catch_clauses
.add (new
CatchClause (type
, id
, block
, get_src (begin
)));
1752 Block
parse_finally_clause () throws ParseError
{
1753 expect (TokenType
.FINALLY
);
1754 var block
= parse_block ();
1758 Statement
parse_lock_statement () throws ParseError
{
1759 var begin
= get_location ();
1760 expect (TokenType
.LOCK
);
1761 expect (TokenType
.OPEN_PARENS
);
1762 var expr
= parse_expression ();
1763 expect (TokenType
.CLOSE_PARENS
);
1764 var stmt
= parse_embedded_statement ();
1765 return new
LockStatement (expr
, stmt
, get_src (begin
));
1768 Statement
parse_delete_statement () throws ParseError
{
1769 var begin
= get_location ();
1770 expect (TokenType
.DELETE
);
1771 var expr
= parse_expression ();
1772 expect (TokenType
.SEMICOLON
);
1773 return new
DeleteStatement (expr
, get_src (begin
));
1776 Gee
.List
<Attribute
>?
parse_attributes () throws ParseError
{
1777 if (current () != TokenType
.OPEN_BRACKET
) {
1780 var attrs
= new ArrayList
<Attribute
> ();
1781 while (accept (TokenType
.OPEN_BRACKET
)) {
1783 var begin
= get_location ();
1784 string id
= parse_identifier ();
1785 var attr
= new
Attribute (id
, get_src (begin
));
1786 if (accept (TokenType
.OPEN_PARENS
)) {
1787 if (current () != TokenType
.CLOSE_PARENS
) {
1789 id
= parse_identifier ();
1790 expect (TokenType
.ASSIGN
);
1791 var expr
= parse_expression ();
1792 attr
.add_argument (id
, expr
);
1793 } while (accept (TokenType
.COMMA
));
1795 expect (TokenType
.CLOSE_PARENS
);
1798 } while (accept (TokenType
.COMMA
));
1799 expect (TokenType
.CLOSE_BRACKET
);
1804 void set_attributes (CodeNode node
, Gee
.List
<Attribute
>? attributes
) {
1805 if (attributes
!= null) {
1806 foreach (Attribute attr
in (Gee
.List
<Attribute
>) attributes
) {
1807 node
.attributes
.append (attr
);
1812 Symbol
parse_declaration () throws ParseError
{
1813 comment
= scanner
.pop_comment ();
1814 var attrs
= parse_attributes ();
1816 var begin
= get_location ();
1818 TokenType last_keyword
= current ();
1820 while (is_declaration_keyword (current ())) {
1821 last_keyword
= current ();
1825 switch (current ()) {
1826 case TokenType
.CONSTRUCT
:
1827 if (context
.profile
== Profile
.GOBJECT
) {
1829 return parse_constructor_declaration (attrs
);
1832 case TokenType
.TILDE
:
1834 return parse_destructor_declaration (attrs
);
1837 switch (current ()) {
1838 case TokenType
.OPEN_BRACE
:
1839 case TokenType
.SEMICOLON
:
1840 case TokenType
.COLON
:
1842 switch (last_keyword
) {
1843 case TokenType
.CLASS
: return parse_class_declaration (attrs
);
1844 case TokenType
.ENUM
: return parse_enum_declaration (attrs
);
1845 case TokenType
.ERRORDOMAIN
: return parse_errordomain_declaration (attrs
);
1846 case TokenType
.INTERFACE
: return parse_interface_declaration (attrs
);
1847 case TokenType
.NAMESPACE
: return parse_namespace_declaration (attrs
);
1848 case TokenType
.STRUCT
: return parse_struct_declaration (attrs
);
1852 case TokenType
.OPEN_PARENS
:
1854 return parse_creation_method_declaration (attrs
);
1856 skip_type (); // might contain type parameter list
1857 switch (current ()) {
1858 case TokenType
.OPEN_PARENS
:
1860 switch (last_keyword
) {
1861 case TokenType
.DELEGATE
: return parse_delegate_declaration (attrs
);
1862 case TokenType
.SIGNAL
: return parse_signal_declaration (attrs
);
1863 default: return parse_method_declaration (attrs
);
1865 case TokenType
.ASSIGN
:
1866 case TokenType
.SEMICOLON
:
1868 switch (last_keyword
) {
1869 case TokenType
.CONST
: return parse_constant_declaration (attrs
);
1870 default: return parse_field_declaration (attrs
);
1872 case TokenType
.OPEN_BRACE
:
1873 case TokenType
.THROWS
:
1875 return parse_property_declaration (attrs
);
1886 throw new ParseError
.SYNTAX (get_error ("expected declaration"));
1889 void parse_declarations (Symbol parent
, bool root
= false) throws ParseError
{
1891 expect (TokenType
.OPEN_BRACE
);
1893 while (current () != TokenType
.CLOSE_BRACE
&& current () != TokenType
.EOF
) {
1895 if (parent is Namespace
) {
1896 parse_namespace_member ((Namespace
) parent
);
1897 } else if (parent is Class
) {
1898 parse_class_member ((Class
) parent
);
1899 } else if (parent is Struct
) {
1900 parse_struct_member ((Struct
) parent
);
1901 } else if (parent is Interface
) {
1902 parse_interface_member ((Interface
) parent
);
1904 } catch (ParseError e
) {
1908 if (r
== RecoveryState
.STATEMENT_BEGIN
) {
1914 if (r
== RecoveryState
.EOF
) {
1920 if (!accept (TokenType
.CLOSE_BRACE
)) {
1921 // only report error if it's not a secondary error
1922 if (context
.report
.get_errors () == 0) {
1923 Report
.error (get_current_src (), "expected `}'");
1929 enum RecoveryState
{
1935 RecoveryState
recover () {
1936 while (current () != TokenType
.EOF
) {
1937 switch (current ()) {
1938 case TokenType
.ABSTRACT
:
1939 case TokenType
.CLASS
:
1940 case TokenType
.CONST
:
1941 case TokenType
.CONSTRUCT
:
1942 case TokenType
.DELEGATE
:
1943 case TokenType
.ENUM
:
1944 case TokenType
.ERRORDOMAIN
:
1945 case TokenType
.EXTERN
:
1946 case TokenType
.INLINE
:
1947 case TokenType
.INTERFACE
:
1948 case TokenType
.INTERNAL
:
1949 case TokenType
.NAMESPACE
:
1951 case TokenType
.OVERRIDE
:
1952 case TokenType
.PRIVATE
:
1953 case TokenType
.PROTECTED
:
1954 case TokenType
.PUBLIC
:
1955 case TokenType
.SIGNAL
:
1956 case TokenType
.STATIC
:
1957 case TokenType
.STRUCT
:
1958 case TokenType
.VIRTUAL
:
1959 case TokenType
.VOLATILE
:
1960 return RecoveryState
.DECLARATION_BEGIN
;
1961 case TokenType
.BREAK
:
1962 case TokenType
.CONTINUE
:
1963 case TokenType
.DELETE
:
1966 case TokenType
.FOREACH
:
1968 case TokenType
.LOCK
:
1969 case TokenType
.RETURN
:
1970 case TokenType
.SWITCH
:
1971 case TokenType
.THROW
:
1974 case TokenType
.WHILE
:
1975 case TokenType
.YIELD
:
1976 return RecoveryState
.STATEMENT_BEGIN
;
1982 return RecoveryState
.EOF
;
1985 Namespace
parse_namespace_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
1986 var begin
= get_location ();
1987 expect (TokenType
.NAMESPACE
);
1988 var sym
= parse_symbol_name ();
1989 var ns
= new
Namespace (sym
.name
, get_src (begin
));
1990 if (comment
!= null) {
1991 ns
.add_comment (comment
);
1995 set_attributes (ns
, attrs
);
1997 expect (TokenType
.OPEN_BRACE
);
1999 var old_using_directives
= scanner
.source_file
.current_using_directives
;
2000 parse_using_directives (ns
);
2002 parse_declarations (ns
, true);
2004 scanner
.source_file
.current_using_directives
= old_using_directives
;
2006 if (!accept (TokenType
.CLOSE_BRACE
)) {
2007 // only report error if it's not a secondary error
2008 if (context
.report
.get_errors () == 0) {
2009 Report
.error (get_current_src (), "expected `}'");
2013 Namespace result
= ns
;
2014 while (sym
.inner
!= null) {
2016 ns
= new
Namespace (sym
.name
, result
.source_reference
);
2017 ns
.add_namespace ((Namespace
) result
);
2023 void parse_namespace_member (Namespace ns
) throws ParseError
{
2024 var sym
= parse_declaration ();
2026 if (sym is Namespace
) {
2027 ns
.add_namespace ((Namespace
) sym
);
2028 } else if (sym is Class
) {
2029 ns
.add_class ((Class
) sym
);
2030 } else if (sym is Interface
) {
2031 ns
.add_interface ((Interface
) sym
);
2032 } else if (sym is Struct
) {
2033 ns
.add_struct ((Struct
) sym
);
2034 } else if (sym is Enum
) {
2035 ns
.add_enum ((Enum
) sym
);
2036 } else if (sym is ErrorDomain
) {
2037 ns
.add_error_domain ((ErrorDomain
) sym
);
2038 } else if (sym is Delegate
) {
2039 ns
.add_delegate ((Delegate
) sym
);
2040 } else if (sym is Method
) {
2041 var method
= (Method
) sym
;
2042 if (method
.binding
== MemberBinding
.INSTANCE
) {
2043 // default to static member binding
2044 method
.binding
= MemberBinding
.STATIC
;
2046 ns
.add_method (method
);
2047 } else if (sym is Field
) {
2048 var field
= (Field
) sym
;
2049 if (field
.binding
== MemberBinding
.INSTANCE
) {
2050 // default to static member binding
2051 field
.binding
= MemberBinding
.STATIC
;
2053 ns
.add_field (field
);
2054 } else if (sym is Constant
) {
2055 ns
.add_constant ((Constant
) sym
);
2057 Report
.error (sym
.source_reference
, "unexpected declaration in namespace");
2059 scanner
.source_file
.add_node (sym
);
2062 void parse_using_directives (Namespace ns
) throws ParseError
{
2063 while (accept (TokenType
.USING
)) {
2065 var begin
= get_location ();
2066 var sym
= parse_symbol_name ();
2067 var ns_ref
= new
UsingDirective (sym
, get_src (begin
));
2068 scanner
.source_file
.add_using_directive (ns_ref
);
2069 ns
.add_using_directive (ns_ref
);
2070 } while (accept (TokenType
.COMMA
));
2071 expect (TokenType
.SEMICOLON
);
2075 Symbol
parse_class_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2076 var begin
= get_location ();
2077 var access
= parse_access_modifier ();
2078 var flags
= parse_type_declaration_modifiers ();
2079 expect (TokenType
.CLASS
);
2080 var sym
= parse_symbol_name ();
2081 var type_param_list
= parse_type_parameter_list ();
2082 var base_types
= new ArrayList
<DataType
> ();
2083 if (accept (TokenType
.COLON
)) {
2085 base_types
.add (parse_type ());
2086 } while (accept (TokenType
.COMMA
));
2089 var cl
= new
Class (sym
.name
, get_src (begin
), comment
);
2091 if (ModifierFlags
.ABSTRACT
in flags
) {
2092 cl
.is_abstract
= true;
2094 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2097 set_attributes (cl
, attrs
);
2098 foreach (TypeParameter type_param
in type_param_list
) {
2099 cl
.add_type_parameter (type_param
);
2101 foreach (DataType base_type
in base_types
) {
2102 cl
.add_base_type (base_type
);
2105 parse_declarations (cl
);
2107 // ensure there is always a default construction method
2108 if (!scanner
.source_file
.external_package
2109 && cl
.default_construction_method
== null) {
2110 var m
= new
CreationMethod (cl
.name
, null, cl
.source_reference
);
2111 m
.access
= SymbolAccessibility
.PUBLIC
;
2112 m
.body
= new
Block (cl
.source_reference
);
2117 while (sym
.inner
!= null) {
2119 var ns
= new
Namespace (sym
.name
, cl
.source_reference
);
2120 if (result is Namespace
) {
2121 ns
.add_namespace ((Namespace
) result
);
2123 ns
.add_class ((Class
) result
);
2124 scanner
.source_file
.add_node (result
);
2131 void parse_class_member (Class cl
) throws ParseError
{
2132 var sym
= parse_declaration ();
2134 cl
.add_class ((Class
) sym
);
2135 } else if (sym is Struct
) {
2136 cl
.add_struct ((Struct
) sym
);
2137 } else if (sym is Enum
) {
2138 cl
.add_enum ((Enum
) sym
);
2139 } else if (sym is Delegate
) {
2140 cl
.add_delegate ((Delegate
) sym
);
2141 } else if (sym is Method
) {
2142 cl
.add_method ((Method
) sym
);
2143 } else if (sym is Signal
) {
2144 cl
.add_signal ((Signal
) sym
);
2145 } else if (sym is Field
) {
2146 cl
.add_field ((Field
) sym
);
2147 } else if (sym is Constant
) {
2148 cl
.add_constant ((Constant
) sym
);
2149 } else if (sym is Property
) {
2150 cl
.add_property ((Property
) sym
);
2151 } else if (sym is Constructor
) {
2152 var c
= (Constructor
) sym
;
2153 if (c
.binding
== MemberBinding
.INSTANCE
) {
2155 } else if (c
.binding
== MemberBinding
.CLASS
) {
2156 cl
.class_constructor
= c
;
2158 cl
.static_constructor
= c
;
2160 } else if (sym is Destructor
) {
2161 var d
= (Destructor
) sym
;
2162 if (d
.binding
== MemberBinding
.STATIC
) {
2163 cl
.static_destructor
= (Destructor
) d
;
2164 } else if (d
.binding
== MemberBinding
.CLASS
) {
2165 cl
.class_destructor
= (Destructor
) d
;
2167 cl
.destructor
= (Destructor
) d
;
2170 Report
.error (sym
.source_reference
, "unexpected declaration in class");
2174 Constant
parse_constant_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2175 var begin
= get_location ();
2176 var access
= parse_access_modifier ();
2177 var flags
= parse_member_declaration_modifiers ();
2178 expect (TokenType
.CONST
);
2179 var type
= parse_type (false);
2180 string id
= parse_identifier ();
2182 type
= parse_inline_array_type (type
);
2184 Expression initializer
= null;
2185 if (accept (TokenType
.ASSIGN
)) {
2186 initializer
= parse_expression ();
2188 expect (TokenType
.SEMICOLON
);
2190 // constant arrays don't own their element
2191 var array_type
= type as ArrayType
;
2192 if (array_type
!= null) {
2193 array_type
.element_type
.value_owned
= false;
2196 var c
= new
Constant (id
, type
, initializer
, get_src (begin
), comment
);
2198 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2201 if (ModifierFlags
.NEW
in flags
) {
2204 set_attributes (c
, attrs
);
2208 Field
parse_field_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2209 var begin
= get_location ();
2210 var access
= parse_access_modifier ();
2211 var flags
= parse_member_declaration_modifiers ();
2212 var type
= parse_type ();
2213 string id
= parse_identifier ();
2215 type
= parse_inline_array_type (type
);
2217 var f
= new
Field (id
, type
, null, get_src (begin
), comment
);
2219 set_attributes (f
, attrs
);
2220 if (ModifierFlags
.STATIC
in flags
) {
2221 f
.binding
= MemberBinding
.STATIC
;
2222 } else if (ModifierFlags
.CLASS
in flags
) {
2223 f
.binding
= MemberBinding
.CLASS
;
2225 if (ModifierFlags
.ABSTRACT
in flags
2226 || ModifierFlags
.VIRTUAL
in flags
2227 || ModifierFlags
.OVERRIDE
in flags
) {
2228 Report
.error (f
.source_reference
, "abstract, virtual, and override modifiers are not applicable to fields");
2230 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2233 if (ModifierFlags
.NEW
in flags
) {
2236 if (accept (TokenType
.ASSIGN
)) {
2237 f
.initializer
= parse_expression ();
2239 expect (TokenType
.SEMICOLON
);
2243 InitializerList
parse_initializer () throws ParseError
{
2244 var begin
= get_location ();
2245 expect (TokenType
.OPEN_BRACE
);
2246 var initializer
= new
InitializerList (get_src (begin
));
2247 if (current () != TokenType
.CLOSE_BRACE
) {
2249 var init
= parse_argument ();
2250 initializer
.append (init
);
2251 } while (accept (TokenType
.COMMA
));
2253 expect (TokenType
.CLOSE_BRACE
);
2257 Method
parse_method_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2258 var begin
= get_location ();
2259 var access
= parse_access_modifier ();
2260 var flags
= parse_member_declaration_modifiers ();
2261 var type
= parse_type ();
2262 string id
= parse_identifier ();
2263 var type_param_list
= parse_type_parameter_list ();
2264 var method
= new
Method (id
, type
, get_src (begin
), comment
);
2265 method
.access
= access
;
2266 set_attributes (method
, attrs
);
2267 foreach (TypeParameter type_param
in type_param_list
) {
2268 method
.add_type_parameter (type_param
);
2270 if (ModifierFlags
.STATIC
in flags
) {
2271 method
.binding
= MemberBinding
.STATIC
;
2272 } else if (ModifierFlags
.CLASS
in flags
) {
2273 method
.binding
= MemberBinding
.CLASS
;
2275 if (ModifierFlags
.ASYNC
in flags
) {
2276 method
.coroutine
= true;
2278 if (ModifierFlags
.NEW
in flags
) {
2279 method
.hides
= true;
2282 if (method
.binding
== MemberBinding
.INSTANCE
) {
2283 if (ModifierFlags
.ABSTRACT
in flags
) {
2284 method
.is_abstract
= true;
2286 if (ModifierFlags
.VIRTUAL
in flags
) {
2287 method
.is_virtual
= true;
2289 if (ModifierFlags
.OVERRIDE
in flags
) {
2290 method
.overrides
= true;
2292 if ((method
.is_abstract
&& method
.is_virtual
)
2293 || (method
.is_abstract
&& method
.overrides
)
2294 || (method
.is_virtual
&& method
.overrides
)) {
2295 throw new ParseError
.SYNTAX (get_error ("only one of `abstract', `virtual', or `override' may be specified"));
2298 if (ModifierFlags
.ABSTRACT
in flags
2299 || ModifierFlags
.VIRTUAL
in flags
2300 || ModifierFlags
.OVERRIDE
in flags
) {
2301 throw new ParseError
.SYNTAX (get_error ("the modifiers `abstract', `virtual', and `override' are not valid for static methods"));
2305 if (ModifierFlags
.INLINE
in flags
) {
2306 method
.is_inline
= true;
2308 if (ModifierFlags
.EXTERN
in flags
) {
2309 method
.external
= true;
2311 expect (TokenType
.OPEN_PARENS
);
2312 if (current () != TokenType
.CLOSE_PARENS
) {
2314 var param
= parse_parameter ();
2315 method
.add_parameter (param
);
2316 } while (accept (TokenType
.COMMA
));
2318 expect (TokenType
.CLOSE_PARENS
);
2319 if (accept (TokenType
.THROWS
)) {
2321 method
.add_error_type (parse_type ());
2322 } while (accept (TokenType
.COMMA
));
2324 while (accept (TokenType
.REQUIRES
)) {
2325 expect (TokenType
.OPEN_PARENS
);
2326 method
.add_precondition (parse_expression ());
2327 expect (TokenType
.CLOSE_PARENS
);
2329 while (accept (TokenType
.ENSURES
)) {
2330 expect (TokenType
.OPEN_PARENS
);
2331 method
.add_postcondition (parse_expression ());
2332 expect (TokenType
.CLOSE_PARENS
);
2334 if (!accept (TokenType
.SEMICOLON
)) {
2335 method
.body
= parse_block ();
2336 } else if (scanner
.source_file
.external_package
) {
2337 method
.external
= true;
2342 Property
parse_property_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2343 var begin
= get_location ();
2344 var access
= parse_access_modifier ();
2345 var flags
= parse_member_declaration_modifiers ();
2346 var type
= parse_type ();
2348 bool getter_owned
= false;
2349 if (accept (TokenType
.HASH
)) {
2350 if (!context
.deprecated
) {
2351 Report
.warning (get_last_src (), "deprecated syntax, use `owned` modifier before `get'");
2353 getter_owned
= true;
2356 string id
= parse_identifier ();
2357 var prop
= new
Property (id
, type
, null, null, get_src (begin
), comment
);
2358 prop
.access
= access
;
2359 set_attributes (prop
, attrs
);
2360 if (ModifierFlags
.STATIC
in flags
) {
2361 prop
.binding
= MemberBinding
.STATIC
;
2362 } else if (ModifierFlags
.CLASS
in flags
) {
2363 prop
.binding
= MemberBinding
.CLASS
;
2365 if (ModifierFlags
.ABSTRACT
in flags
) {
2366 prop
.is_abstract
= true;
2368 if (ModifierFlags
.VIRTUAL
in flags
) {
2369 prop
.is_virtual
= true;
2371 if (ModifierFlags
.OVERRIDE
in flags
) {
2372 prop
.overrides
= true;
2374 if (ModifierFlags
.NEW
in flags
) {
2377 if (ModifierFlags
.ASYNC
in flags
) {
2378 Report
.error (prop
.source_reference
, "async properties are not supported yet");
2380 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2381 prop
.external
= true;
2383 if (accept (TokenType
.THROWS
)) {
2385 prop
.add_error_type (parse_type ());
2386 } while (accept (TokenType
.COMMA
));
2387 Report
.error (prop
.source_reference
, "properties throwing errors are not supported yet");
2389 expect (TokenType
.OPEN_BRACE
);
2390 while (current () != TokenType
.CLOSE_BRACE
) {
2391 if (accept (TokenType
.DEFAULT
)) {
2392 if (prop
.default_expression
!= null) {
2393 throw new ParseError
.SYNTAX (get_error ("property default value already defined"));
2395 expect (TokenType
.ASSIGN
);
2396 prop
.default_expression
= parse_expression ();
2397 expect (TokenType
.SEMICOLON
);
2399 var accessor_begin
= get_location ();
2400 var accessor_attrs
= parse_attributes ();
2401 var accessor_access
= parse_access_modifier (SymbolAccessibility
.PUBLIC
);
2403 var value_type
= type
.copy ();
2404 value_type
.value_owned
= accept (TokenType
.OWNED
);
2406 if (accept (TokenType
.GET
)) {
2407 if (prop
.get_accessor
!= null) {
2408 throw new ParseError
.SYNTAX (get_error ("property get accessor already defined"));
2412 value_type
.value_owned
= true;
2416 if (!accept (TokenType
.SEMICOLON
)) {
2417 block
= parse_block ();
2418 prop
.external
= false;
2420 prop
.get_accessor
= new
PropertyAccessor (true, false, false, value_type
, block
, get_src (accessor_begin
));
2421 set_attributes (prop
.get_accessor
, accessor_attrs
);
2422 prop
.get_accessor
.access
= accessor_access
;
2424 bool writable
, _construct
;
2425 if (accept (TokenType
.SET
)) {
2427 _construct
= (context
.profile
== Profile
.GOBJECT
) && accept (TokenType
.CONSTRUCT
);
2428 } else if (context
.profile
== Profile
.GOBJECT
&& accept (TokenType
.CONSTRUCT
)) {
2430 writable
= accept (TokenType
.SET
);
2432 throw new ParseError
.SYNTAX (get_error ("expected get, set, or construct"));
2434 if (prop
.set_accessor
!= null) {
2435 throw new ParseError
.SYNTAX (get_error ("property set accessor already defined"));
2438 if (!accept (TokenType
.SEMICOLON
)) {
2439 block
= parse_block ();
2440 prop
.external
= false;
2442 prop
.set_accessor
= new
PropertyAccessor (false, writable
, _construct
, value_type
, block
, get_src (accessor_begin
));
2443 set_attributes (prop
.set_accessor
, accessor_attrs
);
2444 prop
.set_accessor
.access
= accessor_access
;
2448 expect (TokenType
.CLOSE_BRACE
);
2450 if (!prop
.is_abstract
&& !prop
.external
) {
2451 bool empty_get
= (prop
.get_accessor
!= null && prop
.get_accessor
.body
== null);
2452 bool empty_set
= (prop
.set_accessor
!= null && prop
.set_accessor
.body
== null);
2454 if (empty_get
!= empty_set
) {
2456 Report
.error (prop
.source_reference
, "property getter must have a body");
2457 } else if (empty_set
) {
2458 Report
.error (prop
.source_reference
, "property setter must have a body");
2463 if (empty_get
&& empty_set
) {
2464 /* automatic property accessor body generation */
2465 var field_type
= prop
.property_type
.copy ();
2466 prop
.field
= new
Field ("_%s".printf (prop
.name
), field_type
, prop
.default_expression
, prop
.source_reference
);
2467 prop
.field
.access
= SymbolAccessibility
.PRIVATE
;
2468 prop
.field
.binding
= prop
.binding
;
2475 Signal
parse_signal_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2476 var begin
= get_location ();
2477 var access
= parse_access_modifier ();
2478 var flags
= parse_member_declaration_modifiers ();
2479 expect (TokenType
.SIGNAL
);
2480 var type
= parse_type ();
2481 string id
= parse_identifier ();
2482 var sig
= new
Signal (id
, type
, get_src (begin
), comment
);
2483 sig
.access
= access
;
2484 set_attributes (sig
, attrs
);
2485 if (ModifierFlags
.STATIC
in flags
) {
2486 throw new ParseError
.SYNTAX (get_error ("`static' modifier not allowed on signals"));
2487 } else if (ModifierFlags
.CLASS
in flags
) {
2488 throw new ParseError
.SYNTAX (get_error ("`class' modifier not allowed on signals"));
2490 if (ModifierFlags
.VIRTUAL
in flags
) {
2491 sig
.is_virtual
= true;
2493 if (ModifierFlags
.NEW
in flags
) {
2496 expect (TokenType
.OPEN_PARENS
);
2497 if (current () != TokenType
.CLOSE_PARENS
) {
2499 var param
= parse_parameter ();
2500 sig
.add_parameter (param
);
2501 } while (accept (TokenType
.COMMA
));
2503 expect (TokenType
.CLOSE_PARENS
);
2504 if (!accept (TokenType
.SEMICOLON
)) {
2505 sig
.body
= parse_block ();
2511 Constructor
parse_constructor_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2512 var begin
= get_location ();
2513 var flags
= parse_member_declaration_modifiers ();
2514 expect (TokenType
.CONSTRUCT
);
2515 if (ModifierFlags
.NEW
in flags
) {
2516 throw new ParseError
.SYNTAX (get_error ("`new' modifier not allowed on constructor"));
2518 var c
= new
Constructor (get_src (begin
));
2519 if (ModifierFlags
.STATIC
in flags
) {
2520 c
.binding
= MemberBinding
.STATIC
;
2521 } else if (ModifierFlags
.CLASS
in flags
) {
2522 c
.binding
= MemberBinding
.CLASS
;
2524 c
.body
= parse_block ();
2528 Destructor
parse_destructor_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2529 var begin
= get_location ();
2530 var flags
= parse_member_declaration_modifiers ();
2531 expect (TokenType
.TILDE
);
2532 parse_identifier ();
2533 expect (TokenType
.OPEN_PARENS
);
2534 expect (TokenType
.CLOSE_PARENS
);
2535 if (ModifierFlags
.NEW
in flags
) {
2536 throw new ParseError
.SYNTAX (get_error ("`new' modifier not allowed on destructor"));
2538 var d
= new
Destructor (get_src (begin
));
2539 if (ModifierFlags
.STATIC
in flags
) {
2540 d
.binding
= MemberBinding
.STATIC
;
2541 } else if (ModifierFlags
.CLASS
in flags
) {
2542 d
.binding
= MemberBinding
.CLASS
;
2544 d
.body
= parse_block ();
2548 Symbol
parse_struct_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2549 var begin
= get_location ();
2550 var access
= parse_access_modifier ();
2551 var flags
= parse_type_declaration_modifiers ();
2552 expect (TokenType
.STRUCT
);
2553 var sym
= parse_symbol_name ();
2554 var type_param_list
= parse_type_parameter_list ();
2555 DataType base_type
= null;
2556 if (accept (TokenType
.COLON
)) {
2557 base_type
= parse_type ();
2559 var st
= new
Struct (sym
.name
, get_src (begin
), comment
);
2561 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2564 set_attributes (st
, attrs
);
2565 foreach (TypeParameter type_param
in type_param_list
) {
2566 st
.add_type_parameter (type_param
);
2568 if (base_type
!= null) {
2569 st
.base_type
= base_type
;
2572 parse_declarations (st
);
2575 while (sym
.inner
!= null) {
2578 var ns
= new
Namespace (sym
.name
, st
.source_reference
);
2579 if (result is Namespace
) {
2580 ns
.add_namespace ((Namespace
) result
);
2582 ns
.add_struct ((Struct
) result
);
2583 scanner
.source_file
.add_node (result
);
2590 void parse_struct_member (Struct st
) throws ParseError
{
2591 var sym
= parse_declaration ();
2592 if (sym is Method
) {
2593 st
.add_method ((Method
) sym
);
2594 } else if (sym is Field
) {
2595 st
.add_field ((Field
) sym
);
2596 } else if (sym is Constant
) {
2597 st
.add_constant ((Constant
) sym
);
2598 } else if (sym is Property
) {
2599 st
.add_property ((Property
) sym
);
2601 Report
.error (sym
.source_reference
, "unexpected declaration in struct");
2605 Symbol
parse_interface_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2606 var begin
= get_location ();
2607 var access
= parse_access_modifier ();
2608 var flags
= parse_type_declaration_modifiers ();
2609 expect (TokenType
.INTERFACE
);
2610 var sym
= parse_symbol_name ();
2611 var type_param_list
= parse_type_parameter_list ();
2612 var base_types
= new ArrayList
<DataType
> ();
2613 if (accept (TokenType
.COLON
)) {
2615 var type
= parse_type ();
2616 base_types
.add (type
);
2617 } while (accept (TokenType
.COMMA
));
2619 var iface
= new
Interface (sym
.name
, get_src (begin
), comment
);
2620 iface
.access
= access
;
2621 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2622 iface
.external
= true;
2624 set_attributes (iface
, attrs
);
2625 foreach (TypeParameter type_param
in type_param_list
) {
2626 iface
.add_type_parameter (type_param
);
2628 foreach (DataType base_type
in base_types
) {
2629 iface
.add_prerequisite (base_type
);
2632 parse_declarations (iface
);
2634 Symbol result
= iface
;
2635 while (sym
.inner
!= null) {
2637 var ns
= new
Namespace (sym
.name
, iface
.source_reference
);
2638 if (result is Namespace
) {
2639 ns
.add_namespace ((Namespace
) result
);
2641 ns
.add_interface ((Interface
) result
);
2642 scanner
.source_file
.add_node (result
);
2649 void parse_interface_member (Interface iface
) throws ParseError
{
2650 var sym
= parse_declaration ();
2652 iface
.add_class ((Class
) sym
);
2653 } else if (sym is Struct
) {
2654 iface
.add_struct ((Struct
) sym
);
2655 } else if (sym is Enum
) {
2656 iface
.add_enum ((Enum
) sym
);
2657 } else if (sym is Delegate
) {
2658 iface
.add_delegate ((Delegate
) sym
);
2659 } else if (sym is Method
) {
2660 iface
.add_method ((Method
) sym
);
2661 } else if (sym is Signal
) {
2662 iface
.add_signal ((Signal
) sym
);
2663 } else if (sym is Field
) {
2664 iface
.add_field ((Field
) sym
);
2665 } else if (sym is Constant
) {
2666 iface
.add_constant ((Constant
) sym
);
2667 } else if (sym is Property
) {
2668 iface
.add_property ((Property
) sym
);
2670 Report
.error (sym
.source_reference
, "unexpected declaration in interface");
2674 Symbol
parse_enum_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2675 var begin
= get_location ();
2676 var access
= parse_access_modifier ();
2677 var flags
= parse_type_declaration_modifiers ();
2678 expect (TokenType
.ENUM
);
2679 var sym
= parse_symbol_name ();
2680 var en
= new
Enum (sym
.name
, get_src (begin
), comment
);
2682 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2685 set_attributes (en
, attrs
);
2687 expect (TokenType
.OPEN_BRACE
);
2689 if (current () == TokenType
.CLOSE_BRACE
2690 && en
.get_values ().size
> 0) {
2691 // allow trailing comma
2694 var value_attrs
= parse_attributes ();
2695 var value_begin
= get_location ();
2696 string id
= parse_identifier ();
2697 comment
= scanner
.pop_comment ();
2698 var ev
= new
EnumValue (id
, get_src (value_begin
), comment
);
2699 set_attributes (ev
, value_attrs
);
2700 if (accept (TokenType
.ASSIGN
)) {
2701 ev
.value
= parse_expression ();
2704 } while (accept (TokenType
.COMMA
));
2705 if (accept (TokenType
.SEMICOLON
)) {
2707 while (current () != TokenType
.CLOSE_BRACE
) {
2708 var member_sym
= parse_declaration ();
2709 if (member_sym is Method
) {
2710 en
.add_method ((Method
) member_sym
);
2712 Report
.error (member_sym
.source_reference
, "unexpected declaration in enum");
2716 expect (TokenType
.CLOSE_BRACE
);
2719 while (sym
.inner
!= null) {
2721 var ns
= new
Namespace (sym
.name
, en
.source_reference
);
2722 if (result is Namespace
) {
2723 ns
.add_namespace ((Namespace
) result
);
2725 ns
.add_enum ((Enum
) result
);
2726 scanner
.source_file
.add_node (result
);
2733 Symbol
parse_errordomain_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2734 var begin
= get_location ();
2735 var access
= parse_access_modifier ();
2736 var flags
= parse_type_declaration_modifiers ();
2737 expect (TokenType
.ERRORDOMAIN
);
2738 var sym
= parse_symbol_name ();
2739 var ed
= new
ErrorDomain (sym
.name
, get_src (begin
), comment
);
2741 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2744 set_attributes (ed
, attrs
);
2746 expect (TokenType
.OPEN_BRACE
);
2748 if (current () == TokenType
.CLOSE_BRACE
2749 && ed
.get_codes ().size
> 0) {
2750 // allow trailing comma
2753 var code_attrs
= parse_attributes ();
2754 var code_begin
= get_location ();
2755 string id
= parse_identifier ();
2756 comment
= scanner
.pop_comment ();
2757 var ec
= new
ErrorCode (id
, get_src (code_begin
), comment
);
2758 set_attributes (ec
, code_attrs
);
2759 if (accept (TokenType
.ASSIGN
)) {
2760 ec
.value
= parse_expression ();
2763 } while (accept (TokenType
.COMMA
));
2764 if (accept (TokenType
.SEMICOLON
)) {
2765 // errordomain methods
2766 while (current () != TokenType
.CLOSE_BRACE
) {
2767 var member_sym
= parse_declaration ();
2768 if (member_sym is Method
) {
2769 ed
.add_method ((Method
) member_sym
);
2771 Report
.error (member_sym
.source_reference
, "unexpected declaration in errordomain");
2775 expect (TokenType
.CLOSE_BRACE
);
2778 while (sym
.inner
!= null) {
2780 var ns
= new
Namespace (sym
.name
, ed
.source_reference
);
2781 if (result is Namespace
) {
2782 ns
.add_namespace ((Namespace
) result
);
2784 ns
.add_error_domain ((ErrorDomain
) result
);
2785 scanner
.source_file
.add_node (result
);
2792 SymbolAccessibility
parse_access_modifier (SymbolAccessibility default_access
= SymbolAccessibility
.PRIVATE
) {
2793 switch (current ()) {
2794 case TokenType
.PRIVATE
:
2796 return SymbolAccessibility
.PRIVATE
;
2797 case TokenType
.PROTECTED
:
2799 return SymbolAccessibility
.PROTECTED
;
2800 case TokenType
.INTERNAL
:
2802 return SymbolAccessibility
.INTERNAL
;
2803 case TokenType
.PUBLIC
:
2805 return SymbolAccessibility
.PUBLIC
;
2807 return default_access
;
2811 ModifierFlags
parse_type_declaration_modifiers () {
2812 ModifierFlags flags
= 0;
2814 switch (current ()) {
2815 case TokenType
.ABSTRACT
:
2817 flags
|= ModifierFlags
.ABSTRACT
;
2819 case TokenType
.EXTERN
:
2821 flags
|= ModifierFlags
.EXTERN
;
2823 case TokenType
.STATIC
:
2825 flags
|= ModifierFlags
.STATIC
;
2833 ModifierFlags
parse_member_declaration_modifiers () {
2834 ModifierFlags flags
= 0;
2836 switch (current ()) {
2837 case TokenType
.ABSTRACT
:
2839 flags
|= ModifierFlags
.ABSTRACT
;
2841 case TokenType
.ASYNC
:
2843 flags
|= ModifierFlags
.ASYNC
;
2845 case TokenType
.CLASS
:
2847 flags
|= ModifierFlags
.CLASS
;
2849 case TokenType
.EXTERN
:
2851 flags
|= ModifierFlags
.EXTERN
;
2853 case TokenType
.INLINE
:
2855 flags
|= ModifierFlags
.INLINE
;
2859 flags
|= ModifierFlags
.NEW
;
2861 case TokenType
.OVERRIDE
:
2863 flags
|= ModifierFlags
.OVERRIDE
;
2865 case TokenType
.STATIC
:
2867 flags
|= ModifierFlags
.STATIC
;
2869 case TokenType
.VIRTUAL
:
2871 flags
|= ModifierFlags
.VIRTUAL
;
2879 FormalParameter
parse_parameter () throws ParseError
{
2880 var attrs
= parse_attributes ();
2881 var begin
= get_location ();
2882 if (accept (TokenType
.ELLIPSIS
)) {
2884 return new FormalParameter
.with_ellipsis (get_src (begin
));
2886 bool params_array
= accept (TokenType
.PARAMS
);
2887 var direction
= ParameterDirection
.IN
;
2888 if (accept (TokenType
.OUT
)) {
2889 direction
= ParameterDirection
.OUT
;
2890 } else if (accept (TokenType
.REF
)) {
2891 direction
= ParameterDirection
.REF
;
2895 if (direction
== ParameterDirection
.IN
) {
2896 // in parameters are weak by default
2897 type
= parse_type (false);
2899 // out parameters own the value by default
2900 type
= parse_type (true);
2902 string id
= parse_identifier ();
2903 var param
= new
FormalParameter (id
, type
, get_src (begin
));
2904 set_attributes (param
, attrs
);
2905 param
.direction
= direction
;
2906 param
.params_array
= params_array
;
2907 if (accept (TokenType
.ASSIGN
)) {
2908 param
.default_expression
= parse_expression ();
2913 CreationMethod
parse_creation_method_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2914 var begin
= get_location ();
2915 var access
= parse_access_modifier ();
2916 var flags
= parse_member_declaration_modifiers ();
2917 var sym
= parse_symbol_name ();
2918 if (ModifierFlags
.NEW
in flags
) {
2919 throw new ParseError
.SYNTAX (get_error ("`new' modifier not allowed on creation method"));
2921 CreationMethod method
;
2922 if (sym
.inner
== null) {
2923 method
= new
CreationMethod (sym
.name
, null, get_src (begin
), comment
);
2925 method
= new
CreationMethod (sym
.inner
.name
, sym
.name
, get_src (begin
), comment
);
2927 if (ModifierFlags
.EXTERN
in flags
) {
2928 method
.external
= true;
2930 if (ModifierFlags
.ABSTRACT
in flags
2931 || ModifierFlags
.VIRTUAL
in flags
2932 || ModifierFlags
.OVERRIDE
in flags
) {
2933 Report
.error (method
.source_reference
, "abstract, virtual, and override modifiers are not applicable to creation methods");
2935 if (ModifierFlags
.ASYNC
in flags
) {
2936 method
.coroutine
= true;
2938 expect (TokenType
.OPEN_PARENS
);
2939 if (current () != TokenType
.CLOSE_PARENS
) {
2941 var param
= parse_parameter ();
2942 method
.add_parameter (param
);
2943 } while (accept (TokenType
.COMMA
));
2945 expect (TokenType
.CLOSE_PARENS
);
2946 if (accept (TokenType
.THROWS
)) {
2948 method
.add_error_type (parse_type ());
2949 } while (accept (TokenType
.COMMA
));
2951 method
.access
= access
;
2952 set_attributes (method
, attrs
);
2953 if (!accept (TokenType
.SEMICOLON
)) {
2954 method
.body
= parse_block ();
2955 } else if (scanner
.source_file
.external_package
) {
2956 method
.external
= true;
2961 Symbol
parse_delegate_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2962 var begin
= get_location ();
2963 var access
= parse_access_modifier ();
2964 var flags
= parse_member_declaration_modifiers ();
2965 expect (TokenType
.DELEGATE
);
2966 if (ModifierFlags
.NEW
in flags
) {
2967 throw new ParseError
.SYNTAX (get_error ("`new' modifier not allowed on delegates"));
2969 var type
= parse_type ();
2970 var sym
= parse_symbol_name ();
2971 var type_param_list
= parse_type_parameter_list ();
2972 var d
= new
Delegate (sym
.name
, type
, get_src (begin
), comment
);
2974 set_attributes (d
, attrs
);
2975 if (ModifierFlags
.STATIC
in flags
) {
2976 if (!context
.deprecated
) {
2977 // TODO enable warning in future releases
2978 // Report.warning (get_last_src (), "deprecated syntax, use [CCode (has_target = false)]");
2981 d
.has_target
= true;
2983 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2986 foreach (TypeParameter type_param
in type_param_list
) {
2987 d
.add_type_parameter (type_param
);
2989 expect (TokenType
.OPEN_PARENS
);
2990 if (current () != TokenType
.CLOSE_PARENS
) {
2992 var param
= parse_parameter ();
2993 d
.add_parameter (param
);
2994 } while (accept (TokenType
.COMMA
));
2996 expect (TokenType
.CLOSE_PARENS
);
2997 if (accept (TokenType
.THROWS
)) {
2999 d
.add_error_type (parse_type ());
3000 } while (accept (TokenType
.COMMA
));
3002 expect (TokenType
.SEMICOLON
);
3005 while (sym
.inner
!= null) {
3007 var ns
= new
Namespace (sym
.name
, d
.source_reference
);
3008 if (result is Namespace
) {
3009 ns
.add_namespace ((Namespace
) result
);
3011 ns
.add_delegate ((Delegate
) result
);
3012 scanner
.source_file
.add_node (result
);
3019 Gee
.List
<TypeParameter
> parse_type_parameter_list () throws ParseError
{
3020 var list
= new ArrayList
<TypeParameter
> ();
3021 if (accept (TokenType
.OP_LT
)) {
3023 var begin
= get_location ();
3024 string id
= parse_identifier ();
3025 list
.add (new
TypeParameter (id
, get_src (begin
)));
3026 } while (accept (TokenType
.COMMA
));
3027 expect (TokenType
.OP_GT
);
3032 void skip_type_argument_list () throws ParseError
{
3033 if (accept (TokenType
.OP_LT
)) {
3036 } while (accept (TokenType
.COMMA
));
3037 expect (TokenType
.OP_GT
);
3041 // try to parse type argument list
3042 Gee
.List
<DataType
>?
parse_type_argument_list (bool maybe_expression
) throws ParseError
{
3043 var begin
= get_location ();
3044 if (accept (TokenType
.OP_LT
)) {
3045 var list
= new ArrayList
<DataType
> ();
3047 switch (current ()) {
3048 case TokenType
.VOID
:
3049 case TokenType
.DYNAMIC
:
3050 case TokenType
.UNOWNED
:
3051 case TokenType
.WEAK
:
3052 case TokenType
.IDENTIFIER
:
3053 var type
= parse_type ();
3060 } while (accept (TokenType
.COMMA
));
3061 if (!accept (TokenType
.OP_GT
)) {
3065 if (maybe_expression
) {
3066 // check follower to decide whether to keep type argument list
3067 switch (current ()) {
3068 case TokenType
.OPEN_PARENS
:
3069 case TokenType
.CLOSE_PARENS
:
3070 case TokenType
.CLOSE_BRACKET
:
3071 case TokenType
.COLON
:
3072 case TokenType
.SEMICOLON
:
3073 case TokenType
.COMMA
:
3075 case TokenType
.INTERR
:
3076 case TokenType
.OP_EQ
:
3077 case TokenType
.OP_NE
:
3078 // keep type argument list
3081 // interpret tokens as expression
3091 MemberAccess
parse_member_name () throws ParseError
{
3092 var begin
= get_location ();
3093 MemberAccess expr
= null;
3096 string id
= parse_identifier ();
3098 // The first member access can be global:: qualified
3099 bool qualified
= false;
3100 if (first
&& id
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
3101 id
= parse_identifier ();
3105 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (false);
3106 expr
= new
MemberAccess (expr
, id
, get_src (begin
));
3107 expr
.qualified
= qualified
;
3108 if (type_arg_list
!= null) {
3109 foreach (DataType type_arg
in type_arg_list
) {
3110 expr
.add_type_argument (type_arg
);
3115 } while (accept (TokenType
.DOT
));
3119 bool is_declaration_keyword (TokenType type
) {
3121 case TokenType
.ABSTRACT
:
3122 case TokenType
.ASYNC
:
3123 case TokenType
.CLASS
:
3124 case TokenType
.CONST
:
3125 case TokenType
.DELEGATE
:
3126 case TokenType
.ENUM
:
3127 case TokenType
.ERRORDOMAIN
:
3128 case TokenType
.EXTERN
:
3129 case TokenType
.INLINE
:
3130 case TokenType
.INTERFACE
:
3131 case TokenType
.INTERNAL
:
3132 case TokenType
.NAMESPACE
:
3134 case TokenType
.OVERRIDE
:
3135 case TokenType
.PRIVATE
:
3136 case TokenType
.PROTECTED
:
3137 case TokenType
.PUBLIC
:
3138 case TokenType
.SIGNAL
:
3139 case TokenType
.STATIC
:
3140 case TokenType
.STRUCT
:
3141 case TokenType
.VIRTUAL
:
3142 case TokenType
.VOLATILE
:
3150 public errordomain Vala
.ParseError
{