lc3asm 0.1.2

LC-3 assembly parser & assembler
Documentation
use crate::Rule;
use pest::iterators::Pair;
use std::collections::BTreeMap;
use std::fmt::{Write, Error as FmtError};

const TABLE_HEADER: & str = r#"//Symbol Name		Page Address
//----------------	------------
"#;
const SPACES: & str = "                              ";

pub(crate) type SymbolTable<'i> = BTreeMap<String, (usize, Pair<'i, Rule>)>;

pub fn table_to_string(sym: SymbolTable<'_>, entry: usize) -> Result<String, FmtError> {
    let mut s = String::from(TABLE_HEADER);
    for (key, (idx, _)) in sym {
        let space_size = 28 - key.len() - 4;
        writeln!(s, "//\t{}{}{:04X}", key, &SPACES[0..space_size], entry + idx)?;
    }
    Ok(s)
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::error::Error;

    #[test]
    fn test_program1() -> Result<(), Error> {
        let parsed = crate::parse(
            r#"	.ORIG	x0400
	ST	R3, SAVE3
	ST	R2, SAVE2
	AND	R2, R2, #0
TEST	IN
	BRz	TEST
	ADD	R1, R0, #-10
	BRn	FINISH
	ADD	R1, R0, #-15
	NOT	R1, R1
	BRn FINISH
	HALT
FINISH	ADD	R2, R2, #1
	HALT
SAVE3	.FILL	x0000
SAVE2	.FILL	x0000
	.END"#,
        )?
        .collect::<Vec<_>>();
        let (symbols, size, entry) = crate::first_pass(&parsed)?;
        let table_str = table_to_string(symbols, entry)?;
        assert_eq!(
            table_str,
            r#"//Symbol Name		Page Address
//----------------	------------
//	FINISH                  040B
//	SAVE2                   040E
//	SAVE3                   040D
//	TEST                    0403
"#
        );
        Ok(())
    }
}