|
|
|
@ -11,8 +11,11 @@ use crate::asm::parse::sexp_expect::expect_string_atom; |
|
|
|
|
use crate::asm::patches::ErrWithPos; |
|
|
|
|
|
|
|
|
|
fn is_valid_identifier(name: &str) -> bool { |
|
|
|
|
name.starts_with(|c: char| c.is_ascii_alphabetic() || c == '_') |
|
|
|
|
&& name.chars().find(|c| !c.is_ascii_alphanumeric() && *c != '_').is_none() |
|
|
|
|
// ascii symbols "!\"#$_&'()*+,-./:;<=>?@[\\]^_`{|}~"
|
|
|
|
|
const BLACKLIST : &str = "!\"#$&'()*+,-./:;<=>?@[\\]^`{|}~"; |
|
|
|
|
name != "_" |
|
|
|
|
&& !name.starts_with(|c: char| c.is_ascii_digit() || BLACKLIST.contains(c)) |
|
|
|
|
&& !name.contains(|c : char| c.is_whitespace() || BLACKLIST.contains(c)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Parse register alias
|
|
|
|
@ -43,18 +46,24 @@ pub fn parse_constant_name(name: Sexp) -> Result<(ConstantName, SourcePosition), |
|
|
|
|
|
|
|
|
|
/// Parse a label
|
|
|
|
|
pub fn parse_label(name: Sexp) -> Result<Label, CrsnError> { |
|
|
|
|
// trace!("parse label: {:?}", name);
|
|
|
|
|
let (name, namepos) = expect_string_atom(name)?; |
|
|
|
|
Ok(parse_label_str(&name, &namepos)?) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn parse_label_str(name: &str, pos: &SourcePosition) -> Result<Label, CrsnError> { |
|
|
|
|
if !name.starts_with(':') { |
|
|
|
|
return Err(CrsnError::Parse("Label must start with a colon".into(), pos.clone())); |
|
|
|
|
} |
|
|
|
|
let label = name.trim_start_matches(':'); |
|
|
|
|
|
|
|
|
|
Ok(if label.starts_with('#') { |
|
|
|
|
let val = parse_u64(&label[1..], pos)?; |
|
|
|
|
Label::Numbered(u32::try_from(val).err_pos(pos)?) |
|
|
|
|
} else { |
|
|
|
|
if !is_valid_identifier(&label) { |
|
|
|
|
return Err(CrsnError::Parse(format!("\"{}\" is not an allowed label name.", name).into(), pos.clone())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Label::Named(label.to_string()) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|