[vala/wip/printer: 1/3] WIP parser: Create bi-directional list of source-references for source-file



commit 31eeac1fcbdfaad8a4653319020df59dcf149484
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Thu Apr 9 18:15:38 2020 +0200

    WIP parser: Create bi-directional list of source-references for source-file
    
    Add first/last source-reference to SourceFile as starting point and
    prev/next source-reference to SourceReference to walk through the created
    syntax-tree.

 vala/valaparser.vala          | 74 +++++++++++++++++++++++++++++++++++++++++--
 vala/valasourcefile.vala      | 10 ++++++
 vala/valasourcereference.vala | 10 ++++++
 3 files changed, 91 insertions(+), 3 deletions(-)
---
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 48818a293..e6f8adec5 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -39,6 +39,8 @@ public class Vala.Parser : CodeVisitor {
 
        Comment comment;
 
+       weak SourceReference? previous_reference;
+
        const int BUFFER_SIZE = 32;
 
        static List<TypeParameter> _empty_type_parameter_list;
@@ -179,6 +181,27 @@ public class Vala.Parser : CodeVisitor {
                return new SourceReference (scanner.source_file, token.begin, token.end);
        }
 
+       void link_src (CodeNode node, SourceReference? insert_at = null) {
+               unowned SourceReference src = node.source_reference;
+               assert (src != null);
+
+               if (previous_reference != insert_at && insert_at != null) {
+                       unowned SourceReference? next = insert_at.next;
+                       insert_at.next = src;
+                       src.prev = insert_at;
+                       src.next = next;
+                       return;
+               }
+
+               if (previous_reference == null) {
+                       src.file.first = src;
+               } else {
+                       previous_reference.next = src;
+                       src.prev = previous_reference;
+               }
+               previous_reference = src;
+       }
+
        void rollback (SourceLocation location) {
                while (tokens[index].begin.pos != location.pos) {
                        index = (index - 1 + BUFFER_SIZE) % BUFFER_SIZE;
@@ -359,6 +382,7 @@ public class Vala.Parser : CodeVisitor {
                scanner = new Scanner (source_file);
                parse_file_comments ();
 
+               previous_reference = null;
                index = -1;
                size = 0;
 
@@ -378,6 +402,10 @@ public class Vala.Parser : CodeVisitor {
                        report_parse_error (e);
                }
 
+               if (previous_reference != null) {
+                       source_file.last = previous_reference;
+               }
+
                scanner = null;
                if (!has_global_context) {
                        context = null;
@@ -639,6 +667,8 @@ public class Vala.Parser : CodeVisitor {
 
                Expression expr;
 
+               unowned SourceReference? current_reference = previous_reference;
+
                switch (current ()) {
                case TokenType.TRUE:
                case TokenType.FALSE:
@@ -718,6 +748,8 @@ public class Vala.Parser : CodeVisitor {
                        }
                }
 
+               link_src (expr, current_reference);
+
                return expr;
        }
 
@@ -1562,6 +1594,7 @@ public class Vala.Parser : CodeVisitor {
                        try {
                                Statement stmt = null;
                                bool is_decl = false;
+                               unowned SourceReference? current_reference = previous_reference;
 
                                comment = scanner.pop_comment ();
                                switch (current ()) {
@@ -1645,6 +1678,7 @@ public class Vala.Parser : CodeVisitor {
 
                                if (!is_decl) {
                                        block.add_statement (stmt);
+                                       link_src (stmt, current_reference);
                                }
                        } catch (ParseError e) {
                                report_parse_error (e);
@@ -1754,9 +1788,11 @@ public class Vala.Parser : CodeVisitor {
                comment = scanner.pop_comment ();
 
                var block = new Block (get_src (get_location ()));
+               link_src (block);
 
                try {
                        var stmt = parse_embedded_statement_without_block (statement_name, accept_empty_body);
+                       link_src (stmt);
                        block.add_statement (stmt);
                } catch (ParseError e) {
                        if (context.keep_going) {
@@ -1817,6 +1853,7 @@ public class Vala.Parser : CodeVisitor {
                var begin = get_location ();
                expect (TokenType.OPEN_BRACE);
                var block = new Block (get_src (begin));
+               link_src (block);
                parse_statements (block);
                if (!accept (TokenType.CLOSE_BRACE)) {
                        // only report error if it's not a secondary error
@@ -1864,14 +1901,18 @@ public class Vala.Parser : CodeVisitor {
                                expect (TokenType.ASSIGN);
                                var tuple = parse_expression ();
                                var tuple_local = new LocalVariable (null, CodeNode.get_temp_name (), tuple, 
get_src (begin));
-                               block.add_statement (new DeclarationStatement (tuple_local, 
tuple_local.source_reference));
+                               var tuple_stmt = new DeclarationStatement (tuple_local, 
tuple_local.source_reference);
+                               link_src (tuple_stmt);
+                               block.add_statement (tuple_stmt);
 
                                for (int i = 0; i < identifiers.length; i++) {
                                        var temp_access = new MemberAccess.simple (tuple_local.name, 
tuple_local.source_reference);
                                        var ea = new ElementAccess (temp_access, 
tuple_local.source_reference);
                                        ea.append_index (new IntegerLiteral (i.to_string ()));
                                        var local = new LocalVariable (null, identifiers[i], ea, 
tuple_local.source_reference);
-                                       block.add_statement (new DeclarationStatement (local, 
local.source_reference));
+                                       var stmt = new DeclarationStatement (local, local.source_reference);
+                                       link_src (stmt);
+                                       block.add_statement (stmt);
                                }
 
                                continue;
@@ -1888,7 +1929,9 @@ public class Vala.Parser : CodeVisitor {
                                type_copy = variable_type.copy ();
                        }
                        var local = parse_local_variable (type_copy);
-                       block.add_statement (new DeclarationStatement (local, get_src (begin)));
+                       var stmt = new DeclarationStatement (local, get_src (begin));
+                       link_src (stmt);
+                       block.add_statement (stmt);
                } while (accept (TokenType.COMMA));
                expect (TokenType.SEMICOLON);
        }
@@ -2063,6 +2106,7 @@ public class Vala.Parser : CodeVisitor {
                                // variable declaration in initializer
                                var decl_begin = get_location ();
                                block = new Block (get_src (decl_begin));
+                               link_src (block);
                                parse_local_variable_declarations (block);
                                block.source_reference.end = get_last_src ().end;
                        }
@@ -2319,6 +2363,7 @@ public class Vala.Parser : CodeVisitor {
                method.access = SymbolAccessibility.PUBLIC;
                method.binding = MemberBinding.STATIC;
                method.body = new Block (get_src (begin));
+               link_src (method.body);
                parse_statements (method.body);
                if (current () != TokenType.EOF) {
                        Report.error (get_current_src (), "expected end of file");
@@ -2577,6 +2622,7 @@ public class Vala.Parser : CodeVisitor {
                expect (TokenType.NAMESPACE);
                var sym = parse_symbol_name ();
                var ns = new Namespace (sym.name, get_src (begin));
+               link_src (ns);
                if (comment != null) {
                        ns.add_comment (comment);
                        comment = null;
@@ -2616,6 +2662,7 @@ public class Vala.Parser : CodeVisitor {
                                var begin = get_location ();
                                var sym = parse_symbol_name ();
                                var ns_ref = new UsingDirective (sym, get_src (begin));
+                               link_src (ns_ref);
                                scanner.source_file.add_using_directive (ns_ref);
                                ns.add_using_directive (ns_ref);
                        } while (accept (TokenType.COMMA));
@@ -2638,6 +2685,7 @@ public class Vala.Parser : CodeVisitor {
                }
 
                var cl = new Class (sym.name, get_src (begin), comment);
+               link_src (cl);
                cl.access = access;
                if (ModifierFlags.ABSTRACT in flags) {
                        cl.is_abstract = true;
@@ -2689,6 +2737,7 @@ public class Vala.Parser : CodeVisitor {
                }
 
                var c = new Constant (id, type, null, get_src (begin), comment);
+               link_src (c);
                c.access = access;
                if (ModifierFlags.EXTERN in flags) {
                        c.is_extern = true;
@@ -2723,6 +2772,7 @@ public class Vala.Parser : CodeVisitor {
                type = parse_inline_array_type (type);
 
                var f = new Field (id, type, null, get_src (begin), comment);
+               link_src (f);
                f.access = access;
 
                set_attributes (f, attrs);
@@ -2796,6 +2846,7 @@ public class Vala.Parser : CodeVisitor {
                var sym = parse_symbol_name ();
                var type_param_list = parse_type_parameter_list ();
                var method = new Method (sym.name, type, get_src (begin), comment);
+               link_src (method);
                if (sym.inner != null) {
                        method.base_interface_type = new UnresolvedType.from_symbol (sym.inner, 
sym.inner.source_reference);
                }
@@ -2888,6 +2939,7 @@ public class Vala.Parser : CodeVisitor {
                var type = parse_type (true, true);
                string id = parse_identifier ();
                var prop = new Property (id, type, null, null, get_src (begin), comment);
+               link_src (prop);
                prop.access = access;
                set_attributes (prop, attrs);
                if (ModifierFlags.STATIC in flags && ModifierFlags.CLASS in flags) {
@@ -2935,6 +2987,7 @@ public class Vala.Parser : CodeVisitor {
                                }
                                expect (TokenType.ASSIGN);
                                prop.initializer = parse_expression ();
+                               link_src (prop.initializer);
                                expect (TokenType.SEMICOLON);
                        } else {
                                comment = scanner.pop_comment ();
@@ -2964,6 +3017,7 @@ public class Vala.Parser : CodeVisitor {
                                                prop.external = false;
                                        }
                                        prop.get_accessor = new PropertyAccessor (true, false, false, 
value_type, block, get_src (accessor_begin), comment);
+                                       link_src (prop.get_accessor);
                                        set_attributes (prop.get_accessor, accessor_attrs);
                                        prop.get_accessor.access = accessor_access;
                                } else {
@@ -2986,6 +3040,7 @@ public class Vala.Parser : CodeVisitor {
                                                prop.external = false;
                                        }
                                        prop.set_accessor = new PropertyAccessor (false, writable, 
_construct, value_type, block, get_src (accessor_begin), comment);
+                                       link_src (prop.set_accessor);
                                        set_attributes (prop.set_accessor, accessor_attrs);
                                        prop.set_accessor.access = accessor_access;
                                }
@@ -3004,6 +3059,7 @@ public class Vala.Parser : CodeVisitor {
                var type = parse_type (true, false);
                string id = parse_identifier ();
                var sig = new Signal (id, type, get_src (begin), comment);
+               link_src (sig);
                sig.access = access;
                set_attributes (sig, attrs);
                if (ModifierFlags.STATIC in flags) {
@@ -3040,6 +3096,7 @@ public class Vala.Parser : CodeVisitor {
                        throw new ParseError.SYNTAX ("`new' modifier not allowed on constructor");
                }
                var c = new Constructor (get_src (begin));
+               link_src (c);
                if (ModifierFlags.STATIC in flags && ModifierFlags.CLASS in flags) {
                        Report.error (c.source_reference, "only one of `static' or `class' may be specified");
                } else if (ModifierFlags.STATIC in flags) {
@@ -3063,6 +3120,7 @@ public class Vala.Parser : CodeVisitor {
                        throw new ParseError.SYNTAX ("`new' modifier not allowed on destructor");
                }
                var d = new Destructor (get_src (begin));
+               link_src (d);
                if (identifier != parent.name) {
                        Report.error (d.source_reference, "destructor and parent symbol name do not match");
                }
@@ -3090,6 +3148,7 @@ public class Vala.Parser : CodeVisitor {
                        base_type = parse_type (true, false);
                }
                var st = new Struct (sym.name, get_src (begin), comment);
+               link_src (st);
                st.access = access;
                if (ModifierFlags.EXTERN in flags) {
                        st.is_extern = true;
@@ -3133,6 +3192,7 @@ public class Vala.Parser : CodeVisitor {
                        } while (accept (TokenType.COMMA));
                }
                var iface = new Interface (sym.name, get_src (begin), comment);
+               link_src (iface);
                iface.access = access;
                if (ModifierFlags.EXTERN in flags) {
                        iface.is_extern = true;
@@ -3168,6 +3228,7 @@ public class Vala.Parser : CodeVisitor {
                expect (TokenType.ENUM);
                var sym = parse_symbol_name ();
                var en = new Enum (sym.name, get_src (begin), comment);
+               link_src (en);
                en.access = access;
                if (ModifierFlags.EXTERN in flags) {
                        en.is_extern = true;
@@ -3201,6 +3262,7 @@ public class Vala.Parser : CodeVisitor {
                        }
 
                        var ev = new EnumValue (id, value, get_src (value_begin), comment);
+                       link_src (ev);
                        ev.access = SymbolAccessibility.PUBLIC;
                        set_attributes (ev, value_attrs);
                        en.add_value (ev);
@@ -3235,6 +3297,7 @@ public class Vala.Parser : CodeVisitor {
                expect (TokenType.ERRORDOMAIN);
                var sym = parse_symbol_name ();
                var ed = new ErrorDomain (sym.name, get_src (begin), comment);
+               link_src (ed);
                ed.access = access;
                if (ModifierFlags.EXTERN in flags) {
                        ed.is_extern = true;
@@ -3263,6 +3326,7 @@ public class Vala.Parser : CodeVisitor {
                        }
 
                        var ec = new ErrorCode (id, get_src (code_begin), comment);
+                       link_src (ec);
                        set_attributes (ec, code_attrs);
                        if (accept (TokenType.ASSIGN)) {
                                ec.value = parse_expression ();
@@ -3414,6 +3478,7 @@ public class Vala.Parser : CodeVisitor {
                type = parse_inline_array_type (type);
 
                var param = new Parameter (id, type, get_src (begin));
+               link_src (param);
                set_attributes (param, attrs);
                param.direction = direction;
                param.params_array = params_array;
@@ -3437,6 +3502,7 @@ public class Vala.Parser : CodeVisitor {
                } else {
                        method = new CreationMethod (sym.inner.name, sym.name, get_src (begin), comment);
                }
+               link_src (method);
                if (ModifierFlags.EXTERN in flags) {
                        method.is_extern = true;
                }
@@ -3493,6 +3559,7 @@ public class Vala.Parser : CodeVisitor {
                var sym = parse_symbol_name ();
                var type_param_list = parse_type_parameter_list ();
                var d = new Delegate (sym.name, type, get_src (begin), comment);
+               link_src (d);
                d.access = access;
                set_attributes (d, attrs);
                if (ModifierFlags.STATIC in flags) {
@@ -3637,6 +3704,7 @@ public class Vala.Parser : CodeVisitor {
 
                        List<DataType> type_arg_list = parse_type_argument_list (false);
                        expr = new MemberAccess (expr != null ? expr : base_expr, id, get_src (begin));
+                       link_src (expr);
                        expr.qualified = qualified;
                        if (type_arg_list != null) {
                                foreach (DataType type_arg in type_arg_list) {
diff --git a/vala/valasourcefile.vala b/vala/valasourcefile.vala
index 2e270a06c..22d7263b4 100644
--- a/vala/valasourcefile.vala
+++ b/vala/valasourcefile.vala
@@ -88,6 +88,16 @@ public class Vala.SourceFile {
         */
        public SourceFileType file_type { get; set; }
 
+       /**
+        * The first source reference.
+        */
+       public weak SourceReference? first { get; set; }
+
+       /**
+        * The last source reference.
+        */
+       public weak SourceReference? last { get; set; }
+
        /**
         * Specifies whether this file came from the command line directly.
         */
diff --git a/vala/valasourcereference.vala b/vala/valasourcereference.vala
index be79e197e..9fb4e01e3 100644
--- a/vala/valasourcereference.vala
+++ b/vala/valasourcereference.vala
@@ -46,6 +46,16 @@ public class Vala.SourceReference {
         */
        public SourceLocation end { get; set; }
 
+       /**
+        * The previous source reference.
+        */
+       public weak SourceReference? prev { get; set; }
+
+       /**
+        * The next source reference.
+        */
+       public weak SourceReference? next { get; set; }
+
        public List<UsingDirective> using_directives { get; private set; }
 
        /**


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]