fn first_pass<R: Read>(input: R) -> Result<Assembler> {
        let br = BufReader::new(input);
        let mut stmts = Vec::new();
        let mut labels = HashMap::new();

        for (n, l) in br.lines().enumerate() {
            // Adjust line number
            let n = n + 1;
            let l = l.chain_err(|| ErrorKind::Io("could not read line".into()))?;
            
            // Get rid of any comments
            let l = if let Some(n) = l.find("//") {
                &l[..n]
            } else {
                l.as_str()
            };

            // Try to get the label/instruction
            let mut iter = l.split_whitespace();
            let mut part = match iter.next() {
                Some(s) => s,
                None => continue,
            };

            // See if we have a label
            if let Some(idx) = part.find(':') {
                // Add the label to the label table
                let label = (&part[..idx]).trim();
                if label.is_empty() {
                    return Err(ErrorKind::Asm("found empty label".into(), n).into());
                }

                let label = label.to_owned();
                if labels.contains_key(&label) {
                    return Err(ErrorKind::Asm(format!("found duplicate label: '{}'", label), n).into());
                }
                labels.insert(label, stmts.len() as u16);

                // Get next part (the actual instruction)
                if idx == part.len() - 1 {
                    // Get the next part from the iterator
                    part = match iter.next() {
                        Some(s) => s,
                        None => continue,
                    };
                } else {
                    // Use the rest of this part
                    part = &part[idx + 1..];
                }
            }

            // Return an error if the program is too long
            if stmts.len() == u16::max_value() as usize {
                return Err(ErrorKind::ProgramTooLong.into());
            }

            // Get the instruction and any arguments (there should only be one argument)
            let instr = part;
            let arg = iter.next();
            if let Some(s) = iter.next() {
                return Err(ErrorKind::Asm(format!("unexpected argument {}", s), n).into());
            }

            // Get the statement and add it to the list
            stmts.push((n, get_stmt(instr, arg, n)?));
        }

        Ok(Assembler {
            stmts: stmts,
            labels: labels,
        })
    }
/// First pass: parse the input to get the initial list of statements and labels
First pass: parse the input to get the initial list of statements and labels
First pass : parse the input to get the initial list of statements and labels
fn first_pass<R: Read>(input: R) -> Result<Assembler> {
        let br = BufReader::new(input);
        let mut stmts = Vec::new();
        let mut labels = HashMap::new();
        for (n, l) in br.lines().enumerate() {
            // Adjust line number
            let n = n + 1;
            let l = l.chain_err(|| ErrorKind::Io("could not read line".into()))?;
            // Get rid of any comments
            let l = if let Some(n) = l.find("//") {
                &l[..n]
            } else {
                l.as_str()
            };
            // Try to get the label/instruction
            let mut iter = l.split_whitespace();
            let mut part = match iter.next() {
                Some(s) => s,
                None => continue,
            };
            // See if we have a label
            if let Some(idx) = part.find(':') {
                // Add the label to the label table
                let label = (&part[..idx]).trim();
                if label.is_empty() {
                    return Err(ErrorKind::Asm("found empty label".into(), n).into());
                }
                let label = label.to_owned();
                if labels.contains_key(&label) {
                    return Err(ErrorKind::Asm(format!("found duplicate label: '{}'", label), n).into());
                }
                labels.insert(label, stmts.len() as u16);
                // Get next part (the actual instruction)
                if idx == part.len() - 1 {
                    // Get the next part from the iterator
                    part = match iter.next() {
                        Some(s) => s,
                        None => continue,
                    };
                } else {
                    // Use the rest of this part
                    part = &part[idx + 1..];
                }
            }
            // Return an error if the program is too long
            if stmts.len() == u16::max_value() as usize {
                return Err(ErrorKind::ProgramTooLong.into());
            }
            // Get the instruction and any arguments (there should only be one argument)
            let instr = part;
            let arg = iter.next();
            if let Some(s) = iter.next() {
                return Err(ErrorKind::Asm(format!("unexpected argument {}", s), n).into());
            }
            // Get the statement and add it to the list
            stmts.push((n, get_stmt(instr, arg, n)?));
        }
        Ok(Assembler {
            stmts: stmts,
            labels: labels,
        })
    }
fn first_pass < R : Read > ( input : R ) -> Result < Assembler > { let br = BufReader :: new ( input ) ; let mut stmts = Vec :: new ( ) ; let mut labels = HashMap :: new ( ) ; for ( n , l ) in br . lines ( ) . enumerate ( ) { // Adjust line number let n = n + 1 ; let l = l . chain_err ( | | ErrorKind :: Io ( " " . into ( ) ) ) ? ; // Get rid of any comments let l = if let Some ( n ) = l . find ( " " ) { & l [ .. n ] } else { l . as_str ( ) } ; // Try to get the label/instruction let mut iter = l . split_whitespace ( ) ; let mut part = match iter . next ( ) { Some ( s ) => s , None => continue , } ; // See if we have a label if let Some ( idx ) = part . find ( ':' ) { // Add the label to the label table let label = ( & part [ .. idx ] ) . trim ( ) ; if label . is_empty ( ) { return Err ( ErrorKind :: Asm ( " " . into ( ) , n ) . into ( ) ) ; } let label = label . to_owned ( ) ; if labels . contains_key ( & label ) { return Err ( ErrorKind :: Asm ( format ! ( " " label ) , n ) . into ( ) ) ; } labels . insert ( label , stmts . len ( ) as u16 ) ; // Get next part (the actual instruction) if idx == part . len ( ) - 1 { // Get the next part from the iterator part = match iter . next ( ) { Some ( s ) => s , None => continue , } ; } else { // Use the rest of this part part = & part [ idx + 1 .. ] ; } } // Return an error if the program is too long if stmts . len ( ) == u16 :: max_value ( ) as usize { return Err ( ErrorKind :: ProgramTooLong . into ( ) ) ; } // Get the instruction and any arguments (there should only be one argument) let instr = part ; let arg = iter . next ( ) ; if let Some ( s ) = iter . next ( ) { return Err ( ErrorKind :: Asm ( format ! ( " " s ) , n ) . into ( ) ) ; } // Get the statement and add it to the list stmts . push ( ( n , get_stmt ( instr , arg , n ) ? ) ) ; } Ok ( Assembler { stmts : stmts , labels : labels , } ) }
First pass: parse the input to get the initial list of statements and labels
First pass : parse the input to get the initial list of statements and labels
input
R
input
R