diff --git a/runtime-rust/src/ast.rs b/runtime-rust/src/ast.rs index b251757d..23e1065e 100644 --- a/runtime-rust/src/ast.rs +++ b/runtime-rust/src/ast.rs @@ -26,7 +26,6 @@ use crate::symbols::{SemanticElementTrait, Symbol}; use crate::text::{TextContext, TextPosition, TextSpan}; use crate::tokens::{Token, TokenRepository}; use crate::utils::biglist::BigList; -use crate::utils::EitherMut; /// Represents a type of symbol table #[derive(Debug, Copy, Clone, Eq, PartialEq)] @@ -53,7 +52,7 @@ impl From for TableType { } /// Represents a compact reference to an element in a table -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)] +#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)] pub struct TableElemRef { /// The backend data data: usize @@ -131,6 +130,25 @@ impl AstImpl { pub fn has_root(&self) -> bool { self.root.is_some() } + + /// Stores the root of this tree + pub fn store_root(&mut self, node: AstCell) { + self.root = Some(self.nodes.push(node)); + } + + /// Stores some children nodes in this AST + #[must_use] + pub fn store(&mut self, nodes: &[AstCell], index: usize, count: usize) -> usize { + if count == 0 { + 0 + } else { + let result = self.nodes.push(nodes[index]); + for i in 1..count { + self.nodes.push(nodes[index + i]); + } + result + } + } } /// Represents a simple AST with a tree structure @@ -138,13 +156,13 @@ impl AstImpl { /// The linkage is represented by each node storing its number of children and the index of its first child. pub struct Ast<'s, 't, 'a> { /// The table of tokens - tokens: Option>, + tokens: TokenRepository<'s, 't, 'a>, /// The table of variables - pub variables: &'a [Symbol<'s>], + variables: &'a [Symbol<'s>], /// The table of virtuals - pub virtuals: &'a [Symbol<'s>], + virtuals: &'a [Symbol<'s>], /// The data of the implementation - data: EitherMut<'a, AstImpl> + data: &'a AstImpl } impl<'s, 't, 'a> Ast<'s, 't, 'a> { @@ -157,33 +175,16 @@ impl<'s, 't, 'a> Ast<'s, 't, 'a> { data: &'a AstImpl ) -> Ast<'s, 't, 'a> { Ast { - tokens: Some(tokens), + tokens, variables, virtuals, - data: EitherMut::Immutable(data) - } - } - - /// Creates a new AST proxy structure - pub fn new_mut( - variables: &'a [Symbol<'s>], - virtuals: &'a [Symbol<'s>], - data: &'a mut AstImpl - ) -> Ast<'s, 't, 'a> { - Ast { - tokens: None, - variables, - virtuals, - data: EitherMut::Mutable(data) + data } } /// Gets the i-th token in the associated repository fn get_token(&'a self, index: usize) -> Token<'s, 't, 'a> { - self.tokens - .as_ref() - .expect("Missing token repository") - .get_token(index) + self.tokens.get_token(index) } /// Gets whether a root has been defined for this AST @@ -237,7 +238,6 @@ impl<'s, 't, 'a> Ast<'s, 't, 'a> { #[must_use] pub fn find_node_at_index(&self, index: usize) -> Option { self.tokens - .as_ref()? .find_token_at(index) .and_then(|token| self.find_node_for(&token)) } @@ -246,9 +246,8 @@ impl<'s, 't, 'a> Ast<'s, 't, 'a> { /// a token label that contains the specified index in the input text #[must_use] pub fn find_node_at_position(&self, position: TextPosition) -> Option { - let tokens = self.tokens.as_ref()?; - let index = tokens.text.get_line_index(position.line) + position.column - 1; - tokens + let index = self.tokens.text.get_line_index(position.line) + position.column - 1; + self.tokens .find_token_at(index) .and_then(|token| self.find_node_for(&token)) } @@ -317,7 +316,7 @@ impl<'s, 't, 'a> Ast<'s, 't, 'a> { for i in (0..cell.count).rev() { stack.push((cell.first + i) as usize); } - action(&self.data, current); + action(self.data, current); } } @@ -346,24 +345,6 @@ impl<'s, 't, 'a> Ast<'s, 't, 'a> { _ => None } } - - /// Stores some children nodes in this AST - pub fn store(&mut self, nodes: &[AstCell], index: usize, count: usize) -> usize { - if count == 0 { - 0 - } else { - let result = self.data.nodes.push(nodes[index]); - for i in 1..count { - self.data.nodes.push(nodes[index + i]); - } - result - } - } - - /// Stores the root of this tree - pub fn store_root(&mut self, node: AstCell) { - self.data.root = Some(self.data.nodes.push(node)); - } } /// Represents a node in an Abstract Syntax Tree @@ -439,12 +420,12 @@ impl<'s, 't, 'a> AstNode<'s, 't, 'a> { impl<'s, 't, 'a> SemanticElementTrait<'s, 'a> for AstNode<'s, 't, 'a> { /// Gets the position in the input text of this element fn get_position(&self) -> Option { - self.tree.get_position_at(&self.tree.data, self.index) + self.tree.get_position_at(self.tree.data, self.index) } /// Gets the span in the input text of this element fn get_span(&self) -> Option { - self.tree.get_span_at(&self.tree.data, self.index) + self.tree.get_span_at(self.tree.data, self.index) } /// Gets the context of this element in the input @@ -470,10 +451,8 @@ impl<'s, 't, 'a> SemanticElementTrait<'s, 'a> for AstNode<'s, 't, 'a> { TableType::Variable => self.tree.variables[cell.label.index()], TableType::Virtual => self.tree.virtuals[cell.label.index()], TableType::None => { - match &self.tree.tokens { - None => panic!("Missing token repository"), - Some(repository) => repository.terminals[0] // terminal epsilon - } + // terminal epsilon + self.tree.tokens.terminals[0] } } } @@ -531,12 +510,9 @@ impl<'s, 't, 'a> Display for AstNode<'s, 't, 'a> { let symbol = self.tree.virtuals[cell.label.index()]; write!(f, "{}", symbol.name) } - TableType::None => match &self.tree.tokens { - None => panic!("Missing token repository"), - Some(repository) => { - let symbol = repository.terminals[0]; - write!(f, "{}", symbol.name) - } + TableType::None => { + let symbol = self.tree.tokens.terminals[0]; + write!(f, "{}", symbol.name) } } } @@ -572,7 +548,7 @@ pub struct AstFamilyIterator<'s, 't, 'a> { tree: &'a Ast<'s, 't, 'a>, /// The index of the current child in the parse tree current: usize, - /// the index of the last child (excluded) in the parse tree + /// The index of the last child (excluded) in the parse tree end: usize } diff --git a/runtime-rust/src/lib.rs b/runtime-rust/src/lib.rs index 453f94e9..226361b7 100644 --- a/runtime-rust/src/lib.rs +++ b/runtime-rust/src/lib.rs @@ -50,6 +50,7 @@ pub mod errors; pub mod lexers; pub mod parsers; pub mod result; +pub mod sppf; pub mod symbols; pub mod text; pub mod tokens; diff --git a/runtime-rust/src/parsers/lrk.rs b/runtime-rust/src/parsers/lrk.rs index 220ff403..f02863f7 100644 --- a/runtime-rust/src/parsers/lrk.rs +++ b/runtime-rust/src/parsers/lrk.rs @@ -29,7 +29,7 @@ use super::{ TREE_ACTION_NONE, TREE_ACTION_PROMOTE, TREE_ACTION_REPLACE_BY_CHILDREN, TREE_ACTION_REPLACE_BY_EPSILON }; -use crate::ast::{Ast, TableElemRef, TableType}; +use crate::ast::{AstImpl, TableElemRef, TableType}; use crate::errors::ParseErrorUnexpectedToken; use crate::lexers::{Lexer, TokenKernel, DEFAULT_CONTEXT}; use crate::symbols::{SemanticBody, SemanticElement, SemanticElementTrait}; @@ -175,10 +175,14 @@ impl LRkAstReduction { struct LRkAstBuilder<'s, 't, 'a> { /// Lexer associated to this parser lexer: &'a mut Lexer<'s, 't, 'a>, + /// The table of variables + variables: &'a [Symbol<'s>], + /// The table of virtuals + virtuals: &'a [Symbol<'s>], /// The stack of semantic objects stack: Vec, /// The AST being built - result: Ast<'s, 't, 'a>, + result: &'a mut AstImpl, /// The reduction handle represented as the indices of the sub-trees in the cache handle: Vec, /// The data of the current reduction @@ -195,12 +199,8 @@ impl<'s, 't, 'a> SemanticBody for LRkAstBuilder<'s, 't, 'a> { TableType::Token => SemanticElement::Token( self.lexer.get_data().repository.get_token(label.index()) ), - TableType::Variable => { - SemanticElement::Variable(self.result.variables[label.index()]) - } - TableType::Virtual => { - SemanticElement::Virtual(self.result.virtuals[label.index()]) - } + TableType::Variable => SemanticElement::Variable(self.variables[label.index()]), + TableType::Virtual => SemanticElement::Virtual(self.virtuals[label.index()]), TableType::None => { SemanticElement::Terminal(self.lexer.get_data().repository.terminals[0]) } @@ -218,10 +218,14 @@ impl<'s, 't, 'a> LRkAstBuilder<'s, 't, 'a> { /// Initializes the builder with the given stack size pub fn new( lexer: &'a mut Lexer<'s, 't, 'a>, - result: Ast<'s, 't, 'a> + variables: &'a [Symbol<'s>], + virtuals: &'a [Symbol<'s>], + result: &'a mut AstImpl ) -> LRkAstBuilder<'s, 't, 'a> { LRkAstBuilder { lexer, + variables, + virtuals, stack: Vec::new(), result, handle: Vec::new(), @@ -321,7 +325,7 @@ impl<'s, 't, 'a> LRkAstBuilder<'s, 't, 'a> { if reduction.cache.get_action_at(0) == TREE_ACTION_REPLACE_BY_CHILDREN { reduction.cache.set_children_count_at(0, self.handle.len()); } else { - LRkAstBuilder::reduce_tree(reduction, &self.handle, &mut self.result); + LRkAstBuilder::reduce_tree(reduction, &self.handle, self.result); } // Put it on the stack self.stack.truncate(stack_size - reduction.length); @@ -333,7 +337,7 @@ impl<'s, 't, 'a> LRkAstBuilder<'s, 't, 'a> { } /// Applies the promotion tree actions to the cache and commits to the final AST - pub fn reduce_tree(reduction: &mut LRkAstReduction, handle: &[usize], result: &mut Ast) { + pub fn reduce_tree(reduction: &mut LRkAstReduction, handle: &[usize], result: &mut AstImpl) { // apply the epsilon replace, if any if reduction.cache.get_action_at(0) == TREE_ACTION_REPLACE_BY_EPSILON { reduction @@ -382,7 +386,7 @@ impl<'s, 't, 'a> LRkAstBuilder<'s, 't, 'a> { let length = self.stack.len(); if length > 1 { let head = &mut self.stack[length - 2]; - head.commit(&mut self.result); + head.commit(self.result); } } } @@ -580,7 +584,7 @@ impl<'s, 't, 'a> LRkParserData<'s, 'a> { stack.truncate(length - production.reduction_length); let action = self.automaton.get_action( stack[stack.len() - 1].state, - builder.result.variables[production.head].id + builder.variables[production.head].id ); stack.push(LRkHead { state: u32::from(action.get_data()), @@ -595,7 +599,7 @@ impl<'s, 't, 'a> LRkParserData<'s, 'a> { builder: &mut LRkAstBuilder<'s, 't, 'a>, actions: &mut dyn FnMut(usize, Symbol, &dyn SemanticBody) ) -> Symbol<'s> { - let variable = builder.result.variables[production.head]; + let variable = builder.variables[production.head]; builder.reduction_prepare( production.head, production.reduction_length, @@ -638,8 +642,10 @@ impl<'s, 't, 'a> LRkParser<'s, 't, 'a> { /// Initializes a new instance of the parser pub fn new( lexer: &'a mut Lexer<'s, 't, 'a>, + variables: &'a [Symbol<'s>], + virtuals: &'a [Symbol<'s>], automaton: LRkAutomaton, - ast: Ast<'s, 't, 'a>, + ast: &'a mut AstImpl, actions: &'a mut dyn FnMut(usize, Symbol, &dyn SemanticBody) ) -> LRkParser<'s, 't, 'a> { LRkParser { @@ -649,10 +655,10 @@ impl<'s, 't, 'a> LRkParser<'s, 't, 'a> { state: 0, identifier: 0 }], - variables: ast.variables, + variables, actions }, - builder: LRkAstBuilder::<'s, 't, 'a>::new(lexer, ast) + builder: LRkAstBuilder::<'s, 't, 'a>::new(lexer, variables, virtuals, ast) } } diff --git a/runtime-rust/src/parsers/rnglr.rs b/runtime-rust/src/parsers/rnglr.rs index e908e991..32e2b535 100644 --- a/runtime-rust/src/parsers/rnglr.rs +++ b/runtime-rust/src/parsers/rnglr.rs @@ -29,11 +29,13 @@ use super::{ LR_OP_CODE_BASE_SEMANTIC_ACTION, TREE_ACTION_DROP, TREE_ACTION_PROMOTE, TREE_ACTION_REPLACE_BY_CHILDREN, TREE_ACTION_REPLACE_BY_EPSILON }; -use crate::ast::{Ast, AstCell, TableElemRef, TableType}; +use crate::ast::{AstCell, AstImpl, TableElemRef, TableType}; use crate::errors::ParseErrorUnexpectedToken; use crate::lexers::{Lexer, TokenKernel, DEFAULT_CONTEXT}; +use crate::sppf::{SppfImpl, SppfImplNode, SppfImplNodeNormal, SppfImplNodeRef, SppfImplNodeTrait}; use crate::symbols::{SemanticBody, SemanticElement, SemanticElementTrait, SID_EPSILON}; use crate::utils::biglist::BigList; +use crate::utils::OwnOrMut; /// Represents a cell in a RNGLR parse table #[derive(Copy, Clone)] @@ -489,275 +491,12 @@ impl GSS { } } -/// Represents a reference to a Shared-Packed Parse Forest node in a specific version -#[derive(Copy, Clone)] -struct SPPFNodeRef { - /// The identifier of the node - node_id: u32, - /// The version to refer to - version: u32 -} - -/// Represents a version of a node in a Shared-Packed Parse Forest -#[derive(Clone)] -struct SPPFNodeVersion { - /// The label of the node for this version - label: TableElemRef, - /// The children of the node for this version - children: Option> -} - -impl SPPFNodeVersion { - /// Initializes this node version without children - pub fn new(label: TableElemRef) -> SPPFNodeVersion { - SPPFNodeVersion { - label, - children: None - } - } - - /// Initializes this node version - pub fn from(label: TableElemRef, buffer: &[SPPFNodeRef], count: usize) -> SPPFNodeVersion { - if count == 0 { - SPPFNodeVersion { - label, - children: None - } - } else { - let mut children = Vec::with_capacity(count); - for x in buffer.iter().take(count) { - children.push(*x); - } - SPPFNodeVersion { - label, - children: Some(children) - } - } - } - - /// Gets the number of children - pub fn len(&self) -> usize { - match &self.children { - None => 0, - Some(children) => children.len() - } - } -} - -/// Represents the interface for a node in a Shared-Packed Parse Forest -trait SPPFNodeTrait { - /// Gets the original symbol for this node - fn get_original_symbol(&self) -> TableElemRef; -} - -/// Represents a node in a Shared-Packed Parse Forest -/// A node can have multiple versions -#[derive(Clone)] -struct SPPFNodeNormal { - /// The original label of this node - original: TableElemRef, - /// The different versions of this node - versions: Vec -} - -impl SPPFNodeTrait for SPPFNodeNormal { - fn get_original_symbol(&self) -> TableElemRef { - self.original - } -} - -impl SPPFNodeNormal { - /// Initializes this node - pub fn new(label: TableElemRef) -> SPPFNodeNormal { - SPPFNodeNormal { - original: label, - versions: alloc::vec![SPPFNodeVersion::new(label)] - } - } - - /// Initializes this node - pub fn new_with_children( - original: TableElemRef, - label: TableElemRef, - buffer: &[SPPFNodeRef], - count: usize - ) -> SPPFNodeNormal { - SPPFNodeNormal { - original, - versions: alloc::vec![SPPFNodeVersion::from(label, buffer, count)] - } - } - - /// Adds a new version to this node - pub fn new_version( - &mut self, - label: TableElemRef, - buffer: &[SPPFNodeRef], - count: usize - ) -> usize { - let result = self.versions.len(); - self.versions - .push(SPPFNodeVersion::from(label, buffer, count)); - result - } -} - -/// Represents a node in a Shared-Packed Parse Forest that can be replaced by its children -#[derive(Clone)] -struct SPPFNodeReplaceable { - /// The original label of this node - original: TableElemRef, - /// The children of this node - children: Option>, - /// The tree actions on the children of this node - actions: Option> -} - -impl SPPFNodeTrait for SPPFNodeReplaceable { - fn get_original_symbol(&self) -> TableElemRef { - self.original - } -} - -impl SPPFNodeReplaceable { - /// Initializes this node - pub fn new( - label: TableElemRef, - children_buffer: &[SPPFNodeRef], - actions_buffer: &[TreeAction], - count: usize - ) -> SPPFNodeReplaceable { - if count == 0 { - SPPFNodeReplaceable { - original: label, - children: None, - actions: None - } - } else { - let mut children = Vec::with_capacity(count); - let mut actions = Vec::with_capacity(count); - for i in 0..count { - children.push(children_buffer[i]); - actions.push(actions_buffer[i]); - } - SPPFNodeReplaceable { - original: label, - children: Some(children), - actions: Some(actions) - } - } - } -} - -/// Represents a node in a Shared-Packed Parse Forest -#[derive(Clone)] -enum SPPFNode { - /// A normal node - Normal(SPPFNodeNormal), - /// A replaceable node - Replaceable(SPPFNodeReplaceable) -} - -impl SPPFNodeTrait for SPPFNode { - fn get_original_symbol(&self) -> TableElemRef { - match self { - SPPFNode::Normal(node) => node.original, - SPPFNode::Replaceable(node) => node.original - } - } -} - -impl SPPFNode { - /// Gets this node as a normal node - pub fn as_normal(&self) -> &SPPFNodeNormal { - match self { - SPPFNode::Normal(node) => node, - SPPFNode::Replaceable(_node) => panic!("Expected a normal node") - } - } - - /// Gets this node as a normal node - pub fn as_normal_mut(&mut self) -> &mut SPPFNodeNormal { - match self { - SPPFNode::Normal(node) => node, - SPPFNode::Replaceable(_node) => panic!("Expected a normal node") - } - } -} - /// Represents the epsilon node const EPSILON: GSSLabel = GSSLabel { sppf_node: 0xFFFF_FFFF, symbol_id: SID_EPSILON }; -/// Represents a Shared-Packed Parse Forest -#[allow(clippy::upper_case_acronyms)] -struct SPPF { - /// The nodes in the SPPF - nodes: Vec -} - -impl SPPF { - /// Initializes this SPPF - pub fn new() -> SPPF { - SPPF { nodes: Vec::new() } - } - - /// Gets the SPPF node for the specified identifier - pub fn get_node(&self, identifier: usize) -> &SPPFNode { - &self.nodes[identifier] - } - - /// Gets the SPPF node for the specified identifier - pub fn get_node_mut(&mut self, identifier: usize) -> &mut SPPFNode { - &mut self.nodes[identifier] - } - - /// Creates a new single node in the SPPF - pub fn new_normal_node(&mut self, label: TableElemRef) -> usize { - let identifier = self.nodes.len(); - self.nodes - .push(SPPFNode::Normal(SPPFNodeNormal::new(label))); - identifier - } - - /// Creates a new single node in the SPPF - pub fn new_normal_node_with_children( - &mut self, - original: TableElemRef, - label: TableElemRef, - buffer: &[SPPFNodeRef], - count: usize - ) -> usize { - let identifier = self.nodes.len(); - self.nodes - .push(SPPFNode::Normal(SPPFNodeNormal::new_with_children( - original, label, buffer, count - ))); - identifier - } - - /// Creates a new replaceable node in the SPPF - pub fn new_replaceable_node( - &mut self, - label: TableElemRef, - children_buffer: &[SPPFNodeRef], - actions_buffer: &[TreeAction], - count: usize - ) -> usize { - let identifier = self.nodes.len(); - self.nodes - .push(SPPFNode::Replaceable(SPPFNodeReplaceable::new( - label, - children_buffer, - actions_buffer, - count - ))); - identifier - } -} - /// Represents a generation of GSS edges in the current history /// The history is used to quickly find pre-existing matching GSS edges struct HistoryPart { @@ -770,7 +509,7 @@ struct HistoryPart { /// The data about a reduction for a SPPF struct SPPFReduction { /// The adjacency cache for the reduction - cache: Vec, + cache: Vec, /// The reduction handle represented as the indices of the sub-trees in the cache handle_indices: Vec, /// The actions for the reduction @@ -788,14 +527,18 @@ struct SPPFReduction { struct SPPFBuilder<'s, 't, 'a, 'l> { /// Lexer associated to this parser lexer: &'l mut Lexer<'s, 't, 'a>, + /// The table of variables + variables: &'a [Symbol<'s>], + /// The table of virtuals + virtuals: &'a [Symbol<'s>], /// The history history: Vec, - /// The SPPF being built - sppf: SPPF, + /// The SPPF front to build the SPPF + sppf: OwnOrMut<'a, SppfImpl>, /// The data of the current reduction reduction: Option, - /// The AST being built - result: Ast<'s, 't, 'a> + /// The AST being built, if any + ast: Option<&'a mut AstImpl> } impl<'s, 't, 'a, 'l> SemanticBody for SPPFBuilder<'s, 't, 'a, 'l> { @@ -808,8 +551,8 @@ impl<'s, 't, 'a, 'l> SemanticBody for SPPFBuilder<'s, 't, 'a, 'l> { TableType::Token => { SemanticElement::Token(self.lexer.get_data().repository.get_token(label.index())) } - TableType::Variable => SemanticElement::Variable(self.result.variables[label.index()]), - TableType::Virtual => SemanticElement::Virtual(self.result.virtuals[label.index()]), + TableType::Variable => SemanticElement::Variable(self.variables[label.index()]), + TableType::Virtual => SemanticElement::Virtual(self.virtuals[label.index()]), TableType::None => { SemanticElement::Terminal(self.lexer.get_data().repository.terminals[0]) } @@ -823,17 +566,39 @@ impl<'s, 't, 'a, 'l> SemanticBody for SPPFBuilder<'s, 't, 'a, 'l> { } impl<'s, 't, 'a, 'l> SPPFBuilder<'s, 't, 'a, 'l> { - /// Initializes the builder with the given stack size - pub fn new( + /// Initializes the builder targeting an AST + pub fn new_ast( lexer: &'l mut Lexer<'s, 't, 'a>, - result: Ast<'s, 't, 'a> + variables: &'a [Symbol<'s>], + virtuals: &'a [Symbol<'s>], + ast: &'a mut AstImpl ) -> SPPFBuilder<'s, 't, 'a, 'l> { SPPFBuilder { lexer, + variables, + virtuals, history: Vec::new(), - sppf: SPPF::new(), + sppf: OwnOrMut::Owned(SppfImpl::default()), reduction: None, - result + ast: Some(ast) + } + } + + /// Initializes the builder targeting an SPPF + pub fn new_sppf( + lexer: &'l mut Lexer<'s, 't, 'a>, + variables: &'a [Symbol<'s>], + virtuals: &'a [Symbol<'s>], + sppf: &'a mut SppfImpl + ) -> SPPFBuilder<'s, 't, 'a, 'l> { + SPPFBuilder { + lexer, + variables, + virtuals, + history: Vec::new(), + sppf: OwnOrMut::MutRef(sppf), + reduction: None, + ast: None } } @@ -902,7 +667,7 @@ impl<'s, 't, 'a, 'l> SPPFBuilder<'s, 't, 'a, 'l> { /// Adds the specified GSS label to the reduction cache with the given tree action fn reduction_add_to_cache( reduction: &mut SPPFReduction, - sppf: &SPPF, + sppf: &SppfImpl, sppf_node: usize, action: TreeAction ) { @@ -911,11 +676,11 @@ impl<'s, 't, 'a, 'l> SPPFBuilder<'s, 't, 'a, 'l> { } let node = sppf.get_node(sppf_node); match node { - SPPFNode::Normal(normal) => { + SppfImplNode::Normal(normal) => { // this is a simple reference to an existing SPPF node SPPFBuilder::reduction_add_to_cache_node(reduction, normal, sppf_node, action); } - SPPFNode::Replaceable(replaceable) => { + SppfImplNode::Replaceable(replaceable) => { // this is replaceable sub-tree match &replaceable.children { None => {} @@ -938,12 +703,12 @@ impl<'s, 't, 'a, 'l> SPPFBuilder<'s, 't, 'a, 'l> { /// Adds the specified GSS label to the reduction cache with the given tree action fn reduction_add_to_cache_node( reduction: &mut SPPFReduction, - node: &SPPFNodeNormal, + node: &SppfImplNodeNormal, node_id: usize, action: TreeAction ) { // add the node in the cache - reduction.cache.push(SPPFNodeRef { + reduction.cache.push(SppfImplNodeRef { node_id: node_id as u32, version: 0 }); @@ -951,13 +716,8 @@ impl<'s, 't, 'a, 'l> SPPFBuilder<'s, 't, 'a, 'l> { reduction.handle_indices.push(reduction.cache.len() - 1); reduction.handle_actions.push(action); // copy the children - match &node.versions[0].children { - None => {} - Some(children) => { - for child in children { - reduction.cache.push(*child); - } - } + for child in &node.versions[0].children { + reduction.cache.push(child); } } @@ -980,7 +740,7 @@ impl<'s, 't, 'a, 'l> SPPFBuilder<'s, 't, 'a, 'l> { let node_id = self .sppf .new_normal_node(TableElemRef::new(TableType::Virtual, index)); - reduction.cache.push(SPPFNodeRef { + reduction.cache.push(SppfImplNodeRef { node_id: node_id as u32, version: 0 }); @@ -1013,7 +773,7 @@ impl<'s, 't, 'a, 'l> SPPFBuilder<'s, 't, 'a, 'l> { /// Executes the reduction as a normal reduction pub fn reduce_normal(&mut self, variable_index: usize, head_action: TreeAction) -> usize { let reduction = self.reduction.as_mut().expect("Not in a reduction"); - let mut promoted: Option<(TableElemRef, SPPFNodeRef)> = None; + let mut promoted: Option<(TableElemRef, SppfImplNodeRef)> = None; let mut insertion = 0; for i in 0..reduction.handle_indices.len() { @@ -1024,7 +784,7 @@ impl<'s, 't, 'a, 'l> SPPFBuilder<'s, 't, 'a, 'l> { // not the first promotion // create a new version for the promoted node let old_promoted_node = self.sppf.get_node_mut(node_ref.node_id as usize); - let old_promoted_ref = SPPFNodeRef { + let old_promoted_ref = SppfImplNodeRef { node_id: node_ref.node_id, version: old_promoted_node.as_normal_mut().new_version( symbol, @@ -1098,40 +858,45 @@ impl<'s, 't, 'a, 'l> SPPFBuilder<'s, 't, 'a, 'l> { /// Finalizes the parse tree pub fn commit_root(&mut self, root: usize) { - let sppf = &self.sppf; - let result = &mut self.result; - let cell_root = SPPFBuilder::build_final_ast( - sppf, - SPPFNodeRef { - node_id: root as u32, - version: 0 - }, - result - ); - result.store_root(cell_root); + self.sppf.store_root(root); + if let Some(ast) = self.ast.as_mut() { + let sppf = &self.sppf; + let cell_root = SPPFBuilder::build_final_ast( + sppf, + SppfImplNodeRef { + node_id: root as u32, + version: 0 + }, + ast + ); + ast.store_root(cell_root); + } } /// Builds thSe final AST for the specified PPF node reference - fn build_final_ast(sppf: &SPPF, reference: SPPFNodeRef, result: &mut Ast) -> AstCell { + fn build_final_ast( + sppf: &SppfImpl, + reference: SppfImplNodeRef, + result: &mut AstImpl + ) -> AstCell { let node = sppf.get_node(reference.node_id as usize).as_normal(); let version = &node.versions[reference.version as usize]; - match &version.children { - None => AstCell { + if version.children.is_empty() { + AstCell { label: version.label, first: 0, count: 0 - }, - Some(children) => { - let mut buffer = Vec::with_capacity(children.len()); - for child in children { - buffer.push(SPPFBuilder::build_final_ast(sppf, *child, result)); - } - let first = result.store(&buffer, 0, buffer.len()); - AstCell { - label: version.label, - first: first as u32, - count: children.len() as u32 - } + } + } else { + let mut buffer = Vec::with_capacity(version.children.len()); + for child in &version.children { + buffer.push(SPPFBuilder::build_final_ast(sppf, child, result)); + } + let first = result.store(&buffer, 0, buffer.len()); + AstCell { + label: version.label, + first: first as u32, + count: version.children.len() as u32 } } } @@ -1592,10 +1357,44 @@ pub struct RNGLRParser<'s, 't, 'a, 'l> { impl<'s, 't, 'a, 'l> RNGLRParser<'s, 't, 'a, 'l> { /// Initializes a new instance of the parser - pub fn new( + pub fn new_with_ast( + lexer: &'l mut Lexer<'s, 't, 'a>, + variables: &'a [Symbol<'s>], + virtuals: &'a [Symbol<'s>], + automaton: RNGLRAutomaton, + ast: &'a mut AstImpl, + actions: &'a mut dyn FnMut(usize, Symbol, &dyn SemanticBody) + ) -> RNGLRParser<'s, 't, 'a, 'l> { + let mut parser = RNGLRParser { + data: RNGLRParserData { + automaton, + gss: GSS::new(), + next_token: None, + reductions: VecDeque::new(), + shifts: VecDeque::new(), + variables, + actions + }, + builder: SPPFBuilder::new_ast(lexer, variables, virtuals, ast), + nullables: Vec::new() + }; + RNGLRParser::build_nullables( + &mut parser.builder, + &mut parser.data.actions, + &mut parser.nullables, + &parser.data.automaton, + parser.data.variables + ); + parser + } + + /// Initializes a new instance of the parser + pub fn new_with_sppf( lexer: &'l mut Lexer<'s, 't, 'a>, + variables: &'a [Symbol<'s>], + virtuals: &'a [Symbol<'s>], automaton: RNGLRAutomaton, - ast: Ast<'s, 't, 'a>, + sppf: &'a mut SppfImpl, actions: &'a mut dyn FnMut(usize, Symbol, &dyn SemanticBody) ) -> RNGLRParser<'s, 't, 'a, 'l> { let mut parser = RNGLRParser { @@ -1605,10 +1404,10 @@ impl<'s, 't, 'a, 'l> RNGLRParser<'s, 't, 'a, 'l> { next_token: None, reductions: VecDeque::new(), shifts: VecDeque::new(), - variables: ast.variables, + variables, actions }, - builder: SPPFBuilder::new(lexer, ast), + builder: SPPFBuilder::new_sppf(lexer, variables, virtuals, sppf), nullables: Vec::new() }; RNGLRParser::build_nullables( @@ -1740,7 +1539,7 @@ impl<'s, 't, 'a, 'l> RNGLRParser<'s, 't, 'a, 'l> { first: GSSLabel, path: &GSSPath ) -> usize { - let variable = builder.result.variables[production.head]; + let variable = builder.variables[production.head]; builder.reduction_prepare(first, path, production.reduction_length); let mut i = 0; while i < production.bytecode.len() { diff --git a/runtime-rust/src/parsers/subtree.rs b/runtime-rust/src/parsers/subtree.rs index 9ddd7088..3197b2b8 100644 --- a/runtime-rust/src/parsers/subtree.rs +++ b/runtime-rust/src/parsers/subtree.rs @@ -20,7 +20,7 @@ use alloc::vec::Vec; use super::{TreeAction, TREE_ACTION_REPLACE_BY_CHILDREN}; -use crate::ast::{Ast, AstCell, TableElemRef}; +use crate::ast::{AstCell, AstImpl, TableElemRef}; /// Represents a sub-tree in an AST /// A sub-tree is composed of a root with its children. @@ -141,13 +141,13 @@ impl SubTree { /// Commits the children of a sub-tree in this buffer to the final ast /// If the index is 0, the root's children are committed, assuming this is a depth-1 sub-tree. /// If not, the children of the child at the given index are committed. - pub fn commit_children_of(&mut self, index: usize, ast: &mut Ast) { + pub fn commit_children_of(&mut self, index: usize, ast: &mut AstImpl) { self.nodes[index].first = ast.store(&self.nodes, index + 1, self.nodes[index].count as usize) as u32; } /// Commits this buffer to the final ast - pub fn commit(&mut self, ast: &mut Ast) { + pub fn commit(&mut self, ast: &mut AstImpl) { self.commit_children_of(0, ast); ast.store_root(self.nodes[0]); } diff --git a/runtime-rust/src/result.rs b/runtime-rust/src/result.rs index 819d19ad..bcc86b95 100644 --- a/runtime-rust/src/result.rs +++ b/runtime-rust/src/result.rs @@ -21,10 +21,62 @@ use serde::ser::{Serialize, SerializeStruct, Serializer}; use crate::ast::{Ast, AstImpl}; use crate::errors::ParseErrors; +use crate::sppf::{Sppf, SppfImpl}; use crate::symbols::Symbol; use crate::text::Text; use crate::tokens::{TokenRepository, TokenRepositoryImpl}; +/// The data for the parse tree +enum ParseTreeData { + /// An AST is expected by the user + Ast(AstImpl), + /// An SPPF is expected by the user at the end + Sppf(SppfImpl) +} + +impl ParseTreeData { + /// Gets whether a root has been defined for this AST + #[must_use] + fn has_root(&self) -> bool { + match self { + ParseTreeData::Ast(data) => data.has_root(), + ParseTreeData::Sppf(data) => data.has_root() + } + } + + /// Gets the AST data + fn as_ast(&self) -> &AstImpl { + match self { + ParseTreeData::Ast(data) => data, + ParseTreeData::Sppf(_) => panic!("Expected AST data, found SPPF") + } + } + + /// Gets the AST data + fn as_ast_mut(&mut self) -> &mut AstImpl { + match self { + ParseTreeData::Ast(data) => data, + ParseTreeData::Sppf(_) => panic!("Expected AST data, found SPPF") + } + } + + /// Gets the SPPF data + fn as_sppf(&self) -> &SppfImpl { + match self { + ParseTreeData::Sppf(data) => data, + ParseTreeData::Ast(_) => panic!("Expected SPPF data, found AST") + } + } + + /// Gets the SPPF data + fn as_sppf_mut(&mut self) -> &mut SppfImpl { + match self { + ParseTreeData::Sppf(data) => data, + ParseTreeData::Ast(_) => panic!("Expected SPPF data, found AST") + } + } +} + /// Represents the output of a parser pub struct ParseResult<'s, 't, 'a> { /// The table of grammar terminals @@ -40,13 +92,13 @@ pub struct ParseResult<'s, 't, 'a> { /// The table of matched tokens pub tokens: TokenRepositoryImpl, /// The produced AST - ast: AstImpl + parse_tree: ParseTreeData } impl<'s, 't, 'a> ParseResult<'s, 't, 'a> { /// Initialize a new parse result #[must_use] - pub fn new( + pub fn new_with_ast( terminals: &'a [Symbol<'s>], variables: &'a [Symbol<'s>], virtuals: &'a [Symbol<'s>], @@ -59,14 +111,33 @@ impl<'s, 't, 'a> ParseResult<'s, 't, 'a> { text, errors: ParseErrors::default(), tokens: TokenRepositoryImpl::default(), - ast: AstImpl::default() + parse_tree: ParseTreeData::Ast(AstImpl::default()) + } + } + + /// Initialize a new parse result + #[must_use] + pub fn new_with_sppf( + terminals: &'a [Symbol<'s>], + variables: &'a [Symbol<'s>], + virtuals: &'a [Symbol<'s>], + text: Text<'t> + ) -> ParseResult<'s, 't, 'a> { + ParseResult { + terminals, + variables, + virtuals, + text, + errors: ParseErrors::default(), + tokens: TokenRepositoryImpl::default(), + parse_tree: ParseTreeData::Sppf(SppfImpl::default()) } } /// Gets whether this result denotes a successful parsing #[must_use] pub fn is_success(&self) -> bool { - self.ast.has_root() + self.parse_tree.has_root() } /// Gets the token repository associated with this result @@ -82,23 +153,50 @@ impl<'s, 't, 'a> ParseResult<'s, 't, 'a> { TokenRepository::new(self.terminals, &self.text, &self.tokens), self.variables, self.virtuals, - &self.ast + self.parse_tree.as_ast() + ) + } + + /// Gets the resulting AST + #[must_use] + pub fn get_sppf<'x>(&'x self) -> Sppf<'s, 't, 'x> { + Sppf::new( + TokenRepository::new(self.terminals, &self.text, &self.tokens), + self.variables, + self.virtuals, + self.parse_tree.as_sppf() + ) + } + + /// Gets the mutable data required for parsing + #[must_use] + pub fn get_parsing_data_ast<'x>( + &'x mut self + ) -> ( + TokenRepository<'s, 't, 'x>, + &'x mut ParseErrors<'s>, + &'x mut AstImpl + ) { + ( + TokenRepository::new_mut(self.terminals, &self.text, &mut self.tokens), + &mut self.errors, + self.parse_tree.as_ast_mut() ) } /// Gets the mutable data required for parsing #[must_use] - pub fn get_parsing_data<'x>( + pub fn get_parsing_data_sppf<'x>( &'x mut self ) -> ( TokenRepository<'s, 't, 'x>, &'x mut ParseErrors<'s>, - Ast<'s, 't, 'x> + &'x mut SppfImpl ) { ( TokenRepository::new_mut(self.terminals, &self.text, &mut self.tokens), &mut self.errors, - Ast::new_mut(self.variables, self.virtuals, &mut self.ast) + self.parse_tree.as_sppf_mut() ) } } diff --git a/runtime-rust/src/sppf.rs b/runtime-rust/src/sppf.rs new file mode 100644 index 00000000..297e755f --- /dev/null +++ b/runtime-rust/src/sppf.rs @@ -0,0 +1,993 @@ +/******************************************************************************* + * Copyright (c) 2023 Association Cénotélie (cenotelie.fr) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program. + * If not, see . + ******************************************************************************/ + +//! Module for Shared-Packed Parse Forest + +use alloc::vec::Vec; +use core::iter::FusedIterator; +use core::ops::Index; + +use crate::ast::{TableElemRef, TableType}; +use crate::parsers::TreeAction; +use crate::symbols::{SemanticElementTrait, Symbol}; +use crate::text::{TextContext, TextPosition, TextSpan}; +use crate::tokens::{Token, TokenRepository}; + +/// Represents a reference to a Shared-Packed Parse Forest node in a specific version +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)] +pub struct SppfImplNodeRef { + /// The identifier of the node + pub node_id: u32, + /// The version to refer to + pub version: u32 +} + +/// The children for a SPPF node +#[derive(Debug, Default, Clone)] +pub enum SppfImplNodeChildren { + /// No children + #[default] + None, + /// A single child + Single(SppfImplNodeRef), + /// Two children + Two([SppfImplNodeRef; 2]), + /// Three children + Three([SppfImplNodeRef; 3]), + /// Four children + Four([SppfImplNodeRef; 4]), + /// More than four children + More(Vec) +} + +impl SppfImplNodeChildren { + /// Gets the number of children + #[must_use] + pub fn len(&self) -> usize { + match self { + SppfImplNodeChildren::None => 0, + SppfImplNodeChildren::Single(_) => 1, + SppfImplNodeChildren::Two(_) => 2, + SppfImplNodeChildren::Three(_) => 3, + SppfImplNodeChildren::Four(_) => 4, + SppfImplNodeChildren::More(data) => data.len() + } + } + + /// Gets whether there are no children + #[must_use] + pub fn is_empty(&self) -> bool { + matches!(self, SppfImplNodeChildren::None) + } +} + +impl Index for SppfImplNodeChildren { + type Output = SppfImplNodeRef; + + fn index(&self, index: usize) -> &Self::Output { + match self { + SppfImplNodeChildren::Single(child) => child, + SppfImplNodeChildren::Two(children) => &children[index], + SppfImplNodeChildren::Three(children) => &children[index], + SppfImplNodeChildren::Four(children) => &children[index], + SppfImplNodeChildren::More(children) => &children[index], + SppfImplNodeChildren::None => todo!() + } + } +} + +impl<'a> IntoIterator for &'a SppfImplNodeChildren { + type Item = SppfImplNodeRef; + type IntoIter = SppfImplNodeChildrenIterator<'a>; + + fn into_iter(self) -> Self::IntoIter { + SppfImplNodeChildrenIterator { + children: self, + index: 0, + end: self.len() + } + } +} + +/// Iterator over SPPF children nodes +pub struct SppfImplNodeChildrenIterator<'a> { + /// The children + children: &'a SppfImplNodeChildren, + /// The next index + index: usize, + /// The last index (excluded) + end: usize +} + +impl<'a> Iterator for SppfImplNodeChildrenIterator<'a> { + type Item = SppfImplNodeRef; + + fn next(&mut self) -> Option { + match (&self.children, self.index) { + (SppfImplNodeChildren::Single(child), 0) => { + self.index += 1; + Some(*child) + } + (SppfImplNodeChildren::Two(children), index) if index < self.end => { + self.index += 1; + Some(children[index]) + } + (SppfImplNodeChildren::Three(children), index) if index < self.end => { + self.index += 1; + Some(children[index]) + } + (SppfImplNodeChildren::Four(children), index) if index < self.end => { + self.index += 1; + Some(children[index]) + } + (SppfImplNodeChildren::More(children), index) if index < self.end => { + self.index += 1; + Some(children[index]) + } + _ => None + } + } + + fn size_hint(&self) -> (usize, Option) { + let c = self.end - self.index; + (c, Some(c)) + } +} + +impl<'a> DoubleEndedIterator for SppfImplNodeChildrenIterator<'a> { + fn next_back(&mut self) -> Option { + if self.index >= self.end { + None + } else { + let result = self.children[self.end - 1]; + self.end -= 1; + Some(result) + } + } +} + +impl<'a> ExactSizeIterator for SppfImplNodeChildrenIterator<'a> {} +impl<'a> FusedIterator for SppfImplNodeChildrenIterator<'a> {} + +/// Represents a version of a node in a Shared-Packed Parse Forest +#[derive(Debug, Default, Clone)] +pub struct SppfImplNodeVersion { + /// The label of the node for this version + pub label: TableElemRef, + /// The children of the node for this version + pub children: SppfImplNodeChildren +} + +impl SppfImplNodeVersion { + /// Initializes this node version without children + #[must_use] + pub fn new(label: TableElemRef) -> SppfImplNodeVersion { + SppfImplNodeVersion { + label, + children: SppfImplNodeChildren::None + } + } + + /// Initializes this node version + #[must_use] + pub fn from( + label: TableElemRef, + buffer: &[SppfImplNodeRef], + count: usize + ) -> SppfImplNodeVersion { + if count == 0 { + SppfImplNodeVersion { + label, + children: SppfImplNodeChildren::None + } + } else if count == 1 { + SppfImplNodeVersion { + label, + children: SppfImplNodeChildren::Single(buffer[count]) + } + } else if count == 2 { + SppfImplNodeVersion { + label, + children: SppfImplNodeChildren::Two([buffer[count], buffer[count + 1]]) + } + } else if count == 3 { + SppfImplNodeVersion { + label, + children: SppfImplNodeChildren::Three([ + buffer[count], + buffer[count + 1], + buffer[count + 2] + ]) + } + } else if count == 4 { + SppfImplNodeVersion { + label, + children: SppfImplNodeChildren::Four([ + buffer[count], + buffer[count + 1], + buffer[count + 2], + buffer[count + 3] + ]) + } + } else { + let mut children = Vec::with_capacity(count); + for x in buffer.iter().take(count) { + children.push(*x); + } + SppfImplNodeVersion { + label, + children: SppfImplNodeChildren::More(children) + } + } + } + + /// Gets the number of children + #[must_use] + pub fn len(&self) -> usize { + self.children.len() + } + + /// Gets whether there are no children + #[must_use] + pub fn is_empty(&self) -> bool { + self.children.is_empty() + } +} + +/// The different versions of a node in a Shared-Packed Parse Forest +#[derive(Debug, Clone)] +pub enum SppfImplNodeVersions { + /// The node has a single version + Single(SppfImplNodeVersion), + /// The node has multiple versions + Multiple(Vec) +} + +impl Default for SppfImplNodeVersions { + fn default() -> Self { + Self::Single(SppfImplNodeVersion::default()) + } +} + +impl SppfImplNodeVersions { + /// Adds a new version to this node + #[must_use] + pub fn with_new_version( + self, + label: TableElemRef, + buffer: &[SppfImplNodeRef], + count: usize + ) -> (Self, usize) { + match self { + SppfImplNodeVersions::Single(first) => ( + SppfImplNodeVersions::Multiple(alloc::vec![ + first, + SppfImplNodeVersion::from(label, buffer, count) + ]), + 0 + ), + SppfImplNodeVersions::Multiple(mut versions) => { + let current = versions.len(); + versions.push(SppfImplNodeVersion::from(label, buffer, count)); + (SppfImplNodeVersions::Multiple(versions), current) + } + } + } + + /// Gets the number of versions + #[must_use] + pub fn len(&self) -> usize { + match self { + SppfImplNodeVersions::Single(_) => 1, + SppfImplNodeVersions::Multiple(versions) => versions.len() + } + } + + /// Gets whether there is no version + /// Always return `false + #[must_use] + pub fn is_empty(&self) -> bool { + false + } +} + +impl Index for SppfImplNodeVersions { + type Output = SppfImplNodeVersion; + + fn index(&self, index: usize) -> &Self::Output { + match (self, index) { + (SppfImplNodeVersions::Single(first), 0) => first, + (SppfImplNodeVersions::Multiple(versions), index) => &versions[index], + _ => panic!("version {index} does not exist") + } + } +} + +impl<'a> IntoIterator for &'a SppfImplNodeVersions { + type IntoIter = SppfImplNodeVersionsIterator<'a>; + type Item = &'a SppfImplNodeVersion; + + fn into_iter(self) -> Self::IntoIter { + SppfImplNodeVersionsIterator { + versions: self, + index: 0, + end: self.len() + } + } +} + +/// An iterator over the versions of a node +pub struct SppfImplNodeVersionsIterator<'a> { + /// The version + versions: &'a SppfImplNodeVersions, + /// The next index + index: usize, + /// The last index (excluded) + end: usize +} + +impl<'a> Iterator for SppfImplNodeVersionsIterator<'a> { + type Item = &'a SppfImplNodeVersion; + + fn next(&mut self) -> Option { + if self.index < self.end { + Some(&self.versions[self.index]) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + let c = self.end - self.index; + (c, Some(c)) + } +} + +impl<'a> DoubleEndedIterator for SppfImplNodeVersionsIterator<'a> { + fn next_back(&mut self) -> Option { + if self.index >= self.end { + None + } else { + let result = &self.versions[self.end - 1]; + self.end -= 1; + Some(result) + } + } +} + +impl<'a> ExactSizeIterator for SppfImplNodeVersionsIterator<'a> {} +impl<'a> FusedIterator for SppfImplNodeVersionsIterator<'a> {} + +/// Represents the interface for a node in a Shared-Packed Parse Forest +pub trait SppfImplNodeTrait { + /// Gets the original symbol for this node + fn get_original_symbol(&self) -> TableElemRef; +} + +/// Represents a node in a Shared-Packed Parse Forest +/// A node can have multiple versions +#[derive(Debug, Clone)] +pub struct SppfImplNodeNormal { + /// The original label of this node + pub original: TableElemRef, + /// The different versions of this node + pub versions: SppfImplNodeVersions +} + +impl SppfImplNodeTrait for SppfImplNodeNormal { + fn get_original_symbol(&self) -> TableElemRef { + self.original + } +} + +impl SppfImplNodeNormal { + /// Initializes this node + #[must_use] + pub fn new(label: TableElemRef) -> SppfImplNodeNormal { + SppfImplNodeNormal { + original: label, + versions: SppfImplNodeVersions::Single(SppfImplNodeVersion::new(label)) + } + } + + /// Initializes this node + #[must_use] + pub fn new_with_children( + original: TableElemRef, + label: TableElemRef, + buffer: &[SppfImplNodeRef], + count: usize + ) -> SppfImplNodeNormal { + SppfImplNodeNormal { + original, + versions: SppfImplNodeVersions::Single(SppfImplNodeVersion::from(label, buffer, count)) + } + } + + /// Adds a new version to this node + pub fn new_version( + &mut self, + label: TableElemRef, + buffer: &[SppfImplNodeRef], + count: usize + ) -> usize { + let result; + (self.versions, result) = + std::mem::take(&mut self.versions).with_new_version(label, buffer, count); + result + } +} + +/// Represents a node in a Shared-Packed Parse Forest that can be replaced by its children +#[derive(Clone)] +pub struct SppfImplNodeReplaceable { + /// The original label of this node + pub original: TableElemRef, + /// The children of this node + pub children: Option>, + /// The tree actions on the children of this node + pub actions: Option> +} + +impl SppfImplNodeTrait for SppfImplNodeReplaceable { + fn get_original_symbol(&self) -> TableElemRef { + self.original + } +} + +impl SppfImplNodeReplaceable { + /// Initializes this node + #[must_use] + pub fn new( + label: TableElemRef, + children_buffer: &[SppfImplNodeRef], + actions_buffer: &[TreeAction], + count: usize + ) -> SppfImplNodeReplaceable { + if count == 0 { + SppfImplNodeReplaceable { + original: label, + children: None, + actions: None + } + } else { + let mut children = Vec::with_capacity(count); + let mut actions = Vec::with_capacity(count); + for i in 0..count { + children.push(children_buffer[i]); + actions.push(actions_buffer[i]); + } + SppfImplNodeReplaceable { + original: label, + children: Some(children), + actions: Some(actions) + } + } + } +} + +/// Represents a node in a Shared-Packed Parse Forest +#[derive(Clone)] +pub enum SppfImplNode { + /// A normal node + Normal(SppfImplNodeNormal), + /// A replaceable node + Replaceable(SppfImplNodeReplaceable) +} + +impl SppfImplNodeTrait for SppfImplNode { + fn get_original_symbol(&self) -> TableElemRef { + match self { + SppfImplNode::Normal(node) => node.original, + SppfImplNode::Replaceable(node) => node.original + } + } +} + +impl SppfImplNode { + /// Gets this node as a normal node + /// + /// # Panics + /// + /// Panics when the node is not a normal node, but a replaceable node + #[must_use] + pub fn as_normal(&self) -> &SppfImplNodeNormal { + match self { + SppfImplNode::Normal(node) => node, + SppfImplNode::Replaceable(_node) => panic!("Expected a normal node") + } + } + + /// Gets this node as a normal node + /// + /// # Panics + /// + /// Panics when the node is not a normal node, but a replaceable node + pub fn as_normal_mut(&mut self) -> &mut SppfImplNodeNormal { + match self { + SppfImplNode::Normal(node) => node, + SppfImplNode::Replaceable(_node) => panic!("Expected a normal node") + } + } +} + +/// Represents a Shared-Packed Parse Forest +#[derive(Default)] +pub struct SppfImpl { + /// The nodes in the SPPF + pub nodes: Vec, + /// The root, if any + pub root: Option +} + +impl SppfImpl { + /// Stores the root of this tree + pub fn store_root(&mut self, root: usize) { + self.root = Some(root); + } + + /// Gets whether a root has been defined for this SPPF + #[must_use] + pub fn has_root(&self) -> bool { + self.root.is_some() + } + + /// Gets the SPPF node for the specified identifier + #[must_use] + pub fn get_node(&self, identifier: usize) -> &SppfImplNode { + &self.nodes[identifier] + } + + /// Gets the SPPF node for the specified identifier + pub fn get_node_mut(&mut self, identifier: usize) -> &mut SppfImplNode { + &mut self.nodes[identifier] + } + + /// Creates a new single node in the SPPF + pub fn new_normal_node(&mut self, label: TableElemRef) -> usize { + let identifier = self.nodes.len(); + self.nodes + .push(SppfImplNode::Normal(SppfImplNodeNormal::new(label))); + identifier + } + + /// Creates a new single node in the SPPF + pub fn new_normal_node_with_children( + &mut self, + original: TableElemRef, + label: TableElemRef, + buffer: &[SppfImplNodeRef], + count: usize + ) -> usize { + let identifier = self.nodes.len(); + self.nodes + .push(SppfImplNode::Normal(SppfImplNodeNormal::new_with_children( + original, label, buffer, count + ))); + identifier + } + + /// Creates a new replaceable node in the SPPF + pub fn new_replaceable_node( + &mut self, + label: TableElemRef, + children_buffer: &[SppfImplNodeRef], + actions_buffer: &[TreeAction], + count: usize + ) -> usize { + let identifier = self.nodes.len(); + self.nodes + .push(SppfImplNode::Replaceable(SppfImplNodeReplaceable::new( + label, + children_buffer, + actions_buffer, + count + ))); + identifier + } +} + +/// Represents a front for a mutable Shared-Packed Parse Forest, +/// i.e. a set of possible parse trees, +/// along with required data +pub struct Sppf<'s, 't, 'a> { + /// The table of tokens + tokens: TokenRepository<'s, 't, 'a>, + /// The table of variables + variables: &'a [Symbol<'s>], + /// The table of virtuals + virtuals: &'a [Symbol<'s>], + /// The SPPF itself + data: &'a SppfImpl +} + +impl<'s, 't, 'a> Sppf<'s, 't, 'a> { + /// Creates a new mutating SPPF front, with a mutably borrowed backend + #[must_use] + pub fn new( + tokens: TokenRepository<'s, 't, 'a>, + variables: &'a [Symbol<'s>], + virtuals: &'a [Symbol<'s>], + data: &'a SppfImpl + ) -> Sppf<'s, 't, 'a> { + Self { + tokens, + variables, + virtuals, + data + } + } + + /// Gets whether a root has been defined for this AST + #[must_use] + pub fn has_root(&self) -> bool { + self.data.has_root() + } + + /// Gets the root for this SPPF + /// + /// # Panics + /// + /// Raise a panic when the SPPF has no root. + /// This can happen when a `ParseResult` contains some errors, + /// but the SPPF `get_sppf` is called to get an SPPF but it will have not root. + #[must_use] + pub fn get_root(&self) -> SppfNode { + let node = self.data.nodes[self.data.root.expect("No root defined!")].as_normal(); + SppfNode { sppf: self, node } + } + + /// Gets the SPPF node (if any) that has the specified token as label + #[must_use] + pub fn find_node_for(&self, token: &Token) -> Option { + self.data + .nodes + .iter() + .find_map(|node| { + let normal = node.as_normal(); + normal.versions.into_iter().find(|version| { + version.label.table_type() == TableType::Token + && version.label.index() == token.index + }) + }) + .map(|version| SppfNodeVersion { + sppf: self, + version + }) + } + + /// Gets the AST node (if any) that has + /// a token label that contains the specified index in the input text + #[must_use] + pub fn find_node_at_index(&self, index: usize) -> Option { + self.tokens + .find_token_at(index) + .and_then(|token| self.find_node_for(&token)) + } + + /// Gets the AST node (if any) that has + /// a token label that contains the specified index in the input text + #[must_use] + pub fn find_node_at_position(&self, position: TextPosition) -> Option { + let index = self.tokens.text.get_line_index(position.line) + position.column - 1; + self.tokens + .find_token_at(index) + .and_then(|token| self.find_node_for(&token)) + } +} + +/// Represents a node in a Shared-Packed Parse Forest +#[derive(Copy, Clone)] +pub struct SppfNode<'s, 't, 'a> { + /// The parent SPPF + sppf: &'a Sppf<'s, 't, 'a>, + /// The underlying node in the SPPF implementation + node: &'a SppfImplNodeNormal +} + +impl<'s, 't, 'a> SppfNode<'s, 't, 'a> { + /// Gets the first version of this node + #[must_use] + pub fn first_version(&self) -> SppfNodeVersion<'s, 't, 'a> { + let version = &self.node.versions[0]; + SppfNodeVersion { + sppf: self.sppf, + version + } + } + + /// Gets the different versions of this node + #[must_use] + pub fn versions(&self) -> SppfNodeVersions<'s, 't, 'a> { + SppfNodeVersions { + sppf: self.sppf, + node: self.node + } + } +} + +#[derive(Copy, Clone)] +pub struct SppfNodeVersions<'s, 't, 'a> { + /// The parent SPPF + sppf: &'a Sppf<'s, 't, 'a>, + /// The underlying node in the SPPF implementation + node: &'a SppfImplNodeNormal +} + +impl<'s, 't, 'a> SppfNodeVersions<'s, 't, 'a> { + /// Gets the number of versions + #[must_use] + pub fn len(&self) -> usize { + self.node.versions.len() + } + + /// Gets whether there is no version + /// Always return `false + #[must_use] + pub fn is_empty(&self) -> bool { + false + } +} + +impl<'s, 't, 'a> IntoIterator for SppfNodeVersions<'s, 't, 'a> { + type Item = SppfNodeVersion<'s, 't, 'a>; + type IntoIter = SppfNodeVersionsIterator<'s, 't, 'a>; + + fn into_iter(self) -> Self::IntoIter { + SppfNodeVersionsIterator { + sppf: self.sppf, + node: self.node, + current: 0, + end: self.node.versions.len() + } + } +} + +#[derive(Copy, Clone)] +pub struct SppfNodeVersionsIterator<'s, 't, 'a> { + /// The parent SPPF + sppf: &'a Sppf<'s, 't, 'a>, + /// The underlying node in the SPPF implementation + node: &'a SppfImplNodeNormal, + /// The current (next) index + current: usize, + /// The end index (excluded) + end: usize +} + +impl<'s, 't, 'a> Iterator for SppfNodeVersionsIterator<'s, 't, 'a> { + type Item = SppfNodeVersion<'s, 't, 'a>; + fn next(&mut self) -> Option { + if self.current < self.end { + let index = self.current; + self.current += 1; + Some(SppfNodeVersion { + sppf: self.sppf, + version: &self.node.versions[index] + }) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + let c = self.end - self.current; + (c, Some(c)) + } +} + +impl<'s, 't, 'a> DoubleEndedIterator for SppfNodeVersionsIterator<'s, 't, 'a> { + fn next_back(&mut self) -> Option { + if self.current >= self.end { + None + } else { + let result = SppfNodeVersion { + sppf: self.sppf, + version: &self.node.versions[self.end - 1] + }; + self.end -= 1; + Some(result) + } + } +} + +impl<'s, 't, 'a> ExactSizeIterator for SppfNodeVersionsIterator<'s, 't, 'a> {} +impl<'s, 't, 'a> FusedIterator for SppfNodeVersionsIterator<'s, 't, 'a> {} + +#[derive(Copy, Clone)] +pub struct SppfNodeVersion<'s, 't, 'a> { + /// The parent SPPF + sppf: &'a Sppf<'s, 't, 'a>, + /// The underlying version in the SPPF implementation + version: &'a SppfImplNodeVersion +} + +impl<'s, 't, 'a> SppfNodeVersion<'s, 't, 'a> { + /// Gets the children for this version of the node + #[must_use] + pub fn children(&self) -> SppfNodeChildren<'s, 't, 'a> { + SppfNodeChildren { + sppf: self.sppf, + version: self.version + } + } +} + +impl<'s, 't, 'a> SemanticElementTrait<'s, 'a> for SppfNodeVersion<'s, 't, 'a> { + /// Gets the position in the input text of this element + fn get_position(&self) -> Option { + let label = self.version.label; + match label.table_type() { + TableType::Token => { + let token = self.sppf.tokens.get_token(label.index()); + token.get_position() + } + _ => None + } + } + + /// Gets the span in the input text of this element + fn get_span(&self) -> Option { + let label = self.version.label; + match label.table_type() { + TableType::Token => { + let token = self.sppf.tokens.get_token(label.index()); + token.get_span() + } + _ => None + } + } + + /// Gets the context of this element in the input + fn get_context(&self) -> Option> { + let label = self.version.label; + match label.table_type() { + TableType::Token => { + let token = self.sppf.tokens.get_token(label.index()); + token.get_context() + } + _ => None + } + } + + /// Gets the grammar symbol associated to this element + fn get_symbol(&self) -> Symbol<'s> { + let label = self.version.label; + match label.table_type() { + TableType::Token => { + let token = self.sppf.tokens.get_token(label.index()); + token.get_symbol() + } + TableType::Variable => self.sppf.variables[label.index()], + TableType::Virtual => self.sppf.virtuals[label.index()], + TableType::None => { + // terminal epsilon + self.sppf.tokens.terminals[0] + } + } + } + + /// Gets the value of this element, if any + fn get_value(&self) -> Option<&'a str> { + let label = self.version.label; + match label.table_type() { + TableType::Token => { + let token = self.sppf.tokens.get_token(label.index()); + token.get_value() + } + _ => None + } + } +} + +#[derive(Copy, Clone)] +pub struct SppfNodeChildren<'s, 't, 'a> { + /// The parent SPPF + sppf: &'a Sppf<'s, 't, 'a>, + /// The underlying version in the SPPF implementation + version: &'a SppfImplNodeVersion +} + +impl<'s, 't, 'a> SppfNodeChildren<'s, 't, 'a> { + /// Gets the number of children + #[must_use] + pub fn len(&self) -> usize { + self.version.len() + } + + /// Gets whether there are no children + #[must_use] + pub fn is_empty(&self) -> bool { + self.version.is_empty() + } +} + +impl<'s, 't, 'a> IntoIterator for SppfNodeChildren<'s, 't, 'a> { + type Item = SppfNode<'s, 't, 'a>; + type IntoIter = SppfNodeChildrenIterator<'s, 't, 'a>; + + fn into_iter(self) -> Self::IntoIter { + SppfNodeChildrenIterator { + sppf: self.sppf, + version: self.version, + index: 0, + end: self.version.len() + } + } +} + +/// Iterator over SPPF children nodes +pub struct SppfNodeChildrenIterator<'s, 't, 'a> { + /// The parent SPPF + sppf: &'a Sppf<'s, 't, 'a>, + /// The underlying version in the SPPF implementation + version: &'a SppfImplNodeVersion, + /// The next index + index: usize, + /// The last index (excluded) + end: usize +} + +impl<'s, 't, 'a> Iterator for SppfNodeChildrenIterator<'s, 't, 'a> { + type Item = SppfNode<'s, 't, 'a>; + + fn next(&mut self) -> Option { + if self.index < self.end { + let node = self + .sppf + .data + .get_node(self.version.children[self.index].node_id as usize) + .as_normal(); + let result = Some(SppfNode { + sppf: self.sppf, + node + }); + self.index += 1; + result + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + let c = self.end - self.index; + (c, Some(c)) + } +} + +impl<'s, 't, 'a> DoubleEndedIterator for SppfNodeChildrenIterator<'s, 't, 'a> { + fn next_back(&mut self) -> Option { + if self.index >= self.end { + None + } else { + let node = self + .sppf + .data + .get_node(self.version.children[self.end - 1].node_id as usize) + .as_normal(); + let result = Some(SppfNode { + sppf: self.sppf, + node + }); + self.end -= 1; + result + } + } +} + +impl<'s, 't, 'a> ExactSizeIterator for SppfNodeChildrenIterator<'s, 't, 'a> {} +impl<'s, 't, 'a> FusedIterator for SppfNodeChildrenIterator<'s, 't, 'a> {} diff --git a/runtime-rust/src/utils/mod.rs b/runtime-rust/src/utils/mod.rs index cddc9292..b380f107 100644 --- a/runtime-rust/src/utils/mod.rs +++ b/runtime-rust/src/utils/mod.rs @@ -49,3 +49,32 @@ impl<'a, T: 'a> DerefMut for EitherMut<'a, T> { } } } + +/// Represents a resource that is either owned, +/// or exclusively held with a a mutable reference +pub enum OwnOrMut<'a, T> { + /// The resource is directly owned + Owned(T), + /// The resource is held through a mutable reference + MutRef(&'a mut T) +} + +impl<'a, T> Deref for OwnOrMut<'a, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + match self { + OwnOrMut::Owned(data) => data, + OwnOrMut::MutRef(data) => data + } + } +} + +impl<'a, T> DerefMut for OwnOrMut<'a, T> { + fn deref_mut(&mut self) -> &mut Self::Target { + match self { + OwnOrMut::Owned(data) => data, + OwnOrMut::MutRef(data) => data + } + } +} diff --git a/sdk-rust/Cargo.toml b/sdk-rust/Cargo.toml index fc53b354..f8b9b474 100644 --- a/sdk-rust/Cargo.toml +++ b/sdk-rust/Cargo.toml @@ -20,6 +20,7 @@ print_errors = ["miette"] [dependencies] hime_redist = "4.3.0" lazy_static = "1.4" +include-flate = "0.2" rand = "0.8" miette = { version = "5.6", optional = true} diff --git a/sdk-rust/src/loaders/hime_grammar.rs b/sdk-rust/src/loaders/hime_grammar.rs index de84095a..6061ec44 100644 --- a/sdk-rust/src/loaders/hime_grammar.rs +++ b/sdk-rust/src/loaders/hime_grammar.rs @@ -584,12 +584,19 @@ fn parse_text_with<'s, 't, 'a>( virtuals: &'a [Symbol<'s>] ) -> ParseResult<'s, 't, 'a> { let mut my_actions = |_index: usize, _head: Symbol, _body: &dyn SemanticBody| (); - let mut result = ParseResult::new(terminals, variables, virtuals, text); + let mut result = ParseResult::new_with_ast(terminals, variables, virtuals, text); { - let data = result.get_parsing_data(); + let data = result.get_parsing_data_ast(); let mut lexer = new_lexer(data.0, data.1); let automaton = LRkAutomaton::new(PARSER_AUTOMATON); - let mut parser = LRkParser::new(&mut lexer, automaton, data.2, &mut my_actions); + let mut parser = LRkParser::new( + &mut lexer, + variables, + virtuals, + automaton, + data.2, + &mut my_actions + ); parser.parse(); } result diff --git a/sdk-rust/src/sdk.rs b/sdk-rust/src/sdk.rs index 44d3cc7a..203cda88 100644 --- a/sdk-rust/src/sdk.rs +++ b/sdk-rust/src/sdk.rs @@ -17,7 +17,7 @@ //! Module for SDK utilities -use hime_redist::ast::Ast; +use hime_redist::ast::AstImpl; use hime_redist::errors::ParseErrors; use hime_redist::lexers::automaton::Automaton; use hime_redist::lexers::impls::{ContextFreeLexer, ContextSensitiveLexer}; @@ -65,10 +65,11 @@ impl<'s> InMemoryParser<'s> { #[must_use] pub fn parse<'a, 't>(&'a self, input: &'t str) -> ParseResult<'s, 't, 'a> { let text = Text::from_str(input); - let mut result = ParseResult::new(&self.terminals, &self.variables, &self.virtuals, text); + let mut result = + ParseResult::new_with_ast(&self.terminals, &self.variables, &self.virtuals, text); let mut my_actions = |_index: usize, _head: Symbol, _body: &dyn SemanticBody| (); { - let data = result.get_parsing_data(); + let data = result.get_parsing_data_ast(); let mut lexer = self.new_lexer(data.0, data.1); self.do_parse(&mut lexer, data.2, &mut my_actions); } @@ -79,16 +80,26 @@ impl<'s> InMemoryParser<'s> { fn do_parse<'a, 't>( &'a self, lexer: &'a mut Lexer<'s, 't, 'a>, - ast: Ast<'s, 't, 'a>, + ast: &'a mut AstImpl, actions: &'a mut dyn FnMut(usize, Symbol, &dyn SemanticBody) ) { let mut parser: Box = match &self.parser_automaton { - ParserAutomaton::Lrk(automaton) => { - Box::new(LRkParser::new(lexer, automaton.clone(), ast, actions)) - } - ParserAutomaton::Rnglr(automaton) => { - Box::new(RNGLRParser::new(lexer, automaton.clone(), ast, actions)) - } + ParserAutomaton::Lrk(automaton) => Box::new(LRkParser::new( + lexer, + &self.variables, + &self.virtuals, + automaton.clone(), + ast, + actions + )), + ParserAutomaton::Rnglr(automaton) => Box::new(RNGLRParser::new_with_ast( + lexer, + &self.variables, + &self.virtuals, + automaton.clone(), + ast, + actions + )) }; parser.parse(); } diff --git a/tests-driver/src/loaders/fixture.rs b/tests-driver/src/loaders/fixture.rs index 1bfb33a3..88da9e85 100644 --- a/tests-driver/src/loaders/fixture.rs +++ b/tests-driver/src/loaders/fixture.rs @@ -698,12 +698,19 @@ fn parse_text_with<'s, 't, 'a>( virtuals: &'a [Symbol<'s>] ) -> ParseResult<'s, 't, 'a> { let mut my_actions = |_index: usize, _head: Symbol, _body: &dyn SemanticBody| (); - let mut result = ParseResult::new(terminals, variables, virtuals, text); + let mut result = ParseResult::new_with_ast(terminals, variables, virtuals, text); { - let data = result.get_parsing_data(); + let data = result.get_parsing_data_ast(); let mut lexer = new_lexer(data.0, data.1); let automaton = LRkAutomaton::new(PARSER_AUTOMATON); - let mut parser = LRkParser::new(&mut lexer, automaton, data.2, &mut my_actions); + let mut parser = LRkParser::new( + &mut lexer, + variables, + virtuals, + automaton, + data.2, + &mut my_actions + ); parser.parse(); } result diff --git a/tests-executor-rust/src/expected_tree.rs b/tests-executor-rust/src/expected_tree.rs index 2aa2aeaa..305bf429 100644 --- a/tests-executor-rust/src/expected_tree.rs +++ b/tests-executor-rust/src/expected_tree.rs @@ -698,12 +698,19 @@ fn parse_text_with<'s, 't, 'a>( virtuals: &'a [Symbol<'s>] ) -> ParseResult<'s, 't, 'a> { let mut my_actions = |_index: usize, _head: Symbol, _body: &dyn SemanticBody| (); - let mut result = ParseResult::new(terminals, variables, virtuals, text); + let mut result = ParseResult::new_with_ast(terminals, variables, virtuals, text); { - let data = result.get_parsing_data(); + let data = result.get_parsing_data_ast(); let mut lexer = new_lexer(data.0, data.1); let automaton = LRkAutomaton::new(PARSER_AUTOMATON); - let mut parser = LRkParser::new(&mut lexer, automaton, data.2, &mut my_actions); + let mut parser = LRkParser::new( + &mut lexer, + variables, + virtuals, + automaton, + data.2, + &mut my_actions + ); parser.parse(); } result