Skip to content

Commit ade5930

Browse files
committed
Several updates
1 parent ebc573b commit ade5930

File tree

13 files changed

+191
-92
lines changed

13 files changed

+191
-92
lines changed

crates/parser/Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mxmlextrema-as3parser"
3-
version = "1.3.5"
3+
version = "1.4.0"
44
edition = "2021"
55
authors = ["Matheus Dias de Souza <[email protected]>"]
66
repository = "https://github.com/mxmlextrema/as3parser"
@@ -17,10 +17,10 @@ path = "lib.rs"
1717
[dependencies]
1818
bitflags = { version = "2.4.1", features = ["serde"] }
1919
bytes = "1"
20-
hydroperfox-filepaths = "1.0.0"
20+
realhydroper-path = "1.0.0"
2121
conv = "0.3.3"
2222
htmlentity = "1.3.1"
23-
hydroperfox-lateformat = "1"
23+
realhydroper-lateformat = "1"
2424
maplit = "1.0.2"
2525
num-bigint = "0.4"
2626
num-derive = "0.4.1"
@@ -31,4 +31,4 @@ unicode-general-category = "0.6.0"
3131
by_address = "1.1.0"
3232
serde = { version = "1.0.192", features = ["rc", "derive"] }
3333
serde_json = "1.0.108"
34-
hydroperfox-sourcetext = "1"
34+
realhydroper-sourcetext = "1"

crates/parser/compilation_unit/compilation_unit.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{any::Any, cell::RefMut};
22
use std::fmt::{Debug, Formatter};
33
use crate::ns::*;
4-
use hydroperfox_sourcetext::SourceText;
4+
use realhydroper_sourcetext::SourceText;
55

66
/// `CompilationUnit` identifies an AS3 compilation unit and contains
77
/// a source text.
@@ -249,5 +249,5 @@ impl CompilationUnit {
249249
}
250250

251251
fn canonicalize_path(path: &str) -> String {
252-
std::path::Path::new(path).canonicalize().unwrap_or(std::path::PathBuf::new()).to_string_lossy().into_owned()
252+
std::path::Path::new(path).canonicalize().unwrap_or_else(|_| std::path::PathBuf::new()).to_string_lossy().into_owned()
253253
}

crates/parser/compilation_unit/location.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,16 @@ impl Location {
144144
self.compilation_unit.get_column(self.last_offset)
145145
}
146146

147+
/// Zero based first column offset of the location.
148+
pub fn first_column_offset(&self) -> usize {
149+
self.first_offset - self.compilation_unit.get_line_offset_from_offset(self.first_offset)
150+
}
151+
152+
/// Zero based last column offset of the location.
153+
pub fn last_column_offset(&self) -> usize {
154+
self.last_offset - self.compilation_unit.get_line_offset_from_offset(self.last_offset)
155+
}
156+
147157
pub fn character_count(&self) -> usize {
148158
self.compilation_unit.text()[self.first_offset..self.last_offset].chars().count()
149159
}
@@ -170,7 +180,7 @@ impl Location {
170180
Self::with_offsets(&self.compilation_unit, self.first_offset + ch.index(), self.last_offset)
171181
}
172182

173-
/// Shifts the count of whitespace characters in a text off this location.
183+
/// Shifts the count of first whitespace characters in a text off this location.
174184
pub fn shift_whitespace(&self, text: &str) -> Location {
175185
self.shift_until_eof(count_first_whitespace_characters(text))
176186
}

crates/parser/diagnostics/diagnostic_kind.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub enum DiagnosticKind {
7070
XmlClosingTagNameMustBeEquals = 1090,
7171
UnexpectedIncludeExtension = 1091,
7272
UnallowedExpression = 1092,
73+
ExpectingCssSelector = 1093,
7374
}
7475

7576
impl DiagnosticKind {

crates/parser/diagnostics/diagnostics.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::any::Any;
22

3-
use hydroperfox_filepaths::FlexPath;
3+
use realhydroper_path::FlexPath;
44
use maplit::hashmap;
55
use crate::ns::*;
66

@@ -168,12 +168,12 @@ impl Diagnostic {
168168
string_arguments.insert(i.to_string(), argument.to_string());
169169
i += 1;
170170
}
171-
use hydroperfox_lateformat::LateFormat;
171+
use realhydroper_lateformat::LateFormat;
172172
let Some(msg) = messages.get(&self.id()) else {
173173
let id = self.id();
174174
panic!("Message resource is missing for ID {id}");
175175
};
176-
msg.hydroperfox_lateformat(string_arguments)
176+
msg.realhydroper_lateformat(string_arguments)
177177
}
178178
}
179179

crates/parser/diagnostics/diagnostics_english_resources.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ lazy_static! {
7373
DiagnosticKind::XmlClosingTagNameMustBeEquals.id() => "Closing tag name must be equals '{1}'.".into(),
7474
DiagnosticKind::UnexpectedIncludeExtension.id() => "Unexpected include extension. Expected the file extension '.include.as'.".into(),
7575
DiagnosticKind::UnallowedExpression.id() => "Unallowed expression.".into(),
76+
DiagnosticKind::ExpectingCssSelector.id() => "Expecting selector here.".into(),
7677
// DiagnosticKind::K.id() => ".".into(),
7778
};
7879
}

crates/parser/parser/css_parser.rs

Lines changed: 82 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ impl<'input> CssParser<'input> {
183183
}))
184184
}
185185

186-
fn _create_invalidated_selector(&self, location: &Location) -> Rc<CssSelector> {
186+
fn create_invalidated_selector(&self, location: &Location) -> Rc<CssSelector> {
187187
Rc::new(CssSelector::Invalidated(InvalidatedNode {
188188
location: location.clone(),
189189
}))
@@ -248,6 +248,8 @@ impl<'input> CssParser<'input> {
248248
self.parse_media_query()
249249
} else if self.peek(Token::CssAtFontFace) {
250250
self.parse_font_face()
251+
} else if self.peek(Token::CssAtImport) {
252+
self.parse_import()
251253
} else {
252254
self.add_syntax_error(&self.token.1, DiagnosticKind::ExpectingDirective, diagarg![self.token.0.clone()]);
253255
let d = self.create_invalidated_directive(&self.tokenizer.cursor_location());
@@ -317,6 +319,25 @@ impl<'input> CssParser<'input> {
317319
}))
318320
}
319321

322+
fn parse_import(&mut self) -> Rc<CssDirective> {
323+
self.mark_location();
324+
self.next();
325+
326+
let mut url: Option<String> = None;
327+
if self.consume_keyword("url") {
328+
if let Ok(facade) = self.parse_arguments() {
329+
url = Some(facade.parse_text().0);
330+
}
331+
}
332+
333+
self.expect(Token::Semicolon);
334+
335+
Rc::new(CssDirective::Import(CssImport {
336+
location: self.pop_location(),
337+
url,
338+
}))
339+
}
340+
320341
fn parse_opt_media_query_condition(&mut self) -> Option<Rc<CssMediaQueryCondition>> {
321342
let mut base: Option<Rc<CssMediaQueryCondition>> = None;
322343
if self.peek_keyword("only") {
@@ -407,20 +428,46 @@ impl<'input> CssParser<'input> {
407428
fn parse_opt_selector(&mut self) -> Option<Rc<CssSelector>> {
408429
let mut base = self.parse_opt_base_selector()?;
409430

410-
// Parse descendant combinators
411-
while let Some(right) = self.parse_opt_base_selector() {
412-
self.push_location(&base.location());
413-
base = Rc::new(CssSelector::Combinator(CssCombinatorSelector {
414-
location: self.pop_location(),
415-
left: base,
416-
right,
417-
combinator_type: CssCombinatorType::Descendant,
418-
}));
431+
// Parse combinators
432+
loop {
433+
// CssCombinatorType::Child
434+
if self.consume(Token::Gt) {
435+
self.push_location(&base.location());
436+
let right: Rc<CssSelector> = self.parse_base_selector();
437+
base = Rc::new(CssSelector::Combinator(CssCombinatorSelector {
438+
location: self.pop_location(),
439+
left: base,
440+
right,
441+
combinator_type: CssCombinatorType::Child,
442+
}));
443+
// CssCombinatorType::Descendant
444+
} else if let Some(right) = self.parse_opt_base_selector() {
445+
self.push_location(&base.location());
446+
base = Rc::new(CssSelector::Combinator(CssCombinatorSelector {
447+
location: self.pop_location(),
448+
left: base,
449+
right,
450+
combinator_type: CssCombinatorType::Descendant,
451+
}));
452+
} else {
453+
break;
454+
}
419455
}
420456

421457
Some(base)
422458
}
423459

460+
fn parse_base_selector(&mut self) -> Rc<CssSelector> {
461+
let s = self.tokenizer.cursor_location();
462+
let r = self.parse_opt_base_selector();
463+
if let Some(r) = r {
464+
r
465+
} else {
466+
self.add_syntax_error(&s, DiagnosticKind::ExpectingCssSelector, diagarg![]);
467+
self.create_invalidated_selector(&s)
468+
}
469+
}
470+
424471
fn parse_opt_base_selector(&mut self) -> Option<Rc<CssSelector>> {
425472
self.mark_location();
426473
let mut namespace_prefix: Option<(String, Location)> = None;
@@ -473,7 +520,14 @@ impl<'input> CssParser<'input> {
473520
if self.peek(Token::Colon) {
474521
self.mark_location();
475522
self.next();
476-
if self.consume_keyword("not") {
523+
if self.consume_keyword("nth-child") {
524+
let condition = if let Ok(a) = self.parse_arguments() {
525+
a.parse_nth_child_kind()
526+
} else {
527+
CssNthChildKind::Invalidated
528+
};
529+
return Some(Rc::new(CssSelectorCondition::NthChild((condition, self.pop_location()))));
530+
} else if self.consume_keyword("not") {
477531
let condition = if let Ok(a) = self.parse_arguments() {
478532
a.parse_selector_condition()
479533
} else {
@@ -844,4 +898,21 @@ impl<'input> CssParserFacade<'input> {
844898
parser.expect_eof();
845899
entries
846900
}
901+
902+
pub fn parse_nth_child_kind(&self) -> CssNthChildKind {
903+
let mut parser = self.create_parser();
904+
parser.next();
905+
if parser.consume_keyword("odd") {
906+
return CssNthChildKind::Odd;
907+
}
908+
if parser.consume_keyword("even") {
909+
return CssNthChildKind::Even;
910+
}
911+
if let Token::CssNumber { value, .. } = parser.token.0.clone() {
912+
parser.next();
913+
return CssNthChildKind::Number(value.round().to_u32().unwrap_or(0));
914+
}
915+
parser.expect_eof();
916+
CssNthChildKind::Invalidated
917+
}
847918
}

crates/parser/parser/css_tokenizer.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ impl<'input> CssTokenizer<'input> {
130130
self.characters.skip_count_in_place(10);
131131
return (Token::CssAtFontFace, start.combine_with(self.cursor_location()));
132132
}
133+
// @import
134+
if self.characters.peek_seq(10) == "@import" {
135+
self.characters.skip_count_in_place(10);
136+
return (Token::CssAtImport, start.combine_with(self.cursor_location()));
137+
}
133138
// @media
134139
if self.characters.peek_seq(6) == "@media" {
135140
self.characters.skip_count_in_place(6);

0 commit comments

Comments
 (0)