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
;
63 tokens
= new TokenInfo
[BUFFER_SIZE
];
67 * Parses all .vala and .vapi source files in the specified code
68 * context and builds a code tree.
70 * @param context a code context
72 public void parse (CodeContext context
) {
73 this
.context
= context
;
74 context
.accept (this
);
77 public override void visit_source_file (SourceFile source_file
) {
78 if (source_file
.filename
.has_suffix (".vala") || source_file
.filename
.has_suffix (".vapi")) {
79 parse_file (source_file
);
84 index
= (index
+ 1) % BUFFER_SIZE
;
87 SourceLocation begin
, end
;
88 TokenType type
= scanner
.read_token (out begin
, out end
);
89 tokens
[index
].type
= type
;
90 tokens
[index
].begin
= begin
;
91 tokens
[index
].end
= end
;
94 return (tokens
[index
].type
!= TokenType
.EOF
);
98 index
= (index
- 1 + BUFFER_SIZE
) % BUFFER_SIZE
;
100 assert (size
<= BUFFER_SIZE
);
103 inline TokenType
current () {
104 return tokens
[index
].type
;
107 inline
bool accept (TokenType type
) {
108 if (current () == type
) {
115 string get_error (string msg
) {
116 var begin
= get_location ();
118 Report
.error (get_src (begin
), "syntax error, " + msg
);
122 inline
bool expect (TokenType type
) throws ParseError
{
127 throw new ParseError
.SYNTAX (get_error ("expected %s".printf (type
.to_string ())));
130 inline SourceLocation
get_location () {
131 return tokens
[index
].begin
;
134 string get_current_string () {
135 return ((string) tokens
[index
].begin
.pos
).ndup ((tokens
[index
].end
.pos
- tokens
[index
].begin
.pos
));
138 string get_last_string () {
139 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
140 return ((string) tokens
[last_index
].begin
.pos
).ndup ((tokens
[last_index
].end
.pos
- tokens
[last_index
].begin
.pos
));
143 SourceReference
get_src (SourceLocation begin
) {
144 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
146 return new
SourceReference (scanner
.source_file
, begin
.line
, begin
.column
, tokens
[last_index
].end
.line
, tokens
[last_index
].end
.column
);
149 SourceReference
get_src_com (SourceLocation begin
) {
150 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
152 var src
= new SourceReference
.with_comment (scanner
.source_file
, begin
.line
, begin
.column
, tokens
[last_index
].end
.line
, tokens
[last_index
].end
.column
, comment
);
157 SourceReference
get_current_src () {
158 return new
SourceReference (scanner
.source_file
, tokens
[index
].begin
.line
, tokens
[index
].begin
.column
, tokens
[index
].end
.line
, tokens
[index
].end
.column
);
161 SourceReference
get_last_src () {
162 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
164 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
);
167 void rollback (SourceLocation location
) {
168 while (tokens
[index
].begin
.pos
!= location
.pos
) {
173 void skip_identifier () throws ParseError
{
174 // also accept keywords as identifiers where there is no conflict
175 switch (current ()) {
176 case TokenType
.ABSTRACT
:
179 case TokenType
.BREAK
:
181 case TokenType
.CATCH
:
182 case TokenType
.CLASS
:
183 case TokenType
.CONST
:
184 case TokenType
.CONSTRUCT
:
185 case TokenType
.CONTINUE
:
186 case TokenType
.DEFAULT
:
187 case TokenType
.DELEGATE
:
188 case TokenType
.DELETE
:
190 case TokenType
.DYNAMIC
:
193 case TokenType
.ENSURES
:
194 case TokenType
.ERRORDOMAIN
:
195 case TokenType
.EXTERN
:
196 case TokenType
.FALSE
:
197 case TokenType
.FINALLY
:
199 case TokenType
.FOREACH
:
201 case TokenType
.IDENTIFIER
:
204 case TokenType
.INLINE
:
205 case TokenType
.INTERFACE
:
206 case TokenType
.INTERNAL
:
209 case TokenType
.NAMESPACE
:
213 case TokenType
.OVERRIDE
:
214 case TokenType
.OWNED
:
215 case TokenType
.PARAMS
:
216 case TokenType
.PRIVATE
:
217 case TokenType
.PROTECTED
:
218 case TokenType
.PUBLIC
:
220 case TokenType
.REQUIRES
:
221 case TokenType
.RETURN
:
223 case TokenType
.SIGNAL
:
224 case TokenType
.SIZEOF
:
225 case TokenType
.STATIC
:
226 case TokenType
.STRUCT
:
227 case TokenType
.SWITCH
:
229 case TokenType
.THROW
:
230 case TokenType
.THROWS
:
233 case TokenType
.TYPEOF
:
234 case TokenType
.UNOWNED
:
235 case TokenType
.USING
:
237 case TokenType
.VIRTUAL
:
239 case TokenType
.VOLATILE
:
241 case TokenType
.WHILE
:
242 case TokenType
.YIELD
:
243 case TokenType
.YIELDS
:
246 case TokenType
.INTEGER_LITERAL
:
247 case TokenType
.REAL_LITERAL
:
248 // also accept integer and real literals
249 // as long as they contain at least one character
250 // and no decimal point
251 // for example, 2D and 3D
252 string id
= get_current_string ();
253 if (id
[id
.length
- 1].isalpha () && !("." in id
)) {
260 throw new ParseError
.SYNTAX (get_error ("expected identifier"));
263 string parse_identifier () throws ParseError
{
265 return get_last_string ();
268 Expression
parse_literal () throws ParseError
{
269 var begin
= get_location ();
271 switch (current ()) {
274 return new
BooleanLiteral (true, get_src (begin
));
275 case TokenType
.FALSE
:
277 return new
BooleanLiteral (false, get_src (begin
));
278 case TokenType
.INTEGER_LITERAL
:
280 return new
IntegerLiteral (get_last_string (), get_src (begin
));
281 case TokenType
.REAL_LITERAL
:
283 return new
RealLiteral (get_last_string (), get_src (begin
));
284 case TokenType
.CHARACTER_LITERAL
:
286 // FIXME validate and unescape here and just pass unichar to CharacterLiteral
287 var lit
= new
CharacterLiteral (get_last_string (), get_src (begin
));
289 Report
.error (lit
.source_reference
, "invalid character literal");
292 case TokenType
.STRING_LITERAL
:
294 return new
StringLiteral (get_last_string (), get_src (begin
));
295 case TokenType
.VERBATIM_STRING_LITERAL
:
297 string raw_string
= get_last_string ();
298 string escaped_string
= raw_string
.substring (3, raw_string
.len () - 6).escape ("");
299 return new
StringLiteral ("\"%s\"".printf (escaped_string
), get_src (begin
));
302 return new
NullLiteral (get_src (begin
));
304 throw new ParseError
.SYNTAX (get_error ("expected literal"));
308 public void parse_file (SourceFile source_file
) {
309 scanner
= new
Scanner (source_file
);
317 parse_using_directives ();
318 parse_declarations (context
.root
, true);
319 } catch (ParseError e
) {
326 void skip_symbol_name () throws ParseError
{
329 } while (accept (TokenType
.DOT
) || accept (TokenType
.DOUBLE_COLON
));
332 UnresolvedSymbol
parse_symbol_name () throws ParseError
{
333 var begin
= get_location ();
334 UnresolvedSymbol sym
= null;
336 string name
= parse_identifier ();
337 if (name
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
339 // qualified access to global symbol
340 name
= parse_identifier ();
341 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
342 sym
.qualified
= true;
345 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
346 } while (accept (TokenType
.DOT
));
350 void skip_type () throws ParseError
{
351 if (accept (TokenType
.VOID
)) {
352 while (accept (TokenType
.STAR
)) {
356 accept (TokenType
.DYNAMIC
);
357 accept (TokenType
.OWNED
);
358 accept (TokenType
.UNOWNED
);
359 accept (TokenType
.WEAK
);
361 skip_type_argument_list ();
362 while (accept (TokenType
.STAR
)) {
364 accept (TokenType
.INTERR
);
365 while (accept (TokenType
.OPEN_BRACKET
)) {
367 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
370 } while (accept (TokenType
.COMMA
));
371 expect (TokenType
.CLOSE_BRACKET
);
372 accept (TokenType
.INTERR
);
374 accept (TokenType
.OP_NEG
);
375 accept (TokenType
.HASH
);
378 DataType
parse_type (bool owned_by_default
= true) throws ParseError
{
379 var begin
= get_location ();
381 if (accept (TokenType
.VOID
)) {
382 DataType type
= new
VoidType (get_src (begin
));
383 while (accept (TokenType
.STAR
)) {
384 type
= new
PointerType (type
);
389 bool is_dynamic
= accept (TokenType
.DYNAMIC
);
391 bool value_owned
= owned_by_default
;
393 if (owned_by_default
) {
394 if (accept (TokenType
.UNOWNED
)
395 || accept (TokenType
.WEAK
)) {
399 value_owned
= accept (TokenType
.OWNED
);
402 var sym
= parse_symbol_name ();
403 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (false);
405 DataType type
= new UnresolvedType
.from_symbol (sym
, get_src (begin
));
406 if (type_arg_list
!= null) {
407 foreach (DataType type_arg
in type_arg_list
) {
408 type
.add_type_argument (type_arg
);
412 while (accept (TokenType
.STAR
)) {
413 type
= new
PointerType (type
, get_src (begin
));
416 if (!(type is PointerType
)) {
417 type
.nullable
= accept (TokenType
.INTERR
);
420 // array brackets in types are read from right to left,
421 // this is more logical, especially when nullable arrays
422 // or pointers are involved
423 while (accept (TokenType
.OPEN_BRACKET
)) {
427 // support for stack-allocated arrays
428 // also required for decision between expression and declaration statement
429 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
433 while (accept (TokenType
.COMMA
));
434 expect (TokenType
.CLOSE_BRACKET
);
436 // arrays contain strong references by default
437 type
.value_owned
= true;
439 type
= new
ArrayType (type
, array_rank
, get_src (begin
));
440 type
.nullable
= accept (TokenType
.INTERR
);
443 if (accept (TokenType
.OP_NEG
)) {
444 Report
.warning (get_last_src (), "obsolete syntax, types are non-null by default");
447 if (!owned_by_default
) {
448 if (accept (TokenType
.HASH
)) {
449 // TODO enable warning after releasing Vala 0.5.5
450 // Report.warning (get_last_src (), "deprecated syntax, use `owned` modifier");
455 type
.is_dynamic
= is_dynamic
;
456 type
.value_owned
= value_owned
;
460 Gee
.List
<Expression
> parse_argument_list () throws ParseError
{
461 var list
= new ArrayList
<Expression
> ();
462 if (current () != TokenType
.CLOSE_PARENS
) {
464 list
.add (parse_argument ());
465 } while (accept (TokenType
.COMMA
));
470 Expression
parse_argument () throws ParseError
{
471 var begin
= get_location ();
473 if (accept (TokenType
.REF
)) {
474 var inner
= parse_expression ();
475 return new
UnaryExpression (UnaryOperator
.REF
, inner
, get_src (begin
));
476 } else if (accept (TokenType
.OUT
)) {
477 var inner
= parse_expression ();
478 return new
UnaryExpression (UnaryOperator
.OUT
, inner
, get_src (begin
));
480 return parse_expression ();
484 Expression
parse_primary_expression () throws ParseError
{
485 var begin
= get_location ();
489 switch (current ()) {
491 case TokenType
.FALSE
:
492 case TokenType
.INTEGER_LITERAL
:
493 case TokenType
.REAL_LITERAL
:
494 case TokenType
.CHARACTER_LITERAL
:
495 case TokenType
.STRING_LITERAL
:
496 case TokenType
.VERBATIM_STRING_LITERAL
:
498 expr
= parse_literal ();
500 case TokenType
.OPEN_BRACE
:
501 expr
= parse_initializer ();
503 case TokenType
.OPEN_PARENS
:
504 expr
= parse_tuple ();
507 expr
= parse_this_access ();
510 expr
= parse_base_access ();
513 expr
= parse_object_or_array_creation_expression ();
515 case TokenType
.SIZEOF
:
516 expr
= parse_sizeof_expression ();
518 case TokenType
.TYPEOF
:
519 expr
= parse_typeof_expression ();
522 expr
= parse_simple_name ();
526 // process primary expressions that start with an inner primary expression
529 switch (current ()) {
531 expr
= parse_member_access (begin
, expr
);
533 case TokenType
.OP_PTR
:
534 expr
= parse_pointer_member_access (begin
, expr
);
536 case TokenType
.OPEN_PARENS
:
537 expr
= parse_method_call (begin
, expr
);
539 case TokenType
.OPEN_BRACKET
:
540 expr
= parse_element_access (begin
, expr
);
542 case TokenType
.OP_INC
:
543 expr
= parse_post_increment_expression (begin
, expr
);
545 case TokenType
.OP_DEC
:
546 expr
= parse_post_decrement_expression (begin
, expr
);
557 Expression
parse_simple_name () throws ParseError
{
558 var begin
= get_location ();
559 string id
= parse_identifier ();
560 bool qualified
= false;
561 if (id
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
562 id
= parse_identifier ();
565 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (true);
566 var expr
= new
MemberAccess (null, id
, get_src (begin
));
567 expr
.qualified
= qualified
;
568 if (type_arg_list
!= null) {
569 foreach (DataType type_arg
in type_arg_list
) {
570 expr
.add_type_argument (type_arg
);
576 Expression
parse_tuple () throws ParseError
{
577 var begin
= get_location ();
578 expect (TokenType
.OPEN_PARENS
);
579 var expr_list
= new ArrayList
<Expression
> ();
580 if (current () != TokenType
.CLOSE_PARENS
) {
582 expr_list
.add (parse_expression ());
583 } while (accept (TokenType
.COMMA
));
585 expect (TokenType
.CLOSE_PARENS
);
586 if (expr_list
.size
!= 1) {
587 var tuple
= new
Tuple ();
588 foreach (Expression expr
in expr_list
) {
589 tuple
.add_expression (expr
);
593 return new
ParenthesizedExpression (expr_list
.get (0), get_src (begin
));
596 Expression
parse_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
597 expect (TokenType
.DOT
);
598 string id
= parse_identifier ();
599 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (true);
600 var expr
= new
MemberAccess (inner
, id
, get_src (begin
));
601 if (type_arg_list
!= null) {
602 foreach (DataType type_arg
in type_arg_list
) {
603 expr
.add_type_argument (type_arg
);
609 Expression
parse_pointer_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
610 expect (TokenType
.OP_PTR
);
611 string id
= parse_identifier ();
612 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (true);
613 var expr
= new MemberAccess
.pointer (inner
, id
, get_src (begin
));
614 if (type_arg_list
!= null) {
615 foreach (DataType type_arg
in type_arg_list
) {
616 expr
.add_type_argument (type_arg
);
622 Expression
parse_method_call (SourceLocation begin
, Expression inner
) throws ParseError
{
623 expect (TokenType
.OPEN_PARENS
);
624 var arg_list
= parse_argument_list ();
625 expect (TokenType
.CLOSE_PARENS
);
626 var init_list
= parse_object_initializer ();
628 if (init_list
.size
> 0 && inner is MemberAccess
) {
629 // struct creation expression
630 var member
= (MemberAccess
) inner
;
631 member
.creation_member
= true;
633 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
634 expr
.struct_creation
= true;
635 foreach (Expression arg
in arg_list
) {
636 expr
.add_argument (arg
);
638 foreach (MemberInitializer initializer
in init_list
) {
639 expr
.add_member_initializer (initializer
);
643 var expr
= new
MethodCall (inner
, get_src (begin
));
644 foreach (Expression arg
in arg_list
) {
645 expr
.add_argument (arg
);
651 Expression
parse_element_access (SourceLocation begin
, Expression inner
) throws ParseError
{
652 expect (TokenType
.OPEN_BRACKET
);
653 var index_list
= parse_expression_list ();
654 expect (TokenType
.CLOSE_BRACKET
);
656 var expr
= new
ElementAccess (inner
, get_src (begin
));
657 foreach (Expression index
in index_list
) {
658 expr
.append_index (index
);
663 Gee
.List
<Expression
> parse_expression_list () throws ParseError
{
664 var list
= new ArrayList
<Expression
> ();
666 list
.add (parse_expression ());
667 } while (accept (TokenType
.COMMA
));
671 Expression
parse_this_access () throws ParseError
{
672 var begin
= get_location ();
673 expect (TokenType
.THIS
);
674 return new
MemberAccess (null, "this", get_src (begin
));
677 Expression
parse_base_access () throws ParseError
{
678 var begin
= get_location ();
679 expect (TokenType
.BASE
);
680 return new
BaseAccess (get_src (begin
));
683 Expression
parse_post_increment_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
684 expect (TokenType
.OP_INC
);
685 return new
PostfixExpression (inner
, true, get_src (begin
));
688 Expression
parse_post_decrement_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
689 expect (TokenType
.OP_DEC
);
690 return new
PostfixExpression (inner
, false, get_src (begin
));
693 Expression
parse_object_or_array_creation_expression () throws ParseError
{
694 var begin
= get_location ();
695 expect (TokenType
.NEW
);
696 var member
= parse_member_name ();
697 if (accept (TokenType
.OPEN_PARENS
)) {
698 var expr
= parse_object_creation_expression (begin
, member
);
700 } else if (accept (TokenType
.OPEN_BRACKET
)) {
701 var expr
= parse_array_creation_expression (begin
, member
);
704 throw new ParseError
.SYNTAX (get_error ("expected ( or ["));
708 Expression
parse_object_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
709 member
.creation_member
= true;
710 var arg_list
= parse_argument_list ();
711 expect (TokenType
.CLOSE_PARENS
);
712 var init_list
= parse_object_initializer ();
714 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
715 foreach (Expression arg
in arg_list
) {
716 expr
.add_argument (arg
);
718 foreach (MemberInitializer initializer
in init_list
) {
719 expr
.add_member_initializer (initializer
);
724 Expression
parse_array_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
725 bool size_specified
= false;
726 Gee
.List
<Expression
> size_specifier_list
= null;
728 DataType element_type
= UnresolvedType
.new_from_expression (member
);
731 // array of arrays: new T[][42]
732 element_type
= new
ArrayType (element_type
, size_specifier_list
.size
, element_type
.source_reference
);
737 size_specifier_list
= new ArrayList
<Expression
> ();
739 Expression size
= null;
740 if (current () != TokenType
.CLOSE_BRACKET
&& current () != TokenType
.COMMA
) {
741 size
= parse_expression ();
742 size_specified
= true;
744 size_specifier_list
.add (size
);
745 } while (accept (TokenType
.COMMA
));
746 expect (TokenType
.CLOSE_BRACKET
);
747 } while (accept (TokenType
.OPEN_BRACKET
));
749 InitializerList initializer
= null;
750 if (current () == TokenType
.OPEN_BRACE
) {
751 initializer
= parse_initializer ();
753 var expr
= new
ArrayCreationExpression (element_type
, size_specifier_list
.size
, initializer
, get_src (begin
));
754 if (size_specified
) {
755 foreach (Expression size
in size_specifier_list
) {
756 expr
.append_size (size
);
762 Gee
.List
<MemberInitializer
> parse_object_initializer () throws ParseError
{
763 var list
= new ArrayList
<MemberInitializer
> ();
764 if (accept (TokenType
.OPEN_BRACE
)) {
766 list
.add (parse_member_initializer ());
767 } while (accept (TokenType
.COMMA
));
768 expect (TokenType
.CLOSE_BRACE
);
773 MemberInitializer
parse_member_initializer () throws ParseError
{
774 var begin
= get_location ();
775 string id
= parse_identifier ();
776 expect (TokenType
.ASSIGN
);
777 var expr
= parse_expression ();
779 return new
MemberInitializer (id
, expr
, get_src (begin
));
782 Expression
parse_sizeof_expression () throws ParseError
{
783 var begin
= get_location ();
784 expect (TokenType
.SIZEOF
);
785 expect (TokenType
.OPEN_PARENS
);
786 var type
= parse_type ();
787 expect (TokenType
.CLOSE_PARENS
);
789 return new
SizeofExpression (type
, get_src (begin
));
792 Expression
parse_typeof_expression () throws ParseError
{
793 var begin
= get_location ();
794 expect (TokenType
.TYPEOF
);
795 expect (TokenType
.OPEN_PARENS
);
796 var type
= parse_type ();
797 expect (TokenType
.CLOSE_PARENS
);
799 return new
TypeofExpression (type
, get_src (begin
));
802 UnaryOperator
get_unary_operator (TokenType token_type
) {
803 switch (token_type
) {
804 case TokenType
.PLUS
: return UnaryOperator
.PLUS
;
805 case TokenType
.MINUS
: return UnaryOperator
.MINUS
;
806 case TokenType
.OP_NEG
: return UnaryOperator
.LOGICAL_NEGATION
;
807 case TokenType
.TILDE
: return UnaryOperator
.BITWISE_COMPLEMENT
;
808 case TokenType
.OP_INC
: return UnaryOperator
.INCREMENT
;
809 case TokenType
.OP_DEC
: return UnaryOperator
.DECREMENT
;
810 default: return UnaryOperator
.NONE
;
814 Expression
parse_unary_expression () throws ParseError
{
815 var begin
= get_location ();
816 var operator
= get_unary_operator (current ());
817 if (operator
!= UnaryOperator
.NONE
) {
819 var op
= parse_unary_expression ();
820 return new
UnaryExpression (operator
, op
, get_src (begin
));
822 switch (current ()) {
824 // TODO enable warning after releasing Vala 0.5.5
825 // Report.warning (get_last_src (), "deprecated syntax, use `(owned)` cast");
827 var op
= parse_unary_expression ();
828 return new
ReferenceTransferExpression (op
, get_src (begin
));
829 case TokenType
.OPEN_PARENS
:
831 switch (current ()) {
832 case TokenType
.OWNED
:
835 if (accept (TokenType
.CLOSE_PARENS
)) {
836 var op
= parse_unary_expression ();
837 return new
ReferenceTransferExpression (op
, get_src (begin
));
841 case TokenType
.DYNAMIC
:
842 case TokenType
.IDENTIFIER
:
843 var type
= parse_type ();
844 if (accept (TokenType
.CLOSE_PARENS
)) {
845 // check follower to decide whether to create cast expression
846 switch (current ()) {
847 case TokenType
.OP_NEG
:
848 case TokenType
.TILDE
:
849 case TokenType
.OPEN_PARENS
:
851 case TokenType
.FALSE
:
852 case TokenType
.INTEGER_LITERAL
:
853 case TokenType
.REAL_LITERAL
:
854 case TokenType
.CHARACTER_LITERAL
:
855 case TokenType
.STRING_LITERAL
:
856 case TokenType
.VERBATIM_STRING_LITERAL
:
861 case TokenType
.SIZEOF
:
862 case TokenType
.TYPEOF
:
863 case TokenType
.IDENTIFIER
:
864 var inner
= parse_unary_expression ();
865 return new
CastExpression (inner
, type
, get_src (begin
), false);
874 // no cast expression
879 var op
= parse_unary_expression ();
880 return new
PointerIndirection (op
, get_src (begin
));
881 case TokenType
.BITWISE_AND
:
883 var op
= parse_unary_expression ();
884 return new
AddressofExpression (op
, get_src (begin
));
889 var expr
= parse_primary_expression ();
893 BinaryOperator
get_binary_operator (TokenType token_type
) {
894 switch (token_type
) {
895 case TokenType
.STAR
: return BinaryOperator
.MUL
;
896 case TokenType
.DIV
: return BinaryOperator
.DIV
;
897 case TokenType
.PERCENT
: return BinaryOperator
.MOD
;
898 case TokenType
.PLUS
: return BinaryOperator
.PLUS
;
899 case TokenType
.MINUS
: return BinaryOperator
.MINUS
;
900 case TokenType
.OP_LT
: return BinaryOperator
.LESS_THAN
;
901 case TokenType
.OP_GT
: return BinaryOperator
.GREATER_THAN
;
902 case TokenType
.OP_LE
: return BinaryOperator
.LESS_THAN_OR_EQUAL
;
903 case TokenType
.OP_GE
: return BinaryOperator
.GREATER_THAN_OR_EQUAL
;
904 case TokenType
.OP_EQ
: return BinaryOperator
.EQUALITY
;
905 case TokenType
.OP_NE
: return BinaryOperator
.INEQUALITY
;
906 default: return BinaryOperator
.NONE
;
910 Expression
parse_multiplicative_expression () throws ParseError
{
911 var begin
= get_location ();
912 var left
= parse_unary_expression ();
915 var operator
= get_binary_operator (current ());
917 case BinaryOperator
.MUL
:
918 case BinaryOperator
.DIV
:
919 case BinaryOperator
.MOD
:
921 var right
= parse_unary_expression ();
922 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
932 Expression
parse_additive_expression () throws ParseError
{
933 var begin
= get_location ();
934 var left
= parse_multiplicative_expression ();
937 var operator
= get_binary_operator (current ());
939 case BinaryOperator
.PLUS
:
940 case BinaryOperator
.MINUS
:
942 var right
= parse_multiplicative_expression ();
943 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
953 Expression
parse_shift_expression () throws ParseError
{
954 var begin
= get_location ();
955 var left
= parse_additive_expression ();
958 switch (current ()) {
959 case TokenType
.OP_SHIFT_LEFT
:
961 var right
= parse_additive_expression ();
962 left
= new
BinaryExpression (BinaryOperator
.SHIFT_LEFT
, left
, right
, get_src (begin
));
964 // don't use OP_SHIFT_RIGHT to support >> for nested generics
965 case TokenType
.OP_GT
:
966 char* first_gt_pos
= tokens
[index
].begin
.pos
;
968 // only accept >> when there is no space between the two > signs
969 if (current () == TokenType
.OP_GT
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
971 var right
= parse_additive_expression ();
972 left
= new
BinaryExpression (BinaryOperator
.SHIFT_RIGHT
, left
, right
, get_src (begin
));
986 Expression
parse_relational_expression () throws ParseError
{
987 var begin
= get_location ();
988 var left
= parse_shift_expression ();
991 var operator
= get_binary_operator (current ());
993 case BinaryOperator
.LESS_THAN
:
994 case BinaryOperator
.LESS_THAN_OR_EQUAL
:
995 case BinaryOperator
.GREATER_THAN_OR_EQUAL
:
997 var right
= parse_shift_expression ();
998 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1000 case BinaryOperator
.GREATER_THAN
:
1002 // ignore >> and >>= (two tokens due to generics)
1003 if (current () != TokenType
.OP_GT
&& current () != TokenType
.OP_GE
) {
1004 var right
= parse_shift_expression ();
1005 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1012 switch (current ()) {
1015 var type
= parse_type ();
1016 left
= new
TypeCheck (left
, type
, get_src (begin
));
1020 var type
= parse_type ();
1021 left
= new
CastExpression (left
, type
, get_src (begin
), true);
1033 Expression
parse_equality_expression () throws ParseError
{
1034 var begin
= get_location ();
1035 var left
= parse_relational_expression ();
1038 var operator
= get_binary_operator (current ());
1040 case BinaryOperator
.EQUALITY
:
1041 case BinaryOperator
.INEQUALITY
:
1043 var right
= parse_relational_expression ();
1044 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1054 Expression
parse_and_expression () throws ParseError
{
1055 var begin
= get_location ();
1056 var left
= parse_equality_expression ();
1057 while (accept (TokenType
.BITWISE_AND
)) {
1058 var right
= parse_equality_expression ();
1059 left
= new
BinaryExpression (BinaryOperator
.BITWISE_AND
, left
, right
, get_src (begin
));
1064 Expression
parse_exclusive_or_expression () throws ParseError
{
1065 var begin
= get_location ();
1066 var left
= parse_and_expression ();
1067 while (accept (TokenType
.CARRET
)) {
1068 var right
= parse_and_expression ();
1069 left
= new
BinaryExpression (BinaryOperator
.BITWISE_XOR
, left
, right
, get_src (begin
));
1074 Expression
parse_inclusive_or_expression () throws ParseError
{
1075 var begin
= get_location ();
1076 var left
= parse_exclusive_or_expression ();
1077 while (accept (TokenType
.BITWISE_OR
)) {
1078 var right
= parse_exclusive_or_expression ();
1079 left
= new
BinaryExpression (BinaryOperator
.BITWISE_OR
, left
, right
, get_src (begin
));
1084 Expression
parse_in_expression () throws ParseError
{
1085 var begin
= get_location ();
1086 var left
= parse_inclusive_or_expression ();
1087 while (accept (TokenType
.IN
)) {
1088 var right
= parse_inclusive_or_expression ();
1089 left
= new
BinaryExpression (BinaryOperator
.IN
, left
, right
, get_src (begin
));
1094 Expression
parse_conditional_and_expression () throws ParseError
{
1095 var begin
= get_location ();
1096 var left
= parse_in_expression ();
1097 while (accept (TokenType
.OP_AND
)) {
1098 var right
= parse_in_expression ();
1099 left
= new
BinaryExpression (BinaryOperator
.AND
, left
, right
, get_src (begin
));
1104 Expression
parse_conditional_or_expression () throws ParseError
{
1105 var begin
= get_location ();
1106 var left
= parse_conditional_and_expression ();
1107 while (accept (TokenType
.OP_OR
)) {
1108 var right
= parse_conditional_and_expression ();
1109 left
= new
BinaryExpression (BinaryOperator
.OR
, left
, right
, get_src (begin
));
1114 Expression
parse_conditional_expression () throws ParseError
{
1115 var begin
= get_location ();
1116 var condition
= parse_conditional_or_expression ();
1117 if (accept (TokenType
.INTERR
)) {
1118 var true_expr
= parse_expression ();
1119 expect (TokenType
.COLON
);
1120 var false_expr
= parse_expression ();
1121 return new
ConditionalExpression (condition
, true_expr
, false_expr
, get_src (begin
));
1127 Expression
parse_lambda_expression () throws ParseError
{
1128 var begin
= get_location ();
1129 Gee
.List
<string> params
= new ArrayList
<string> ();
1130 if (accept (TokenType
.OPEN_PARENS
)) {
1131 if (current () != TokenType
.CLOSE_PARENS
) {
1133 params
.add (parse_identifier ());
1134 } while (accept (TokenType
.COMMA
));
1136 expect (TokenType
.CLOSE_PARENS
);
1138 params
.add (parse_identifier ());
1140 expect (TokenType
.LAMBDA
);
1142 LambdaExpression lambda
;
1143 if (current () == TokenType
.OPEN_BRACE
) {
1144 var block
= parse_block ();
1145 lambda
= new LambdaExpression
.with_statement_body (block
, get_src (begin
));
1147 var expr
= parse_expression ();
1148 lambda
= new
LambdaExpression (expr
, get_src (begin
));
1150 foreach (string param
in params
) {
1151 lambda
.add_parameter (param
);
1156 AssignmentOperator
get_assignment_operator (TokenType token_type
) {
1157 switch (token_type
) {
1158 case TokenType
.ASSIGN
: return AssignmentOperator
.SIMPLE
;
1159 case TokenType
.ASSIGN_ADD
: return AssignmentOperator
.ADD
;
1160 case TokenType
.ASSIGN_SUB
: return AssignmentOperator
.SUB
;
1161 case TokenType
.ASSIGN_BITWISE_OR
: return AssignmentOperator
.BITWISE_OR
;
1162 case TokenType
.ASSIGN_BITWISE_AND
: return AssignmentOperator
.BITWISE_AND
;
1163 case TokenType
.ASSIGN_BITWISE_XOR
: return AssignmentOperator
.BITWISE_XOR
;
1164 case TokenType
.ASSIGN_DIV
: return AssignmentOperator
.DIV
;
1165 case TokenType
.ASSIGN_MUL
: return AssignmentOperator
.MUL
;
1166 case TokenType
.ASSIGN_PERCENT
: return AssignmentOperator
.PERCENT
;
1167 case TokenType
.ASSIGN_SHIFT_LEFT
: return AssignmentOperator
.SHIFT_LEFT
;
1168 default: return AssignmentOperator
.NONE
;
1172 Expression
parse_expression () throws ParseError
{
1173 var begin
= get_location ();
1174 Expression expr
= parse_conditional_expression ();
1176 if (current () == TokenType
.LAMBDA
) {
1178 var lambda
= parse_lambda_expression ();
1183 var operator
= get_assignment_operator (current ());
1184 if (operator
!= AssignmentOperator
.NONE
) {
1186 var rhs
= parse_expression ();
1187 expr
= new
Assignment (expr
, rhs
, operator
, get_src (begin
));
1188 } else if (current () == TokenType
.OP_GT
) { // >>=
1189 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1191 // only accept >>= when there is no space between the two > signs
1192 if (current () == TokenType
.OP_GE
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1194 var rhs
= parse_expression ();
1195 expr
= new
Assignment (expr
, rhs
, AssignmentOperator
.SHIFT_RIGHT
, get_src (begin
));
1208 void parse_statements (Block block
) throws ParseError
{
1209 while (current () != TokenType
.CLOSE_BRACE
1210 && current () != TokenType
.CASE
1211 && current () != TokenType
.DEFAULT
) {
1213 Statement stmt
= null;
1214 bool is_decl
= false;
1215 comment
= scanner
.pop_comment ();
1216 switch (current ()) {
1217 case TokenType
.OPEN_BRACE
:
1218 stmt
= parse_block ();
1220 case TokenType
.SEMICOLON
:
1221 stmt
= parse_empty_statement ();
1224 stmt
= parse_if_statement ();
1226 case TokenType
.SWITCH
:
1227 stmt
= parse_switch_statement ();
1229 case TokenType
.WHILE
:
1230 stmt
= parse_while_statement ();
1233 stmt
= parse_do_statement ();
1236 stmt
= parse_for_statement ();
1238 case TokenType
.FOREACH
:
1239 stmt
= parse_foreach_statement ();
1241 case TokenType
.BREAK
:
1242 stmt
= parse_break_statement ();
1244 case TokenType
.CONTINUE
:
1245 stmt
= parse_continue_statement ();
1247 case TokenType
.RETURN
:
1248 stmt
= parse_return_statement ();
1250 case TokenType
.YIELD
:
1251 stmt
= parse_yield_statement ();
1253 case TokenType
.THROW
:
1254 stmt
= parse_throw_statement ();
1257 stmt
= parse_try_statement ();
1259 case TokenType
.LOCK
:
1260 stmt
= parse_lock_statement ();
1262 case TokenType
.DELETE
:
1263 stmt
= parse_delete_statement ();
1267 parse_local_variable_declarations (block
);
1269 case TokenType
.OP_INC
:
1270 case TokenType
.OP_DEC
:
1271 case TokenType
.BASE
:
1272 case TokenType
.THIS
:
1273 case TokenType
.OPEN_PARENS
:
1274 case TokenType
.STAR
:
1276 stmt
= parse_expression_statement ();
1279 bool is_expr
= is_expression ();
1281 stmt
= parse_expression_statement ();
1284 parse_local_variable_declarations (block
);
1290 block
.add_statement (stmt
);
1292 } catch (ParseError e
) {
1293 if (recover () != RecoveryState
.STATEMENT_BEGIN
) {
1294 // beginning of next declaration or end of file reached
1295 // return what we have so far
1302 bool is_expression () throws ParseError
{
1303 var begin
= get_location ();
1305 // decide between declaration and expression statement
1307 switch (current ()) {
1308 // invocation expression
1309 case TokenType
.OPEN_PARENS
:
1310 // postfix increment
1311 case TokenType
.OP_INC
:
1312 // postfix decrement
1313 case TokenType
.OP_DEC
:
1315 case TokenType
.ASSIGN
:
1316 case TokenType
.ASSIGN_ADD
:
1317 case TokenType
.ASSIGN_BITWISE_AND
:
1318 case TokenType
.ASSIGN_BITWISE_OR
:
1319 case TokenType
.ASSIGN_BITWISE_XOR
:
1320 case TokenType
.ASSIGN_DIV
:
1321 case TokenType
.ASSIGN_MUL
:
1322 case TokenType
.ASSIGN_PERCENT
:
1323 case TokenType
.ASSIGN_SHIFT_LEFT
:
1324 case TokenType
.ASSIGN_SUB
:
1325 case TokenType
.OP_GT
: // >>=
1328 // pointer member access
1329 case TokenType
.OP_PTR
:
1338 Block
parse_embedded_statement () throws ParseError
{
1339 if (current () == TokenType
.OPEN_BRACE
) {
1340 var block
= parse_block ();
1344 comment
= scanner
.pop_comment ();
1346 var block
= new
Block (get_src_com (get_location ()));
1347 block
.add_statement (parse_embedded_statement_without_block ());
1352 Statement
parse_embedded_statement_without_block () throws ParseError
{
1353 switch (current ()) {
1354 case TokenType
.SEMICOLON
: return parse_empty_statement ();
1355 case TokenType
.IF
: return parse_if_statement ();
1356 case TokenType
.SWITCH
: return parse_switch_statement ();
1357 case TokenType
.WHILE
: return parse_while_statement ();
1358 case TokenType
.DO
: return parse_do_statement ();
1359 case TokenType
.FOR
: return parse_for_statement ();
1360 case TokenType
.FOREACH
: return parse_foreach_statement ();
1361 case TokenType
.BREAK
: return parse_break_statement ();
1362 case TokenType
.CONTINUE
: return parse_continue_statement ();
1363 case TokenType
.RETURN
: return parse_return_statement ();
1364 case TokenType
.YIELD
: return parse_yield_statement ();
1365 case TokenType
.THROW
: return parse_throw_statement ();
1366 case TokenType
.TRY
: return parse_try_statement ();
1367 case TokenType
.LOCK
: return parse_lock_statement ();
1368 case TokenType
.DELETE
: return parse_delete_statement ();
1369 default: return parse_expression_statement ();
1373 Block
parse_block () throws ParseError
{
1374 var begin
= get_location ();
1375 expect (TokenType
.OPEN_BRACE
);
1376 var block
= new
Block (get_src_com (begin
));
1377 parse_statements (block
);
1378 if (!accept (TokenType
.CLOSE_BRACE
)) {
1379 // only report error if it's not a secondary error
1380 if (Report
.get_errors () == 0) {
1381 Report
.error (get_current_src (), "expected `}'");
1385 block
.source_reference
.last_line
= get_current_src ().last_line
;
1386 block
.source_reference
.last_column
= get_current_src ().last_column
;
1391 Statement
parse_empty_statement () throws ParseError
{
1392 var begin
= get_location ();
1393 expect (TokenType
.SEMICOLON
);
1394 return new
EmptyStatement (get_src_com (begin
));
1397 void parse_local_variable_declarations (Block block
) throws ParseError
{
1398 DataType variable_type
;
1399 if (accept (TokenType
.VAR
)) {
1400 variable_type
= null;
1402 variable_type
= parse_type ();
1405 DataType type_copy
= null;
1406 if (variable_type
!= null) {
1407 type_copy
= variable_type
.copy ();
1409 var local
= parse_local_variable (type_copy
);
1410 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1411 } while (accept (TokenType
.COMMA
));
1412 expect (TokenType
.SEMICOLON
);
1415 LocalVariable
parse_local_variable (DataType? variable_type
) throws ParseError
{
1416 var begin
= get_location ();
1417 string id
= parse_identifier ();
1418 Expression initializer
= null;
1419 if (accept (TokenType
.ASSIGN
)) {
1420 initializer
= parse_expression ();
1422 return new
LocalVariable (variable_type
, id
, initializer
, get_src_com (begin
));
1425 Statement
parse_expression_statement () throws ParseError
{
1426 var begin
= get_location ();
1427 var expr
= parse_statement_expression ();
1428 expect (TokenType
.SEMICOLON
);
1429 return new
ExpressionStatement (expr
, get_src_com (begin
));
1432 Expression
parse_statement_expression () throws ParseError
{
1433 // invocation expression, assignment,
1434 // or pre/post increment/decrement expression
1435 var expr
= parse_expression ();
1439 Statement
parse_if_statement () throws ParseError
{
1440 var begin
= get_location ();
1441 expect (TokenType
.IF
);
1442 expect (TokenType
.OPEN_PARENS
);
1443 var condition
= parse_expression ();
1444 expect (TokenType
.CLOSE_PARENS
);
1445 var src
= get_src_com (begin
);
1446 var true_stmt
= parse_embedded_statement ();
1447 Block false_stmt
= null;
1448 if (accept (TokenType
.ELSE
)) {
1449 false_stmt
= parse_embedded_statement ();
1451 return new
IfStatement (condition
, true_stmt
, false_stmt
, src
);
1454 Statement
parse_switch_statement () throws ParseError
{
1455 var begin
= get_location ();
1456 expect (TokenType
.SWITCH
);
1457 expect (TokenType
.OPEN_PARENS
);
1458 var condition
= parse_expression ();
1459 expect (TokenType
.CLOSE_PARENS
);
1460 var stmt
= new
SwitchStatement (condition
, get_src_com (begin
));
1461 expect (TokenType
.OPEN_BRACE
);
1462 while (current () != TokenType
.CLOSE_BRACE
) {
1463 var section
= new
SwitchSection (get_src_com (begin
));
1465 if (accept (TokenType
.CASE
)) {
1466 section
.add_label (new
SwitchLabel (parse_expression (), get_src_com (begin
)));
1468 expect (TokenType
.DEFAULT
);
1469 section
.add_label (new SwitchLabel
.with_default (get_src_com (begin
)));
1471 expect (TokenType
.COLON
);
1472 } while (current () == TokenType
.CASE
|| current () == TokenType
.DEFAULT
);
1473 parse_statements (section
);
1474 stmt
.add_section (section
);
1476 expect (TokenType
.CLOSE_BRACE
);
1480 Statement
parse_while_statement () throws ParseError
{
1481 var begin
= get_location ();
1482 expect (TokenType
.WHILE
);
1483 expect (TokenType
.OPEN_PARENS
);
1484 var condition
= parse_expression ();
1485 expect (TokenType
.CLOSE_PARENS
);
1486 var body
= parse_embedded_statement ();
1487 return new
WhileStatement (condition
, body
, get_src_com (begin
));
1490 Statement
parse_do_statement () throws ParseError
{
1491 var begin
= get_location ();
1492 expect (TokenType
.DO
);
1493 var body
= parse_embedded_statement ();
1494 expect (TokenType
.WHILE
);
1495 expect (TokenType
.OPEN_PARENS
);
1496 var condition
= parse_expression ();
1497 expect (TokenType
.CLOSE_PARENS
);
1498 expect (TokenType
.SEMICOLON
);
1499 return new
DoStatement (body
, condition
, get_src_com (begin
));
1502 Statement
parse_for_statement () throws ParseError
{
1503 var begin
= get_location ();
1505 expect (TokenType
.FOR
);
1506 expect (TokenType
.OPEN_PARENS
);
1507 var initializer_list
= new ArrayList
<Expression
> ();
1508 if (!accept (TokenType
.SEMICOLON
)) {
1510 switch (current ()) {
1514 case TokenType
.OP_INC
:
1515 case TokenType
.OP_DEC
:
1519 is_expr
= is_expression ();
1525 initializer_list
.add (parse_statement_expression ());
1526 } while (accept (TokenType
.COMMA
));
1528 block
= new
Block (get_src (begin
));
1529 DataType variable_type
;
1530 if (accept (TokenType
.VAR
)) {
1531 variable_type
= null;
1533 variable_type
= parse_type ();
1535 var local
= parse_local_variable (variable_type
);
1536 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1538 expect (TokenType
.SEMICOLON
);
1540 Expression condition
= null;
1541 if (current () != TokenType
.SEMICOLON
) {
1542 condition
= parse_expression ();
1544 expect (TokenType
.SEMICOLON
);
1545 var iterator_list
= new ArrayList
<Expression
> ();
1546 if (current () != TokenType
.CLOSE_PARENS
) {
1548 iterator_list
.add (parse_statement_expression ());
1549 } while (accept (TokenType
.COMMA
));
1551 expect (TokenType
.CLOSE_PARENS
);
1552 var src
= get_src_com (begin
);
1553 var body
= parse_embedded_statement ();
1554 var stmt
= new
ForStatement (condition
, body
, src
);
1555 foreach (Expression init
in initializer_list
) {
1556 stmt
.add_initializer (init
);
1558 foreach (Expression iter
in iterator_list
) {
1559 stmt
.add_iterator (iter
);
1561 if (block
!= null) {
1562 block
.add_statement (stmt
);
1569 Statement
parse_foreach_statement () throws ParseError
{
1570 var begin
= get_location ();
1571 expect (TokenType
.FOREACH
);
1572 expect (TokenType
.OPEN_PARENS
);
1573 DataType type
= null;
1574 if (!accept (TokenType
.VAR
)) {
1575 type
= parse_type ();
1577 string id
= parse_identifier ();
1578 expect (TokenType
.IN
);
1579 var collection
= parse_expression ();
1580 expect (TokenType
.CLOSE_PARENS
);
1581 var src
= get_src_com (begin
);
1582 var body
= parse_embedded_statement ();
1583 return new
ForeachStatement (type
, id
, collection
, body
, src
);
1586 Statement
parse_break_statement () throws ParseError
{
1587 var begin
= get_location ();
1588 expect (TokenType
.BREAK
);
1589 expect (TokenType
.SEMICOLON
);
1590 return new
BreakStatement (get_src_com (begin
));
1593 Statement
parse_continue_statement () throws ParseError
{
1594 var begin
= get_location ();
1595 expect (TokenType
.CONTINUE
);
1596 expect (TokenType
.SEMICOLON
);
1597 return new
ContinueStatement (get_src_com (begin
));
1600 Statement
parse_return_statement () throws ParseError
{
1601 var begin
= get_location ();
1602 expect (TokenType
.RETURN
);
1603 Expression expr
= null;
1604 if (current () != TokenType
.SEMICOLON
) {
1605 expr
= parse_expression ();
1607 expect (TokenType
.SEMICOLON
);
1608 return new
ReturnStatement (expr
, get_src_com (begin
));
1611 Statement
parse_yield_statement () throws ParseError
{
1612 var begin
= get_location ();
1613 expect (TokenType
.YIELD
);
1614 Expression expr
= null;
1615 if (current () != TokenType
.SEMICOLON
) {
1616 expr
= parse_expression ();
1618 expect (TokenType
.SEMICOLON
);
1619 return new
YieldStatement (expr
, get_src (begin
));
1622 Statement
parse_throw_statement () throws ParseError
{
1623 var begin
= get_location ();
1624 expect (TokenType
.THROW
);
1625 var expr
= parse_expression ();
1626 expect (TokenType
.SEMICOLON
);
1627 return new
ThrowStatement (expr
, get_src_com (begin
));
1630 Statement
parse_try_statement () throws ParseError
{
1631 var begin
= get_location ();
1632 expect (TokenType
.TRY
);
1633 var try_block
= parse_block ();
1634 Block finally_clause
= null;
1635 var catch_clauses
= new ArrayList
<CatchClause
> ();
1636 if (current () == TokenType
.CATCH
) {
1637 parse_catch_clauses (catch_clauses
);
1638 if (current () == TokenType
.FINALLY
) {
1639 finally_clause
= parse_finally_clause ();
1642 finally_clause
= parse_finally_clause ();
1644 var stmt
= new
TryStatement (try_block
, finally_clause
, get_src_com (begin
));
1645 foreach (CatchClause clause
in catch_clauses
) {
1646 stmt
.add_catch_clause (clause
);
1651 void parse_catch_clauses (Gee
.List
<CatchClause
> catch_clauses
) throws ParseError
{
1652 while (accept (TokenType
.CATCH
)) {
1653 var begin
= get_location ();
1654 DataType type
= null;
1656 if (accept (TokenType
.OPEN_PARENS
)) {
1657 type
= parse_type ();
1658 id
= parse_identifier ();
1659 expect (TokenType
.CLOSE_PARENS
);
1661 var block
= parse_block ();
1662 catch_clauses
.add (new
CatchClause (type
, id
, block
, get_src (begin
)));
1666 Block
parse_finally_clause () throws ParseError
{
1667 expect (TokenType
.FINALLY
);
1668 var block
= parse_block ();
1672 Statement
parse_lock_statement () throws ParseError
{
1673 var begin
= get_location ();
1674 expect (TokenType
.LOCK
);
1675 expect (TokenType
.OPEN_PARENS
);
1676 var expr
= parse_expression ();
1677 expect (TokenType
.CLOSE_PARENS
);
1678 var stmt
= parse_embedded_statement ();
1679 return new
LockStatement (expr
, stmt
, get_src_com (begin
));
1682 Statement
parse_delete_statement () throws ParseError
{
1683 var begin
= get_location ();
1684 expect (TokenType
.DELETE
);
1685 var expr
= parse_expression ();
1686 expect (TokenType
.SEMICOLON
);
1687 return new
DeleteStatement (expr
, get_src_com (begin
));
1690 Gee
.List
<Attribute
>?
parse_attributes () throws ParseError
{
1691 if (current () != TokenType
.OPEN_BRACKET
) {
1694 var attrs
= new ArrayList
<Attribute
> ();
1695 while (accept (TokenType
.OPEN_BRACKET
)) {
1697 var begin
= get_location ();
1698 string id
= parse_identifier ();
1699 var attr
= new
Attribute (id
, get_src (begin
));
1700 if (accept (TokenType
.OPEN_PARENS
)) {
1701 if (current () != TokenType
.CLOSE_PARENS
) {
1703 id
= parse_identifier ();
1704 expect (TokenType
.ASSIGN
);
1705 var expr
= parse_expression ();
1706 attr
.add_argument (id
, expr
);
1707 } while (accept (TokenType
.COMMA
));
1709 expect (TokenType
.CLOSE_PARENS
);
1712 } while (accept (TokenType
.COMMA
));
1713 expect (TokenType
.CLOSE_BRACKET
);
1718 void set_attributes (CodeNode node
, Gee
.List
<Attribute
>? attributes
) {
1719 if (attributes
!= null) {
1720 foreach (Attribute attr
in (Gee
.List
<Attribute
>) attributes
) {
1721 node
.attributes
.append (attr
);
1726 Symbol
parse_declaration () throws ParseError
{
1727 comment
= scanner
.pop_comment ();
1728 var attrs
= parse_attributes ();
1730 var begin
= get_location ();
1732 TokenType last_keyword
= current ();
1734 while (is_declaration_keyword (current ())) {
1735 last_keyword
= current ();
1739 switch (current ()) {
1740 case TokenType
.CONSTRUCT
:
1742 return parse_constructor_declaration (attrs
);
1743 case TokenType
.TILDE
:
1745 return parse_destructor_declaration (attrs
);
1748 switch (current ()) {
1749 case TokenType
.OPEN_BRACE
:
1750 case TokenType
.SEMICOLON
:
1751 case TokenType
.COLON
:
1753 switch (last_keyword
) {
1754 case TokenType
.CLASS
: return parse_class_declaration (attrs
);
1755 case TokenType
.ENUM
: return parse_enum_declaration (attrs
);
1756 case TokenType
.ERRORDOMAIN
: return parse_errordomain_declaration (attrs
);
1757 case TokenType
.INTERFACE
: return parse_interface_declaration (attrs
);
1758 case TokenType
.NAMESPACE
: return parse_namespace_declaration (attrs
);
1759 case TokenType
.STRUCT
: return parse_struct_declaration (attrs
);
1763 case TokenType
.OPEN_PARENS
:
1765 return parse_creation_method_declaration (attrs
);
1767 skip_type (); // might contain type parameter list
1768 switch (current ()) {
1769 case TokenType
.OPEN_PARENS
:
1771 switch (last_keyword
) {
1772 case TokenType
.DELEGATE
: return parse_delegate_declaration (attrs
);
1773 case TokenType
.SIGNAL
: return parse_signal_declaration (attrs
);
1774 default: return parse_method_declaration (attrs
);
1776 case TokenType
.ASSIGN
:
1777 case TokenType
.SEMICOLON
:
1779 switch (last_keyword
) {
1780 case TokenType
.CONST
: return parse_constant_declaration (attrs
);
1781 default: return parse_field_declaration (attrs
);
1783 case TokenType
.OPEN_BRACE
:
1785 return parse_property_declaration (attrs
);
1796 throw new ParseError
.SYNTAX (get_error ("expected declaration"));
1799 void parse_declarations (Symbol parent
, bool root
= false) throws ParseError
{
1801 expect (TokenType
.OPEN_BRACE
);
1803 while (current () != TokenType
.CLOSE_BRACE
&& current () != TokenType
.EOF
) {
1805 if (parent is Namespace
) {
1806 parse_namespace_member ((Namespace
) parent
);
1807 } else if (parent is Class
) {
1808 parse_class_member ((Class
) parent
);
1809 } else if (parent is Struct
) {
1810 parse_struct_member ((Struct
) parent
);
1811 } else if (parent is Interface
) {
1812 parse_interface_member ((Interface
) parent
);
1814 } catch (ParseError e
) {
1818 if (r
== RecoveryState
.STATEMENT_BEGIN
) {
1824 if (r
== RecoveryState
.EOF
) {
1830 if (!accept (TokenType
.CLOSE_BRACE
)) {
1831 // only report error if it's not a secondary error
1832 if (Report
.get_errors () == 0) {
1833 Report
.error (get_current_src (), "expected `}'");
1839 enum RecoveryState
{
1845 RecoveryState
recover () {
1846 while (current () != TokenType
.EOF
) {
1847 switch (current ()) {
1848 case TokenType
.ABSTRACT
:
1849 case TokenType
.CLASS
:
1850 case TokenType
.CONST
:
1851 case TokenType
.CONSTRUCT
:
1852 case TokenType
.DELEGATE
:
1853 case TokenType
.ENUM
:
1854 case TokenType
.ERRORDOMAIN
:
1855 case TokenType
.EXTERN
:
1856 case TokenType
.INLINE
:
1857 case TokenType
.INTERFACE
:
1858 case TokenType
.INTERNAL
:
1859 case TokenType
.NAMESPACE
:
1860 case TokenType
.OVERRIDE
:
1861 case TokenType
.PRIVATE
:
1862 case TokenType
.PROTECTED
:
1863 case TokenType
.PUBLIC
:
1864 case TokenType
.SIGNAL
:
1865 case TokenType
.STATIC
:
1866 case TokenType
.STRUCT
:
1867 case TokenType
.VIRTUAL
:
1868 case TokenType
.VOLATILE
:
1869 return RecoveryState
.DECLARATION_BEGIN
;
1870 case TokenType
.BREAK
:
1871 case TokenType
.CONTINUE
:
1872 case TokenType
.DELETE
:
1875 case TokenType
.FOREACH
:
1877 case TokenType
.LOCK
:
1878 case TokenType
.RETURN
:
1879 case TokenType
.SWITCH
:
1880 case TokenType
.THROW
:
1883 case TokenType
.WHILE
:
1884 case TokenType
.YIELD
:
1885 return RecoveryState
.STATEMENT_BEGIN
;
1891 return RecoveryState
.EOF
;
1894 Namespace
parse_namespace_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
1895 var begin
= get_location ();
1896 expect (TokenType
.NAMESPACE
);
1897 var sym
= parse_symbol_name ();
1898 var ns
= new
Namespace (sym
.name
, get_src_com (begin
));
1899 set_attributes (ns
, attrs
);
1900 parse_declarations (ns
);
1902 Namespace result
= ns
;
1903 while (sym
.inner
!= null) {
1905 ns
= new
Namespace (sym
.name
, result
.source_reference
);
1906 ns
.add_namespace ((Namespace
) result
);
1912 void parse_namespace_member (Namespace ns
) throws ParseError
{
1913 var sym
= parse_declaration ();
1915 // namespaces do not support private memebers
1916 if (sym
.access
== SymbolAccessibility
.PRIVATE
) {
1917 sym
.access
= SymbolAccessibility
.INTERNAL
;
1920 if (sym is Namespace
) {
1921 ns
.add_namespace ((Namespace
) sym
);
1922 } else if (sym is Class
) {
1923 ns
.add_class ((Class
) sym
);
1924 } else if (sym is Interface
) {
1925 ns
.add_interface ((Interface
) sym
);
1926 } else if (sym is Struct
) {
1927 ns
.add_struct ((Struct
) sym
);
1928 } else if (sym is Enum
) {
1929 ns
.add_enum ((Enum
) sym
);
1930 } else if (sym is ErrorDomain
) {
1931 ns
.add_error_domain ((ErrorDomain
) sym
);
1932 } else if (sym is Delegate
) {
1933 ns
.add_delegate ((Delegate
) sym
);
1934 } else if (sym is Method
) {
1935 var method
= (Method
) sym
;
1936 if (method
.binding
== MemberBinding
.INSTANCE
) {
1937 // default to static member binding
1938 method
.binding
= MemberBinding
.STATIC
;
1940 ns
.add_method (method
);
1941 } else if (sym is Field
) {
1942 var field
= (Field
) sym
;
1943 if (field
.binding
== MemberBinding
.INSTANCE
) {
1944 // default to static member binding
1945 field
.binding
= MemberBinding
.STATIC
;
1947 ns
.add_field (field
);
1948 } else if (sym is Constant
) {
1949 ns
.add_constant ((Constant
) sym
);
1951 Report
.error (sym
.source_reference
, "unexpected declaration in namespace");
1953 scanner
.source_file
.add_node (sym
);
1956 void parse_using_directives () throws ParseError
{
1957 while (accept (TokenType
.USING
)) {
1959 var begin
= get_location ();
1960 var sym
= parse_symbol_name ();
1961 var ns_ref
= new
UsingDirective (sym
, get_src (begin
));
1962 scanner
.source_file
.add_using_directive (ns_ref
);
1963 } while (accept (TokenType
.COMMA
));
1964 expect (TokenType
.SEMICOLON
);
1968 Symbol
parse_class_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
1969 var begin
= get_location ();
1970 var access
= parse_access_modifier ();
1971 var flags
= parse_type_declaration_modifiers ();
1972 expect (TokenType
.CLASS
);
1973 var sym
= parse_symbol_name ();
1974 var type_param_list
= parse_type_parameter_list ();
1975 var base_types
= new ArrayList
<DataType
> ();
1976 if (accept (TokenType
.COLON
)) {
1978 base_types
.add (parse_type ());
1979 } while (accept (TokenType
.COMMA
));
1982 var cl
= new
Class (sym
.name
, get_src_com (begin
));
1984 if (ModifierFlags
.ABSTRACT
in flags
) {
1985 cl
.is_abstract
= true;
1987 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
1990 set_attributes (cl
, attrs
);
1991 foreach (TypeParameter type_param
in type_param_list
) {
1992 cl
.add_type_parameter (type_param
);
1994 foreach (DataType base_type
in base_types
) {
1995 cl
.add_base_type (base_type
);
1998 parse_declarations (cl
);
2000 // ensure there is always a default construction method
2001 if (!scanner
.source_file
.external_package
2003 && cl
.default_construction_method
== null) {
2004 var m
= new
CreationMethod (cl
.name
, null, cl
.source_reference
);
2005 m
.access
= SymbolAccessibility
.PUBLIC
;
2006 m
.body
= new
Block (cl
.source_reference
);
2011 while (sym
.inner
!= null) {
2013 var ns
= new
Namespace (sym
.name
, cl
.source_reference
);
2014 if (result is Namespace
) {
2015 ns
.add_namespace ((Namespace
) result
);
2017 ns
.add_class ((Class
) result
);
2018 scanner
.source_file
.add_node (result
);
2025 void parse_class_member (Class cl
) throws ParseError
{
2026 var sym
= parse_declaration ();
2028 cl
.add_class ((Class
) sym
);
2029 } else if (sym is Struct
) {
2030 cl
.add_struct ((Struct
) sym
);
2031 } else if (sym is Enum
) {
2032 cl
.add_enum ((Enum
) sym
);
2033 } else if (sym is Delegate
) {
2034 cl
.add_delegate ((Delegate
) sym
);
2035 } else if (sym is Method
) {
2036 cl
.add_method ((Method
) sym
);
2037 } else if (sym is Signal
) {
2038 cl
.add_signal ((Signal
) sym
);
2039 } else if (sym is Field
) {
2040 cl
.add_field ((Field
) sym
);
2041 } else if (sym is Constant
) {
2042 cl
.add_constant ((Constant
) sym
);
2043 } else if (sym is Property
) {
2044 cl
.add_property ((Property
) sym
);
2045 } else if (sym is Constructor
) {
2046 var c
= (Constructor
) sym
;
2047 if (c
.binding
== MemberBinding
.INSTANCE
) {
2049 } else if (c
.binding
== MemberBinding
.CLASS
) {
2050 cl
.class_constructor
= c
;
2052 cl
.static_constructor
= c
;
2054 } else if (sym is Destructor
) {
2055 var d
= (Destructor
) sym
;
2056 if (d
.binding
== MemberBinding
.STATIC
) {
2057 cl
.static_destructor
= (Destructor
) d
;
2058 } else if (d
.binding
== MemberBinding
.CLASS
) {
2059 cl
.class_destructor
= (Destructor
) d
;
2061 cl
.destructor
= (Destructor
) d
;
2064 Report
.error (sym
.source_reference
, "unexpected declaration in class");
2068 Constant
parse_constant_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2069 var begin
= get_location ();
2070 var access
= parse_access_modifier ();
2071 var flags
= parse_member_declaration_modifiers ();
2072 expect (TokenType
.CONST
);
2073 var type
= parse_type (false);
2074 string id
= parse_identifier ();
2075 Expression initializer
= null;
2076 if (accept (TokenType
.ASSIGN
)) {
2077 initializer
= parse_expression ();
2079 expect (TokenType
.SEMICOLON
);
2081 // constant arrays don't own their element
2082 var array_type
= type as ArrayType
;
2083 if (array_type
!= null) {
2084 array_type
.element_type
.value_owned
= false;
2087 var c
= new
Constant (id
, type
, initializer
, get_src_com (begin
));
2089 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2092 set_attributes (c
, attrs
);
2096 Field
parse_field_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2097 var begin
= get_location ();
2098 var access
= parse_access_modifier ();
2099 var flags
= parse_member_declaration_modifiers ();
2100 var type
= parse_type ();
2101 string id
= parse_identifier ();
2102 var f
= new
Field (id
, type
, null, get_src_com (begin
));
2104 set_attributes (f
, attrs
);
2105 if (ModifierFlags
.STATIC
in flags
) {
2106 f
.binding
= MemberBinding
.STATIC
;
2107 } else if (ModifierFlags
.CLASS
in flags
) {
2108 f
.binding
= MemberBinding
.CLASS
;
2110 if (ModifierFlags
.ABSTRACT
in flags
2111 || ModifierFlags
.VIRTUAL
in flags
2112 || ModifierFlags
.OVERRIDE
in flags
) {
2113 Report
.error (f
.source_reference
, "abstract, virtual, and override modifiers are not applicable to fields");
2115 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2118 if (accept (TokenType
.ASSIGN
)) {
2119 f
.initializer
= parse_expression ();
2121 expect (TokenType
.SEMICOLON
);
2125 InitializerList
parse_initializer () throws ParseError
{
2126 var begin
= get_location ();
2127 expect (TokenType
.OPEN_BRACE
);
2128 var initializer
= new
InitializerList (get_src (begin
));
2129 if (current () != TokenType
.CLOSE_BRACE
) {
2131 var init
= parse_argument ();
2132 initializer
.append (init
);
2133 } while (accept (TokenType
.COMMA
));
2135 expect (TokenType
.CLOSE_BRACE
);
2139 Method
parse_method_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2140 var begin
= get_location ();
2141 var access
= parse_access_modifier ();
2142 var flags
= parse_member_declaration_modifiers ();
2143 var type
= parse_type ();
2144 string id
= parse_identifier ();
2145 parse_type_parameter_list ();
2146 var method
= new
Method (id
, type
, get_src_com (begin
));
2147 method
.access
= access
;
2148 set_attributes (method
, attrs
);
2149 if (ModifierFlags
.STATIC
in flags
) {
2150 method
.binding
= MemberBinding
.STATIC
;
2151 } else if (ModifierFlags
.CLASS
in flags
) {
2152 method
.binding
= MemberBinding
.CLASS
;
2155 if (method
.binding
== MemberBinding
.INSTANCE
) {
2156 if (ModifierFlags
.ABSTRACT
in flags
) {
2157 method
.is_abstract
= true;
2159 if (ModifierFlags
.VIRTUAL
in flags
) {
2160 method
.is_virtual
= true;
2162 if (ModifierFlags
.OVERRIDE
in flags
) {
2163 method
.overrides
= true;
2165 if ((method
.is_abstract
&& method
.is_virtual
)
2166 || (method
.is_abstract
&& method
.overrides
)
2167 || (method
.is_virtual
&& method
.overrides
)) {
2168 throw new ParseError
.SYNTAX (get_error ("only one of `abstract', `virtual', or `override' may be specified"));
2171 if (ModifierFlags
.ABSTRACT
in flags
2172 || ModifierFlags
.VIRTUAL
in flags
2173 || ModifierFlags
.OVERRIDE
in flags
) {
2174 throw new ParseError
.SYNTAX (get_error ("the modifiers `abstract', `virtual', and `override' are not valid for static methods"));
2178 if (ModifierFlags
.INLINE
in flags
) {
2179 method
.is_inline
= true;
2181 if (ModifierFlags
.EXTERN
in flags
) {
2182 method
.external
= true;
2184 expect (TokenType
.OPEN_PARENS
);
2185 if (current () != TokenType
.CLOSE_PARENS
) {
2187 var param
= parse_parameter ();
2188 method
.add_parameter (param
);
2189 } while (accept (TokenType
.COMMA
));
2191 expect (TokenType
.CLOSE_PARENS
);
2192 if (accept (TokenType
.YIELDS
)) {
2193 method
.coroutine
= true;
2195 if (accept (TokenType
.THROWS
)) {
2197 method
.add_error_type (parse_type ());
2198 } while (accept (TokenType
.COMMA
));
2200 while (accept (TokenType
.REQUIRES
)) {
2201 expect (TokenType
.OPEN_PARENS
);
2202 method
.add_precondition (parse_expression ());
2203 expect (TokenType
.CLOSE_PARENS
);
2205 while (accept (TokenType
.ENSURES
)) {
2206 expect (TokenType
.OPEN_PARENS
);
2207 method
.add_postcondition (parse_expression ());
2208 expect (TokenType
.CLOSE_PARENS
);
2210 if (!accept (TokenType
.SEMICOLON
)) {
2211 method
.body
= parse_block ();
2212 } else if (scanner
.source_file
.external_package
) {
2213 method
.external
= true;
2218 Property
parse_property_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2219 var begin
= get_location ();
2220 var access
= parse_access_modifier ();
2221 var flags
= parse_member_declaration_modifiers ();
2222 var type
= parse_type ();
2224 bool getter_owned
= false;
2225 if (accept (TokenType
.HASH
)) {
2226 if (!context
.deprecated
) {
2227 Report
.warning (get_last_src (), "deprecated syntax, use `owned` modifier before `get'");
2229 getter_owned
= true;
2232 string id
= parse_identifier ();
2233 var prop
= new
Property (id
, type
, null, null, get_src_com (begin
));
2234 prop
.access
= access
;
2235 set_attributes (prop
, attrs
);
2236 if (ModifierFlags
.STATIC
in flags
) {
2237 prop
.binding
= MemberBinding
.STATIC
;
2238 } else if (ModifierFlags
.CLASS
in flags
) {
2239 prop
.binding
= MemberBinding
.CLASS
;
2241 if (ModifierFlags
.ABSTRACT
in flags
) {
2242 prop
.is_abstract
= true;
2244 if (ModifierFlags
.VIRTUAL
in flags
) {
2245 prop
.is_virtual
= true;
2247 if (ModifierFlags
.OVERRIDE
in flags
) {
2248 prop
.overrides
= true;
2250 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2251 prop
.external
= true;
2253 expect (TokenType
.OPEN_BRACE
);
2254 while (current () != TokenType
.CLOSE_BRACE
) {
2255 if (accept (TokenType
.DEFAULT
)) {
2256 if (prop
.default_expression
!= null) {
2257 throw new ParseError
.SYNTAX (get_error ("property default value already defined"));
2259 expect (TokenType
.ASSIGN
);
2260 prop
.default_expression
= parse_expression ();
2261 expect (TokenType
.SEMICOLON
);
2263 var accessor_begin
= get_location ();
2264 var attrs
= parse_attributes ();
2265 var accessor_access
= parse_access_modifier (SymbolAccessibility
.PUBLIC
);
2267 var value_type
= type
.copy ();
2268 value_type
.value_owned
= accept (TokenType
.OWNED
);
2270 if (accept (TokenType
.GET
)) {
2271 if (prop
.get_accessor
!= null) {
2272 throw new ParseError
.SYNTAX (get_error ("property get accessor already defined"));
2276 value_type
.value_owned
= true;
2280 if (!accept (TokenType
.SEMICOLON
)) {
2281 block
= parse_block ();
2282 prop
.external
= false;
2284 prop
.get_accessor
= new
PropertyAccessor (true, false, false, value_type
, block
, get_src (accessor_begin
));
2285 set_attributes (prop
.get_accessor
, attrs
);
2286 prop
.get_accessor
.access
= accessor_access
;
2288 bool writable
, _construct
;
2289 if (accept (TokenType
.SET
)) {
2291 _construct
= accept (TokenType
.CONSTRUCT
);
2292 } else if (accept (TokenType
.CONSTRUCT
)) {
2294 writable
= accept (TokenType
.SET
);
2296 throw new ParseError
.SYNTAX (get_error ("expected get, set, or construct"));
2298 if (prop
.set_accessor
!= null) {
2299 throw new ParseError
.SYNTAX (get_error ("property set accessor already defined"));
2302 if (!accept (TokenType
.SEMICOLON
)) {
2303 block
= parse_block ();
2304 prop
.external
= false;
2306 prop
.set_accessor
= new
PropertyAccessor (false, writable
, _construct
, value_type
, block
, get_src (accessor_begin
));
2307 set_attributes (prop
.set_accessor
, attrs
);
2308 prop
.set_accessor
.access
= accessor_access
;
2312 expect (TokenType
.CLOSE_BRACE
);
2314 if (!prop
.is_abstract
&& !scanner
.source_file
.external_package
) {
2315 bool empty_get
= (prop
.get_accessor
!= null && prop
.get_accessor
.body
== null);
2316 bool empty_set
= (prop
.set_accessor
!= null && prop
.set_accessor
.body
== null);
2318 if (empty_get
!= empty_set
) {
2320 Report
.error (prop
.source_reference
, "property getter must have a body");
2321 } else if (empty_set
) {
2322 Report
.error (prop
.source_reference
, "property setter must have a body");
2327 if (empty_get
&& empty_set
) {
2328 /* automatic property accessor body generation */
2329 var field_type
= prop
.property_type
.copy ();
2330 prop
.field
= new
Field ("_%s".printf (prop
.name
), field_type
, prop
.default_expression
, prop
.source_reference
);
2331 prop
.field
.access
= SymbolAccessibility
.PRIVATE
;
2338 Signal
parse_signal_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2339 var begin
= get_location ();
2340 var access
= parse_access_modifier ();
2341 var flags
= parse_member_declaration_modifiers ();
2342 expect (TokenType
.SIGNAL
);
2343 var type
= parse_type ();
2344 string id
= parse_identifier ();
2345 var sig
= new
Signal (id
, type
, get_src_com (begin
));
2346 sig
.access
= access
;
2347 set_attributes (sig
, attrs
);
2348 if (ModifierFlags
.VIRTUAL
in flags
) {
2349 sig
.is_virtual
= true;
2351 expect (TokenType
.OPEN_PARENS
);
2352 if (current () != TokenType
.CLOSE_PARENS
) {
2354 var param
= parse_parameter ();
2355 sig
.add_parameter (param
);
2356 } while (accept (TokenType
.COMMA
));
2358 expect (TokenType
.CLOSE_PARENS
);
2359 expect (TokenType
.SEMICOLON
);
2363 Constructor
parse_constructor_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2364 var begin
= get_location ();
2365 var flags
= parse_member_declaration_modifiers ();
2366 expect (TokenType
.CONSTRUCT
);
2367 var c
= new
Constructor (get_src_com (begin
));
2368 if (ModifierFlags
.STATIC
in flags
) {
2369 c
.binding
= MemberBinding
.STATIC
;
2370 } else if (ModifierFlags
.CLASS
in flags
) {
2371 c
.binding
= MemberBinding
.CLASS
;
2373 c
.body
= parse_block ();
2377 Destructor
parse_destructor_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2378 var begin
= get_location ();
2379 var flags
= parse_member_declaration_modifiers ();
2380 expect (TokenType
.TILDE
);
2381 parse_identifier ();
2382 expect (TokenType
.OPEN_PARENS
);
2383 expect (TokenType
.CLOSE_PARENS
);
2384 var d
= new
Destructor (get_src_com (begin
));
2385 if (ModifierFlags
.STATIC
in flags
) {
2386 d
.binding
= MemberBinding
.STATIC
;
2387 } else if (ModifierFlags
.CLASS
in flags
) {
2388 d
.binding
= MemberBinding
.CLASS
;
2390 d
.body
= parse_block ();
2394 Symbol
parse_struct_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2395 var begin
= get_location ();
2396 var access
= parse_access_modifier ();
2397 var flags
= parse_type_declaration_modifiers ();
2398 expect (TokenType
.STRUCT
);
2399 var sym
= parse_symbol_name ();
2400 var type_param_list
= parse_type_parameter_list ();
2401 var base_types
= new ArrayList
<DataType
> ();
2402 if (accept (TokenType
.COLON
)) {
2404 base_types
.add (parse_type ());
2405 } while (accept (TokenType
.COMMA
));
2407 var st
= new
Struct (sym
.name
, get_src_com (begin
));
2409 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2412 set_attributes (st
, attrs
);
2413 foreach (TypeParameter type_param
in type_param_list
) {
2414 st
.add_type_parameter (type_param
);
2416 foreach (DataType base_type
in base_types
) {
2417 st
.add_base_type (base_type
);
2420 parse_declarations (st
);
2423 while (sym
.inner
!= null) {
2425 var ns
= new
Namespace (sym
.name
, st
.source_reference
);
2426 if (result is Namespace
) {
2427 ns
.add_namespace ((Namespace
) result
);
2429 ns
.add_struct ((Struct
) result
);
2430 scanner
.source_file
.add_node (result
);
2437 void parse_struct_member (Struct st
) throws ParseError
{
2438 var sym
= parse_declaration ();
2439 if (sym is Method
) {
2440 st
.add_method ((Method
) sym
);
2441 } else if (sym is Field
) {
2442 st
.add_field ((Field
) sym
);
2443 } else if (sym is Constant
) {
2444 st
.add_constant ((Constant
) sym
);
2446 Report
.error (sym
.source_reference
, "unexpected declaration in struct");
2450 Symbol
parse_interface_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2451 var begin
= get_location ();
2452 var access
= parse_access_modifier ();
2453 var flags
= parse_type_declaration_modifiers ();
2454 expect (TokenType
.INTERFACE
);
2455 var sym
= parse_symbol_name ();
2456 var type_param_list
= parse_type_parameter_list ();
2457 var base_types
= new ArrayList
<DataType
> ();
2458 if (accept (TokenType
.COLON
)) {
2460 var type
= parse_type ();
2461 base_types
.add (type
);
2462 } while (accept (TokenType
.COMMA
));
2464 var iface
= new
Interface (sym
.name
, get_src_com (begin
));
2465 iface
.access
= access
;
2466 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2467 iface
.external
= true;
2469 set_attributes (iface
, attrs
);
2470 foreach (TypeParameter type_param
in type_param_list
) {
2471 iface
.add_type_parameter (type_param
);
2473 foreach (DataType base_type
in base_types
) {
2474 iface
.add_prerequisite (base_type
);
2477 parse_declarations (iface
);
2479 Symbol result
= iface
;
2480 while (sym
.inner
!= null) {
2482 var ns
= new
Namespace (sym
.name
, iface
.source_reference
);
2483 if (result is Namespace
) {
2484 ns
.add_namespace ((Namespace
) result
);
2486 ns
.add_interface ((Interface
) result
);
2487 scanner
.source_file
.add_node (result
);
2494 void parse_interface_member (Interface iface
) throws ParseError
{
2495 var sym
= parse_declaration ();
2497 iface
.add_class ((Class
) sym
);
2498 } else if (sym is Struct
) {
2499 iface
.add_struct ((Struct
) sym
);
2500 } else if (sym is Enum
) {
2501 iface
.add_enum ((Enum
) sym
);
2502 } else if (sym is Delegate
) {
2503 iface
.add_delegate ((Delegate
) sym
);
2504 } else if (sym is Method
) {
2505 iface
.add_method ((Method
) sym
);
2506 } else if (sym is Signal
) {
2507 iface
.add_signal ((Signal
) sym
);
2508 } else if (sym is Field
) {
2509 iface
.add_field ((Field
) sym
);
2510 } else if (sym is Property
) {
2511 iface
.add_property ((Property
) sym
);
2513 Report
.error (sym
.source_reference
, "unexpected declaration in interface");
2517 Symbol
parse_enum_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2518 var begin
= get_location ();
2519 var access
= parse_access_modifier ();
2520 var flags
= parse_type_declaration_modifiers ();
2521 expect (TokenType
.ENUM
);
2522 var sym
= parse_symbol_name ();
2523 var en
= new
Enum (sym
.name
, get_src_com (begin
));
2525 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2528 set_attributes (en
, attrs
);
2530 expect (TokenType
.OPEN_BRACE
);
2532 if (current () == TokenType
.CLOSE_BRACE
2533 && en
.get_values ().size
> 0) {
2534 // allow trailing comma
2537 var value_attrs
= parse_attributes ();
2538 var value_begin
= get_location ();
2539 string id
= parse_identifier ();
2540 var ev
= new
EnumValue (id
, get_src (value_begin
));
2541 set_attributes (ev
, value_attrs
);
2542 if (accept (TokenType
.ASSIGN
)) {
2543 ev
.value
= parse_expression ();
2546 } while (accept (TokenType
.COMMA
));
2547 if (accept (TokenType
.SEMICOLON
)) {
2549 while (current () != TokenType
.CLOSE_BRACE
) {
2550 var member_sym
= parse_declaration ();
2551 if (member_sym is Method
) {
2552 en
.add_method ((Method
) member_sym
);
2554 Report
.error (member_sym
.source_reference
, "unexpected declaration in enum");
2558 expect (TokenType
.CLOSE_BRACE
);
2561 while (sym
.inner
!= null) {
2563 var ns
= new
Namespace (sym
.name
, en
.source_reference
);
2564 if (result is Namespace
) {
2565 ns
.add_namespace ((Namespace
) result
);
2567 ns
.add_enum ((Enum
) result
);
2568 scanner
.source_file
.add_node (result
);
2575 Symbol
parse_errordomain_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2576 var begin
= get_location ();
2577 var access
= parse_access_modifier ();
2578 var flags
= parse_type_declaration_modifiers ();
2579 expect (TokenType
.ERRORDOMAIN
);
2580 var sym
= parse_symbol_name ();
2581 var ed
= new
ErrorDomain (sym
.name
, get_src_com (begin
));
2583 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2586 set_attributes (ed
, attrs
);
2588 expect (TokenType
.OPEN_BRACE
);
2590 if (current () == TokenType
.CLOSE_BRACE
2591 && ed
.get_codes ().size
> 0) {
2592 // allow trailing comma
2595 var code_attrs
= parse_attributes ();
2596 var code_begin
= get_location ();
2597 string id
= parse_identifier ();
2598 var ec
= new
ErrorCode (id
, get_src (code_begin
));
2599 set_attributes (ec
, code_attrs
);
2600 if (accept (TokenType
.ASSIGN
)) {
2601 ec
.value
= parse_expression ();
2604 } while (accept (TokenType
.COMMA
));
2605 if (accept (TokenType
.SEMICOLON
)) {
2606 // errordomain methods
2607 while (current () != TokenType
.CLOSE_BRACE
) {
2608 var member_sym
= parse_declaration ();
2609 if (member_sym is Method
) {
2610 ed
.add_method ((Method
) member_sym
);
2612 Report
.error (member_sym
.source_reference
, "unexpected declaration in errordomain");
2616 expect (TokenType
.CLOSE_BRACE
);
2619 while (sym
.inner
!= null) {
2621 var ns
= new
Namespace (sym
.name
, ed
.source_reference
);
2622 if (result is Namespace
) {
2623 ns
.add_namespace ((Namespace
) result
);
2625 ns
.add_error_domain ((ErrorDomain
) result
);
2626 scanner
.source_file
.add_node (result
);
2633 SymbolAccessibility
parse_access_modifier (SymbolAccessibility default_access
= SymbolAccessibility
.PRIVATE
) {
2634 switch (current ()) {
2635 case TokenType
.PRIVATE
:
2637 return SymbolAccessibility
.PRIVATE
;
2638 case TokenType
.PROTECTED
:
2640 return SymbolAccessibility
.PROTECTED
;
2641 case TokenType
.INTERNAL
:
2643 return SymbolAccessibility
.INTERNAL
;
2644 case TokenType
.PUBLIC
:
2646 return SymbolAccessibility
.PUBLIC
;
2648 return default_access
;
2652 ModifierFlags
parse_type_declaration_modifiers () {
2653 ModifierFlags flags
= 0;
2655 switch (current ()) {
2656 case TokenType
.ABSTRACT
:
2658 flags
|= ModifierFlags
.ABSTRACT
;
2660 case TokenType
.EXTERN
:
2662 flags
|= ModifierFlags
.EXTERN
;
2664 case TokenType
.STATIC
:
2666 flags
|= ModifierFlags
.STATIC
;
2674 ModifierFlags
parse_member_declaration_modifiers () {
2675 ModifierFlags flags
= 0;
2677 switch (current ()) {
2678 case TokenType
.ABSTRACT
:
2680 flags
|= ModifierFlags
.ABSTRACT
;
2682 case TokenType
.CLASS
:
2684 flags
|= ModifierFlags
.CLASS
;
2686 case TokenType
.EXTERN
:
2688 flags
|= ModifierFlags
.EXTERN
;
2690 case TokenType
.INLINE
:
2692 flags
|= ModifierFlags
.INLINE
;
2694 case TokenType
.OVERRIDE
:
2696 flags
|= ModifierFlags
.OVERRIDE
;
2698 case TokenType
.STATIC
:
2700 flags
|= ModifierFlags
.STATIC
;
2702 case TokenType
.VIRTUAL
:
2704 flags
|= ModifierFlags
.VIRTUAL
;
2712 FormalParameter
parse_parameter () throws ParseError
{
2713 var attrs
= parse_attributes ();
2714 var begin
= get_location ();
2715 if (accept (TokenType
.ELLIPSIS
)) {
2717 return new FormalParameter
.with_ellipsis (get_src (begin
));
2719 bool params_array
= accept (TokenType
.PARAMS
);
2720 var direction
= ParameterDirection
.IN
;
2721 if (accept (TokenType
.OUT
)) {
2722 direction
= ParameterDirection
.OUT
;
2723 } else if (accept (TokenType
.REF
)) {
2724 direction
= ParameterDirection
.REF
;
2728 if (direction
== ParameterDirection
.IN
) {
2729 // in parameters are weak by default
2730 type
= parse_type (false);
2732 // out parameters own the value by default
2733 type
= parse_type (true);
2735 string id
= parse_identifier ();
2736 var param
= new
FormalParameter (id
, type
, get_src (begin
));
2737 set_attributes (param
, attrs
);
2738 param
.direction
= direction
;
2739 param
.params_array
= params_array
;
2740 if (accept (TokenType
.ASSIGN
)) {
2741 param
.default_expression
= parse_expression ();
2746 CreationMethod
parse_creation_method_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2747 var begin
= get_location ();
2748 var access
= parse_access_modifier ();
2749 var flags
= parse_member_declaration_modifiers ();
2750 var sym
= parse_symbol_name ();
2751 CreationMethod method
;
2752 if (sym
.inner
== null) {
2753 method
= new
CreationMethod (sym
.name
, null, get_src_com (begin
));
2755 method
= new
CreationMethod (sym
.inner
.name
, sym
.name
, get_src_com (begin
));
2757 if (ModifierFlags
.EXTERN
in flags
) {
2758 method
.external
= true;
2760 expect (TokenType
.OPEN_PARENS
);
2761 if (current () != TokenType
.CLOSE_PARENS
) {
2763 var param
= parse_parameter ();
2764 method
.add_parameter (param
);
2765 } while (accept (TokenType
.COMMA
));
2767 expect (TokenType
.CLOSE_PARENS
);
2768 if (accept (TokenType
.YIELDS
)) {
2769 method
.coroutine
= true;
2771 if (accept (TokenType
.THROWS
)) {
2773 method
.add_error_type (parse_type ());
2774 } while (accept (TokenType
.COMMA
));
2776 method
.access
= access
;
2777 set_attributes (method
, attrs
);
2778 if (!accept (TokenType
.SEMICOLON
)) {
2779 method
.body
= parse_block ();
2780 } else if (scanner
.source_file
.external_package
) {
2781 method
.external
= true;
2786 Symbol
parse_delegate_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2787 var begin
= get_location ();
2788 var access
= parse_access_modifier ();
2789 var flags
= parse_member_declaration_modifiers ();
2790 expect (TokenType
.DELEGATE
);
2791 var type
= parse_type ();
2792 var sym
= parse_symbol_name ();
2793 var type_param_list
= parse_type_parameter_list ();
2794 var d
= new
Delegate (sym
.name
, type
, get_src_com (begin
));
2796 set_attributes (d
, attrs
);
2797 if (!(ModifierFlags
.STATIC
in flags
)) {
2798 d
.has_target
= true;
2800 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2803 foreach (TypeParameter type_param
in type_param_list
) {
2804 d
.add_type_parameter (type_param
);
2806 expect (TokenType
.OPEN_PARENS
);
2807 if (current () != TokenType
.CLOSE_PARENS
) {
2809 var param
= parse_parameter ();
2810 d
.add_parameter (param
);
2811 } while (accept (TokenType
.COMMA
));
2813 expect (TokenType
.CLOSE_PARENS
);
2814 if (accept (TokenType
.THROWS
)) {
2816 d
.add_error_type (parse_type ());
2817 } while (accept (TokenType
.COMMA
));
2819 expect (TokenType
.SEMICOLON
);
2822 while (sym
.inner
!= null) {
2824 var ns
= new
Namespace (sym
.name
, d
.source_reference
);
2825 if (result is Namespace
) {
2826 ns
.add_namespace ((Namespace
) result
);
2828 ns
.add_delegate ((Delegate
) result
);
2829 scanner
.source_file
.add_node (result
);
2836 Gee
.List
<TypeParameter
> parse_type_parameter_list () throws ParseError
{
2837 var list
= new ArrayList
<TypeParameter
> ();
2838 if (accept (TokenType
.OP_LT
)) {
2840 var begin
= get_location ();
2841 string id
= parse_identifier ();
2842 list
.add (new
TypeParameter (id
, get_src (begin
)));
2843 } while (accept (TokenType
.COMMA
));
2844 expect (TokenType
.OP_GT
);
2849 void skip_type_argument_list () throws ParseError
{
2850 if (accept (TokenType
.OP_LT
)) {
2853 } while (accept (TokenType
.COMMA
));
2854 expect (TokenType
.OP_GT
);
2858 // try to parse type argument list
2859 Gee
.List
<DataType
>?
parse_type_argument_list (bool maybe_expression
) throws ParseError
{
2860 var begin
= get_location ();
2861 if (accept (TokenType
.OP_LT
)) {
2862 var list
= new ArrayList
<DataType
> ();
2864 switch (current ()) {
2865 case TokenType
.VOID
:
2866 case TokenType
.DYNAMIC
:
2867 case TokenType
.UNOWNED
:
2868 case TokenType
.WEAK
:
2869 case TokenType
.IDENTIFIER
:
2870 var type
= parse_type ();
2877 } while (accept (TokenType
.COMMA
));
2878 if (!accept (TokenType
.OP_GT
)) {
2882 if (maybe_expression
) {
2883 // check follower to decide whether to keep type argument list
2884 switch (current ()) {
2885 case TokenType
.OPEN_PARENS
:
2886 case TokenType
.CLOSE_PARENS
:
2887 case TokenType
.CLOSE_BRACKET
:
2888 case TokenType
.COLON
:
2889 case TokenType
.SEMICOLON
:
2890 case TokenType
.COMMA
:
2892 case TokenType
.INTERR
:
2893 case TokenType
.OP_EQ
:
2894 case TokenType
.OP_NE
:
2895 // keep type argument list
2898 // interpret tokens as expression
2908 MemberAccess
parse_member_name () throws ParseError
{
2909 var begin
= get_location ();
2910 MemberAccess expr
= null;
2913 string id
= parse_identifier ();
2915 // The first member access can be global:: qualified
2916 bool qualified
= false;
2917 if (first
&& id
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
2918 id
= parse_identifier ();
2922 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (false);
2923 expr
= new
MemberAccess (expr
, id
, get_src (begin
));
2924 expr
.qualified
= qualified
;
2925 if (type_arg_list
!= null) {
2926 foreach (DataType type_arg
in type_arg_list
) {
2927 expr
.add_type_argument (type_arg
);
2932 } while (accept (TokenType
.DOT
));
2936 bool is_declaration_keyword (TokenType type
) {
2938 case TokenType
.ABSTRACT
:
2939 case TokenType
.CLASS
:
2940 case TokenType
.CONST
:
2941 case TokenType
.DELEGATE
:
2942 case TokenType
.ENUM
:
2943 case TokenType
.ERRORDOMAIN
:
2944 case TokenType
.EXTERN
:
2945 case TokenType
.INLINE
:
2946 case TokenType
.INTERFACE
:
2947 case TokenType
.INTERNAL
:
2948 case TokenType
.NAMESPACE
:
2949 case TokenType
.OVERRIDE
:
2950 case TokenType
.PRIVATE
:
2951 case TokenType
.PROTECTED
:
2952 case TokenType
.PUBLIC
:
2953 case TokenType
.SIGNAL
:
2954 case TokenType
.STATIC
:
2955 case TokenType
.STRUCT
:
2956 case TokenType
.VIRTUAL
:
2957 case TokenType
.VOLATILE
:
2965 public errordomain Vala
.ParseError
{