Refactor mixin parsing into mixin.rs
This commit is contained in:
parent
2f1113ead8
commit
b28295d2b1
@ -489,7 +489,7 @@ impl Scope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum Printer {
|
pub enum Printer {
|
||||||
Error(Pos, String),
|
Error(Pos, String),
|
||||||
Warn(Pos, String),
|
Warn(Pos, String),
|
||||||
Debug(Pos, String),
|
Debug(Pos, String),
|
||||||
|
60
src/main.rs
60
src/main.rs
@ -349,7 +349,7 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
}
|
}
|
||||||
TokenKind::AtRule(AtRule::Mixin) => {
|
TokenKind::AtRule(AtRule::Mixin) => {
|
||||||
let (name, mixin) =
|
let (name, mixin) =
|
||||||
parse_mixin(&mut self.lexer, self.global_scope.clone()).unwrap();
|
Mixin::from_tokens(&mut self.lexer, &self.global_scope).unwrap();
|
||||||
self.global_scope.mixins.insert(name, mixin);
|
self.global_scope.mixins.insert(name, mixin);
|
||||||
}
|
}
|
||||||
TokenKind::AtRule(_) => {
|
TokenKind::AtRule(_) => {
|
||||||
@ -469,60 +469,6 @@ fn eat_include<I: Iterator<Item = Token>>(
|
|||||||
Ok(rules)
|
Ok(rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_mixin<I: Iterator<Item = Token>>(
|
|
||||||
toks: &mut Peekable<I>,
|
|
||||||
scope: Scope,
|
|
||||||
) -> Result<(String, Mixin), Printer> {
|
|
||||||
let Token { pos, .. } = toks
|
|
||||||
.next()
|
|
||||||
.expect("this must exist because we have already peeked");
|
|
||||||
devour_whitespace(toks);
|
|
||||||
let name = if let Some(Token {
|
|
||||||
kind: TokenKind::Ident(s),
|
|
||||||
..
|
|
||||||
}) = toks.next()
|
|
||||||
{
|
|
||||||
s
|
|
||||||
} else {
|
|
||||||
return Err(Printer::Error(
|
|
||||||
pos,
|
|
||||||
String::from("expected identifier after mixin declaration"),
|
|
||||||
));
|
|
||||||
};
|
|
||||||
devour_whitespace(toks);
|
|
||||||
let args = match toks.next() {
|
|
||||||
Some(Token {
|
|
||||||
kind: TokenKind::Symbol(Symbol::OpenParen),
|
|
||||||
..
|
|
||||||
}) => eat_func_args(toks),
|
|
||||||
Some(Token {
|
|
||||||
kind: TokenKind::Symbol(Symbol::OpenCurlyBrace),
|
|
||||||
..
|
|
||||||
}) => FuncArgs::new(),
|
|
||||||
_ => return Err(Printer::Error(pos, String::from("expected `(` or `{`"))),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut nesting = 1;
|
|
||||||
let mut body = Vec::new();
|
|
||||||
|
|
||||||
while nesting > 0 {
|
|
||||||
if let Some(tok) = toks.next() {
|
|
||||||
match &tok.kind {
|
|
||||||
TokenKind::Symbol(Symbol::OpenCurlyBrace)
|
|
||||||
// interpolation token eats the opening brace but not the closing
|
|
||||||
| TokenKind::Interpolation => nesting += 1,
|
|
||||||
TokenKind::Symbol(Symbol::CloseCurlyBrace) => nesting -= 1,
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
body.push(tok)
|
|
||||||
} else {
|
|
||||||
return Err(Printer::Error(pos, String::from("unexpected EOF")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok((name, Mixin::new(scope, args, body)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eat_at_rule<I: Iterator<Item = Token>>(
|
fn eat_at_rule<I: Iterator<Item = Token>>(
|
||||||
rule: &AtRule,
|
rule: &AtRule,
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
@ -556,7 +502,7 @@ fn eat_at_rule<I: Iterator<Item = Token>>(
|
|||||||
Err(Printer::Debug(pos, message))
|
Err(Printer::Debug(pos, message))
|
||||||
}
|
}
|
||||||
AtRule::Mixin => {
|
AtRule::Mixin => {
|
||||||
let (name, mixin) = parse_mixin(toks, scope.clone())?;
|
let (name, mixin) = Mixin::from_tokens(toks, scope)?;
|
||||||
Ok(Expr::MixinDecl(name, mixin))
|
Ok(Expr::MixinDecl(name, mixin))
|
||||||
}
|
}
|
||||||
// AtRule::Include => return Some(self.eat_include()),
|
// AtRule::Include => return Some(self.eat_include()),
|
||||||
@ -640,7 +586,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
|||||||
}
|
}
|
||||||
TokenKind::AtRule(AtRule::Mixin) => {
|
TokenKind::AtRule(AtRule::Mixin) => {
|
||||||
toks.next();
|
toks.next();
|
||||||
let (name, mixin) = parse_mixin(toks, scope.clone()).unwrap();
|
let (name, mixin) = Mixin::from_tokens(toks, scope).unwrap();
|
||||||
return Ok(Some(Expr::MixinDecl(name, mixin)));
|
return Ok(Some(Expr::MixinDecl(name, mixin)));
|
||||||
}
|
}
|
||||||
TokenKind::AtRule(_) => {
|
TokenKind::AtRule(_) => {
|
||||||
|
64
src/mixin.rs
64
src/mixin.rs
@ -1,10 +1,11 @@
|
|||||||
use std::iter::Peekable;
|
use std::iter::Peekable;
|
||||||
use std::vec::IntoIter;
|
use std::vec::IntoIter;
|
||||||
|
|
||||||
use crate::common::{Pos, Scope};
|
use crate::common::{Pos, Printer, Scope, Symbol};
|
||||||
use crate::function::{CallArgs, FuncArgs};
|
use crate::function::{eat_func_args, CallArgs, FuncArgs};
|
||||||
use crate::selector::Selector;
|
use crate::selector::Selector;
|
||||||
use crate::{eat_expr, Expr, RuleSet, Stmt, Token};
|
use crate::utils::devour_whitespace;
|
||||||
|
use crate::{eat_expr, Expr, RuleSet, Stmt, Token, TokenKind};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Mixin {
|
pub struct Mixin {
|
||||||
@ -25,6 +26,60 @@ impl Mixin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_tokens<I: Iterator<Item = Token>>(
|
||||||
|
toks: &mut Peekable<I>,
|
||||||
|
scope: &Scope,
|
||||||
|
) -> Result<(String, Mixin), Printer> {
|
||||||
|
let Token { pos, .. } = toks
|
||||||
|
.next()
|
||||||
|
.expect("this must exist because we have already peeked");
|
||||||
|
devour_whitespace(toks);
|
||||||
|
let name = if let Some(Token {
|
||||||
|
kind: TokenKind::Ident(s),
|
||||||
|
..
|
||||||
|
}) = toks.next()
|
||||||
|
{
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
return Err(Printer::Error(
|
||||||
|
pos,
|
||||||
|
String::from("expected identifier after mixin declaration"),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
devour_whitespace(toks);
|
||||||
|
let args = match toks.next() {
|
||||||
|
Some(Token {
|
||||||
|
kind: TokenKind::Symbol(Symbol::OpenParen),
|
||||||
|
..
|
||||||
|
}) => eat_func_args(toks),
|
||||||
|
Some(Token {
|
||||||
|
kind: TokenKind::Symbol(Symbol::OpenCurlyBrace),
|
||||||
|
..
|
||||||
|
}) => FuncArgs::new(),
|
||||||
|
_ => return Err(Printer::Error(pos, String::from("expected `(` or `{`"))),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut nesting = 1;
|
||||||
|
let mut body = Vec::new();
|
||||||
|
|
||||||
|
while nesting > 0 {
|
||||||
|
if let Some(tok) = toks.next() {
|
||||||
|
match &tok.kind {
|
||||||
|
TokenKind::Symbol(Symbol::OpenCurlyBrace)
|
||||||
|
// interpolation token eats the opening brace but not the closing
|
||||||
|
| TokenKind::Interpolation => nesting += 1,
|
||||||
|
TokenKind::Symbol(Symbol::CloseCurlyBrace) => nesting -= 1,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
body.push(tok)
|
||||||
|
} else {
|
||||||
|
return Err(Printer::Error(pos, String::from("unexpected EOF")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((name, Mixin::new(scope.clone(), args, body)))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn args(&mut self, args: &CallArgs) -> &mut Mixin {
|
pub fn args(&mut self, args: &CallArgs) -> &mut Mixin {
|
||||||
for (idx, arg) in args.0.iter().enumerate() {
|
for (idx, arg) in args.0.iter().enumerate() {
|
||||||
if arg.is_named() {
|
if arg.is_named() {
|
||||||
@ -57,8 +112,7 @@ impl Mixin {
|
|||||||
while let Some(expr) = eat_expr(&mut self.body, scope, super_selector)? {
|
while let Some(expr) = eat_expr(&mut self.body, scope, super_selector)? {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Style(s) => stmts.push(Stmt::Style(s)),
|
Expr::Style(s) => stmts.push(Stmt::Style(s)),
|
||||||
Expr::Include(_)
|
Expr::Include(_) | Expr::MixinDecl(_, _) => todo!(),
|
||||||
| Expr::MixinDecl(_, _) => todo!(),
|
|
||||||
Expr::Selector(s) => {
|
Expr::Selector(s) => {
|
||||||
self.nesting += 1;
|
self.nesting += 1;
|
||||||
let rules = self.eval(&super_selector.clone().zip(s.clone()), scope)?;
|
let rules = self.eval(&super_selector.clone().zip(s.clone()), scope)?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user