diff --git a/Cargo.lock b/Cargo.lock index 60d6c18..e19323b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,7 +67,7 @@ checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "as3_parser" -version = "0.5.29" +version = "1.0.0" dependencies = [ "bitflags", "by_address", diff --git a/crates/parser/Cargo.toml b/crates/parser/Cargo.toml index de464ae..bf5913a 100644 --- a/crates/parser/Cargo.toml +++ b/crates/parser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "as3_parser" -version = "0.5.29" +version = "1.0.0" edition = "2021" authors = ["hydroper "] repository = "https://github.com/hydroper/as3parser" diff --git a/crates/parser/diagnostics/diagnostic_kind.rs b/crates/parser/diagnostics/diagnostic_kind.rs index a56b218..baac4cb 100644 --- a/crates/parser/diagnostics/diagnostic_kind.rs +++ b/crates/parser/diagnostics/diagnostic_kind.rs @@ -50,8 +50,8 @@ pub enum DiagnosticKind { RedefiningXmlAttribute = 1070, InvalidXmlPi = 1071, XmlPiUnknownAttribute = 1072, - XmlPiVersionMustBe10 = 1073, - XmlPiEncodingMustBeUtf8 = 1074, + XmlPiVersion = 1073, + XmlPiEncoding = 1074, XmlMustConsistOfExactly1Element = 1075, XmlNameAtMostOneColon = 1076, UnexpectedCharacter = 1077, diff --git a/crates/parser/diagnostics/diagnostics_english_resources.rs b/crates/parser/diagnostics/diagnostics_english_resources.rs index ae24a31..b7eccc2 100644 --- a/crates/parser/diagnostics/diagnostics_english_resources.rs +++ b/crates/parser/diagnostics/diagnostics_english_resources.rs @@ -53,8 +53,8 @@ lazy_static! { DiagnosticKind::RedefiningXmlAttribute.id() => "Redefining attribute: '{1}'.".into(), DiagnosticKind::InvalidXmlPi.id() => "Invalid processing instruction.".into(), DiagnosticKind::XmlPiUnknownAttribute.id() => "Unknown attribute at processing instruction: '{1}'.".into(), - DiagnosticKind::XmlPiVersionMustBe10.id() => "XML version must be '1.0'.".into(), - DiagnosticKind::XmlPiEncodingMustBeUtf8.id() => "XML encoding must be 'utf-8'.".into(), + DiagnosticKind::XmlPiVersion.id() => "XML version must be '1.0'.".into(), + DiagnosticKind::XmlPiEncoding.id() => "XML encoding must be either 'utf-8' or 'utf-16'.".into(), DiagnosticKind::XmlMustConsistOfExactly1Element.id() => "Document must consist of exactly one element.".into(), DiagnosticKind::XmlNameAtMostOneColon.id() => "XML name may have at most one colon.".into(), DiagnosticKind::UnexpectedCharacter.id() => "Unexpected character. '{1}' is not allowed here".into(), diff --git a/crates/parser/parser/css_parser.rs b/crates/parser/parser/css_parser.rs index f0af633..d58394a 100644 --- a/crates/parser/parser/css_parser.rs +++ b/crates/parser/parser/css_parser.rs @@ -272,15 +272,17 @@ impl<'input> CssParser<'input> { } let mut rules: Vec> = vec![]; self.expect(Token::BlockOpen); - while !(self.eof() || self.peek(Token::BlockClose)) { - if let Some(rule) = self.parse_opt_rule() { - rules.push(Rc::new(rule)); - } else { - self.add_syntax_error(&self.token.1, DiagnosticKind::Unexpected, diagarg![self.token.0.clone()]); - self.next(); + if !self.expecting_token_error { + while !(self.eof() || self.peek(Token::BlockClose)) { + if let Some(rule) = self.parse_opt_rule() { + rules.push(Rc::new(rule)); + } else { + self.add_syntax_error(&self.token.1, DiagnosticKind::Unexpected, diagarg![self.token.0.clone()]); + self.next(); + } } + self.expect(Token::BlockClose); } - self.expect(Token::BlockClose); Rc::new(CssDirective::MediaQuery(CssMediaQuery { location: self.pop_location(), conditions, @@ -293,14 +295,16 @@ impl<'input> CssParser<'input> { self.next(); let mut properties: Vec> = vec![]; self.expect(Token::BlockOpen); - self.consume(Token::CssSemicolons); - while !(self.eof() || self.peek(Token::BlockClose)) { - properties.push(self.parse_property()); - if !self.consume(Token::CssSemicolons) { - break; + if !self.expecting_token_error { + self.consume(Token::CssSemicolons); + while !(self.eof() || self.peek(Token::BlockClose)) { + properties.push(self.parse_property()); + if !self.consume(Token::CssSemicolons) { + break; + } } + self.expect(Token::BlockClose); } - self.expect(Token::BlockClose); Rc::new(CssDirective::FontFace(CssFontFace { location: self.pop_location(), properties, @@ -376,14 +380,16 @@ impl<'input> CssParser<'input> { } let mut properties: Vec> = vec![]; self.expect(Token::BlockOpen); - self.consume(Token::CssSemicolons); - while !(self.eof() || self.peek(Token::BlockClose)) { - properties.push(self.parse_property()); - if !self.consume(Token::CssSemicolons) { - break; + if !self.expecting_token_error { + self.consume(Token::CssSemicolons); + while !(self.eof() || self.peek(Token::BlockClose)) { + properties.push(self.parse_property()); + if !self.consume(Token::CssSemicolons) { + break; + } } + self.expect(Token::BlockClose); } - self.expect(Token::BlockClose); self.push_location(&selectors[0].location()); Some(CssRule { location: self.pop_location(), @@ -631,6 +637,10 @@ impl<'input> CssParser<'input> { entries, }))); } else { + if self.peek(Token::ParenOpen) { + self.add_syntax_error(&self.token_location(), DiagnosticKind::Unexpected, diagarg![self.token.0.clone()]); + self.parse_arguments().unwrap(); + } base = Some(Rc::new(CssPropertyValue::Identifier(CssIdentifierPropertyValue { location: self.pop_location(), value: id.0, diff --git a/crates/parser/parser/parser.rs b/crates/parser/parser/parser.rs index 4246e82..c51bcfa 100644 --- a/crates/parser/parser/parser.rs +++ b/crates/parser/parser/parser.rs @@ -4834,7 +4834,7 @@ impl<'input> Parser<'input> { } /// Parses MXMLElement starting from its XMLTagContent. - fn parse_mxml_element(&mut self, start: Location, namespace: &Rc) -> MxmlElement { + fn parse_mxml_element(&mut self, start: Location, namespace: &Rc, encoding: &mut String) -> MxmlElement { self.push_location(&start); let namespace = Rc::new(MxmlNamespace::new(Some(namespace))); let name = self.parse_xml_name(); @@ -4876,7 +4876,7 @@ impl<'input> Parser<'input> { if !is_empty { self.expect_and_ie_xml_content(Token::Gt); - content = Some(self.parse_mxml_content(false, &namespace)); + content = Some(self.parse_mxml_content(false, &namespace, encoding)); self.non_greedy_expect_and_ie_xml_tag(Token::XmlLtSlash); let name = self.parse_xml_name(); closing_name = Some(self.process_mxml_tag_name(name, &namespace)); @@ -5028,7 +5028,7 @@ impl<'input> Parser<'input> { } /// Parses XMLContent until either the `) -> Vec> { + fn parse_mxml_content(&mut self, until_eof: bool, namespace: &Rc, encoding: &mut String) -> Vec> { let mut content = vec![]; while if until_eof { self.tokenizer.characters().has_remaining() } else { !self.peek(Token::XmlLtSlash) } { if let Token::XmlMarkup(markup) = self.token.0.clone() { @@ -5058,17 +5058,17 @@ impl<'input> Parser<'input> { let i = location.first_offset() + 2 + name.len(); let j = decrease_last_offset(i, location.last_offset(), 2); - let errors = process_xml_pi(self.compilation_unit(), (i, j), &name); + let errors = process_xml_pi(self.compilation_unit(), (i, j), &name, encoding); for error in errors.iter() { match error { XmlPiError::UnknownAttribute(name) => { self.add_syntax_error(&location, DiagnosticKind::XmlPiUnknownAttribute, diagarg![name.clone()]); }, - XmlPiError::VersionMustBe10 => { - self.add_syntax_error(&location, DiagnosticKind::XmlPiVersionMustBe10, vec![]); + XmlPiError::Version => { + self.add_syntax_error(&location, DiagnosticKind::XmlPiVersion, vec![]); }, - XmlPiError::EncodingMustBeUtf8 => { - self.add_syntax_error(&location, DiagnosticKind::XmlPiEncodingMustBeUtf8, vec![]); + XmlPiError::Encoding => { + self.add_syntax_error(&location, DiagnosticKind::XmlPiEncoding, vec![]); }, } } @@ -5084,7 +5084,7 @@ impl<'input> Parser<'input> { content.push(Rc::new(MxmlContent::Characters((unescape_xml(&text), location)))); } else if self.consume_and_ie_xml_tag(Token::Lt) { let start = self.token_location(); - let element = self.parse_mxml_element(start, namespace); + let element = self.parse_mxml_element(start, namespace, encoding); content.push(Rc::new(MxmlContent::Element(Rc::new(element)))); } else if !until_eof { self.expect_and_ie_xml_content(Token::XmlLtSlash); @@ -5099,7 +5099,8 @@ impl<'input> Parser<'input> { fn parse_mxml(&mut self) -> Rc { self.mark_location(); let ns = Rc::new(MxmlNamespace::new(None)); - let mut content = self.parse_mxml_content(true, &ns); + let mut encoding = "utf-8".to_owned(); + let mut content = self.parse_mxml_content(true, &ns, &mut encoding); self.filter_mxml_whitespace_out(&mut content); let mut element_count = 0usize; @@ -5124,7 +5125,7 @@ impl<'input> Parser<'input> { Rc::new(Mxml { location, version: XmlVersion::Version10, - encoding: "utf-8".into(), + encoding, content, }) } @@ -5179,7 +5180,7 @@ fn join_asdoc_content(content: &Vec<(String, Location)>) -> (String, Location) { (s, location) } -fn process_xml_pi(cu: &Rc, byte_range: (usize, usize), name: &str) -> Vec { +fn process_xml_pi(cu: &Rc, byte_range: (usize, usize), name: &str, encoding: &mut String) -> Vec { if name != "xml" { return vec![]; } @@ -5199,12 +5200,15 @@ fn process_xml_pi(cu: &Rc, byte_range: (usize, usize), name: &s match name.0.as_ref() { "version" => { if value.0 != "1.0" { - errors.push(XmlPiError::VersionMustBe10); + errors.push(XmlPiError::Version); } }, "encoding" => { - if value.0.to_lowercase() != "utf-8" { - errors.push(XmlPiError::EncodingMustBeUtf8); + let v = value.0.to_lowercase(); + if ["utf-8", "utf-16"].contains(&v.as_str()) { + *encoding = v; + } else { + errors.push(XmlPiError::Encoding); } }, _ => { @@ -5225,8 +5229,8 @@ fn is_flex_documentable_meta_data(name: &str) -> bool { enum XmlPiError { UnknownAttribute(String), - VersionMustBe10, - EncodingMustBeUtf8, + Version, + Encoding, } struct ParserAsDocLine { diff --git a/crates/parser_test/Cargo.toml b/crates/parser_test/Cargo.toml index 0ffe8ff..fc873d6 100644 --- a/crates/parser_test/Cargo.toml +++ b/crates/parser_test/Cargo.toml @@ -17,7 +17,7 @@ path = "main.rs" [dependencies] clap = { version = "4.4.8", features = ["derive"] } file_paths = "1.0.0" -as3_parser = { path = "../parser", version = "0.5" } +as3_parser = { path = "../parser", version = "1.0" } maplit = "1.0.2" serde = { version = "1.0.192", features = ["rc", "derive"] } serde_json = "1.0.108" diff --git a/demo/Cargo.toml b/demo/Cargo.toml index 162625f..4c5f005 100644 --- a/demo/Cargo.toml +++ b/demo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -as3_parser = { path = "../crates/parser", version = "0.5" } +as3_parser = { path = "../crates/parser", version = "1.0" } maplit = "1.0.2" serde = { version = "1.0.192", features = ["rc", "derive"] } serde_json = "1.0.108" diff --git a/demo/dist/as3_parser_demo_bg.wasm b/demo/dist/as3_parser_demo_bg.wasm index 18c1cf5..7bdc039 100644 Binary files a/demo/dist/as3_parser_demo_bg.wasm and b/demo/dist/as3_parser_demo_bg.wasm differ diff --git a/docs/getting-started.md b/docs/getting-started.md index 10bbc3b..d84514e 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -10,7 +10,7 @@ Install `as3_parser` in your Cargo project with `cargo add as3_parser`, or add t ```toml [dependencies] -as3_parser = "0.5" +as3_parser = "1.0" ``` Parse programs or expressions through the `ParserFacade` structure of the `as3_parser` crate: diff --git a/examples/asdoc/Cargo.toml b/examples/asdoc/Cargo.toml index 203a1d3..8472705 100644 --- a/examples/asdoc/Cargo.toml +++ b/examples/asdoc/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -as3_parser = { path = "../../crates/parser", version = "0.5" } +as3_parser = { path = "../../crates/parser", version = "1.0" } [[example]] name = "asdoc"