Move yaml_parser_load to Document::load

This commit is contained in:
Simon Ask Ulsnes 2024-02-04 10:55:28 +01:00
parent dc69732a25
commit eae9fe8a4c
4 changed files with 366 additions and 396 deletions

View file

@ -1,6 +1,7 @@
use crate::{ use crate::{
MappingStyle, Mark, ScalarStyle, SequenceStyle, TagDirective, VersionDirective, AliasData, ComposerError, Event, EventData, MappingStyle, Mark, Parser, ScalarStyle,
DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG, DEFAULT_SEQUENCE_TAG, SequenceStyle, TagDirective, VersionDirective, DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG,
DEFAULT_SEQUENCE_TAG,
}; };
/// The document structure. /// The document structure.
@ -248,4 +249,361 @@ impl Document {
pairs.push(pair); 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<Document, ComposerError> {
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<T>(
problem: &'static str,
problem_mark: Mark,
) -> Result<T, ComposerError> {
Err(ComposerError::Problem {
problem,
mark: problem_mark,
})
}
fn set_composer_error_context<T>(
context: &'static str,
context_mark: Mark,
problem: &'static str,
problem_mark: Mark,
) -> Result<T, ComposerError> {
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<i32>) -> 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<String>,
) -> 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<i32>,
) -> 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<i32>) -> 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<i32>,
) -> 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<i32>) -> 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(())
}
} }

View file

@ -32,7 +32,6 @@ mod dumper;
mod emitter; mod emitter;
mod error; mod error;
mod event; mod event;
mod loader;
mod parser; mod parser;
mod reader; mod reader;
mod scanner; 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::emitter::*;
pub use crate::error::*; pub use crate::error::*;
pub use crate::event::*; pub use crate::event::*;
pub use crate::loader::yaml_parser_load;
pub use crate::parser::*; pub use crate::parser::*;
pub use crate::scanner::yaml_parser_scan; pub use crate::scanner::yaml_parser_scan;
pub use crate::token::*; 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"; // "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(); let mut read_in = SANITY_INPUT.as_bytes();
parser.set_input_string(&mut read_in); 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 doc = doc.assume_init();
// let mut emitter = core::mem::MaybeUninit::uninit(); // let mut emitter = core::mem::MaybeUninit::uninit();
@ -228,7 +226,7 @@ foo: bar
let mut parser = Parser::new(); let mut parser = Parser::new();
let mut input = TEST_CASE_QF4Y.as_bytes(); let mut input = TEST_CASE_QF4Y.as_bytes();
parser.set_input_string(&mut input); parser.set_input_string(&mut input);
let _doc = yaml_parser_load(&mut parser).unwrap(); let _doc = Document::load(&mut parser).unwrap();
} }
// #[test] // #[test]

View file

@ -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<Document, ComposerError> {
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<T>(
problem: &'static str,
problem_mark: Mark,
) -> Result<T, ComposerError> {
Err(ComposerError::Problem {
problem,
mark: problem_mark,
})
}
fn yaml_parser_set_composer_error_context<T>(
context: &'static str,
context_mark: Mark,
problem: &'static str,
problem_mark: Mark,
) -> Result<T, ComposerError> {
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<i32>,
) -> 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<String>,
) -> 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<i32>,
) -> 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<i32>,
) -> 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<i32>,
) -> 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<i32>,
) -> 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(())
}

View file

@ -1081,4 +1081,8 @@ impl<'r> Parser<'r> {
self.tag_directives.push(value); self.tag_directives.push(value);
Ok(()) Ok(())
} }
pub(crate) fn delete_aliases(&mut self) {
self.aliases.clear();
}
} }