From cee40858ee140a671cd20c4ea55c1e0a33c56638 Mon Sep 17 00:00:00 2001 From: ConnorSkees <39542938+ConnorSkees@users.noreply.github.com> Date: Fri, 17 Jan 2020 16:23:21 -0500 Subject: [PATCH] Refactor function parsing into separate module --- src/function.rs | 140 ++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 98 +++------------------------------ src/mixin.rs | 52 +++--------------- 3 files changed, 154 insertions(+), 136 deletions(-) create mode 100644 src/function.rs diff --git a/src/function.rs b/src/function.rs new file mode 100644 index 0000000..544232d --- /dev/null +++ b/src/function.rs @@ -0,0 +1,140 @@ +use std::iter::Peekable; + +use crate::common::Symbol; +use crate::utils::devour_whitespace; +use crate::{Token, TokenKind}; + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct FuncArgs(pub Vec); + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct FuncArg { + pub name: String, + pub default: Option>, +} + +impl FuncArgs { + pub const fn new() -> Self { + FuncArgs(Vec::new()) + } +} + +#[derive(Debug, Clone)] +pub struct CallArgs(pub Vec); + +#[derive(Debug, Clone)] +pub struct CallArg { + pub name: Option, + pub val: Vec, +} + +impl CallArg { + pub fn is_named(&self) -> bool { + self.name.is_some() + } +} + +impl CallArgs { + pub const fn new() -> Self { + CallArgs(Vec::new()) + } + + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +pub fn eat_func_args>(toks: &mut Peekable) -> FuncArgs { + let mut args: Vec = Vec::new(); + + devour_whitespace(toks); + while let Some(Token { kind, .. }) = toks.next() { + let name = match kind { + TokenKind::Variable(v) => v, + TokenKind::Symbol(Symbol::CloseParen) => break, + _ => todo!(), + }; + devour_whitespace(toks); + let kind = if let Some(Token { kind, .. }) = toks.next() { + kind + } else { + todo!() + }; + match kind { + TokenKind::Symbol(Symbol::Colon) => { + todo!("handle default values") + // let mut val: Vec = Vec::new(); + // while let Some(tok) = toks.next() { + // match &kind { + // _ => val.push(tok), + // } + // } + } + TokenKind::Symbol(Symbol::Period) => todo!("handle varargs"), + TokenKind::Symbol(Symbol::CloseParen) => { + args.push(FuncArg { + name, + default: None, + }); + break; + } + TokenKind::Symbol(Symbol::Comma) => args.push(FuncArg { + name, + default: None, + }), + _ => {} + } + devour_whitespace(toks); + } + devour_whitespace(toks); + if let Some(Token { + kind: TokenKind::Symbol(Symbol::OpenCurlyBrace), + .. + }) = toks.next() + { + } else { + todo!("expected `{{` after mixin args") + } + FuncArgs(args) +} + +pub fn eat_call_args>(toks: &mut Peekable) -> CallArgs { + let mut args: Vec = Vec::new(); + devour_whitespace(toks); + let mut name: Option = None; + let mut val = Vec::new(); + while let Some(Token { kind, pos }) = toks.next() { + match kind { + TokenKind::Variable(v) => name = Some(v), + TokenKind::Symbol(Symbol::Colon) => { + todo!("handle default values") + // let mut val: Vec = Vec::new(); + // while let Some(Token { kind, .. }) = toks.next() { + // match &kind { + // _ => {} + // } + // } + } + TokenKind::Symbol(Symbol::CloseParen) => { + args.push(CallArg { + name: name.clone(), + val: val.clone(), + }); + break; + } + TokenKind::Symbol(Symbol::Comma) => { + args.push(CallArg { + name: name.clone(), + val: val.clone(), + }); + if let Some(ref mut s) = name { + s.clear(); + } + val.clear(); + } + _ => val.push(Token { kind, pos }), + } + devour_whitespace(toks); + } + CallArgs(args) +} diff --git a/src/main.rs b/src/main.rs index af53060..502809c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,8 +35,9 @@ use crate::common::{AtRule, Keyword, Op, Pos, Printer, Scope, Symbol, Whitespace use crate::css::Css; use crate::error::SassError; use crate::format::PrettyPrinter; +use crate::function::{eat_call_args, eat_func_args, CallArgs, FuncArgs}; use crate::lexer::Lexer; -use crate::mixin::{CallArg, CallArgs, FuncArg, FuncArgs, Mixin}; +use crate::mixin::Mixin; use crate::selector::{Attribute, Selector}; use crate::style::Style; use crate::units::Unit; @@ -47,6 +48,7 @@ mod common; mod css; mod error; mod format; +mod function; mod imports; mod lexer; mod mixin; @@ -379,100 +381,12 @@ fn eat_include>( } else { return Err((pos, "expected identifier")); }; - let rules = mixin.call_with_args(&args).eval(super_selector, &mut scope.clone()); + let rules = mixin + .call_with_args(&args) + .eval(super_selector, &mut scope.clone()); Ok(rules) } -fn eat_func_args>(toks: &mut Peekable) -> FuncArgs { - let mut args: Vec = Vec::new(); - - devour_whitespace(toks); - while let Some(Token { kind, .. }) = toks.next() { - let name = match kind { - TokenKind::Variable(v) => v, - TokenKind::Symbol(Symbol::CloseParen) => break, - _ => todo!(), - }; - devour_whitespace(toks); - let kind = if let Some(Token { kind, .. }) = toks.next() { - kind - } else { - todo!() - }; - match kind { - TokenKind::Symbol(Symbol::Colon) => { - todo!("handle default values") - // let mut val: Vec = Vec::new(); - // while let Some(tok) = toks.next() { - // match &kind { - // _ => val.push(tok), - // } - // } - } - TokenKind::Symbol(Symbol::Period) => todo!("handle varargs"), - TokenKind::Symbol(Symbol::CloseParen) => { - args.push(FuncArg { - name, - default: None, - }); - break; - } - TokenKind::Symbol(Symbol::Comma) => args.push(FuncArg { - name, - default: None, - }), - _ => {} - } - devour_whitespace(toks); - } - devour_whitespace(toks); - if let Some(Token { kind: TokenKind::Symbol(Symbol::OpenCurlyBrace), .. }) = toks.next() {} else { - todo!("expected `{{` after mixin args") - } - FuncArgs(args) -} - -fn eat_call_args>(toks: &mut Peekable) -> CallArgs { - let mut args: Vec = Vec::new(); - devour_whitespace(toks); - let mut name: Option = None; - let mut val = Vec::new(); - while let Some(Token { kind, pos }) = toks.next() { - match kind { - TokenKind::Variable(v) => name = Some(v), - TokenKind::Symbol(Symbol::Colon) => { - todo!("handle default values") - // let mut val: Vec = Vec::new(); - // while let Some(Token { kind, .. }) = toks.next() { - // match &kind { - // _ => {} - // } - // } - } - TokenKind::Symbol(Symbol::CloseParen) => { - args.push(CallArg { - name: name.clone(), - val: val.clone(), - }); - break; - }, - TokenKind::Symbol(Symbol::Comma) => { - args.push(CallArg { - name: name.clone(), - val: val.clone(), - }); - if let Some(ref mut s) = name { - s.clear(); - } - val.clear(); - } - _ => val.push(Token { kind, pos }), - } - devour_whitespace(toks); - } - CallArgs(args) -} - fn parse_mixin>( toks: &mut Peekable, scope: Scope, diff --git a/src/mixin.rs b/src/mixin.rs index 93b0bb7..0f6b00e 100644 --- a/src/mixin.rs +++ b/src/mixin.rs @@ -1,9 +1,11 @@ -use crate::common::Scope; -use crate::selector::Selector; -use crate::{eat_expr, Expr, RuleSet, Stmt, Token}; use std::iter::Peekable; use std::vec::IntoIter; +use crate::common::Scope; +use crate::function::{CallArgs, FuncArgs}; +use crate::selector::Selector; +use crate::{eat_expr, Expr, RuleSet, Stmt, Token}; + #[derive(Debug, Clone)] pub struct Mixin { scope: Scope, @@ -29,7 +31,9 @@ impl Mixin { todo!("keyword args") } else { // dbg!(&self.args.0[idx].name.clone()); - self.scope.vars.insert(self.args.0[idx].name.clone(), arg.val.clone()); + self.scope + .vars + .insert(self.args.0[idx].name.clone(), arg.val.clone()); } } self @@ -67,43 +71,3 @@ impl Mixin { stmts } } - -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct FuncArgs(pub Vec); - -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct FuncArg { - pub name: String, - pub default: Option>, -} - -impl FuncArgs { - pub const fn new() -> Self { - FuncArgs(Vec::new()) - } -} - -#[derive(Debug, Clone)] -pub struct CallArgs(pub Vec); - -#[derive(Debug, Clone)] -pub struct CallArg { - pub name: Option, - pub val: Vec, -} - -impl CallArg { - pub fn is_named(&self) -> bool { - self.name.is_some() - } -} - -impl CallArgs { - pub const fn new() -> Self { - CallArgs(Vec::new()) - } - - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} \ No newline at end of file