]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
GENIE: Updated genie to include fixes from vala parser
authorJamie McCracken <jamie.mccrack@gmail.com>
Sat, 15 Sep 2012 16:57:48 +0000 (12:57 -0400)
committerJamie McCracken <jamie.mccrack@gmail.com>
Sat, 15 Sep 2012 16:57:48 +0000 (12:57 -0400)
vala/valagenieparser.vala
vala/valageniescanner.vala
vala/valagenietokentype.vala

index 77fbd1c5dca17033ff703a5f5aa7560bc422c5ae..d4d9d3fde66df2a9448a42ea3dd1d2ae85f91cec 100644 (file)
@@ -1,6 +1,6 @@
 /* valagenieparser.vala
  *
- * Copyright (C) 2008  Jamie McCracken, Jürg Billeter
+ * Copyright (C) 2008-2012  Jamie McCracken, Jürg Billeter
  * Based on code by Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
@@ -67,7 +67,8 @@ public class Vala.Genie.Parser : CodeVisitor {
                STATIC = 1 << 6,
                VIRTUAL = 1 << 7,
                PRIVATE = 1 << 8,
-               ASYNC = 1 << 9
+               ASYNC = 1 << 9,
+               SEALED = 1 << 10
        }
 
        public Parser () {
@@ -281,6 +282,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                case TokenType.REF:
                case TokenType.REQUIRES:
                case TokenType.RETURN:
+               case TokenType.SEALED:
                case TokenType.SET:
                case TokenType.SIZEOF:
                case TokenType.STATIC:
@@ -426,21 +428,23 @@ public class Vala.Genie.Parser : CodeVisitor {
        }
 
        void skip_type () throws ParseError {
-               if (accept (TokenType.VOID)) {
-                       while (accept (TokenType.STAR)) {
-                       }
-                       return;
-               }
+               
                accept (TokenType.DYNAMIC);
                accept (TokenType.OWNED);
                accept (TokenType.UNOWNED);
                accept (TokenType.WEAK);
+               
+
                if (accept (TokenType.ARRAY) || accept (TokenType.LIST) || accept (TokenType.DICT)) {
                        accept (TokenType.OF);
                }
                
-               skip_symbol_name ();
-               skip_type_argument_list ();
+               if (accept (TokenType.VOID)) {
+               } else {
+                       skip_symbol_name ();
+                       skip_type_argument_list ();
+               }
+               
                while (accept (TokenType.OPEN_BRACKET)) {       
                        do {
                                if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
@@ -463,25 +467,22 @@ public class Vala.Genie.Parser : CodeVisitor {
                return expr;
        }
 
-       DataType parse_type (bool owned_by_default = true) throws ParseError {
+       DataType parse_type (bool owned_by_default, bool can_weak_ref) throws ParseError {
                var begin = get_location ();
 
-               if (accept (TokenType.VOID)) {
-                       DataType type = new VoidType ();
-                       while (accept (TokenType.STAR)) {
-                               type = new PointerType (type);
-                       }
-                       return type;
-               }
-
                List<DataType> type_arg_list = null;
                UnresolvedSymbol sym = null;
                
                bool is_dynamic = accept (TokenType.DYNAMIC);
                bool value_owned = owned_by_default;
+               
                if (owned_by_default) {
-                       if (accept (TokenType.UNOWNED)
-                           || accept (TokenType.WEAK)) {
+                       if (accept (TokenType.UNOWNED)) {
+                               value_owned = false;
+                       } else if (accept (TokenType.WEAK)) {
+                               if (!can_weak_ref && !context.deprecated) {
+                                       Report.warning (get_src (begin), "deprecated syntax, use `unowned` modifier");
+                               }
                                value_owned = false;
                        }
                } else {
@@ -514,25 +515,32 @@ public class Vala.Genie.Parser : CodeVisitor {
                        is_dict = true;
                }
                
-               if (is_list) {
-                       var sym_parent = new UnresolvedSymbol (null, "Gee", get_src (begin));
-                       sym = new UnresolvedSymbol (sym_parent, "ArrayList", get_src (begin));
-               } else if (is_dict) {
-                       var sym_parent = new UnresolvedSymbol (null, "Gee", get_src (begin));
-                       sym = new UnresolvedSymbol (sym_parent, "HashMap", get_src (begin));
-               } else {
-                       sym = parse_symbol_name ();
-               }
+               DataType type;
                
-               type_arg_list = parse_type_argument_list (false);
+               if (!is_dynamic && value_owned == owned_by_default && accept (TokenType.VOID)) {
+                       type = new VoidType (get_src (begin));
+               } else {
+                       
+                       if (is_list) {
+                               var sym_parent = new UnresolvedSymbol (null, "Gee", get_src (begin));
+                               sym = new UnresolvedSymbol (sym_parent, "ArrayList", get_src (begin));
+                       } else if (is_dict) {
+                               var sym_parent = new UnresolvedSymbol (null, "Gee", get_src (begin));
+                               sym = new UnresolvedSymbol (sym_parent, "HashMap", get_src (begin));
+                       } else {
+                               sym = parse_symbol_name ();
+                       }
+                       
+                       type_arg_list = parse_type_argument_list (false);
 
-               DataType type = new UnresolvedType.from_symbol (sym, get_src (begin));
-               if (type_arg_list != null) {
-                       foreach (DataType type_arg in type_arg_list) {
-                               type.add_type_argument (type_arg);
+                       type = new UnresolvedType.from_symbol (sym, get_src (begin));
+                       if (type_arg_list != null) {
+                               foreach (DataType type_arg in type_arg_list) {
+                                       type.add_type_argument (type_arg);
+                               }
                        }
                }
-
+               
                while (accept (TokenType.STAR)) {
                         type = new PointerType (type, get_src (begin));
                }
@@ -562,8 +570,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                                                        // only used for parsing, reject use as real type
                                                        invalid_array = true;
                                                }
-                                       }
-                                       while (accept (TokenType.COMMA));
+                                       } while (accept (TokenType.COMMA));
                                        expect (TokenType.CLOSE_BRACKET);
 
                                        type.value_owned = true;
@@ -581,6 +588,10 @@ public class Vala.Genie.Parser : CodeVisitor {
                        value_owned = accept (TokenType.HASH);
                }
 
+               if (type is PointerType) {
+                       value_owned = false;
+               }
+               
                type.is_dynamic = is_dynamic;
                type.value_owned = value_owned;
                return type;
@@ -903,6 +914,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                expect (TokenType.OPEN_PARENS);
                var arg_list = parse_argument_list ();
                expect (TokenType.CLOSE_PARENS);
+               
                var init_list = parse_object_initializer ();
 
                if (init_list.size > 0 && inner is MemberAccess) {
@@ -985,23 +997,23 @@ public class Vala.Genie.Parser : CodeVisitor {
                
                if (accept (TokenType.ARRAY)) {
                        expect (TokenType.OF);
-                       var mtype = parse_type ();
+                       var mtype = parse_type (true, false);
                        var expr = parse_array_creation_expression (begin, mtype);
                        return expr;
                }
                
                if (accept (TokenType.LIST)) {
                        expect (TokenType.OF);
-                       var mtype = parse_type ();
+                       var mtype = parse_type (true, false);
                        var expr = parse_list_creation_expression (begin, mtype);
                        return expr;
                }
                
                if (accept (TokenType.DICT)) {
                        expect (TokenType.OF);
-                       var mtype1 = parse_type ();
+                       var mtype1 = parse_type (true, false);
                        expect (TokenType.COMMA);
-                       var mtype2 = parse_type ();
+                       var mtype2 = parse_type (true, false);
                        var expr = parse_dict_creation_expression (begin, mtype1, mtype2);
                        return expr;
                }
@@ -1138,24 +1150,31 @@ public class Vala.Genie.Parser : CodeVisitor {
        }
 
        Expression parse_yield_expression () throws ParseError {
-               var begin = get_location ();
                expect (TokenType.YIELD);
-               Expression base_expr = null;
-               if (current () == TokenType.SUPER) {
-                       base_expr = parse_base_access ();
-                       expect (TokenType.DOT);
+
+               var expr = parse_expression ();
+
+               var call = expr as MethodCall;
+               var object_creation = expr as ObjectCreationExpression;
+               if (call == null && object_creation == null) {
+                       Report.error (expr.source_reference, "syntax error, expected method call");
+                       throw new ParseError.SYNTAX ("expected method call");
+               }
+
+               if (call != null) {
+                       call.is_yield_expression = true;
+               } else if (object_creation != null) {
+                       object_creation.is_yield_expression = true;
                }
-               var member = parse_member_name (base_expr);
-               var call = (MethodCall) parse_method_call (begin, member);
-               call.is_yield_expression = true;
-               return call;
+
+               return expr;
        }
 
        Expression parse_sizeof_expression () throws ParseError {
                var begin = get_location ();
                expect (TokenType.SIZEOF);
                expect (TokenType.OPEN_PARENS);
-               var type = parse_type ();
+               var type = parse_type (true, false);
                expect (TokenType.CLOSE_PARENS);
 
                return new SizeofExpression (type, get_src (begin));
@@ -1165,7 +1184,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                var begin = get_location ();
                expect (TokenType.TYPEOF);
                expect (TokenType.OPEN_PARENS);
-               var type = parse_type ();
+               var type = parse_type (true, false);
                expect (TokenType.CLOSE_PARENS);
 
                return new TypeofExpression (type, get_src (begin));
@@ -1179,7 +1198,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                case TokenType.TILDE:  return UnaryOperator.BITWISE_COMPLEMENT;
                case TokenType.OP_INC: return UnaryOperator.INCREMENT;
                case TokenType.OP_DEC: return UnaryOperator.DECREMENT;
-               default:               return UnaryOperator.NONE;
+               default:                           return UnaryOperator.NONE;
                }
        }
 
@@ -1193,6 +1212,9 @@ public class Vala.Genie.Parser : CodeVisitor {
                }
                switch (current ()) {
                case TokenType.HASH:
+                       if (!context.deprecated) {
+                               Report.warning (get_src (begin), "deprecated syntax, use `(owned)` cast");
+                       }               
                        next ();
                        var op = parse_unary_expression ();
                        return new ReferenceTransferExpression (op, get_src (begin));
@@ -1213,7 +1235,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                        case TokenType.ARRAY:
                        case TokenType.LIST:
                        case TokenType.DICT:
-                               var type = parse_type ();
+                               var type = parse_type (true, false);
                                if (accept (TokenType.CLOSE_PARENS)) {
                                        // check follower to decide whether to create cast expression
                                        switch (current ()) {
@@ -1237,6 +1259,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                                        case TokenType.TYPEOF:
                                        case TokenType.IDENTIFIER:
                                        case TokenType.PARAMS:
+                                       case TokenType.YIELD:
                                                var inner = parse_unary_expression ();
                                                return new CastExpression (inner, type, get_src (begin), false);
                                        default:
@@ -1277,10 +1300,10 @@ public class Vala.Genie.Parser : CodeVisitor {
 
        BinaryOperator get_binary_operator (TokenType token_type) {
                switch (token_type) {
-               case TokenType.STAR:    return BinaryOperator.MUL;
-               case TokenType.DIV:     return BinaryOperator.DIV;
+               case TokenType.STAR:    return BinaryOperator.MUL;
+               case TokenType.DIV:      return BinaryOperator.DIV;
                case TokenType.PERCENT: return BinaryOperator.MOD;
-               case TokenType.PLUS:    return BinaryOperator.PLUS;
+               case TokenType.PLUS:    return BinaryOperator.PLUS;
                case TokenType.MINUS:   return BinaryOperator.MINUS;
                case TokenType.OP_LT:   return BinaryOperator.LESS_THAN;
                case TokenType.OP_GT:   return BinaryOperator.GREATER_THAN;
@@ -1296,7 +1319,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                        prev ();
                        return BinaryOperator.EQUALITY;
                case TokenType.OP_NE:   return BinaryOperator.INEQUALITY;
-               default:                return BinaryOperator.NONE;
+               default:                                return BinaryOperator.NONE;
                }
        }
 
@@ -1405,12 +1428,12 @@ public class Vala.Genie.Parser : CodeVisitor {
                                switch (current ()) {
                                case TokenType.ISA:
                                        next ();
-                                       var type = parse_type ();
+                                       var type = parse_type (true, false);
                                        left = new TypeCheck (left, type, get_src (begin));
                                        break;
                                case TokenType.AS:
                                        next ();
-                                       var type = parse_type ();
+                                       var type = parse_type (true, false);
                                        left = new CastExpression (left, type, get_src (begin), true);
                                        break;
                                default:
@@ -1520,6 +1543,22 @@ public class Vala.Genie.Parser : CodeVisitor {
                }
        }
 
+       Parameter parse_lambda_parameter () throws ParseError {
+               var begin = get_location ();
+               var direction = ParameterDirection.IN;
+               if (accept (TokenType.OUT)) {
+                       direction = ParameterDirection.OUT;
+               } else if (accept (TokenType.REF)) {
+                       direction = ParameterDirection.REF;
+               }
+
+               string id = parse_identifier ();
+
+               var param = new Parameter (id, null, get_src (begin));
+               param.direction = direction;
+               return param;
+       }
+       
        Expression parse_lambda_expression () throws ParseError {
                var begin = get_location ();
                List<Parameter> params = new ArrayList<Parameter> ();
@@ -1529,18 +1568,16 @@ public class Vala.Genie.Parser : CodeVisitor {
                if (accept (TokenType.OPEN_PARENS)) {
                        if (current () != TokenType.CLOSE_PARENS) {
                                do {
-                                       var param = new Parameter (parse_identifier (), null, get_src (get_location ()));
-                                       params.add (param);
+                                       params.add (parse_lambda_parameter ());
                                } while (accept (TokenType.COMMA));
                        }
                        expect (TokenType.CLOSE_PARENS);
                } else {
-                       var param = new Parameter (parse_identifier (), null, get_src (get_location ()));
-                       params.add (param);
+                       params.add (parse_lambda_parameter ());
                }
 
-
                LambdaExpression lambda;
+
                if (accept_block ()) {
                        var block = parse_block ();
                        lambda = new LambdaExpression.with_statement_body (block, get_src (begin));
@@ -1560,17 +1597,17 @@ public class Vala.Genie.Parser : CodeVisitor {
 
        AssignmentOperator get_assignment_operator (TokenType token_type) {
                switch (token_type) {
-               case TokenType.ASSIGN:             return AssignmentOperator.SIMPLE;
-               case TokenType.ASSIGN_ADD:         return AssignmentOperator.ADD;
-               case TokenType.ASSIGN_SUB:         return AssignmentOperator.SUB;
-               case TokenType.ASSIGN_BITWISE_OR:  return AssignmentOperator.BITWISE_OR;
-               case TokenType.ASSIGN_BITWISE_AND: return AssignmentOperator.BITWISE_AND;
-               case TokenType.ASSIGN_BITWISE_XOR: return AssignmentOperator.BITWISE_XOR;
-               case TokenType.ASSIGN_DIV:         return AssignmentOperator.DIV;
-               case TokenType.ASSIGN_MUL:         return AssignmentOperator.MUL;
-               case TokenType.ASSIGN_PERCENT:     return AssignmentOperator.PERCENT;
-               case TokenType.ASSIGN_SHIFT_LEFT:  return AssignmentOperator.SHIFT_LEFT;
-               default:                           return AssignmentOperator.NONE;
+               case TokenType.ASSIGN:                          return AssignmentOperator.SIMPLE;
+               case TokenType.ASSIGN_ADD:                      return AssignmentOperator.ADD;
+               case TokenType.ASSIGN_SUB:                      return AssignmentOperator.SUB;
+               case TokenType.ASSIGN_BITWISE_OR:       return AssignmentOperator.BITWISE_OR;
+               case TokenType.ASSIGN_BITWISE_AND:      return AssignmentOperator.BITWISE_AND;
+               case TokenType.ASSIGN_BITWISE_XOR:      return AssignmentOperator.BITWISE_XOR;
+               case TokenType.ASSIGN_DIV:                      return AssignmentOperator.DIV;
+               case TokenType.ASSIGN_MUL:                      return AssignmentOperator.MUL;
+               case TokenType.ASSIGN_PERCENT:          return AssignmentOperator.PERCENT;
+               case TokenType.ASSIGN_SHIFT_LEFT:       return AssignmentOperator.SHIFT_LEFT;
+               default:                                                        return AssignmentOperator.NONE;
                }
        }
 
@@ -1579,6 +1616,8 @@ public class Vala.Genie.Parser : CodeVisitor {
                        var lambda = parse_lambda_expression ();
                        current_expr_is_lambda = true;
                        return lambda;
+               } else {
+                       current_expr_is_lambda = false;
                }
 
                var begin = get_location ();
@@ -1636,8 +1675,8 @@ public class Vala.Genie.Parser : CodeVisitor {
 
        void parse_statements (Block block) throws ParseError {
                while (current () != TokenType.DEDENT
-                      && current () != TokenType.WHEN
-                      && current () != TokenType.DEFAULT) {
+                          && current () != TokenType.WHEN
+                          && current () != TokenType.DEFAULT) {
                        try {
                                Statement stmt = null;
                                bool is_decl = false;
@@ -1810,20 +1849,36 @@ public class Vala.Genie.Parser : CodeVisitor {
                switch (current ()) {
                case TokenType.PASS:
                case TokenType.SEMICOLON: return parse_empty_statement ();
-               case TokenType.IF:        return parse_if_statement ();
-               case TokenType.CASE:      return parse_switch_statement ();
-               case TokenType.WHILE:     return parse_while_statement ();
-               case TokenType.DO:        return parse_do_statement ();
-               case TokenType.FOR:       return get_for_statement_type ();
-               case TokenType.BREAK:     return parse_break_statement ();
+               case TokenType.IF:              return parse_if_statement ();
+               case TokenType.CASE:      return parse_switch_statement ();
+               case TokenType.WHILE:    return parse_while_statement ();
+               case TokenType.DO:              return parse_do_statement ();
+               case TokenType.FOR:        return get_for_statement_type ();
+               case TokenType.BREAK:    return parse_break_statement ();
                case TokenType.CONTINUE:  return parse_continue_statement ();
-               case TokenType.RETURN:    return parse_return_statement ();
-               case TokenType.YIELD:     return parse_yield_statement ();
-               case TokenType.RAISE:     return parse_throw_statement ();
-               case TokenType.TRY:       return parse_try_statement ();
-               case TokenType.LOCK:      return parse_lock_statement ();
-               case TokenType.DELETE:    return parse_delete_statement ();
-               default:                  return parse_expression_statement ();
+               case TokenType.RETURN:  return parse_return_statement ();
+               case TokenType.YIELD:    return parse_yield_statement ();
+               case TokenType.RAISE:    return parse_throw_statement ();
+               case TokenType.TRY:        return parse_try_statement ();
+               case TokenType.LOCK:      return parse_lock_statement ();
+               case TokenType.DELETE:  return parse_delete_statement ();
+               case TokenType.VAR:
+               case TokenType.CONST:
+                       throw new ParseError.SYNTAX (get_error ("embedded statement cannot be declaration "));
+               case TokenType.OP_INC:
+               case TokenType.OP_DEC:
+               case TokenType.SUPER:
+               case TokenType.THIS:
+               case TokenType.OPEN_PARENS:
+               case TokenType.STAR:
+               case TokenType.NEW:
+                       return parse_expression_statement ();
+               default:
+                       if (is_expression ()) {
+                               return parse_expression_statement ();
+                       } else {
+                               throw new ParseError.SYNTAX (get_error ("embedded statement cannot be declaration"));
+                       }
                }
        }
 
@@ -1890,7 +1945,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 
                expect (TokenType.COLON);
 
-               variable_type = parse_type ();
+               variable_type = parse_type (true, true);
                var type = parse_inline_array_type (variable_type);
 
                foreach (string id in id_list) {
@@ -2067,7 +2122,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                        } else {
                                id = parse_identifier ();
                                expect (TokenType.COLON);
-                               variable_type = parse_type ();
+                               variable_type = parse_type (true, true);
                        }
                        
                        DataType type_copy = null;
@@ -2137,7 +2192,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                } else {
                        id = parse_identifier ();
                        if (accept (TokenType.COLON)) {
-                               type = parse_type ();
+                               type = parse_type (true, true);
                        }
                }
 
@@ -2229,7 +2284,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                        if (!accept (TokenType.EOL)) {
                                id = parse_identifier ();
                                expect (TokenType.COLON);
-                               type = parse_type ();
+                               type = parse_type (true, true);
                                expect (TokenType.EOL);
                                
                        }
@@ -2320,6 +2375,9 @@ public class Vala.Genie.Parser : CodeVisitor {
        void set_attributes (CodeNode node, List<Attribute>? attributes) {
                if (attributes != null) {
                        foreach (Attribute attr in (List<Attribute>) attributes) {
+                               if (node.get_attribute (attr.name) != null) {
+                                       Report.error (attr.source_reference, "duplicate attribute `%s`".printf (attr.name));
+                               }
                                node.attributes.append (attr);
                        }
                }
@@ -2572,12 +2630,12 @@ public class Vala.Genie.Parser : CodeVisitor {
                var type_param_list = parse_type_parameter_list ();
                var base_types = new ArrayList<DataType> ();
                if (accept (TokenType.COLON)) {
-                       var type1 = parse_type ();
+                       var type1 = parse_type (true, false);
                        base_types.add (type1);
                        
                        if (accept (TokenType.IMPLEMENTS)) {
                                do {
-                                       var type2 = parse_type ();
+                                       var type2 = parse_type (true, true);
                                        base_types.add (type2);
                                } while (accept (TokenType.COMMA));
                        }
@@ -2615,7 +2673,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 
                // ensure there is always a default construction method
                if (scanner.source_file.file_type == SourceFileType.SOURCE
-                   && cl.default_construction_method == null) {
+                       && cl.default_construction_method == null) {
                        var m = new CreationMethod (cl.name, null, cl.source_reference);
                        m.access = SymbolAccessibility.PUBLIC;
                        m.body = new Block (cl.source_reference);
@@ -2709,7 +2767,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                string id = parse_identifier ();
        
                expect (TokenType.COLON);
-               var type = parse_type (false);
+               var type = parse_type (false, false);
                type = parse_inline_array_type (type);
 
                Expression initializer = null;
@@ -2745,7 +2803,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 
                var flags = parse_member_declaration_modifiers ();
 
-               var type = parse_type ();
+               var type = parse_type (true, true);
                
                type = parse_inline_array_type (type);
 
@@ -2753,7 +2811,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 
                if (ModifierFlags.ABSTRACT in flags || ModifierFlags.VIRTUAL in flags || ModifierFlags.OVERRIDE in flags) {
                        Report.error (f.source_reference, "abstract, virtual, and override modifiers are not applicable to fields");
-                }
+               }
 
                if (ModifierFlags.PRIVATE in flags) {
                        f.access = SymbolAccessibility.PRIVATE;
@@ -2861,7 +2919,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 
                /* deal with return value */
                if (accept (TokenType.COLON)) {
-                       type = parse_type ();
+                       type = parse_type (true, false);
                }
                
                var type_param_list = parse_type_parameter_list ();
@@ -2887,7 +2945,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 
                if (accept (TokenType.RAISES)) {
                        do {
-                               method.add_error_type (parse_type ());
+                               method.add_error_type (parse_type (true, false));
                        } while (accept (TokenType.COMMA));
                }
 
@@ -2916,14 +2974,14 @@ public class Vala.Genie.Parser : CodeVisitor {
                                method.overrides = true;
                        }
                        if ((method.is_abstract && method.is_virtual)
-                           || (method.is_abstract && method.overrides)
-                           || (method.is_virtual && method.overrides)) {
+                               || (method.is_abstract && method.overrides)
+                               || (method.is_virtual && method.overrides)) {
                                throw new ParseError.SYNTAX (get_error ("only one of `abstract', `virtual', or `override' may be specified"));
                        }
                } else {
                        if (ModifierFlags.ABSTRACT in flags
-                           || ModifierFlags.VIRTUAL in flags
-                           || ModifierFlags.OVERRIDE in flags) {
+                               || ModifierFlags.VIRTUAL in flags
+                               || ModifierFlags.OVERRIDE in flags) {
                                throw new ParseError.SYNTAX (get_error ("the modifiers `abstract', `virtual', and `override' are not valid for static methods"));
                        }
                }
@@ -3001,7 +3059,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                string id = parse_identifier ();
                expect (TokenType.COLON);
 
-               var type = parse_type (false);
+               var type = parse_type (true, true);
 
                var prop = new Property (id, type, null, null, get_src (begin), comment);
                if (ModifierFlags.PRIVATE in flags) {
@@ -3152,7 +3210,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                expect (TokenType.CLOSE_PARENS);
 
                if (accept (TokenType.COLON)) {
-                       type = parse_type ();
+                       type = parse_type (true, false);
                } else {
                        type = new VoidType ();
                }
@@ -3225,7 +3283,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                var type_param_list = parse_type_parameter_list ();
                DataType base_type = null;
                if (accept (TokenType.COLON)) {
-                       base_type = parse_type ();
+                       base_type = parse_type (true, false);
                }
 
                var st = new Struct (sym.name, get_src (begin), comment);
@@ -3268,6 +3326,8 @@ public class Vala.Genie.Parser : CodeVisitor {
                        st.add_field ((Field) sym);
                } else if (sym is Constant) {
                        st.add_constant ((Constant) sym);
+               } else if (sym is Property) {
+                       st.add_property ((Property) sym);       
                } else {
                        Report.error (sym.source_reference, "unexpected declaration in struct");
                }
@@ -3283,7 +3343,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                var base_types = new ArrayList<DataType> ();
                if (accept (TokenType.COLON)) {
                        do {
-                               var type = parse_type ();
+                               var type = parse_type (true, false);
                                base_types.add (type);
                        } while (accept (TokenType.COMMA));
                }
@@ -3370,7 +3430,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                expect (TokenType.EOL);
                expect (TokenType.INDENT);
                do {
-                       if (current () == TokenType.DEDENT) {
+                       if (current () == TokenType.DEDENT && en.get_values ().size > 0) {
                                // allow trailing comma
                                break;
                        }
@@ -3427,7 +3487,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                expect (TokenType.INDENT);
 
                do {
-                       if (current () == TokenType.DEDENT) {
+                       if (current () == TokenType.DEDENT && ed.get_codes ().size > 0) {
                                // allow trailing comma
                                break;
                        }
@@ -3524,6 +3584,10 @@ public class Vala.Genie.Parser : CodeVisitor {
                                next ();
                                flags |= ModifierFlags.OVERRIDE;
                                break;
+                       case TokenType.SEALED:
+                               next ();
+                               flags |= ModifierFlags.SEALED;
+                               break;  
                        case TokenType.STATIC:
                                next ();
                                flags |= ModifierFlags.STATIC;
@@ -3563,9 +3627,13 @@ public class Vala.Genie.Parser : CodeVisitor {
 
                DataType type;
                if (direction == ParameterDirection.IN) {
-                        type = parse_type (false);
+                        type = parse_type (false, false);
+               } else if (direction == ParameterDirection.REF) {
+                       // ref parameters own the value by default
+                       type = parse_type (true, true);
                } else {
-                        type = parse_type (true);
+                       // out parameters own the value by default
+                       type = parse_type (true, false);
                }
 
                var param = new Parameter (id, type, get_src (begin));
@@ -3612,7 +3680,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                expect (TokenType.CLOSE_PARENS);
                if (accept (TokenType.RAISES)) {
                        do {
-                               method.add_error_type (parse_type ());
+                               method.add_error_type (parse_type (true, false));
                        } while (accept (TokenType.COMMA));
                }
                method.access = SymbolAccessibility.PUBLIC;
@@ -3656,7 +3724,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                expect (TokenType.CLOSE_PARENS);
 
                if (accept (TokenType.COLON)) {
-                       type = parse_type ();
+                       type = parse_type (true, false);
                        
                } else {
                        type = new VoidType ();
@@ -3666,7 +3734,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 
                if (accept (TokenType.RAISES)) {
                        do {
-                               d.add_error_type (parse_type ());
+                               d.add_error_type (parse_type (true, false));
                        } while (accept (TokenType.COMMA));
                }
 
@@ -3732,20 +3800,20 @@ public class Vala.Genie.Parser : CodeVisitor {
 
        void skip_type_argument_list () throws ParseError {
                if (accept (TokenType.OF)) {
-               if (accept (TokenType.OPEN_PARENS)) {
-                           do {
-                           skip_type ();
-                           } while (accept (TokenType.COMMA));
-                           expect (TokenType.CLOSE_PARENS);
-               } else {
-                           do {
-                           skip_type ();
-                           } while (accept (TokenType.COMMA));
+                       if (accept (TokenType.OPEN_PARENS)) {
+                               do {
+                                       skip_type ();
+                               } while (accept (TokenType.COMMA));
+                               expect (TokenType.CLOSE_PARENS);
+                       } else {
+                               do {
+                                       skip_type ();
+                               } while (accept (TokenType.COMMA));
                        }
                }
        }
 
-    
+       
        // try to parse type argument list
        List<DataType>? parse_type_argument_list (bool maybe_expression) throws ParseError {
                var begin = get_location ();
@@ -3756,28 +3824,28 @@ public class Vala.Genie.Parser : CodeVisitor {
                        // Optional parens allow multi arg types in function signature: "dict of (int, string)"
                        // See: https://bugzilla.gnome.org/show_bug.cgi?id=611191
                        if (accept (TokenType.OPEN_PARENS)) {
-                           inParens = true;
-                       }
-                                               
-                   do {
-                           switch (current ()) {
-                           case TokenType.VOID:
-                           case TokenType.DYNAMIC:
-                           case TokenType.UNOWNED:
-                           case TokenType.WEAK:
-                           case TokenType.IDENTIFIER:
-                                   var type = parse_type ();
-
-                                   list.add (type);
-                                   break;
-                           default:
-                                   rollback (begin);
-                                   return null;
-                           }
-                   } while (accept (TokenType.COMMA));
-                   
-                   if (inParens) {
-                           expect (TokenType.CLOSE_PARENS);
+                               inParens = true;
+                       }
+                                                       
+                       do {
+                               switch (current ()) {
+                               case TokenType.VOID:
+                               case TokenType.DYNAMIC:
+                               case TokenType.UNOWNED:
+                               case TokenType.WEAK:
+                               case TokenType.IDENTIFIER:
+                                       var type = parse_type (true, true);
+
+                                       list.add (type);
+                                       break;
+                               default:
+                                       rollback (begin);
+                                       return null;
+                               }
+                       } while (accept (TokenType.COMMA));
+                       
+                       if (inParens) {
+                               expect (TokenType.CLOSE_PARENS);
                        }
 
                        return list;
index 5f73ba483f7c6ff395b6ee0f86e53d56e86f94ef..e2c5466b54664c26c64f5bddc63344d274f72afd 100644 (file)
@@ -283,7 +283,7 @@ public class Vala.Genie.Scanner {
                state_stack = null;
        }
 
-       TokenType get_identifier_or_keyword (char* begin, int len) {
+       public static TokenType get_identifier_or_keyword (char* begin, int len) {
                switch (len) {
                case 2:
                        switch (begin[0]) {
@@ -538,6 +538,9 @@ public class Vala.Genie.Scanner {
                                break;
                        case 's':
                                switch (begin[1]) {
+                               case 'e':
+                                       if (matches (begin, "sealed")) return TokenType.SEALED;
+                                       break;
                                case 'i':
                                        if (matches (begin, "sizeof")) return TokenType.SIZEOF;
                                        break;
@@ -736,7 +739,10 @@ public class Vala.Genie.Scanner {
                                                        break;
                                                }
                                        } else if (current[0] == '\n') {
-                                               break;
+                                               current++;
+                                               line++;
+                                               column = 1;
+                                               token_length_in_chars = 1;
                                        } else {
                                                unichar u = ((string) current).get_char_validated ((long) (end - current));
                                                if (u != (unichar) (-1)) {
@@ -748,7 +754,7 @@ public class Vala.Genie.Scanner {
                                                }
                                        }
                                }
-                               if (current >= end || current[0] == '\n') {
+                               if (current >= end) {
                                        Report.error (get_source_reference (token_length_in_chars), "syntax error, expected \"");
                                        state_stack.length--;
                                        return read_token (out token_begin, out token_end);
@@ -817,7 +823,7 @@ public class Vala.Genie.Scanner {
                
                /* handle automatic line continuations (when inside parens or braces) */
                while (current < end && current[0] == '\n' && (open_parens_count > 0 || open_brace_count > 0)) {
-                   current++;
+                       current++;
                        line++;
                        skip_space_tabs ();
                }
@@ -941,7 +947,7 @@ public class Vala.Genie.Scanner {
                                }
                                type = TokenType.REAL_LITERAL;
                        } else if (current < end && current == begin + 1
-                                  && begin[0] == '0' && begin[1] == 'x' && begin[2].isxdigit ()) {
+                                          && begin[0] == '0' && begin[1] == 'x' && begin[2].isxdigit ()) {
                                // hexadecimal integer literal
                                current++;
                                while (current < end && current[0].isxdigit ()) {
@@ -1176,7 +1182,6 @@ public class Vala.Genie.Scanner {
                                case TokenType.COMMA:
                                case TokenType.MINUS:
                                case TokenType.OP_AND:
-                               case TokenType.OP_DEC:
                                case TokenType.OP_EQ:
                                case TokenType.OP_GE:
                                case TokenType.OP_GT:
@@ -1222,7 +1227,7 @@ public class Vala.Genie.Scanner {
                                        token_length_in_chars = 6;
                                        current += 3;
                                        while (current < end - 4) {
-                                               if (current[0] == '"' && current[1] == '"' && current[2] == '"') {
+                                               if (current[0] == '"' && current[1] == '"' && current[2] == '"' && current[3] != '"') {
                                                        break;
                                                } else if (current[0] == '\n') {
                                                        current++;
@@ -1285,7 +1290,10 @@ public class Vala.Genie.Scanner {
                                                        break;
                                                }
                                        } else if (current[0] == '\n') {
-                                               break;
+                                               current++;
+                                               line++;
+                                               column = 1;
+                                               token_length_in_chars = 1;
                                        } else {
                                                unichar u = ((string) current).get_char_validated ((long) (end - current));
                                                if (u != (unichar) (-1)) {
@@ -1296,8 +1304,12 @@ public class Vala.Genie.Scanner {
                                                        Report.error (get_source_reference (token_length_in_chars), "invalid UTF-8 character");
                                                }
                                        }
+                                       if (current < end && begin[0] == '\'' && current[0] != '\'') {
+                                               // multiple characters in single character literal
+                                               Report.error (get_source_reference (token_length_in_chars), "invalid character literal");
+                                       }
                                }
-                               if (current < end && current[0] != '\n') {
+                               if (current < end) {
                                        current++;
                                } else {
                                        Report.error (get_source_reference (token_length_in_chars), "syntax error, expected %c".printf (begin[0]));
@@ -1313,7 +1325,6 @@ public class Vala.Genie.Scanner {
                                        Report.error (get_source_reference (0), "invalid UTF-8 character");
                                }
                                column++;
-                               last_token = TokenType.STRING_LITERAL;
                                return read_token (out token_begin, out token_end);
                        }
                }
@@ -1363,7 +1374,7 @@ public class Vala.Genie.Scanner {
                return tab_count;
        }
 
-       bool matches (char* begin, string keyword) {
+       static bool matches (char* begin, string keyword) {
                char* keyword_array = (char *) keyword;
                long len = keyword.length;
                for (int i = 0; i < len; i++) {
@@ -1416,9 +1427,10 @@ public class Vala.Genie.Scanner {
        }
 
        bool comment (bool file_comment = false) {
-               if (current > end - 2
-                   || current[0] != '/'
-                   || (current[1] != '/' && current[1] != '*')) {
+               if (current == null
+                       || current > end - 2
+                       || current[0] != '/'
+                       || (current[1] != '/' && current[1] != '*')) {
                        return false;
                }
 
@@ -1457,7 +1469,7 @@ public class Vala.Genie.Scanner {
                                return false;
                        }
 
-            if (current[2] == '*' || file_comment) {
+                       if (current[2] == '*' || file_comment) {
                                source_reference = get_source_reference (0);
                        }
 
@@ -1465,7 +1477,7 @@ public class Vala.Genie.Scanner {
                        char* begin = current;
 
                        while (current < end - 1
-                              && (current[0] != '*' || current[1] != '/')) {
+                                  && (current[0] != '*' || current[1] != '/')) {
                                if (current[0] == '\n') {
                                        line++;
                                        column = 0;
@@ -1512,7 +1524,7 @@ public class Vala.Genie.Scanner {
                }
        }
 
-    public void parse_file_comments () {
+       public void parse_file_comments () {
                while (whitespace () || comment (true)) {
                }
                
@@ -1520,6 +1532,10 @@ public class Vala.Genie.Scanner {
 
        void push_comment (string comment_item, SourceReference source_reference, bool file_comment) {
                if (comment_item[0] == '*') {
+                       if (_comment != null) {
+                               // extra doc comment, add it to source file comments
+                               source_file.add_comment (_comment);
+                       }
                        _comment = new Comment (comment_item, source_reference);
                }
 
@@ -1554,12 +1570,17 @@ public class Vala.Genie.Scanner {
                return found;
        }
 
+       void pp_space () {
+               while (pp_whitespace () || comment ()) {
+               }
+       }
+
        void pp_directive () {
                // hash sign
                current++;
                column++;
 
-               pp_whitespace ();
+               pp_space ();
 
                char* begin = current;
                int len = 0;
@@ -1582,11 +1603,11 @@ public class Vala.Genie.Scanner {
                }
 
                if (conditional_stack.length > 0
-                   && conditional_stack[conditional_stack.length - 1].skip_section) {
+                       && conditional_stack[conditional_stack.length - 1].skip_section) {
                        // skip lines until next preprocessing directive
                        bool bol = false;
                        while (current < end) {
-                               if (bol && current[0] == '#') {
+                               if (bol && current < end && current[0] == '#') {
                                        // go back to begin of line
                                        current -= (column - 1);
                                        column = 1;
@@ -1606,14 +1627,14 @@ public class Vala.Genie.Scanner {
        }
 
        void pp_eol () {
-               pp_whitespace ();
+               pp_space ();
                if (current >= end || current[0] != '\n') {
                        Report.error (get_source_reference (0), "syntax error, expected newline");
                }
        }
 
        void parse_pp_if () {
-               pp_whitespace ();
+               pp_space ();
 
                bool condition = parse_pp_expression ();
 
@@ -1631,7 +1652,7 @@ public class Vala.Genie.Scanner {
        }
 
        void parse_pp_elif () {
-               pp_whitespace ();
+               pp_space ();
 
                bool condition = parse_pp_expression ();
 
@@ -1643,7 +1664,7 @@ public class Vala.Genie.Scanner {
                }
 
                if (condition && !conditional_stack[conditional_stack.length - 1].matched
-                   && (conditional_stack.length == 1 || !conditional_stack[conditional_stack.length - 2].skip_section)) {
+                       && (conditional_stack.length == 1 || !conditional_stack[conditional_stack.length - 2].skip_section)) {
                        // condition true => process code within if
                        conditional_stack[conditional_stack.length - 1].matched = true;
                        conditional_stack[conditional_stack.length - 1].skip_section = false;
@@ -1662,7 +1683,7 @@ public class Vala.Genie.Scanner {
                }
 
                if (!conditional_stack[conditional_stack.length - 1].matched
-                   && (conditional_stack.length == 1 || !conditional_stack[conditional_stack.length - 2].skip_section)) {
+                       && (conditional_stack.length == 1 || !conditional_stack[conditional_stack.length - 2].skip_section)) {
                        // condition true => process code within if
                        conditional_stack[conditional_stack.length - 1].matched = true;
                        conditional_stack[conditional_stack.length - 1].skip_section = false;
@@ -1717,9 +1738,9 @@ public class Vala.Genie.Scanner {
                } else if (current[0] == '(') {
                        current++;
                        column++;
-                       pp_whitespace ();
+                       pp_space ();
                        bool result = parse_pp_expression ();
-                       pp_whitespace ();
+                       pp_space ();
                        if (current < end && current[0] ==  ')') {
                                current++;
                                column++;
@@ -1737,7 +1758,7 @@ public class Vala.Genie.Scanner {
                if (current < end && current[0] == '!') {
                        current++;
                        column++;
-                       pp_whitespace ();
+                       pp_space ();
                        return !parse_pp_unary_expression ();
                }
 
@@ -1746,18 +1767,18 @@ public class Vala.Genie.Scanner {
 
        bool parse_pp_equality_expression () {
                bool left = parse_pp_unary_expression ();
-               pp_whitespace ();
+               pp_space ();
                while (true) {
                        if (current < end - 1 && current[0] == '=' && current[1] == '=') {
                                current += 2;
                                column += 2;
-                               pp_whitespace ();
+                               pp_space ();
                                bool right = parse_pp_unary_expression ();
                                left = (left == right);
                        } else if (current < end - 1 && current[0] == '!' && current[1] == '=') {
                                current += 2;
                                column += 2;
-                               pp_whitespace ();
+                               pp_space ();
                                bool right = parse_pp_unary_expression ();
                                left = (left != right);
                        } else {
@@ -1769,11 +1790,11 @@ public class Vala.Genie.Scanner {
 
        bool parse_pp_and_expression () {
                bool left = parse_pp_equality_expression ();
-               pp_whitespace ();
+               pp_space ();
                while (current < end - 1 && current[0] == '&' && current[1] == '&') {
                        current += 2;
                        column += 2;
-                       pp_whitespace ();
+                       pp_space ();
                        bool right = parse_pp_equality_expression ();
                        left = left && right;
                }
@@ -1782,11 +1803,11 @@ public class Vala.Genie.Scanner {
 
        bool parse_pp_or_expression () {
                bool left = parse_pp_and_expression ();
-               pp_whitespace ();
+               pp_space ();
                while (current < end - 1 && current[0] == '|' && current[1] == '|') {
                        current += 2;
                        column += 2;
-                       pp_whitespace ();
+                       pp_space ();
                        bool right = parse_pp_and_expression ();
                        left = left || right;
                }
index fb8f54f6e1875db1811405e44a53c1897cffaa52..920a96af80aa10c6baceb7bb0df5bb8760ccde4e 100644 (file)
@@ -1,6 +1,6 @@
 /* valagenietokentype.vala
  *
- * Copyright (C) 2008  Jamie McCracken, Jürg Billeter
+ * Copyright (C) 2008-2012  Jamie McCracken, Jürg Billeter
  * Based on code by Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
@@ -137,12 +137,13 @@ public enum Vala.Genie.TokenType {
        PUBLIC,
        RAISE,
        RAISES,
-       REAL_LITERAL,
        READONLY,
+       REAL_LITERAL,
        REF,
        REGEX_LITERAL,
        REQUIRES,
        RETURN,
+       SEALED,
        SEMICOLON,
        SET,
        SIZEOF,
@@ -253,7 +254,7 @@ public enum Vala.Genie.TokenType {
                case NULL: return "`null'";
                case OF: return "`of'";         
                case OUT: return "`out'";
-               case OP_AND: return "`&&'";
+               case OP_AND: return "`and'";
                case OP_DEC: return "`--'";
                case OP_EQ: return "`=='";
                case OP_GE: return "`>='";
@@ -263,7 +264,7 @@ public enum Vala.Genie.TokenType {
                case OP_LT: return "`<'";
                case OP_NE: return "`!='";
                case OP_NEG: return "`!'";
-               case OP_OR: return "`||'";
+               case OP_OR: return "`or'";
                case OP_PTR: return "`->'";
                case OP_SHIFT_LEFT: return "`<<'";
                case OPEN_BRACE: return "`{'";
@@ -289,6 +290,7 @@ public enum Vala.Genie.TokenType {
                case REGEX_LITERAL: return "regex literal";
                case REQUIRES: return "`requires'";
                case RETURN: return "`return'";
+               case SEALED: return "`sealed'";
                case SEMICOLON: return "`;'";
                case SET: return "`set'";
                case SIZEOF: return "`sizeof'";