refactor parsing of toplevel variables
This commit is contained in:
parent
6b9f68922f
commit
c68576bb23
@ -22,7 +22,7 @@ use crate::selector::Selector;
|
|||||||
use crate::token::Token;
|
use crate::token::Token;
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
devour_whitespace, eat_comment, eat_ident, eat_variable_value, parse_quoted_string,
|
devour_whitespace, eat_comment, eat_ident, eat_variable_value, parse_quoted_string,
|
||||||
read_until_newline, VariableDecl,
|
peek_ident_no_interpolation, peek_whitespace, read_until_newline, VariableDecl,
|
||||||
};
|
};
|
||||||
use crate::{eat_expr, Expr, RuleSet, Stmt};
|
use crate::{eat_expr, Expr, RuleSet, Stmt};
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ impl StyleSheet {
|
|||||||
let file = map.add_file("stdin".into(), input);
|
let file = map.add_file("stdin".into(), input);
|
||||||
Css::from_stylesheet(StyleSheet(
|
Css::from_stylesheet(StyleSheet(
|
||||||
StyleSheetParser {
|
StyleSheetParser {
|
||||||
lexer: Lexer::new(&file).peekmore(),
|
lexer: &mut Lexer::new(&file).peekmore(),
|
||||||
nesting: 0,
|
nesting: 0,
|
||||||
map: &mut map,
|
map: &mut map,
|
||||||
path: Path::new(""),
|
path: Path::new(""),
|
||||||
@ -111,7 +111,7 @@ impl StyleSheet {
|
|||||||
let file = map.add_file(p.into(), String::from_utf8(fs::read(p)?)?);
|
let file = map.add_file(p.into(), String::from_utf8(fs::read(p)?)?);
|
||||||
Css::from_stylesheet(StyleSheet(
|
Css::from_stylesheet(StyleSheet(
|
||||||
StyleSheetParser {
|
StyleSheetParser {
|
||||||
lexer: Lexer::new(&file).peekmore(),
|
lexer: &mut Lexer::new(&file).peekmore(),
|
||||||
nesting: 0,
|
nesting: 0,
|
||||||
map: &mut map,
|
map: &mut map,
|
||||||
path: p.as_ref(),
|
path: p.as_ref(),
|
||||||
@ -131,7 +131,7 @@ impl StyleSheet {
|
|||||||
) -> SassResult<(Vec<Spanned<Stmt>>, Scope)> {
|
) -> SassResult<(Vec<Spanned<Stmt>>, Scope)> {
|
||||||
let file = map.add_file(p.clone().into(), String::from_utf8(fs::read(p)?)?);
|
let file = map.add_file(p.clone().into(), String::from_utf8(fs::read(p)?)?);
|
||||||
Ok(StyleSheetParser {
|
Ok(StyleSheetParser {
|
||||||
lexer: Lexer::new(&file).peekmore(),
|
lexer: &mut Lexer::new(&file).peekmore(),
|
||||||
nesting: 0,
|
nesting: 0,
|
||||||
map,
|
map,
|
||||||
path: p.as_ref(),
|
path: p.as_ref(),
|
||||||
@ -145,7 +145,7 @@ impl StyleSheet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct StyleSheetParser<'a> {
|
struct StyleSheetParser<'a> {
|
||||||
lexer: PeekMoreIterator<Lexer<'a>>,
|
lexer: &'a mut PeekMoreIterator<Lexer<'a>>,
|
||||||
nesting: u32,
|
nesting: u32,
|
||||||
map: &'a mut CodeMap,
|
map: &'a mut CodeMap,
|
||||||
path: &'a Path,
|
path: &'a Path,
|
||||||
@ -171,36 +171,35 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
'$' => {
|
'$' => {
|
||||||
let span_before = self.lexer.next().unwrap().pos();
|
self.lexer.next();
|
||||||
let name = eat_ident(
|
let name = peek_ident_no_interpolation(self.lexer, false)?;
|
||||||
&mut self.lexer,
|
let whitespace = peek_whitespace(self.lexer);
|
||||||
&Scope::new(),
|
|
||||||
&Selector::new(),
|
match self.lexer.peek() {
|
||||||
span_before
|
Some(Token { kind: ':', .. }) => {
|
||||||
)?;
|
self.lexer.take(name.node.chars().count() + whitespace + 1)
|
||||||
devour_whitespace(&mut self.lexer);
|
.for_each(drop);
|
||||||
let Token { kind, pos } = self
|
devour_whitespace(self.lexer);
|
||||||
.lexer
|
|
||||||
.next()
|
let VariableDecl { val, default, .. } =
|
||||||
.unwrap();
|
eat_variable_value(self.lexer, &Scope::new(), &Selector::new())?;
|
||||||
if kind != ':' {
|
|
||||||
return Err(("expected \":\".", pos).into());
|
if !(default && global_var_exists(&name)) {
|
||||||
}
|
insert_global_var(&name.node, val)?;
|
||||||
let VariableDecl { val, default, .. } =
|
}
|
||||||
eat_variable_value(&mut self.lexer, &Scope::new(), &Selector::new())?;
|
}
|
||||||
if !(default && global_var_exists(&name)) {
|
Some(..) | None => return Err(("expected \":\".", name.span).into()),
|
||||||
insert_global_var(&name.node, val)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'/' => {
|
'/' => {
|
||||||
let pos = self.lexer.next().unwrap().pos;
|
let pos = self.lexer.next().unwrap().pos;
|
||||||
match self.lexer.next() {
|
match self.lexer.next() {
|
||||||
Some(Token { kind: '/', .. }) => {
|
Some(Token { kind: '/', .. }) => {
|
||||||
read_until_newline(&mut self.lexer);
|
read_until_newline(self.lexer);
|
||||||
devour_whitespace(&mut self.lexer);
|
devour_whitespace(self.lexer);
|
||||||
}
|
}
|
||||||
Some(Token { kind: '*', .. }) => {
|
Some(Token { kind: '*', .. }) => {
|
||||||
let comment = eat_comment(&mut self.lexer, &Scope::new(), &Selector::new())?;
|
let comment = eat_comment(self.lexer, &Scope::new(), &Selector::new())?;
|
||||||
rules.push(comment.map_node(Stmt::MultilineComment));
|
rules.push(comment.map_node(Stmt::MultilineComment));
|
||||||
}
|
}
|
||||||
_ => return Err(("expected selector.", pos).into())
|
_ => return Err(("expected selector.", pos).into())
|
||||||
@ -209,7 +208,7 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
'@' => {
|
'@' => {
|
||||||
let span_before = self.lexer.next().unwrap().pos();
|
let span_before = self.lexer.next().unwrap().pos();
|
||||||
let Spanned { node: at_rule_kind, span } = eat_ident(
|
let Spanned { node: at_rule_kind, span } = eat_ident(
|
||||||
&mut self.lexer,
|
self.lexer,
|
||||||
&Scope::new(),
|
&Scope::new(),
|
||||||
&Selector::new(),
|
&Selector::new(),
|
||||||
span_before
|
span_before
|
||||||
@ -219,14 +218,14 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
}
|
}
|
||||||
match AtRuleKind::from(at_rule_kind.as_str()) {
|
match AtRuleKind::from(at_rule_kind.as_str()) {
|
||||||
AtRuleKind::Include => rules.extend(eat_include(
|
AtRuleKind::Include => rules.extend(eat_include(
|
||||||
&mut self.lexer,
|
self.lexer,
|
||||||
&Scope::new(),
|
&Scope::new(),
|
||||||
&Selector::new(),
|
&Selector::new(),
|
||||||
None,
|
None,
|
||||||
span
|
span
|
||||||
)?),
|
)?),
|
||||||
AtRuleKind::Import => {
|
AtRuleKind::Import => {
|
||||||
devour_whitespace(&mut self.lexer);
|
devour_whitespace(self.lexer);
|
||||||
let mut file_name = String::new();
|
let mut file_name = String::new();
|
||||||
let next = match self.lexer.next() {
|
let next = match self.lexer.next() {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
@ -236,7 +235,7 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
q @ '"' | q @ '\'' => {
|
q @ '"' | q @ '\'' => {
|
||||||
file_name.push_str(
|
file_name.push_str(
|
||||||
&parse_quoted_string(
|
&parse_quoted_string(
|
||||||
&mut self.lexer,
|
self.lexer,
|
||||||
&Scope::new(),
|
&Scope::new(),
|
||||||
q,
|
q,
|
||||||
&Selector::new())?
|
&Selector::new())?
|
||||||
@ -250,7 +249,7 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
devour_whitespace(&mut self.lexer);
|
devour_whitespace(self.lexer);
|
||||||
|
|
||||||
let (new_rules, new_scope) = import(self.path, file_name.as_ref(), &mut self.map)?;
|
let (new_rules, new_scope) = import(self.path, file_name.as_ref(), &mut self.map)?;
|
||||||
rules.extend(new_rules);
|
rules.extend(new_rules);
|
||||||
@ -259,7 +258,7 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
v => {
|
v => {
|
||||||
let rule = AtRule::from_tokens(v, span, &mut self.lexer, &mut Scope::new(), &Selector::new(), None)?;
|
let rule = AtRule::from_tokens(v, span, self.lexer, &mut Scope::new(), &Selector::new(), None)?;
|
||||||
match rule.node {
|
match rule.node {
|
||||||
AtRule::Mixin(name, mixin) => {
|
AtRule::Mixin(name, mixin) => {
|
||||||
insert_global_mixin(&name, *mixin);
|
insert_global_mixin(&name, *mixin);
|
||||||
@ -320,7 +319,7 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
) -> SassResult<Vec<Spanned<Stmt>>> {
|
) -> SassResult<Vec<Spanned<Stmt>>> {
|
||||||
let mut stmts = Vec::new();
|
let mut stmts = Vec::new();
|
||||||
while let Some(expr) = eat_expr(&mut self.lexer, scope, super_selector, None)? {
|
while let Some(expr) = eat_expr(self.lexer, scope, super_selector, None)? {
|
||||||
let span = expr.span;
|
let span = expr.span;
|
||||||
match expr.node {
|
match expr.node {
|
||||||
Expr::Style(s) => stmts.push(Spanned {
|
Expr::Style(s) => stmts.push(Spanned {
|
||||||
|
@ -161,6 +161,7 @@ pub(crate) fn peek_ident_no_interpolation<I: Iterator<Item = Token>>(
|
|||||||
toks: &mut PeekMoreIterator<I>,
|
toks: &mut PeekMoreIterator<I>,
|
||||||
unit: bool,
|
unit: bool,
|
||||||
) -> SassResult<Spanned<String>> {
|
) -> SassResult<Spanned<String>> {
|
||||||
|
// todo: panics on "$"
|
||||||
let mut span = toks.peek().unwrap().pos();
|
let mut span = toks.peek().unwrap().pos();
|
||||||
let mut text = String::new();
|
let mut text = String::new();
|
||||||
if toks.peek().unwrap().kind == '-' {
|
if toks.peek().unwrap().kind == '-' {
|
||||||
|
@ -123,3 +123,4 @@ error!(
|
|||||||
"#{", "Error: expected \"}\"."
|
"#{", "Error: expected \"}\"."
|
||||||
);
|
);
|
||||||
error!(toplevel_hash, "#", "Error: expected \"{\".");
|
error!(toplevel_hash, "#", "Error: expected \"{\".");
|
||||||
|
error!(toplevel_var_no_colon, "$r", "Error: expected \":\".");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user