fn finish_basic_string(&mut self,
                           start: usize,
                           multiline: bool) -> Option<String> {
        let mut ret = String::new();
        loop {
            while multiline && self.newline() { ret.push('\n') }
            match self.cur.next() {
                Some((_, '"')) => {
                    if multiline {
                        if !self.eat('"') { ret.push_str("\""); continue }
                        if !self.eat('"') { ret.push_str("\"\""); continue }
                    }
                    return Some(ret)
                }
                Some((pos, '\\')) => {
                    if let Some(c) = escape(self, pos, multiline) {
                        ret.push(c);
                    }
                }
                Some((pos, ch)) if ch < '\u{1f}' => {
                    self.errors.push(ParserError {
                        lo: pos,
                        hi: pos + 1,
                        desc: format!("control character `{}` must be escaped",
                                      ch.escape_default().collect::<String>())
                    });
                }
                Some((_, ch)) => ret.push(ch),
                None => {
                    self.errors.push(ParserError {
                        lo: start,
                        hi: self.input.len(),
                        desc: format!("unterminated string literal"),
                    });
                    return None
                }
            }
        }

        fn escape(me: &mut Parser, pos: usize, multiline: bool) -> Option<char> {
            if multiline && me.newline() {
                while me.ws() || me.newline() { /* ... */ }
                return None
            }
            match me.cur.next() {
                Some((_, 'b')) => Some('\u{8}'),
                Some((_, 't')) => Some('\u{9}'),
                Some((_, 'n')) => Some('\u{a}'),
                Some((_, 'f')) => Some('\u{c}'),
                Some((_, 'r')) => Some('\u{d}'),
                Some((_, '"')) => Some('\u{22}'),
                Some((_, '\\')) => Some('\u{5c}'),
                Some((pos, c @ 'u')) |
                Some((pos, c @ 'U')) => {
                    let len = if c == 'u' {4} else {8};
                    let num = &me.input[pos+1..];
                    let num = if num.char_indices().nth(len).map(|(i, _)| i).unwrap_or(0) == len {
                        &num[..len]
                    } else {
                        "invalid"
                    };
                    if let Some(n) = u32::from_str_radix(num, 16).ok() {
                        if let Some(c) = char::from_u32(n) {
                            me.cur.by_ref().skip(len - 1).next();
                            return Some(c)
                        } else {
                            me.errors.push(ParserError {
                                lo: pos + 1,
                                hi: pos + 5,
                                desc: format!("codepoint `{:x}` is \
                                               not a valid unicode \
                                               codepoint", n),
                            })
                        }
                    } else {
                        me.errors.push(ParserError {
                            lo: pos,
                            hi: pos + 1,
                            desc: format!("expected {} hex digits \
                                           after a `{}` escape", len, c),
                        })
                    }
                    None
                }
                Some((pos, ch)) => {
                    let next_pos = me.next_pos();
                    me.errors.push(ParserError {
                        lo: pos,
                        hi: next_pos,
                        desc: format!("unknown string escape: `{}`",
                                      ch.escape_default().collect::<String>()),
                    });
                    None
                }
                None => {
                    me.errors.push(ParserError {
                        lo: pos,
                        hi: pos + 1,
                        desc: format!("unterminated escape sequence"),
                    });
                    None
                }
            }
        }
    }
// Finish parsing a basic string after the opening quote has been seen
Finish parsing a basic string after the opening quote has been seen
Finish parsing a basic string after the opening quote has been seen
fn finish_basic_string(&mut self,
                           start: usize,
                           multiline: bool) -> Option<String> {
        let mut ret = String::new();
        loop {
            while multiline && self.newline() { ret.push('\n') }
            match self.cur.next() {
                Some((_, '"')) => {
                    if multiline {
                        if !self.eat('"') { ret.push_str("\""); continue }
                        if !self.eat('"') { ret.push_str("\"\""); continue }
                    }
                    return Some(ret)
                }
                Some((pos, '\\')) => {
                    if let Some(c) = escape(self, pos, multiline) {
                        ret.push(c);
                    }
                }
                Some((pos, ch)) if ch < '\u{1f}' => {
                    self.errors.push(ParserError {
                        lo: pos,
                        hi: pos + 1,
                        desc: format!("control character `{}` must be escaped",
                                      ch.escape_default().collect::<String>())
                    });
                }
                Some((_, ch)) => ret.push(ch),
                None => {
                    self.errors.push(ParserError {
                        lo: start,
                        hi: self.input.len(),
                        desc: format!("unterminated string literal"),
                    });
                    return None
                }
            }
        }
        fn escape(me: &mut Parser, pos: usize, multiline: bool) -> Option<char> {
            if multiline && me.newline() {
                while me.ws() || me.newline() { /* ... */ }
                return None
            }
            match me.cur.next() {
                Some((_, 'b')) => Some('\u{8}'),
                Some((_, 't')) => Some('\u{9}'),
                Some((_, 'n')) => Some('\u{a}'),
                Some((_, 'f')) => Some('\u{c}'),
                Some((_, 'r')) => Some('\u{d}'),
                Some((_, '"')) => Some('\u{22}'),
                Some((_, '\\')) => Some('\u{5c}'),
                Some((pos, c @ 'u')) |
                Some((pos, c @ 'U')) => {
                    let len = if c == 'u' {4} else {8};
                    let num = &me.input[pos+1..];
                    let num = if num.char_indices().nth(len).map(|(i, _)| i).unwrap_or(0) == len {
                        &num[..len]
                    } else {
                        "invalid"
                    };
                    if let Some(n) = u32::from_str_radix(num, 16).ok() {
                        if let Some(c) = char::from_u32(n) {
                            me.cur.by_ref().skip(len - 1).next();
                            return Some(c)
                        } else {
                            me.errors.push(ParserError {
                                lo: pos + 1,
                                hi: pos + 5,
                                desc: format!("codepoint `{:x}` is \
                                               not a valid unicode \
                                               codepoint", n),
                            })
                        }
                    } else {
                        me.errors.push(ParserError {
                            lo: pos,
                            hi: pos + 1,
                            desc: format!("expected {} hex digits \
                                           after a `{}` escape", len, c),
                        })
                    }
                    None
                }
                Some((pos, ch)) => {
                    let next_pos = me.next_pos();
                    me.errors.push(ParserError {
                        lo: pos,
                        hi: next_pos,
                        desc: format!("unknown string escape: `{}`",
                                      ch.escape_default().collect::<String>()),
                    });
                    None
                }
                None => {
                    me.errors.push(ParserError {
                        lo: pos,
                        hi: pos + 1,
                        desc: format!("unterminated escape sequence"),
                    });
                    None
                }
            }
        }
    }
fn finish_basic_string ( & mut self , start : usize , multiline : bool ) -> Option < String > { let mut ret = String :: new ( ) ; loop { while multiline && self . newline ( ) { ret . push ( '\n' ) } match self . cur . next ( ) { Some ( ( _ , '"' ) ) => { if multiline { if ! self . eat ( '"' ) { ret . push_str ( " \" " ) ; continue } if ! self . eat ( '"' ) { ret . push_str ( " \" \" " ) ; continue } } return Some ( ret ) } Some ( ( pos , '\\' ) ) => { if let Some ( c ) = escape ( self , pos , multiline ) { ret . push ( c ) ; } } Some ( ( pos , ch ) ) if ch < '\u{1f}' => { self . errors . push ( ParserError { lo : pos , hi : pos + 1 , desc : format ! ( " " ch escape_default ( ) collect String ( ) ) } ) ; } Some ( ( _ , ch ) ) => ret . push ( ch ) , None => { self . errors . push ( ParserError { lo : start , hi : self . input . len ( ) , desc : format ! ( " " ) , } ) ; return None } } } fn escape ( me : & mut Parser , pos : usize , multiline : bool ) -> Option < char > { if multiline && me . newline ( ) { while me . ws ( ) || me . newline ( ) { /* ... */ } return None } match me . cur . next ( ) { Some ( ( _ , 'b' ) ) => Some ( '\u{8}' ) , Some ( ( _ , 't' ) ) => Some ( '\u{9}' ) , Some ( ( _ , 'n' ) ) => Some ( '\u{a}' ) , Some ( ( _ , 'f' ) ) => Some ( '\u{c}' ) , Some ( ( _ , 'r' ) ) => Some ( '\u{d}' ) , Some ( ( _ , '"' ) ) => Some ( '\u{22}' ) , Some ( ( _ , '\\' ) ) => Some ( '\u{5c}' ) , Some ( ( pos , c @ 'u' ) ) | Some ( ( pos , c @ 'U' ) ) => { let len = if c == 'u' { 4 } else { 8 } ; let num = & me . input [ pos + 1 .. ] ; let num = if num . char_indices ( ) . nth ( len ) . map ( | ( i , _ ) | i ) . unwrap_or ( 0 ) == len { & num [ .. len ] } else { " " } ; if let Some ( n ) = u32 :: from_str_radix ( num , 16 ) . ok ( ) { if let Some ( c ) = char :: from_u32 ( n ) { me . cur . by_ref ( ) . skip ( len - 1 ) . next ( ) ; return Some ( c ) } else { me . errors . push ( ParserError { lo : pos + 1 , hi : pos + 5 , desc : format ! ( " \
 \
 " n ) , } ) } } else { me . errors . push ( ParserError { lo : pos , hi : pos + 1 , desc : format ! ( " \
 " len c ) , } ) } None } Some ( ( pos , ch ) ) => { let next_pos = me . next_pos ( ) ; me . errors . push ( ParserError { lo : pos , hi : next_pos , desc : format ! ( " " ch escape_default ( ) collect String ( ) ) , } ) ; None } None => { me . errors . push ( ParserError { lo : pos , hi : pos + 1 , desc : format ! ( " " ) , } ) ; None } } } }
Finish parsing a basic string after the opening quote has been seen
Finish parsing a basic string after the opening quote has been seen
&mut self
start
usize
multiline
bool
&mut self
start
usize
multiline
bool