Initial implementation of @debug and @warn
This commit is contained in:
parent
42d0fa657f
commit
fd423ce300
@ -314,7 +314,6 @@ impl fmt::UpperHex for Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Display for Color {
|
impl Display for Color {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{:X}", self)
|
write!(f, "{:X}", self)
|
||||||
@ -477,4 +476,4 @@ impl TryFrom<&str> for Color {
|
|||||||
_ => Err("invalid color"),
|
_ => Err("invalid color"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
src/lexer.rs
12
src/lexer.rs
@ -321,7 +321,11 @@ impl<'a> Lexer<'a> {
|
|||||||
.next()
|
.next()
|
||||||
.expect("this is impossible because we have already peeked");
|
.expect("this is impossible because we have already peeked");
|
||||||
self.pos.next_char();
|
self.pos.next_char();
|
||||||
name.push(tok);
|
if tok == '_' {
|
||||||
|
name.push('-');
|
||||||
|
} else {
|
||||||
|
name.push(tok);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TokenKind::Variable(name)
|
TokenKind::Variable(name)
|
||||||
}
|
}
|
||||||
@ -338,7 +342,11 @@ impl<'a> Lexer<'a> {
|
|||||||
.next()
|
.next()
|
||||||
.expect("this is impossible because we have already peeked");
|
.expect("this is impossible because we have already peeked");
|
||||||
self.pos.next_char();
|
self.pos.next_char();
|
||||||
string.push(tok);
|
if tok == '_' {
|
||||||
|
string.push('-');
|
||||||
|
} else {
|
||||||
|
string.push(tok);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(kw) = Keyword::try_from(string.as_ref()) {
|
if let Ok(kw) = Keyword::try_from(string.as_ref()) {
|
||||||
|
133
src/main.rs
133
src/main.rs
@ -25,6 +25,7 @@
|
|||||||
clippy::let_underscore_must_use,
|
clippy::let_underscore_must_use,
|
||||||
clippy::module_name_repetitions
|
clippy::module_name_repetitions
|
||||||
)]
|
)]
|
||||||
|
// todo! handle erroring on styles at the toplevel
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@ -205,7 +206,7 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
| TokenKind::Symbol(Symbol::Period) => rules.extend(
|
| TokenKind::Symbol(Symbol::Period) => rules.extend(
|
||||||
self.eat_rules(&Selector(Vec::new()), &mut self.global_variables.clone()),
|
self.eat_rules(&Selector(Vec::new()), &mut self.global_variables.clone()),
|
||||||
),
|
),
|
||||||
TokenKind::Whitespace(_) | TokenKind::Symbol(_) => {
|
TokenKind::Whitespace(_) => {
|
||||||
self.lexer.next();
|
self.lexer.next();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -232,7 +233,13 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
rules.push(Stmt::MultilineComment(comment));
|
rules.push(Stmt::MultilineComment(comment));
|
||||||
}
|
}
|
||||||
TokenKind::AtRule(_) => self.eat_at_rule(),
|
TokenKind::AtRule(_) => self.eat_at_rule(),
|
||||||
_ => todo!("unexpected toplevel token"),
|
_ => {
|
||||||
|
if let Some(Token { pos, .. }) = self.lexer.next() {
|
||||||
|
self.error(pos.clone(), "unexpected toplevel token")
|
||||||
|
} else {
|
||||||
|
unsafe { std::hint::unreachable_unchecked() }
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Ok(StyleSheet { rules })
|
Ok(StyleSheet { rules })
|
||||||
@ -255,36 +262,31 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
self.error(pos, &message);
|
self.error(pos, &message);
|
||||||
}
|
}
|
||||||
|
AtRule::Warn => {
|
||||||
|
self.devour_whitespace();
|
||||||
|
let message = self
|
||||||
|
.lexer
|
||||||
|
.by_ref()
|
||||||
|
.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon))
|
||||||
|
.map(|x| x.kind.to_string())
|
||||||
|
.collect::<String>();
|
||||||
|
self.warn(pos, &message);
|
||||||
|
}
|
||||||
|
AtRule::Debug => {
|
||||||
|
self.devour_whitespace();
|
||||||
|
let message = self
|
||||||
|
.lexer
|
||||||
|
.by_ref()
|
||||||
|
.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon))
|
||||||
|
.map(|x| x.kind.to_string())
|
||||||
|
.collect::<String>();
|
||||||
|
self.debug(pos, &message);
|
||||||
|
}
|
||||||
_ => todo!("encountered unimplemented at rule"),
|
_ => todo!("encountered unimplemented at rule"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error(&self, pos: Pos, message: &str) -> ! {
|
|
||||||
eprintln!("Error: {}", message);
|
|
||||||
eprintln!(
|
|
||||||
"{} {}:{} scope on line {} at column {}",
|
|
||||||
self.file,
|
|
||||||
pos.line(),
|
|
||||||
pos.column(),
|
|
||||||
pos.line(),
|
|
||||||
pos.column()
|
|
||||||
);
|
|
||||||
let padding = vec![' '; format!("{}", pos.line()).len() + 1]
|
|
||||||
.iter()
|
|
||||||
.collect::<String>();
|
|
||||||
eprintln!("{}|", padding);
|
|
||||||
eprint!("{} | ", pos.line());
|
|
||||||
eprintln!("todo! get line to print as error");
|
|
||||||
eprintln!(
|
|
||||||
"{}| {}^",
|
|
||||||
padding,
|
|
||||||
vec![' '; pos.column() as usize].iter().collect::<String>()
|
|
||||||
);
|
|
||||||
eprintln!("{}|", padding);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eat_variable_value(&mut self) -> Vec<Token> {
|
fn eat_variable_value(&mut self) -> Vec<Token> {
|
||||||
self.devour_whitespace();
|
self.devour_whitespace();
|
||||||
let iter1 = self
|
let iter1 = self
|
||||||
@ -312,6 +314,10 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
iter2
|
iter2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn eat_func_call(&mut self) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
fn eat_rules(
|
fn eat_rules(
|
||||||
&mut self,
|
&mut self,
|
||||||
super_selector: &Selector,
|
super_selector: &Selector,
|
||||||
@ -354,20 +360,28 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
super_selector: &Selector,
|
super_selector: &Selector,
|
||||||
) -> Result<Expr, ()> {
|
) -> Result<Expr, ()> {
|
||||||
let mut values = Vec::with_capacity(5);
|
let mut values = Vec::with_capacity(5);
|
||||||
while let Some(tok) = self.lexer.next() {
|
while let Some(tok) = self.lexer.peek() {
|
||||||
match tok.kind {
|
match &tok.kind {
|
||||||
TokenKind::Symbol(Symbol::SemiColon) | TokenKind::Symbol(Symbol::CloseBrace) => {
|
TokenKind::Symbol(Symbol::SemiColon) | TokenKind::Symbol(Symbol::CloseBrace) => {
|
||||||
|
self.lexer.next();
|
||||||
self.devour_whitespace();
|
self.devour_whitespace();
|
||||||
return Ok(Expr::Style(Style::from_tokens(&values, vars)?));
|
return Ok(Expr::Style(Style::from_tokens(&values, vars)?));
|
||||||
}
|
}
|
||||||
TokenKind::Symbol(Symbol::OpenBrace) => {
|
TokenKind::Symbol(Symbol::OpenBrace) => {
|
||||||
|
self.lexer.next();
|
||||||
self.devour_whitespace();
|
self.devour_whitespace();
|
||||||
return Ok(Expr::Selector(Selector::from_tokens(
|
return Ok(Expr::Selector(Selector::from_tokens(
|
||||||
values.iter().peekable(),
|
values.iter().peekable(),
|
||||||
super_selector,
|
super_selector,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
TokenKind::Variable(name) => {
|
TokenKind::Variable(_) => {
|
||||||
|
let tok = self.lexer.next().unwrap();
|
||||||
|
let name = if let TokenKind::Variable(n) = tok.kind {
|
||||||
|
n
|
||||||
|
} else {
|
||||||
|
unsafe { std::hint::unreachable_unchecked() }
|
||||||
|
};
|
||||||
if let TokenKind::Symbol(Symbol::Colon) = self
|
if let TokenKind::Symbol(Symbol::Colon) = self
|
||||||
.lexer
|
.lexer
|
||||||
.peek()
|
.peek()
|
||||||
@ -384,7 +398,13 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TokenKind::MultilineComment(ref s) => {
|
TokenKind::MultilineComment(_) => {
|
||||||
|
let tok = self.lexer.next().unwrap();
|
||||||
|
let s = if let TokenKind::MultilineComment(s) = &tok.kind {
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
unsafe { std::hint::unreachable_unchecked() }
|
||||||
|
};
|
||||||
self.devour_whitespace();
|
self.devour_whitespace();
|
||||||
if values.is_empty() {
|
if values.is_empty() {
|
||||||
return Ok(Expr::MultilineComment(s.clone()));
|
return Ok(Expr::MultilineComment(s.clone()));
|
||||||
@ -392,7 +412,14 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
values.push(tok.clone())
|
values.push(tok.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => values.push(tok.clone()),
|
TokenKind::AtRule(_) => self.eat_at_rule(),
|
||||||
|
_ => {
|
||||||
|
if let Some(tok) = self.lexer.next() {
|
||||||
|
values.push(tok.clone())
|
||||||
|
} else {
|
||||||
|
unsafe { std::hint::unreachable_unchecked() }
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Err(())
|
Err(())
|
||||||
@ -410,6 +437,48 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Functions that print to stdout or stderr
|
||||||
|
impl<'a> StyleSheetParser<'a> {
|
||||||
|
fn debug(&self, pos: Pos, message: &str) {
|
||||||
|
println!("{}:{} Debug: {}", self.file, pos.line(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn warn(&self, pos: Pos, message: &str) {
|
||||||
|
eprintln!(
|
||||||
|
"Warning: {}\n\t{} {}:{} todo!(scope)",
|
||||||
|
message,
|
||||||
|
self.file,
|
||||||
|
pos.line(),
|
||||||
|
pos.column()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn error(&self, pos: Pos, message: &str) -> ! {
|
||||||
|
eprintln!("Error: {}", message);
|
||||||
|
eprintln!(
|
||||||
|
"{} {}:{} todo!(scope) on line {} at column {}",
|
||||||
|
self.file,
|
||||||
|
pos.line(),
|
||||||
|
pos.column(),
|
||||||
|
pos.line(),
|
||||||
|
pos.column()
|
||||||
|
);
|
||||||
|
let padding = vec![' '; format!("{}", pos.line()).len() + 1]
|
||||||
|
.iter()
|
||||||
|
.collect::<String>();
|
||||||
|
eprintln!("{}|", padding);
|
||||||
|
eprint!("{} | ", pos.line());
|
||||||
|
eprintln!("todo! get line to print as error");
|
||||||
|
eprintln!(
|
||||||
|
"{}| {}^",
|
||||||
|
padding,
|
||||||
|
vec![' '; pos.column() as usize].iter().collect::<String>()
|
||||||
|
);
|
||||||
|
eprintln!("{}|", padding);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> SassResult<()> {
|
fn main() -> SassResult<()> {
|
||||||
let mut stdout = std::io::stdout();
|
let mut stdout = std::io::stdout();
|
||||||
let s = StyleSheet::from_path("input.scss")?;
|
let s = StyleSheet::from_path("input.scss")?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user