aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMiquel Sabaté Solà <mssola@mssola.com>2026-08-18 16:41:34 +0200
committerMiquel Sabaté Solà <mssola@mssola.com>2026-08-18 16:41:34 +0200
commit6cb4215f55876a7fffb1fd33f2bd061283d2389f (patch)
treeba0f17915bb3a24d2d5112d89cfd8b5fea9a74e4 /lib
parentfcd4c9a267b407e653ed6b21ae87f219f3e4c4af (diff)
downloadtools.nes-6cb4215f55876a7fffb1fd33f2bd061283d2389f.tar.gz
tools.nes-6cb4215f55876a7fffb1fd33f2bd061283d2389f.zip
Validate labels when walking through the context
The parser does not validate label names completely (it only takes care of validating that it something that makes sense syntactically). The assembler can tell whether the label is actually taking a reserved name, or an invalid hexadecimal constant, etc. Before this commit a user would get a cryptic "invalid identifier" message when referencing an invalid label (e.g. "jmp 1234"). Fix this by validating the identifier there, but also when the label was defined before any of this. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/xixanta/src/assembler.rs35
1 files changed, 32 insertions, 3 deletions
diff --git a/lib/xixanta/src/assembler.rs b/lib/xixanta/src/assembler.rs
index 3cf1e0b..0c5227e 100644
--- a/lib/xixanta/src/assembler.rs
+++ b/lib/xixanta/src/assembler.rs
@@ -605,6 +605,21 @@ impl<'a> Assembler<'a> {
});
continue;
}
+
+ // If this is a named label with an invalid identifier,
+ // report it now.
+ if !node.value.is_empty()
+ && let Err(err) = node.value.is_valid_identifier(true)
+ {
+ errors.push(Error {
+ message: format!("invalid identifier: {err}"),
+ line: node.value.line,
+ source: self.source_for(node),
+ expanded_from: self.macro_context.clone(),
+ global: false,
+ });
+ }
+
if let Err(err) = self.define_variable(node, ObjectType::Address) {
errors.push(err);
}
@@ -1825,10 +1840,13 @@ impl<'a> Assembler<'a> {
Ok(self.evaluate_decimal(node)?)
} else if node.value.is_anonymous_relative_reference() {
Ok(self.evaluate_anonymous_relative_reference(node)?)
- } else if node.value.is_valid_identifier(true).is_err() {
- // If this is not a valid identifier, just error out.
+ } else if let Err(err) = node.value.is_valid_identifier(true) {
+ // If this is not a valid identifier, just error
+ // out. Note that this should have been already covered
+ // when defining the identifier, but just as a sanity
+ // check.
Err(Error {
- message: "invalid identifier".to_string(),
+ message: format!("invalid identifier: {err}"),
line: node.value.line,
source: self.source_for(node),
expanded_from: self.macro_context.clone(),
@@ -5027,6 +5045,17 @@ label:
);
}
+ #[test]
+ fn bad_label_name() {
+ let res = just_assemble("x: nop");
+
+ assert_eq!(res.errors.len(), 1);
+ assert_eq!(
+ res.errors[0].to_string(),
+ "invalid identifier: cannot use reserved name 'x' (line 4)"
+ );
+ }
+
// Control statements
#[test]