From 68810253e8c08246d744f1731c500fd3ed3c0316 Mon Sep 17 00:00:00 2001 From: Yuheng Chen Date: Fri, 29 May 2015 02:26:37 +0800 Subject: [PATCH] Add alias event --- saphyr/Readme.md | 2 +- saphyr/src/parser.rs | 41 +++++++++++++++++++++++++++++---------- saphyr/tests/spec_test.rs | 5 +++++ 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/saphyr/Readme.md b/saphyr/Readme.md index fb9de9f..58ac418 100644 --- a/saphyr/Readme.md +++ b/saphyr/Readme.md @@ -8,4 +8,4 @@ The missing Rust implementation for YAML 1.2. * Tag directive * Tag data type are ignored -* Alias & Anchor +* Alias while desearilization diff --git a/saphyr/src/parser.rs b/saphyr/src/parser.rs index 5608d63..fcbf37c 100644 --- a/saphyr/src/parser.rs +++ b/saphyr/src/parser.rs @@ -1,4 +1,5 @@ use scanner::*; +use std::collections::HashMap; // use yaml::*; #[derive(Clone, Copy, PartialEq, Debug, Eq)] @@ -61,6 +62,8 @@ pub struct Parser { state: State, marks: Vec, token: Option, + anchors: HashMap, + anchor_id: usize, } pub trait EventReceiver { @@ -77,6 +80,10 @@ impl> Parser { state: State::StreamStart, marks: Vec::new(), token: None, + + anchors: HashMap::new(), + // valid anchor_id starts from 1 + anchor_id: 1, } } @@ -137,6 +144,8 @@ impl> Parser { recv.on_event(&Event::StreamEnd); return Ok(()); } + // clear anchors before a new document + self.anchors.clear(); try!(self.load_document(&ev, recv)); if !multi { break; @@ -370,17 +379,33 @@ impl> Parser { Ok(Event::DocumentEnd) } + fn register_anchor(&mut self, name: &String, _: &Marker) -> Result { + // anchors can be overrided/reused + // if self.anchors.contains_key(name) { + // return Err(ScanError::new(*mark, + // "while parsing anchor, found duplicated anchor")); + // } + let new_id = self.anchor_id; + self.anchor_id += 1; + self.anchors.insert(name.clone(), new_id); + Ok(new_id) + } + fn parse_node(&mut self, block: bool, indentless_sequence: bool) -> ParseResult { let mut tok = try!(self.peek()); - let anchor_id = 0; + let mut anchor_id = 0; match tok.1 { - TokenType::AliasToken(v) => { + TokenType::AliasToken(name) => { self.pop_state(); self.skip(); // TODO(chenyh): find anchor id - return Ok(Event::Alias(0)); + match self.anchors.get(&name) { + None => return Err(ScanError::new(tok.0, "while parsing node, found unknown anchor")), + Some(id) => return Ok(Event::Alias(*id)) + } }, - TokenType::AnchorToken(..) => { + TokenType::AnchorToken(name) => { + anchor_id = try!(self.register_anchor(&name, &tok.0)); self.skip(); tok = try!(self.peek()); if let TokenType::TagToken(_, _) = tok.1 { @@ -393,7 +418,8 @@ impl> Parser { // but we haven't implemented it self.skip(); tok = try!(self.peek()); - if let TokenType::AnchorToken(_) = tok.1 { + if let TokenType::AnchorToken(name) = tok.1 { + anchor_id = try!(self.register_anchor(&name, &tok.0)); self.skip(); tok = try!(self.peek()); } @@ -724,8 +750,3 @@ impl> Parser { } } -#[cfg(test)] -mod test { - use super::*; -} - diff --git a/saphyr/tests/spec_test.rs b/saphyr/tests/spec_test.rs index f6342a3..bbb647f 100644 --- a/saphyr/tests/spec_test.rs +++ b/saphyr/tests/spec_test.rs @@ -67,3 +67,8 @@ macro_rules! assert_next { include!("specexamples.rs.inc"); include!("spec_test.rs.inc"); +// hand-crafted tests +//#[test] +//fn test_hc_alias() { +//} +