Treat - and _ as the same in identifiers
This commit is contained in:
parent
783e43b765
commit
fa582b3316
@ -144,11 +144,11 @@ pub(crate) fn eat_call_args<I: Iterator<Item = Token>>(
|
||||
toks.next();
|
||||
match name {
|
||||
Some(ref name) => {
|
||||
args.insert(name.clone(), scope.vars.get(&v).unwrap().clone())
|
||||
args.insert(name.clone(), scope.get_var(&v).unwrap().clone())
|
||||
}
|
||||
None => args.insert(
|
||||
format!("{}", args.len()),
|
||||
scope.vars.get(&v).unwrap().clone(),
|
||||
scope.get_var(&v).unwrap().clone(),
|
||||
),
|
||||
};
|
||||
if let Some(ref mut s) = name {
|
||||
@ -162,10 +162,10 @@ pub(crate) fn eat_call_args<I: Iterator<Item = Token>>(
|
||||
}) => {
|
||||
toks.next();
|
||||
match name {
|
||||
Some(name) => args.insert(name, scope.vars.get(&v).unwrap().clone()),
|
||||
Some(name) => args.insert(name, scope.get_var(&v).unwrap().clone()),
|
||||
None => args.insert(
|
||||
format!("{}", args.len()),
|
||||
scope.vars.get(&v).unwrap().clone(),
|
||||
scope.get_var(&v).unwrap().clone(),
|
||||
),
|
||||
};
|
||||
break;
|
||||
|
@ -342,9 +342,9 @@ impl Display for Pos {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct Scope {
|
||||
pub vars: HashMap<String, Value>,
|
||||
pub mixins: HashMap<String, Mixin>,
|
||||
pub functions: HashMap<String, Function>,
|
||||
vars: HashMap<String, Value>,
|
||||
mixins: HashMap<String, Mixin>,
|
||||
functions: HashMap<String, Function>,
|
||||
}
|
||||
|
||||
impl Scope {
|
||||
@ -357,7 +357,52 @@ impl Scope {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn merge(&mut self, other: Scope) {
|
||||
pub fn get_var(&self, v: &str) -> Result<&Value, String> {
|
||||
match self.vars.get(&v.replace('_', "-")) {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(format!("Undefined variable `{}`.", v))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_var(&mut self, s: &str, v: Value) -> Option<Value> {
|
||||
self.vars.insert(s.replace('_', "-"), v)
|
||||
}
|
||||
|
||||
pub fn var_exists(&self, v: &str) -> bool {
|
||||
self.vars.contains_key(&v.replace('_', "-"))
|
||||
}
|
||||
|
||||
pub fn get_mixin(&self, v: &str) -> Result<&Mixin, String> {
|
||||
match self.mixins.get(&v.replace('_', "-")) {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(format!("Undefined mixin `{}`.", v))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_mixin(&mut self, s: &str, v: Mixin) -> Option<Mixin> {
|
||||
self.mixins.insert(s.replace('_', "-"), v)
|
||||
}
|
||||
|
||||
pub fn mixin_exists(&self, v: &str) -> bool {
|
||||
self.mixins.contains_key(&v.replace('_', "-"))
|
||||
}
|
||||
|
||||
pub fn get_fn(&self, v: &str) -> Result<&Function, String> {
|
||||
match self.functions.get(&v.replace('_', "-")) {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(format!("Undefined function `{}`.", v))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_fn(&mut self, s: &str, v: Function) -> Option<Function> {
|
||||
self.functions.insert(s.replace('_', "-"), v)
|
||||
}
|
||||
|
||||
pub fn fn_exists(&self, v: &str) -> bool {
|
||||
self.functions.contains_key(&v.replace('_', "-"))
|
||||
}
|
||||
|
||||
pub fn extend(&mut self, other: Scope) {
|
||||
self.vars.extend(other.vars);
|
||||
self.mixins.extend(other.mixins);
|
||||
self.functions.extend(other.functions);
|
||||
|
@ -75,7 +75,7 @@ impl Function {
|
||||
None => arg.default.clone().expect("missing variable!"),
|
||||
},
|
||||
};
|
||||
self.scope.vars.insert(arg.name.clone(), val);
|
||||
self.scope.insert_var(&arg.name, val);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ pub(crate) fn import<P: AsRef<Path>>(path: P) -> SassResult<(Vec<Stmt>, Scope)>
|
||||
let (rules2, scope2) =
|
||||
StyleSheet::export_from_path(name.to_str().expect("path should be UTF-8"))?;
|
||||
rules.extend(rules2);
|
||||
scope.merge(scope2);
|
||||
scope.extend(scope2);
|
||||
}
|
||||
}
|
||||
Ok((rules, scope))
|
||||
|
22
src/lib.rs
22
src/lib.rs
@ -353,8 +353,8 @@ impl<'a> StyleSheetParser<'a> {
|
||||
}
|
||||
let VariableDecl { val, default } = eat_variable_value(&mut self.lexer, &self.global_scope)
|
||||
.unwrap_or_else(|err| self.error(err.0, &err.1));
|
||||
if !default || self.global_scope.vars.get(&name).is_none() {
|
||||
self.global_scope.vars.insert(name, val);
|
||||
if !default || self.global_scope.get_var(&name).is_err() {
|
||||
self.global_scope.insert_var(&name, val);
|
||||
}
|
||||
}
|
||||
TokenKind::MultilineComment(_) => {
|
||||
@ -413,7 +413,7 @@ impl<'a> StyleSheetParser<'a> {
|
||||
|
||||
let (new_rules, new_scope) = import(file_name)?;
|
||||
rules.extend(new_rules);
|
||||
self.global_scope.merge(new_scope);
|
||||
self.global_scope.extend(new_scope);
|
||||
}
|
||||
TokenKind::AtRule(_) => {
|
||||
if let Some(Token {
|
||||
@ -423,10 +423,10 @@ impl<'a> StyleSheetParser<'a> {
|
||||
{
|
||||
match AtRule::from_tokens(rule, pos, &mut self.lexer, &self.global_scope) {
|
||||
AtRule::Mixin(name, mixin) => {
|
||||
self.global_scope.mixins.insert(name, *mixin);
|
||||
self.global_scope.insert_mixin(&name, *mixin);
|
||||
}
|
||||
AtRule::Function(name, func) => {
|
||||
self.global_scope.functions.insert(name, *func);
|
||||
self.global_scope.insert_fn(&name, *func);
|
||||
}
|
||||
AtRule::Charset(toks) => rules.push(Stmt::AtRule(AtRule::Charset(toks))),
|
||||
AtRule::Error(pos, message) => self.error(pos, &message),
|
||||
@ -458,10 +458,10 @@ impl<'a> StyleSheetParser<'a> {
|
||||
#[allow(clippy::redundant_closure)]
|
||||
Expr::Styles(s) => stmts.extend(s.into_iter().map(Stmt::Style)),
|
||||
Expr::MixinDecl(name, mixin) => {
|
||||
scope.mixins.insert(name, *mixin);
|
||||
scope.insert_mixin(&name, *mixin);
|
||||
}
|
||||
Expr::FunctionDecl(name, func) => {
|
||||
scope.functions.insert(name, *func);
|
||||
scope.insert_fn(&name, *func);
|
||||
}
|
||||
Expr::Selector(s) => {
|
||||
self.scope += 1;
|
||||
@ -478,10 +478,10 @@ impl<'a> StyleSheetParser<'a> {
|
||||
}
|
||||
Expr::VariableDecl(name, val) => {
|
||||
if self.scope == 0 {
|
||||
scope.vars.insert(name.clone(), val.clone());
|
||||
self.global_scope.vars.insert(name, val);
|
||||
scope.insert_var(&name, val.clone());
|
||||
self.global_scope.insert_var(&name, val);
|
||||
} else {
|
||||
scope.vars.insert(name, val);
|
||||
scope.insert_var(&name, val);
|
||||
}
|
||||
}
|
||||
Expr::Include(rules) => stmts.extend(rules),
|
||||
@ -564,7 +564,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
||||
toks.next();
|
||||
devour_whitespace(toks);
|
||||
let VariableDecl { val, default } = eat_variable_value(toks, scope)?;
|
||||
if !default || scope.vars.get(&name).is_none() {
|
||||
if !default || scope.get_var(&name).is_err() {
|
||||
return Ok(Some(Expr::VariableDecl(name, val)));
|
||||
}
|
||||
} else {
|
||||
|
@ -82,7 +82,7 @@ impl Mixin {
|
||||
None => arg.default.clone().expect("missing variable!"),
|
||||
},
|
||||
};
|
||||
self.scope.vars.insert(arg.name.clone(), val);
|
||||
self.scope.insert_var(&arg.name, val);
|
||||
}
|
||||
self
|
||||
}
|
||||
@ -110,7 +110,7 @@ impl Mixin {
|
||||
}));
|
||||
}
|
||||
Expr::VariableDecl(name, val) => {
|
||||
self.scope.vars.insert(name, val);
|
||||
self.scope.insert_var(&name, val);
|
||||
}
|
||||
Expr::MultilineComment(s) => stmts.push(Stmt::MultilineComment(s)),
|
||||
}
|
||||
@ -155,8 +155,8 @@ pub(crate) fn eat_include<I: Iterator<Item = Token>>(
|
||||
|
||||
devour_whitespace(toks);
|
||||
|
||||
let mixin = match scope.mixins.get(&name) {
|
||||
Some(m) => m.clone(),
|
||||
let mixin = match scope.get_mixin(&name) {
|
||||
Ok(m) => m.clone(),
|
||||
_ => return Err((pos, String::from("Expected identifier."))),
|
||||
};
|
||||
|
||||
|
@ -52,7 +52,7 @@ pub(crate) fn parse_interpolation<I: Iterator<Item = Token>>(
|
||||
todo!("invalid character in interpolation")
|
||||
}
|
||||
TokenKind::Variable(ref v) => val.extend(
|
||||
Lexer::new(&scope.vars.get(v).unwrap().to_string()).collect::<Vec<Token>>(),
|
||||
Lexer::new(&scope.get_var(v).unwrap().to_string()).collect::<Vec<Token>>(),
|
||||
),
|
||||
TokenKind::Interpolation => val.extend(parse_interpolation(tokens, scope)),
|
||||
_ => val.push(tok),
|
||||
|
@ -197,9 +197,9 @@ impl Value {
|
||||
}) => {
|
||||
toks.next();
|
||||
let args = eat_call_args(toks, scope);
|
||||
let func = match scope.functions.get(&s) {
|
||||
Some(f) => f,
|
||||
None => match GLOBAL_FUNCTIONS.get(&s) {
|
||||
let func = match scope.get_fn(&s) {
|
||||
Ok(f) => f,
|
||||
Err(_) => match GLOBAL_FUNCTIONS.get(&s) {
|
||||
Some(f) => return f(&args),
|
||||
None => todo!("called undefined function"),
|
||||
},
|
||||
@ -243,7 +243,7 @@ impl Value {
|
||||
Some(Value::Ident(s, QuoteKind::Single))
|
||||
}
|
||||
TokenKind::Variable(ref v) => {
|
||||
Some(scope.vars.get(v).expect("expected variable").clone())
|
||||
Some(scope.get_var(v).expect("expected variable").clone())
|
||||
}
|
||||
TokenKind::Interpolation => {
|
||||
let mut s = parse_interpolation(toks, scope)
|
||||
|
Loading…
x
Reference in New Issue
Block a user