diff --git a/extractor/src/extractor.rs b/extractor/src/extractor.rs index 58565ae0e1a..0cb7c8073e7 100644 --- a/extractor/src/extractor.rs +++ b/extractor/src/extractor.rs @@ -259,12 +259,13 @@ struct Visitor<'a> { token_counter: usize, /// A lookup table from type name to node types schema: &'a NodeTypeMap, - /// A stack for gathering information from hild nodes. Whenever a node is entered - /// an empty list is pushed. All children append their data (field name, label, type) to - /// the the list. When the visitor leaves a node the list containing the child data is popped - /// from the stack and matched against the dbscheme for the node. If the expectations are met - /// the corresponding row definitions are added to the trap_output. - stack: Vec, Label, TypeName)>>, + /// A stack for gathering information from child nodes. Whenever a node is entered + /// the parent's [Label] and an empty list is pushed. All children append their data + /// (field name, label, type) to the the list. When the visitor leaves a node the list + /// containing the child data is popped from the stack and matched against the dbscheme + /// for the node. If the expectations are met the corresponding row definitions are + /// added to the trap_output. + stack: Vec<(Label, Vec<(Option<&'static str>, Label, TypeName)>)>, } impl Visitor<'_> { @@ -287,7 +288,9 @@ impl Visitor<'_> { return false; } - self.stack.push(Vec::new()); + let id = self.trap_writer.fresh_id(); + + self.stack.push((id, Vec::new())); return true; } @@ -295,11 +298,10 @@ impl Visitor<'_> { if node.is_error() || node.is_missing() { return; } - let child_nodes = self.stack.pop().expect("Vistor: empty stack"); - let id = self.trap_writer.fresh_id(); + let (id, child_nodes) = self.stack.pop().expect("Vistor: empty stack"); let (start_line, start_column, end_line, end_column) = location_for(&self.source, node); let loc = self.trap_writer.location( - self.file_label.clone(), + self.file_label, start_line, start_column, end_line, @@ -313,12 +315,17 @@ impl Visitor<'_> { }) .unwrap(); let mut valid = true; + let parent_id = match self.stack.last_mut() { + Some(p) if !node.is_extra() => p.0, + _ => self.file_label, + }; match &table.kind { EntryKind::Token { kind_id, .. } => { self.trap_writer.add_tuple( "tokeninfo", vec![ Arg::Label(id), + Arg::Label(parent_id), Arg::Int(*kind_id), Arg::Label(self.file_label), Arg::Int(self.token_counter), @@ -335,6 +342,7 @@ impl Visitor<'_> { if let Some(args) = self.complex_node(&node, fields, child_nodes, id) { let mut all_args = Vec::new(); all_args.push(Arg::Label(id)); + all_args.push(Arg::Label(parent_id)); all_args.extend(args); all_args.push(Arg::Label(loc)); self.trap_writer.add_tuple(&table_name, all_args); @@ -354,7 +362,7 @@ impl Visitor<'_> { // Extra nodes are independent root nodes and do not belong to the parent node // Therefore we should not register them in the parent vector if let Some(parent) = self.stack.last_mut() { - parent.push(( + parent.1.push(( field_name, id, TypeName { diff --git a/generator/src/main.rs b/generator/src/main.rs index 652209df6bd..f2b0f071312 100644 --- a/generator/src/main.rs +++ b/generator/src/main.rs @@ -136,7 +136,7 @@ fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec { @@ -155,13 +155,22 @@ fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec(nodes: &'a node_types::NodeTypeMap) -> Vec( ql_type: ql::Type::AtType("token"), ql_type_is_ref: false, }, + dbscheme::Column { + db_type: dbscheme::DbColumnType::Int, + name: "parent", + unique: false, + ql_type: ql::Type::AtType("ast_node_parent"), + ql_type_is_ref: true, + }, dbscheme::Column { unique: false, db_type: dbscheme::DbColumnType::Int, diff --git a/generator/src/ql_gen.rs b/generator/src/ql_gen.rs index 443a009abf9..35a1d6196ef 100644 --- a/generator/src/ql_gen.rs +++ b/generator/src/ql_gen.rs @@ -46,31 +46,7 @@ fn create_ast_node_class<'a>() -> ql::Class<'a> { create_none_predicate("getLocation", false, Some(ql::Type::Normal("Location"))); let get_a_field_or_child = create_none_predicate("getAFieldOrChild", false, Some(ql::Type::Normal("AstNode"))); - let get_parent = ql::Predicate { - name: "getParent", - overridden: false, - return_type: Some(ql::Type::Normal("AstNode")), - formal_parameters: vec![], - body: ql::Expression::Equals( - Box::new(ql::Expression::Var("result")), - Box::new(ql::Expression::Aggregate( - "unique", - vec![ql::FormalParameter { - name: "parent", - param_type: ql::Type::Normal("AstNode"), - }], - Box::new(ql::Expression::Equals( - Box::new(ql::Expression::Var("this")), - Box::new(ql::Expression::Dot( - Box::new(ql::Expression::Var("parent")), - "getAFieldOrChild", - vec![], - )), - )), - Box::new(ql::Expression::Var("parent")), - )), - ), - }; + let get_parent = create_none_predicate("getParent", false, Some(ql::Type::Normal("AstNode"))); let describe_ql_class = ql::Predicate { name: "describeQlClass", overridden: false, @@ -97,6 +73,24 @@ fn create_ast_node_class<'a>() -> ql::Class<'a> { } fn create_token_class<'a>() -> ql::Class<'a> { + let get_parent = ql::Predicate { + name: "getParent", + overridden: true, + return_type: Some(ql::Type::Normal("AstNode")), + formal_parameters: vec![], + body: ql::Expression::Pred( + "tokeninfo", + vec![ + ql::Expression::Var("this"), + ql::Expression::Var("result"), + ql::Expression::Var("_"), + ql::Expression::Var("_"), + ql::Expression::Var("_"), + ql::Expression::Var("_"), + ql::Expression::Var("_"), + ], + ), + }; let get_value = ql::Predicate { name: "getValue", overridden: false, @@ -109,6 +103,7 @@ fn create_token_class<'a>() -> ql::Class<'a> { ql::Expression::Var("_"), ql::Expression::Var("_"), ql::Expression::Var("_"), + ql::Expression::Var("_"), ql::Expression::Var("result"), ql::Expression::Var("_"), ], @@ -127,6 +122,7 @@ fn create_token_class<'a>() -> ql::Class<'a> { ql::Expression::Var("_"), ql::Expression::Var("_"), ql::Expression::Var("_"), + ql::Expression::Var("_"), ql::Expression::Var("result"), ], ), @@ -149,6 +145,7 @@ fn create_token_class<'a>() -> ql::Class<'a> { .collect(), characteristic_predicate: None, predicates: vec![ + get_parent, get_value, get_location, to_string, @@ -262,7 +259,7 @@ fn create_get_field_expr_for_column_storage<'a>( column_index: usize, arity: usize, ) -> ql::Expression<'a> { - let num_underscores_before = column_index - 1; + let num_underscores_before = column_index; let num_underscores_after = arity - 2 - num_underscores_before; ql::Expression::Pred( table_name, @@ -436,10 +433,11 @@ pub fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec(nodes: &'a node_types::NodeTypeMap) -> Vec