stricter label parsing, more relaxed identifier rules

This commit is contained in:
2020-10-07 19:10:52 +02:00
parent 0cc0be370f
commit ce5bf513c0
3 changed files with 22 additions and 9 deletions
+12 -3
View File
@@ -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())
})
}
+6 -6
View File
@@ -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));
}