include full parser context in predicate
This commit is contained in:
parent
a34aa32128
commit
fd685ee36f
@ -183,15 +183,16 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
self.whitespace_or_comment();
|
self.whitespace_or_comment();
|
||||||
|
|
||||||
let value = self.parse_value(true, &|c| match c.peek() {
|
let value = self.parse_value(true, &|parser| match parser.toks.peek() {
|
||||||
Some(Token { kind: ')', .. }) | Some(Token { kind: ',', .. }) => true,
|
Some(Token { kind: ')', .. }) | Some(Token { kind: ',', .. }) => true,
|
||||||
Some(Token { kind: '.', .. }) => {
|
Some(Token { kind: '.', .. }) => {
|
||||||
let next_is_dot = matches!(c.peek_n(1), Some(Token { kind: '.', .. }));
|
let next_is_dot =
|
||||||
|
matches!(parser.toks.peek_n(1), Some(Token { kind: '.', .. }));
|
||||||
|
|
||||||
next_is_dot
|
next_is_dot
|
||||||
}
|
}
|
||||||
Some(Token { kind: '=', .. }) => {
|
Some(Token { kind: '=', .. }) => {
|
||||||
let next_is_eq = matches!(c.peek_n(1), Some(Token { kind: '=', .. }));
|
let next_is_eq = matches!(parser.toks.peek_n(1), Some(Token { kind: '=', .. }));
|
||||||
|
|
||||||
!next_is_eq
|
!next_is_eq
|
||||||
}
|
}
|
||||||
@ -283,10 +284,11 @@ impl<'a> Parser<'a> {
|
|||||||
self.toks.next();
|
self.toks.next();
|
||||||
let left = value?;
|
let left = value?;
|
||||||
|
|
||||||
let right = self.parse_value(true, &|c| match c.peek() {
|
let right = self.parse_value(true, &|parser| match parser.toks.peek() {
|
||||||
Some(Token { kind: ')', .. }) | Some(Token { kind: ',', .. }) => true,
|
Some(Token { kind: ')', .. }) | Some(Token { kind: ',', .. }) => true,
|
||||||
Some(Token { kind: '.', .. }) => {
|
Some(Token { kind: '.', .. }) => {
|
||||||
let next_is_dot = matches!(c.peek_n(1), Some(Token { kind: '.', .. }));
|
let next_is_dot =
|
||||||
|
matches!(parser.toks.peek_n(1), Some(Token { kind: '.', .. }));
|
||||||
|
|
||||||
next_is_dot
|
next_is_dot
|
||||||
}
|
}
|
||||||
|
@ -176,18 +176,18 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
self.whitespace_or_comment();
|
self.whitespace_or_comment();
|
||||||
|
|
||||||
let from_val = self.parse_value(false, &|toks| match toks.peek() {
|
let from_val = self.parse_value(false, &|parser| match parser.toks.peek() {
|
||||||
Some(Token { kind: 't', pos })
|
Some(Token { kind: 't', pos })
|
||||||
| Some(Token { kind: 'T', pos })
|
| Some(Token { kind: 'T', pos })
|
||||||
| Some(Token { kind: '\\', pos }) => {
|
| Some(Token { kind: '\\', pos }) => {
|
||||||
let span = pos;
|
let span = pos;
|
||||||
let mut ident = match peek_ident_no_interpolation(toks, false, span) {
|
let mut ident = match peek_ident_no_interpolation(parser.toks, false, span) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(..) => return false,
|
Err(..) => return false,
|
||||||
};
|
};
|
||||||
ident.node.make_ascii_lowercase();
|
ident.node.make_ascii_lowercase();
|
||||||
let v = matches!(ident.node.to_ascii_lowercase().as_str(), "to" | "through");
|
let v = matches!(ident.node.to_ascii_lowercase().as_str(), "to" | "through");
|
||||||
toks.reset_cursor();
|
parser.toks.reset_cursor();
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
Some(..) | None => false,
|
Some(..) | None => false,
|
||||||
|
@ -34,14 +34,14 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn expression_until_comparison(&mut self) -> SassResult<Cow<'static, str>> {
|
pub fn expression_until_comparison(&mut self) -> SassResult<Cow<'static, str>> {
|
||||||
let value = self.parse_value(false, &|toks| match toks.peek() {
|
let value = self.parse_value(false, &|parser| match parser.toks.peek() {
|
||||||
Some(Token { kind: '>', .. })
|
Some(Token { kind: '>', .. })
|
||||||
| Some(Token { kind: '<', .. })
|
| Some(Token { kind: '<', .. })
|
||||||
| Some(Token { kind: ':', .. })
|
| Some(Token { kind: ':', .. })
|
||||||
| Some(Token { kind: ')', .. }) => true,
|
| Some(Token { kind: ')', .. }) => true,
|
||||||
Some(Token { kind: '=', .. }) => {
|
Some(Token { kind: '=', .. }) => {
|
||||||
let is_double_eq = matches!(toks.peek_next(), Some(Token { kind: '=', .. }));
|
let is_double_eq = matches!(parser.toks.peek_next(), Some(Token { kind: '=', .. }));
|
||||||
toks.reset_cursor();
|
parser.toks.reset_cursor();
|
||||||
// if it is a double eq, then parse as normal
|
// if it is a double eq, then parse as normal
|
||||||
//
|
//
|
||||||
// otherwise, it is a single eq and we should
|
// otherwise, it is a single eq and we should
|
||||||
@ -88,8 +88,8 @@ impl<'a> Parser<'a> {
|
|||||||
buf.push(':');
|
buf.push(':');
|
||||||
buf.push(' ');
|
buf.push(' ');
|
||||||
|
|
||||||
let value = self.parse_value(false, &|toks| {
|
let value = self.parse_value(false, &|parser| {
|
||||||
matches!(toks.peek(), Some(Token { kind: ')', .. }))
|
matches!(parser.toks.peek(), Some(Token { kind: ')', .. }))
|
||||||
})?;
|
})?;
|
||||||
self.expect_char(')')?;
|
self.expect_char(')')?;
|
||||||
|
|
||||||
|
@ -78,9 +78,9 @@ impl<'a> Parser<'a> {
|
|||||||
self.expect_char(':')?;
|
self.expect_char(':')?;
|
||||||
self.whitespace_or_comment();
|
self.whitespace_or_comment();
|
||||||
|
|
||||||
let value = self.parse_value(false, &|toks| {
|
let value = self.parse_value(false, &|parser| {
|
||||||
matches!(
|
matches!(
|
||||||
toks.peek(),
|
parser.toks.peek(),
|
||||||
Some(Token { kind: ',', .. }) | Some(Token { kind: ')', .. })
|
Some(Token { kind: ',', .. }) | Some(Token { kind: ')', .. })
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
@ -45,6 +45,9 @@ impl IsWhitespace for IntermediateValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// We parse a value until the predicate returns true
|
||||||
|
type Predicate<'a> = &'a dyn Fn(&mut Parser<'_>) -> bool;
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
/// Parse a value from a stream of tokens
|
/// Parse a value from a stream of tokens
|
||||||
///
|
///
|
||||||
@ -52,7 +55,7 @@ impl<'a> Parser<'a> {
|
|||||||
pub(crate) fn parse_value(
|
pub(crate) fn parse_value(
|
||||||
&mut self,
|
&mut self,
|
||||||
in_paren: bool,
|
in_paren: bool,
|
||||||
predicate: &dyn Fn(&mut Lexer) -> bool,
|
predicate: Predicate<'_>,
|
||||||
) -> SassResult<Spanned<Value>> {
|
) -> SassResult<Spanned<Value>> {
|
||||||
self.whitespace();
|
self.whitespace();
|
||||||
|
|
||||||
@ -64,7 +67,7 @@ impl<'a> Parser<'a> {
|
|||||||
Some(Token { pos, .. }) => pos,
|
Some(Token { pos, .. }) => pos,
|
||||||
};
|
};
|
||||||
|
|
||||||
if predicate(self.toks) {
|
if predicate(self) {
|
||||||
return Err(("Expected expression.", span).into());
|
return Err(("Expected expression.", span).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,7 +293,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
fn parse_ident_value(
|
fn parse_ident_value(
|
||||||
&mut self,
|
&mut self,
|
||||||
predicate: &dyn Fn(&mut Lexer) -> bool,
|
predicate: Predicate<'_>,
|
||||||
) -> SassResult<Spanned<IntermediateValue>> {
|
) -> SassResult<Spanned<IntermediateValue>> {
|
||||||
let Spanned { node: mut s, span } = self.parse_identifier()?;
|
let Spanned { node: mut s, span } = self.parse_identifier()?;
|
||||||
|
|
||||||
@ -320,7 +323,7 @@ impl<'a> Parser<'a> {
|
|||||||
return self.parse_fn_call(s, lower);
|
return self.parse_fn_call(s, lower);
|
||||||
}
|
}
|
||||||
Some(Token { kind: '.', .. }) => {
|
Some(Token { kind: '.', .. }) => {
|
||||||
if !predicate(self.toks) {
|
if !predicate(self) {
|
||||||
self.toks.next();
|
self.toks.next();
|
||||||
return self.parse_module_item(&s, span);
|
return self.parse_module_item(&s, span);
|
||||||
}
|
}
|
||||||
@ -360,14 +363,11 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_number(
|
fn parse_number(&mut self, predicate: Predicate<'_>) -> SassResult<Spanned<ParsedNumber>> {
|
||||||
&mut self,
|
|
||||||
predicate: &dyn Fn(&mut Lexer) -> bool,
|
|
||||||
) -> SassResult<Spanned<ParsedNumber>> {
|
|
||||||
let mut span = self.toks.peek().unwrap().pos;
|
let mut span = self.toks.peek().unwrap().pos;
|
||||||
let mut whole = eat_whole_number(self.toks);
|
let mut whole = eat_whole_number(self.toks);
|
||||||
|
|
||||||
if self.toks.peek().is_none() || predicate(self.toks) {
|
if self.toks.peek().is_none() || predicate(self) {
|
||||||
return Ok(Spanned {
|
return Ok(Spanned {
|
||||||
node: ParsedNumber::new(whole, 0, String::new(), true),
|
node: ParsedNumber::new(whole, 0, String::new(), true),
|
||||||
span,
|
span,
|
||||||
@ -452,8 +452,8 @@ impl<'a> Parser<'a> {
|
|||||||
.span(span)
|
.span(span)
|
||||||
} else {
|
} else {
|
||||||
// todo: we don't know if we're `in_paren` here
|
// todo: we don't know if we're `in_paren` here
|
||||||
let inner = self.parse_value(false, &|toks| {
|
let inner = self.parse_value(false, &|parser| {
|
||||||
matches!(toks.peek(), Some(Token { kind: ']', .. }))
|
matches!(parser.toks.peek(), Some(Token { kind: ']', .. }))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
span = span.merge(inner.span);
|
span = span.merge(inner.span);
|
||||||
@ -470,7 +470,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
fn parse_intermediate_value_dimension(
|
fn parse_intermediate_value_dimension(
|
||||||
&mut self,
|
&mut self,
|
||||||
predicate: &dyn Fn(&mut Lexer) -> bool,
|
predicate: Predicate<'_>,
|
||||||
) -> SassResult<Spanned<IntermediateValue>> {
|
) -> SassResult<Spanned<IntermediateValue>> {
|
||||||
let Spanned { node, span } = self.parse_dimension(predicate)?;
|
let Spanned { node, span } = self.parse_dimension(predicate)?;
|
||||||
|
|
||||||
@ -479,7 +479,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
pub(crate) fn parse_dimension(
|
pub(crate) fn parse_dimension(
|
||||||
&mut self,
|
&mut self,
|
||||||
predicate: &dyn Fn(&mut Lexer) -> bool,
|
predicate: Predicate<'_>,
|
||||||
) -> SassResult<Spanned<Value>> {
|
) -> SassResult<Spanned<Value>> {
|
||||||
let Spanned {
|
let Spanned {
|
||||||
node: val,
|
node: val,
|
||||||
@ -568,9 +568,9 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut map = SassMap::new();
|
let mut map = SassMap::new();
|
||||||
let key = self.parse_value(true, &|c| {
|
let key = self.parse_value(true, &|parser| {
|
||||||
matches!(
|
matches!(
|
||||||
c.peek(),
|
parser.toks.peek(),
|
||||||
Some(Token { kind: ':', .. }) | Some(Token { kind: ')', .. })
|
Some(Token { kind: ':', .. }) | Some(Token { kind: ')', .. })
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
@ -586,9 +586,9 @@ impl<'a> Parser<'a> {
|
|||||||
Some(..) | None => return Err(("expected \")\".", key.span).into()),
|
Some(..) | None => return Err(("expected \")\".", key.span).into()),
|
||||||
}
|
}
|
||||||
|
|
||||||
let val = self.parse_value(true, &|c| {
|
let val = self.parse_value(true, &|parser| {
|
||||||
matches!(
|
matches!(
|
||||||
c.peek(),
|
parser.toks.peek(),
|
||||||
Some(Token { kind: ',', .. }) | Some(Token { kind: ')', .. })
|
Some(Token { kind: ',', .. }) | Some(Token { kind: ')', .. })
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
@ -624,9 +624,9 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let key = self.parse_value(true, &|c| {
|
let key = self.parse_value(true, &|parser| {
|
||||||
matches!(
|
matches!(
|
||||||
c.peek(),
|
parser.toks.peek(),
|
||||||
Some(Token { kind: ':', .. }) | Some(Token { kind: ',', .. })
|
Some(Token { kind: ':', .. }) | Some(Token { kind: ',', .. })
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
@ -634,9 +634,9 @@ impl<'a> Parser<'a> {
|
|||||||
self.expect_char(':')?;
|
self.expect_char(':')?;
|
||||||
|
|
||||||
self.whitespace_or_comment();
|
self.whitespace_or_comment();
|
||||||
let val = self.parse_value(true, &|c| {
|
let val = self.parse_value(true, &|parser| {
|
||||||
matches!(
|
matches!(
|
||||||
c.peek(),
|
parser.toks.peek(),
|
||||||
Some(Token { kind: ',', .. }) | Some(Token { kind: ')', .. })
|
Some(Token { kind: ',', .. }) | Some(Token { kind: ')', .. })
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
@ -763,9 +763,9 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
fn parse_intermediate_value(
|
fn parse_intermediate_value(
|
||||||
&mut self,
|
&mut self,
|
||||||
predicate: &dyn Fn(&mut Lexer) -> bool,
|
predicate: Predicate<'_>,
|
||||||
) -> Option<SassResult<Spanned<IntermediateValue>>> {
|
) -> Option<SassResult<Spanned<IntermediateValue>>> {
|
||||||
if predicate(self.toks) {
|
if predicate(self) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let (kind, span) = match self.toks.peek() {
|
let (kind, span) = match self.toks.peek() {
|
||||||
@ -1038,7 +1038,7 @@ impl<'a> Parser<'a> {
|
|||||||
struct IntermediateValueIterator<'a, 'b: 'a> {
|
struct IntermediateValueIterator<'a, 'b: 'a> {
|
||||||
parser: &'a mut Parser<'b>,
|
parser: &'a mut Parser<'b>,
|
||||||
peek: Option<SassResult<Spanned<IntermediateValue>>>,
|
peek: Option<SassResult<Spanned<IntermediateValue>>>,
|
||||||
predicate: &'a dyn Fn(&mut Lexer) -> bool,
|
predicate: Predicate<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b: 'a> Iterator for IntermediateValueIterator<'a, 'b> {
|
impl<'a, 'b: 'a> Iterator for IntermediateValueIterator<'a, 'b> {
|
||||||
@ -1053,7 +1053,7 @@ impl<'a, 'b: 'a> Iterator for IntermediateValueIterator<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b: 'a> IntermediateValueIterator<'a, 'b> {
|
impl<'a, 'b: 'a> IntermediateValueIterator<'a, 'b> {
|
||||||
pub fn new(parser: &'a mut Parser<'b>, predicate: &'a dyn Fn(&mut Lexer) -> bool) -> Self {
|
pub fn new(parser: &'a mut Parser<'b>, predicate: Predicate<'a>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
parser,
|
parser,
|
||||||
peek: None,
|
peek: None,
|
||||||
|
@ -111,15 +111,15 @@ impl<'a> Parser<'a> {
|
|||||||
let mut default = false;
|
let mut default = false;
|
||||||
let mut global = false;
|
let mut global = false;
|
||||||
|
|
||||||
let value = self.parse_value(true, &|toks| {
|
let value = self.parse_value(true, &|parser| {
|
||||||
if matches!(toks.peek(), Some(Token { kind: '!', .. })) {
|
if matches!(parser.toks.peek(), Some(Token { kind: '!', .. })) {
|
||||||
let is_important = matches!(
|
let is_important = matches!(
|
||||||
toks.peek_next(),
|
parser.toks.peek_next(),
|
||||||
Some(Token { kind: 'i', .. })
|
Some(Token { kind: 'i', .. })
|
||||||
| Some(Token { kind: 'I', .. })
|
| Some(Token { kind: 'I', .. })
|
||||||
| Some(Token { kind: '=', .. })
|
| Some(Token { kind: '=', .. })
|
||||||
);
|
);
|
||||||
toks.reset_cursor();
|
parser.toks.reset_cursor();
|
||||||
!is_important
|
!is_important
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
Loading…
x
Reference in New Issue
Block a user