From 01ea7da5e755559073ee29b139fd1bd19a99090e Mon Sep 17 00:00:00 2001 From: CGQAQ Date: Wed, 24 Nov 2021 07:13:52 +0800 Subject: [PATCH] parser structure code with some todos Signed-off-by: CGQAQ --- src/lib.rs | 2 + src/parser.rs | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/util.rs | 18 +++++++ 3 files changed, 165 insertions(+) create mode 100644 src/parser.rs create mode 100644 src/util.rs diff --git a/src/lib.rs b/src/lib.rs index 31b3a2a..2972330 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,7 @@ +pub mod parser; pub mod tokenizer; pub mod types; +mod util; #[cfg(test)] mod tests { diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..c64707d --- /dev/null +++ b/src/parser.rs @@ -0,0 +1,145 @@ +use crate::tokenizer::{Token, TokenType, Tokenizer}; +use crate::util; + +pub struct Parser<'a> { + css: &'a str, + + // options + lossy: bool, + safe: bool, // always false + + tokens: Vec, + + position: usize, +} + +// TODO: use this instead +#[allow(dead_code)] +pub struct ParserOptions { + lossy: bool, + safe: Option, // always false +} + +pub struct Parse {} + +pub struct Node {} + +impl<'a> Parser<'a> { + pub fn new(css: &'a str, lossy: bool) -> Parser { + Parser { + // input + css, + + // options + lossy, + safe: false, + + // tokens generated from input + tokens: Tokenizer::new(css, None).tokenize(), + position: 0, + } + } + + pub fn parse(mut self) -> Parse { + while self.position < self.tokens.len() { + self.parse_token(); + } + + todo!("constructing Parse"); + } + + fn parse_token(&mut self /*throw on missing parenthesis*/) -> Node { + let current_token = &self.tokens[self.position]; + match current_token.ty { + TokenType::Space => self.parse_space(), + TokenType::Comment => self.parse_comment(), + TokenType::OpenParenthesis => self.parse_parenthesis(), + TokenType::CloseParenthesis => { + // if throw on missing parenthesis; then + util::expected(vec!["opening parenthesis"], current_token.pos.0, None); + } + TokenType::OpenSquare => self.parse_attribute(), + + ty @ _ + if ty == TokenType::Dollar + || ty == TokenType::Caret + || ty == TokenType::Equals + || ty == TokenType::Word => + { + self.parse_word(); + } + + TokenType::Colon => { + self.parse_pseudo(); + } + TokenType::Comma => { + self.parse_comma(); + } + TokenType::Asterisk => { + self.parse_universal(); + } + TokenType::Ampersand => { + self.parse_ampersand(); + } + + ty @ _ if ty == TokenType::Slash || ty == TokenType::Combinator => { + self.parse_combinator(); + } + TokenType::SingleQuote => { + self.parse_string(); + } + TokenType::CloseSquare => {} + TokenType::Semicolon => {} + + // TODO(CGQAQ): Why these will panic? + TokenType::At => {} + TokenType::Tilde => {} + TokenType::Plus => {} + TokenType::Pipe => {} + TokenType::Greater => {} + TokenType::DoubleQuote => {} + TokenType::Bang => {} + TokenType::Backslash => {} + TokenType::Cr => {} + TokenType::Feed => {} + TokenType::Newline => {} + TokenType::Tab => {} + } + + todo!("Maybe not returning a Node?") + } + + fn parse_space() { + todo!("impl parse_space") + } + fn parse_comment() { + todo!("impl parse_comment") + } + fn parse_parenthesis() { + todo!("impl parse_parenthesis") + } + fn parse_attribute() { + todo!("impl parse_attribute") + } + fn parse_word() { + todo!("impl parse_word") + } + fn parse_pseudo() { + todo!("impl parse_pseudo") + } + fn parse_comma() { + todo!("impl parse_comma") + } + fn parse_universal() { + todo!("impl parse_universal") + } + fn parse_nesting() { + todo!("impl parse_nesting") + } + fn parse_combinator() { + todo!("impl parse_combinator") + } + fn parse_string() { + todo!("impl parse_string") + } +} diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..cdde5fc --- /dev/null +++ b/src/util.rs @@ -0,0 +1,18 @@ +pub fn expected(mut description: Vec<&str>, index: usize, found: Option<&str>) { + let last = description.pop(); + let description = format!("{} or {}", description.join(", "), last.unwrap_or("")); + let an = if ['a', 'e', 'i', 'o', 'u'].contains(description[0]) { + "an" + } else { + "a" + }; + + if let Some(founded) = found { + panic!( + "Expected {} {}, found \"{}\" instead. At #{}", + an, description, founded, index + ); + } + + panic!("Expected {} {}. At #{}", an, description, index); +}