Propagate tag to MappingStart event.

This commit is contained in:
Ethiraric 2023-11-19 01:09:41 +01:00
parent e4c4182020
commit ddd768e681
4 changed files with 55 additions and 29 deletions

View file

@ -51,7 +51,7 @@ pub enum Event {
usize, usize,
), ),
/// Value, style, anchor_id, tag /// Value, style, anchor_id, tag
Scalar(String, TScalarStyle, usize, Option<TokenType>), Scalar(String, TScalarStyle, usize, Option<Tag>),
SequenceStart( SequenceStart(
/// The anchor ID of the start of the squence. /// The anchor ID of the start of the squence.
usize, usize,
@ -60,10 +60,21 @@ pub enum Event {
MappingStart( MappingStart(
/// The anchor ID of the start of the mapping. /// The anchor ID of the start of the mapping.
usize, usize,
/// An optional tag
Option<Tag>,
), ),
MappingEnd, MappingEnd,
} }
/// A YAML tag.
#[derive(Clone, PartialEq, Debug, Eq)]
pub struct Tag {
/// Handle of the tag (`!` included).
pub handle: String,
/// The suffix of the tag.
pub suffix: String,
}
impl Event { impl Event {
/// Create an empty scalar. /// Create an empty scalar.
fn empty_scalar() -> Event { fn empty_scalar() -> Event {
@ -72,7 +83,7 @@ impl Event {
} }
/// Create an empty scalar with the given anchor. /// Create an empty scalar with the given anchor.
fn empty_scalar_with_anchor(anchor: usize, tag: Option<TokenType>) -> Event { fn empty_scalar_with_anchor(anchor: usize, tag: Option<Tag>) -> Event {
Event::Scalar(String::new(), TScalarStyle::Plain, anchor, tag) Event::Scalar(String::new(), TScalarStyle::Plain, anchor, tag)
} }
} }
@ -340,7 +351,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
recv.on_event(first_ev, mark); recv.on_event(first_ev, mark);
self.load_sequence(recv) self.load_sequence(recv)
} }
Event::MappingStart(_) => { Event::MappingStart(..) => {
recv.on_event(first_ev, mark); recv.on_event(first_ev, mark);
self.load_mapping(recv) self.load_mapping(recv)
} }
@ -575,8 +586,8 @@ impl<T: Iterator<Item = char>> Parser<T> {
if let Token(mark, TokenType::Anchor(name)) = self.fetch_token() { if let Token(mark, TokenType::Anchor(name)) = self.fetch_token() {
anchor_id = self.register_anchor(name, &mark); anchor_id = self.register_anchor(name, &mark);
if let TokenType::Tag(..) = self.peek_token()?.1 { if let TokenType::Tag(..) = self.peek_token()?.1 {
if let tg @ TokenType::Tag(..) = self.fetch_token().1 { if let TokenType::Tag(handle, suffix) = self.fetch_token().1 {
tag = Some(tg); tag = Some(Tag { handle, suffix });
} else { } else {
unreachable!() unreachable!()
} }
@ -586,9 +597,9 @@ impl<T: Iterator<Item = char>> Parser<T> {
} }
} }
Token(_, TokenType::Tag(..)) => { Token(_, TokenType::Tag(..)) => {
if let tg @ TokenType::Tag(..) = self.fetch_token().1 { if let TokenType::Tag(handle, suffix) = self.fetch_token().1 {
tag = Some(tg); tag = Some(Tag { handle, suffix });
if let TokenType::Anchor(_) = self.peek_token()?.1 { if let TokenType::Anchor(_) = &self.peek_token()?.1 {
if let Token(mark, TokenType::Anchor(name)) = self.fetch_token() { if let Token(mark, TokenType::Anchor(name)) = self.fetch_token() {
anchor_id = self.register_anchor(name, &mark); anchor_id = self.register_anchor(name, &mark);
} else { } else {
@ -620,7 +631,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
} }
Token(mark, TokenType::FlowMappingStart) => { Token(mark, TokenType::FlowMappingStart) => {
self.state = State::FlowMappingFirstKey; self.state = State::FlowMappingFirstKey;
Ok((Event::MappingStart(anchor_id), mark)) Ok((Event::MappingStart(anchor_id, tag), mark))
} }
Token(mark, TokenType::BlockSequenceStart) if block => { Token(mark, TokenType::BlockSequenceStart) if block => {
self.state = State::BlockSequenceFirstEntry; self.state = State::BlockSequenceFirstEntry;
@ -628,7 +639,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
} }
Token(mark, TokenType::BlockMappingStart) if block => { Token(mark, TokenType::BlockMappingStart) if block => {
self.state = State::BlockMappingFirstKey; self.state = State::BlockMappingFirstKey;
Ok((Event::MappingStart(anchor_id), mark)) Ok((Event::MappingStart(anchor_id, tag), mark))
} }
// ex 7.2, an empty scalar can follow a secondary tag // ex 7.2, an empty scalar can follow a secondary tag
Token(mark, _) if tag.is_some() || anchor_id > 0 => { Token(mark, _) if tag.is_some() || anchor_id > 0 => {
@ -819,7 +830,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
Token(mark, TokenType::Key) => { Token(mark, TokenType::Key) => {
self.state = State::FlowSequenceEntryMappingKey; self.state = State::FlowSequenceEntryMappingKey;
self.skip(); self.skip();
Ok((Event::MappingStart(0), mark)) Ok((Event::MappingStart(0, None), mark))
} }
_ => { _ => {
self.push_state(State::FlowSequenceEntry); self.push_state(State::FlowSequenceEntry);

View file

@ -109,26 +109,43 @@ impl fmt::Display for ScanError {
#[derive(Clone, PartialEq, Debug, Eq)] #[derive(Clone, PartialEq, Debug, Eq)]
pub enum TokenType { pub enum TokenType {
NoToken, NoToken,
/// The start of the stream. Sent first, before even [`DocumentStart`].
StreamStart(TEncoding), StreamStart(TEncoding),
/// The end of the stream, EOF.
StreamEnd, StreamEnd,
/// major, minor VersionDirective(
VersionDirective(u32, u32), /// Major
/// handle, prefix u32,
TagDirective(String, String), /// Minor
u32,
),
TagDirective(
/// Handle
String,
/// Prefix
String,
),
/// The start of a YAML document (`---`).
DocumentStart, DocumentStart,
/// The end of a YAML document (`...`).
DocumentEnd, DocumentEnd,
BlockSequenceStart, BlockSequenceStart,
BlockMappingStart, BlockMappingStart,
BlockEnd, BlockEnd,
/// Start of an inline array (`[ a, b ]`).
FlowSequenceStart, FlowSequenceStart,
/// End of an inline array.
FlowSequenceEnd, FlowSequenceEnd,
/// Start of an inline mapping (`{ a: b, c: d }`).
FlowMappingStart, FlowMappingStart,
/// End of an inline mapping.
FlowMappingEnd, FlowMappingEnd,
BlockEntry, BlockEntry,
FlowEntry, FlowEntry,
Key, Key,
Value, Value,
Alias(String), Alias(String),
/// A YAML anchor (`&`/`*`).
Anchor(String), Anchor(String),
/// handle, suffix /// handle, suffix
Tag(String, String), Tag(String, String),

View file

@ -1,6 +1,6 @@
#![allow(clippy::module_name_repetitions)] #![allow(clippy::module_name_repetitions)]
use crate::parser::{Event, MarkedEventReceiver, Parser}; use crate::parser::{Event, MarkedEventReceiver, Parser, Tag};
use crate::scanner::{Marker, ScanError, TScalarStyle, TokenType}; use crate::scanner::{Marker, ScanError, TScalarStyle, TokenType};
use linked_hash_map::LinkedHashMap; use linked_hash_map::LinkedHashMap;
use std::collections::BTreeMap; use std::collections::BTreeMap;
@ -98,7 +98,7 @@ impl MarkedEventReceiver for YamlLoader {
let node = self.doc_stack.pop().unwrap(); let node = self.doc_stack.pop().unwrap();
self.insert_new_node(node); self.insert_new_node(node);
} }
Event::MappingStart(aid) => { Event::MappingStart(aid, _) => {
self.doc_stack.push((Yaml::Hash(Hash::new()), aid)); self.doc_stack.push((Yaml::Hash(Hash::new()), aid));
self.key_stack.push(Yaml::BadValue); self.key_stack.push(Yaml::BadValue);
} }
@ -110,7 +110,7 @@ impl MarkedEventReceiver for YamlLoader {
Event::Scalar(v, style, aid, tag) => { Event::Scalar(v, style, aid, tag) => {
let node = if style != TScalarStyle::Plain { let node = if style != TScalarStyle::Plain {
Yaml::String(v) Yaml::String(v)
} else if let Some(TokenType::Tag(ref handle, ref suffix)) = tag { } else if let Some(Tag { ref handle, ref suffix }) = tag {
// XXX tag:yaml.org,2002: // XXX tag:yaml.org,2002:
if handle == "!!" { if handle == "!!" {
match suffix.as_ref() { match suffix.as_ref() {

View file

@ -3,8 +3,8 @@ use std::fs::{self, DirEntry};
use libtest_mimic::{run_tests, Arguments, Outcome, Test}; use libtest_mimic::{run_tests, Arguments, Outcome, Test};
use yaml_rust::{ use yaml_rust::{
parser::{Event, EventReceiver, Parser}, parser::{Event, EventReceiver, Parser, Tag},
scanner::{TScalarStyle, TokenType}, scanner::{TScalarStyle},
yaml, ScanError, Yaml, YamlLoader, yaml, ScanError, Yaml, YamlLoader,
}; };
@ -148,7 +148,9 @@ impl EventReceiver for EventReporter {
Event::SequenceStart(idx) => format!("+SEQ{}", format_index(idx)), Event::SequenceStart(idx) => format!("+SEQ{}", format_index(idx)),
Event::SequenceEnd => "-SEQ".into(), Event::SequenceEnd => "-SEQ".into(),
Event::MappingStart(idx) => format!("+MAP{}", format_index(idx)), Event::MappingStart(idx, tag) => {
format!("+MAP{}{}", format_index(idx), format_tag(&tag))
}
Event::MappingEnd => "-MAP".into(), Event::MappingEnd => "-MAP".into(),
Event::Scalar(ref text, style, idx, ref tag) => { Event::Scalar(ref text, style, idx, ref tag) => {
@ -197,13 +199,13 @@ fn escape_text(text: &str) -> String {
text text
} }
fn format_tag(tag: &Option<TokenType>) -> String { fn format_tag(tag: &Option<Tag>) -> String {
if let Some(TokenType::Tag(ns, tag)) = tag { if let Some(tag) = tag {
let ns = match ns.as_str() { let ns = match tag.handle.as_str() {
"!!" => "tag:yaml.org,2002:", // Wrong if this ns is overridden "!!" => "tag:yaml.org,2002:", // Wrong if this ns is overridden
other => other, other => other,
}; };
format!(" <{}{}>", ns, tag) format!(" <{}{}>", ns, tag.suffix)
} else { } else {
"".into() "".into()
} }
@ -302,13 +304,9 @@ static EXPECTED_FAILURES: &[&str] = &[
"35KP", "35KP",
"57H4", "57H4",
"6JWB", "6JWB",
"735Y",
"9KAX",
"BU8L",
"C4HZ", "C4HZ",
"EHF6", "EHF6",
"J7PZ", "J7PZ",
"UGM3",
// Cannot resolve tag namespaces // Cannot resolve tag namespaces
"5TYM", "5TYM",
"6CK3", "6CK3",