diff options
Diffstat (limited to 'src/tokens/assembler.rs')
-rw-r--r-- | src/tokens/assembler.rs | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/tokens/assembler.rs b/src/tokens/assembler.rs new file mode 100644 index 0000000..04ecd38 --- /dev/null +++ b/src/tokens/assembler.rs @@ -0,0 +1,140 @@ +use crate::*; + + +#[derive(Clone)] +pub enum AssembledToken { + Word(AssembledWord), + LabelDefinition(LabelDefinition), + PinnedAddress(PinnedAddress), + Error(AssemblerError), +} + +#[derive(Clone)] +pub struct AssembledWord { + pub source: SourceSpan, + pub value: usize, + pub bits: usize, + pub fields: Vec<AssembledField>, + pub errors: Vec<AssemblerError>, +} + +#[derive(Clone)] +pub struct AssembledField { + pub source: SourceSpan, + pub value: IntegerArgument, + /// Length of field in bits + pub bits: usize, + /// Distance to left-shift field in value + pub shift: usize, +} + +#[derive(Clone)] +pub struct AssembledExpression { + pub source: SourceSpan, + pub tokens: Vec<AssembledExpressionToken>, +} + +#[derive(Clone)] +pub enum AssembledExpressionToken { + Integer(TrackedInteger), + LabelReference(Tracked<String>), + Operator(Operator), + Expression(Box<AssembledExpression>), +} + +#[derive(Clone)] +pub enum Argument { + Integer(IntegerArgument), + Block(Vec<AssembledToken>), +} + +#[derive(Clone)] +pub enum IntegerArgument { + LabelReference(Tracked<String>), + Integer(TrackedInteger), + Expression(AssembledExpression), +} + +#[derive(Clone)] +pub struct AssemblerError { + pub source: SourceSpan, + pub variant: AssemblerErrorVariant, +} + +#[derive(Clone, Debug)] +pub enum AssemblerErrorVariant { + DefinitionNotFound(String), + NotAnInteger, + NotABlock, + IntegerInBlock, + /// expected, received + IncorrectArgumentCount(usize, usize), + /// expected, received, index + IncorrectArgumentType(ArgumentVariant, ArgumentVariant), +} + +// ------------------------------------------------------------------------ // + +macro_rules! indent { + ($indent:expr => $($tokens:tt)*) => {{ + for _ in 0..$indent { print!(" "); } + println!($($tokens)*); + }}; +} + +pub fn print_assembled_tokens(tokens: &[AssembledToken]) { + println!(); + println!("--------------------------------------------------------------"); + println!(); + for token in tokens { + match token { + AssembledToken::LabelDefinition(definition) => { + println!("LABEL {}", definition.name) + } + AssembledToken::PinnedAddress(address) => { + println!("PINNED {}", address.address) + } + AssembledToken::Word(word) => { + println!("WORD {:b}", word.value); + for field in &word.fields { + print!(" FIELD ({} << {}) ", field.bits, field.shift); + match &field.value { + IntegerArgument::LabelReference(name) => { + println!("LABEL '{name}'"); + } + IntegerArgument::Integer(integer) => { + println!("INTEGER '{}'", integer.value); + } + IntegerArgument::Expression(expr) => { + println!("EXPRESSION"); + print_assembled_expression(2, expr); + } + } + } + } + AssembledToken::Error(error) => { + println!("ERROR {:?}", error.variant) + } + } + } +} + +fn print_assembled_expression(indent: usize, expr: &AssembledExpression) { + for token in &expr.tokens { + match token { + AssembledExpressionToken::Integer(integer) => { + indent!(indent => "INTEGER {}", integer.value) + } + AssembledExpressionToken::LabelReference(name) => { + indent!(indent => "LABEL '{name}'") + } + AssembledExpressionToken::Operator(operator) => { + indent!(indent => "OPERATOR {operator:?}") + } + AssembledExpressionToken::Expression(expr) => { + indent!(indent => "EXPRESSION"); + print_assembled_expression(indent+1, expr); + } + } + } +} |