1 /* valagenieparser.vala
3 * Copyright (C) 2008 Jamie McCracken, Jürg Billeter
4 * Based on code by Jürg Billeter
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * Jamie McCracken jamiemcc gnome org
28 * Code visitor parsing all Genie source files.
30 public class Vala
.Genie
.Parser
: CodeVisitor
{
37 // index of current token in buffer
39 // number of tokens in buffer
46 /* hack needed to know if any part of an expression is a lambda one */
47 bool current_expr_is_lambda
;
49 const int BUFFER_SIZE
= 32;
51 static List
<TypeParameter
> _empty_type_parameter_list
;
54 public TokenType type
;
55 public SourceLocation begin
;
56 public SourceLocation end
;
74 tokens
= new TokenInfo
[BUFFER_SIZE
];
76 current_expr_is_lambda
= false;
80 * Parses all .gs source files in the specified code context and
83 * @param context a code context
85 public void parse (CodeContext context
) {
86 this
.context
= context
;
87 context
.accept (this
);
90 public override void visit_source_file (SourceFile source_file
) {
91 if (source_file
.filename
.has_suffix (".gs")) {
92 parse_file (source_file
);
97 index
= (index
+ 1) % BUFFER_SIZE
;
100 SourceLocation begin
, end
;
101 TokenType type
= scanner
.read_token (out begin
, out end
);
102 tokens
[index
].type
= type
;
103 tokens
[index
].begin
= begin
;
104 tokens
[index
].end
= end
;
107 return (tokens
[index
].type
!= TokenType
.EOF
);
110 inline
void prev () {
111 index
= (index
- 1 + BUFFER_SIZE
) % BUFFER_SIZE
;
113 assert (size
<= BUFFER_SIZE
);
116 inline TokenType
current () {
117 return tokens
[index
].type
;
120 inline
bool accept (TokenType type
) {
121 if (current () == type
) {
128 inline
bool accept_terminator () {
129 if (current () == TokenType
.SEMICOLON
|| current () == TokenType
.EOL
) {
136 inline
bool accept_block () {
138 bool has_term
= accept_terminator ();
140 if (accept (TokenType
.INDENT
)) {
152 string get_error (string msg
) {
153 var begin
= get_location ();
155 Report
.error (get_src (begin
), "syntax error, " + msg
);
159 inline
bool expect (TokenType type
) throws ParseError
{
164 TokenType cur
= current ();
165 TokenType pre
= tokens
[index
- 1].type
;
167 throw new ParseError
.SYNTAX (get_error ("expected %s but got %s with previous %s".printf (type
.to_string (), cur
.to_string (), pre
.to_string())));
170 inline
bool expect_terminator () throws ParseError
{
171 if (accept_terminator ()) {
175 TokenType cur
= current ();
177 throw new ParseError
.SYNTAX (get_error ("expected line end or semicolon but got %s".printf (cur
.to_string())));
180 inline SourceLocation
get_location () {
181 return tokens
[index
].begin
;
184 string get_current_string () {
185 return ((string) tokens
[index
].begin
.pos
).substring (0, (int) (tokens
[index
].end
.pos
- tokens
[index
].begin
.pos
));
188 string get_last_string () {
189 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
190 return ((string) tokens
[last_index
].begin
.pos
).substring (0, (int) (tokens
[last_index
].end
.pos
- tokens
[last_index
].begin
.pos
));
193 SourceReference
get_src (SourceLocation begin
) {
194 int last_index
= (index
+ BUFFER_SIZE
- 1) % BUFFER_SIZE
;
196 return new
SourceReference (scanner
.source_file
, begin
.line
, begin
.column
, tokens
[last_index
].end
.line
, tokens
[last_index
].end
.column
);
199 SourceReference
get_current_src () {
200 return new
SourceReference (scanner
.source_file
, tokens
[index
].begin
.line
, tokens
[index
].begin
.column
, tokens
[index
].end
.line
, tokens
[index
].end
.column
);
203 void rollback (SourceLocation location
) {
204 while (tokens
[index
].begin
.pos
!= location
.pos
) {
205 index
= (index
- 1 + BUFFER_SIZE
) % BUFFER_SIZE
;
207 if (size
> BUFFER_SIZE
) {
208 scanner
.seek (location
);
217 inline SymbolAccessibility
get_access (string s
) {
219 return SymbolAccessibility
.PRIVATE
;
222 return SymbolAccessibility
.PUBLIC
;
225 void skip_identifier () throws ParseError
{
226 // also accept keywords as identifiers where there is no conflict
227 switch (current ()) {
228 case TokenType
.ABSTRACT
:
230 case TokenType
.ASSERT
:
231 case TokenType
.ASYNC
:
232 case TokenType
.BREAK
:
233 case TokenType
.CLASS
:
234 case TokenType
.CONST
:
235 case TokenType
.CONTINUE
:
236 case TokenType
.DEDENT
:
238 case TokenType
.DEFAULT
:
239 case TokenType
.DELEGATE
:
240 case TokenType
.DELETE
:
242 case TokenType
.DOWNTO
:
243 case TokenType
.DYNAMIC
:
247 case TokenType
.ENSURES
:
248 case TokenType
.ERRORDOMAIN
:
249 case TokenType
.EVENT
:
250 case TokenType
.EXCEPT
:
251 case TokenType
.EXTERN
:
252 case TokenType
.FALSE
:
253 case TokenType
.FINAL
:
254 case TokenType
.FINALLY
:
257 case TokenType
.IDENTIFIER
:
260 case TokenType
.INDENT
:
262 case TokenType
.INLINE
:
263 case TokenType
.INTERFACE
:
264 case TokenType
.INTERNAL
:
268 case TokenType
.NAMESPACE
:
273 case TokenType
.OVERRIDE
:
274 case TokenType
.OWNED
:
276 case TokenType
.PRINT
:
277 case TokenType
.PRIVATE
:
279 case TokenType
.RAISE
:
280 case TokenType
.RAISES
:
282 case TokenType
.REQUIRES
:
283 case TokenType
.RETURN
:
285 case TokenType
.SIZEOF
:
286 case TokenType
.STATIC
:
287 case TokenType
.STRUCT
:
288 case TokenType
.SUPER
:
293 case TokenType
.TYPEOF
:
294 case TokenType
.UNOWNED
:
297 case TokenType
.VIRTUAL
:
299 case TokenType
.VOLATILE
:
302 case TokenType
.WHILE
:
303 case TokenType
.YIELD
:
306 case TokenType
.INTEGER_LITERAL
:
307 case TokenType
.REAL_LITERAL
:
308 // also accept integer and real literals
309 // as long as they contain at least one character
310 // and no decimal point
311 // for example, 2D and 3D
312 string id
= get_current_string ();
313 if (id
[id
.length
- 1].isalpha () && !("." in id
)) {
319 throw new ParseError
.SYNTAX (get_error ("expected identifier"));
323 string parse_identifier () throws ParseError
{
325 return get_last_string ();
328 Expression
parse_literal () throws ParseError
{
329 var begin
= get_location ();
331 switch (current ()) {
334 return new
BooleanLiteral (true, get_src (begin
));
335 case TokenType
.FALSE
:
337 return new
BooleanLiteral (false, get_src (begin
));
338 case TokenType
.INTEGER_LITERAL
:
340 return new
IntegerLiteral (get_last_string (), get_src (begin
));
341 case TokenType
.REAL_LITERAL
:
343 return new
RealLiteral (get_last_string (), get_src (begin
));
344 case TokenType
.CHARACTER_LITERAL
:
346 // FIXME validate and unescape here and just pass unichar to CharacterLiteral
347 var lit
= new
CharacterLiteral (get_last_string (), get_src (begin
));
349 Report
.error (lit
.source_reference
, "invalid character literal");
352 case TokenType
.REGEX_LITERAL
:
354 string match_part
= get_last_string ();
355 SourceReference src_begin
= get_src (begin
);
356 expect (TokenType
.CLOSE_REGEX_LITERAL
);
357 string close_token
= get_last_string ();
358 return new
RegexLiteral ("%s/%s".printf (close_token
, match_part
), src_begin
);
359 case TokenType
.STRING_LITERAL
:
361 return new
StringLiteral (get_last_string (), get_src (begin
));
362 case TokenType
.TEMPLATE_STRING_LITERAL
:
364 return new
StringLiteral ("\"%s\"".printf (get_last_string ()), get_src (begin
));
365 case TokenType
.VERBATIM_STRING_LITERAL
:
367 string raw_string
= get_last_string ();
368 string escaped_string
= raw_string
.substring (3, raw_string
.length
- 6).escape ("");
369 return new
StringLiteral ("\"%s\"".printf (escaped_string
), get_src (begin
));
372 return new
NullLiteral (get_src (begin
));
374 throw new ParseError
.SYNTAX (get_error ("expected literal"));
378 public void parse_file (SourceFile source_file
) {
379 scanner
= new
Scanner (source_file
);
380 scanner
.parse_file_comments ();
381 scanner
.indent_spaces
= 0;
388 var begin
= get_location ();
389 /* see if there is an indent attribute */
390 if (accept (TokenType
.OPEN_BRACKET
)) {
391 var id
= parse_identifier ();
392 if (id
== "indent") {
393 expect (TokenType
.ASSIGN
);
394 expect (TokenType
.INTEGER_LITERAL
);
395 scanner
.indent_spaces
= int.parse (get_last_string());
396 expect (TokenType
.CLOSE_BRACKET
);
397 expect (TokenType
.EOL
);
403 parse_using_directives (context
.root
);
404 parse_declarations (context
.root
, true);
405 } catch (ParseError e
) {
412 void skip_symbol_name () throws ParseError
{
415 } while (accept (TokenType
.DOT
));
418 UnresolvedSymbol
parse_symbol_name () throws ParseError
{
419 var begin
= get_location ();
420 UnresolvedSymbol sym
= null;
422 string name
= parse_identifier ();
423 sym
= new
UnresolvedSymbol (sym
, name
, get_src (begin
));
424 } while (accept (TokenType
.DOT
));
428 void skip_type () throws ParseError
{
429 if (accept (TokenType
.VOID
)) {
430 while (accept (TokenType
.STAR
)) {
434 accept (TokenType
.DYNAMIC
);
435 accept (TokenType
.OWNED
);
436 accept (TokenType
.UNOWNED
);
437 accept (TokenType
.WEAK
);
438 if (accept (TokenType
.ARRAY
) || accept (TokenType
.LIST
) || accept (TokenType
.DICT
)) {
439 accept (TokenType
.OF
);
443 skip_type_argument_list ();
444 while (accept (TokenType
.OPEN_BRACKET
)) {
446 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
449 } while (accept (TokenType
.COMMA
));
450 expect (TokenType
.CLOSE_BRACKET
);
452 accept (TokenType
.OP_NEG
);
453 accept (TokenType
.INTERR
);
454 accept (TokenType
.HASH
);
458 Expression
parse_regex_literal () throws ParseError
{
459 expect (TokenType
.OPEN_REGEX_LITERAL
);
461 var expr
= parse_literal ();
466 DataType
parse_type (bool owned_by_default
= true) throws ParseError
{
467 var begin
= get_location ();
469 if (accept (TokenType
.VOID
)) {
470 DataType type
= new
VoidType ();
471 while (accept (TokenType
.STAR
)) {
472 type
= new
PointerType (type
);
477 List
<DataType
> type_arg_list
= null;
478 UnresolvedSymbol sym
= null;
480 bool is_dynamic
= accept (TokenType
.DYNAMIC
);
481 bool value_owned
= owned_by_default
;
482 if (owned_by_default
) {
483 if (accept (TokenType
.UNOWNED
)
484 || accept (TokenType
.WEAK
)) {
488 value_owned
= accept (TokenType
.OWNED
);
492 bool is_array
= false;
494 if (accept (TokenType
.ARRAY
)) {
495 expect (TokenType
.OF
);
500 bool is_list
= false;
502 if (accept (TokenType
.LIST
)) {
503 expect (TokenType
.OF
);
509 bool is_dict
= false;
511 if (accept (TokenType
.DICT
)) {
512 expect (TokenType
.OF
);
518 var sym_parent
= new
UnresolvedSymbol (null, "Gee", get_src (begin
));
519 sym
= new
UnresolvedSymbol (sym_parent
, "ArrayList", get_src (begin
));
520 } else if (is_dict
) {
521 var sym_parent
= new
UnresolvedSymbol (null, "Gee", get_src (begin
));
522 sym
= new
UnresolvedSymbol (sym_parent
, "HashMap", get_src (begin
));
524 sym
= parse_symbol_name ();
527 type_arg_list
= parse_type_argument_list (false);
529 DataType type
= new UnresolvedType
.from_symbol (sym
, get_src (begin
));
530 if (type_arg_list
!= null) {
531 foreach (DataType type_arg
in type_arg_list
) {
532 type
.add_type_argument (type_arg
);
536 while (accept (TokenType
.STAR
)) {
537 type
= new
PointerType (type
, get_src (begin
));
540 if (!(type is PointerType
)) {
541 type
.nullable
= accept (TokenType
.INTERR
);
546 if (!accept (TokenType
.OPEN_BRACKET
)) {
547 type
.value_owned
= true;
548 type
= new
ArrayType (type
, 1, get_src (begin
));
549 type
.nullable
= accept (TokenType
.INTERR
);
554 while (accept (TokenType
.OPEN_BRACKET
)) {
555 bool invalid_array
= false;
559 // required for decision between expression and declaration statement
560 if (current () != TokenType
.COMMA
&& current () != TokenType
.CLOSE_BRACKET
) {
562 // only used for parsing, reject use as real type
563 invalid_array
= true;
566 while (accept (TokenType
.COMMA
));
567 expect (TokenType
.CLOSE_BRACKET
);
569 type
.value_owned
= true;
570 var array_type
= new
ArrayType (type
, array_rank
, get_src (begin
));
571 array_type
.nullable
= accept (TokenType
.INTERR
);
573 array_type
.invalid_syntax
= invalid_array
;
580 if (!owned_by_default
) {
581 value_owned
= accept (TokenType
.HASH
);
584 type
.is_dynamic
= is_dynamic
;
585 type
.value_owned
= value_owned
;
589 DataType?
parse_inline_array_type (DataType? type
) throws ParseError
{
590 var begin
= get_location ();
592 // inline-allocated array
593 if (type
!= null && accept (TokenType
.OPEN_BRACKET
)) {
594 int array_length
= -1;
596 if (current () != TokenType
.CLOSE_BRACKET
) {
597 if (current () != TokenType
.INTEGER_LITERAL
) {
598 throw new ParseError
.SYNTAX (get_error ("expected `]' or integer literal"));
601 var length_literal
= (IntegerLiteral
) parse_literal ();
602 array_length
= int.parse (length_literal
.value
);
604 expect (TokenType
.CLOSE_BRACKET
);
606 var array_type
= new
ArrayType (type
, 1, get_src (begin
));
607 array_type
.inline_allocated
= true;
608 if (array_length
> 0) {
609 array_type
.fixed_length
= true;
610 array_type
.length
= array_length
;
612 array_type
.value_owned
= type
.value_owned
;
619 List
<Expression
> parse_argument_list () throws ParseError
{
620 var list
= new ArrayList
<Expression
> ();
621 if (current () != TokenType
.CLOSE_PARENS
) {
623 list
.add (parse_argument ());
624 } while (accept (TokenType
.COMMA
));
629 Expression
parse_argument () throws ParseError
{
630 var begin
= get_location ();
632 if (accept (TokenType
.REF
)) {
633 var inner
= parse_expression ();
634 return new
UnaryExpression (UnaryOperator
.REF
, inner
, get_src (begin
));
635 } else if (accept (TokenType
.OUT
)) {
636 var inner
= parse_expression ();
637 return new
UnaryExpression (UnaryOperator
.OUT
, inner
, get_src (begin
));
639 var expr
= parse_expression ();
640 var ma
= expr as MemberAccess
;
641 if (ma
!= null && ma
.inner
== null && accept (TokenType
.COLON
)) {
643 expr
= parse_expression ();
644 return new
NamedArgument (ma
.member_name
, expr
, get_src (begin
));
652 Expression
parse_primary_expression () throws ParseError
{
653 var begin
= get_location ();
657 switch (current ()) {
659 case TokenType
.FALSE
:
660 case TokenType
.INTEGER_LITERAL
:
661 case TokenType
.REAL_LITERAL
:
662 case TokenType
.CHARACTER_LITERAL
:
663 case TokenType
.REGEX_LITERAL
:
664 case TokenType
.STRING_LITERAL
:
665 case TokenType
.TEMPLATE_STRING_LITERAL
:
666 case TokenType
.VERBATIM_STRING_LITERAL
:
668 expr
= parse_literal ();
670 case TokenType
.ASSERT
:
671 return parse_assert_expression ();
672 case TokenType
.OPEN_BRACE
:
673 expr
= parse_initializer ();
675 case TokenType
.OPEN_PARENS
:
676 expr
= parse_tuple ();
678 case TokenType
.OPEN_REGEX_LITERAL
:
679 expr
= parse_regex_literal ();
681 case TokenType
.OPEN_TEMPLATE
:
682 expr
= parse_template ();
685 expr
= parse_this_access ();
687 case TokenType
.SUPER
:
688 expr
= parse_base_access ();
691 expr
= parse_object_or_array_creation_expression ();
693 case TokenType
.PRINT
:
694 return parse_print_expression ();
695 case TokenType
.SIZEOF
:
696 expr
= parse_sizeof_expression ();
698 case TokenType
.TYPEOF
:
699 expr
= parse_typeof_expression ();
701 case TokenType
.YIELD
:
702 expr
= parse_yield_expression ();
705 expr
= parse_simple_name ();
709 // process primary expressions that start with an inner primary expression
712 switch (current ()) {
714 expr
= parse_member_access (begin
, expr
);
716 case TokenType
.OP_PTR
:
717 expr
= parse_pointer_member_access (begin
, expr
);
719 case TokenType
.OPEN_PARENS
:
720 expr
= parse_method_call (begin
, expr
);
722 case TokenType
.OPEN_BRACKET
:
723 expr
= parse_element_access (begin
, expr
);
725 case TokenType
.OP_INC
:
726 expr
= parse_post_increment_expression (begin
, expr
);
728 case TokenType
.OP_DEC
:
729 expr
= parse_post_decrement_expression (begin
, expr
);
741 Expression
parse_simple_name () throws ParseError
{
742 var begin
= get_location ();
743 string id
= parse_identifier ();
744 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
745 var expr
= new
MemberAccess (null, id
, get_src (begin
));
746 if (type_arg_list
!= null) {
747 foreach (DataType type_arg
in type_arg_list
) {
748 expr
.add_type_argument (type_arg
);
754 Expression
parse_template () throws ParseError
{
755 var begin
= get_location ();
756 var template
= new
Template ();
758 expect (TokenType
.OPEN_TEMPLATE
);
759 while (current () != TokenType
.CLOSE_TEMPLATE
) {
760 template
.add_expression (parse_expression ());
761 expect (TokenType
.COMMA
);
763 expect (TokenType
.CLOSE_TEMPLATE
);
765 template
.source_reference
= get_src (begin
);
769 Expression
parse_tuple () throws ParseError
{
770 expect (TokenType
.OPEN_PARENS
);
771 var expr_list
= new ArrayList
<Expression
> ();
772 if (current () != TokenType
.CLOSE_PARENS
) {
774 expr_list
.add (parse_expression ());
775 } while (accept (TokenType
.COMMA
));
777 expect (TokenType
.CLOSE_PARENS
);
778 if (expr_list
.size
!= 1) {
779 var tuple
= new
Tuple ();
780 foreach (Expression expr
in expr_list
) {
781 tuple
.add_expression (expr
);
785 return expr_list
.get (0);
788 Expression
parse_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
789 expect (TokenType
.DOT
);
790 string id
= parse_identifier ();
791 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
792 var expr
= new
MemberAccess (inner
, id
, get_src (begin
));
793 if (type_arg_list
!= null) {
794 foreach (DataType type_arg
in type_arg_list
) {
795 expr
.add_type_argument (type_arg
);
801 Expression
parse_pointer_member_access (SourceLocation begin
, Expression inner
) throws ParseError
{
802 expect (TokenType
.OP_PTR
);
803 string id
= parse_identifier ();
804 List
<DataType
> type_arg_list
= parse_type_argument_list (true);
805 var expr
= new MemberAccess
.pointer (inner
, id
, get_src (begin
));
806 if (type_arg_list
!= null) {
807 foreach (DataType type_arg
in type_arg_list
) {
808 expr
.add_type_argument (type_arg
);
815 List
<Expression
> parse_print_argument_list () throws ParseError
{
816 var list
= new ArrayList
<Expression
> ();
818 var begin
= get_location ();
820 if (current () != TokenType
.CLOSE_PARENS
) {
822 var p_expr
= parse_expression ();
826 if (p_expr
!= null) {
829 if (p_expr is StringLiteral
) {
830 var s_exp
= (StringLiteral
) p_expr
;
831 var len
= s_exp
.value
.length
;
835 var st
= s_exp
.value
.substring (0, len
-1);
840 string s
= "\"\\n\"";
841 var rhs
= new
StringLiteral (s
, get_src (begin
));
842 p_expr
= new
BinaryExpression (BinaryOperator
.PLUS
, p_expr
, rhs
, get_src (begin
));
849 } while (accept (TokenType
.COMMA
));
854 Expression
parse_print_expression () throws ParseError
{
855 var begin
= get_location ();
857 expect (TokenType
.PRINT
);
858 bool parens
= accept (TokenType
.OPEN_PARENS
);
860 var expr
= new
MemberAccess (null, "print", get_src (begin
));
862 var arg_list
= parse_print_argument_list ();
865 expect (TokenType
.CLOSE_PARENS
);
868 var print_expr
= new
MethodCall (expr
, get_src (begin
));
870 foreach (Expression arg
in arg_list
) {
871 print_expr
.add_argument (arg
);
878 Expression
parse_assert_expression () throws ParseError
{
879 var begin
= get_location ();
881 expect (TokenType
.ASSERT
);
882 bool parens
= accept (TokenType
.OPEN_PARENS
);
884 var expr
= new
MemberAccess (null, "assert", get_src (begin
));
886 var arg_list
= parse_argument_list ();
889 expect (TokenType
.CLOSE_PARENS
);
892 var assert_expr
= new
MethodCall (expr
, get_src (begin
));
894 foreach (Expression arg
in arg_list
) {
895 assert_expr
.add_argument (arg
);
902 Expression
parse_method_call (SourceLocation begin
, Expression inner
) throws ParseError
{
903 expect (TokenType
.OPEN_PARENS
);
904 var arg_list
= parse_argument_list ();
905 expect (TokenType
.CLOSE_PARENS
);
906 var init_list
= parse_object_initializer ();
908 if (init_list
.size
> 0 && inner is MemberAccess
) {
909 // struct creation expression
910 var member
= (MemberAccess
) inner
;
911 member
.creation_member
= true;
913 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
914 expr
.struct_creation
= true;
915 foreach (Expression arg
in arg_list
) {
916 expr
.add_argument (arg
);
918 foreach (MemberInitializer initializer
in init_list
) {
919 expr
.add_member_initializer (initializer
);
923 var expr
= new
MethodCall (inner
, get_src (begin
));
924 foreach (Expression arg
in arg_list
) {
925 expr
.add_argument (arg
);
931 Expression
parse_element_access (SourceLocation begin
, Expression inner
) throws ParseError
{
932 expect (TokenType
.OPEN_BRACKET
);
933 var index_list
= parse_expression_list ();
934 Expression? stop
= null;
935 if (index_list
.size
== 1 && accept (TokenType
.COLON
)) {
937 stop
= parse_expression ();
939 expect (TokenType
.CLOSE_BRACKET
);
942 var expr
= new
ElementAccess (inner
, get_src (begin
));
943 foreach (Expression index
in index_list
) {
944 expr
.append_index (index
);
948 return new
SliceExpression (inner
, index_list
[0], stop
, get_src (begin
));
952 List
<Expression
> parse_expression_list () throws ParseError
{
953 var list
= new ArrayList
<Expression
> ();
955 list
.add (parse_expression ());
956 } while (accept (TokenType
.COMMA
));
960 Expression
parse_this_access () throws ParseError
{
961 var begin
= get_location ();
962 expect (TokenType
.THIS
);
963 return new
MemberAccess (null, "this", get_src (begin
));
966 Expression
parse_base_access () throws ParseError
{
967 var begin
= get_location ();
968 expect (TokenType
.SUPER
);
969 return new
BaseAccess (get_src (begin
));
972 Expression
parse_post_increment_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
973 expect (TokenType
.OP_INC
);
974 return new
PostfixExpression (inner
, true, get_src (begin
));
977 Expression
parse_post_decrement_expression (SourceLocation begin
, Expression inner
) throws ParseError
{
978 expect (TokenType
.OP_DEC
);
979 return new
PostfixExpression (inner
, false, get_src (begin
));
982 Expression
parse_object_or_array_creation_expression () throws ParseError
{
983 var begin
= get_location ();
984 expect (TokenType
.NEW
);
986 if (accept (TokenType
.ARRAY
)) {
987 expect (TokenType
.OF
);
988 var mtype
= parse_type ();
989 var expr
= parse_array_creation_expression (begin
, mtype
);
993 if (accept (TokenType
.LIST
)) {
994 expect (TokenType
.OF
);
995 var mtype
= parse_type ();
996 var expr
= parse_list_creation_expression (begin
, mtype
);
1000 if (accept (TokenType
.DICT
)) {
1001 expect (TokenType
.OF
);
1002 var mtype1
= parse_type ();
1003 expect (TokenType
.COMMA
);
1004 var mtype2
= parse_type ();
1005 var expr
= parse_dict_creation_expression (begin
, mtype1
, mtype2
);
1010 var member
= parse_member_name ();
1011 var expr
= parse_object_creation_expression (begin
, member
);
1016 Expression
parse_object_creation_expression (SourceLocation begin
, MemberAccess member
) throws ParseError
{
1017 member
.creation_member
= true;
1018 List
<Expression
> arg_list
;
1019 if (accept (TokenType
.OPEN_PARENS
)) {
1020 arg_list
= parse_argument_list ();
1021 expect (TokenType
.CLOSE_PARENS
);
1023 arg_list
= new ArrayList
<Expression
> ();
1026 var init_list
= parse_object_initializer ();
1028 var expr
= new
ObjectCreationExpression (member
, get_src (begin
));
1029 foreach (Expression arg
in arg_list
) {
1030 expr
.add_argument (arg
);
1032 foreach (MemberInitializer initializer
in init_list
) {
1033 expr
.add_member_initializer (initializer
);
1038 Expression
parse_array_creation_expression (SourceLocation begin
, DataType element_type
) throws ParseError
{
1039 bool size_specified
= false;
1040 List
<Expression
> size_specifier_list
= null;
1042 DataType etype
= element_type
.copy ();
1044 var has_bracket
= accept (TokenType
.OPEN_BRACKET
);
1048 // array of arrays: new T[][42]
1050 if (size_specified
) {
1051 throw new ParseError
.SYNTAX (get_error ("size of inner arrays must not be specified in array creation expression"));
1054 etype
= new
ArrayType (etype
, size_specifier_list
.size
, etype
.source_reference
);
1059 size_specifier_list
= new ArrayList
<Expression
> ();
1061 Expression size
= null;
1062 if (has_bracket
&& current () != TokenType
.CLOSE_BRACKET
&& current () != TokenType
.COMMA
) {
1063 size
= parse_expression ();
1064 size_specified
= true;
1066 size_specifier_list
.add (size
);
1067 } while (accept (TokenType
.COMMA
));
1070 expect (TokenType
.CLOSE_BRACKET
);
1072 } while (accept (TokenType
.OPEN_BRACKET
));
1074 InitializerList initializer
= null;
1075 if (accept (TokenType
.ASSIGN
)) {
1076 initializer
= parse_initializer ();
1079 var expr
= new
ArrayCreationExpression (etype
, size_specifier_list
.size
, initializer
, get_src (begin
));
1080 if (size_specified
) {
1081 foreach (Expression size
in size_specifier_list
) {
1082 expr
.append_size (size
);
1089 Expression
parse_list_creation_expression (SourceLocation begin
, DataType element_type
) throws ParseError
{
1091 MemberAccess list_member
= null, parent_member
= null;
1093 parent_member
= new
MemberAccess (null, "Gee", get_src (begin
));
1094 list_member
= new
MemberAccess (parent_member
, "ArrayList", get_src (begin
));
1095 list_member
.add_type_argument (element_type
);
1097 list_member
.creation_member
= true;
1099 var expr
= new
ObjectCreationExpression (list_member
, get_src (begin
));
1103 Expression
parse_dict_creation_expression (SourceLocation begin
, DataType key_type
, DataType value_type
) throws ParseError
{
1105 MemberAccess dict_member
= null, parent_member
= null;
1107 parent_member
= new
MemberAccess (null, "Gee", get_src (begin
));
1108 dict_member
= new
MemberAccess (parent_member
, "HashMap", get_src (begin
));
1109 dict_member
.add_type_argument (key_type
);
1110 dict_member
.add_type_argument (value_type
);
1112 dict_member
.creation_member
= true;
1114 var expr
= new
ObjectCreationExpression (dict_member
, get_src (begin
));
1120 List
<MemberInitializer
> parse_object_initializer () throws ParseError
{
1121 var list
= new ArrayList
<MemberInitializer
> ();
1122 if (accept (TokenType
.OPEN_BRACE
)) {
1124 list
.add (parse_member_initializer ());
1125 } while (accept (TokenType
.COMMA
));
1126 expect (TokenType
.CLOSE_BRACE
);
1131 MemberInitializer
parse_member_initializer () throws ParseError
{
1132 var begin
= get_location ();
1133 string id
= parse_identifier ();
1134 expect (TokenType
.ASSIGN
);
1135 var expr
= parse_expression ();
1137 return new
MemberInitializer (id
, expr
, get_src (begin
));
1140 Expression
parse_yield_expression () throws ParseError
{
1141 var begin
= get_location ();
1142 expect (TokenType
.YIELD
);
1143 Expression base_expr
= null;
1144 if (current () == TokenType
.SUPER
) {
1145 base_expr
= parse_base_access ();
1146 expect (TokenType
.DOT
);
1148 var member
= parse_member_name (base_expr
);
1149 var call
= (MethodCall
) parse_method_call (begin
, member
);
1150 call
.is_yield_expression
= true;
1154 Expression
parse_sizeof_expression () throws ParseError
{
1155 var begin
= get_location ();
1156 expect (TokenType
.SIZEOF
);
1157 expect (TokenType
.OPEN_PARENS
);
1158 var type
= parse_type ();
1159 expect (TokenType
.CLOSE_PARENS
);
1161 return new
SizeofExpression (type
, get_src (begin
));
1164 Expression
parse_typeof_expression () throws ParseError
{
1165 var begin
= get_location ();
1166 expect (TokenType
.TYPEOF
);
1167 expect (TokenType
.OPEN_PARENS
);
1168 var type
= parse_type ();
1169 expect (TokenType
.CLOSE_PARENS
);
1171 return new
TypeofExpression (type
, get_src (begin
));
1174 UnaryOperator
get_unary_operator (TokenType token_type
) {
1175 switch (token_type
) {
1176 case TokenType
.PLUS
: return UnaryOperator
.PLUS
;
1177 case TokenType
.MINUS
: return UnaryOperator
.MINUS
;
1178 case TokenType
.OP_NEG
: return UnaryOperator
.LOGICAL_NEGATION
;
1179 case TokenType
.TILDE
: return UnaryOperator
.BITWISE_COMPLEMENT
;
1180 case TokenType
.OP_INC
: return UnaryOperator
.INCREMENT
;
1181 case TokenType
.OP_DEC
: return UnaryOperator
.DECREMENT
;
1182 default: return UnaryOperator
.NONE
;
1186 Expression
parse_unary_expression () throws ParseError
{
1187 var begin
= get_location ();
1188 var operator
= get_unary_operator (current ());
1189 if (operator
!= UnaryOperator
.NONE
) {
1191 var op
= parse_unary_expression ();
1192 return new
UnaryExpression (operator
, op
, get_src (begin
));
1194 switch (current ()) {
1195 case TokenType
.HASH
:
1197 var op
= parse_unary_expression ();
1198 return new
ReferenceTransferExpression (op
, get_src (begin
));
1199 case TokenType
.OPEN_PARENS
:
1201 switch (current ()) {
1202 case TokenType
.OWNED
:
1205 if (accept (TokenType
.CLOSE_PARENS
)) {
1206 var op
= parse_unary_expression ();
1207 return new
ReferenceTransferExpression (op
, get_src (begin
));
1210 case TokenType
.VOID
:
1211 case TokenType
.DYNAMIC
:
1212 case TokenType
.IDENTIFIER
:
1213 case TokenType
.ARRAY
:
1214 case TokenType
.LIST
:
1215 case TokenType
.DICT
:
1216 var type
= parse_type ();
1217 if (accept (TokenType
.CLOSE_PARENS
)) {
1218 // check follower to decide whether to create cast expression
1219 switch (current ()) {
1220 case TokenType
.OP_NEG
:
1221 case TokenType
.TILDE
:
1222 case TokenType
.OPEN_PARENS
:
1223 case TokenType
.TRUE
:
1224 case TokenType
.FALSE
:
1225 case TokenType
.INTEGER_LITERAL
:
1226 case TokenType
.REAL_LITERAL
:
1227 case TokenType
.CHARACTER_LITERAL
:
1228 case TokenType
.REGEX_LITERAL
:
1229 case TokenType
.STRING_LITERAL
:
1230 case TokenType
.TEMPLATE_STRING_LITERAL
:
1231 case TokenType
.VERBATIM_STRING_LITERAL
:
1232 case TokenType
.NULL
:
1233 case TokenType
.THIS
:
1234 case TokenType
.SUPER
:
1236 case TokenType
.SIZEOF
:
1237 case TokenType
.TYPEOF
:
1238 case TokenType
.IDENTIFIER
:
1239 case TokenType
.PARAMS
:
1240 var inner
= parse_unary_expression ();
1241 return new
CastExpression (inner
, type
, get_src (begin
), false);
1247 case TokenType
.OP_NEG
:
1249 if (accept (TokenType
.CLOSE_PARENS
)) {
1250 // (!) non-null cast
1251 var inner
= parse_unary_expression ();
1252 return new CastExpression
.non_null (inner
, get_src (begin
));
1259 // no cast expression
1262 case TokenType
.STAR
:
1264 var op
= parse_unary_expression ();
1265 return new
PointerIndirection (op
, get_src (begin
));
1266 case TokenType
.BITWISE_AND
:
1268 var op
= parse_unary_expression ();
1269 return new
AddressofExpression (op
, get_src (begin
));
1274 var expr
= parse_primary_expression ();
1278 BinaryOperator
get_binary_operator (TokenType token_type
) {
1279 switch (token_type
) {
1280 case TokenType
.STAR
: return BinaryOperator
.MUL
;
1281 case TokenType
.DIV
: return BinaryOperator
.DIV
;
1282 case TokenType
.PERCENT
: return BinaryOperator
.MOD
;
1283 case TokenType
.PLUS
: return BinaryOperator
.PLUS
;
1284 case TokenType
.MINUS
: return BinaryOperator
.MINUS
;
1285 case TokenType
.OP_LT
: return BinaryOperator
.LESS_THAN
;
1286 case TokenType
.OP_GT
: return BinaryOperator
.GREATER_THAN
;
1287 case TokenType
.OP_LE
: return BinaryOperator
.LESS_THAN_OR_EQUAL
;
1288 case TokenType
.OP_GE
: return BinaryOperator
.GREATER_THAN_OR_EQUAL
;
1289 case TokenType
.OP_EQ
: return BinaryOperator
.EQUALITY
;
1292 if (current () == TokenType
.OP_NEG
) {
1294 return BinaryOperator
.INEQUALITY
;
1297 return BinaryOperator
.EQUALITY
;
1298 case TokenType
.OP_NE
: return BinaryOperator
.INEQUALITY
;
1299 default: return BinaryOperator
.NONE
;
1303 Expression
parse_multiplicative_expression () throws ParseError
{
1304 var begin
= get_location ();
1305 var left
= parse_unary_expression ();
1308 var operator
= get_binary_operator (current ());
1310 case BinaryOperator
.MUL
:
1311 case BinaryOperator
.DIV
:
1312 case BinaryOperator
.MOD
:
1314 var right
= parse_unary_expression ();
1315 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1325 Expression
parse_additive_expression () throws ParseError
{
1326 var begin
= get_location ();
1327 var left
= parse_multiplicative_expression ();
1330 var operator
= get_binary_operator (current ());
1332 case BinaryOperator
.PLUS
:
1333 case BinaryOperator
.MINUS
:
1335 var right
= parse_multiplicative_expression ();
1336 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1346 Expression
parse_shift_expression () throws ParseError
{
1347 var begin
= get_location ();
1348 var left
= parse_additive_expression ();
1351 switch (current ()) {
1352 case TokenType
.OP_SHIFT_LEFT
:
1354 var right
= parse_additive_expression ();
1355 left
= new
BinaryExpression (BinaryOperator
.SHIFT_LEFT
, left
, right
, get_src (begin
));
1357 // don't use OP_SHIFT_RIGHT to support >> for nested generics
1358 case TokenType
.OP_GT
:
1359 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1361 // only accept >> when there is no space between the two > signs
1362 if (current () == TokenType
.OP_GT
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1364 var right
= parse_additive_expression ();
1365 left
= new
BinaryExpression (BinaryOperator
.SHIFT_RIGHT
, left
, right
, get_src (begin
));
1379 Expression
parse_relational_expression () throws ParseError
{
1380 var begin
= get_location ();
1381 var left
= parse_shift_expression ();
1384 var operator
= get_binary_operator (current ());
1386 case BinaryOperator
.LESS_THAN
:
1387 case BinaryOperator
.LESS_THAN_OR_EQUAL
:
1388 case BinaryOperator
.GREATER_THAN_OR_EQUAL
:
1390 var right
= parse_shift_expression ();
1391 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1393 case BinaryOperator
.GREATER_THAN
:
1395 // ignore >> and >>= (two tokens due to generics)
1396 if (current () != TokenType
.OP_GT
&& current () != TokenType
.OP_GE
) {
1397 var right
= parse_shift_expression ();
1398 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1405 switch (current ()) {
1408 var type
= parse_type ();
1409 left
= new
TypeCheck (left
, type
, get_src (begin
));
1413 var type
= parse_type ();
1414 left
= new
CastExpression (left
, type
, get_src (begin
), true);
1426 Expression
parse_equality_expression () throws ParseError
{
1427 var begin
= get_location ();
1428 var left
= parse_relational_expression ();
1431 var operator
= get_binary_operator (current ());
1433 case BinaryOperator
.INEQUALITY
:
1434 case BinaryOperator
.EQUALITY
:
1435 if ((operator
== BinaryOperator
.INEQUALITY
) && (current () == TokenType
.IS
)) {
1439 var right
= parse_relational_expression ();
1440 left
= new
BinaryExpression (operator
, left
, right
, get_src (begin
));
1450 Expression
parse_and_expression () throws ParseError
{
1451 var begin
= get_location ();
1452 var left
= parse_equality_expression ();
1453 while (accept (TokenType
.BITWISE_AND
)) {
1454 var right
= parse_equality_expression ();
1455 left
= new
BinaryExpression (BinaryOperator
.BITWISE_AND
, left
, right
, get_src (begin
));
1460 Expression
parse_exclusive_or_expression () throws ParseError
{
1461 var begin
= get_location ();
1462 var left
= parse_and_expression ();
1463 while (accept (TokenType
.CARRET
)) {
1464 var right
= parse_and_expression ();
1465 left
= new
BinaryExpression (BinaryOperator
.BITWISE_XOR
, left
, right
, get_src (begin
));
1470 Expression
parse_inclusive_or_expression () throws ParseError
{
1471 var begin
= get_location ();
1472 var left
= parse_exclusive_or_expression ();
1473 while (accept (TokenType
.BITWISE_OR
)) {
1474 var right
= parse_exclusive_or_expression ();
1475 left
= new
BinaryExpression (BinaryOperator
.BITWISE_OR
, left
, right
, get_src (begin
));
1480 Expression
parse_in_expression () throws ParseError
{
1481 var begin
= get_location ();
1482 var left
= parse_inclusive_or_expression ();
1483 while (accept (TokenType
.IN
)) {
1484 var right
= parse_inclusive_or_expression ();
1485 left
= new
BinaryExpression (BinaryOperator
.IN
, left
, right
, get_src (begin
));
1490 Expression
parse_conditional_and_expression () throws ParseError
{
1491 var begin
= get_location ();
1492 var left
= parse_in_expression ();
1493 while (accept (TokenType
.OP_AND
)) {
1494 var right
= parse_in_expression ();
1495 left
= new
BinaryExpression (BinaryOperator
.AND
, left
, right
, get_src (begin
));
1500 Expression
parse_conditional_or_expression () throws ParseError
{
1501 var begin
= get_location ();
1502 var left
= parse_conditional_and_expression ();
1503 while (accept (TokenType
.OP_OR
)) {
1504 var right
= parse_conditional_and_expression ();
1505 left
= new
BinaryExpression (BinaryOperator
.OR
, left
, right
, get_src (begin
));
1510 Expression
parse_conditional_expression () throws ParseError
{
1511 var begin
= get_location ();
1512 var condition
= parse_conditional_or_expression ();
1513 if (accept (TokenType
.INTERR
)) {
1514 var true_expr
= parse_expression ();
1515 expect (TokenType
.COLON
);
1516 var false_expr
= parse_expression ();
1517 return new
ConditionalExpression (condition
, true_expr
, false_expr
, get_src (begin
));
1523 Expression
parse_lambda_expression () throws ParseError
{
1524 var begin
= get_location ();
1525 List
<string> params
= new ArrayList
<string> ();
1527 expect (TokenType
.DEF
);
1529 if (accept (TokenType
.OPEN_PARENS
)) {
1530 if (current () != TokenType
.CLOSE_PARENS
) {
1532 params
.add (parse_identifier ());
1533 } while (accept (TokenType
.COMMA
));
1535 expect (TokenType
.CLOSE_PARENS
);
1537 params
.add (parse_identifier ());
1541 LambdaExpression lambda
;
1542 if (accept_block ()) {
1543 var block
= parse_block ();
1544 lambda
= new LambdaExpression
.with_statement_body (block
, get_src (begin
));
1546 var expr
= parse_expression ();
1547 lambda
= new
LambdaExpression (expr
, get_src (begin
));
1548 expect_terminator ();
1553 foreach (string param
in params
) {
1554 lambda
.add_parameter (param
);
1559 AssignmentOperator
get_assignment_operator (TokenType token_type
) {
1560 switch (token_type
) {
1561 case TokenType
.ASSIGN
: return AssignmentOperator
.SIMPLE
;
1562 case TokenType
.ASSIGN_ADD
: return AssignmentOperator
.ADD
;
1563 case TokenType
.ASSIGN_SUB
: return AssignmentOperator
.SUB
;
1564 case TokenType
.ASSIGN_BITWISE_OR
: return AssignmentOperator
.BITWISE_OR
;
1565 case TokenType
.ASSIGN_BITWISE_AND
: return AssignmentOperator
.BITWISE_AND
;
1566 case TokenType
.ASSIGN_BITWISE_XOR
: return AssignmentOperator
.BITWISE_XOR
;
1567 case TokenType
.ASSIGN_DIV
: return AssignmentOperator
.DIV
;
1568 case TokenType
.ASSIGN_MUL
: return AssignmentOperator
.MUL
;
1569 case TokenType
.ASSIGN_PERCENT
: return AssignmentOperator
.PERCENT
;
1570 case TokenType
.ASSIGN_SHIFT_LEFT
: return AssignmentOperator
.SHIFT_LEFT
;
1571 default: return AssignmentOperator
.NONE
;
1575 Expression
parse_expression () throws ParseError
{
1576 if (current () == TokenType
.DEF
) {
1577 var lambda
= parse_lambda_expression ();
1578 current_expr_is_lambda
= true;
1582 var begin
= get_location ();
1583 Expression expr
= parse_conditional_expression ();
1586 var operator
= get_assignment_operator (current ());
1587 if (operator
!= AssignmentOperator
.NONE
) {
1589 var rhs
= parse_expression ();
1590 expr
= new
Assignment (expr
, rhs
, operator
, get_src (begin
));
1591 } else if (current () == TokenType
.OP_GT
) { // >>=
1592 char* first_gt_pos
= tokens
[index
].begin
.pos
;
1594 // only accept >>= when there is no space between the two > signs
1595 if (current () == TokenType
.OP_GE
&& tokens
[index
].begin
.pos
== first_gt_pos
+ 1) {
1597 var rhs
= parse_expression ();
1598 expr
= new
Assignment (expr
, rhs
, AssignmentOperator
.SHIFT_RIGHT
, get_src (begin
));
1612 Statement
get_for_statement_type () throws ParseError
{
1614 var begin
= get_location ();
1615 bool is_foreach
= false;
1617 while (current () != TokenType
.EOL
&& current () != TokenType
.DO
) {
1619 if (accept (TokenType
.IN
)) {
1628 return parse_foreach_statement ();
1630 return parse_for_statement ();
1635 void parse_statements (Block block
) throws ParseError
{
1636 while (current () != TokenType
.DEDENT
1637 && current () != TokenType
.WHEN
1638 && current () != TokenType
.DEFAULT
) {
1640 Statement stmt
= null;
1641 bool is_decl
= false;
1642 comment
= scanner
.pop_comment ();
1643 switch (current ()) {
1645 /* skip over requires and ensures as we handled them in method declaration */
1646 case TokenType
.REQUIRES
:
1647 case TokenType
.ENSURES
:
1648 var begin
= get_location ();
1651 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
1652 while (current () != TokenType
.DEDENT
) {
1656 expect (TokenType
.DEDENT
);
1658 while (current () != TokenType
.EOL
) {
1662 expect (TokenType
.EOL
);
1665 stmt
= new
EmptyStatement (get_src (begin
));
1669 case TokenType
.INDENT
:
1670 stmt
= parse_block ();
1672 case TokenType
.SEMICOLON
:
1673 case TokenType
.PASS
:
1674 stmt
= parse_empty_statement ();
1676 case TokenType
.PRINT
:
1677 case TokenType
.ASSERT
:
1678 stmt
= parse_expression_statement ();
1681 stmt
= parse_if_statement ();
1683 case TokenType
.CASE
:
1684 stmt
= parse_switch_statement ();
1686 case TokenType
.WHILE
:
1687 stmt
= parse_while_statement ();
1690 stmt
= parse_do_statement ();
1693 stmt
= get_for_statement_type ();
1695 case TokenType
.BREAK
:
1696 stmt
= parse_break_statement ();
1698 case TokenType
.CONTINUE
:
1699 stmt
= parse_continue_statement ();
1701 case TokenType
.RETURN
:
1702 stmt
= parse_return_statement ();
1704 case TokenType
.RAISE
:
1705 stmt
= parse_throw_statement ();
1708 stmt
= parse_try_statement ();
1710 case TokenType
.LOCK
:
1711 stmt
= parse_lock_statement ();
1713 case TokenType
.DELETE
:
1714 stmt
= parse_delete_statement ();
1718 parse_local_variable_declarations (block
);
1720 case TokenType
.YIELD
:
1721 stmt
= parse_yield_statement ();
1724 case TokenType
.OP_INC
:
1725 case TokenType
.OP_DEC
:
1726 case TokenType
.SUPER
:
1727 case TokenType
.THIS
:
1728 case TokenType
.OPEN_PARENS
:
1729 case TokenType
.STAR
:
1731 stmt
= parse_expression_statement ();
1734 bool is_expr
= is_expression ();
1736 stmt
= parse_expression_statement ();
1739 parse_local_variable_declarations (block
);
1745 block
.add_statement (stmt
);
1747 } catch (ParseError e
) {
1748 if (recover () != RecoveryState
.STATEMENT_BEGIN
) {
1749 // beginning of next declaration or end of file reached
1750 // return what we have so far
1757 bool is_expression () throws ParseError
{
1758 var begin
= get_location ();
1760 // decide between declaration and expression statement
1762 switch (current ()) {
1763 // invocation expression
1764 case TokenType
.OPEN_PARENS
:
1765 // postfix increment
1766 case TokenType
.OP_INC
:
1767 // postfix decrement
1768 case TokenType
.OP_DEC
:
1770 case TokenType
.ASSIGN
:
1771 case TokenType
.ASSIGN_ADD
:
1772 case TokenType
.ASSIGN_BITWISE_AND
:
1773 case TokenType
.ASSIGN_BITWISE_OR
:
1774 case TokenType
.ASSIGN_BITWISE_XOR
:
1775 case TokenType
.ASSIGN_DIV
:
1776 case TokenType
.ASSIGN_MUL
:
1777 case TokenType
.ASSIGN_PERCENT
:
1778 case TokenType
.ASSIGN_SHIFT_LEFT
:
1779 case TokenType
.ASSIGN_SUB
:
1780 case TokenType
.OP_GT
: // >>=
1783 // pointer member access
1784 case TokenType
.OP_PTR
:
1793 Block
parse_embedded_statement () throws ParseError
{
1794 if (current () == TokenType
.INDENT
) {
1795 var block
= parse_block ();
1799 comment
= scanner
.pop_comment ();
1801 var block
= new
Block (get_src (get_location ()));
1802 block
.add_statement (parse_embedded_statement_without_block ());
1807 Statement
parse_embedded_statement_without_block () throws ParseError
{
1808 switch (current ()) {
1809 case TokenType
.PASS
:
1810 case TokenType
.SEMICOLON
: return parse_empty_statement ();
1811 case TokenType
.IF
: return parse_if_statement ();
1812 case TokenType
.CASE
: return parse_switch_statement ();
1813 case TokenType
.WHILE
: return parse_while_statement ();
1814 case TokenType
.DO
: return parse_do_statement ();
1815 case TokenType
.FOR
: return get_for_statement_type ();
1816 case TokenType
.BREAK
: return parse_break_statement ();
1817 case TokenType
.CONTINUE
: return parse_continue_statement ();
1818 case TokenType
.RETURN
: return parse_return_statement ();
1819 case TokenType
.YIELD
: return parse_yield_statement ();
1820 case TokenType
.RAISE
: return parse_throw_statement ();
1821 case TokenType
.TRY
: return parse_try_statement ();
1822 case TokenType
.LOCK
: return parse_lock_statement ();
1823 case TokenType
.DELETE
: return parse_delete_statement ();
1824 default: return parse_expression_statement ();
1828 Block
parse_block () throws ParseError
{
1829 var begin
= get_location ();
1830 expect (TokenType
.INDENT
);
1831 var block
= new
Block (get_src (begin
));
1832 parse_statements (block
);
1833 if (!accept (TokenType
.DEDENT
)) {
1834 // only report error if it's not a secondary error
1835 if (context
.report
.get_errors () == 0) {
1836 Report
.error (get_current_src (), "tab indentation is incorrect");
1840 block
.source_reference
.last_line
= get_current_src ().last_line
;
1841 block
.source_reference
.last_column
= get_current_src ().last_column
;
1846 Statement
parse_empty_statement () throws ParseError
{
1847 var begin
= get_location ();
1849 accept (TokenType
.PASS
);
1850 accept (TokenType
.SEMICOLON
);
1851 expect_terminator ();
1853 return new
EmptyStatement (get_src (begin
));
1856 void add_local_var_variable (Block block
, string id
) throws ParseError
{
1857 DataType type_copy
= null;
1858 var local
= parse_local_variable (type_copy
, id
);
1859 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1862 void parse_local_variable_declarations (Block block
) throws ParseError
{
1863 if (accept (TokenType
.VAR
)) {
1864 /* support block vars */
1865 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
1866 while (current () != TokenType
.DEDENT
) {
1867 var s
= parse_identifier ();
1868 add_local_var_variable (block
, s
);
1869 accept (TokenType
.EOL
);
1870 accept (TokenType
.SEMICOLON
);
1873 expect (TokenType
.DEDENT
);
1875 var s
= parse_identifier ();
1876 add_local_var_variable (block
, s
);
1877 expect_terminator ();
1883 var id_list
= new ArrayList
<string> ();
1884 DataType variable_type
= null;
1887 id_list
.add (parse_identifier ());
1888 } while (accept (TokenType
.COMMA
));
1890 expect (TokenType
.COLON
);
1892 variable_type
= parse_type ();
1893 var type
= parse_inline_array_type (variable_type
);
1895 foreach (string id
in id_list
) {
1896 DataType type_copy
= null;
1898 type_copy
= type
.copy ();
1900 var local
= parse_local_variable (type_copy
, id
);
1901 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
1904 expect_terminator ();
1907 LocalVariable
parse_local_variable (DataType? variable_type
, string id
) throws ParseError
{
1908 var begin
= get_location ();
1909 Expression initializer
= null;
1910 if (accept (TokenType
.ASSIGN
)) {
1911 initializer
= parse_expression ();
1913 return new
LocalVariable (variable_type
, id
, initializer
, get_src (begin
));
1916 Statement
parse_expression_statement () throws ParseError
{
1917 var begin
= get_location ();
1918 var expr
= parse_statement_expression ();
1920 if (current_expr_is_lambda
) {
1921 current_expr_is_lambda
= false;
1923 expect_terminator ();
1926 return new
ExpressionStatement (expr
, get_src (begin
));
1929 Expression
parse_statement_expression () throws ParseError
{
1930 // invocation expression, assignment,
1931 // or pre/post increment/decrement expression
1932 var expr
= parse_expression ();
1936 Statement
parse_if_statement () throws ParseError
{
1937 var begin
= get_location ();
1939 expect (TokenType
.IF
);
1941 var condition
= parse_expression ();
1943 if (!accept (TokenType
.DO
)) {
1944 expect (TokenType
.EOL
);
1946 accept (TokenType
.EOL
);
1949 var src
= get_src (begin
);
1950 var true_stmt
= parse_embedded_statement ();
1951 Block false_stmt
= null;
1952 if (accept (TokenType
.ELSE
)) {
1953 // allow `else if' on the same line without `do'
1954 if (!accept (TokenType
.DO
) && current () != TokenType
.IF
) {
1955 expect (TokenType
.EOL
);
1957 accept (TokenType
.EOL
);
1960 false_stmt
= parse_embedded_statement ();
1962 return new
IfStatement (condition
, true_stmt
, false_stmt
, src
);
1965 Statement
parse_switch_statement () throws ParseError
{
1966 var begin
= get_location ();
1967 expect (TokenType
.CASE
);
1968 var condition
= parse_expression ();
1970 expect (TokenType
.EOL
);
1972 var stmt
= new
SwitchStatement (condition
, get_src (begin
));
1973 expect (TokenType
.INDENT
);
1974 while (current () != TokenType
.DEDENT
) {
1975 var section
= new
SwitchSection (get_src (begin
));
1977 if (accept (TokenType
.WHEN
)) {
1979 section
.add_label (new
SwitchLabel (parse_expression (), get_src (begin
)));
1981 while (accept (TokenType
.COMMA
));
1983 expect (TokenType
.DEFAULT
);
1984 section
.add_label (new SwitchLabel
.with_default (get_src (begin
)));
1987 if (!accept (TokenType
.EOL
)) {
1988 expect (TokenType
.DO
);
1991 parse_statements (section
);
1993 /* add break statement for each block */
1994 var break_stmt
= new
BreakStatement (get_src (begin
));
1995 section
.add_statement (break_stmt
);
1997 stmt
.add_section (section
);
1999 expect (TokenType
.DEDENT
);
2003 Statement
parse_while_statement () throws ParseError
{
2004 var begin
= get_location ();
2005 expect (TokenType
.WHILE
);
2006 var condition
= parse_expression ();
2008 if (!accept (TokenType
.DO
)) {
2009 expect (TokenType
.EOL
);
2011 accept (TokenType
.EOL
);
2014 var body
= parse_embedded_statement ();
2015 return new
WhileStatement (condition
, body
, get_src (begin
));
2018 Statement
parse_do_statement () throws ParseError
{
2019 var begin
= get_location ();
2020 expect (TokenType
.DO
);
2021 expect (TokenType
.EOL
);
2022 var body
= parse_embedded_statement ();
2023 expect (TokenType
.WHILE
);
2025 var condition
= parse_expression ();
2027 expect_terminator ();
2029 return new
DoStatement (body
, condition
, get_src (begin
));
2033 Statement
parse_for_statement () throws ParseError
{
2034 var begin
= get_location ();
2036 Expression initializer
= null;
2037 Expression condition
= null;
2038 Expression iterator
= null;
2042 expect (TokenType
.FOR
);
2044 switch (current ()) {
2050 bool local_is_expr
= is_expression ();
2051 is_expr
= local_is_expr
;
2056 var expr_begin
= get_location ();
2057 id
= parse_identifier ();
2058 rollback (expr_begin
);
2059 initializer
= parse_statement_expression ();
2061 block
= new
Block (get_src (begin
));
2062 DataType variable_type
;
2063 if (accept (TokenType
.VAR
)) {
2064 variable_type
= null;
2065 id
= parse_identifier ();
2067 id
= parse_identifier ();
2068 expect (TokenType
.COLON
);
2069 variable_type
= parse_type ();
2072 DataType type_copy
= null;
2073 if (variable_type
!= null) {
2074 type_copy
= variable_type
.copy ();
2076 var local
= parse_local_variable (type_copy
, id
);
2078 block
.add_statement (new
DeclarationStatement (local
, local
.source_reference
));
2083 if (accept (TokenType
.TO
)) {
2084 /* create expression for condition and incrementing iterator */
2085 var to_begin
= get_location ();
2086 var to_src
= get_src (to_begin
);
2087 var left
= new
MemberAccess (null, id
, to_src
);
2088 var right
= parse_primary_expression ();
2090 condition
= new
BinaryExpression (BinaryOperator
.LESS_THAN_OR_EQUAL
, left
, right
, to_src
);
2092 iterator
= new
PostfixExpression (left
, true, to_src
);
2094 expect (TokenType
.DOWNTO
);
2095 var downto_begin
= get_location ();
2096 var downto_src
= get_src (downto_begin
);
2097 /* create expression for condition and decrementing iterator */
2098 var left
= new
MemberAccess (null, id
, downto_src
);
2099 var right
= parse_primary_expression ();
2101 condition
= new
BinaryExpression (BinaryOperator
.GREATER_THAN_OR_EQUAL
, left
, right
, downto_src
);
2103 iterator
= new
PostfixExpression (left
, false, downto_src
);
2106 if (!accept (TokenType
.EOL
)) {
2107 expect (TokenType
.DO
);
2110 var src
= get_src (begin
);
2111 var body
= parse_embedded_statement ();
2112 var stmt
= new
ForStatement (condition
, body
, src
);
2114 if (initializer
!= null) stmt
.add_initializer (initializer
);
2116 stmt
.add_iterator (iterator
);
2119 if (block
!= null) {
2120 block
.add_statement (stmt
);
2127 Statement
parse_foreach_statement () throws ParseError
{
2128 var begin
= get_location ();
2129 DataType type
= null;
2132 expect (TokenType
.FOR
);
2134 if (accept (TokenType
.VAR
)) {
2135 id
= parse_identifier ();
2137 id
= parse_identifier ();
2138 if (accept (TokenType
.COLON
)) {
2139 type
= parse_type ();
2143 expect (TokenType
.IN
);
2144 var collection
= parse_expression ();
2145 if (!accept (TokenType
.EOL
)) {
2146 expect (TokenType
.DO
);
2148 var src
= get_src (begin
);
2149 var body
= parse_embedded_statement ();
2150 return new
ForeachStatement (type
, id
, collection
, body
, src
);
2153 Statement
parse_break_statement () throws ParseError
{
2154 var begin
= get_location ();
2155 expect (TokenType
.BREAK
);
2156 expect_terminator ();
2157 return new
BreakStatement (get_src (begin
));
2160 Statement
parse_continue_statement () throws ParseError
{
2161 var begin
= get_location ();
2162 expect (TokenType
.CONTINUE
);
2163 expect_terminator ();
2164 return new
ContinueStatement (get_src (begin
));
2167 Statement
parse_return_statement () throws ParseError
{
2168 var begin
= get_location ();
2169 expect (TokenType
.RETURN
);
2170 Expression expr
= null;
2171 if (current () != TokenType
.SEMICOLON
&& current () != TokenType
.EOL
) {
2172 expr
= parse_expression ();
2174 expect_terminator ();
2175 return new
ReturnStatement (expr
, get_src (begin
));
2178 Statement
parse_yield_statement () throws ParseError
{
2179 var begin
= get_location ();
2180 expect (TokenType
.YIELD
);
2181 if (current () != TokenType
.SEMICOLON
&& current () != TokenType
.EOL
&& current () != TokenType
.RETURN
) {
2183 return parse_expression_statement ();
2185 Expression expr
= null;
2186 if (accept (TokenType
.RETURN
)) {
2187 expr
= parse_expression ();
2189 expect_terminator ();
2190 return new
YieldStatement (expr
, get_src (begin
));
2193 Statement
parse_throw_statement () throws ParseError
{
2194 var begin
= get_location ();
2195 expect (TokenType
.RAISE
);
2196 var expr
= parse_expression ();
2197 expect_terminator ();
2198 return new
ThrowStatement (expr
, get_src (begin
));
2201 Statement
parse_try_statement () throws ParseError
{
2202 var begin
= get_location ();
2203 expect (TokenType
.TRY
);
2204 expect (TokenType
.EOL
);
2205 var try_block
= parse_block ();
2206 Block finally_clause
= null;
2207 var catch_clauses
= new ArrayList
<CatchClause
> ();
2208 if (current () == TokenType
.EXCEPT
) {
2209 parse_catch_clauses (catch_clauses
);
2210 if (current () == TokenType
.FINALLY
) {
2211 finally_clause
= parse_finally_clause ();
2214 finally_clause
= parse_finally_clause ();
2216 var stmt
= new
TryStatement (try_block
, finally_clause
, get_src (begin
));
2217 foreach (CatchClause clause
in catch_clauses
) {
2218 stmt
.add_catch_clause (clause
);
2223 void parse_catch_clauses (List
<CatchClause
> catch_clauses
) throws ParseError
{
2224 while (accept (TokenType
.EXCEPT
)) {
2225 var begin
= get_location ();
2226 DataType type
= null;
2228 if (!accept (TokenType
.EOL
)) {
2229 id
= parse_identifier ();
2230 expect (TokenType
.COLON
);
2231 type
= parse_type ();
2232 expect (TokenType
.EOL
);
2235 var block
= parse_block ();
2236 catch_clauses
.add (new
CatchClause (type
, id
, block
, get_src (begin
)));
2240 Block
parse_finally_clause () throws ParseError
{
2241 expect (TokenType
.FINALLY
);
2243 var block
= parse_block ();
2247 Statement
parse_lock_statement () throws ParseError
{
2248 var begin
= get_location ();
2249 expect (TokenType
.LOCK
);
2250 expect (TokenType
.OPEN_PARENS
);
2251 var expr
= parse_expression ();
2252 expect (TokenType
.CLOSE_PARENS
);
2253 var stmt
= parse_embedded_statement ();
2254 return new
LockStatement (expr
, stmt
, get_src (begin
));
2257 Statement
parse_delete_statement () throws ParseError
{
2258 var begin
= get_location ();
2259 expect (TokenType
.DELETE
);
2260 var expr
= parse_expression ();
2261 expect_terminator ();
2262 return new
DeleteStatement (expr
, get_src (begin
));
2265 string parse_attribute_value () throws ParseError
{
2266 switch (current ()) {
2267 case TokenType
.NULL
:
2268 case TokenType
.TRUE
:
2269 case TokenType
.FALSE
:
2270 case TokenType
.INTEGER_LITERAL
:
2271 case TokenType
.REAL_LITERAL
:
2272 case TokenType
.STRING_LITERAL
:
2274 return get_last_string ();
2275 case TokenType
.MINUS
:
2277 switch (current ()) {
2278 case TokenType
.INTEGER_LITERAL
:
2279 case TokenType
.REAL_LITERAL
:
2281 return "-" + get_last_string ();
2283 throw new ParseError
.SYNTAX (get_error ("expected number"));
2286 throw new ParseError
.SYNTAX (get_error ("expected literal"));
2290 List
<Attribute
>?
parse_attributes (bool parameter
) throws ParseError
{
2291 if (current () != TokenType
.OPEN_BRACKET
) {
2294 var attrs
= new ArrayList
<Attribute
> ();
2295 while (accept (TokenType
.OPEN_BRACKET
)) {
2297 var begin
= get_location ();
2298 string id
= parse_identifier ();
2299 var attr
= new
Attribute (id
, get_src (begin
));
2300 if (accept (TokenType
.OPEN_PARENS
)) {
2301 if (current () != TokenType
.CLOSE_PARENS
) {
2303 id
= parse_identifier ();
2304 expect (TokenType
.ASSIGN
);
2305 attr
.add_argument (id
, parse_attribute_value ());
2306 } while (accept (TokenType
.COMMA
));
2308 expect (TokenType
.CLOSE_PARENS
);
2311 } while (accept (TokenType
.COMMA
));
2312 expect (TokenType
.CLOSE_BRACKET
);
2315 expect (TokenType
.EOL
);
2319 void set_attributes (CodeNode node
, List
<Attribute
>? attributes
) {
2320 if (attributes
!= null) {
2321 foreach (Attribute attr
in (List
<Attribute
>) attributes
) {
2322 node
.attributes
.append (attr
);
2327 Symbol
parse_declaration (bool is_root
= false) throws ParseError
{
2328 comment
= scanner
.pop_comment ();
2329 var attrs
= parse_attributes (false);
2330 var begin
= get_location ();
2332 switch (current ()) {
2333 case TokenType
.CONST
:
2334 return parse_constant_declaration (attrs
);
2335 case TokenType
.CONSTRUCT
:
2336 return parse_creation_method_declaration (attrs
);
2337 case TokenType
.CLASS
:
2338 return parse_class_declaration (attrs
);
2339 case TokenType
.INIT
:
2341 return parse_main_method_declaration (attrs
);
2343 if (context
.profile
== Profile
.GOBJECT
) {
2345 return parse_constructor_declaration (attrs
);
2348 case TokenType
.DELEGATE
:
2349 return parse_delegate_declaration (attrs
);
2351 return parse_method_declaration (attrs
);
2352 case TokenType
.ENUM
:
2353 return parse_enum_declaration (attrs
);
2354 case TokenType
.ERRORDOMAIN
:
2355 return parse_errordomain_declaration (attrs
);
2356 case TokenType
.FINAL
:
2357 return parse_destructor_declaration (attrs
);
2358 case TokenType
.INTERFACE
:
2359 return parse_interface_declaration (attrs
);
2360 case TokenType
.NAMESPACE
:
2361 return parse_namespace_declaration (attrs
);
2362 case TokenType
.PROP
:
2363 return parse_property_declaration (attrs
);
2364 case TokenType
.EVENT
:
2365 return parse_signal_declaration (attrs
);
2366 case TokenType
.STRUCT
:
2367 return parse_struct_declaration (attrs
);
2370 while (current () != TokenType
.EOL
&& current () != TokenType
.SEMICOLON
&& current () != TokenType
.EOF
) {
2371 if (current () == TokenType
.COLON
) {
2373 return parse_field_declaration (attrs
);
2383 TokenType cur
= current ();
2384 TokenType pre
= tokens
[index
-1].type
;
2386 throw new ParseError
.SYNTAX (get_error ("expected declaration but got %s with previous %s".printf (cur
.to_string (), pre
.to_string())));
2389 void parse_declarations (Symbol parent
, bool root
= false) throws ParseError
{
2391 expect (TokenType
.INDENT
);
2393 while (current () != TokenType
.DEDENT
&& current () != TokenType
.EOF
) {
2395 if (parent is Namespace
) {
2396 parse_namespace_member ((Namespace
) parent
);
2397 } else if (parent is Class
) {
2398 parse_class_member ((Class
) parent
);
2399 } else if (parent is Struct
) {
2400 parse_struct_member ((Struct
) parent
);
2401 } else if (parent is Interface
) {
2402 parse_interface_member ((Interface
) parent
);
2404 } catch (ParseError e
) {
2408 if (r
== RecoveryState
.STATEMENT_BEGIN
) {
2414 if (r
== RecoveryState
.EOF
) {
2420 if (!accept (TokenType
.DEDENT
)) {
2421 // only report error if it's not a secondary error
2422 if (context
.report
.get_errors () == 0) {
2423 Report
.error (get_current_src (), "expected dedent");
2429 enum RecoveryState
{
2435 RecoveryState
recover () {
2436 while (current () != TokenType
.EOF
) {
2437 switch (current ()) {
2438 case TokenType
.CLASS
:
2439 case TokenType
.CONST
:
2440 case TokenType
.CONSTRUCT
:
2441 case TokenType
.INIT
:
2443 case TokenType
.DELEGATE
:
2444 case TokenType
.ENUM
:
2445 case TokenType
.ERRORDOMAIN
:
2446 case TokenType
.FINAL
:
2447 case TokenType
.INTERFACE
:
2448 case TokenType
.NAMESPACE
:
2449 case TokenType
.PROP
:
2450 case TokenType
.EVENT
:
2451 case TokenType
.STRUCT
:
2452 return RecoveryState
.DECLARATION_BEGIN
;
2453 case TokenType
.BREAK
:
2454 case TokenType
.CASE
:
2455 case TokenType
.CONTINUE
:
2456 case TokenType
.DELETE
:
2460 case TokenType
.LOCK
:
2461 case TokenType
.RETURN
:
2462 case TokenType
.RAISE
:
2465 case TokenType
.WHILE
:
2466 case TokenType
.YIELD
:
2467 return RecoveryState
.STATEMENT_BEGIN
;
2473 return RecoveryState
.EOF
;
2476 Namespace
parse_namespace_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2477 var begin
= get_location ();
2478 expect (TokenType
.NAMESPACE
);
2479 var sym
= parse_symbol_name ();
2480 var ns
= new
Namespace (sym
.name
, get_src (begin
));
2481 if (comment
!= null) {
2482 ns
.add_comment (comment
);
2485 set_attributes (ns
, attrs
);
2486 expect (TokenType
.EOL
);
2487 parse_declarations (ns
);
2489 Namespace result
= ns
;
2490 while (sym
.inner
!= null) {
2492 ns
= new
Namespace (sym
.name
, result
.source_reference
);
2493 ns
.add_namespace ((Namespace
) result
);
2499 void parse_namespace_member (Namespace ns
) throws ParseError
{
2501 var sym
= parse_declaration ((ns
== context
.root
));
2502 if (sym is Namespace
) {
2503 ns
.add_namespace ((Namespace
) sym
);
2504 } else if (sym is Class
) {
2505 ns
.add_class ((Class
) sym
);
2506 } else if (sym is Interface
) {
2507 ns
.add_interface ((Interface
) sym
);
2508 } else if (sym is Struct
) {
2509 ns
.add_struct ((Struct
) sym
);
2510 } else if (sym is Enum
) {
2511 ns
.add_enum ((Enum
) sym
);
2512 } else if (sym is ErrorDomain
) {
2513 ns
.add_error_domain ((ErrorDomain
) sym
);
2514 } else if (sym is Delegate
) {
2515 ns
.add_delegate ((Delegate
) sym
);
2516 } else if (sym is Method
) {
2517 var method
= (Method
) sym
;
2518 if (method
.binding
== MemberBinding
.INSTANCE
) {
2519 method
.binding
= MemberBinding
.STATIC
;
2521 ns
.add_method (method
);
2522 } else if (sym is Field
) {
2523 var field
= (Field
) sym
;
2524 if (field
.binding
== MemberBinding
.INSTANCE
) {
2525 field
.binding
= MemberBinding
.STATIC
;
2527 ns
.add_field (field
);
2528 } else if (sym is Constant
) {
2529 ns
.add_constant ((Constant
) sym
);
2531 Report
.error (sym
.source_reference
, "unexpected declaration in namespace");
2536 void add_uses_clause (Namespace ns
) throws ParseError
{
2537 var begin
= get_location ();
2538 var sym
= parse_symbol_name ();
2539 var ns_ref
= new
UsingDirective (sym
, get_src (begin
));
2541 scanner
.source_file
.add_using_directive (ns_ref
);
2542 ns
.add_using_directive (ns_ref
);
2545 void parse_using_directives (Namespace ns
) throws ParseError
{
2546 while (accept (TokenType
.USES
)) {
2547 if (accept_block ()) {
2548 expect (TokenType
.INDENT
);
2550 while (current () != TokenType
.DEDENT
&& current () != TokenType
.EOF
) {
2551 add_uses_clause (ns
);
2552 expect (TokenType
.EOL
);
2555 expect (TokenType
.DEDENT
);
2558 add_uses_clause (ns
);
2559 } while (accept (TokenType
.COMMA
));
2561 expect_terminator ();
2567 Symbol
parse_class_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2568 var begin
= get_location ();
2569 expect (TokenType
.CLASS
);
2571 var flags
= parse_type_declaration_modifiers ();
2573 var sym
= parse_symbol_name ();
2574 var type_param_list
= parse_type_parameter_list ();
2575 var base_types
= new ArrayList
<DataType
> ();
2576 if (accept (TokenType
.COLON
)) {
2577 var type1
= parse_type ();
2578 base_types
.add (type1
);
2580 if (accept (TokenType
.IMPLEMENTS
)) {
2582 var type2
= parse_type ();
2583 base_types
.add (type2
);
2584 } while (accept (TokenType
.COMMA
));
2588 accept (TokenType
.EOL
);
2590 var cl
= new
Class (sym
.name
, get_src (begin
), comment
);
2592 if (ModifierFlags
.PRIVATE
in flags
) {
2593 cl
.access
= SymbolAccessibility
.PRIVATE
;
2595 /* class must always be Public unless its name starts wtih underscore */
2596 if (sym
.name
[0] == '_') {
2597 cl
.access
= SymbolAccessibility
.PRIVATE
;
2599 cl
.access
= SymbolAccessibility
.PUBLIC
;
2603 if (ModifierFlags
.ABSTRACT
in flags
) {
2604 cl
.is_abstract
= true;
2606 set_attributes (cl
, attrs
);
2607 foreach (TypeParameter type_param
in type_param_list
) {
2608 cl
.add_type_parameter (type_param
);
2610 foreach (DataType base_type
in base_types
) {
2611 cl
.add_base_type (base_type
);
2614 class_name
= cl
.name
;
2616 parse_declarations (cl
);
2618 // ensure there is always a default construction method
2619 if (scanner
.source_file
.file_type
== SourceFileType
.SOURCE
2620 && cl
.default_construction_method
== null) {
2621 var m
= new
CreationMethod (cl
.name
, null, cl
.source_reference
);
2622 m
.access
= SymbolAccessibility
.PUBLIC
;
2623 m
.body
= new
Block (cl
.source_reference
);
2628 while (sym
.inner
!= null) {
2630 var ns
= new
Namespace (sym
.name
, cl
.source_reference
);
2631 if (result is Namespace
) {
2632 ns
.add_namespace ((Namespace
) result
);
2634 ns
.add_class ((Class
) result
);
2641 void parse_class_member (Class cl
) throws ParseError
{
2642 var sym
= parse_declaration ();
2644 cl
.add_class ((Class
) sym
);
2645 } else if (sym is Struct
) {
2646 cl
.add_struct ((Struct
) sym
);
2647 } else if (sym is Enum
) {
2648 cl
.add_enum ((Enum
) sym
);
2649 } else if (sym is Delegate
) {
2650 cl
.add_delegate ((Delegate
) sym
);
2651 } else if (sym is Method
) {
2652 cl
.add_method ((Method
) sym
);
2653 } else if (sym is Vala
.Signal
) {
2654 cl
.add_signal ((Vala
.Signal
) sym
);
2655 } else if (sym is Field
) {
2656 cl
.add_field ((Field
) sym
);
2657 } else if (sym is Constant
) {
2658 cl
.add_constant ((Constant
) sym
);
2659 } else if (sym is Property
) {
2660 cl
.add_property ((Property
) sym
);
2661 } else if (sym is Constructor
) {
2662 var c
= (Constructor
) sym
;
2663 if (c
.binding
== MemberBinding
.INSTANCE
) {
2664 if (cl
.constructor
!= null) {
2665 Report
.error (c
.source_reference
, "class already contains a constructor");
2668 } else if (c
.binding
== MemberBinding
.CLASS
) {
2669 if (cl
.class_constructor
!= null) {
2670 Report
.error (c
.source_reference
, "class already contains a class constructor");
2672 cl
.class_constructor
= c
;
2674 if (cl
.static_constructor
!= null) {
2675 Report
.error (c
.source_reference
, "class already contains a static constructor");
2677 cl
.static_constructor
= c
;
2680 } else if (sym is Destructor
) {
2681 var d
= (Destructor
) sym
;
2682 if (d
.binding
== MemberBinding
.STATIC
) {
2683 if (cl
.static_destructor
!= null) {
2684 Report
.error (d
.source_reference
, "class already contains a static destructor");
2686 cl
.static_destructor
= (Destructor
) d
;
2687 } else if (d
.binding
== MemberBinding
.CLASS
) {
2688 if (cl
.class_destructor
!= null) {
2689 Report
.error (d
.source_reference
, "class already contains a class destructor");
2691 cl
.class_destructor
= (Destructor
) d
;
2693 if (cl
.destructor
!= null) {
2694 Report
.error (d
.source_reference
, "class already contains a destructor");
2696 cl
.destructor
= (Destructor
) d
;
2700 Report
.error (sym
.source_reference
, "unexpected declaration in class");
2704 Constant
parse_constant_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2705 var begin
= get_location ();
2707 expect (TokenType
.CONST
);
2709 var flags
= parse_member_declaration_modifiers ();
2711 string id
= parse_identifier ();
2713 expect (TokenType
.COLON
);
2714 var type
= parse_type (false);
2715 type
= parse_inline_array_type (type
);
2717 Expression initializer
= null;
2718 if (accept (TokenType
.ASSIGN
)) {
2719 initializer
= parse_expression ();
2721 expect_terminator ();
2723 // constant arrays don't own their element
2724 var array_type
= type as ArrayType
;
2725 if (array_type
!= null) {
2726 array_type
.element_type
.value_owned
= false;
2729 var c
= new
Constant (id
, type
, initializer
, get_src (begin
), comment
);
2730 c
.access
= get_access (id
);
2732 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2735 if (ModifierFlags
.NEW
in flags
) {
2739 set_attributes (c
, attrs
);
2743 Field
parse_field_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2744 var begin
= get_location ();
2745 string id
= parse_identifier ();
2746 expect (TokenType
.COLON
);
2748 var flags
= parse_member_declaration_modifiers ();
2750 var type
= parse_type ();
2752 type
= parse_inline_array_type (type
);
2754 var f
= new
Field (id
, type
, null, get_src (begin
), comment
);
2756 if (ModifierFlags
.ABSTRACT
in flags
|| ModifierFlags
.VIRTUAL
in flags
|| ModifierFlags
.OVERRIDE
in flags
) {
2757 Report
.error (f
.source_reference
, "abstract, virtual, and override modifiers are not applicable to fields");
2760 if (ModifierFlags
.PRIVATE
in flags
) {
2761 f
.access
= SymbolAccessibility
.PRIVATE
;
2763 f
.access
= get_access (id
);
2766 set_attributes (f
, attrs
);
2768 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2771 if (ModifierFlags
.NEW
in flags
) {
2775 if (accept (TokenType
.ASSIGN
)) {
2776 f
.initializer
= parse_expression ();
2779 if (ModifierFlags
.STATIC
in flags
) {
2780 f
.binding
= MemberBinding
.STATIC
;
2781 } else if (ModifierFlags
.CLASS
in flags
) {
2782 f
.binding
= MemberBinding
.CLASS
;
2785 expect_terminator ();
2790 InitializerList
parse_initializer () throws ParseError
{
2791 var begin
= get_location ();
2792 if (!accept (TokenType
.OPEN_PARENS
)) {
2793 expect (TokenType
.OPEN_BRACE
);
2795 var initializer
= new
InitializerList (get_src (begin
));
2796 if (current () != TokenType
.DEDENT
) {
2798 var init
= parse_argument ();
2799 initializer
.append (init
);
2800 } while (accept (TokenType
.COMMA
));
2802 if (!accept (TokenType
.CLOSE_PARENS
)) {
2803 expect (TokenType
.CLOSE_BRACE
);
2811 Method
parse_main_method_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2813 var begin
= get_location ();
2814 DataType type
= new
VoidType ();
2815 expect (TokenType
.INIT
);
2817 var method
= new
Method (id
, type
, get_src (begin
), comment
);
2818 method
.access
= SymbolAccessibility
.PUBLIC
;
2820 set_attributes (method
, attrs
);
2822 method
.binding
= MemberBinding
.STATIC
;
2824 var sym
= new
UnresolvedSymbol (null, "string", get_src (begin
));
2825 type
= new UnresolvedType
.from_symbol (sym
, get_src (begin
));
2826 type
.value_owned
= true;
2827 type
= new
ArrayType (type
, 1, get_src (begin
));
2828 type
.nullable
= false;
2830 var param
= new
Parameter ("args", type
, get_src (begin
));
2831 method
.add_parameter (param
);
2834 expect (TokenType
.EOL
);
2836 if (accept_block ()) {
2837 method
.body
= parse_block ();
2843 Method
parse_method_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2844 var begin
= get_location ();
2845 DataType type
= new
VoidType ();
2846 expect (TokenType
.DEF
);
2847 var flags
= parse_member_declaration_modifiers ();
2849 string id
= parse_identifier ();
2851 var params
= new ArrayList
<Parameter
> ();
2852 expect (TokenType
.OPEN_PARENS
);
2854 if (current () != TokenType
.CLOSE_PARENS
) {
2856 var param
= parse_parameter ();
2858 } while (accept (TokenType
.COMMA
));
2861 expect (TokenType
.CLOSE_PARENS
);
2864 /* deal with return value */
2865 if (accept (TokenType
.COLON
)) {
2866 type
= parse_type ();
2869 var type_param_list
= parse_type_parameter_list ();
2871 var method
= new
Method (id
, type
, get_src (begin
), comment
);
2872 if (ModifierFlags
.PRIVATE
in flags
) {
2873 method
.access
= SymbolAccessibility
.PRIVATE
;
2875 method
.access
= get_access (id
);
2879 set_attributes (method
, attrs
);
2881 foreach (TypeParameter type_param
in type_param_list
) {
2882 method
.add_type_parameter (type_param
);
2886 foreach (Parameter param
in params
) {
2887 method
.add_parameter (param
);
2890 if (accept (TokenType
.RAISES
)) {
2892 method
.add_error_type (parse_type ());
2893 } while (accept (TokenType
.COMMA
));
2897 if (ModifierFlags
.STATIC
in flags
|| id
== "main") {
2898 method
.binding
= MemberBinding
.STATIC
;
2899 } else if (ModifierFlags
.CLASS
in flags
) {
2900 method
.binding
= MemberBinding
.CLASS
;
2902 if (ModifierFlags
.ASYNC
in flags
) {
2903 method
.coroutine
= true;
2906 if (ModifierFlags
.NEW
in flags
) {
2907 method
.hides
= true;
2910 if (method
.binding
== MemberBinding
.INSTANCE
) {
2911 if (ModifierFlags
.ABSTRACT
in flags
) {
2912 method
.is_abstract
= true;
2914 if (ModifierFlags
.VIRTUAL
in flags
) {
2915 method
.is_virtual
= true;
2917 if (ModifierFlags
.OVERRIDE
in flags
) {
2918 method
.overrides
= true;
2920 if ((method
.is_abstract
&& method
.is_virtual
)
2921 || (method
.is_abstract
&& method
.overrides
)
2922 || (method
.is_virtual
&& method
.overrides
)) {
2923 throw new ParseError
.SYNTAX (get_error ("only one of `abstract', `virtual', or `override' may be specified"));
2926 if (ModifierFlags
.ABSTRACT
in flags
2927 || ModifierFlags
.VIRTUAL
in flags
2928 || ModifierFlags
.OVERRIDE
in flags
) {
2929 throw new ParseError
.SYNTAX (get_error ("the modifiers `abstract', `virtual', and `override' are not valid for static methods"));
2933 if (ModifierFlags
.INLINE
in flags
) {
2934 method
.is_inline
= true;
2936 if (ModifierFlags
.EXTERN
in flags
) {
2937 method
.external
= true;
2940 expect (TokenType
.EOL
);
2942 var body_location
= get_location ();
2945 /* "requires" and "ensures" if present will be at start of the method body */
2946 if (accept (TokenType
.INDENT
)) {
2947 if (accept (TokenType
.REQUIRES
)) {
2949 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
2950 while (current() != TokenType
.DEDENT
) {
2951 method
.add_precondition (parse_expression ());
2952 expect (TokenType
.EOL
);
2955 expect (TokenType
.DEDENT
);
2956 accept_terminator ();
2959 method
.add_precondition (parse_expression ());
2960 expect_terminator ();
2966 if (accept (TokenType
.ENSURES
)) {
2967 if (accept (TokenType
.EOL
) && accept (TokenType
.INDENT
)) {
2968 while (current() != TokenType
.DEDENT
) {
2969 method
.add_postcondition (parse_expression ());
2970 expect (TokenType
.EOL
);
2973 expect (TokenType
.DEDENT
);
2974 accept_terminator ();
2976 method
.add_postcondition (parse_expression ());
2977 expect_terminator ();
2982 rollback (body_location
);
2985 if (accept_block ()) {
2986 method
.body
= parse_block ();
2987 } else if (scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
2988 method
.external
= true;
2993 Property
parse_property_declaration (List
<Attribute
>? attrs
) throws ParseError
{
2994 var begin
= get_location ();
2995 var readonly = false;
2997 expect (TokenType
.PROP
);
2999 var flags
= parse_member_declaration_modifiers ();
3001 readonly = accept (TokenType
.READONLY
);
3003 string id
= parse_identifier ();
3004 expect (TokenType
.COLON
);
3006 var type
= parse_type (false);
3008 var prop
= new
Property (id
, type
, null, null, get_src (begin
), comment
);
3009 if (ModifierFlags
.PRIVATE
in flags
) {
3010 prop
.access
= SymbolAccessibility
.PRIVATE
;
3012 prop
.access
= get_access (id
);
3015 set_attributes (prop
, attrs
);
3017 if (ModifierFlags
.STATIC
in flags
) {
3018 prop
.binding
= MemberBinding
.STATIC
;
3019 } else if (ModifierFlags
.CLASS
in flags
) {
3020 prop
.binding
= MemberBinding
.CLASS
;
3022 if (ModifierFlags
.ABSTRACT
in flags
) {
3023 prop
.is_abstract
= true;
3025 if (ModifierFlags
.VIRTUAL
in flags
) {
3026 prop
.is_virtual
= true;
3028 if (ModifierFlags
.OVERRIDE
in flags
) {
3029 prop
.overrides
= true;
3032 if (ModifierFlags
.NEW
in flags
) {
3035 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3036 prop
.external
= true;
3039 if (ModifierFlags
.ASYNC
in flags
) {
3040 Report
.error (prop
.source_reference
, "async properties are not supported yet");
3043 if (accept (TokenType
.ASSIGN
)) {
3044 prop
.initializer
= parse_expression ();
3048 if (accept_block ()) {
3049 expect (TokenType
.INDENT
);
3050 while (current () != TokenType
.DEDENT
) {
3051 var accessor_begin
= get_location ();
3052 var attribs
= parse_attributes (false);
3054 var value_type
= type
.copy ();
3055 value_type
.value_owned
= accept (TokenType
.OWNED
);
3057 if (accept (TokenType
.GET
)) {
3058 if (prop
.get_accessor
!= null) {
3059 throw new ParseError
.SYNTAX (get_error ("property get accessor already defined"));
3062 if (accept_block ()) {
3063 block
= parse_block ();
3064 prop
.external
= false;
3066 prop
.get_accessor
= new
PropertyAccessor (true, false, false, value_type
, block
, get_src (accessor_begin
));
3067 set_attributes (prop
.get_accessor
, attribs
);
3068 prop
.get_accessor
.access
= SymbolAccessibility
.PUBLIC
;
3070 bool _construct
= false;
3071 if (accept (TokenType
.SET
)) {
3073 throw new ParseError
.SYNTAX (get_error ("set block not allowed for a read only property"));
3075 _construct
= (context
.profile
== Profile
.GOBJECT
) && accept (TokenType
.CONSTRUCT
);
3076 } else if (context
.profile
== Profile
.GOBJECT
&& accept (TokenType
.CONSTRUCT
)) {
3078 } else if (!accept (TokenType
.EOL
)) {
3079 throw new ParseError
.SYNTAX (get_error ("expected get, set, or construct"));
3082 if (prop
.set_accessor
!= null) {
3083 throw new ParseError
.SYNTAX (get_error ("property set accessor already defined"));
3087 if (accept_block ()) {
3088 block
= parse_block ();
3089 prop
.external
= false;
3091 prop
.set_accessor
= new
PropertyAccessor (false, !readonly, _construct
, value_type
, block
, get_src (accessor_begin
));
3092 set_attributes (prop
.set_accessor
, attribs
);
3093 prop
.set_accessor
.access
= SymbolAccessibility
.PUBLIC
;
3096 accept (TokenType
.EOL
);
3097 expect (TokenType
.DEDENT
);
3099 var value_type
= type
.copy ();
3100 value_type
.value_owned
= false;
3102 prop
.get_accessor
= new
PropertyAccessor (true, false, false, value_type
, null, get_src (begin
));
3103 prop
.get_accessor
.access
= SymbolAccessibility
.PUBLIC
;
3106 value_type
= type
.copy ();
3107 value_type
.value_owned
= false;
3109 prop
.set_accessor
= new
PropertyAccessor (false, true, false, value_type
, null, get_src (begin
));
3110 prop
.set_accessor
.access
= SymbolAccessibility
.PUBLIC
;
3114 expect_terminator ();
3117 if (!prop
.is_abstract
&& scanner
.source_file
.file_type
== SourceFileType
.SOURCE
) {
3118 var needs_var
= (readonly && (prop
.get_accessor
!= null && prop
.get_accessor
.body
== null));
3121 needs_var
= (prop
.get_accessor
!= null && prop
.get_accessor
.body
== null) || (prop
.set_accessor
!= null && prop
.set_accessor
.body
== null);
3125 /* automatic property accessor body generation */
3126 var variable_type
= prop
.property_type
.copy ();
3127 prop
.field
= new
Field ("_%s".printf (prop
.name
), variable_type
, prop
.initializer
, prop
.source_reference
);
3128 prop
.field
.access
= SymbolAccessibility
.PRIVATE
;
3129 prop
.field
.binding
= prop
.binding
;
3136 Vala
.Signal
parse_signal_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3137 var begin
= get_location ();
3140 expect (TokenType
.EVENT
);
3141 var flags
= parse_member_declaration_modifiers ();
3142 string id
= parse_identifier ();
3145 var params
= new ArrayList
<Parameter
> ();
3147 expect (TokenType
.OPEN_PARENS
);
3148 if (current () != TokenType
.CLOSE_PARENS
) {
3150 var param
= parse_parameter ();
3152 } while (accept (TokenType
.COMMA
));
3154 expect (TokenType
.CLOSE_PARENS
);
3156 if (accept (TokenType
.COLON
)) {
3157 type
= parse_type ();
3159 type
= new
VoidType ();
3162 var sig
= new Vala
.Signal (id
, type
, get_src (begin
), comment
);
3163 if (ModifierFlags
.PRIVATE
in flags
) {
3164 sig
.access
= SymbolAccessibility
.PRIVATE
;
3166 sig
.access
= get_access (id
);
3169 if (ModifierFlags
.VIRTUAL
in flags
) {
3170 sig
.is_virtual
= true;
3172 if (ModifierFlags
.NEW
in flags
) {
3176 if (ModifierFlags
.STATIC
in flags
) {
3177 throw new ParseError
.SYNTAX (get_error ("`static' modifier not allowed on signals"));
3178 } else if (ModifierFlags
.CLASS
in flags
) {
3179 throw new ParseError
.SYNTAX (get_error ("`class' modifier not allowed on signals"));
3182 set_attributes (sig
, attrs
);
3184 foreach (Parameter formal_param
in params
) {
3185 sig
.add_parameter (formal_param
);
3188 if (!accept_terminator ()) {
3189 sig
.body
= parse_block ();
3194 Constructor
parse_constructor_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3195 var begin
= get_location ();
3197 expect (TokenType
.INIT
);
3198 var flags
= parse_member_declaration_modifiers ();
3200 var c
= new
Constructor (get_src (begin
));
3201 if (ModifierFlags
.STATIC
in flags
) {
3202 c
.binding
= MemberBinding
.STATIC
;
3203 } else if (ModifierFlags
.CLASS
in flags
) {
3204 c
.binding
= MemberBinding
.CLASS
;
3208 c
.body
= parse_block ();
3212 Destructor
parse_destructor_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3213 var begin
= get_location ();
3214 expect (TokenType
.FINAL
);
3215 var d
= new
Destructor (get_src (begin
));
3217 d
.body
= parse_block ();
3221 Symbol
parse_struct_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3222 var begin
= get_location ();
3224 expect (TokenType
.STRUCT
);
3225 var flags
= parse_type_declaration_modifiers ();
3226 var sym
= parse_symbol_name ();
3227 var type_param_list
= parse_type_parameter_list ();
3228 DataType base_type
= null;
3229 if (accept (TokenType
.COLON
)) {
3230 base_type
= parse_type ();
3233 var st
= new
Struct (sym
.name
, get_src (begin
), comment
);
3234 if (ModifierFlags
.PRIVATE
in flags
) {
3235 st
.access
= SymbolAccessibility
.PRIVATE
;
3237 st
.access
= get_access (sym
.name
);
3239 set_attributes (st
, attrs
);
3240 foreach (TypeParameter type_param
in type_param_list
) {
3241 st
.add_type_parameter (type_param
);
3243 if (base_type
!= null) {
3244 st
.base_type
= base_type
;
3247 expect (TokenType
.EOL
);
3249 parse_declarations (st
);
3252 while (sym
.inner
!= null) {
3254 var ns
= new
Namespace (sym
.name
, st
.source_reference
);
3255 if (result is Namespace
) {
3256 ns
.add_namespace ((Namespace
) result
);
3258 ns
.add_struct ((Struct
) result
);
3265 void parse_struct_member (Struct st
) throws ParseError
{
3266 var sym
= parse_declaration ();
3267 if (sym is Method
) {
3268 st
.add_method ((Method
) sym
);
3269 } else if (sym is Field
) {
3270 st
.add_field ((Field
) sym
);
3271 } else if (sym is Constant
) {
3272 st
.add_constant ((Constant
) sym
);
3274 Report
.error (sym
.source_reference
, "unexpected declaration in struct");
3278 Symbol
parse_interface_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3279 var begin
= get_location ();
3281 expect (TokenType
.INTERFACE
);
3282 var flags
= parse_type_declaration_modifiers ();
3283 var sym
= parse_symbol_name ();
3284 var type_param_list
= parse_type_parameter_list ();
3285 var base_types
= new ArrayList
<DataType
> ();
3286 if (accept (TokenType
.COLON
)) {
3288 var type
= parse_type ();
3289 base_types
.add (type
);
3290 } while (accept (TokenType
.COMMA
));
3293 var iface
= new
Interface (sym
.name
, get_src (begin
), comment
);
3294 if (ModifierFlags
.PRIVATE
in flags
) {
3295 iface
.access
= SymbolAccessibility
.PRIVATE
;
3297 iface
.access
= get_access (sym
.name
);
3299 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3300 iface
.external
= true;
3302 set_attributes (iface
, attrs
);
3303 foreach (TypeParameter type_param
in type_param_list
) {
3304 iface
.add_type_parameter (type_param
);
3306 foreach (DataType base_type
in base_types
) {
3307 iface
.add_prerequisite (base_type
);
3311 expect (TokenType
.EOL
);
3313 parse_declarations (iface
);
3316 Symbol result
= iface
;
3317 while (sym
.inner
!= null) {
3319 var ns
= new
Namespace (sym
.name
, iface
.source_reference
);
3320 if (result is Namespace
) {
3321 ns
.add_namespace ((Namespace
) result
);
3323 ns
.add_interface ((Interface
) result
);
3330 void parse_interface_member (Interface iface
) throws ParseError
{
3331 var sym
= parse_declaration ();
3333 iface
.add_class ((Class
) sym
);
3334 } else if (sym is Struct
) {
3335 iface
.add_struct ((Struct
) sym
);
3336 } else if (sym is Enum
) {
3337 iface
.add_enum ((Enum
) sym
);
3338 } else if (sym is Delegate
) {
3339 iface
.add_delegate ((Delegate
) sym
);
3340 } else if (sym is Method
) {
3341 iface
.add_method ((Method
) sym
);
3342 } else if (sym is Vala
.Signal
) {
3343 iface
.add_signal ((Vala
.Signal
) sym
);
3344 } else if (sym is Field
) {
3345 iface
.add_field ((Field
) sym
);
3346 } else if (sym is Constant
) {
3347 iface
.add_constant ((Constant
) sym
);
3348 } else if (sym is Property
) {
3349 iface
.add_property ((Property
) sym
);
3351 Report
.error (sym
.source_reference
, "unexpected declaration in interface");
3355 Symbol
parse_enum_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3356 var begin
= get_location ();
3357 expect (TokenType
.ENUM
);
3358 var flags
= parse_type_declaration_modifiers ();
3360 var sym
= parse_symbol_name ();
3361 var en
= new
Enum (sym
.name
, get_src (begin
), comment
);
3362 if (ModifierFlags
.PRIVATE
in flags
) {
3363 en
.access
= SymbolAccessibility
.PRIVATE
;
3365 en
.access
= get_access (sym
.name
);
3367 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3370 set_attributes (en
, attrs
);
3372 expect (TokenType
.EOL
);
3373 expect (TokenType
.INDENT
);
3375 if (current () == TokenType
.DEDENT
) {
3376 // allow trailing comma
3379 var value_attrs
= parse_attributes (false);
3380 var value_begin
= get_location ();
3381 string id
= parse_identifier ();
3382 comment
= scanner
.pop_comment ();
3384 Expression value
= null;
3385 if (accept (TokenType
.ASSIGN
)) {
3386 value
= parse_expression ();
3389 var ev
= new
EnumValue (id
, value
, get_src (value_begin
), comment
);
3390 ev
.access
= SymbolAccessibility
.PUBLIC
;
3391 set_attributes (ev
, value_attrs
);
3394 expect (TokenType
.EOL
);
3397 expect (TokenType
.DEDENT
);
3400 while (sym
.inner
!= null) {
3402 var ns
= new
Namespace (sym
.name
, en
.source_reference
);
3403 if (result is Namespace
) {
3404 ns
.add_namespace ((Namespace
) result
);
3406 ns
.add_enum ((Enum
) result
);
3413 Symbol
parse_errordomain_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3414 var begin
= get_location ();
3415 expect (TokenType
.ERRORDOMAIN
);
3416 var flags
= parse_type_declaration_modifiers ();
3418 var sym
= parse_symbol_name ();
3419 var ed
= new
ErrorDomain (sym
.name
, get_src (begin
), comment
);
3420 if (ModifierFlags
.PRIVATE
in flags
) {
3421 ed
.access
= SymbolAccessibility
.PRIVATE
;
3423 ed
.access
= get_access (sym
.name
);
3426 set_attributes (ed
, attrs
);
3428 expect (TokenType
.EOL
);
3429 expect (TokenType
.INDENT
);
3432 if (current () == TokenType
.DEDENT
) {
3433 // allow trailing comma
3436 var code_attrs
= parse_attributes (false);
3437 var code_begin
= get_location ();
3438 string id
= parse_identifier ();
3439 comment
= scanner
.pop_comment ();
3440 var ec
= new
ErrorCode (id
, get_src (code_begin
), comment
);
3441 set_attributes (ec
, code_attrs
);
3442 if (accept (TokenType
.ASSIGN
)) {
3443 ec
.value
= parse_expression ();
3446 accept (TokenType
.EOL
);
3450 expect (TokenType
.DEDENT
);
3453 while (sym
.inner
!= null) {
3455 var ns
= new
Namespace (sym
.name
, ed
.source_reference
);
3457 if (result is Namespace
) {
3458 ns
.add_namespace ((Namespace
) result
);
3460 ns
.add_error_domain ((ErrorDomain
) result
);
3467 ModifierFlags
parse_type_declaration_modifiers () {
3468 ModifierFlags flags
= 0;
3470 switch (current ()) {
3471 case TokenType
.ABSTRACT
:
3473 flags
|= ModifierFlags
.ABSTRACT
;
3476 case TokenType
.EXTERN
:
3478 flags
|= ModifierFlags
.EXTERN
;
3481 case TokenType
.STATIC
:
3483 flags
|= ModifierFlags
.STATIC
;
3486 case TokenType
.PRIVATE
:
3488 flags
|= ModifierFlags
.PRIVATE
;
3497 ModifierFlags
parse_member_declaration_modifiers () {
3498 ModifierFlags flags
= 0;
3500 switch (current ()) {
3501 case TokenType
.ABSTRACT
:
3503 flags
|= ModifierFlags
.ABSTRACT
;
3505 case TokenType
.ASYNC
:
3507 flags
|= ModifierFlags
.ASYNC
;
3509 case TokenType
.CLASS
:
3511 flags
|= ModifierFlags
.CLASS
;
3513 case TokenType
.EXTERN
:
3515 flags
|= ModifierFlags
.EXTERN
;
3517 case TokenType
.INLINE
:
3519 flags
|= ModifierFlags
.INLINE
;
3523 flags
|= ModifierFlags
.NEW
;
3525 case TokenType
.OVERRIDE
:
3527 flags
|= ModifierFlags
.OVERRIDE
;
3529 case TokenType
.STATIC
:
3531 flags
|= ModifierFlags
.STATIC
;
3533 case TokenType
.VIRTUAL
:
3535 flags
|= ModifierFlags
.VIRTUAL
;
3537 case TokenType
.PRIVATE
:
3539 flags
|= ModifierFlags
.PRIVATE
;
3547 Parameter
parse_parameter () throws ParseError
{
3548 var attrs
= parse_attributes (true);
3549 var begin
= get_location ();
3550 if (accept (TokenType
.ELLIPSIS
)) {
3552 return new Parameter
.with_ellipsis (get_src (begin
));
3554 bool params_array
= accept (TokenType
.PARAMS
);
3555 var direction
= ParameterDirection
.IN
;
3556 if (accept (TokenType
.OUT
)) {
3557 direction
= ParameterDirection
.OUT
;
3558 } else if (accept (TokenType
.REF
)) {
3559 direction
= ParameterDirection
.REF
;
3562 string id
= parse_identifier ();
3564 expect (TokenType
.COLON
);
3567 if (direction
== ParameterDirection
.IN
) {
3568 type
= parse_type (false);
3570 type
= parse_type (true);
3573 var param
= new
Parameter (id
, type
, get_src (begin
));
3574 set_attributes (param
, attrs
);
3575 param
.direction
= direction
;
3576 param
.params_array
= params_array
;
3577 if (accept (TokenType
.ASSIGN
)) {
3578 param
.initializer
= parse_expression ();
3583 CreationMethod
parse_creation_method_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3584 var begin
= get_location ();
3585 CreationMethod method
;
3587 expect (TokenType
.CONSTRUCT
);
3588 parse_member_declaration_modifiers ();
3590 if (accept (TokenType
.OPEN_PARENS
)) {
3591 /* create default name using class name */
3592 method
= new
CreationMethod (class_name
, null, get_src (begin
), comment
);
3594 var sym
= parse_symbol_name ();
3595 if (sym
.inner
== null) {
3597 if (sym
.name
!= class_name
) {
3598 method
= new
CreationMethod (class_name
, sym
.name
, get_src (begin
), comment
);
3600 method
= new
CreationMethod (sym
.name
, null, get_src (begin
), comment
);
3603 method
= new
CreationMethod (sym
.inner
.name
, sym
.name
, get_src (begin
), comment
);
3605 expect (TokenType
.OPEN_PARENS
);
3608 if (current () != TokenType
.CLOSE_PARENS
) {
3610 var param
= parse_parameter ();
3611 method
.add_parameter (param
);
3612 } while (accept (TokenType
.COMMA
));
3614 expect (TokenType
.CLOSE_PARENS
);
3615 if (accept (TokenType
.RAISES
)) {
3617 method
.add_error_type (parse_type ());
3618 } while (accept (TokenType
.COMMA
));
3620 method
.access
= SymbolAccessibility
.PUBLIC
;
3621 set_attributes (method
, attrs
);
3622 method
.binding
= MemberBinding
.STATIC
;
3624 if (accept_block ()) {
3625 method
.body
= parse_block ();
3626 } else if (scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3627 method
.external
= true;
3633 Symbol
parse_delegate_declaration (List
<Attribute
>? attrs
) throws ParseError
{
3634 var begin
= get_location ();
3637 expect (TokenType
.DELEGATE
);
3639 var flags
= parse_member_declaration_modifiers ();
3641 var sym
= parse_symbol_name ();
3643 var type_param_list
= parse_type_parameter_list ();
3645 if (ModifierFlags
.NEW
in flags
) {
3646 throw new ParseError
.SYNTAX (get_error ("`new' modifier not allowed on delegates"));
3649 var params
= new ArrayList
<Parameter
> ();
3651 expect (TokenType
.OPEN_PARENS
);
3652 if (current () != TokenType
.CLOSE_PARENS
) {
3654 var param
= parse_parameter ();
3656 } while (accept (TokenType
.COMMA
));
3658 expect (TokenType
.CLOSE_PARENS
);
3660 if (accept (TokenType
.COLON
)) {
3661 type
= parse_type ();
3664 type
= new
VoidType ();
3667 var d
= new
Delegate (sym
.name
, type
, get_src (begin
), comment
);
3669 if (accept (TokenType
.RAISES
)) {
3671 d
.add_error_type (parse_type ());
3672 } while (accept (TokenType
.COMMA
));
3675 expect_terminator ();
3678 if (ModifierFlags
.PRIVATE
in flags
) {
3679 d
.access
= SymbolAccessibility
.PRIVATE
;
3681 d
.access
= get_access (sym
.name
);
3684 if (!(ModifierFlags
.STATIC
in flags
)) {
3685 d
.has_target
= true;
3687 if (ModifierFlags
.EXTERN
in flags
|| scanner
.source_file
.file_type
== SourceFileType
.PACKAGE
) {
3691 set_attributes (d
, attrs
);
3693 foreach (TypeParameter type_param
in type_param_list
) {
3694 d
.add_type_parameter (type_param
);
3697 foreach (Parameter formal_param
in params
) {
3698 d
.add_parameter (formal_param
);
3704 while (sym
.inner
!= null) {
3706 var ns
= new
Namespace (sym
.name
, d
.source_reference
);
3708 if (result is Namespace
) {
3709 ns
.add_namespace ((Namespace
) result
);
3711 ns
.add_delegate ((Delegate
) result
);
3718 List
<TypeParameter
> parse_type_parameter_list () throws ParseError
{
3719 if (accept (TokenType
.OF
)) {
3720 var list
= new ArrayList
<TypeParameter
> ();
3722 var begin
= get_location ();
3723 string id
= parse_identifier ();
3724 list
.add (new
TypeParameter (id
, get_src (begin
)));
3725 } while (accept (TokenType
.COMMA
));
3728 if (_empty_type_parameter_list
== null) {
3729 _empty_type_parameter_list
= new ArrayList
<TypeParameter
> ();
3731 return _empty_type_parameter_list
;
3735 void skip_type_argument_list () throws ParseError
{
3736 if (accept (TokenType
.OF
)) {
3739 } while (accept (TokenType
.COMMA
));
3743 // try to parse type argument list
3744 List
<DataType
>?
parse_type_argument_list (bool maybe_expression
) throws ParseError
{
3745 var begin
= get_location ();
3746 if (accept (TokenType
.OF
)) {
3747 var list
= new ArrayList
<DataType
> ();
3749 switch (current ()) {
3750 case TokenType
.VOID
:
3751 case TokenType
.DYNAMIC
:
3752 case TokenType
.UNOWNED
:
3753 case TokenType
.WEAK
:
3754 case TokenType
.IDENTIFIER
:
3755 var type
= parse_type ();
3763 } while (accept (TokenType
.COMMA
));
3770 MemberAccess
parse_member_name (Expression? base_expr
= null) throws ParseError
{
3771 var begin
= get_location ();
3772 MemberAccess expr
= null;
3774 string id
= parse_identifier ();
3775 List
<DataType
> type_arg_list
= parse_type_argument_list (false);
3776 expr
= new
MemberAccess (expr
!= null ? expr
: base_expr
, id
, get_src (begin
));
3777 if (type_arg_list
!= null) {
3778 foreach (DataType type_arg
in type_arg_list
) {
3779 expr
.add_type_argument (type_arg
);
3782 } while (accept (TokenType
.DOT
));