forked from MightyPork/crsn
stricter label parsing, more relaxed identifier rules
This commit is contained in:
@@ -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())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use sexp::{Atom, Sexp, SourcePosition};
|
||||
|
||||
use crate::asm::data::literal::{Label, RoutineName};
|
||||
use crate::asm::data::literal::{RoutineName};
|
||||
use crate::asm::data::reg::parse_reg;
|
||||
use crate::asm::error::CrsnError;
|
||||
use crate::asm::instr::op::OpKind;
|
||||
@@ -185,9 +185,9 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok
|
||||
}
|
||||
|
||||
"far" => {
|
||||
if let Some(Sexp::Atom(Atom::S(ref label), _)) = args.peek() {
|
||||
if let Some(label) = label.strip_prefix(':') {
|
||||
let label = Label::Named(label.to_string());
|
||||
if let Some(Sexp::Atom(Atom::S(ref label), labelpos)) = args.peek() {
|
||||
if label.starts_with(':') {
|
||||
let label = parse_label_str(label, labelpos)?;
|
||||
BuiltinOp::FarLabel(label)
|
||||
} else {
|
||||
return Ok(ParseRes::Unknown(args));
|
||||
@@ -198,8 +198,8 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok
|
||||
}
|
||||
|
||||
other => {
|
||||
if let Some(label) = other.strip_prefix(':') {
|
||||
BuiltinOp::Label(parse_label_str(label, &op_pos)?)
|
||||
if other.starts_with(':') {
|
||||
BuiltinOp::Label(parse_label_str(other, &op_pos)?)
|
||||
} else {
|
||||
return Ok(ParseRes::Unknown(args));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user