fn parse_cell_from_token<Chars: Iterator<Item=char>>(code: &mut TokenReadBuffer<Chars>, original_location: FileLocation, token: Token, token_text: String, location: FileLocation) -> Result<(Option<CellRef>, FileLocation), ParseError> {
    // Action depends on the token
    match token {
        Token::Whitespace | Token::Comment => { Err(ParseError::InternalError(original_location, "Whitespace should not make it through to this point".to_string())) },
        Token::EndOfFile    => { Ok((None, location)) }

        Token::BitNumber    => { (Ok((Some(bit_number(&token_text, &original_location)?.into()), location))) }
        Token::HexNumber    => { (Ok((Some(hex_number(&token_text, &original_location)?.into()), location))) }
        Token::IntNumber    => { (Ok((Some(int_number(&token_text, &original_location)?.into()), location))) }
        Token::Boolean      => { Ok((Some(SafasCell::Boolean(token_text.chars().nth(1) == Some('t')).into()), location)) }
        Token::Atom         => { Ok((Some(SafasCell::atom(&token_text)), location)) }
        Token::Symbol(_)    => { Ok((Some(SafasCell::atom(&token_text)), location)) }
        Token::CloseParen   => { Err(ParseError::UnexpectedCloseParen(original_location)) }
        Token::String       => { Ok((Some(SafasCell::String(unquote_string(token_text)).into()), location)) }

        Token::Character    => {
            let chr_string = unquote_string(token_text);
            if chr_string.chars().count() != 1 {
                Err(ParseError::InvalidCharacter(original_location, chr_string))
            } else {
                Ok((Some(SafasCell::Char(chr_string.chars().nth(0).unwrap()).into()), location))
            }
        }

        Token::OpenParen    => {
            // List of cells
            let mut list        = vec![];
            let mut location    = location;

            loop {
                // Read the next token
                let start_location                          = location.clone();
                let (next_token, next_text, next_location)  = tokenize_no_comments(code, location);
                location                                    = next_location;

                match next_token {
                    // Close paren indicates the end of the list
                    Token::CloseParen   => { break; }
                    Token::EndOfFile    => return Err(ParseError::MissingCloseParen(original_location)),

                    other_token         => {
                        // Other symbols indicate a different cell of some kind
                        let (cell, next_location) = parse_cell_from_token(code, start_location, other_token, next_text, location)?;
                        location = next_location;

                        if let Some(cell) = cell {
                            // Add the cell to the list
                            list.push(cell);
                        } else {
                            // Indicates we hit an EOF
                            return Err(ParseError::MissingCloseParen(original_location));
                        }
                    }
                }
            }

            Ok((Some(SafasCell::list_with_cells(list)), location))
        }
    }
}
///
/// Parses the next cell on the token stream, with a token read from the stream (returning None if there is no following cell)
///
Parses the next cell on the token stream, with a token read from the stream (returning None if there is no following cell)
Parses the next cell on the token stream with a token read from the stream ( returning None if there is no following cell )
fn parse_cell_from_token<Chars: Iterator<Item=char>>(code: &mut TokenReadBuffer<Chars>, original_location: FileLocation, token: Token, token_text: String, location: FileLocation) -> Result<(Option<CellRef>, FileLocation), ParseError> {
    // Action depends on the token
    match token {
        Token::Whitespace | Token::Comment => { Err(ParseError::InternalError(original_location, "Whitespace should not make it through to this point".to_string())) },
        Token::EndOfFile    => { Ok((None, location)) }
        Token::BitNumber    => { (Ok((Some(bit_number(&token_text, &original_location)?.into()), location))) }
        Token::HexNumber    => { (Ok((Some(hex_number(&token_text, &original_location)?.into()), location))) }
        Token::IntNumber    => { (Ok((Some(int_number(&token_text, &original_location)?.into()), location))) }
        Token::Boolean      => { Ok((Some(SafasCell::Boolean(token_text.chars().nth(1) == Some('t')).into()), location)) }
        Token::Atom         => { Ok((Some(SafasCell::atom(&token_text)), location)) }
        Token::Symbol(_)    => { Ok((Some(SafasCell::atom(&token_text)), location)) }
        Token::CloseParen   => { Err(ParseError::UnexpectedCloseParen(original_location)) }
        Token::String       => { Ok((Some(SafasCell::String(unquote_string(token_text)).into()), location)) }
        Token::Character    => {
            let chr_string = unquote_string(token_text);
            if chr_string.chars().count() != 1 {
                Err(ParseError::InvalidCharacter(original_location, chr_string))
            } else {
                Ok((Some(SafasCell::Char(chr_string.chars().nth(0).unwrap()).into()), location))
            }
        }
        Token::OpenParen    => {
            // List of cells
            let mut list        = vec![];
            let mut location    = location;
            loop {
                // Read the next token
                let start_location                          = location.clone();
                let (next_token, next_text, next_location)  = tokenize_no_comments(code, location);
                location                                    = next_location;
                match next_token {
                    // Close paren indicates the end of the list
                    Token::CloseParen   => { break; }
                    Token::EndOfFile    => return Err(ParseError::MissingCloseParen(original_location)),
                    other_token         => {
                        // Other symbols indicate a different cell of some kind
                        let (cell, next_location) = parse_cell_from_token(code, start_location, other_token, next_text, location)?;
                        location = next_location;
                        if let Some(cell) = cell {
                            // Add the cell to the list
                            list.push(cell);
                        } else {
                            // Indicates we hit an EOF
                            return Err(ParseError::MissingCloseParen(original_location));
                        }
                    }
                }
            }
            Ok((Some(SafasCell::list_with_cells(list)), location))
        }
    }
}
fn parse_cell_from_token < Chars : Iterator < Item = char > > ( code : & mut TokenReadBuffer < Chars > , original_location : FileLocation , token : Token , token_text : String , location : FileLocation ) -> Result < ( Option < CellRef > , FileLocation ) , ParseError > { // Action depends on the token match token { Token :: Whitespace | Token :: Comment => { Err ( ParseError :: InternalError ( original_location , " " . to_string ( ) ) ) } , Token :: EndOfFile => { Ok ( ( None , location ) ) } Token :: BitNumber => { ( Ok ( ( Some ( bit_number ( & token_text , & original_location ) ? . into ( ) ) , location ) ) ) } Token :: HexNumber => { ( Ok ( ( Some ( hex_number ( & token_text , & original_location ) ? . into ( ) ) , location ) ) ) } Token :: IntNumber => { ( Ok ( ( Some ( int_number ( & token_text , & original_location ) ? . into ( ) ) , location ) ) ) } Token :: Boolean => { Ok ( ( Some ( SafasCell :: Boolean ( token_text . chars ( ) . nth ( 1 ) == Some ( 't' ) ) . into ( ) ) , location ) ) } Token :: Atom => { Ok ( ( Some ( SafasCell :: atom ( & token_text ) ) , location ) ) } Token :: Symbol ( _ ) => { Ok ( ( Some ( SafasCell :: atom ( & token_text ) ) , location ) ) } Token :: CloseParen => { Err ( ParseError :: UnexpectedCloseParen ( original_location ) ) } Token :: String => { Ok ( ( Some ( SafasCell :: String ( unquote_string ( token_text ) ) . into ( ) ) , location ) ) } Token :: Character => { let chr_string = unquote_string ( token_text ) ; if chr_string . chars ( ) . count ( ) != 1 { Err ( ParseError :: InvalidCharacter ( original_location , chr_string ) ) } else { Ok ( ( Some ( SafasCell :: Char ( chr_string . chars ( ) . nth ( 0 ) . unwrap ( ) ) . into ( ) ) , location ) ) } } Token :: OpenParen => { // List of cells let mut list = vec ! [ ] ; let mut location = location ; loop { // Read the next token let start_location = location . clone ( ) ; let ( next_token , next_text , next_location ) = tokenize_no_comments ( code , location ) ; location = next_location ; match next_token { // Close paren indicates the end of the list Token :: CloseParen => { break ; } Token :: EndOfFile => return Err ( ParseError :: MissingCloseParen ( original_location ) ) , other_token => { // Other symbols indicate a different cell of some kind let ( cell , next_location ) = parse_cell_from_token ( code , start_location , other_token , next_text , location ) ? ; location = next_location ; if let Some ( cell ) = cell { // Add the cell to the list list . push ( cell ) ; } else { // Indicates we hit an EOF return Err ( ParseError :: MissingCloseParen ( original_location ) ) ; } } } } Ok ( ( Some ( SafasCell :: list_with_cells ( list ) ) , location ) ) } } }
Parses the next cell on the token stream, with a token read from the stream (returning None if there is no following cell)
Parses the next cell on the token stream with a token read from the stream ( returning None if there is no following cell )
code
&mut TokenReadBuffer<Chars>
original_location
FileLocation
token
Token
token_text
String
location
FileLocation
code
&mut TokenReadBuffer<Chars>
original_location
FileLocation
token
Token
token_text
String
location
FileLocation