pub use self::{
base::{Parser, TakeOpt},
error::{PError, PResult},
};
use crate::{repr::Repr, *};
use alloc::{
collections::BTreeMap,
string::{String, ToString},
vec,
vec::Vec,
};
use core::ops::{Deref, DerefMut};
mod base;
mod error;
macro_rules! tag_prefix {
() => {
"tag:yaml.org,2002:"
};
}
pub(crate) use tag_prefix;
pub type Anchors<R> = BTreeMap<String, Node<R>>;
pub const DEFAULT_PREFIX: &str = tag_prefix!();
pub struct Loader<'a, R: Repr> {
pub parser: Parser<'a>,
cyclic_mode: bool,
anchors: Vec<Anchors<R>>,
doc_ind: usize,
}
impl<'a, R: Repr> Loader<'a, R> {
pub fn new(doc: &'a [u8]) -> Self {
Self {
parser: Parser::new(doc),
cyclic_mode: false,
anchors: Vec::new(),
doc_ind: 0,
}
}
}
impl<R: Repr> Loader<'_, R> {
pub fn cyclic_mode(self, cyclic_mode: bool) -> Self {
Self { cyclic_mode, ..self }
}
pub fn get_anchors(self) -> Vec<Anchors<R>> {
self.anchors
}
pub fn parse(&mut self) -> PResult<Vec<Node<R>>> {
loop {
match self.context(Parser::directive) {
Ok(()) => (),
Err(PError::Mismatch) => break,
Err(e) => return Err(e),
}
}
self.gap(true).unwrap_or_default();
self.sym_seq(b"---").unwrap_or_default();
let mut v = vec![self.doc()?];
loop {
self.gap(true).unwrap_or_default();
if self.food().is_empty() {
break;
}
if self.sym_seq(b"---").is_err() {
return self.err("document splitter");
}
v.push(self.doc()?);
}
Ok(v)
}
pub fn doc(&mut self) -> PResult<Node<R>> {
self.context(|p| p.bound().unwrap_or_default());
self.forward();
self.anchors.push(Anchors::new());
let ret = self.scalar(0, false, false)?;
self.gap(true).unwrap_or_default();
self.sym_seq(b"...").unwrap_or_default();
self.forward();
self.doc_ind += 1;
Ok(ret)
}
pub fn doc_end(&mut self) -> bool {
if self.food().is_empty() {
true
} else {
self.context(|p| {
let b = p.sym_seq(b"---").is_ok() || p.sym_seq(b"...").is_ok();
if b {
p.backward();
}
b
})
}
}
pub fn scalar(&mut self, level: usize, map: bool, flow: bool) -> PResult<Node<R>> {
self.scalar_node(|p| {
if let Ok(s) = p.string_literal(level) {
Ok(R::new_rc(Yaml::Str(s)))
} else if let Ok(s) = p.string_folded(level) {
Ok(R::new_rc(Yaml::Str(s)))
} else {
p.seq(level, map)
.or_else(|e| e.or(|| p.map(level, map, flow)))
.or_else(|e| e.or(|| p.scalar_term(level, flow)))
}
})
}
pub fn scalar_flow(&mut self, level: usize, flow: bool) -> PResult<Node<R>> {
self.scalar_node(|p| p.scalar_term(level, flow))
}
fn scalar_node<F>(&mut self, f: F) -> PResult<Node<R>>
where
F: FnOnce(&mut Self) -> PResult<R::Rc>,
{
let mut anchor = self.anchor().unwrap_or_default();
if !anchor.is_empty() {
self.bound()?;
}
self.forward();
let tag = self.tag().unwrap_or_default();
if !tag.is_empty() {
self.bound()?;
}
self.forward();
let anchor2 = self.anchor().unwrap_or_default();
if !anchor2.is_empty() {
if anchor.is_empty() {
self.bound()?;
anchor = anchor2;
} else {
return self.err("duplicated anchor definition");
}
}
self.forward();
let pos = self.indicator();
let yaml = f(self)?;
self.forward();
let node = Node::new_repr(yaml, pos, &tag);
if !anchor.is_empty()
&& self.anchors[self.doc_ind]
.insert(anchor, node.clone())
.is_some()
{
self.err("duplicated anchor definition")
} else {
Ok(node)
}
}
pub fn scalar_term(&mut self, level: usize, flow: bool) -> PResult<R::Rc> {
let yaml = if let Ok(s) = self.float() {
R::new_rc(Yaml::Float(s))
} else if let Ok(s) = self.sci_float() {
R::new_rc(Yaml::Float(s))
} else if let Ok(s) = self.int() {
R::new_rc(Yaml::Int(s))
} else if let Ok(s) = self.anchor_use() {
if self.cyclic_mode {
R::new_rc(Yaml::Alias(s))
} else if let Some(node) = self.anchors[self.doc_ind].get(&s) {
node.clone_yaml()
} else {
return self.err("anchor referenced before definition");
}
} else if let Ok(s) = self.string_quoted(b'\'', b"''") {
R::new_rc(Yaml::Str(s))
} else if let Ok(s) = self.string_quoted(b'"', b"\\\"") {
R::new_rc(Yaml::Str(Parser::escape(&s)))
} else if let Ok(s) = self.string_plain(level, flow) {
R::new_rc(match s.as_str() {
"~" | "null" | "Null" | "NULL" => Yaml::Null,
"true" | "True" | "TRUE" => Yaml::Bool(true),
"false" | "False" | "FALSE" => Yaml::Bool(false),
".nan" | ".NaN" | ".NAN" => Yaml::Float("NaN".to_string()),
".inf" | ".Inf" | ".INF" => Yaml::Float("inf".to_string()),
"-.inf" | "-.Inf" | "-.INF" => Yaml::Float("-inf".to_string()),
_ => Yaml::Str(s),
})
} else {
self.seq_flow(level)
.or_else(|e| e.or(|| self.map_flow(level)))
.or_else(|e| e.or(|| Ok(R::new_rc(Yaml::Null))))?
};
Ok(yaml)
}
pub fn seq_flow(&mut self, level: usize) -> PResult<R::Rc> {
self.sym(b'[')?;
let mut v = vec![];
loop {
self.inv(TakeOpt::More(0))?;
self.forward();
if self.sym(b']').is_ok() {
break;
}
self.forward();
let n = self
.scalar(level + 1, false, true)
.or_else(|e| e.or(|| self.err("flow sequence item")))?;
v.push(n);
self.inv(TakeOpt::More(0))?;
if self.sym(b',').is_err() {
self.inv(TakeOpt::More(0))?;
self.sym(b']')?;
break;
}
}
self.forward();
Ok(R::new_rc(v.into_iter().collect()))
}
pub fn map_flow(&mut self, level: usize) -> PResult<R::Rc> {
self.sym(b'{')?;
let mut m = vec![];
loop {
self.inv(TakeOpt::More(0))?;
self.forward();
if self.sym(b'}').is_ok() {
break;
}
self.forward();
let k = if self.complex_mapping().is_ok() {
self.forward();
let k = self
.scalar(level + 1, false, true)
.or_else(|e| e.or(|| self.err("flow map key")))?;
if self.gap(true).is_ok() {
self.ind(level)?;
}
k
} else {
self.scalar_flow(level + 1, true)
.or_else(|e| e.or(|| self.err("flow map key")))?
};
if self.sym(b':').is_err() {
return self.err("flow map splitter");
}
self.context(|p| p.bound().unwrap_or_default());
self.forward();
let v = self
.scalar(level + 1, false, true)
.or_else(|e| e.or(|| self.err("flow map value")))?;
m.push((k, v));
if self.sym(b',').is_err() {
self.inv(TakeOpt::More(0))?;
self.sym(b'}')?;
break;
}
}
self.forward();
Ok(R::new_rc(m.into_iter().collect()))
}
pub fn seq(&mut self, level: usize, map: bool) -> PResult<R::Rc> {
let mut v = vec![];
loop {
self.forward();
if v.is_empty() {
if map {
self.gap(true)?;
self.ind_define(level)?;
} else if self.gap(true).is_ok() {
self.ind(level)?;
}
self.sym(b'-')?;
self.bound()?;
} else {
if self.gap(true).is_err() && !self.doc_end() {
return self.err("sequence terminator");
}
if self.doc_end() || self.ind(level).is_err() {
break;
}
if self.sym(b'-').is_err() || self.bound().is_err() {
break;
}
self.forward();
}
self.forward();
let n = self
.scalar(level + 1, false, false)
.or_else(|e| e.or(|| self.err("sequence item")))?;
v.push(n);
}
self.backward();
Ok(R::new_rc(v.into_iter().collect()))
}
pub fn map(&mut self, level: usize, map: bool, flow: bool) -> PResult<R::Rc> {
let mut m = vec![];
loop {
self.forward();
let k = if m.is_empty() {
if map {
self.gap(true)?;
self.ind_define(level)?;
} else if self.gap(true).is_ok() {
self.ind(level)?;
}
self.forward();
let k = if self.complex_mapping().is_ok() {
self.forward();
let k = self
.scalar(level + 1, true, flow)
.or_else(|e| e.or(|| self.err("map key")))?;
if self.gap(true).is_ok() {
self.ind(level)?;
}
k
} else {
self.scalar_flow(level + 1, flow)?
};
if self.sym(b':').is_err() || self.bound().is_err() {
return Ok(k.clone_yaml());
}
k
} else {
if self.gap(true).is_err() && !self.doc_end() {
return self.err("map terminator");
}
if self.doc_end() || self.ind(level).is_err() {
break;
}
self.forward();
let k = if self.complex_mapping().is_ok() {
self.forward();
let k = self
.scalar(level + 1, true, flow)
.or_else(|e| e.or(|| self.err("map key")))?;
if self.gap(true).is_ok() {
self.ind(level)?;
}
k
} else {
self.scalar_flow(level + 1, flow)
.or_else(|e| e.or(|| self.err("map key")))?
};
if self.sym(b':').is_err() || self.bound().is_err() {
return self.err("map splitter");
}
k
};
self.forward();
let v = self
.scalar(level + 1, true, false)
.or_else(|e| e.or(|| self.err("map value")))?;
m.push((k, v));
}
self.backward();
Ok(R::new_rc(m.into_iter().collect()))
}
}
impl<'a, R: Repr> Deref for Loader<'a, R> {
type Target = Parser<'a>;
fn deref(&self) -> &Self::Target {
&self.parser
}
}
impl<R: Repr> DerefMut for Loader<'_, R> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.parser
}
}
pub fn parse<R: Repr>(doc: &str) -> Result<Seq<R>, PError> {
Loader::new(doc.as_bytes()).parse()
}
pub fn parse_cyclic<R: Repr>(doc: &str) -> Result<(Seq<R>, Vec<Anchors<R>>), PError> {
let mut loader = Loader::new(doc.as_bytes()).cyclic_mode(true);
loader.parse().map(|root| (root, loader.get_anchors()))
}