Changed libfmt_macros Parse iterator to Peekable

This commit is contained in:
Simon Mazur 2015-09-10 15:03:22 +03:00
parent 1a1e6b85f6
commit 69092ffdf2

View File

@ -37,6 +37,7 @@ pub use self::Count::*;
use std::str; use std::str;
use std::string; use std::string;
use std::iter;
/// A piece is a portion of the format string which represents the next part /// A piece is a portion of the format string which represents the next part
/// to emit. These are emitted as a stream by the `Parser` class. /// to emit. These are emitted as a stream by the `Parser` class.
@ -141,7 +142,7 @@ pub enum Count<'a> {
/// necessary there's probably lots of room for improvement performance-wise. /// necessary there's probably lots of room for improvement performance-wise.
pub struct Parser<'a> { pub struct Parser<'a> {
input: &'a str, input: &'a str,
cur: str::CharIndices<'a>, cur: iter::Peekable<str::CharIndices<'a>>,
/// Error messages accumulated during parsing /// Error messages accumulated during parsing
pub errors: Vec<string::String>, pub errors: Vec<string::String>,
} }
@ -150,8 +151,8 @@ impl<'a> Iterator for Parser<'a> {
type Item = Piece<'a>; type Item = Piece<'a>;
fn next(&mut self) -> Option<Piece<'a>> { fn next(&mut self) -> Option<Piece<'a>> {
match self.cur.clone().next() { match self.cur.peek() {
Some((pos, '{')) => { Some(&(pos, '{')) => {
self.cur.next(); self.cur.next();
if self.consume('{') { if self.consume('{') {
Some(String(self.string(pos + 1))) Some(String(self.string(pos + 1)))
@ -161,7 +162,7 @@ impl<'a> Iterator for Parser<'a> {
ret ret
} }
} }
Some((pos, '}')) => { Some(&(pos, '}')) => {
self.cur.next(); self.cur.next();
if self.consume('}') { if self.consume('}') {
Some(String(self.string(pos + 1))) Some(String(self.string(pos + 1)))
@ -170,7 +171,7 @@ impl<'a> Iterator for Parser<'a> {
None None
} }
} }
Some((pos, _)) => { Some(String(self.string(pos))) } Some(&(pos, _)) => { Some(String(self.string(pos))) }
None => None None => None
} }
} }
@ -181,7 +182,7 @@ impl<'a> Parser<'a> {
pub fn new(s: &'a str) -> Parser<'a> { pub fn new(s: &'a str) -> Parser<'a> {
Parser { Parser {
input: s, input: s,
cur: s.char_indices(), cur: s.char_indices().peekable(),
errors: vec!(), errors: vec!(),
} }
} }
@ -197,8 +198,8 @@ impl<'a> Parser<'a> {
/// the current position, then the current iterator isn't moved and false is /// the current position, then the current iterator isn't moved and false is
/// returned, otherwise the character is consumed and true is returned. /// returned, otherwise the character is consumed and true is returned.
fn consume(&mut self, c: char) -> bool { fn consume(&mut self, c: char) -> bool {
match self.cur.clone().next() { match self.cur.peek() {
Some((_, maybe)) if c == maybe => { Some(&(_, maybe)) if c == maybe => {
self.cur.next(); self.cur.next();
true true
} }
@ -210,11 +211,11 @@ impl<'a> Parser<'a> {
/// found, an error is emitted. /// found, an error is emitted.
fn must_consume(&mut self, c: char) { fn must_consume(&mut self, c: char) {
self.ws(); self.ws();
match self.cur.clone().next() { match self.cur.peek() {
Some((_, maybe)) if c == maybe => { Some(&(_, maybe)) if c == maybe => {
self.cur.next(); self.cur.next();
} }
Some((_, other)) => { Some(&(_, other)) => {
self.err(&format!("expected `{:?}`, found `{:?}`", c, self.err(&format!("expected `{:?}`, found `{:?}`", c,
other)); other));
} }
@ -229,8 +230,8 @@ impl<'a> Parser<'a> {
/// character /// character
fn ws(&mut self) { fn ws(&mut self) {
loop { loop {
match self.cur.clone().next() { match self.cur.peek() {
Some((_, c)) if c.is_whitespace() => { self.cur.next(); } Some(&(_, c)) if c.is_whitespace() => { self.cur.next(); }
Some(..) | None => { return } Some(..) | None => { return }
} }
} }
@ -241,8 +242,8 @@ impl<'a> Parser<'a> {
fn string(&mut self, start: usize) -> &'a str { fn string(&mut self, start: usize) -> &'a str {
loop { loop {
// we may not consume the character, so clone the iterator // we may not consume the character, so clone the iterator
match self.cur.clone().next() { match self.cur.peek() {
Some((pos, '}')) | Some((pos, '{')) => { Some(&(pos, '}')) | Some(&(pos, '{')) => {
return &self.input[start..pos]; return &self.input[start..pos];
} }
Some(..) => { self.cur.next(); } Some(..) => { self.cur.next(); }
@ -269,8 +270,8 @@ impl<'a> Parser<'a> {
match self.integer() { match self.integer() {
Some(i) => { ArgumentIs(i) } Some(i) => { ArgumentIs(i) }
None => { None => {
match self.cur.clone().next() { match self.cur.peek() {
Some((_, c)) if c.is_alphabetic() => { Some(&(_, c)) if c.is_alphabetic() => {
ArgumentNamed(self.word()) ArgumentNamed(self.word())
} }
_ => ArgumentNext _ => ArgumentNext
@ -293,8 +294,8 @@ impl<'a> Parser<'a> {
if !self.consume(':') { return spec } if !self.consume(':') { return spec }
// fill character // fill character
match self.cur.clone().next() { match self.cur.peek() {
Some((_, c)) => { Some(&(_, c)) => {
match self.cur.clone().skip(1).next() { match self.cur.clone().skip(1).next() {
Some((_, '>')) | Some((_, '<')) | Some((_, '^')) => { Some((_, '>')) | Some((_, '<')) | Some((_, '^')) => {
spec.fill = Some(c); spec.fill = Some(c);
@ -392,8 +393,8 @@ impl<'a> Parser<'a> {
/// be an alphabetic character followed by any number of alphanumeric /// be an alphabetic character followed by any number of alphanumeric
/// characters. /// characters.
fn word(&mut self) -> &'a str { fn word(&mut self) -> &'a str {
let start = match self.cur.clone().next() { let start = match self.cur.peek() {
Some((pos, c)) if c.is_xid_start() => { Some(&(pos, c)) if c.is_xid_start() => {
self.cur.next(); self.cur.next();
pos pos
} }
@ -401,11 +402,11 @@ impl<'a> Parser<'a> {
}; };
let end; let end;
loop { loop {
match self.cur.clone().next() { match self.cur.peek() {
Some((_, c)) if c.is_xid_continue() => { Some(&(_, c)) if c.is_xid_continue() => {
self.cur.next(); self.cur.next();
} }
Some((pos, _)) => { end = pos; break } Some(&(pos, _)) => { end = pos; break }
None => { end = self.input.len(); break } None => { end = self.input.len(); break }
} }
} }
@ -417,7 +418,7 @@ impl<'a> Parser<'a> {
fn integer(&mut self) -> Option<usize> { fn integer(&mut self) -> Option<usize> {
let mut cur = 0; let mut cur = 0;
let mut found = false; let mut found = false;
while let Some((_, c)) = self.cur.clone().next() { while let Some(&(_, c)) = self.cur.peek() {
if let Some(i) = c.to_digit(10) { if let Some(i) = c.to_digit(10) {
cur = cur * 10 + i as usize; cur = cur * 10 + i as usize;
found = true; found = true;