parse variadic arguments
This commit is contained in:
parent
b440258027
commit
c16b8f448b
40
src/args.rs
40
src/args.rs
@ -1,4 +1,4 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::HashMap;
|
||||||
use std::iter::Peekable;
|
use std::iter::Peekable;
|
||||||
|
|
||||||
use crate::common::Pos;
|
use crate::common::Pos;
|
||||||
@ -19,6 +19,7 @@ pub(crate) struct FuncArgs(pub Vec<FuncArg>);
|
|||||||
pub(crate) struct FuncArg {
|
pub(crate) struct FuncArg {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub default: Option<Value>,
|
pub default: Option<Value>,
|
||||||
|
pub is_variadic: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FuncArgs {
|
impl FuncArgs {
|
||||||
@ -28,11 +29,11 @@ impl FuncArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, std::default::Default)]
|
#[derive(Debug, Clone, std::default::Default)]
|
||||||
pub(crate) struct CallArgs(pub BTreeMap<String, Value>);
|
pub(crate) struct CallArgs(pub HashMap<String, Value>);
|
||||||
|
|
||||||
impl CallArgs {
|
impl CallArgs {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
CallArgs(BTreeMap::new())
|
CallArgs(HashMap::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, val: &str) -> Option<&Value> {
|
pub fn get(&self, val: &str) -> Option<&Value> {
|
||||||
@ -67,6 +68,7 @@ pub(crate) fn eat_func_args<I: Iterator<Item = Token>>(
|
|||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
let mut default: Vec<Token> = Vec::new();
|
let mut default: Vec<Token> = Vec::new();
|
||||||
|
let mut is_variadic = false;
|
||||||
devour_whitespace(toks);
|
devour_whitespace(toks);
|
||||||
let kind = match toks.next() {
|
let kind = match toks.next() {
|
||||||
Some(Token { kind, .. }) => kind,
|
Some(Token { kind, .. }) => kind,
|
||||||
@ -86,6 +88,7 @@ pub(crate) fn eat_func_args<I: Iterator<Item = Token>>(
|
|||||||
scope,
|
scope,
|
||||||
super_selector,
|
super_selector,
|
||||||
)?),
|
)?),
|
||||||
|
is_variadic,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -97,6 +100,7 @@ pub(crate) fn eat_func_args<I: Iterator<Item = Token>>(
|
|||||||
scope,
|
scope,
|
||||||
super_selector,
|
super_selector,
|
||||||
)?),
|
)?),
|
||||||
|
is_variadic,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -107,7 +111,31 @@ pub(crate) fn eat_func_args<I: Iterator<Item = Token>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'.' => todo!("handle varargs"),
|
'.' => {
|
||||||
|
if toks.next().ok_or("expected \".\".")?.kind != '.' {
|
||||||
|
return Err("expected \".\".".into());
|
||||||
|
}
|
||||||
|
if toks.next().ok_or("expected \".\".")?.kind != '.' {
|
||||||
|
return Err("expected \".\".".into());
|
||||||
|
}
|
||||||
|
devour_whitespace(toks);
|
||||||
|
if toks.next().ok_or("expected \")\".")?.kind != ')' {
|
||||||
|
return Err("expected \")\".".into());
|
||||||
|
}
|
||||||
|
|
||||||
|
is_variadic = true;
|
||||||
|
|
||||||
|
args.push(FuncArg {
|
||||||
|
name: name.replace('_', "-"),
|
||||||
|
default: Some(Value::from_tokens(
|
||||||
|
&mut default.into_iter().peekable(),
|
||||||
|
scope,
|
||||||
|
super_selector,
|
||||||
|
)?),
|
||||||
|
is_variadic,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
')' => {
|
')' => {
|
||||||
args.push(FuncArg {
|
args.push(FuncArg {
|
||||||
name: name.replace('_', "-"),
|
name: name.replace('_', "-"),
|
||||||
@ -120,12 +148,14 @@ pub(crate) fn eat_func_args<I: Iterator<Item = Token>>(
|
|||||||
super_selector,
|
super_selector,
|
||||||
)?)
|
)?)
|
||||||
},
|
},
|
||||||
|
is_variadic,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
',' => args.push(FuncArg {
|
',' => args.push(FuncArg {
|
||||||
name: name.replace('_', "-"),
|
name: name.replace('_', "-"),
|
||||||
default: None,
|
default: None,
|
||||||
|
is_variadic,
|
||||||
}),
|
}),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -144,7 +174,7 @@ pub(crate) fn eat_call_args<I: Iterator<Item = Token>>(
|
|||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
super_selector: &Selector,
|
super_selector: &Selector,
|
||||||
) -> SassResult<CallArgs> {
|
) -> SassResult<CallArgs> {
|
||||||
let mut args: BTreeMap<String, Value> = BTreeMap::new();
|
let mut args: HashMap<String, Value> = HashMap::new();
|
||||||
devour_whitespace_or_comment(toks)?;
|
devour_whitespace_or_comment(toks)?;
|
||||||
let mut name: String;
|
let mut name: String;
|
||||||
let mut val: Vec<Token> = Vec::new();
|
let mut val: Vec<Token> = Vec::new();
|
||||||
|
17
tests/args.rs
Normal file
17
tests/args.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#![cfg(test)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod macros;
|
||||||
|
|
||||||
|
error!(
|
||||||
|
variable_after_varargs,
|
||||||
|
"@function foo($a..., $b) {\n @return $a;\n}\n", "Error: expected \")\"."
|
||||||
|
);
|
||||||
|
error!(
|
||||||
|
varargs_one_period,
|
||||||
|
"@function foo($a.) {\n @return $a;\n}\n", "Error: expected \".\"."
|
||||||
|
);
|
||||||
|
error!(
|
||||||
|
varargs_two_periods,
|
||||||
|
"@function foo($a..) {\n @return $a;\n}\n", "Error: expected \".\"."
|
||||||
|
);
|
Loading…
x
Reference in New Issue
Block a user