Skip to content

Commit

Permalink
Added improvements on the CSS3 user stylesheet parser
Browse files Browse the repository at this point in the history
  • Loading branch information
jaytaph committed Aug 24, 2024
1 parent a9e7869 commit b2788c0
Show file tree
Hide file tree
Showing 52 changed files with 672 additions and 486 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions benches/tree_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn wikipedia_main_page(c: &mut Criterion) {
group.significance_level(0.1).sample_size(500);

let html_file = File::open("tests/data/tree_iterator/wikipedia_main.html").unwrap();
let mut stream = ByteStream::new();
let mut stream = ByteStream::new(None);
let _ = stream.read_from_file(html_file, Some(gosub_shared::byte_stream::Encoding::UTF8));
stream.set_confidence(gosub_shared::byte_stream::Confidence::Certain);

Expand All @@ -41,7 +41,7 @@ fn stackoverflow_home(c: &mut Criterion) {

// using the main page of (english) wikipedia as a rough estimate of traversing a decently sized website
let html_file = File::open("tests/data/tree_iterator/stackoverflow.html").unwrap();
let mut bytestream = ByteStream::new();
let mut bytestream = ByteStream::new(None);
let _ = bytestream.read_from_file(html_file, Some(gosub_shared::byte_stream::Encoding::UTF8));
bytestream.set_confidence(gosub_shared::byte_stream::Confidence::Certain);

Expand Down
5 changes: 2 additions & 3 deletions crates/gosub_bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub mod wrapper;
use gosub_html5::parser::document::{Document, DocumentBuilder};
use gosub_html5::parser::Html5Parser;
use gosub_rendering::render_tree::{Node, NodeType, RenderTree, TreeIterator};
use gosub_shared::byte_stream::{ByteStream, Confidence, Encoding};
use gosub_shared::byte_stream::{ByteStream, Encoding};
use wrapper::node::CNode;

/// Initialize a render tree and return an owning pointer to it.
Expand All @@ -30,9 +30,8 @@ pub unsafe extern "C" fn gosub_rendertree_init(html: *const c_char) -> *mut Rend
return ptr::null_mut();
}
};
let mut stream = ByteStream::new();
let mut stream = ByteStream::new(None);
stream.read_from_str(html_str, Some(Encoding::UTF8));
stream.set_confidence(Confidence::Certain);
stream.close();

let doc = DocumentBuilder::new_document(None);
Expand Down
14 changes: 9 additions & 5 deletions crates/gosub_css3/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::node::Node;
use crate::node::{Node, NodeType};
use crate::parser_config::{Context, ParserConfig};
use crate::tokenizer::Tokenizer;
use gosub_shared::byte_stream::{ByteStream, Encoding, Location};
Expand Down Expand Up @@ -46,16 +46,20 @@ impl<'stream> Css3<'stream> {
pub fn parse(data: &str, config: ParserConfig) -> Result<Node, Error> {
let t_id = timing_start!("css3.parse", config.source.as_deref().unwrap_or(""));

let mut stream = ByteStream::new();
let mut stream = ByteStream::new(None);
stream.read_from_str(data, Some(Encoding::UTF8));
stream.close();

let mut parser = Css3::new(&mut stream);
let ret = parser.parse_internal(config);
let result = parser.parse_internal(config);

timing_stop!(t_id);

ret
match result {
Ok(Some(node)) => Ok(node),
Ok(None) => Ok(Node::new(NodeType::StyleSheet { children: Vec::new() }, Location::default())),
Err(e) => Err(e),
}
}

/// Create a new parser with the given bytestream
Expand All @@ -68,7 +72,7 @@ impl<'stream> Css3<'stream> {
}

/// Actual parser implementation
fn parse_internal(&mut self, config: ParserConfig) -> Result<Node, Error> {
fn parse_internal(&mut self, config: ParserConfig) -> Result<Option<Node>, Error> {
self.config = config;

match self.config.context {
Expand Down
7 changes: 7 additions & 0 deletions crates/gosub_css3/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ pub enum NodeType {
Container {
children: Vec<Node>,
},
Range {
left: Node,
left_comparison: Node,
middle: Node,
right_comparison: Option<Node>,
right: Option<Node>
},
}

/// A node is a single element in the AST
Expand Down
32 changes: 22 additions & 10 deletions crates/gosub_css3/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl Css3<'_> {
if t.token_type != token_type {
return Err(Error::new(
format!("Expected {:?}, got {:?}", token_type, t),
self.tokenizer.current_location().clone(),
self.tokenizer.current_location(),
));
}

Expand All @@ -44,7 +44,7 @@ impl Css3<'_> {
TokenType::Function(name) => Ok(name),
_ => Err(Error::new(
format!("Expected function, got {:?}", t),
self.tokenizer.current_location().clone(),
self.tokenizer.current_location(),
)),
}
}
Expand All @@ -55,7 +55,7 @@ impl Css3<'_> {
TokenType::Number(value) => Ok(value),
_ => Err(Error::new(
format!("Expected number, got {:?}", t),
self.tokenizer.current_location().clone(),
self.tokenizer.current_location(),
)),
}
}
Expand All @@ -66,7 +66,7 @@ impl Css3<'_> {
TokenType::Delim(c) => Ok(c),
_ => Err(Error::new(
format!("Expected delimiter, got {:?}", t),
self.tokenizer.current_location().clone(),
self.tokenizer.current_location(),
)),
}
}
Expand All @@ -77,7 +77,7 @@ impl Css3<'_> {
TokenType::QuotedString(s) => Ok(s),
_ => Err(Error::new(
format!("Expected string, got {:?}", t),
self.tokenizer.current_location().clone(),
self.tokenizer.current_location(),
)),
}
}
Expand All @@ -88,7 +88,7 @@ impl Css3<'_> {
TokenType::Delim(c) if c == delimiter => Ok(c),
_ => Err(Error::new(
format!("Expected delimiter '{}', got {:?}", delimiter, t),
self.tokenizer.current_location().clone(),
self.tokenizer.current_location(),
)),
}
}
Expand All @@ -97,7 +97,7 @@ impl Css3<'_> {
loop {
let t = self.tokenizer.consume();
match t.token_type {
TokenType::Whitespace | TokenType::Comment(_) => {
TokenType::Whitespace(_) | TokenType::Comment(_) => {
// just eat it
}
_ => {
Expand All @@ -114,7 +114,7 @@ impl Css3<'_> {
TokenType::Ident(s) if s.eq_ignore_ascii_case(ident) => Ok(s),
_ => Err(Error::new(
format!("Expected ident, got {:?}", t),
self.tokenizer.current_location().clone(),
self.tokenizer.current_location(),
)),
}
}
Expand All @@ -125,18 +125,30 @@ impl Css3<'_> {
TokenType::Ident(s) if s == ident => Ok(s),
_ => Err(Error::new(
format!("Expected ident, got {:?}", t),
self.tokenizer.current_location().clone(),
self.tokenizer.current_location(),
)),
}
}

pub fn consume_any_ident(&mut self) -> Result<String, Error> {
let t = self.tokenizer.consume();


match t.token_type {
TokenType::Delim('.') => {
let t = self.tokenizer.consume();
match t.token_type {
TokenType::Ident(s) => Ok(format!(".{}", s)),
_ => Err(Error::new(
format!("Expected ident, got {:?}", t),
self.tokenizer.current_location(),
)),
}
}
TokenType::Ident(s) => Ok(s),
_ => Err(Error::new(
format!("Expected ident, got {:?}", t),
self.tokenizer.current_location().clone(),
self.tokenizer.current_location(),
)),
}
}
Expand Down
14 changes: 7 additions & 7 deletions crates/gosub_css3/src/parser/anplusb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl Css3<'_> {
if unit.chars().nth(0).unwrap().to_lowercase().to_string() != "n" {
return Err(Error::new(
format!("Expected n, found {}", unit).to_string(),
self.tokenizer.current_location().clone(),
self.tokenizer.current_location(),
));
}
Ok(if unit.len() == 1 {
Expand Down Expand Up @@ -43,7 +43,7 @@ impl Css3<'_> {
if !allow_sign {
return Err(Error::new(
format!("Unexpected sign {}", sign).to_string(),
self.tokenizer.current_location().clone(),
self.tokenizer.current_location(),
));
}
pos += 1;
Expand All @@ -68,7 +68,7 @@ impl Css3<'_> {
if nval != c {
return Err(Error::new(
format!("Expected {}", c).to_string(),
self.tokenizer.current_location().clone(),
self.tokenizer.current_location(),
));
}

Expand Down Expand Up @@ -113,7 +113,7 @@ impl Css3<'_> {
self.tokenizer.lookahead(0).token_type
)
.to_string(),
self.tokenizer.current_location().clone(),
self.tokenizer.current_location(),
));
}
};
Expand Down Expand Up @@ -199,7 +199,7 @@ impl Css3<'_> {
pub fn parse_anplusb(&mut self) -> Result<Node, Error> {
log::trace!("parse_anplusb");

let loc = self.tokenizer.current_location().clone();
let loc = self.tokenizer.current_location();

let mut a = String::from("1");
let mut b;
Expand Down Expand Up @@ -230,7 +230,7 @@ impl Css3<'_> {
self.tokenizer.reconsume();
return Err(Error::new(
"Expected anplusb".to_string(),
self.tokenizer.current_location().clone(),
self.tokenizer.current_location(),
));
}
}
Expand All @@ -254,7 +254,7 @@ mod test {

macro_rules! test {
($func:ident, $input:expr, $expected:expr) => {
let mut stream = ByteStream::new();
let mut stream = ByteStream::new(None);
stream.read_from_str($input, Some(Encoding::UTF8));
stream.close();

Expand Down
20 changes: 19 additions & 1 deletion crates/gosub_css3/src/parser/at_rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,27 @@ impl Css3<'_> {
Ok(node)
}

pub fn parse_at_rule(&mut self, is_declaration: bool) -> Result<Node, Error> {
// Either the at_rule parsing succeeds as a whole, or not. When not a valid at_rule is found, we
// return None if the config.ignore_errors is set to true, otherwise this will return an Err
// and is handled by the caller
pub fn parse_at_rule(&mut self, is_declaration: bool) -> Result<Option<Node>, Error> {
log::trace!("parse_at_rule");

let result = self.parse_at_rule_internal(is_declaration);
if result.is_err() && self.config.ignore_errors {
self.parse_until_rule_end();
log::warn!("Ignoring error in parse_at_rule: {:?}", result);
return Ok(None);
}

if let Ok(at_rule_node) = result {
return Ok(Some(at_rule_node));
}

Ok(None)
}

fn parse_at_rule_internal(&mut self, is_declaration: bool) -> Result<Node, Error> {
let name;

let t = self.consume_any()?;
Expand Down
2 changes: 1 addition & 1 deletion crates/gosub_css3/src/parser/at_rule/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ impl Css3<'_> {

let mut children = Vec::new();

let loc = self.tokenizer.current_location().clone();
let loc = self.tokenizer.current_location();

let t = self.consume_any()?;
match t.token_type {
Expand Down
2 changes: 1 addition & 1 deletion crates/gosub_css3/src/parser/at_rule/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ impl Css3<'_> {
pub fn parse_at_rule_layer_prelude(&mut self) -> Result<Node, Error> {
log::trace!("parse_at_rule_layer_prelude");

let loc = self.tokenizer.current_location().clone();
let loc = self.tokenizer.current_location();

self.consume_whitespace_comments();

Expand Down
Loading

0 comments on commit b2788c0

Please sign in to comment.