3 * Copyright (C) 2006-2008 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_last_string () {
135 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
136 return ((string) tokens
[last_index
].begin
.pos
).ndup ((tokens
[last_index
].end
.pos
- tokens
[last_index
].begin
.pos
));
139 SourceReference
get_src (SourceLocation begin
) {
140 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
142 return new
SourceReference (scanner
.source_file
, begin
.line
, begin
.column
, tokens
[last_index
].end
.line
, tokens
[last_index
].end
.column
);
145 SourceReference
get_src_com (SourceLocation begin
) {
146 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
148 var src
= new SourceReference
.with_comment (scanner
.source_file
, begin
.line
, begin
.column
, tokens
[last_index
].end
.line
, tokens
[last_index
].end
.column
, comment
);
153 SourceReference
get_current_src () {
154 return new
SourceReference (scanner
.source_file
, tokens
[index
].begin
.line
, tokens
[index
].begin
.column
, tokens
[index
].end
.line
, tokens
[index
].end
.column
);
157 SourceReference
get_last_src () {
158 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
160 return new
SourceReference (scanner
.source_file
, tokens
[last_index
].begin
.line
, tokens
[last_index
].begin
.column
, tokens
[last_index
].end
.line
, tokens
[last_index
].end
.column
);
163 void rollback (SourceLocation location
) {
164 while (tokens
[index
].begin
.pos
!= location
.pos
) {
169 void skip_identifier () throws ParseError
{
170 // also accept keywords as identifiers where there is no conflict
171 switch (current ()) {
172 case TokenType
.ABSTRACT
:
175 case TokenType
.BREAK
:
177 case TokenType
.CATCH
:
178 case TokenType
.CLASS
:
179 case TokenType
.CONST
:
180 case TokenType
.CONSTRUCT
:
181 case TokenType
.CONTINUE
:
182 case TokenType
.DEFAULT
:
183 case TokenType
.DELEGATE
:
184 case TokenType
.DELETE
:
186 case TokenType
.DYNAMIC
:
189 case TokenType
.ENSURES
:
190 case TokenType
.ERRORDOMAIN
:
191 case TokenType
.EXTERN
:
192 case TokenType
.FALSE
:
193 case TokenType
.FINALLY
:
195 case TokenType
.FOREACH
:
197 case TokenType
.IDENTIFIER
:
200 case TokenType
.INLINE
:
201 case TokenType
.INTERFACE
:
202 case TokenType
.INTERNAL
:
205 case TokenType
.NAMESPACE
:
209 case TokenType
.OVERRIDE
:
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
.USING
:
231 case TokenType
.VIRTUAL
:
233 case TokenType
.VOLATILE
:
235 case TokenType
.WHILE
:
236 case TokenType
.YIELD
:
237 case TokenType
.YIELDS
:
241 throw new ParseError
.SYNTAX (get_error ("expected identifier"));
245 string parse_identifier () throws ParseError
{
247 return get_last_string ();
250 Expression
parse_literal () throws ParseError
{
251 var begin
= get_location ();
253 switch (current ()) {
256 return new
BooleanLiteral (true, get_src (begin
));
257 case TokenType
.FALSE
:
259 return new
BooleanLiteral (false, get_src (begin
));
260 case TokenType
.INTEGER_LITERAL
:
262 return new
IntegerLiteral (get_last_string (), get_src (begin
));
263 case TokenType
.REAL_LITERAL
:
265 return new
RealLiteral (get_last_string (), get_src (begin
));
266 case TokenType
.CHARACTER_LITERAL
:
268 // FIXME validate and unescape here and just pass unichar to CharacterLiteral
269 var lit
= new
CharacterLiteral (get_last_string (), get_src (begin
));
271 Report
.error (lit
.source_reference
, "invalid character literal");
274 case TokenType
.STRING_LITERAL
:
276 return new
StringLiteral (get_last_string (), get_src (begin
));
277 case TokenType
.VERBATIM_STRING_LITERAL
:
279 string raw_string
= get_last_string ();
280 string escaped_string
= raw_string
.substring (3, raw_string
.len () - 6).escape ("");
281 return new
StringLiteral ("\"%s\"".printf (escaped_string
), get_src (begin
));
284 return new
NullLiteral (get_src (begin
));
286 throw new ParseError
.SYNTAX (get_error ("expected literal"));
290 public void parse_file (SourceFile source_file
) {
291 scanner
= new
Scanner (source_file
);
299 parse_using_directives ();
300 parse_declarations (context
.root
, true);
301 } catch (ParseError e
) {
308 void skip_symbol_name () throws ParseError
{
311 } while (accept (TokenType
.DOT
) || accept (TokenType
.DOUBLE_COLON
));
314 UnresolvedSymbol
parse_symbol_name () throws ParseError
{
315 var begin
= get_location ();
316 UnresolvedSymbol sym
= null;
318 string name
= parse_identifier ();
319 if (name
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
321 // qualified access to global symbol
322 name
= parse_identifier ();
323 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
324 sym
.qualified
= true;
327 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
328 } while (accept (TokenType
.DOT
));
332 void skip_type () throws ParseError
{
333 if (accept (TokenType
.VOID
)) {
334 while (accept (TokenType
.STAR
)) {
338 accept (TokenType
.DYNAMIC
);
339 accept (TokenType
.WEAK
);
341 skip_type_argument_list ();
342 while (accept (TokenType
.STAR
)) {
344 accept (TokenType
.INTERR
);
345 while (accept (TokenType
.OPEN_BRACKET
)) {
347 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
350 } while (accept (TokenType
.COMMA
));
351 expect (TokenType
.CLOSE_BRACKET
);
352 accept (TokenType
.INTERR
);
354 accept (TokenType
.OP_NEG
);
355 accept (TokenType
.HASH
);
358 DataType
parse_type (bool owned_by_default
= true) throws ParseError
{
359 var begin
= get_location ();
361 if (accept (TokenType
.VOID
)) {
362 DataType type
= new
VoidType ();
363 while (accept (TokenType
.STAR
)) {
364 type
= new
PointerType (type
);
369 bool is_dynamic
= accept (TokenType
.DYNAMIC
);
371 bool value_owned
= owned_by_default
;
372 if (owned_by_default
) {
373 value_owned
= !accept (TokenType
.WEAK
);
376 var sym
= parse_symbol_name ();
377 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (false);
379 DataType type
= new UnresolvedType
.from_symbol (sym
, get_src (begin
));
380 if (type_arg_list
!= null) {
381 foreach (DataType type_arg
in type_arg_list
) {
382 type
.add_type_argument (type_arg
);
386 while (accept (TokenType
.STAR
)) {
387 type
= new
PointerType (type
, get_src (begin
));
390 if (!(type is PointerType
)) {
391 type
.nullable
= accept (TokenType
.INTERR
);
394 // array brackets in types are read from right to left,
395 // this is more logical, especially when nullable arrays
396 // or pointers are involved
397 while (accept (TokenType
.OPEN_BRACKET
)) {
401 // support for stack-allocated arrays
402 // also required for decision between expression and declaration statement
403 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
407 while (accept (TokenType
.COMMA
));
408 expect (TokenType
.CLOSE_BRACKET
);
410 // arrays contain strong references by default
411 type
.value_owned
= true;
413 type
= new
ArrayType (type
, array_rank
, get_src (begin
));
414 type
.nullable
= accept (TokenType
.INTERR
);
417 if (accept (TokenType
.OP_NEG
)) {
418 Report
.warning (get_last_src (), "obsolete syntax, types are non-null by default");
421 if (!owned_by_default
) {
422 value_owned
= accept (TokenType
.HASH
);
425 type
.is_dynamic
= is_dynamic
;
426 type
.value_owned
= value_owned
;
430 Gee
.List
<Expression
> parse_argument_list () throws ParseError
{
431 var list
= new ArrayList
<Expression
> ();
432 if (current () != TokenType
.CLOSE_PARENS
) {
434 list
.add (parse_expression ());
435 } while (accept (TokenType
.COMMA
));
440 Expression
parse_primary_expression () throws ParseError
{
441 var begin
= get_location ();
445 switch (current ()) {
447 case TokenType
.FALSE
:
448 case TokenType
.INTEGER_LITERAL
:
449 case TokenType
.REAL_LITERAL
:
450 case TokenType
.CHARACTER_LITERAL
:
451 case TokenType
.STRING_LITERAL
:
452 case TokenType
.VERBATIM_STRING_LITERAL
:
454 expr
= parse_literal ();
456 case TokenType
.OPEN_PARENS
:
457 expr
= parse_tuple ();
460 expr
= parse_this_access ();
463 expr
= parse_base_access ();
466 expr
= parse_object_or_array_creation_expression ();
468 case TokenType
.SIZEOF
:
469 expr
= parse_sizeof_expression ();
471 case TokenType
.TYPEOF
:
472 expr
= parse_typeof_expression ();
475 expr
= parse_simple_name ();
480 // workaround for current limitation of exception handling
481 throw new ParseError
.SYNTAX ("syntax error in primary expression");
484 // process primary expressions that start with an inner primary expression
487 switch (current ()) {
489 expr
= parse_member_access (begin
, expr
);
491 case TokenType
.OP_PTR
:
492 expr
= parse_pointer_member_access (begin
, expr
);
494 case TokenType
.OPEN_PARENS
:
495 expr
= parse_method_call (begin
, expr
);
497 case TokenType
.OPEN_BRACKET
:
498 expr
= parse_element_access (begin
, expr
);
500 case TokenType
.OP_INC
:
501 expr
= parse_post_increment_expression (begin
, expr
);
503 case TokenType
.OP_DEC
:
504 expr
= parse_post_decrement_expression (begin
, expr
);
512 // workaround for current limitation of exception handling
513 throw new ParseError
.SYNTAX ("syntax error in primary expression");
520 Expression
parse_simple_name () throws ParseError
{
521 var begin
= get_location ();
522 string id
= parse_identifier ();
523 bool qualified
= false;
524 if (id
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
525 id
= parse_identifier ();
528 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (true);
529 var expr
= new
MemberAccess (null, id
, get_src (begin
));
530 expr
.qualified
= qualified
;
531 if (type_arg_list
!= null) {
532 foreach (DataType type_arg
in type_arg_list
) {
533 expr
.add_type_argument (type_arg
);
539 Expression
parse_tuple () throws ParseError
{
540 var begin
= get_location ();
541 expect (TokenType
.OPEN_PARENS
);
542 var expr_list
= new ArrayList
<Expression
> ();
543 if (current () != TokenType
.CLOSE_PARENS
) {
545 expr_list
.add (parse_expression ());
546 } while (accept (TokenType
.COMMA
));
548 expect (TokenType
.CLOSE_PARENS
);
549 if (expr_list
.size
!= 1) {
550 var tuple
= new
Tuple ();
551 foreach (Expression expr
in expr_list
) {
552 tuple
.add_expression (expr
);
556 return new
ParenthesizedExpression (expr_list
.get (0), get_src (begin
));
559 Expression
parse_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
560 expect (TokenType
.DOT
);
561 string id
= parse_identifier ();
562 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (true);
563 var expr
= new
MemberAccess (inner
, id
, get_src (begin
));
564 if (type_arg_list
!= null) {
565 foreach (DataType type_arg
in type_arg_list
) {
566 expr
.add_type_argument (type_arg
);
572 Expression
parse_pointer_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
573 expect (TokenType
.OP_PTR
);
574 string id
= parse_identifier ();
575 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (true);
576 var expr
= new MemberAccess
.pointer (inner
, id
, get_src (begin
));
577 if (type_arg_list
!= null) {
578 foreach (DataType type_arg
in type_arg_list
) {
579 expr
.add_type_argument (type_arg
);
585 Expression
parse_method_call (SourceLocation begin
, Expression inner
) throws ParseError
{
586 expect (TokenType
.OPEN_PARENS
);
587 var arg_list
= parse_argument_list ();
588 expect (TokenType
.CLOSE_PARENS
);
589 var init_list
= parse_object_initializer ();
591 if (init_list
.size
> 0 && inner is MemberAccess
) {
592 // struct creation expression
593 var member
= (MemberAccess
) inner
;
594 member
.creation_member
= true;
596 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
597 expr
.struct_creation
= true;
598 foreach (Expression arg
in arg_list
) {
599 expr
.add_argument (arg
);
601 foreach (MemberInitializer initializer
in init_list
) {
602 expr
.add_member_initializer (initializer
);
606 var expr
= new
MethodCall (inner
, get_src (begin
));
607 foreach (Expression arg
in arg_list
) {
608 expr
.add_argument (arg
);
614 Expression
parse_element_access (SourceLocation begin
, Expression inner
) throws ParseError
{
615 expect (TokenType
.OPEN_BRACKET
);
616 var index_list
= parse_expression_list ();
617 expect (TokenType
.CLOSE_BRACKET
);
619 var expr
= new
ElementAccess (inner
, get_src (begin
));
620 foreach (Expression index
in index_list
) {
621 expr
.append_index (index
);
626 Gee
.List
<Expression
> parse_expression_list () throws ParseError
{
627 var list
= new ArrayList
<Expression
> ();
629 list
.add (parse_expression ());
630 } while (accept (TokenType
.COMMA
));
634 Expression
parse_this_access () throws ParseError
{
635 var begin
= get_location ();
636 expect (TokenType
.THIS
);
637 return new
MemberAccess (null, "this", get_src (begin
));
640 Expression
parse_base_access () throws ParseError
{
641 var begin
= get_location ();
642 expect (TokenType
.BASE
);
643 return new
BaseAccess (get_src (begin
));
646 Expression
parse_post_increment_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
647 expect (TokenType
.OP_INC
);
648 return new
PostfixExpression (inner
, true, get_src (begin
));
651 Expression
parse_post_decrement_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
652 expect (TokenType
.OP_DEC
);
653 return new
PostfixExpression (inner
, false, get_src (begin
));
656 Expression
parse_object_or_array_creation_expression () throws ParseError
{
657 var begin
= get_location ();
658 expect (TokenType
.NEW
);
659 var member
= parse_member_name ();
660 if (accept (TokenType
.OPEN_PARENS
)) {
661 var expr
= parse_object_creation_expression (begin
, member
);
663 } else if (accept (TokenType
.OPEN_BRACKET
)) {
664 var expr
= parse_array_creation_expression (begin
, member
);
667 throw new ParseError
.SYNTAX (get_error ("expected ( or ["));
671 Expression
parse_object_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
672 member
.creation_member
= true;
673 var arg_list
= parse_argument_list ();
674 expect (TokenType
.CLOSE_PARENS
);
675 var init_list
= parse_object_initializer ();
677 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
678 foreach (Expression arg
in arg_list
) {
679 expr
.add_argument (arg
);
681 foreach (MemberInitializer initializer
in init_list
) {
682 expr
.add_member_initializer (initializer
);
687 Expression
parse_array_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
688 bool size_specified
= false;
689 Gee
.List
<Expression
> size_specifier_list
= null;
691 DataType element_type
= UnresolvedType
.new_from_expression (member
);
694 // array of arrays: new T[][42]
695 element_type
= new
ArrayType (element_type
, size_specifier_list
.size
, element_type
.source_reference
);
700 size_specifier_list
= new ArrayList
<Expression
> ();
702 Expression size
= null;
703 if (current () != TokenType
.CLOSE_BRACKET
&& current () != TokenType
.COMMA
) {
704 size
= parse_expression ();
705 size_specified
= true;
707 size_specifier_list
.add (size
);
708 } while (accept (TokenType
.COMMA
));
709 expect (TokenType
.CLOSE_BRACKET
);
710 } while (accept (TokenType
.OPEN_BRACKET
));
712 InitializerList initializer
= null;
713 if (current () == TokenType
.OPEN_BRACE
) {
714 initializer
= parse_initializer ();
716 var expr
= new
ArrayCreationExpression (element_type
, size_specifier_list
.size
, initializer
, get_src (begin
));
717 if (size_specified
) {
718 foreach (Expression size
in size_specifier_list
) {
719 expr
.append_size (size
);
725 Gee
.List
<MemberInitializer
> parse_object_initializer () throws ParseError
{
726 var list
= new ArrayList
<MemberInitializer
> ();
727 if (accept (TokenType
.OPEN_BRACE
)) {
729 list
.add (parse_member_initializer ());
730 } while (accept (TokenType
.COMMA
));
731 expect (TokenType
.CLOSE_BRACE
);
736 MemberInitializer
parse_member_initializer () throws ParseError
{
737 var begin
= get_location ();
738 string id
= parse_identifier ();
739 expect (TokenType
.ASSIGN
);
740 var expr
= parse_expression ();
742 return new
MemberInitializer (id
, expr
, get_src (begin
));
745 Expression
parse_sizeof_expression () throws ParseError
{
746 var begin
= get_location ();
747 expect (TokenType
.SIZEOF
);
748 expect (TokenType
.OPEN_PARENS
);
749 var type
= parse_type ();
750 expect (TokenType
.CLOSE_PARENS
);
752 return new
SizeofExpression (type
, get_src (begin
));
755 Expression
parse_typeof_expression () throws ParseError
{
756 var begin
= get_location ();
757 expect (TokenType
.TYPEOF
);
758 expect (TokenType
.OPEN_PARENS
);
759 var type
= parse_type ();
760 expect (TokenType
.CLOSE_PARENS
);
762 return new
TypeofExpression (type
, get_src (begin
));
765 UnaryOperator
get_unary_operator (TokenType token_type
) {
766 switch (token_type
) {
767 case TokenType
.PLUS
: return UnaryOperator
.PLUS
;
768 case TokenType
.MINUS
: return UnaryOperator
.MINUS
;
769 case TokenType
.OP_NEG
: return UnaryOperator
.LOGICAL_NEGATION
;
770 case TokenType
.TILDE
: return UnaryOperator
.BITWISE_COMPLEMENT
;
771 case TokenType
.OP_INC
: return UnaryOperator
.INCREMENT
;
772 case TokenType
.OP_DEC
: return UnaryOperator
.DECREMENT
;
773 case TokenType
.REF
: return UnaryOperator
.REF
;
774 case TokenType
.OUT
: return UnaryOperator
.OUT
;
775 default: return UnaryOperator
.NONE
;
779 Expression
parse_unary_expression () throws ParseError
{
780 var begin
= get_location ();
781 var operator
= get_unary_operator (current ());
782 if (operator
!= UnaryOperator
.NONE
) {
784 var op
= parse_unary_expression ();
785 return new
UnaryExpression (operator
, op
, get_src (begin
));
787 switch (current ()) {
790 var op
= parse_unary_expression ();
791 return new
ReferenceTransferExpression (op
, get_src (begin
));
792 case TokenType
.OPEN_PARENS
:
794 switch (current ()) {
796 case TokenType
.DYNAMIC
:
798 case TokenType
.IDENTIFIER
:
799 var type
= parse_type ();
800 if (accept (TokenType
.CLOSE_PARENS
)) {
801 // check follower to decide whether to create cast expression
802 switch (current ()) {
803 case TokenType
.OP_NEG
:
804 case TokenType
.TILDE
:
805 case TokenType
.OPEN_PARENS
:
807 case TokenType
.FALSE
:
808 case TokenType
.INTEGER_LITERAL
:
809 case TokenType
.REAL_LITERAL
:
810 case TokenType
.CHARACTER_LITERAL
:
811 case TokenType
.STRING_LITERAL
:
812 case TokenType
.VERBATIM_STRING_LITERAL
:
817 case TokenType
.SIZEOF
:
818 case TokenType
.TYPEOF
:
819 case TokenType
.IDENTIFIER
:
820 if (!(type is PointerType
) && !type
.value_owned
) {
821 Report
.warning (get_src (begin
), "obsolete syntax, weak type modifier unused in cast expressions");
823 var inner
= parse_unary_expression ();
824 return new
CastExpression (inner
, type
, get_src (begin
), false);
833 // no cast expression
838 var op
= parse_unary_expression ();
839 return new
PointerIndirection (op
, get_src (begin
));
840 case TokenType
.BITWISE_AND
:
842 var op
= parse_unary_expression ();
843 return new
AddressofExpression (op
, get_src (begin
));
848 var expr
= parse_primary_expression ();
852 BinaryOperator
get_binary_operator (TokenType token_type
) {
853 switch (token_type
) {
854 case TokenType
.STAR
: return BinaryOperator
.MUL
;
855 case TokenType
.DIV
: return BinaryOperator
.DIV
;
856 case TokenType
.PERCENT
: return BinaryOperator
.MOD
;
857 case TokenType
.PLUS
: return BinaryOperator
.PLUS
;
858 case TokenType
.MINUS
: return BinaryOperator
.MINUS
;
859 case TokenType
.OP_LT
: return BinaryOperator
.LESS_THAN
;
860 case TokenType
.OP_GT
: return BinaryOperator
.GREATER_THAN
;
861 case TokenType
.OP_LE
: return BinaryOperator
.LESS_THAN_OR_EQUAL
;
862 case TokenType
.OP_GE
: return BinaryOperator
.GREATER_THAN_OR_EQUAL
;
863 case TokenType
.OP_EQ
: return BinaryOperator
.EQUALITY
;
864 case TokenType
.OP_NE
: return BinaryOperator
.INEQUALITY
;
865 default: return BinaryOperator
.NONE
;
869 Expression
parse_multiplicative_expression () throws ParseError
{
870 var begin
= get_location ();
871 var left
= parse_unary_expression ();
874 var operator
= get_binary_operator (current ());
876 case BinaryOperator
.MUL
:
877 case BinaryOperator
.DIV
:
878 case BinaryOperator
.MOD
:
880 var right
= parse_unary_expression ();
881 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
891 Expression
parse_additive_expression () throws ParseError
{
892 var begin
= get_location ();
893 var left
= parse_multiplicative_expression ();
896 var operator
= get_binary_operator (current ());
898 case BinaryOperator
.PLUS
:
899 case BinaryOperator
.MINUS
:
901 var right
= parse_multiplicative_expression ();
902 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
912 Expression
parse_shift_expression () throws ParseError
{
913 var begin
= get_location ();
914 var left
= parse_additive_expression ();
917 switch (current ()) {
918 case TokenType
.OP_SHIFT_LEFT
:
920 var right
= parse_additive_expression ();
921 left
= new
BinaryExpression (BinaryOperator
.SHIFT_LEFT
, left
, right
, get_src (begin
));
923 // don't use OP_SHIFT_RIGHT to support >> for nested generics
924 case TokenType
.OP_GT
:
925 char* first_gt_pos
= tokens
[index
].begin
.pos
;
927 // only accept >> when there is no space between the two > signs
928 if (current () == TokenType
.OP_GT
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
930 var right
= parse_additive_expression ();
931 left
= new
BinaryExpression (BinaryOperator
.SHIFT_RIGHT
, left
, right
, get_src (begin
));
945 Expression
parse_relational_expression () throws ParseError
{
946 var begin
= get_location ();
947 var left
= parse_shift_expression ();
950 var operator
= get_binary_operator (current ());
952 case BinaryOperator
.LESS_THAN
:
953 case BinaryOperator
.LESS_THAN_OR_EQUAL
:
954 case BinaryOperator
.GREATER_THAN_OR_EQUAL
:
956 var right
= parse_shift_expression ();
957 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
959 case BinaryOperator
.GREATER_THAN
:
961 // ignore >> and >>= (two tokens due to generics)
962 if (current () != TokenType
.OP_GT
&& current () != TokenType
.OP_GE
) {
963 var right
= parse_shift_expression ();
964 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
971 switch (current ()) {
974 var type
= parse_type ();
975 left
= new
TypeCheck (left
, type
, get_src (begin
));
979 var type
= parse_type ();
980 left
= new
CastExpression (left
, type
, get_src (begin
), true);
992 Expression
parse_equality_expression () throws ParseError
{
993 var begin
= get_location ();
994 var left
= parse_relational_expression ();
997 var operator
= get_binary_operator (current ());
999 case BinaryOperator
.EQUALITY
:
1000 case BinaryOperator
.INEQUALITY
:
1002 var right
= parse_relational_expression ();
1003 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1013 Expression
parse_and_expression () throws ParseError
{
1014 var begin
= get_location ();
1015 var left
= parse_equality_expression ();
1016 while (accept (TokenType
.BITWISE_AND
)) {
1017 var right
= parse_equality_expression ();
1018 left
= new
BinaryExpression (BinaryOperator
.BITWISE_AND
, left
, right
, get_src (begin
));
1023 Expression
parse_exclusive_or_expression () throws ParseError
{
1024 var begin
= get_location ();
1025 var left
= parse_and_expression ();
1026 while (accept (TokenType
.CARRET
)) {
1027 var right
= parse_and_expression ();
1028 left
= new
BinaryExpression (BinaryOperator
.BITWISE_XOR
, left
, right
, get_src (begin
));
1033 Expression
parse_inclusive_or_expression () throws ParseError
{
1034 var begin
= get_location ();
1035 var left
= parse_exclusive_or_expression ();
1036 while (accept (TokenType
.BITWISE_OR
)) {
1037 var right
= parse_exclusive_or_expression ();
1038 left
= new
BinaryExpression (BinaryOperator
.BITWISE_OR
, left
, right
, get_src (begin
));
1043 Expression
parse_in_expression () throws ParseError
{
1044 var begin
= get_location ();
1045 var left
= parse_inclusive_or_expression ();
1046 while (accept (TokenType
.IN
)) {
1047 var right
= parse_inclusive_or_expression ();
1048 left
= new
BinaryExpression (BinaryOperator
.IN
, left
, right
, get_src (begin
));
1053 Expression
parse_conditional_and_expression () throws ParseError
{
1054 var begin
= get_location ();
1055 var left
= parse_in_expression ();
1056 while (accept (TokenType
.OP_AND
)) {
1057 var right
= parse_in_expression ();
1058 left
= new
BinaryExpression (BinaryOperator
.AND
, left
, right
, get_src (begin
));
1063 Expression
parse_conditional_or_expression () throws ParseError
{
1064 var begin
= get_location ();
1065 var left
= parse_conditional_and_expression ();
1066 while (accept (TokenType
.OP_OR
)) {
1067 var right
= parse_conditional_and_expression ();
1068 left
= new
BinaryExpression (BinaryOperator
.OR
, left
, right
, get_src (begin
));
1073 Expression
parse_conditional_expression () throws ParseError
{
1074 var begin
= get_location ();
1075 var condition
= parse_conditional_or_expression ();
1076 if (accept (TokenType
.INTERR
)) {
1077 var true_expr
= parse_expression ();
1078 expect (TokenType
.COLON
);
1079 var false_expr
= parse_expression ();
1080 return new
ConditionalExpression (condition
, true_expr
, false_expr
, get_src (begin
));
1086 Expression
parse_lambda_expression () throws ParseError
{
1087 var begin
= get_location ();
1088 Gee
.List
<string> params
= new ArrayList
<string> ();
1089 if (accept (TokenType
.OPEN_PARENS
)) {
1090 if (current () != TokenType
.CLOSE_PARENS
) {
1092 params
.add (parse_identifier ());
1093 } while (accept (TokenType
.COMMA
));
1095 expect (TokenType
.CLOSE_PARENS
);
1097 params
.add (parse_identifier ());
1099 expect (TokenType
.LAMBDA
);
1101 LambdaExpression lambda
;
1102 if (current () == TokenType
.OPEN_BRACE
) {
1103 var block
= parse_block ();
1104 lambda
= new LambdaExpression
.with_statement_body (block
, get_src (begin
));
1106 var expr
= parse_expression ();
1107 lambda
= new
LambdaExpression (expr
, get_src (begin
));
1109 foreach (string param
in params
) {
1110 lambda
.add_parameter (param
);
1115 AssignmentOperator
get_assignment_operator (TokenType token_type
) {
1116 switch (token_type
) {
1117 case TokenType
.ASSIGN
: return AssignmentOperator
.SIMPLE
;
1118 case TokenType
.ASSIGN_ADD
: return AssignmentOperator
.ADD
;
1119 case TokenType
.ASSIGN_SUB
: return AssignmentOperator
.SUB
;
1120 case TokenType
.ASSIGN_BITWISE_OR
: return AssignmentOperator
.BITWISE_OR
;
1121 case TokenType
.ASSIGN_BITWISE_AND
: return AssignmentOperator
.BITWISE_AND
;
1122 case TokenType
.ASSIGN_BITWISE_XOR
: return AssignmentOperator
.BITWISE_XOR
;
1123 case TokenType
.ASSIGN_DIV
: return AssignmentOperator
.DIV
;
1124 case TokenType
.ASSIGN_MUL
: return AssignmentOperator
.MUL
;
1125 case TokenType
.ASSIGN_PERCENT
: return AssignmentOperator
.PERCENT
;
1126 case TokenType
.ASSIGN_SHIFT_LEFT
: return AssignmentOperator
.SHIFT_LEFT
;
1127 default: return AssignmentOperator
.NONE
;
1131 Expression
parse_expression () throws ParseError
{
1132 var begin
= get_location ();
1133 Expression expr
= parse_conditional_expression ();
1135 if (current () == TokenType
.LAMBDA
) {
1137 var lambda
= parse_lambda_expression ();
1142 var operator
= get_assignment_operator (current ());
1143 if (operator
!= AssignmentOperator
.NONE
) {
1145 var rhs
= parse_expression ();
1146 expr
= new
Assignment (expr
, rhs
, operator
, get_src (begin
));
1148 // workaround for current limitation of exception handling
1149 throw new ParseError
.SYNTAX ("syntax error in assignment");
1151 } else if (current () == TokenType
.OP_GT
) { // >>=
1152 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1154 // only accept >>= when there is no space between the two > signs
1155 if (current () == TokenType
.OP_GE
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1157 var rhs
= parse_expression ();
1158 expr
= new
Assignment (expr
, rhs
, AssignmentOperator
.SHIFT_RIGHT
, get_src (begin
));
1160 // workaround for current limitation of exception handling
1161 throw new ParseError
.SYNTAX ("syntax error in assignment");
1175 void parse_statements (Block block
) throws ParseError
{
1176 while (current () != TokenType
.CLOSE_BRACE
1177 && current () != TokenType
.CASE
1178 && current () != TokenType
.DEFAULT
) {
1180 Statement stmt
= null;
1181 bool is_decl
= false;
1182 comment
= scanner
.pop_comment ();
1183 switch (current ()) {
1184 case TokenType
.OPEN_BRACE
:
1185 stmt
= parse_block ();
1187 case TokenType
.SEMICOLON
:
1188 stmt
= parse_empty_statement ();
1191 stmt
= parse_if_statement ();
1193 case TokenType
.SWITCH
:
1194 stmt
= parse_switch_statement ();
1196 case TokenType
.WHILE
:
1197 stmt
= parse_while_statement ();
1200 stmt
= parse_do_statement ();
1203 stmt
= parse_for_statement ();
1205 case TokenType
.FOREACH
:
1206 stmt
= parse_foreach_statement ();
1208 case TokenType
.BREAK
:
1209 stmt
= parse_break_statement ();
1211 case TokenType
.CONTINUE
:
1212 stmt
= parse_continue_statement ();
1214 case TokenType
.RETURN
:
1215 stmt
= parse_return_statement ();
1217 case TokenType
.YIELD
:
1218 stmt
= parse_yield_statement ();
1220 case TokenType
.THROW
:
1221 stmt
= parse_throw_statement ();
1224 stmt
= parse_try_statement ();
1226 case TokenType
.LOCK
:
1227 stmt
= parse_lock_statement ();
1229 case TokenType
.DELETE
:
1230 stmt
= parse_delete_statement ();
1234 parse_local_variable_declarations (block
);
1236 case TokenType
.OP_INC
:
1237 case TokenType
.OP_DEC
:
1238 case TokenType
.BASE
:
1239 case TokenType
.THIS
:
1240 case TokenType
.OPEN_PARENS
:
1241 case TokenType
.STAR
:
1243 stmt
= parse_expression_statement ();
1246 bool is_expr
= is_expression ();
1248 stmt
= parse_expression_statement ();
1251 parse_local_variable_declarations (block
);
1258 // workaround for current limitation of exception handling
1259 throw new ParseError
.SYNTAX ("syntax error in statement");
1261 block
.add_statement (stmt
);
1263 } catch (ParseError e
) {
1264 if (recover () != RecoveryState
.STATEMENT_BEGIN
) {
1265 // beginning of next declaration or end of file reached
1266 // return what we have so far
1273 bool is_expression () throws ParseError
{
1274 var begin
= get_location ();
1276 // decide between declaration and expression statement
1278 switch (current ()) {
1279 // invocation expression
1280 case TokenType
.OPEN_PARENS
:
1281 // postfix increment
1282 case TokenType
.OP_INC
:
1283 // postfix decrement
1284 case TokenType
.OP_DEC
:
1286 case TokenType
.ASSIGN
:
1287 case TokenType
.ASSIGN_ADD
:
1288 case TokenType
.ASSIGN_BITWISE_AND
:
1289 case TokenType
.ASSIGN_BITWISE_OR
:
1290 case TokenType
.ASSIGN_BITWISE_XOR
:
1291 case TokenType
.ASSIGN_DIV
:
1292 case TokenType
.ASSIGN_MUL
:
1293 case TokenType
.ASSIGN_PERCENT
:
1294 case TokenType
.ASSIGN_SHIFT_LEFT
:
1295 case TokenType
.ASSIGN_SUB
:
1296 case TokenType
.OP_GT
: // >>=
1299 // pointer member access
1300 case TokenType
.OP_PTR
:
1309 Block
parse_embedded_statement () throws ParseError
{
1310 if (current () == TokenType
.OPEN_BRACE
) {
1311 var block
= parse_block ();
1315 comment
= scanner
.pop_comment ();
1317 var block
= new
Block (get_src_com (get_location ()));
1318 var stmt
= parse_embedded_statement_without_block ();
1320 // workaround for current limitation of exception handling
1321 throw new ParseError
.SYNTAX ("syntax error in embedded statement");
1323 block
.add_statement (stmt
);
1328 Statement
parse_embedded_statement_without_block () throws ParseError
{
1329 switch (current ()) {
1330 case TokenType
.SEMICOLON
: return parse_empty_statement ();
1331 case TokenType
.IF
: return parse_if_statement ();
1332 case TokenType
.SWITCH
: return parse_switch_statement ();
1333 case TokenType
.WHILE
: return parse_while_statement ();
1334 case TokenType
.DO
: return parse_do_statement ();
1335 case TokenType
.FOR
: return parse_for_statement ();
1336 case TokenType
.FOREACH
: return parse_foreach_statement ();
1337 case TokenType
.BREAK
: return parse_break_statement ();
1338 case TokenType
.CONTINUE
: return parse_continue_statement ();
1339 case TokenType
.RETURN
: return parse_return_statement ();
1340 case TokenType
.YIELD
: return parse_yield_statement ();
1341 case TokenType
.THROW
: return parse_throw_statement ();
1342 case TokenType
.TRY
: return parse_try_statement ();
1343 case TokenType
.LOCK
: return parse_lock_statement ();
1344 case TokenType
.DELETE
: return parse_delete_statement ();
1345 default: return parse_expression_statement ();
1349 Block
parse_block () throws ParseError
{
1350 var begin
= get_location ();
1351 expect (TokenType
.OPEN_BRACE
);
1352 var block
= new
Block (get_src_com (begin
));
1353 parse_statements (block
);
1354 if (!accept (TokenType
.CLOSE_BRACE
)) {
1355 // only report error if it's not a secondary error
1356 if (Report
.get_errors () == 0) {
1357 Report
.error (get_current_src (), "expected `}'");
1361 block
.source_reference
.last_line
= get_current_src ().last_line
;
1362 block
.source_reference
.last_column
= get_current_src ().last_column
;
1367 Statement
parse_empty_statement () throws ParseError
{
1368 var begin
= get_location ();
1369 expect (TokenType
.SEMICOLON
);
1370 return new
EmptyStatement (get_src_com (begin
));
1373 void parse_local_variable_declarations (Block block
) throws ParseError
{
1374 DataType variable_type
;
1375 if (accept (TokenType
.VAR
)) {
1376 variable_type
= null;
1378 variable_type
= parse_type ();
1381 DataType type_copy
= null;
1382 if (variable_type
!= null) {
1383 type_copy
= variable_type
.copy ();
1385 var local
= parse_local_variable (type_copy
);
1386 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1387 } while (accept (TokenType
.COMMA
));
1388 expect (TokenType
.SEMICOLON
);
1391 LocalVariable
parse_local_variable (DataType? variable_type
) throws ParseError
{
1392 var begin
= get_location ();
1393 string id
= parse_identifier ();
1394 Expression initializer
= null;
1395 if (accept (TokenType
.ASSIGN
)) {
1396 initializer
= parse_variable_initializer ();
1398 // transform shorthand form
1399 // int[] array = { 42 };
1401 // int[] array = new int[] { 42 };
1402 var array_type
= variable_type as ArrayType
;
1403 if (array_type
!= null && initializer is InitializerList
) {
1404 initializer
= new
ArrayCreationExpression (array_type
.element_type
.copy (), array_type
.rank
, (InitializerList
) initializer
, initializer
.source_reference
);
1407 return new
LocalVariable (variable_type
, id
, initializer
, get_src_com (begin
));
1410 Statement
parse_expression_statement () throws ParseError
{
1411 var begin
= get_location ();
1412 var expr
= parse_statement_expression ();
1413 expect (TokenType
.SEMICOLON
);
1414 return new
ExpressionStatement (expr
, get_src_com (begin
));
1417 Expression
parse_statement_expression () throws ParseError
{
1418 // invocation expression, assignment,
1419 // or pre/post increment/decrement expression
1420 var expr
= parse_expression ();
1424 Statement
parse_if_statement () throws ParseError
{
1425 var begin
= get_location ();
1426 expect (TokenType
.IF
);
1427 expect (TokenType
.OPEN_PARENS
);
1428 var condition
= parse_expression ();
1429 expect (TokenType
.CLOSE_PARENS
);
1430 var src
= get_src_com (begin
);
1431 var true_stmt
= parse_embedded_statement ();
1432 Block false_stmt
= null;
1433 if (accept (TokenType
.ELSE
)) {
1434 false_stmt
= parse_embedded_statement ();
1436 return new
IfStatement (condition
, true_stmt
, false_stmt
, src
);
1439 Statement
parse_switch_statement () throws ParseError
{
1440 var begin
= get_location ();
1441 expect (TokenType
.SWITCH
);
1442 expect (TokenType
.OPEN_PARENS
);
1443 var condition
= parse_expression ();
1444 expect (TokenType
.CLOSE_PARENS
);
1445 var stmt
= new
SwitchStatement (condition
, get_src_com (begin
));
1446 expect (TokenType
.OPEN_BRACE
);
1447 while (current () != TokenType
.CLOSE_BRACE
) {
1448 var section
= new
SwitchSection (get_src_com (begin
));
1450 if (accept (TokenType
.CASE
)) {
1451 section
.add_label (new
SwitchLabel (parse_expression (), get_src_com (begin
)));
1453 expect (TokenType
.DEFAULT
);
1454 section
.add_label (new SwitchLabel
.with_default (get_src_com (begin
)));
1456 expect (TokenType
.COLON
);
1457 } while (current () == TokenType
.CASE
|| current () == TokenType
.DEFAULT
);
1458 parse_statements (section
);
1459 stmt
.add_section (section
);
1461 expect (TokenType
.CLOSE_BRACE
);
1465 Statement
parse_while_statement () throws ParseError
{
1466 var begin
= get_location ();
1467 expect (TokenType
.WHILE
);
1468 expect (TokenType
.OPEN_PARENS
);
1469 var condition
= parse_expression ();
1470 expect (TokenType
.CLOSE_PARENS
);
1471 var body
= parse_embedded_statement ();
1472 return new
WhileStatement (condition
, body
, get_src_com (begin
));
1475 Statement
parse_do_statement () throws ParseError
{
1476 var begin
= get_location ();
1477 expect (TokenType
.DO
);
1478 var body
= parse_embedded_statement ();
1479 expect (TokenType
.WHILE
);
1480 expect (TokenType
.OPEN_PARENS
);
1481 var condition
= parse_expression ();
1482 expect (TokenType
.CLOSE_PARENS
);
1483 expect (TokenType
.SEMICOLON
);
1484 return new
DoStatement (body
, condition
, get_src_com (begin
));
1487 Statement
parse_for_statement () throws ParseError
{
1488 var begin
= get_location ();
1490 expect (TokenType
.FOR
);
1491 expect (TokenType
.OPEN_PARENS
);
1492 var initializer_list
= new ArrayList
<Expression
> ();
1493 if (!accept (TokenType
.SEMICOLON
)) {
1495 switch (current ()) {
1499 case TokenType
.OP_INC
:
1500 case TokenType
.OP_DEC
:
1504 // workaround for current limitation of exception handling
1505 bool local_is_expr
= is_expression ();
1506 is_expr
= local_is_expr
;
1512 initializer_list
.add (parse_statement_expression ());
1513 } while (accept (TokenType
.COMMA
));
1515 block
= new
Block (get_src (begin
));
1516 DataType variable_type
;
1517 if (accept (TokenType
.VAR
)) {
1518 variable_type
= null;
1520 variable_type
= parse_type ();
1522 var local
= parse_local_variable (variable_type
);
1523 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1525 expect (TokenType
.SEMICOLON
);
1527 Expression condition
= null;
1528 if (current () != TokenType
.SEMICOLON
) {
1529 condition
= parse_expression ();
1531 expect (TokenType
.SEMICOLON
);
1532 var iterator_list
= new ArrayList
<Expression
> ();
1533 if (current () != TokenType
.CLOSE_PARENS
) {
1535 iterator_list
.add (parse_statement_expression ());
1536 } while (accept (TokenType
.COMMA
));
1538 expect (TokenType
.CLOSE_PARENS
);
1539 var src
= get_src_com (begin
);
1540 var body
= parse_embedded_statement ();
1541 var stmt
= new
ForStatement (condition
, body
, src
);
1542 foreach (Expression init
in initializer_list
) {
1543 stmt
.add_initializer (init
);
1545 foreach (Expression iter
in iterator_list
) {
1546 stmt
.add_iterator (iter
);
1548 if (block
!= null) {
1549 block
.add_statement (stmt
);
1556 Statement
parse_foreach_statement () throws ParseError
{
1557 var begin
= get_location ();
1558 expect (TokenType
.FOREACH
);
1559 expect (TokenType
.OPEN_PARENS
);
1560 DataType type
= null;
1561 if (!accept (TokenType
.VAR
)) {
1562 type
= parse_type ();
1564 string id
= parse_identifier ();
1565 expect (TokenType
.IN
);
1566 var collection
= parse_expression ();
1567 expect (TokenType
.CLOSE_PARENS
);
1568 var src
= get_src_com (begin
);
1569 var body
= parse_embedded_statement ();
1570 return new
ForeachStatement (type
, id
, collection
, body
, src
);
1573 Statement
parse_break_statement () throws ParseError
{
1574 var begin
= get_location ();
1575 expect (TokenType
.BREAK
);
1576 expect (TokenType
.SEMICOLON
);
1577 return new
BreakStatement (get_src_com (begin
));
1580 Statement
parse_continue_statement () throws ParseError
{
1581 var begin
= get_location ();
1582 expect (TokenType
.CONTINUE
);
1583 expect (TokenType
.SEMICOLON
);
1584 return new
ContinueStatement (get_src_com (begin
));
1587 Statement
parse_return_statement () throws ParseError
{
1588 var begin
= get_location ();
1589 expect (TokenType
.RETURN
);
1590 Expression expr
= null;
1591 if (current () != TokenType
.SEMICOLON
) {
1592 expr
= parse_expression ();
1594 expect (TokenType
.SEMICOLON
);
1595 return new
ReturnStatement (expr
, get_src_com (begin
));
1598 Statement
parse_yield_statement () throws ParseError
{
1599 var begin
= get_location ();
1600 expect (TokenType
.YIELD
);
1601 Expression expr
= null;
1602 if (current () != TokenType
.SEMICOLON
) {
1603 expr
= parse_expression ();
1605 expect (TokenType
.SEMICOLON
);
1606 return new
YieldStatement (expr
, get_src (begin
));
1609 Statement
parse_throw_statement () throws ParseError
{
1610 var begin
= get_location ();
1611 expect (TokenType
.THROW
);
1612 var expr
= parse_expression ();
1613 expect (TokenType
.SEMICOLON
);
1614 return new
ThrowStatement (expr
, get_src_com (begin
));
1617 Statement
parse_try_statement () throws ParseError
{
1618 var begin
= get_location ();
1619 expect (TokenType
.TRY
);
1620 var try_block
= parse_block ();
1621 Block finally_clause
= null;
1622 var catch_clauses
= new ArrayList
<CatchClause
> ();
1623 if (current () == TokenType
.CATCH
) {
1624 parse_catch_clauses (catch_clauses
);
1625 if (current () == TokenType
.FINALLY
) {
1626 finally_clause
= parse_finally_clause ();
1629 finally_clause
= parse_finally_clause ();
1631 var stmt
= new
TryStatement (try_block
, finally_clause
, get_src_com (begin
));
1632 foreach (CatchClause clause
in catch_clauses
) {
1633 stmt
.add_catch_clause (clause
);
1638 void parse_catch_clauses (Gee
.List
<CatchClause
> catch_clauses
) throws ParseError
{
1639 while (accept (TokenType
.CATCH
)) {
1640 var begin
= get_location ();
1641 DataType type
= null;
1643 if (accept (TokenType
.OPEN_PARENS
)) {
1644 type
= parse_type ();
1645 id
= parse_identifier ();
1646 expect (TokenType
.CLOSE_PARENS
);
1648 var block
= parse_block ();
1649 catch_clauses
.add (new
CatchClause (type
, id
, block
, get_src (begin
)));
1653 Block
parse_finally_clause () throws ParseError
{
1654 expect (TokenType
.FINALLY
);
1655 var block
= parse_block ();
1659 Statement
parse_lock_statement () throws ParseError
{
1660 var begin
= get_location ();
1661 expect (TokenType
.LOCK
);
1662 expect (TokenType
.OPEN_PARENS
);
1663 var expr
= parse_expression ();
1664 expect (TokenType
.CLOSE_PARENS
);
1665 var stmt
= parse_embedded_statement ();
1666 return new
LockStatement (expr
, stmt
, get_src_com (begin
));
1669 Statement
parse_delete_statement () throws ParseError
{
1670 var begin
= get_location ();
1671 expect (TokenType
.DELETE
);
1672 var expr
= parse_expression ();
1673 expect (TokenType
.SEMICOLON
);
1674 return new
DeleteStatement (expr
, get_src_com (begin
));
1677 Gee
.List
<Attribute
>?
parse_attributes () throws ParseError
{
1678 if (current () != TokenType
.OPEN_BRACKET
) {
1681 var attrs
= new ArrayList
<Attribute
> ();
1682 while (accept (TokenType
.OPEN_BRACKET
)) {
1684 var begin
= get_location ();
1685 string id
= parse_identifier ();
1686 var attr
= new
Attribute (id
, get_src (begin
));
1687 if (accept (TokenType
.OPEN_PARENS
)) {
1688 if (current () != TokenType
.CLOSE_PARENS
) {
1690 string id
= parse_identifier ();
1691 expect (TokenType
.ASSIGN
);
1692 var expr
= parse_expression ();
1693 attr
.add_argument (id
, expr
);
1694 } while (accept (TokenType
.COMMA
));
1696 expect (TokenType
.CLOSE_PARENS
);
1699 } while (accept (TokenType
.COMMA
));
1700 expect (TokenType
.CLOSE_BRACKET
);
1705 void set_attributes (CodeNode node
, Gee
.List
<Attribute
>? attributes
) {
1706 if (attributes
!= null) {
1707 foreach (Attribute attr
in (Gee
.List
<Attribute
>) attributes
) {
1708 node
.attributes
.append (attr
);
1713 Symbol
parse_declaration () throws ParseError
{
1714 comment
= scanner
.pop_comment ();
1715 var attrs
= parse_attributes ();
1717 var begin
= get_location ();
1719 TokenType last_keyword
= current ();
1721 while (is_declaration_keyword (current ())) {
1722 last_keyword
= current ();
1726 switch (current ()) {
1727 case TokenType
.CONSTRUCT
:
1729 return parse_constructor_declaration (attrs
);
1730 case TokenType
.TILDE
:
1732 return parse_destructor_declaration (attrs
);
1735 switch (current ()) {
1736 case TokenType
.OPEN_BRACE
:
1737 case TokenType
.SEMICOLON
:
1738 case TokenType
.COLON
:
1740 switch (last_keyword
) {
1741 case TokenType
.CLASS
: return parse_class_declaration (attrs
);
1742 case TokenType
.ENUM
: return parse_enum_declaration (attrs
);
1743 case TokenType
.ERRORDOMAIN
: return parse_errordomain_declaration (attrs
);
1744 case TokenType
.INTERFACE
: return parse_interface_declaration (attrs
);
1745 case TokenType
.NAMESPACE
: return parse_namespace_declaration (attrs
);
1746 case TokenType
.STRUCT
: return parse_struct_declaration (attrs
);
1750 case TokenType
.OPEN_PARENS
:
1752 return parse_creation_method_declaration (attrs
);
1754 skip_type (); // might contain type parameter list
1755 switch (current ()) {
1756 case TokenType
.OPEN_PARENS
:
1758 switch (last_keyword
) {
1759 case TokenType
.DELEGATE
: return parse_delegate_declaration (attrs
);
1760 case TokenType
.SIGNAL
: return parse_signal_declaration (attrs
);
1761 default: return parse_method_declaration (attrs
);
1763 case TokenType
.ASSIGN
:
1764 case TokenType
.SEMICOLON
:
1766 switch (last_keyword
) {
1767 case TokenType
.CONST
: return parse_constant_declaration (attrs
);
1768 default: return parse_field_declaration (attrs
);
1770 case TokenType
.OPEN_BRACE
:
1772 return parse_property_declaration (attrs
);
1781 throw new ParseError
.SYNTAX (get_error ("expected declaration"));
1784 void parse_declarations (Symbol parent
, bool root
= false) throws ParseError
{
1786 expect (TokenType
.OPEN_BRACE
);
1788 while (current () != TokenType
.CLOSE_BRACE
&& current () != TokenType
.EOF
) {
1790 if (parent is Namespace
) {
1791 parse_namespace_member ((Namespace
) parent
);
1792 } else if (parent is Class
) {
1793 parse_class_member ((Class
) parent
);
1794 } else if (parent is Struct
) {
1795 parse_struct_member ((Struct
) parent
);
1796 } else if (parent is Interface
) {
1797 parse_interface_member ((Interface
) parent
);
1799 } catch (ParseError e
) {
1803 if (r
== RecoveryState
.STATEMENT_BEGIN
) {
1809 if (r
== RecoveryState
.EOF
) {
1815 if (!accept (TokenType
.CLOSE_BRACE
)) {
1816 // only report error if it's not a secondary error
1817 if (Report
.get_errors () == 0) {
1818 Report
.error (get_current_src (), "expected `}'");
1824 enum RecoveryState
{
1830 RecoveryState
recover () {
1831 while (current () != TokenType
.EOF
) {
1832 switch (current ()) {
1833 case TokenType
.ABSTRACT
:
1834 case TokenType
.CLASS
:
1835 case TokenType
.CONST
:
1836 case TokenType
.CONSTRUCT
:
1837 case TokenType
.DELEGATE
:
1838 case TokenType
.ENUM
:
1839 case TokenType
.ERRORDOMAIN
:
1840 case TokenType
.EXTERN
:
1841 case TokenType
.INLINE
:
1842 case TokenType
.INTERFACE
:
1843 case TokenType
.INTERNAL
:
1844 case TokenType
.NAMESPACE
:
1845 case TokenType
.OVERRIDE
:
1846 case TokenType
.PRIVATE
:
1847 case TokenType
.PROTECTED
:
1848 case TokenType
.PUBLIC
:
1849 case TokenType
.SIGNAL
:
1850 case TokenType
.STATIC
:
1851 case TokenType
.STRUCT
:
1852 case TokenType
.VIRTUAL
:
1853 case TokenType
.VOLATILE
:
1854 return RecoveryState
.DECLARATION_BEGIN
;
1855 case TokenType
.BREAK
:
1856 case TokenType
.CONTINUE
:
1857 case TokenType
.DELETE
:
1860 case TokenType
.FOREACH
:
1862 case TokenType
.LOCK
:
1863 case TokenType
.RETURN
:
1864 case TokenType
.SWITCH
:
1865 case TokenType
.THROW
:
1868 case TokenType
.WHILE
:
1869 case TokenType
.YIELD
:
1870 return RecoveryState
.STATEMENT_BEGIN
;
1876 return RecoveryState
.EOF
;
1879 Namespace
parse_namespace_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
1880 var begin
= get_location ();
1881 expect (TokenType
.NAMESPACE
);
1882 var sym
= parse_symbol_name ();
1883 var ns
= new
Namespace (sym
.name
, get_src_com (begin
));
1884 set_attributes (ns
, attrs
);
1885 parse_declarations (ns
);
1887 Namespace result
= ns
;
1888 while (sym
.inner
!= null) {
1890 ns
= new
Namespace (sym
.name
, result
.source_reference
);
1891 ns
.add_namespace ((Namespace
) result
);
1897 void parse_namespace_member (Namespace ns
) throws ParseError
{
1898 var sym
= parse_declaration ();
1899 if (sym is Namespace
) {
1900 ns
.add_namespace ((Namespace
) sym
);
1901 } else if (sym is Class
) {
1902 ns
.add_class ((Class
) sym
);
1903 } else if (sym is Interface
) {
1904 ns
.add_interface ((Interface
) sym
);
1905 } else if (sym is Struct
) {
1906 ns
.add_struct ((Struct
) sym
);
1907 } else if (sym is Enum
) {
1908 ns
.add_enum ((Enum
) sym
);
1909 } else if (sym is ErrorDomain
) {
1910 ns
.add_error_domain ((ErrorDomain
) sym
);
1911 } else if (sym is Delegate
) {
1912 ns
.add_delegate ((Delegate
) sym
);
1913 } else if (sym is Method
) {
1914 var method
= (Method
) sym
;
1915 if (method
.binding
== MemberBinding
.INSTANCE
) {
1916 // default to static member binding
1917 method
.binding
= MemberBinding
.STATIC
;
1919 ns
.add_method (method
);
1920 } else if (sym is Field
) {
1921 var field
= (Field
) sym
;
1922 if (field
.binding
== MemberBinding
.INSTANCE
) {
1923 // default to static member binding
1924 field
.binding
= MemberBinding
.STATIC
;
1926 ns
.add_field (field
);
1927 } else if (sym is Constant
) {
1928 ns
.add_constant ((Constant
) sym
);
1929 } else if (sym
== null) {
1930 // workaround for current limitation of exception handling
1931 throw new ParseError
.SYNTAX ("syntax error in declaration");
1933 Report
.error (sym
.source_reference
, "unexpected declaration in namespace");
1935 scanner
.source_file
.add_node (sym
);
1938 void parse_using_directives () throws ParseError
{
1939 while (accept (TokenType
.USING
)) {
1941 var begin
= get_location ();
1942 var sym
= parse_symbol_name ();
1943 var ns_ref
= new
UsingDirective (sym
, get_src (begin
));
1944 scanner
.source_file
.add_using_directive (ns_ref
);
1945 } while (accept (TokenType
.COMMA
));
1946 expect (TokenType
.SEMICOLON
);
1950 Symbol
parse_class_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
1951 var begin
= get_location ();
1952 var access
= parse_access_modifier ();
1953 var flags
= parse_type_declaration_modifiers ();
1954 expect (TokenType
.CLASS
);
1955 var sym
= parse_symbol_name ();
1956 var type_param_list
= parse_type_parameter_list ();
1957 var base_types
= new ArrayList
<DataType
> ();
1958 if (accept (TokenType
.COLON
)) {
1960 base_types
.add (parse_type ());
1961 } while (accept (TokenType
.COMMA
));
1964 var cl
= new
Class (sym
.name
, get_src_com (begin
));
1966 if (ModifierFlags
.ABSTRACT
in flags
) {
1967 cl
.is_abstract
= true;
1969 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
1972 set_attributes (cl
, attrs
);
1973 foreach (TypeParameter type_param
in type_param_list
) {
1974 cl
.add_type_parameter (type_param
);
1976 foreach (DataType base_type
in base_types
) {
1977 cl
.add_base_type (base_type
);
1980 parse_declarations (cl
);
1982 // ensure there is always a default construction method
1983 if (!scanner
.source_file
.external_package
1985 && cl
.default_construction_method
== null) {
1986 var m
= new
CreationMethod (cl
.name
, null, cl
.source_reference
);
1987 m
.access
= SymbolAccessibility
.PUBLIC
;
1988 m
.body
= new
Block (cl
.source_reference
);
1993 while (sym
.inner
!= null) {
1995 var ns
= new
Namespace (sym
.name
, cl
.source_reference
);
1996 if (result is Namespace
) {
1997 ns
.add_namespace ((Namespace
) result
);
1999 ns
.add_class ((Class
) result
);
2000 scanner
.source_file
.add_node (result
);
2007 void parse_class_member (Class cl
) throws ParseError
{
2008 var sym
= parse_declaration ();
2010 cl
.add_class ((Class
) sym
);
2011 } else if (sym is Struct
) {
2012 cl
.add_struct ((Struct
) sym
);
2013 } else if (sym is Enum
) {
2014 cl
.add_enum ((Enum
) sym
);
2015 } else if (sym is Delegate
) {
2016 cl
.add_delegate ((Delegate
) sym
);
2017 } else if (sym is Method
) {
2018 cl
.add_method ((Method
) sym
);
2019 } else if (sym is Signal
) {
2020 cl
.add_signal ((Signal
) sym
);
2021 } else if (sym is Field
) {
2022 cl
.add_field ((Field
) sym
);
2023 } else if (sym is Constant
) {
2024 cl
.add_constant ((Constant
) sym
);
2025 } else if (sym is Property
) {
2026 cl
.add_property ((Property
) sym
);
2027 } else if (sym is Constructor
) {
2028 var c
= (Constructor
) sym
;
2029 if (c
.binding
== MemberBinding
.INSTANCE
) {
2031 } else if (c
.binding
== MemberBinding
.CLASS
) {
2032 cl
.class_constructor
= c
;
2034 cl
.static_constructor
= c
;
2036 } else if (sym is Destructor
) {
2037 cl
.destructor
= (Destructor
) sym
;
2038 } else if (sym
== null) {
2039 // workaround for current limitation of exception handling
2040 throw new ParseError
.SYNTAX ("syntax error in declaration");
2042 Report
.error (sym
.source_reference
, "unexpected declaration in class");
2046 Constant
parse_constant_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2047 var begin
= get_location ();
2048 var access
= parse_access_modifier ();
2049 var flags
= parse_member_declaration_modifiers ();
2050 expect (TokenType
.CONST
);
2051 var type
= parse_type (false);
2052 string id
= parse_identifier ();
2053 Expression initializer
= null;
2054 if (accept (TokenType
.ASSIGN
)) {
2055 initializer
= parse_variable_initializer ();
2057 expect (TokenType
.SEMICOLON
);
2059 // constant arrays don't own their element
2060 var array_type
= type as ArrayType
;
2061 if (array_type
!= null) {
2062 array_type
.element_type
.value_owned
= false;
2065 var c
= new
Constant (id
, type
, initializer
, get_src_com (begin
));
2067 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2070 set_attributes (c
, attrs
);
2074 Field
parse_field_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2075 var begin
= get_location ();
2076 var access
= parse_access_modifier ();
2077 var flags
= parse_member_declaration_modifiers ();
2078 var type
= parse_type ();
2079 string id
= parse_identifier ();
2080 var f
= new
Field (id
, type
, null, get_src_com (begin
));
2082 set_attributes (f
, attrs
);
2083 if (ModifierFlags
.STATIC
in flags
) {
2084 f
.binding
= MemberBinding
.STATIC
;
2085 } else if (ModifierFlags
.CLASS
in flags
) {
2086 f
.binding
= MemberBinding
.CLASS
;
2088 if (ModifierFlags
.ABSTRACT
in flags
2089 || ModifierFlags
.VIRTUAL
in flags
2090 || ModifierFlags
.OVERRIDE
in flags
) {
2091 Report
.error (f
.source_reference
, "abstract, virtual, and override modifiers are not applicable to fields");
2093 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2096 if (accept (TokenType
.ASSIGN
)) {
2097 f
.initializer
= parse_expression ();
2099 expect (TokenType
.SEMICOLON
);
2103 InitializerList
parse_initializer () throws ParseError
{
2104 var begin
= get_location ();
2105 expect (TokenType
.OPEN_BRACE
);
2106 var initializer
= new
InitializerList (get_src (begin
));
2107 if (current () != TokenType
.CLOSE_BRACE
) {
2109 var init
= parse_variable_initializer ();
2110 initializer
.append (init
);
2111 } while (accept (TokenType
.COMMA
));
2113 expect (TokenType
.CLOSE_BRACE
);
2117 Expression
parse_variable_initializer () throws ParseError
{
2118 if (current () == TokenType
.OPEN_BRACE
) {
2119 var expr
= parse_initializer ();
2122 var expr
= parse_expression ();
2127 Method
parse_method_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2128 var begin
= get_location ();
2129 var access
= parse_access_modifier ();
2130 var flags
= parse_member_declaration_modifiers ();
2131 var type
= parse_type ();
2132 string id
= parse_identifier ();
2133 parse_type_parameter_list ();
2134 var method
= new
Method (id
, type
, get_src_com (begin
));
2135 method
.access
= access
;
2136 set_attributes (method
, attrs
);
2137 if (ModifierFlags
.STATIC
in flags
) {
2138 method
.binding
= MemberBinding
.STATIC
;
2139 } else if (ModifierFlags
.CLASS
in flags
) {
2140 method
.binding
= MemberBinding
.CLASS
;
2143 if (method
.binding
== MemberBinding
.INSTANCE
) {
2144 if (ModifierFlags
.ABSTRACT
in flags
) {
2145 method
.is_abstract
= true;
2147 if (ModifierFlags
.VIRTUAL
in flags
) {
2148 method
.is_virtual
= true;
2150 if (ModifierFlags
.OVERRIDE
in flags
) {
2151 method
.overrides
= true;
2153 if ((method
.is_abstract
&& method
.is_virtual
)
2154 || (method
.is_abstract
&& method
.overrides
)
2155 || (method
.is_virtual
&& method
.overrides
)) {
2156 throw new ParseError
.SYNTAX (get_error ("only one of `abstract', `virtual', or `override' may be specified"));
2159 if (ModifierFlags
.ABSTRACT
in flags
2160 || ModifierFlags
.VIRTUAL
in flags
2161 || ModifierFlags
.OVERRIDE
in flags
) {
2162 throw new ParseError
.SYNTAX (get_error ("the modifiers `abstract', `virtual', and `override' are not valid for static methods"));
2166 if (ModifierFlags
.INLINE
in flags
) {
2167 method
.is_inline
= true;
2169 if (ModifierFlags
.EXTERN
in flags
) {
2170 method
.external
= true;
2172 expect (TokenType
.OPEN_PARENS
);
2173 if (current () != TokenType
.CLOSE_PARENS
) {
2175 var param
= parse_parameter ();
2176 method
.add_parameter (param
);
2177 } while (accept (TokenType
.COMMA
));
2179 expect (TokenType
.CLOSE_PARENS
);
2180 if (accept (TokenType
.YIELDS
)) {
2181 method
.coroutine
= true;
2183 if (accept (TokenType
.THROWS
)) {
2185 method
.add_error_type (parse_type ());
2186 } while (accept (TokenType
.COMMA
));
2188 while (accept (TokenType
.REQUIRES
)) {
2189 expect (TokenType
.OPEN_PARENS
);
2190 method
.add_precondition (parse_expression ());
2191 expect (TokenType
.CLOSE_PARENS
);
2193 while (accept (TokenType
.ENSURES
)) {
2194 expect (TokenType
.OPEN_PARENS
);
2195 method
.add_postcondition (parse_expression ());
2196 expect (TokenType
.CLOSE_PARENS
);
2198 if (!accept (TokenType
.SEMICOLON
)) {
2199 method
.body
= parse_block ();
2200 } else if (scanner
.source_file
.external_package
) {
2201 method
.external
= true;
2206 Property
parse_property_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2207 var begin
= get_location ();
2208 var access
= parse_access_modifier ();
2209 var flags
= parse_member_declaration_modifiers ();
2210 bool is_weak
= accept (TokenType
.WEAK
);
2211 var type
= parse_type (false);
2212 string id
= parse_identifier ();
2213 var prop
= new
Property (id
, type
, null, null, get_src_com (begin
));
2214 prop
.access
= access
;
2215 set_attributes (prop
, attrs
);
2216 if (ModifierFlags
.STATIC
in flags
) {
2217 prop
.binding
= MemberBinding
.STATIC
;
2218 } else if (ModifierFlags
.CLASS
in flags
) {
2219 prop
.binding
= MemberBinding
.CLASS
;
2221 if (ModifierFlags
.ABSTRACT
in flags
) {
2222 prop
.is_abstract
= true;
2224 if (ModifierFlags
.VIRTUAL
in flags
) {
2225 prop
.is_virtual
= true;
2227 if (ModifierFlags
.OVERRIDE
in flags
) {
2228 prop
.overrides
= true;
2230 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2231 prop
.external
= true;
2233 expect (TokenType
.OPEN_BRACE
);
2234 while (current () != TokenType
.CLOSE_BRACE
) {
2235 if (accept (TokenType
.DEFAULT
)) {
2236 if (prop
.default_expression
!= null) {
2237 throw new ParseError
.SYNTAX (get_error ("property default value already defined"));
2239 if (accept (TokenType
.OPEN_PARENS
)) {
2240 Report
.warning (get_last_src (), "deprecated syntax, use `default = value;`");
2241 prop
.default_expression
= parse_expression ();
2242 expect (TokenType
.CLOSE_PARENS
);
2244 expect (TokenType
.ASSIGN
);
2245 prop
.default_expression
= parse_expression ();
2247 expect (TokenType
.SEMICOLON
);
2249 var accessor_begin
= get_location ();
2250 var attrs
= parse_attributes ();
2251 var accessor_access
= parse_access_modifier (SymbolAccessibility
.PUBLIC
);
2252 if (accept (TokenType
.GET
)) {
2253 if (prop
.get_accessor
!= null) {
2254 throw new ParseError
.SYNTAX (get_error ("property get accessor already defined"));
2257 if (!accept (TokenType
.SEMICOLON
)) {
2258 block
= parse_block ();
2259 prop
.external
= false;
2261 prop
.get_accessor
= new
PropertyAccessor (true, false, false, block
, get_src (accessor_begin
));
2262 set_attributes (prop
.get_accessor
, attrs
);
2263 prop
.get_accessor
.access
= accessor_access
;
2265 bool writable
, _construct
;
2266 if (accept (TokenType
.SET
)) {
2268 _construct
= accept (TokenType
.CONSTRUCT
);
2269 } else if (accept (TokenType
.CONSTRUCT
)) {
2271 writable
= accept (TokenType
.SET
);
2273 throw new ParseError
.SYNTAX (get_error ("expected get, set, or construct"));
2275 if (prop
.set_accessor
!= null) {
2276 throw new ParseError
.SYNTAX (get_error ("property set accessor already defined"));
2279 if (!accept (TokenType
.SEMICOLON
)) {
2280 block
= parse_block ();
2281 prop
.external
= false;
2283 prop
.set_accessor
= new
PropertyAccessor (false, writable
, _construct
, block
, get_src (accessor_begin
));
2284 set_attributes (prop
.set_accessor
, attrs
);
2285 prop
.set_accessor
.access
= accessor_access
;
2289 expect (TokenType
.CLOSE_BRACE
);
2291 if (!prop
.is_abstract
&& !scanner
.source_file
.external_package
) {
2292 bool empty_get
= (prop
.get_accessor
!= null && prop
.get_accessor
.body
== null);
2293 bool empty_set
= (prop
.set_accessor
!= null && prop
.set_accessor
.body
== null);
2295 if (empty_get
!= empty_set
) {
2297 Report
.error (prop
.source_reference
, "property getter must have a body");
2298 } else if (empty_set
) {
2299 Report
.error (prop
.source_reference
, "property setter must have a body");
2304 if (empty_get
&& empty_set
) {
2305 /* automatic property accessor body generation */
2306 var field_type
= prop
.property_type
.copy ();
2307 field_type
.value_owned
= !is_weak
;
2308 prop
.field
= new
Field ("_%s".printf (prop
.name
), field_type
, prop
.default_expression
, prop
.source_reference
);
2309 prop
.field
.access
= SymbolAccessibility
.PRIVATE
;
2316 Signal
parse_signal_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2317 var begin
= get_location ();
2318 var access
= parse_access_modifier ();
2319 var flags
= parse_member_declaration_modifiers ();
2320 expect (TokenType
.SIGNAL
);
2321 var type
= parse_type ();
2322 string id
= parse_identifier ();
2323 var sig
= new
Signal (id
, type
, get_src_com (begin
));
2324 sig
.access
= access
;
2325 set_attributes (sig
, attrs
);
2326 if (ModifierFlags
.VIRTUAL
in flags
) {
2327 sig
.is_virtual
= true;
2329 expect (TokenType
.OPEN_PARENS
);
2330 if (current () != TokenType
.CLOSE_PARENS
) {
2332 var param
= parse_parameter ();
2333 sig
.add_parameter (param
);
2334 } while (accept (TokenType
.COMMA
));
2336 expect (TokenType
.CLOSE_PARENS
);
2337 expect (TokenType
.SEMICOLON
);
2341 Constructor
parse_constructor_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2342 var begin
= get_location ();
2343 var flags
= parse_member_declaration_modifiers ();
2344 expect (TokenType
.CONSTRUCT
);
2345 var c
= new
Constructor (get_src_com (begin
));
2346 if (ModifierFlags
.STATIC
in flags
) {
2347 c
.binding
= MemberBinding
.STATIC
;
2348 } else if (ModifierFlags
.CLASS
in flags
) {
2349 c
.binding
= MemberBinding
.CLASS
;
2351 c
.body
= parse_block ();
2355 Destructor
parse_destructor_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2356 var begin
= get_location ();
2357 expect (TokenType
.TILDE
);
2358 parse_identifier ();
2359 expect (TokenType
.OPEN_PARENS
);
2360 expect (TokenType
.CLOSE_PARENS
);
2361 var d
= new
Destructor (get_src_com (begin
));
2362 d
.body
= parse_block ();
2366 Symbol
parse_struct_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2367 var begin
= get_location ();
2368 var access
= parse_access_modifier ();
2369 var flags
= parse_type_declaration_modifiers ();
2370 expect (TokenType
.STRUCT
);
2371 var sym
= parse_symbol_name ();
2372 var type_param_list
= parse_type_parameter_list ();
2373 var base_types
= new ArrayList
<DataType
> ();
2374 if (accept (TokenType
.COLON
)) {
2376 base_types
.add (parse_type ());
2377 } while (accept (TokenType
.COMMA
));
2379 var st
= new
Struct (sym
.name
, get_src_com (begin
));
2381 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2384 set_attributes (st
, attrs
);
2385 foreach (TypeParameter type_param
in type_param_list
) {
2386 st
.add_type_parameter (type_param
);
2388 foreach (DataType base_type
in base_types
) {
2389 st
.add_base_type (base_type
);
2392 parse_declarations (st
);
2395 while (sym
.inner
!= null) {
2397 var ns
= new
Namespace (sym
.name
, st
.source_reference
);
2398 if (result is Namespace
) {
2399 ns
.add_namespace ((Namespace
) result
);
2401 ns
.add_struct ((Struct
) result
);
2402 scanner
.source_file
.add_node (result
);
2409 void parse_struct_member (Struct st
) throws ParseError
{
2410 var sym
= parse_declaration ();
2411 if (sym is Method
) {
2412 st
.add_method ((Method
) sym
);
2413 } else if (sym is Field
) {
2414 st
.add_field ((Field
) sym
);
2415 } else if (sym is Constant
) {
2416 st
.add_constant ((Constant
) sym
);
2417 } else if (sym
== null) {
2418 // workaround for current limitation of exception handling
2419 throw new ParseError
.SYNTAX ("syntax error in declaration");
2421 Report
.error (sym
.source_reference
, "unexpected declaration in struct");
2425 Symbol
parse_interface_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2426 var begin
= get_location ();
2427 var access
= parse_access_modifier ();
2428 var flags
= parse_type_declaration_modifiers ();
2429 expect (TokenType
.INTERFACE
);
2430 var sym
= parse_symbol_name ();
2431 var type_param_list
= parse_type_parameter_list ();
2432 var base_types
= new ArrayList
<DataType
> ();
2433 if (accept (TokenType
.COLON
)) {
2435 var type
= parse_type ();
2436 base_types
.add (type
);
2437 } while (accept (TokenType
.COMMA
));
2439 var iface
= new
Interface (sym
.name
, get_src_com (begin
));
2440 iface
.access
= access
;
2441 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2442 iface
.external
= true;
2444 set_attributes (iface
, attrs
);
2445 foreach (TypeParameter type_param
in type_param_list
) {
2446 iface
.add_type_parameter (type_param
);
2448 foreach (DataType base_type
in base_types
) {
2449 iface
.add_prerequisite (base_type
);
2452 parse_declarations (iface
);
2454 Symbol result
= iface
;
2455 while (sym
.inner
!= null) {
2457 var ns
= new
Namespace (sym
.name
, iface
.source_reference
);
2458 if (result is Namespace
) {
2459 ns
.add_namespace ((Namespace
) result
);
2461 ns
.add_interface ((Interface
) result
);
2462 scanner
.source_file
.add_node (result
);
2469 void parse_interface_member (Interface iface
) throws ParseError
{
2470 var sym
= parse_declaration ();
2472 iface
.add_class ((Class
) sym
);
2473 } else if (sym is Struct
) {
2474 iface
.add_struct ((Struct
) sym
);
2475 } else if (sym is Enum
) {
2476 iface
.add_enum ((Enum
) sym
);
2477 } else if (sym is Delegate
) {
2478 iface
.add_delegate ((Delegate
) sym
);
2479 } else if (sym is Method
) {
2480 iface
.add_method ((Method
) sym
);
2481 } else if (sym is Signal
) {
2482 iface
.add_signal ((Signal
) sym
);
2483 } else if (sym is Field
) {
2484 iface
.add_field ((Field
) sym
);
2485 } else if (sym is Property
) {
2486 iface
.add_property ((Property
) sym
);
2487 } else if (sym
== null) {
2488 // workaround for current limitation of exception handling
2489 throw new ParseError
.SYNTAX ("syntax error in declaration");
2491 Report
.error (sym
.source_reference
, "unexpected declaration in interface");
2495 Symbol
parse_enum_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2496 var begin
= get_location ();
2497 var access
= parse_access_modifier ();
2498 var flags
= parse_type_declaration_modifiers ();
2499 expect (TokenType
.ENUM
);
2500 var sym
= parse_symbol_name ();
2501 var en
= new
Enum (sym
.name
, get_src_com (begin
));
2503 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2506 set_attributes (en
, attrs
);
2508 expect (TokenType
.OPEN_BRACE
);
2510 if (current () == TokenType
.CLOSE_BRACE
) {
2511 // allow trailing comma
2514 var value_attrs
= parse_attributes ();
2515 var value_begin
= get_location ();
2516 string id
= parse_identifier ();
2517 var ev
= new
EnumValue (id
, get_src (value_begin
));
2518 set_attributes (ev
, value_attrs
);
2519 if (accept (TokenType
.ASSIGN
)) {
2520 ev
.value
= parse_expression ();
2523 } while (accept (TokenType
.COMMA
));
2524 if (accept (TokenType
.SEMICOLON
)) {
2526 while (current () != TokenType
.CLOSE_BRACE
) {
2527 var sym
= parse_declaration ();
2528 if (sym is Method
) {
2529 en
.add_method ((Method
) sym
);
2530 } else if (sym
== null) {
2531 // workaround for current limitation of exception handling
2532 throw new ParseError
.SYNTAX ("syntax error in declaration");
2534 Report
.error (sym
.source_reference
, "unexpected declaration in enum");
2538 expect (TokenType
.CLOSE_BRACE
);
2541 while (sym
.inner
!= null) {
2543 var ns
= new
Namespace (sym
.name
, en
.source_reference
);
2544 if (result is Namespace
) {
2545 ns
.add_namespace ((Namespace
) result
);
2547 ns
.add_enum ((Enum
) result
);
2548 scanner
.source_file
.add_node (result
);
2555 Symbol
parse_errordomain_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2556 var begin
= get_location ();
2557 var access
= parse_access_modifier ();
2558 var flags
= parse_type_declaration_modifiers ();
2559 expect (TokenType
.ERRORDOMAIN
);
2560 var sym
= parse_symbol_name ();
2561 var ed
= new
ErrorDomain (sym
.name
, get_src_com (begin
));
2563 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2566 set_attributes (ed
, attrs
);
2568 expect (TokenType
.OPEN_BRACE
);
2570 if (current () == TokenType
.CLOSE_BRACE
) {
2571 // allow trailing comma
2574 var code_attrs
= parse_attributes ();
2575 var code_begin
= get_location ();
2576 string id
= parse_identifier ();
2577 var ec
= new
ErrorCode (id
, get_src (code_begin
));
2578 set_attributes (ec
, code_attrs
);
2579 if (accept (TokenType
.ASSIGN
)) {
2580 ec
.value
= parse_expression ();
2583 } while (accept (TokenType
.COMMA
));
2584 if (accept (TokenType
.SEMICOLON
)) {
2585 // errordomain methods
2586 while (current () != TokenType
.CLOSE_BRACE
) {
2587 var sym
= parse_declaration ();
2588 if (sym is Method
) {
2589 ed
.add_method ((Method
) sym
);
2590 } else if (sym
== null) {
2591 // workaround for current limitation of exception handling
2592 throw new ParseError
.SYNTAX ("syntax error in declaration");
2594 Report
.error (sym
.source_reference
, "unexpected declaration in errordomain");
2598 expect (TokenType
.CLOSE_BRACE
);
2601 while (sym
.inner
!= null) {
2603 var ns
= new
Namespace (sym
.name
, ed
.source_reference
);
2604 if (result is Namespace
) {
2605 ns
.add_namespace ((Namespace
) result
);
2607 ns
.add_error_domain ((ErrorDomain
) result
);
2608 scanner
.source_file
.add_node (result
);
2615 SymbolAccessibility
parse_access_modifier (SymbolAccessibility default_access
= SymbolAccessibility
.PRIVATE
) {
2616 switch (current ()) {
2617 case TokenType
.PRIVATE
:
2619 return SymbolAccessibility
.PRIVATE
;
2620 case TokenType
.PROTECTED
:
2622 return SymbolAccessibility
.PROTECTED
;
2623 case TokenType
.INTERNAL
:
2625 return SymbolAccessibility
.INTERNAL
;
2626 case TokenType
.PUBLIC
:
2628 return SymbolAccessibility
.PUBLIC
;
2630 return default_access
;
2634 ModifierFlags
parse_type_declaration_modifiers () {
2635 ModifierFlags flags
= 0;
2637 switch (current ()) {
2638 case TokenType
.ABSTRACT
:
2640 flags
|= ModifierFlags
.ABSTRACT
;
2642 case TokenType
.EXTERN
:
2644 flags
|= ModifierFlags
.EXTERN
;
2646 case TokenType
.STATIC
:
2648 flags
|= ModifierFlags
.STATIC
;
2657 ModifierFlags
parse_member_declaration_modifiers () {
2658 ModifierFlags flags
= 0;
2660 switch (current ()) {
2661 case TokenType
.ABSTRACT
:
2663 flags
|= ModifierFlags
.ABSTRACT
;
2665 case TokenType
.CLASS
:
2667 flags
|= ModifierFlags
.CLASS
;
2669 case TokenType
.EXTERN
:
2671 flags
|= ModifierFlags
.EXTERN
;
2673 case TokenType
.INLINE
:
2675 flags
|= ModifierFlags
.INLINE
;
2677 case TokenType
.OVERRIDE
:
2679 flags
|= ModifierFlags
.OVERRIDE
;
2681 case TokenType
.STATIC
:
2683 flags
|= ModifierFlags
.STATIC
;
2685 case TokenType
.VIRTUAL
:
2687 flags
|= ModifierFlags
.VIRTUAL
;
2696 FormalParameter
parse_parameter () throws ParseError
{
2697 var attrs
= parse_attributes ();
2698 var begin
= get_location ();
2699 if (accept (TokenType
.ELLIPSIS
)) {
2701 return new FormalParameter
.with_ellipsis (get_src (begin
));
2703 bool params_array
= accept (TokenType
.PARAMS
);
2704 bool construct_param
= false;
2705 if (accept (TokenType
.CONSTRUCT
)) {
2706 Report
.warning (get_last_src (), "deprecated syntax, use assignments in the method body");
2707 construct_param
= true;
2709 var direction
= ParameterDirection
.IN
;
2710 if (accept (TokenType
.OUT
)) {
2711 direction
= ParameterDirection
.OUT
;
2712 } else if (accept (TokenType
.REF
)) {
2713 direction
= ParameterDirection
.REF
;
2717 if (direction
== ParameterDirection
.IN
) {
2718 // in parameters are weak by default
2719 type
= parse_type (false);
2721 // out parameters own the value by default
2722 type
= parse_type (true);
2724 string id
= parse_identifier ();
2725 var param
= new
FormalParameter (id
, type
, get_src (begin
));
2726 set_attributes (param
, attrs
);
2727 param
.direction
= direction
;
2728 param
.params_array
= params_array
;
2729 param
.construct_parameter
= construct_param
;
2730 if (accept (TokenType
.ASSIGN
)) {
2731 param
.default_expression
= parse_expression ();
2736 CreationMethod
parse_creation_method_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2737 var begin
= get_location ();
2738 var access
= parse_access_modifier ();
2739 var flags
= parse_member_declaration_modifiers ();
2740 var sym
= parse_symbol_name ();
2741 CreationMethod method
;
2742 if (sym
.inner
== null) {
2743 method
= new
CreationMethod (sym
.name
, null, get_src_com (begin
));
2745 method
= new
CreationMethod (sym
.inner
.name
, sym
.name
, get_src_com (begin
));
2747 if (ModifierFlags
.EXTERN
in flags
) {
2748 method
.external
= true;
2750 expect (TokenType
.OPEN_PARENS
);
2751 if (current () != TokenType
.CLOSE_PARENS
) {
2753 var param
= parse_parameter ();
2754 method
.add_parameter (param
);
2755 } while (accept (TokenType
.COMMA
));
2757 expect (TokenType
.CLOSE_PARENS
);
2758 if (accept (TokenType
.YIELDS
)) {
2759 method
.coroutine
= true;
2761 if (accept (TokenType
.THROWS
)) {
2763 method
.add_error_type (parse_type ());
2764 } while (accept (TokenType
.COMMA
));
2766 method
.access
= access
;
2767 set_attributes (method
, attrs
);
2768 if (!accept (TokenType
.SEMICOLON
)) {
2769 method
.body
= parse_block ();
2770 } else if (scanner
.source_file
.external_package
) {
2771 method
.external
= true;
2776 Symbol
parse_delegate_declaration (Gee
.List
<Attribute
>? attrs
) throws ParseError
{
2777 var begin
= get_location ();
2778 var access
= parse_access_modifier ();
2779 var flags
= parse_member_declaration_modifiers ();
2780 expect (TokenType
.DELEGATE
);
2781 var type
= parse_type ();
2782 var sym
= parse_symbol_name ();
2783 var type_param_list
= parse_type_parameter_list ();
2784 var d
= new
Delegate (sym
.name
, type
, get_src_com (begin
));
2786 set_attributes (d
, attrs
);
2787 if (!(ModifierFlags
.STATIC
in flags
)) {
2788 d
.has_target
= true;
2790 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.external_package
) {
2793 foreach (TypeParameter type_param
in type_param_list
) {
2794 d
.add_type_parameter (type_param
);
2796 expect (TokenType
.OPEN_PARENS
);
2797 if (current () != TokenType
.CLOSE_PARENS
) {
2799 var param
= parse_parameter ();
2800 d
.add_parameter (param
);
2801 } while (accept (TokenType
.COMMA
));
2803 expect (TokenType
.CLOSE_PARENS
);
2804 if (accept (TokenType
.THROWS
)) {
2807 } while (accept (TokenType
.COMMA
));
2809 expect (TokenType
.SEMICOLON
);
2812 while (sym
.inner
!= null) {
2814 var ns
= new
Namespace (sym
.name
, d
.source_reference
);
2815 if (result is Namespace
) {
2816 ns
.add_namespace ((Namespace
) result
);
2818 ns
.add_delegate ((Delegate
) result
);
2819 scanner
.source_file
.add_node (result
);
2826 Gee
.List
<TypeParameter
> parse_type_parameter_list () throws ParseError
{
2827 var list
= new ArrayList
<TypeParameter
> ();
2828 if (accept (TokenType
.OP_LT
)) {
2830 var begin
= get_location ();
2831 string id
= parse_identifier ();
2832 list
.add (new
TypeParameter (id
, get_src (begin
)));
2833 } while (accept (TokenType
.COMMA
));
2834 expect (TokenType
.OP_GT
);
2839 void skip_type_argument_list () throws ParseError
{
2840 if (accept (TokenType
.OP_LT
)) {
2843 } while (accept (TokenType
.COMMA
));
2844 expect (TokenType
.OP_GT
);
2848 // try to parse type argument list
2849 Gee
.List
<DataType
>?
parse_type_argument_list (bool maybe_expression
) throws ParseError
{
2850 var begin
= get_location ();
2851 if (accept (TokenType
.OP_LT
)) {
2852 var list
= new ArrayList
<DataType
> ();
2854 switch (current ()) {
2855 case TokenType
.VOID
:
2856 case TokenType
.DYNAMIC
:
2857 case TokenType
.WEAK
:
2858 case TokenType
.IDENTIFIER
:
2859 var type
= parse_type ();
2866 } while (accept (TokenType
.COMMA
));
2867 if (!accept (TokenType
.OP_GT
)) {
2871 if (maybe_expression
) {
2872 // check follower to decide whether to keep type argument list
2873 switch (current ()) {
2874 case TokenType
.OPEN_PARENS
:
2875 case TokenType
.CLOSE_PARENS
:
2876 case TokenType
.CLOSE_BRACKET
:
2877 case TokenType
.COLON
:
2878 case TokenType
.SEMICOLON
:
2879 case TokenType
.COMMA
:
2881 case TokenType
.INTERR
:
2882 case TokenType
.OP_EQ
:
2883 case TokenType
.OP_NE
:
2884 // keep type argument list
2887 // interpret tokens as expression
2897 MemberAccess
parse_member_name () throws ParseError
{
2898 var begin
= get_location ();
2899 MemberAccess expr
= null;
2902 string id
= parse_identifier ();
2904 // The first member access can be global:: qualified
2905 bool qualified
= false;
2906 if (first
&& id
== "global" && accept (TokenType
.DOUBLE_COLON
)) {
2907 id
= parse_identifier ();
2911 Gee
.List
<DataType
> type_arg_list
= parse_type_argument_list (false);
2912 expr
= new
MemberAccess (expr
, id
, get_src (begin
));
2913 expr
.qualified
= qualified
;
2914 if (type_arg_list
!= null) {
2915 foreach (DataType type_arg
in type_arg_list
) {
2916 expr
.add_type_argument (type_arg
);
2921 } while (accept (TokenType
.DOT
));
2925 bool is_declaration_keyword (TokenType type
) {
2927 case TokenType
.ABSTRACT
:
2928 case TokenType
.CLASS
:
2929 case TokenType
.CONST
:
2930 case TokenType
.DELEGATE
:
2931 case TokenType
.ENUM
:
2932 case TokenType
.ERRORDOMAIN
:
2933 case TokenType
.EXTERN
:
2934 case TokenType
.INLINE
:
2935 case TokenType
.INTERFACE
:
2936 case TokenType
.INTERNAL
:
2937 case TokenType
.NAMESPACE
:
2938 case TokenType
.OVERRIDE
:
2939 case TokenType
.PRIVATE
:
2940 case TokenType
.PROTECTED
:
2941 case TokenType
.PUBLIC
:
2942 case TokenType
.SIGNAL
:
2943 case TokenType
.STATIC
:
2944 case TokenType
.STRUCT
:
2945 case TokenType
.VIRTUAL
:
2946 case TokenType
.VOLATILE
:
2954 public errordomain Vala
.ParseError
{