Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Rethink parsing #785

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
75d6992
rethink parsing
Aiving Jul 13, 2024
852d3fd
change parsing api
Aiving Jul 15, 2024
b83476d
Merge branch 'main' into feat/rethink-parsing
Aiving Jul 15, 2024
3abffe9
Merge remote-tracking branch 'refs/remotes/origin/feat/rethink-parsin…
Aiving Jul 15, 2024
bf5cd55
feat: add `try_as_u8` function for `Token`
Aiving Jul 15, 2024
c953a5b
reduced number of modifications for PR files diff
Aiving Jul 15, 2024
f3a86be
Merge branch 'main' into feat/rethink-parsing
Aiving Jul 16, 2024
17bee71
fix rgba color parsing
Aiving Jul 16, 2024
33f151d
Merge branch 'feat/rethink-parsing' of https://github.com/Aiving/frey…
Aiving Jul 16, 2024
ad66c4a
Merge branch 'main' into feat/rethink-parsing
Aiving Jul 16, 2024
fd37282
Update crates/state/src/values/font.rs
Aiving Jul 16, 2024
08818aa
fix unicode character parsing
Aiving Jul 17, 2024
0ee85ba
change text-overflow parsing
Aiving Jul 17, 2024
168d95f
Merge branch 'main' into feat/rethink-parsing
Aiving Jul 17, 2024
017668c
Merge branch 'main' into feat/rethink-parsing
Aiving Aug 4, 2024
fc751ee
fixes
Aiving Aug 4, 2024
3dafc96
more fixes
Aiving Aug 4, 2024
424393d
Merge branch 'main' into feat/rethink-parsing
Aiving Aug 4, 2024
83a0276
Merge branch 'main' into feat/rethink-parsing
marc2332 Aug 18, 2024
1399586
Merge branch 'main' into feat/rethink-parsing
Aiving Sep 29, 2024
b50b78d
yoo
Aiving Sep 29, 2024
b88b19b
fix corner_radius.rs
Aiving Sep 29, 2024
3babf8c
Update style.rs
Aiving Sep 29, 2024
c3a630c
Update border.rs
Aiving Sep 29, 2024
32ec692
Update color.rs
Aiving Sep 29, 2024
a1dd2cb
add parse error messages
Aiving Sep 29, 2024
bee0ee5
fix rgb(a) parsing
Aiving Sep 29, 2024
873306f
fix text shadow parsing
Aiving Sep 29, 2024
6fed2d5
maybe fixed text shadow parsing
Aiving Sep 29, 2024
31aec74
fix hsl color parsing
Aiving Sep 29, 2024
49cf1ca
fix corner radius parsing
Aiving Sep 29, 2024
d6f3396
forgor to fmt
Aiving Sep 29, 2024
315ad4d
fix gradients angle parsing
Aiving Sep 29, 2024
9836be6
Merge branch 'main' into feat/rethink-parsing
Aiving Sep 29, 2024
c32dd2c
Merge branch 'main' into feat/rethink-parsing
Aiving Oct 16, 2024
e7caef3
implement new parse for text height
Aiving Oct 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 19 additions & 45 deletions crates/state/src/font_style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ use torin::torin::Torin;

use crate::{
CustomAttributeValues,
ExtSplit,
Parse,
ParseAttribute,
ParseError,
TextOverflow,
Token,
};

#[derive(Debug, Clone, PartialEq, Component)]
Expand Down Expand Up @@ -105,7 +106,7 @@ impl ParseAttribute for FontStyleState {
fn parse_attribute(
&mut self,
attr: freya_native_core::prelude::OwnedAttributeView<CustomAttributeValues>,
) -> Result<(), crate::ParseError> {
) -> Result<(), ParseError> {
match attr.attribute {
AttributeName::Color => {
if let Some(value) = attr.value.as_text() {
Expand All @@ -118,15 +119,13 @@ impl ParseAttribute for FontStyleState {
}
AttributeName::TextShadow => {
if let Some(value) = attr.value.as_text() {
self.text_shadows = value
.split_excluding_group(',', '(', ')')
.map(|chunk| TextShadow::parse(chunk).unwrap_or_default())
.collect();
self.text_shadows = TextShadow::parse_with_separator(value, &Token::Comma)?;
}
}
AttributeName::FontFamily => {
if let Some(value) = attr.value.as_text() {
let families = value.split(',');

self.font_family = families
.into_iter()
.map(|f| f.trim().to_string())
Expand All @@ -149,84 +148,59 @@ impl ParseAttribute for FontStyleState {
}
AttributeName::TextAlign => {
if let Some(value) = attr.value.as_text() {
if let Ok(text_align) = TextAlign::parse(value) {
self.text_align = text_align;
}
self.text_align = TextAlign::parse(value)?;
}
}
AttributeName::MaxLines => {
if let Some(value) = attr.value.as_text() {
if let Ok(max_lines) = value.parse() {
self.max_lines = Some(max_lines);
}
self.max_lines = Some(value.parse().map_err(|_| ParseError)?);
}
}
AttributeName::TextOverflow => {
let value = attr.value.as_text();
if let Some(value) = value {
if let Ok(text_overflow) = TextOverflow::parse(value) {
self.text_overflow = text_overflow;
}
if let Some(value) = attr.value.as_text() {
self.text_overflow = TextOverflow::parse(value)?;
}
}
AttributeName::FontStyle => {
if let Some(value) = attr.value.as_text() {
if let Ok(font_slant) = Slant::parse(value) {
self.font_slant = font_slant;
}
self.font_slant = Slant::parse(value)?;
}
}
AttributeName::FontWeight => {
if let Some(value) = attr.value.as_text() {
if let Ok(font_weight) = Weight::parse(value) {
self.font_weight = font_weight;
}
self.font_weight = Weight::parse(value)?;
}
}
AttributeName::FontWidth => {
if let Some(value) = attr.value.as_text() {
if let Ok(font_width) = Width::parse(value) {
self.font_width = font_width;
}
self.font_width = Width::parse(value)?;
}
}
AttributeName::Decoration => {
if let Some(value) = attr.value.as_text() {
if let Ok(decoration) = TextDecoration::parse(value) {
self.decoration.ty = decoration;
}
self.decoration.ty = TextDecoration::parse(value)?;
}
}
AttributeName::DecorationStyle => {
if let Some(value) = attr.value.as_text() {
if let Ok(style) = TextDecorationStyle::parse(value) {
self.decoration.style = style;
}
self.decoration.style = TextDecorationStyle::parse(value)?;
}
}
AttributeName::DecorationColor => {
if let Some(value) = attr.value.as_text() {
if let Ok(new_decoration_color) = Color::parse(value) {
self.decoration.color = new_decoration_color;
}
self.decoration.color = Color::parse(value)?;
} else {
self.decoration.color = self.color;
}
}
AttributeName::WordSpacing => {
let value = attr.value.as_text();
if let Some(value) = value {
if let Ok(word_spacing) = value.parse() {
self.word_spacing = word_spacing;
}
if let Some(value) = attr.value.as_text() {
self.word_spacing = value.parse().map_err(|_| ParseError)?;
}
}
AttributeName::LetterSpacing => {
let value = attr.value.as_text();
if let Some(value) = value {
if let Ok(letter_spacing) = value.parse() {
self.letter_spacing = letter_spacing;
}
if let Some(value) = attr.value.as_text() {
self.letter_spacing = value.parse().map_err(|_| ParseError)?;
}
}
_ => {}
Expand Down
3 changes: 2 additions & 1 deletion crates/state/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ impl ParseAttribute for LayoutState {
if let Some(value) = attr.value.as_text() {
self.direction = match value {
"horizontal" => DirectionMode::Horizontal,
_ => DirectionMode::Vertical,
"vertical" => DirectionMode::Vertical,
_ => return Err(ParseError),
}
}
}
Expand Down
186 changes: 186 additions & 0 deletions crates/state/src/lexing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
use std::iter;

#[derive(Debug, PartialEq, Clone)]
pub enum Token {
Ident(String),
Float(f32),
Integer(i64),
ParenOpen,
ParenClose,
Minus,
Plus,
Slash,
Star,
Pound,
Percent,
Comma,
Unknown(char),
}

impl Token {
pub fn ident<T: Into<String>>(value: T) -> Self {
Self::Ident(value.into())
}

pub fn is_ident(&self) -> bool {
matches!(self, Token::Ident(_))
}

pub fn is_f32(&self) -> bool {
matches!(self, Token::Float(_))
}

pub fn is_i64(&self) -> bool {
matches!(self, Token::Integer(_))
}

pub fn is_i64_or_f32(&self) -> bool {
matches!(self, Token::Integer(_) | Token::Float(_))
}

pub fn into_string(self) -> String {
if let Token::Ident(value) = self {
value
} else {
unreachable!()
}
}

pub fn into_f32(self) -> f32 {
if let Token::Float(value) = self {
value
} else if let Token::Integer(value) = self {
value as f32
} else {
unreachable!()
}
}

pub fn into_i64(self) -> i64 {
if let Token::Integer(value) = self {
value
} else {
unreachable!()
}
}

pub fn as_str(&self) -> &str {
if let Token::Ident(value) = self {
value.as_str()
} else {
unreachable!()
}
}

pub fn try_as_str(&self) -> Option<&str> {
if let Token::Ident(value) = self {
Some(value.as_str())
} else {
None
}
}

pub fn try_as_f32(&self) -> Option<f32> {
if let Token::Float(value) = self {
Some(*value)
} else if let Token::Integer(value) = self {
Some(*value as f32)
} else {
None
}
}

pub fn try_as_i64(&self) -> Option<i64> {
if let Token::Integer(value) = self {
Some(*value)
} else {
None
}
}

pub fn try_as_u8(&self) -> Option<u8> {
if let Token::Integer(value) = self {
u8::try_from(*value).ok()
} else {
None
}
}
}

pub struct Lexer;

impl Lexer {
pub fn parse<T: AsRef<str>>(data: T) -> Vec<Token> {
let mut tokens = vec![];
let mut chars = data.as_ref().chars().peekable();

while let Some(character) = chars.next() {
match character {
' ' => continue,
'A'..='z' => {
tokens.push(Token::Ident(
iter::once(character)
.chain(iter::from_fn(|| {
chars
.by_ref()
.next_if(|s| s.is_ascii_alphanumeric() || s == &'-')
}))
.collect::<String>()
.parse()
.unwrap(),
));
}
'0'..='9' => {
let value = iter::once(character)
.chain(iter::from_fn(|| {
chars.by_ref().next_if(|s| s.is_ascii_digit() || s == &'.')
}))
.collect::<String>();

if value.contains('.') {
tokens.push(Token::Float(value.parse().unwrap()));
} else {
tokens.push(Token::Integer(value.parse().unwrap()));
}
}
'(' => tokens.push(Token::ParenOpen),
')' => tokens.push(Token::ParenClose),
'+' => tokens.push(Token::Plus),
'-' => {
if chars.peek().is_some_and(char::is_ascii_digit) {
let value = iter::once(character)
.chain(iter::from_fn(|| {
chars.by_ref().next_if(|s| s.is_ascii_digit() || s == &'.')
}))
.collect::<String>();

if value.contains('.') {
tokens.push(Token::Float(value.parse().unwrap()));
} else {
tokens.push(Token::Integer(value.parse().unwrap()));
}
} else {
tokens.push(Token::Minus);
}
}
'*' => tokens.push(Token::Star),
'/' => tokens.push(Token::Slash),
'#' => {
tokens.push(Token::Pound);

if chars.peek().is_some_and(char::is_ascii_alphanumeric) {
tokens.push(Token::Ident(
iter::from_fn(|| chars.by_ref().next_if(char::is_ascii_alphanumeric))
.collect::<String>(),
));
}
}
'%' => tokens.push(Token::Percent),
',' => tokens.push(Token::Comma),
character => tokens.push(Token::Unknown(character)),
}
}

tokens
}
}
2 changes: 2 additions & 0 deletions crates/state/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod custom_attributes;
mod font_style;
mod layer;
mod layout;
mod lexing;
mod parsing;
mod references;
mod style;
Expand All @@ -17,6 +18,7 @@ pub use custom_attributes::*;
pub use font_style::*;
pub use layer::*;
pub use layout::*;
pub use lexing::*;
pub use parsing::*;
pub use references::*;
pub use style::*;
Expand Down
Loading