summaryrefslogtreecommitdiff
path: root/src/tokens
diff options
context:
space:
mode:
Diffstat (limited to 'src/tokens')
-rw-r--r--src/tokens/assembler.rs140
-rw-r--r--src/tokens/bytecode.rs49
-rw-r--r--src/tokens/constant_expression.rs134
-rw-r--r--src/tokens/expression.rs74
-rw-r--r--src/tokens/mod.rs22
-rw-r--r--src/tokens/packed_binary_literal.rs11
-rw-r--r--src/tokens/semantic.rs184
-rw-r--r--src/tokens/syntactic.rs32
-rw-r--r--src/tokens/tracked.rs47
-rw-r--r--src/tokens/tracked_integer.rs14
10 files changed, 461 insertions, 246 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);
+ }
+ }
+ }
+}
diff --git a/src/tokens/bytecode.rs b/src/tokens/bytecode.rs
new file mode 100644
index 0000000..9ac340e
--- /dev/null
+++ b/src/tokens/bytecode.rs
@@ -0,0 +1,49 @@
+use crate::*;
+
+
+pub struct Bytecode {
+ pub words: Vec<Word>,
+ pub errors: Vec<BytecodeError>,
+}
+
+#[derive(Clone, Copy)]
+pub struct Word {
+ pub bits: usize,
+ pub value: usize,
+}
+
+impl std::fmt::Display for Word {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+ for i in (0..self.bits).rev() {
+ let is_first_bit = i+1 == self.bits;
+ if !is_first_bit && (i+1) % 4 == 0 {
+ write!(f, "_")?;
+ }
+ match (self.value >> i) & 1 {
+ 0 => write!(f, "0")?,
+ _ => write!(f, "1")?,
+ }
+ }
+ if self.bits == 0 {
+ write!(f, "0")?;
+ }
+ return Ok(());
+ }
+}
+
+pub struct BytecodeError {
+ pub source: SourceSpan,
+ pub variant: BytecodeErrorVariant,
+}
+
+pub enum BytecodeErrorVariant {
+ DefinitionNotFound(String),
+ DuplicateLabelDefinition(String),
+ /// pin, real
+ PinnedAddressBacktrack(usize, usize),
+ /// expected, received
+ ValueTooLarge(usize, usize),
+ StackUnderflow,
+ MultipleReturnValues,
+ NoReturnValue,
+}
diff --git a/src/tokens/constant_expression.rs b/src/tokens/constant_expression.rs
deleted file mode 100644
index e4aa099..0000000
--- a/src/tokens/constant_expression.rs
+++ /dev/null
@@ -1,134 +0,0 @@
-use crate::*;
-
-
-pub struct ConstantExpression {
- pub tokens: Vec<ConstantExpressionToken>,
-}
-
-impl ConstantExpression {
- pub fn from_str(string: &str, tokeniser: &Tokeniser) -> Self {
- parse_constant_expression(string, tokeniser)
- }
-}
-
-pub struct ConstantExpressionToken {
- pub source: SourceSpan,
- pub variant: ConstantExpressionTokenVariant,
-}
-
-pub enum ConstantExpressionTokenVariant {
- SymbolReference(String),
- IntegerLiteral(usize),
- Operator(Operator),
- Error(ConstantExpressionParseError),
-}
-
-pub enum Operator {
- Equal,
- NotEqual,
- LessThan,
- GreaterThan,
- Add,
- Subtract,
- LeftShift,
- RightShift,
- And,
- Or,
- Xor,
- Not,
-}
-
-pub enum ConstantExpressionParseError {
- InvalidHexadecimalLiteral(String),
-}
-
-
-impl ConstantExpression {
- pub fn evaluate(&self, environment: &Environment) -> Result<usize, ConstantExpressionEvaluationError> {
- use ConstantExpressionTokenVariant as Token;
- use ConstantExpressionEvaluationError as EvalErr;
-
- let mut stack = Vec::new();
- macro_rules! push {
- ($value:expr) => { stack.push($value) };
- }
- macro_rules! pop {
- ($name:ident) => { let $name = match stack.pop() {
- Some(value) => value,
- None => return Err(EvalErr::StackUnderflow),
- }; };
- }
- macro_rules! truth {
- ($bool:expr) => { match $bool { true => 1, false => 0 } };
- }
-
- for token in &self.tokens {
- match &token.variant {
- Token::IntegerLiteral(value) => push!(*value),
- Token::SymbolReference(name) => match environment.get_integer(name) {
- Ok(value) => push!(value),
- Err(_) => todo!(),
- }
- Token::Operator(operator) => match operator {
- Operator::Equal => { pop!(b); pop!(a); push!(truth!(a==b)) },
- Operator::NotEqual => { pop!(b); pop!(a); push!(truth!(a!=b)) },
- Operator::LessThan => { pop!(b); pop!(a); push!(truth!(a < b)) },
- Operator::GreaterThan => { pop!(b); pop!(a); push!(truth!(a > b)) },
- Operator::Add => { pop!(b); pop!(a); push!(a + b) },
- Operator::Subtract => { pop!(b); pop!(a); push!(a - b) },
- Operator::LeftShift => { pop!(b); pop!(a); push!(a << b) },
- Operator::RightShift => { pop!(b); pop!(a); push!(a >> b) },
- Operator::And => { pop!(b); pop!(a); push!(a & b) },
- Operator::Or => { pop!(b); pop!(a); push!(a | b) },
- Operator::Xor => { pop!(b); pop!(a); push!(a ^ b) },
- Operator::Not => { pop!(a); push!(!a) },
- }
- Token::Error(_) => (),
- }
- }
- match stack.len() {
- 0 => Err(EvalErr::NoReturnValue),
- 1 => Ok(stack[0]),
- _ => Err(EvalErr::MultipleReturnValues),
- }
- }
-}
-
-pub enum ConstantExpressionEvaluationError {
- StackUnderflow,
- MultipleReturnValues,
- NoReturnValue,
-}
-
-
-impl std::fmt::Debug for ConstantExpression {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
- use ConstantExpressionTokenVariant as TokenVar;
- for (i, token) in self.tokens.iter().enumerate() {
- let string = match &token.variant {
- TokenVar::SymbolReference(name) => name,
- TokenVar::IntegerLiteral(value) => &value.to_string(),
- TokenVar::Operator(operator) => match operator {
- Operator::Equal => "=",
- Operator::NotEqual => "!",
- Operator::LessThan => "<",
- Operator::GreaterThan => ">",
- Operator::Add => "+",
- Operator::Subtract => "-",
- Operator::LeftShift => "<<",
- Operator::RightShift => ">>",
- Operator::And => "&",
- Operator::Or => "|",
- Operator::Xor => "^",
- Operator::Not => "~",
- }
- TokenVar::Error(_) => "<error>",
- };
- match i {
- 0 => write!(f, "{string}")?,
- _ => write!(f, " {string}")?,
- }
- }
- return Ok(());
- }
-}
diff --git a/src/tokens/expression.rs b/src/tokens/expression.rs
new file mode 100644
index 0000000..ff2d82d
--- /dev/null
+++ b/src/tokens/expression.rs
@@ -0,0 +1,74 @@
+use crate::*;
+
+
+#[derive(Clone)]
+pub struct Expression {
+ pub source: SourceSpan,
+ pub tokens: Vec<ExpressionToken>,
+}
+
+#[derive(Clone)]
+pub struct ExpressionToken {
+ pub source: SourceSpan,
+ pub variant: ExpressionTokenVariant,
+}
+
+#[derive(Clone)]
+pub enum ExpressionTokenVariant {
+ Invocation(String),
+ Literal(isize),
+ Operator(Operator),
+ Error(ExpressionParseError),
+}
+
+#[derive(Clone, Copy, Debug)]
+pub enum Operator {
+ Equal,
+ NotEqual,
+ LessThan,
+ GreaterThan,
+ Add,
+ Subtract,
+ LeftShift,
+ RightShift,
+ And,
+ Or,
+ Xor,
+ Not,
+}
+
+#[derive(Clone)]
+pub enum ExpressionParseError {
+ InvalidHexadecimalLiteral(String),
+}
+
+impl std::fmt::Debug for Expression {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+ for (i, token) in self.tokens.iter().enumerate() {
+ let string = match &token.variant {
+ ExpressionTokenVariant::Invocation(name) => name,
+ ExpressionTokenVariant::Literal(value) => &value.to_string(),
+ ExpressionTokenVariant::Operator(operator) => match operator {
+ Operator::Equal => "=",
+ Operator::NotEqual => "!=",
+ Operator::LessThan => "<",
+ Operator::GreaterThan => ">",
+ Operator::Add => "+",
+ Operator::Subtract => "-",
+ Operator::LeftShift => "<<",
+ Operator::RightShift => ">>",
+ Operator::And => "&",
+ Operator::Or => "|",
+ Operator::Xor => "^",
+ Operator::Not => "~",
+ }
+ ExpressionTokenVariant::Error(_) => "<error>",
+ };
+ match i {
+ 0 => write!(f, "{string}")?,
+ _ => write!(f, " {string}")?,
+ }
+ }
+ return Ok(());
+ }
+}
diff --git a/src/tokens/mod.rs b/src/tokens/mod.rs
index edb7c19..53ccc6e 100644
--- a/src/tokens/mod.rs
+++ b/src/tokens/mod.rs
@@ -1,9 +1,19 @@
-pub mod syntactic;
+mod expression;
+mod packed_binary_literal;
+mod tracked_integer;
+mod tracked;
-pub mod semantic;
+pub use expression::*;
+pub use packed_binary_literal::*;
+pub use tracked_integer::*;
+pub use tracked::*;
-mod constant_expression;
-pub use constant_expression::*;
+mod syntactic;
+mod semantic;
+mod assembler;
+mod bytecode;
-mod packed_binary_literal;
-pub use packed_binary_literal::*;
+pub use syntactic::*;
+pub use semantic::*;
+pub use assembler::*;
+pub use bytecode::*;
diff --git a/src/tokens/packed_binary_literal.rs b/src/tokens/packed_binary_literal.rs
index 1252398..a2720b7 100644
--- a/src/tokens/packed_binary_literal.rs
+++ b/src/tokens/packed_binary_literal.rs
@@ -2,17 +2,13 @@ use crate::*;
pub struct PackedBinaryLiteral {
+ pub source: SourceSpan,
pub value: usize,
+ pub bits: usize,
pub fields: Vec<BitField>,
pub errors: Vec<PackedBinaryLiteralParseError>,
}
-impl PackedBinaryLiteral {
- pub fn from_str(string: &str, parent: &Tokeniser) -> Self {
- parse_packed_binary_literal(string, parent)
- }
-}
-
pub struct BitField {
pub name: char,
pub source: SourceSpan,
@@ -40,7 +36,8 @@ impl std::fmt::Display for PackedBinaryLiteral {
} else {
let bitcount = (self.value.ilog2() + 1) as usize;
'bit: for i in (0..bitcount).rev() {
- if (i+1) % 4 == 0 {
+ let is_first_bit = i+1 == bitcount;
+ if !is_first_bit && (i+1) % 4 == 0 {
write!(f, "_")?;
}
for field in &self.fields {
diff --git a/src/tokens/semantic.rs b/src/tokens/semantic.rs
index 7d5d327..d61ad8e 100644
--- a/src/tokens/semantic.rs
+++ b/src/tokens/semantic.rs
@@ -1,90 +1,100 @@
use crate::*;
+use indexmap::IndexMap;
+
/// The entire semantic program, ready to generate bytecode.
-pub struct Program {
- pub definitions: Vec<Definition>,
- pub invocations: Vec<Invocation>,
- pub errors: Vec<ParseError>,
+pub struct SemanticProgram {
+ pub macro_definitions: IndexMap<String, MacroDefinition>,
+ pub label_definitions: IndexMap<String, LabelDefinition>,
+ pub body: Vec<SemanticToken>,
}
/// A symbol definition.
-pub struct Definition {
- pub name: String,
+pub struct MacroDefinition {
pub source: SourceSpan,
pub arguments: Vec<ArgumentDefinition>,
- pub variant: DefinitionVariant,
+ pub value: Value,
+ pub errors: Vec<SemanticParseError>,
}
pub struct ArgumentDefinition {
pub name: String,
pub source: SourceSpan,
- pub variant: ArgumentDefinitionVariant,
+ pub variant: ArgumentVariant,
}
-pub enum ArgumentDefinitionVariant {
+#[derive(PartialEq, Clone, Copy, Debug)]
+pub enum ArgumentVariant {
Integer,
Block,
}
-pub enum DefinitionVariant {
- Integer(IntegerDefinition),
- Block(BlockDefinition),
- Reference(ReferenceDefinition),
-}
-
-pub struct IntegerDefinition {
+pub struct ArgumentInvocation {
pub source: SourceSpan,
- pub variant: IntegerDefinitionVariant,
+ pub value: Value,
}
-pub enum IntegerDefinitionVariant {
- Literal(usize),
- Constant(ConstantExpression),
+pub enum Value {
+ Integer(Integer),
+ Block(Vec<SemanticToken>),
+ Invocation(Invocation),
}
-pub struct BlockDefinition {
- pub tokens: Vec<BlockToken>,
- pub errors: Vec<ParseError>,
+pub enum Integer {
+ Literal(TrackedInteger),
+ Expression(Expression),
+ LabelReference(Tracked<String>),
}
-pub struct BlockToken {
- pub source: SourceSpan,
- pub variant: BlockTokenVariant,
+pub enum SemanticToken {
+ Word(PackedBinaryLiteral),
+ Invocation(Invocation),
+ LabelDefinition(LabelDefinition),
+ PinnedAddress(PinnedAddress),
+ Error(SemanticParseError),
}
-pub enum BlockTokenVariant {
- Invocation(Invocation),
- Comment(String),
- Word(PackedBinaryLiteral),
+pub struct Invocation {
+ pub name: String,
+ pub source: SourceSpan,
+ pub arguments: Vec<ArgumentInvocation>,
+ pub errors: Vec<SemanticParseError>,
}
-/// References aren't necessarily an integer or a block
-pub struct ReferenceDefinition {
+#[derive(Clone)]
+pub struct LabelDefinition {
pub source: SourceSpan,
pub name: String,
}
-pub struct Invocation {
- pub name: String,
- pub arguments: Vec<DefinitionVariant>,
- pub errors: Vec<ParseError>,
+#[derive(Clone)]
+pub struct PinnedAddress {
+ pub source: SourceSpan,
+ pub address: usize,
}
-pub struct ParseError {
+pub struct SemanticParseError {
pub source: SourceSpan,
- pub variant: ParseErrorVariant,
+ pub variant: SemanticParseErrorVariant,
}
-pub enum ParseErrorVariant {
+pub enum SemanticParseErrorVariant {
UnterminatedMacroDefinition(String),
- UnterminatedBlockDefinition,
- /// Name of the macro.
- InvalidArgumentDefinition(String),
+ UnterminatedBlock,
InvalidToken,
}
+impl std::fmt::Display for ArgumentVariant {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+ match self {
+ ArgumentVariant::Integer => write!(f, "integer"),
+ ArgumentVariant::Block => write!(f, "block"),
+ }
+ }
+}
+
// ------------------------------------------------------------------------ //
macro_rules! indent {
@@ -94,77 +104,85 @@ macro_rules! indent {
}};
}
-impl Program {
+impl SemanticProgram {
pub fn print_definitions(&self) {
- for definition in &self.definitions {
- let variant = match &definition.variant {
- DefinitionVariant::Integer(_) => "INTEGER",
- DefinitionVariant::Block(_) => "BLOCK",
- DefinitionVariant::Reference(_) => "REFERENCE",
+ for (name, definition) in &self.macro_definitions {
+ let variant = match &definition.value {
+ Value::Integer(_) => "INTEGER",
+ Value::Block(_) => "BLOCK",
+ Value::Invocation(_) => "INVOCATION",
};
- println!("DEFINE {variant} '{}'", definition.name);
+ println!("DEFINE {variant} '{name}'");
for argument in &definition.arguments {
self.print_argument_definition(argument);
}
- match &definition.variant {
- DefinitionVariant::Integer(integer) =>
- self.print_integer_definition(1, integer),
- DefinitionVariant::Block(block) =>
- self.print_block_definition(1, block),
- DefinitionVariant::Reference(reference) =>
- indent!(1 => "REFERENCE '{}'", reference.name),
+ match &definition.value {
+ Value::Integer(integer) =>
+ self.print_integer(1, integer),
+ Value::Block(block) =>
+ self.print_block(1, block),
+ Value::Invocation(invocation) =>
+ indent!(1 => "INVOCATION '{}'", invocation.name),
};
println!();
}
- for invocation in &self.invocations {
- self.print_invocation(0, invocation);
+ println!("LABELS");
+ for (name, _) in &self.label_definitions {
+ println!(" @{name}");
}
+ println!();
+
+ self.print_block(0, &self.body);
}
fn print_argument_definition(&self, argument: &ArgumentDefinition) {
let variant = match argument.variant {
- ArgumentDefinitionVariant::Integer => "INTEGER",
- ArgumentDefinitionVariant::Block => "BLOCK",
+ ArgumentVariant::Integer => "INTEGER",
+ ArgumentVariant::Block => "BLOCK",
};
println!(" ARGUMENT {variant} '{}'", argument.name);
}
- fn print_integer_definition(&self, indent: usize, definition: &IntegerDefinition) {
- match &definition.variant {
- IntegerDefinitionVariant::Literal(value) =>
+ fn print_integer(&self, indent: usize, integer: &Integer) {
+ match &integer {
+ Integer::Literal(value) =>
indent!(indent => "LITERAL {value}"),
- IntegerDefinitionVariant::Constant(expr) =>
- indent!(indent => "CONSTANT [{expr:?}]"),
+ Integer::Expression(expr) =>
+ indent!(indent => "EXPRESSION [{expr:?}]"),
+ Integer::LabelReference(name) =>
+ indent!(indent => "LABEL REFERENCE '{name}'"),
}
}
- fn print_block_definition(&self, indent: usize, definition: &BlockDefinition) {
+ fn print_block(&self, indent: usize, block: &[SemanticToken]) {
indent!(indent => "BLOCK");
- let indent = indent + 1;
- for token in &definition.tokens {
- match &token.variant {
- BlockTokenVariant::Invocation(invocation) =>
- self.print_invocation(indent, invocation),
- BlockTokenVariant::Comment(_) =>
- indent!(indent => "COMMENT"),
- BlockTokenVariant::Word(word) =>
- indent!(indent => "WORD #{word}"),
+ for semantic_token in block {
+ match &semantic_token {
+ SemanticToken::Word(word) =>
+ indent!(indent+1 => "WORD #{word}"),
+ SemanticToken::Invocation(invocation) =>
+ self.print_invocation(indent+1, invocation),
+ SemanticToken::LabelDefinition(definition) =>
+ indent!(indent+1 => "LABEL DEFINITION @{}", definition.name),
+ SemanticToken::PinnedAddress(addr) =>
+ indent!(indent+1 => "PINNED ADDRESS {}", addr.address),
+ SemanticToken::Error(_) =>
+ indent!(indent+1 => "ERROR"),
}
}
}
fn print_invocation(&self, indent: usize, invocation: &Invocation) {
indent!(indent => "INVOCATION '{}'", invocation.name);
- let indent = indent + 1;
for argument in &invocation.arguments {
- match &argument {
- DefinitionVariant::Integer(integer) =>
- self.print_integer_definition(indent, integer),
- DefinitionVariant::Block(block) =>
- self.print_block_definition(indent, block),
- DefinitionVariant::Reference(reference) =>
- indent!(indent => "REFERENCE '{}'", reference.name),
+ match &argument.value {
+ Value::Integer(integer) =>
+ self.print_integer(indent+1, integer),
+ Value::Block(block) =>
+ self.print_block(indent+1, block),
+ Value::Invocation(invocation) =>
+ self.print_invocation(indent+1, invocation),
};
}
}
diff --git a/src/tokens/syntactic.rs b/src/tokens/syntactic.rs
index 162f1c0..eb33806 100644
--- a/src/tokens/syntactic.rs
+++ b/src/tokens/syntactic.rs
@@ -1,22 +1,21 @@
use crate::*;
-pub struct Token {
+pub struct SyntacticToken {
pub source: SourceSpan,
- pub variant: TokenVariant,
+ pub variant: SyntacticTokenVariant,
}
-pub enum TokenVariant {
+pub enum SyntacticTokenVariant {
LabelDefinition(String),
MacroDefinition(String),
MacroDefinitionTerminator,
- DecimalLiteral(usize),
- HexadecimalLiteral(usize),
+ IntegerLiteral(isize),
PackedBinaryLiteral(PackedBinaryLiteral),
+ PinnedAddress(usize),
- Comment(String),
- ConstantExpression(ConstantExpression),
+ Expression(Expression),
BlockOpen,
BlockClose,
@@ -24,33 +23,34 @@ pub enum TokenVariant {
Symbol(String),
- Error(ParseError),
+ Error(SyntacticParseError),
}
#[derive(Debug)]
-pub enum ParseError {
+pub enum SyntacticParseError {
InvalidHexadecimalLiteral(String),
+ InvalidDecimalLiteral(String),
InvalidSymbolIdentifier(String),
UnterminatedComment,
- UnterminatedConstantExpression,
+ UnterminatedExpression,
+ LabelInMacroDefinition,
}
-impl std::fmt::Debug for Token {
+impl std::fmt::Debug for SyntacticToken {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
- use TokenVariant::*;
+ use SyntacticTokenVariant::*;
let start = &self.source.in_merged;
let name = match &self.variant {
LabelDefinition(name) => format!("LabelDefinition({name})"),
MacroDefinition(name) => format!("MacroDefinition({name})"),
MacroDefinitionTerminator => format!("MacroDefinitionTerminator"),
- DecimalLiteral(value) => format!("DecimalLiteral({value})"),
- HexadecimalLiteral(value) => format!("HexadecimalLiteral(0x{value:x})"),
+ IntegerLiteral(value) => format!("IntegerLiteral({value})"),
PackedBinaryLiteral(pbl) => format!("PackedBinaryLiteral({pbl})"),
+ PinnedAddress(value) => format!("PinnedAddress({value})"),
- Comment(_) => format!("Comment"),
- ConstantExpression(expr) => format!("ConstantExpression({expr:?})"),
+ Expression(expr) => format!("Expression({expr:?})"),
BlockOpen => format!("BlockOpen"),
BlockClose => format!("BlockClose"),
diff --git a/src/tokens/tracked.rs b/src/tokens/tracked.rs
new file mode 100644
index 0000000..049c8f8
--- /dev/null
+++ b/src/tokens/tracked.rs
@@ -0,0 +1,47 @@
+use crate::*;
+
+
+#[derive(Clone)]
+pub struct Tracked<T> {
+ pub source: SourceSpan,
+ pub value: T,
+}
+
+impl<T> Tracked<T> {
+ pub fn from(value: T, source: &SourceSpan) -> Self {
+ Self { source: source.clone(), value }
+ }
+}
+
+impl<T> std::ops::Deref for Tracked<T> {
+ type Target = T;
+ fn deref(&self) -> &T {
+ &self.value
+ }
+}
+
+impl<T> std::ops::DerefMut for Tracked<T> {
+ fn deref_mut(&mut self) -> &mut T {
+ &mut self.value
+ }
+}
+
+impl<T: std::fmt::Display> std::fmt::Display for Tracked<T> {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+ write!(f, "{}", self.value)
+ }
+}
+
+impl<T: std::fmt::Debug> std::fmt::Debug for Tracked<T> {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+ write!(f, "{:?}", self.value)
+ }
+}
+
+impl<T: PartialEq> PartialEq for Tracked<T> {
+ fn eq(&self, other: &Tracked<T>) -> bool {
+ self.value.eq(&other.value)
+ }
+}
+
+impl<T: Eq> Eq for Tracked<T> {}
diff --git a/src/tokens/tracked_integer.rs b/src/tokens/tracked_integer.rs
new file mode 100644
index 0000000..fa55f09
--- /dev/null
+++ b/src/tokens/tracked_integer.rs
@@ -0,0 +1,14 @@
+use crate::*;
+
+
+#[derive(Clone)]
+pub struct TrackedInteger {
+ pub source: SourceSpan,
+ pub value: isize,
+}
+
+impl std::fmt::Display for TrackedInteger {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+ write!(f, "{}", self.value)
+ }
+}