<commit_before>
use std::mem;

use assembler::source_file_location::SourceFileLocation;
use assembler::token::Token;
use assembler::token::display_names;
use assembler::u12::*;

// MARK: - Abstract Syntax List

#[derive(Debug, PartialEq)]
pub enum Node<'a> {
  /// A directive and corresponding parameters.
  Directive(DirectiveData<'a>),
  /// A label and corresponding parameters.
  Label(LabelData<'a>),
  /// An instruction and corresponding parameters.
  Instruction(InstructionData<'a>)
}

#[derive(Debug, Clone, PartialEq)]
pub enum Literal<'a> {
  /// A literal string value.
  String(&'a str),
  /// A literal numeric value.
  Numeric(usize)
}

#[derive(Debug, PartialEq)]
pub struct DirectiveData<'a> {
  /// The location at which the directive is defined for error reporting purposes.
  pub location: SourceFileLocation<'a>,
  /// The name of the directive (db, org).
  pub identifier: &'a str,
  /// Arguments to the directive.
  pub arguments: Vec<Literal<'a>> 
}

#[derive(Debug, PartialEq)]
pub struct LabelData<'a> {
  /// The location at which the label is defined for error reporting purposes.
  pub location: SourceFileLocation<'a>,
  /// The name of the label.
  pub identifier: &'a str
}

#[derive(Debug, PartialEq)]
pub enum InstructionField<'a> {
  /// A numeric literal value.
  NumericLiteral(U12),
  /// A general-purpose register beginning with "v".
  GeneralPurposeRegister(u8),
  /// The delay timer register ("dt").
  DelayTimer,
  /// The sound timer register ("st").
  SoundTimer,
  /// The keypad register ("k").
  KeypadRegister,
  /// The index register ("i").
  IndexRegister,
  /// Register-indirect access of memory ("[i]").
  IndexRegisterIndirect,
  /// Any other literal identifier, usually a label.
  Identifier(&'a str)
}

#[derive(Debug, PartialEq)]
pub struct InstructionData<'a> {
  /// The location at which the directive is defined for error reporting purposes.
  pub location: SourceFileLocation<'a>,
  /// The mnemonic corresponding to the operation.
  pub mnemonic: &'a str,
  /// Instruction fields for the mnemonic.
  pub fields: Vec<InstructionField<'a>>
}

// MARK: - Local Parser Context

struct Parser<'a,I> where I: Iterator<Item=Token<'a>> {
  /// Iterator over input token stream.
  scanner: I,
  /// Current token.
  current_token: Option<Token<'a>>,
  /// Lookahead token.
  next_token: Option<Token<'a>>
}

// MARK: - Helper Macros<commit_msg>Implement Display trait on InstructionField.<commit_after>
use std::fmt;
use std::mem;

use assembler::source_file_location::SourceFileLocation;
use assembler::token::Token;
use assembler::token::display_names;
use assembler::u12::*;

// MARK: - Abstract Syntax List

#[derive(Debug, PartialEq)]
pub enum Node<'a> {
  /// A directive and corresponding parameters.
  Directive(DirectiveData<'a>),
  /// A label and corresponding parameters.
  Label(LabelData<'a>),
  /// An instruction and corresponding parameters.
  Instruction(InstructionData<'a>)
}

#[derive(Debug, Clone, PartialEq)]
pub enum Literal<'a> {
  /// A literal string value.
  String(&'a str),
  /// A literal numeric value.
  Numeric(usize)
}

#[derive(Debug, PartialEq)]
pub struct DirectiveData<'a> {
  /// The location at which the directive is defined for error reporting purposes.
  pub location: SourceFileLocation<'a>,
  /// The name of the directive (db, org).
  pub identifier: &'a str,
  /// Arguments to the directive.
  pub arguments: Vec<Literal<'a>> 
}

#[derive(Debug, PartialEq)]
pub struct LabelData<'a> {
  /// The location at which the label is defined for error reporting purposes.
  pub location: SourceFileLocation<'a>,
  /// The name of the label.
  pub identifier: &'a str
}

#[derive(Debug, PartialEq)]
pub enum InstructionField<'a> {
  /// A numeric literal value.
  NumericLiteral(U12),
  /// A general-purpose register beginning with "v".
  GeneralPurposeRegister(u8),
  /// The delay timer register ("dt").
  DelayTimer,
  /// The sound timer register ("st").
  SoundTimer,
  /// The keypad register ("k").
  KeypadRegister,
  /// The index register ("i").
  IndexRegister,
  /// Register-indirect access of memory ("[i]").
  IndexRegisterIndirect,
  /// Any other literal identifier, usually a label.
  Identifier(&'a str)
}

#[derive(Debug, PartialEq)]
pub struct InstructionData<'a> {
  /// The location at which the directive is defined for error reporting purposes.
  pub location: SourceFileLocation<'a>,
  /// The mnemonic corresponding to the operation.
  pub mnemonic: &'a str,
  /// Instruction fields for the mnemonic.
  pub fields: Vec<InstructionField<'a>>
}

// MARK: - Local Parser Context

struct Parser<'a,I> where I: Iterator<Item=Token<'a>> {
  /// Iterator over input token stream.
  scanner: I,
  /// Current token.
  current_token: Option<Token<'a>>,
  /// Lookahead token.
  next_token: Option<Token<'a>>
}

// MARK: - Instruction Field

impl<'a> fmt::Display for InstructionField<'a> {
  /**
   Formats the instruction field for display purposes.
   */
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match self {
      &InstructionField::NumericLiteral(value)      => write!(f, "${:x}", value.as_usize()),
      &InstructionField::GeneralPurposeRegister(r)  => write!(f, "v{:x}", r),
      &InstructionField::DelayTimer                 => write!(f, "dt"),
      &InstructionField::SoundTimer                 => write!(f, "st"),
      &InstructionField::KeypadRegister             => write!(f, "k"),
      &InstructionField::IndexRegister              => write!(f, "i"),
      &InstructionField::IndexRegisterIndirect      => write!(f, "[i]"),
      &InstructionField::Identifier(id)             => write!(f, "{}", id)
    }
  }
}

// MARK: - Helper Macros
{'fraction_non_alphanumeric': 0.14609306409130818, 'fraction_numerical': 0.001755926251097454, 'mean_word_length': 3.6233766233766236, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 60, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1646055', 'n_tokens_mistral': 1758, 'n_tokens_neox': 1766, 'n_words': 535}