diff --git a/src/document.rs b/src/document.rs index 4221b79..21ff056 100644 --- a/src/document.rs +++ b/src/document.rs @@ -1,6 +1,7 @@ use crate::{ - MappingStyle, Mark, ScalarStyle, SequenceStyle, TagDirective, VersionDirective, - DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG, DEFAULT_SEQUENCE_TAG, + AliasData, ComposerError, Event, EventData, MappingStyle, Mark, Parser, ScalarStyle, + SequenceStyle, TagDirective, VersionDirective, DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG, + DEFAULT_SEQUENCE_TAG, }; /// The document structure. @@ -248,4 +249,361 @@ impl Document { pairs.push(pair); } } + + /// Parse the input stream and produce the next YAML document. + /// + /// Call this function subsequently to produce a sequence of documents + /// constituting the input stream. + /// + /// If the produced document has no root node, it means that the document end + /// has been reached. + /// + /// An application must not alternate the calls of + /// [`yaml_parser_load()`](crate::yaml_parser_load) with the calls of + /// [`yaml_parser_scan()`](crate::yaml_parser_scan) or + /// [`yaml_parser_parse()`](crate::yaml_parser_parse). Doing this will break the + /// parser. + pub fn load(parser: &mut Parser) -> Result { + let mut document = Document::new(None, &[], false, false); + document.nodes.reserve(16); + + if !parser.stream_start_produced { + match parser.parse() { + Ok(Event { + data: EventData::StreamStart { .. }, + .. + }) => (), + Ok(_) => panic!("expected stream start"), + Err(err) => { + parser.delete_aliases(); + return Err(err.into()); + } + } + } + if parser.stream_end_produced { + return Ok(document); + } + let err: ComposerError; + match parser.parse() { + Ok(event) => { + if let EventData::StreamEnd = &event.data { + return Ok(document); + } + parser.aliases.reserve(16); + match document.load_document(parser, event) { + Ok(()) => { + parser.delete_aliases(); + return Ok(document); + } + Err(e) => err = e, + } + } + Err(e) => err = e.into(), + } + parser.delete_aliases(); + Err(err) + } + + fn set_composer_error( + problem: &'static str, + problem_mark: Mark, + ) -> Result { + Err(ComposerError::Problem { + problem, + mark: problem_mark, + }) + } + + fn set_composer_error_context( + context: &'static str, + context_mark: Mark, + problem: &'static str, + problem_mark: Mark, + ) -> Result { + Err(ComposerError::ProblemWithContext { + context, + context_mark, + problem, + mark: problem_mark, + }) + } + + fn load_document(&mut self, parser: &mut Parser, event: Event) -> Result<(), ComposerError> { + let mut ctx = vec![]; + if let EventData::DocumentStart { + version_directive, + tag_directives, + implicit, + } = event.data + { + self.version_directive = version_directive; + self.tag_directives = tag_directives; + self.start_implicit = implicit; + self.start_mark = event.start_mark; + ctx.reserve(16); + if let Err(err) = self.load_nodes(parser, &mut ctx) { + ctx.clear(); + return Err(err); + } + ctx.clear(); + Ok(()) + } else { + panic!("Expected YAML_DOCUMENT_START_EVENT") + } + } + + fn load_nodes(&mut self, parser: &mut Parser, ctx: &mut Vec) -> Result<(), ComposerError> { + let end_implicit; + let end_mark; + + loop { + let event = parser.parse()?; + match event.data { + EventData::NoEvent => panic!("empty event"), + EventData::StreamStart { .. } => panic!("unexpected stream start event"), + EventData::StreamEnd => panic!("unexpected stream end event"), + EventData::DocumentStart { .. } => panic!("unexpected document start event"), + EventData::DocumentEnd { implicit } => { + end_implicit = implicit; + end_mark = event.end_mark; + break; + } + EventData::Alias { .. } => { + self.load_alias(parser, event, ctx)?; + } + EventData::Scalar { .. } => { + self.load_scalar(parser, event, ctx)?; + } + EventData::SequenceStart { .. } => { + self.load_sequence(parser, event, ctx)?; + } + EventData::SequenceEnd => { + self.load_sequence_end(event, ctx)?; + } + EventData::MappingStart { .. } => { + self.load_mapping(parser, event, ctx)?; + } + EventData::MappingEnd => { + self.load_mapping_end(event, ctx)?; + } + } + } + self.end_implicit = end_implicit; + self.end_mark = end_mark; + Ok(()) + } + + fn register_anchor( + &mut self, + parser: &mut Parser, + index: i32, + anchor: Option, + ) -> Result<(), ComposerError> { + let Some(anchor) = anchor else { + return Ok(()); + }; + let data = AliasData { + anchor, + index, + mark: self.nodes[index as usize - 1].start_mark, + }; + for alias_data in &parser.aliases { + if alias_data.anchor == data.anchor { + return Self::set_composer_error_context( + "found duplicate anchor; first occurrence", + alias_data.mark, + "second occurrence", + data.mark, + ); + } + } + parser.aliases.push(data); + Ok(()) + } + + fn load_node_add(&mut self, ctx: &[i32], index: i32) -> Result<(), ComposerError> { + if ctx.is_empty() { + return Ok(()); + } + let parent_index: i32 = *ctx.last().unwrap(); + let parent = &mut self.nodes[parent_index as usize - 1]; + match parent.data { + NodeData::Sequence { ref mut items, .. } => { + items.push(index); + } + NodeData::Mapping { ref mut pairs, .. } => { + let mut pair = NodePair::default(); + let mut do_push = true; + if !pairs.is_empty() { + let p: &mut NodePair = pairs.last_mut().unwrap(); + if p.key != 0 && p.value == 0 { + p.value = index; + do_push = false; + } + } + if do_push { + pair.key = index; + pair.value = 0; + pairs.push(pair); + } + } + _ => { + panic!("document parent node is not a sequence or a mapping") + } + } + Ok(()) + } + + fn load_alias( + &mut self, + parser: &mut Parser, + event: Event, + ctx: &[i32], + ) -> Result<(), ComposerError> { + let EventData::Alias { anchor } = &event.data else { + unreachable!() + }; + + for alias_data in &parser.aliases { + if alias_data.anchor == *anchor { + return self.load_node_add(ctx, alias_data.index); + } + } + + Self::set_composer_error("found undefined alias", event.start_mark) + } + + fn load_scalar( + &mut self, + parser: &mut Parser, + event: Event, + ctx: &[i32], + ) -> Result<(), ComposerError> { + let EventData::Scalar { + mut tag, + value, + style, + anchor, + .. + } = event.data + else { + unreachable!() + }; + + if tag.is_none() || tag.as_deref() == Some("!") { + tag = Some(String::from(DEFAULT_SCALAR_TAG)); + } + let node = Node { + data: NodeData::Scalar { value, style }, + tag, + start_mark: event.start_mark, + end_mark: event.end_mark, + }; + self.nodes.push(node); + let index: i32 = self.nodes.len() as i32; + self.register_anchor(parser, index, anchor)?; + self.load_node_add(ctx, index) + } + + fn load_sequence( + &mut self, + parser: &mut Parser, + event: Event, + ctx: &mut Vec, + ) -> Result<(), ComposerError> { + let EventData::SequenceStart { + anchor, + mut tag, + style, + .. + } = event.data + else { + unreachable!() + }; + + let mut items = Vec::with_capacity(16); + + if tag.is_none() || tag.as_deref() == Some("!") { + tag = Some(String::from(DEFAULT_SEQUENCE_TAG)); + } + + let node = Node { + data: NodeData::Sequence { + items: core::mem::take(&mut items), + style, + }, + tag, + start_mark: event.start_mark, + end_mark: event.end_mark, + }; + + self.nodes.push(node); + let index: i32 = self.nodes.len() as i32; + self.register_anchor(parser, index, anchor)?; + self.load_node_add(ctx, index)?; + ctx.push(index); + Ok(()) + } + + fn load_sequence_end(&mut self, event: Event, ctx: &mut Vec) -> Result<(), ComposerError> { + assert!(!ctx.is_empty()); + let index: i32 = *ctx.last().unwrap(); + assert!(matches!( + self.nodes[index as usize - 1].data, + NodeData::Sequence { .. } + )); + self.nodes[index as usize - 1].end_mark = event.end_mark; + _ = ctx.pop(); + Ok(()) + } + + fn load_mapping( + &mut self, + parser: &mut Parser, + event: Event, + ctx: &mut Vec, + ) -> Result<(), ComposerError> { + let EventData::MappingStart { + anchor, + mut tag, + style, + .. + } = event.data + else { + unreachable!() + }; + + let mut pairs = Vec::with_capacity(16); + + if tag.is_none() || tag.as_deref() == Some("!") { + tag = Some(String::from(DEFAULT_MAPPING_TAG)); + } + let node = Node { + data: NodeData::Mapping { + pairs: core::mem::take(&mut pairs), + style, + }, + tag, + start_mark: event.start_mark, + end_mark: event.end_mark, + }; + self.nodes.push(node); + let index: i32 = self.nodes.len() as i32; + self.register_anchor(parser, index, anchor)?; + self.load_node_add(ctx, index)?; + ctx.push(index); + Ok(()) + } + + fn load_mapping_end(&mut self, event: Event, ctx: &mut Vec) -> Result<(), ComposerError> { + assert!(!ctx.is_empty()); + let index: i32 = *ctx.last().unwrap(); + assert!(matches!( + self.nodes[index as usize - 1].data, + NodeData::Mapping { .. } + )); + self.nodes[index as usize - 1].end_mark = event.end_mark; + _ = ctx.pop(); + Ok(()) + } } diff --git a/src/lib.rs b/src/lib.rs index 91be83a..4464352 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,7 +32,6 @@ mod dumper; mod emitter; mod error; mod event; -mod loader; mod parser; mod reader; mod scanner; @@ -44,7 +43,6 @@ pub use crate::dumper::{yaml_emitter_close, yaml_emitter_dump, yaml_emitter_open pub use crate::emitter::*; pub use crate::error::*; pub use crate::event::*; -pub use crate::loader::yaml_parser_load; pub use crate::parser::*; pub use crate::scanner::yaml_parser_scan; pub use crate::token::*; @@ -194,7 +192,7 @@ tie-fighter: '|\-*-/|' // "Mark McGwire:\n hr: 65\n avg: 0.278\nSammy Sosa:\n hr: 63\n avg: 0.288\n"; let mut read_in = SANITY_INPUT.as_bytes(); parser.set_input_string(&mut read_in); - let _doc = yaml_parser_load(&mut parser).unwrap(); + let _doc = Document::load(&mut parser).unwrap(); // let mut doc = doc.assume_init(); // let mut emitter = core::mem::MaybeUninit::uninit(); @@ -228,7 +226,7 @@ foo: bar let mut parser = Parser::new(); let mut input = TEST_CASE_QF4Y.as_bytes(); parser.set_input_string(&mut input); - let _doc = yaml_parser_load(&mut parser).unwrap(); + let _doc = Document::load(&mut parser).unwrap(); } // #[test] diff --git a/src/loader.rs b/src/loader.rs deleted file mode 100644 index 2dcf39b..0000000 --- a/src/loader.rs +++ /dev/null @@ -1,390 +0,0 @@ -use alloc::string::String; -use alloc::{vec, vec::Vec}; - -use crate::{ - AliasData, ComposerError, Document, Event, EventData, Mark, Node, NodeData, NodePair, Parser, - DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG, DEFAULT_SEQUENCE_TAG, -}; - -/// Parse the input stream and produce the next YAML document. -/// -/// Call this function subsequently to produce a sequence of documents -/// constituting the input stream. -/// -/// If the produced document has no root node, it means that the document end -/// has been reached. -/// -/// An application must not alternate the calls of -/// [`yaml_parser_load()`](crate::yaml_parser_load) with the calls of -/// [`yaml_parser_scan()`](crate::yaml_parser_scan) or -/// [`yaml_parser_parse()`](crate::yaml_parser_parse). Doing this will break the -/// parser. -pub fn yaml_parser_load(parser: &mut Parser) -> Result { - let mut document = Document::new(None, &[], false, false); - document.nodes.reserve(16); - - if !parser.stream_start_produced { - match parser.parse() { - Ok(Event { - data: EventData::StreamStart { .. }, - .. - }) => (), - Ok(_) => panic!("expected stream start"), - Err(err) => { - yaml_parser_delete_aliases(parser); - return Err(err.into()); - } - } - } - if parser.stream_end_produced { - return Ok(document); - } - let err: ComposerError; - match parser.parse() { - Ok(event) => { - if let EventData::StreamEnd = &event.data { - return Ok(document); - } - parser.aliases.reserve(16); - match yaml_parser_load_document(parser, event, &mut document) { - Ok(()) => { - yaml_parser_delete_aliases(parser); - return Ok(document); - } - Err(e) => err = e, - } - } - Err(e) => err = e.into(), - } - yaml_parser_delete_aliases(parser); - Err(err) -} - -fn yaml_parser_set_composer_error( - problem: &'static str, - problem_mark: Mark, -) -> Result { - Err(ComposerError::Problem { - problem, - mark: problem_mark, - }) -} - -fn yaml_parser_set_composer_error_context( - context: &'static str, - context_mark: Mark, - problem: &'static str, - problem_mark: Mark, -) -> Result { - Err(ComposerError::ProblemWithContext { - context, - context_mark, - problem, - mark: problem_mark, - }) -} - -fn yaml_parser_delete_aliases(parser: &mut Parser) { - parser.aliases.clear(); -} - -fn yaml_parser_load_document( - parser: &mut Parser, - event: Event, - document: &mut Document, -) -> Result<(), ComposerError> { - let mut ctx = vec![]; - if let EventData::DocumentStart { - version_directive, - tag_directives, - implicit, - } = event.data - { - document.version_directive = version_directive; - document.tag_directives = tag_directives; - document.start_implicit = implicit; - document.start_mark = event.start_mark; - ctx.reserve(16); - if let Err(err) = yaml_parser_load_nodes(parser, document, &mut ctx) { - ctx.clear(); - return Err(err); - } - ctx.clear(); - Ok(()) - } else { - panic!("Expected YAML_DOCUMENT_START_EVENT") - } -} - -fn yaml_parser_load_nodes( - parser: &mut Parser, - document: &mut Document, - ctx: &mut Vec, -) -> Result<(), ComposerError> { - let end_implicit; - let end_mark; - - loop { - let event = parser.parse()?; - match event.data { - EventData::NoEvent => panic!("empty event"), - EventData::StreamStart { .. } => panic!("unexpected stream start event"), - EventData::StreamEnd => panic!("unexpected stream end event"), - EventData::DocumentStart { .. } => panic!("unexpected document start event"), - EventData::DocumentEnd { implicit } => { - end_implicit = implicit; - end_mark = event.end_mark; - break; - } - EventData::Alias { .. } => { - yaml_parser_load_alias(parser, event, document, ctx)?; - } - EventData::Scalar { .. } => { - yaml_parser_load_scalar(parser, event, document, ctx)?; - } - EventData::SequenceStart { .. } => { - yaml_parser_load_sequence(parser, event, document, ctx)?; - } - EventData::SequenceEnd => { - yaml_parser_load_sequence_end(parser, event, document, ctx)?; - } - EventData::MappingStart { .. } => { - yaml_parser_load_mapping(parser, event, document, ctx)?; - } - EventData::MappingEnd => { - yaml_parser_load_mapping_end(parser, event, document, ctx)?; - } - } - } - document.end_implicit = end_implicit; - document.end_mark = end_mark; - Ok(()) -} - -fn yaml_parser_register_anchor( - parser: &mut Parser, - document: &mut Document, - index: i32, - anchor: Option, -) -> Result<(), ComposerError> { - let Some(anchor) = anchor else { - return Ok(()); - }; - let data = AliasData { - anchor, - index, - mark: document.nodes[index as usize - 1].start_mark, - }; - for alias_data in &parser.aliases { - if alias_data.anchor == data.anchor { - return yaml_parser_set_composer_error_context( - "found duplicate anchor; first occurrence", - alias_data.mark, - "second occurrence", - data.mark, - ); - } - } - parser.aliases.push(data); - Ok(()) -} - -fn yaml_parser_load_node_add( - document: &mut Document, - ctx: &[i32], - index: i32, -) -> Result<(), ComposerError> { - if ctx.is_empty() { - return Ok(()); - } - let parent_index: i32 = *ctx.last().unwrap(); - let parent = &mut document.nodes[parent_index as usize - 1]; - match parent.data { - NodeData::Sequence { ref mut items, .. } => { - items.push(index); - } - NodeData::Mapping { ref mut pairs, .. } => { - let mut pair = NodePair::default(); - let mut do_push = true; - if !pairs.is_empty() { - let p: &mut NodePair = pairs.last_mut().unwrap(); - if p.key != 0 && p.value == 0 { - p.value = index; - do_push = false; - } - } - if do_push { - pair.key = index; - pair.value = 0; - pairs.push(pair); - } - } - _ => { - panic!("document parent node is not a sequence or a mapping") - } - } - Ok(()) -} - -fn yaml_parser_load_alias( - parser: &mut Parser, - event: Event, - document: &mut Document, - ctx: &[i32], -) -> Result<(), ComposerError> { - let EventData::Alias { anchor } = &event.data else { - unreachable!() - }; - - for alias_data in &parser.aliases { - if alias_data.anchor == *anchor { - return yaml_parser_load_node_add(document, ctx, alias_data.index); - } - } - - yaml_parser_set_composer_error("found undefined alias", event.start_mark) -} - -fn yaml_parser_load_scalar( - parser: &mut Parser, - event: Event, - document: &mut Document, - ctx: &[i32], -) -> Result<(), ComposerError> { - let EventData::Scalar { - mut tag, - value, - style, - anchor, - .. - } = event.data - else { - unreachable!() - }; - - if tag.is_none() || tag.as_deref() == Some("!") { - tag = Some(String::from(DEFAULT_SCALAR_TAG)); - } - let node = Node { - data: NodeData::Scalar { value, style }, - tag, - start_mark: event.start_mark, - end_mark: event.end_mark, - }; - document.nodes.push(node); - let index: i32 = document.nodes.len() as i32; - yaml_parser_register_anchor(parser, document, index, anchor)?; - yaml_parser_load_node_add(document, ctx, index) -} - -fn yaml_parser_load_sequence( - parser: &mut Parser, - event: Event, - document: &mut Document, - ctx: &mut Vec, -) -> Result<(), ComposerError> { - let EventData::SequenceStart { - anchor, - mut tag, - style, - .. - } = event.data - else { - unreachable!() - }; - - let mut items = Vec::with_capacity(16); - - if tag.is_none() || tag.as_deref() == Some("!") { - tag = Some(String::from(DEFAULT_SEQUENCE_TAG)); - } - - let node = Node { - data: NodeData::Sequence { - items: core::mem::take(&mut items), - style, - }, - tag, - start_mark: event.start_mark, - end_mark: event.end_mark, - }; - - document.nodes.push(node); - let index: i32 = document.nodes.len() as i32; - yaml_parser_register_anchor(parser, document, index, anchor)?; - yaml_parser_load_node_add(document, ctx, index)?; - ctx.push(index); - Ok(()) -} - -fn yaml_parser_load_sequence_end( - _parser: &mut Parser, - event: Event, - document: &mut Document, - ctx: &mut Vec, -) -> Result<(), ComposerError> { - assert!(!ctx.is_empty()); - let index: i32 = *ctx.last().unwrap(); - assert!(matches!( - document.nodes[index as usize - 1].data, - NodeData::Sequence { .. } - )); - document.nodes[index as usize - 1].end_mark = event.end_mark; - _ = ctx.pop(); - Ok(()) -} - -fn yaml_parser_load_mapping( - parser: &mut Parser, - event: Event, - document: &mut Document, - ctx: &mut Vec, -) -> Result<(), ComposerError> { - let EventData::MappingStart { - anchor, - mut tag, - style, - .. - } = event.data - else { - unreachable!() - }; - - let mut pairs = Vec::with_capacity(16); - - if tag.is_none() || tag.as_deref() == Some("!") { - tag = Some(String::from(DEFAULT_MAPPING_TAG)); - } - let node = Node { - data: NodeData::Mapping { - pairs: core::mem::take(&mut pairs), - style, - }, - tag, - start_mark: event.start_mark, - end_mark: event.end_mark, - }; - document.nodes.push(node); - let index: i32 = document.nodes.len() as i32; - yaml_parser_register_anchor(parser, document, index, anchor)?; - yaml_parser_load_node_add(document, ctx, index)?; - ctx.push(index); - Ok(()) -} - -fn yaml_parser_load_mapping_end( - _parser: &mut Parser, - event: Event, - document: &mut Document, - ctx: &mut Vec, -) -> Result<(), ComposerError> { - assert!(!ctx.is_empty()); - let index: i32 = *ctx.last().unwrap(); - assert!(matches!( - document.nodes[index as usize - 1].data, - NodeData::Mapping { .. } - )); - document.nodes[index as usize - 1].end_mark = event.end_mark; - _ = ctx.pop(); - Ok(()) -} diff --git a/src/parser.rs b/src/parser.rs index 219ca00..23d7d98 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1081,4 +1081,8 @@ impl<'r> Parser<'r> { self.tag_directives.push(value); Ok(()) } + + pub(crate) fn delete_aliases(&mut self) { + self.aliases.clear(); + } }