stricter label parsing, more relaxed identifier rules

pull/21/head
Ondřej Hruška 4 years ago
parent 0cc0be370f
commit ce5bf513c0
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 15
      crsn/src/asm/parse/parse_data.rs
  2. 12
      crsn/src/builtin/parse.rs
  3. 4
      examples/aliases.csn

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

@ -1,6 +1,6 @@
use sexp::{Atom, Sexp, SourcePosition}; 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::data::reg::parse_reg;
use crate::asm::error::CrsnError; use crate::asm::error::CrsnError;
use crate::asm::instr::op::OpKind; 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" => { "far" => {
if let Some(Sexp::Atom(Atom::S(ref label), _)) = args.peek() { if let Some(Sexp::Atom(Atom::S(ref label), labelpos)) = args.peek() {
if let Some(label) = label.strip_prefix(':') { if label.starts_with(':') {
let label = Label::Named(label.to_string()); let label = parse_label_str(label, labelpos)?;
BuiltinOp::FarLabel(label) BuiltinOp::FarLabel(label)
} else { } else {
return Ok(ParseRes::Unknown(args)); return Ok(ParseRes::Unknown(args));
@ -198,8 +198,8 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok
} }
other => { other => {
if let Some(label) = other.strip_prefix(':') { if other.starts_with(':') {
BuiltinOp::Label(parse_label_str(label, &op_pos)?) BuiltinOp::Label(parse_label_str(other, &op_pos)?)
} else { } else {
return Ok(ParseRes::Unknown(args)); return Ok(ParseRes::Unknown(args));
} }

@ -1,4 +1,8 @@
( (
(sym 🐈 r0)
(ld 🐈 7)
(unsym 🐈)
(def FOO 777) (def FOO 777)
(undef FOO) (undef FOO)

Loading…
Cancel
Save