Add alias event

This commit is contained in:
Yuheng Chen 2015-05-29 02:26:37 +08:00
parent 3d7a97ad32
commit 68810253e8
3 changed files with 37 additions and 11 deletions

View file

@ -8,4 +8,4 @@ The missing Rust implementation for YAML 1.2.
* Tag directive * Tag directive
* Tag data type are ignored * Tag data type are ignored
* Alias & Anchor * Alias while desearilization

View file

@ -1,4 +1,5 @@
use scanner::*; use scanner::*;
use std::collections::HashMap;
// use yaml::*; // use yaml::*;
#[derive(Clone, Copy, PartialEq, Debug, Eq)] #[derive(Clone, Copy, PartialEq, Debug, Eq)]
@ -61,6 +62,8 @@ pub struct Parser<T> {
state: State, state: State,
marks: Vec<Marker>, marks: Vec<Marker>,
token: Option<Token>, token: Option<Token>,
anchors: HashMap<String, usize>,
anchor_id: usize,
} }
pub trait EventReceiver { pub trait EventReceiver {
@ -77,6 +80,10 @@ impl<T: Iterator<Item=char>> Parser<T> {
state: State::StreamStart, state: State::StreamStart,
marks: Vec::new(), marks: Vec::new(),
token: None, token: None,
anchors: HashMap::new(),
// valid anchor_id starts from 1
anchor_id: 1,
} }
} }
@ -137,6 +144,8 @@ impl<T: Iterator<Item=char>> Parser<T> {
recv.on_event(&Event::StreamEnd); recv.on_event(&Event::StreamEnd);
return Ok(()); return Ok(());
} }
// clear anchors before a new document
self.anchors.clear();
try!(self.load_document(&ev, recv)); try!(self.load_document(&ev, recv));
if !multi { if !multi {
break; break;
@ -370,17 +379,33 @@ impl<T: Iterator<Item=char>> Parser<T> {
Ok(Event::DocumentEnd) Ok(Event::DocumentEnd)
} }
fn register_anchor(&mut self, name: &String, _: &Marker) -> Result<usize, ScanError> {
// 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 { fn parse_node(&mut self, block: bool, indentless_sequence: bool) -> ParseResult {
let mut tok = try!(self.peek()); let mut tok = try!(self.peek());
let anchor_id = 0; let mut anchor_id = 0;
match tok.1 { match tok.1 {
TokenType::AliasToken(v) => { TokenType::AliasToken(name) => {
self.pop_state(); self.pop_state();
self.skip(); self.skip();
// TODO(chenyh): find anchor id // 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(); self.skip();
tok = try!(self.peek()); tok = try!(self.peek());
if let TokenType::TagToken(_, _) = tok.1 { if let TokenType::TagToken(_, _) = tok.1 {
@ -393,7 +418,8 @@ impl<T: Iterator<Item=char>> Parser<T> {
// but we haven't implemented it // but we haven't implemented it
self.skip(); self.skip();
tok = try!(self.peek()); 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(); self.skip();
tok = try!(self.peek()); tok = try!(self.peek());
} }
@ -724,8 +750,3 @@ impl<T: Iterator<Item=char>> Parser<T> {
} }
} }
#[cfg(test)]
mod test {
use super::*;
}

View file

@ -67,3 +67,8 @@ macro_rules! assert_next {
include!("specexamples.rs.inc"); include!("specexamples.rs.inc");
include!("spec_test.rs.inc"); include!("spec_test.rs.inc");
// hand-crafted tests
//#[test]
//fn test_hc_alias() {
//}