diff --git a/parser/src/parser.rs b/parser/src/parser.rs index 4ffab44..dead8e4 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -199,7 +199,7 @@ impl> Parser { fn state_machine(&mut self) -> ParseResult { let next_tok = self.peek(); - //println!("cur_state {:?}, next tok: {:?}", self.state, next_tok); + println!("cur_state {:?}, next tok: {:?}", self.state, next_tok); match self.state { State::StreamStart => self.stream_start(), @@ -222,6 +222,8 @@ impl> Parser { State::FlowSequenceFirstEntry => self.flow_sequence_entry(true), State::FlowSequenceEntry => self.flow_sequence_entry(false), + State::IndentlessSequenceEntry => self.indentless_sequence_entry(), + _ => unimplemented!() } } @@ -464,6 +466,30 @@ impl> Parser { } } + fn indentless_sequence_entry(&mut self) -> ParseResult { + let mut tok = try!(self.peek()); + if tok.1 != TokenType::BlockEntryToken { + self.pop_state(); + return Ok(Event::SequenceEnd); + } + + self.skip(); + tok = try!(self.peek()); + match tok.1 { + TokenType::BlockEntryToken + | TokenType::KeyToken + | TokenType::ValueToken + | TokenType::BlockEndToken => { + self.state = State::IndentlessSequenceEntry; + Ok(Event::empty_scalar()) + }, + _ => { + self.push_state(State::IndentlessSequenceEntry); + self.parse_node(true, false) + } + } + } + fn block_sequence_entry(&mut self, first: bool) -> ParseResult { // BLOCK-SEQUENCE-START if first { diff --git a/parser/src/scanner.rs b/parser/src/scanner.rs index 3f55eda..e56fa8a 100644 --- a/parser/src/scanner.rs +++ b/parser/src/scanner.rs @@ -1,4 +1,5 @@ use std::collections::VecDeque; +use std::char; #[derive(Clone, Copy, PartialEq, Debug, Eq)] pub enum TEncoding { @@ -151,6 +152,21 @@ fn is_blankz(c: char) -> bool { fn is_digit(c: char) -> bool { c >= '0' && c <= '9' } +#[inline] +fn is_hex(c: char) -> bool { + (c >= '0' && c <= '9') + || (c >= 'a' && c <= 'f') + || (c >= 'A' && c <= 'F') +} +#[inline] +fn as_hex(c: char) -> u32 { + match c { + '0'...'9' => (c as u32) - ('0' as u32), + 'a'...'f' => (c as u32) - ('a' as u32) + 10, + 'A'...'F' => (c as u32) - ('A' as u32) + 10, + _ => unreachable!() + } +} pub type ScanResult = Result<(), ScanError>; @@ -804,9 +820,29 @@ impl> Scanner { self.skip(); // Consume an arbitrary escape code. if code_length > 0 { - let val = 0; + let val = 0usize; self.lookahead(code_length); - unimplemented!(); + let mut value = 0u32; + for i in 0..code_length { + if !is_hex(self.buffer[i]) { + return Err(ScanError::new(start_mark, + "while parsing a quoted scalar, did not find expected hexdecimal number")); + } + value = (value << 4) + as_hex(self.buffer[i]); + } + + let ch = match char::from_u32(value) { + Some(v) => v, + None => { + return Err(ScanError::new(start_mark, + "while parsing a quoted scalar, found invalid Unicode character escape code")); + } + }; + string.push(ch); + + for i in 0..code_length { + self.skip(); + } } }, c => { string.push(c); self.skip(); }