Refactor AtRule parsing and parse @return
This commit is contained in:
parent
a3c668ae83
commit
cdd0ccca16
@ -1,17 +1,87 @@
|
|||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
use std::iter::Peekable;
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
|
|
||||||
use crate::common::Pos;
|
use crate::{Token, TokenKind};
|
||||||
|
use crate::common::{Pos, Scope, Symbol};
|
||||||
use crate::function::Function;
|
use crate::function::Function;
|
||||||
use crate::mixin::Mixin;
|
use crate::mixin::Mixin;
|
||||||
|
use crate::utils::devour_whitespace;
|
||||||
|
use crate::value::Value;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) enum AtRule {
|
pub(crate) enum AtRule {
|
||||||
Error(Pos, String),
|
Error(Pos, String),
|
||||||
Warn(Pos, String),
|
Warn(Pos, String),
|
||||||
Debug(Pos, String),
|
Debug(Pos, String),
|
||||||
Mixin(String, Mixin),
|
Mixin(String, Box<Mixin>),
|
||||||
Function(String, Function),
|
Function(String, Box<Function>),
|
||||||
|
Return(Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AtRule {
|
||||||
|
pub fn from_tokens<I: Iterator<Item = Token>>(
|
||||||
|
rule: &AtRuleKind,
|
||||||
|
pos: Pos,
|
||||||
|
toks: &mut Peekable<I>,
|
||||||
|
scope: &Scope,
|
||||||
|
) -> AtRule {
|
||||||
|
devour_whitespace(toks);
|
||||||
|
match rule {
|
||||||
|
AtRuleKind::Error => {
|
||||||
|
let message = toks
|
||||||
|
.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon))
|
||||||
|
.map(|x| x.kind.to_string())
|
||||||
|
.collect::<String>();
|
||||||
|
AtRule::Error(pos, message)
|
||||||
|
}
|
||||||
|
AtRuleKind::Warn => {
|
||||||
|
let message = toks
|
||||||
|
.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon))
|
||||||
|
.map(|x| x.kind.to_string())
|
||||||
|
.collect::<String>();
|
||||||
|
devour_whitespace(toks);
|
||||||
|
AtRule::Warn(pos, message)
|
||||||
|
}
|
||||||
|
AtRuleKind::Debug => {
|
||||||
|
let message = toks
|
||||||
|
.by_ref()
|
||||||
|
.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon))
|
||||||
|
.map(|x| x.kind.to_string())
|
||||||
|
.collect::<String>();
|
||||||
|
devour_whitespace(toks);
|
||||||
|
AtRule::Debug(pos, message)
|
||||||
|
}
|
||||||
|
AtRuleKind::Mixin => {
|
||||||
|
let (name, mixin) = match Mixin::decl_from_tokens(toks, scope) {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(e) => return AtRule::Error(e.0, e.1),
|
||||||
|
};
|
||||||
|
AtRule::Mixin(name, Box::new(mixin))
|
||||||
|
}
|
||||||
|
AtRuleKind::Function => {
|
||||||
|
let (name, func) = match Function::decl_from_tokens(toks, scope) {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(e) => return AtRule::Error(e.0, e.1),
|
||||||
|
};
|
||||||
|
AtRule::Function(name, Box::new(func))
|
||||||
|
}
|
||||||
|
AtRuleKind::Return => AtRule::Return(Value::from_tokens(toks, scope).unwrap()),
|
||||||
|
AtRuleKind::Use => todo!("@use not yet implemented"),
|
||||||
|
AtRuleKind::Annotation => todo!("@annotation not yet implemented"),
|
||||||
|
AtRuleKind::AtRoot => todo!("@at-root not yet implemented"),
|
||||||
|
AtRuleKind::Charset => todo!("@charset not yet implemented"),
|
||||||
|
AtRuleKind::Each => todo!("@each not yet implemented"),
|
||||||
|
AtRuleKind::Extend => todo!("@extend not yet implemented"),
|
||||||
|
AtRuleKind::If => todo!("@if not yet implemented"),
|
||||||
|
AtRuleKind::Else => todo!("@else not yet implemented"),
|
||||||
|
AtRuleKind::For => todo!("@for not yet implemented"),
|
||||||
|
AtRuleKind::While => todo!("@while not yet implemented"),
|
||||||
|
AtRuleKind::Media => todo!("@media not yet implemented"),
|
||||||
|
AtRuleKind::Keyframes => todo!("@keyframes not yet implemented"),
|
||||||
|
_ => todo!("encountered unimplemented at rule"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
@ -27,6 +97,7 @@ pub enum AtRuleKind {
|
|||||||
Include,
|
Include,
|
||||||
/// Defines custom functions that can be used in SassScript expressions
|
/// Defines custom functions that can be used in SassScript expressions
|
||||||
Function,
|
Function,
|
||||||
|
Return,
|
||||||
/// Allows selectors to inherit styles from one another
|
/// Allows selectors to inherit styles from one another
|
||||||
Extend,
|
Extend,
|
||||||
/// Puts styles within it at the root of the CSS document
|
/// Puts styles within it at the root of the CSS document
|
||||||
@ -94,6 +165,7 @@ impl TryFrom<&str> for AtRuleKind {
|
|||||||
"mixin" => Ok(Self::Mixin),
|
"mixin" => Ok(Self::Mixin),
|
||||||
"include" => Ok(Self::Include),
|
"include" => Ok(Self::Include),
|
||||||
"function" => Ok(Self::Function),
|
"function" => Ok(Self::Function),
|
||||||
|
"return" => Ok(Self::Return),
|
||||||
"extend" => Ok(Self::Extend),
|
"extend" => Ok(Self::Extend),
|
||||||
"atroot" => Ok(Self::AtRoot),
|
"atroot" => Ok(Self::AtRoot),
|
||||||
"error" => Ok(Self::Error),
|
"error" => Ok(Self::Error),
|
||||||
@ -135,6 +207,7 @@ impl Display for AtRuleKind {
|
|||||||
Self::Mixin => write!(f, "@mixin"),
|
Self::Mixin => write!(f, "@mixin"),
|
||||||
Self::Include => write!(f, "@include"),
|
Self::Include => write!(f, "@include"),
|
||||||
Self::Function => write!(f, "@function"),
|
Self::Function => write!(f, "@function"),
|
||||||
|
Self::Return => write!(f, "@return"),
|
||||||
Self::Extend => write!(f, "@extend"),
|
Self::Extend => write!(f, "@extend"),
|
||||||
Self::AtRoot => write!(f, "@atroot"),
|
Self::AtRoot => write!(f, "@atroot"),
|
||||||
Self::Error => write!(f, "@error"),
|
Self::Error => write!(f, "@error"),
|
||||||
|
76
src/lib.rs
76
src/lib.rs
@ -406,12 +406,13 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
pos,
|
pos,
|
||||||
}) = self.lexer.next()
|
}) = self.lexer.next()
|
||||||
{
|
{
|
||||||
match eat_at_rule(rule, pos, &mut self.lexer, &self.global_scope) {
|
match AtRule::from_tokens(rule, pos, &mut self.lexer, &self.global_scope) {
|
||||||
AtRule::Mixin(name, mixin) => {self.global_scope.mixins.insert(name, mixin);},
|
AtRule::Mixin(name, mixin) => {self.global_scope.mixins.insert(name, *mixin);},
|
||||||
AtRule::Function(name, func) => {self.global_scope.functions.insert(name, func);},
|
AtRule::Function(name, func) => {self.global_scope.functions.insert(name, *func);},
|
||||||
AtRule::Error(pos, message) => self.error(pos, &message),
|
AtRule::Error(pos, message) => self.error(pos, &message),
|
||||||
AtRule::Warn(pos, message) => self.warn(pos, &message),
|
AtRule::Warn(pos, message) => self.warn(pos, &message),
|
||||||
AtRule::Debug(pos, message) => self.debug(pos, &message),
|
AtRule::Debug(pos, message) => self.debug(pos, &message),
|
||||||
|
AtRule::Return(_) => todo!("@return in unexpected location!"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -468,68 +469,6 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eat_at_rule<I: Iterator<Item = Token>>(
|
|
||||||
rule: &AtRuleKind,
|
|
||||||
pos: Pos,
|
|
||||||
toks: &mut Peekable<I>,
|
|
||||||
scope: &Scope,
|
|
||||||
) -> AtRule {
|
|
||||||
devour_whitespace(toks);
|
|
||||||
match rule {
|
|
||||||
AtRuleKind::Error => {
|
|
||||||
let message = toks
|
|
||||||
.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon))
|
|
||||||
.map(|x| x.kind.to_string())
|
|
||||||
.collect::<String>();
|
|
||||||
AtRule::Error(pos, message)
|
|
||||||
}
|
|
||||||
AtRuleKind::Warn => {
|
|
||||||
let message = toks
|
|
||||||
.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon))
|
|
||||||
.map(|x| x.kind.to_string())
|
|
||||||
.collect::<String>();
|
|
||||||
devour_whitespace(toks);
|
|
||||||
AtRule::Warn(pos, message)
|
|
||||||
}
|
|
||||||
AtRuleKind::Debug => {
|
|
||||||
let message = toks
|
|
||||||
.by_ref()
|
|
||||||
.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon))
|
|
||||||
.map(|x| x.kind.to_string())
|
|
||||||
.collect::<String>();
|
|
||||||
devour_whitespace(toks);
|
|
||||||
AtRule::Debug(pos, message)
|
|
||||||
}
|
|
||||||
AtRuleKind::Mixin => {
|
|
||||||
let (name, mixin) = match Mixin::decl_from_tokens(toks, scope) {
|
|
||||||
Ok(m) => m,
|
|
||||||
Err(e) => return AtRule::Error(e.0, e.1),
|
|
||||||
};
|
|
||||||
AtRule::Mixin(name, mixin)
|
|
||||||
}
|
|
||||||
AtRuleKind::Function => {
|
|
||||||
let (name, mixin) = match Function::decl_from_tokens(toks, scope) {
|
|
||||||
Ok(m) => m,
|
|
||||||
Err(e) => return AtRule::Error(e.0, e.1),
|
|
||||||
};
|
|
||||||
AtRule::Function(name, mixin)
|
|
||||||
}
|
|
||||||
AtRuleKind::Use => todo!("@use not yet implemented"),
|
|
||||||
AtRuleKind::Annotation => todo!("@annotation not yet implemented"),
|
|
||||||
AtRuleKind::AtRoot => todo!("@at-root not yet implemented"),
|
|
||||||
AtRuleKind::Charset => todo!("@charset not yet implemented"),
|
|
||||||
AtRuleKind::Each => todo!("@each not yet implemented"),
|
|
||||||
AtRuleKind::Extend => todo!("@extend not yet implemented"),
|
|
||||||
AtRuleKind::If => todo!("@if not yet implemented"),
|
|
||||||
AtRuleKind::Else => todo!("@else not yet implemented"),
|
|
||||||
AtRuleKind::For => todo!("@for not yet implemented"),
|
|
||||||
AtRuleKind::While => todo!("@while not yet implemented"),
|
|
||||||
AtRuleKind::Media => todo!("@media not yet implemented"),
|
|
||||||
AtRuleKind::Keyframes => todo!("@keyframes not yet implemented"),
|
|
||||||
_ => todo!("encountered unimplemented at rule"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
||||||
toks: &mut Peekable<I>,
|
toks: &mut Peekable<I>,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
@ -617,12 +556,13 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
|||||||
pos,
|
pos,
|
||||||
}) = toks.next()
|
}) = toks.next()
|
||||||
{
|
{
|
||||||
return match eat_at_rule(rule, pos, toks, scope) {
|
return match AtRule::from_tokens(rule, pos, toks, scope) {
|
||||||
AtRule::Mixin(name, mixin) => Ok(Some(Expr::MixinDecl(name, mixin))),
|
AtRule::Mixin(name, mixin) => Ok(Some(Expr::MixinDecl(name, *mixin))),
|
||||||
AtRule::Function(name, func) => Ok(Some(Expr::FunctionDecl(name, func))),
|
AtRule::Function(name, func) => Ok(Some(Expr::FunctionDecl(name, *func))),
|
||||||
AtRule::Debug(a, b) => Ok(Some(Expr::Debug(a, b))),
|
AtRule::Debug(a, b) => Ok(Some(Expr::Debug(a, b))),
|
||||||
AtRule::Warn(a, b) => Ok(Some(Expr::Warn(a, b))),
|
AtRule::Warn(a, b) => Ok(Some(Expr::Warn(a, b))),
|
||||||
AtRule::Error(a, b) => Err((a, b)),
|
AtRule::Error(a, b) => Err((a, b)),
|
||||||
|
AtRule::Return(_) => todo!("@return in unexpected location!"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user