servo: Merge #16752 - Report more informative CSS errors (from jdm:css-parse-error); r=SimonSapin

This requires https://github.com/servo/rust-cssparser/pull/143 for the final commit. There's no better way to split that work up, unfortunately, and it's extremely easy to bitrot. I would appreciate if we could expedite reviewing this work.

This is the work necessary to enable https://bugzilla.mozilla.org/show_bug.cgi?id=1352669. It makes sense to merge it separately because it's so much effort to keep it up to date with the ongoing Stylo work.

---
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [x] There are tests for these changes

Source-Repo: https://github.com/servo/servo
Source-Revision: 061cb5f48e5c93a5decf39e530aea4a566e97341

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 683cf352b472110df4b28c191e8850763334134d
This commit is contained in:
Josh Matthews 2017-06-09 14:31:48 -07:00
Родитель da2db41a9c
Коммит 1f87774d78
123 изменённых файлов: 2212 добавлений и 1513 удалений

35
servo/Cargo.lock сгенерированный
Просмотреть файл

@ -314,7 +314,7 @@ version = "0.0.1"
dependencies = [
"azure 0.16.0 (git+https://github.com/servo/rust-azure)",
"canvas_traits 0.0.1",
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -329,7 +329,7 @@ dependencies = [
name = "canvas_traits"
version = "0.0.1"
dependencies = [
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -567,14 +567,14 @@ dependencies = [
[[package]]
name = "cssparser"
version = "0.13.7"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
"procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
@ -586,7 +586,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
"procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1005,7 +1005,7 @@ name = "geckoservo"
version = "0.0.1"
dependencies = [
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1072,7 +1072,7 @@ dependencies = [
name = "gfx_tests"
version = "0.0.1"
dependencies = [
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx 0.0.1",
"ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"style 0.0.1",
@ -2158,7 +2158,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "procedural-masquerade"
version = "0.1.1"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -2371,7 +2371,7 @@ dependencies = [
"caseless 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
"cookie 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"deny_public_fields 0.0.1",
"devtools_traits 0.0.1",
"dom_struct 0.0.1",
@ -2444,7 +2444,7 @@ dependencies = [
"app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"canvas_traits 0.0.1",
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx_traits 0.0.1",
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2516,7 +2516,7 @@ name = "selectors"
version = "0.19.0"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2898,7 +2898,7 @@ dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2952,7 +2952,7 @@ version = "0.0.1"
dependencies = [
"app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"html5ever 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2972,10 +2972,11 @@ name = "style_traits"
version = "0.0.1"
dependencies = [
"app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.19.0",
"serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2985,7 +2986,7 @@ name = "stylo_tests"
version = "0.0.1"
dependencies = [
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"geckoservo 0.0.1",
@ -3565,7 +3566,7 @@ dependencies = [
"checksum core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41115a6aa5d3e1e5ef98148373f25971d1fad53818553f216495f9e67e90a624"
"checksum core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ead017dcf77f503dc991f6b52de6084eeea60a94b0a652baa9bf88654a28e83f"
"checksum core-text 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9719616a10f717628e074744f8c55df7b450f7a34d29c196d14f4498aad05d"
"checksum cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef6124306e5ebc5ab11891d063aeafdd0cdc308079b708c8b566125f3680292b"
"checksum cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a5ca71edbab09f8dc1e3d1c132717562c3b01c8598ab669183c5195bb1761"
"checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
"checksum dbus 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4aee01fb76ada3e5e7ca642ea6664ebf7308a810739ca2aca44909a1191ac254"
@ -3696,7 +3697,7 @@ dependencies = [
"checksum plane-split 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "556929ef77bf07a9f8584d21382bcebcd6e6f5845d311824d369e1df7cf56d54"
"checksum png 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3cb773e9a557edb568ce9935cf783e3cdcabe06a9449d41b3e5506d88e582c82"
"checksum precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf1fc3616b3ef726a847f2cd2388c646ef6a1f1ba4835c2629004da48184150"
"checksum procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f566249236c6ca4340f7ca78968271f0ed2b0f234007a61b66f9ecd0af09260"
"checksum procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c93cdc1fb30af9ddf3debc4afbdb0f35126cbd99daa229dd76cdd5349b41d989"
"checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41"
"checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3"
"checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4"

Просмотреть файл

@ -12,7 +12,7 @@ path = "lib.rs"
[dependencies]
azure = {git = "https://github.com/servo/rust-azure"}
canvas_traits = {path = "../canvas_traits"}
cssparser = "0.13.7"
cssparser = "0.14.0"
euclid = "0.13"
gleam = "0.4"
ipc-channel = "0.7"

Просмотреть файл

@ -10,7 +10,7 @@ name = "canvas_traits"
path = "lib.rs"
[dependencies]
cssparser = "0.13.7"
cssparser = "0.14.0"
euclid = "0.13"
heapsize = "0.4"
heapsize_derive = "0.1"

Просмотреть файл

@ -35,7 +35,7 @@ byteorder = "1.0"
canvas_traits = {path = "../canvas_traits"}
caseless = "0.1.0"
cookie = "0.6"
cssparser = "0.13.7"
cssparser = "0.14.0"
deny_public_fields = {path = "../deny_public_fields"}
devtools_traits = {path = "../devtools_traits"}
dom_struct = {path = "../dom_struct"}

Просмотреть файл

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use canvas_traits::{CanvasGradientStop, FillOrStrokeStyle, LinearGradientStyle, RadialGradientStyle};
use cssparser::{Parser, RGBA};
use cssparser::{Parser, ParserInput, RGBA};
use cssparser::Color as CSSColor;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::CanvasGradientBinding;
@ -53,7 +53,8 @@ impl CanvasGradientMethods for CanvasGradient {
return Err(Error::IndexSize);
}
let mut parser = Parser::new(&color);
let mut input = ParserInput::new(&color);
let mut parser = Parser::new(&mut input);
let color = CSSColor::parse(&mut parser);
let color = if parser.is_exhausted() {
match color {

Просмотреть файл

@ -6,7 +6,7 @@ use canvas_traits::{Canvas2dMsg, CanvasCommonMsg, CanvasMsg};
use canvas_traits::{CompositionOrBlending, FillOrStrokeStyle, FillRule};
use canvas_traits::{LineCapStyle, LineJoinStyle, LinearGradientStyle};
use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply};
use cssparser::{Parser, RGBA};
use cssparser::{Parser, ParserInput, RGBA};
use cssparser::Color as CSSColor;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
@ -463,7 +463,8 @@ impl CanvasRenderingContext2D {
}
fn parse_color(&self, string: &str) -> Result<RGBA, ()> {
let mut parser = Parser::new(&string);
let mut input = ParserInput::new(string);
let mut parser = Parser::new(&mut input);
let color = CSSColor::parse(&mut parser);
if parser.is_exhausted() {
match color {
@ -1314,7 +1315,8 @@ impl Drop for CanvasRenderingContext2D {
}
pub fn parse_color(string: &str) -> Result<RGBA, ()> {
let mut parser = Parser::new(&string);
let mut input = ParserInput::new(string);
let mut parser = Parser::new(&mut input);
match CSSColor::parse(&mut parser) {
Ok(CSSColor::RGBA(rgba)) => {
if parser.is_exhausted() {

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cssparser::{Parser, serialize_identifier};
use cssparser::{Parser, ParserInput, serialize_identifier};
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
use dom::bindings::error::Fallible;
use dom::bindings::reflector::Reflector;
@ -39,7 +39,8 @@ impl CSS {
/// https://drafts.csswg.org/css-conditional/#dom-css-supports
pub fn Supports_(win: &Window, condition: DOMString) -> bool {
let mut input = Parser::new(&condition);
let mut input = ParserInput::new(&condition);
let mut input = Parser::new(&mut input);
let cond = parse_condition_or_declaration(&mut input);
if let Ok(cond) = cond {
let url = win.Document().url();

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cssparser::Parser;
use cssparser::{Parser, ParserInput};
use dom::bindings::codegen::Bindings::CSSKeyframesRuleBinding;
use dom::bindings::codegen::Bindings::CSSKeyframesRuleBinding::CSSKeyframesRuleMethods;
use dom::bindings::error::ErrorResult;
@ -58,7 +58,8 @@ impl CSSKeyframesRule {
/// Given a keyframe selector, finds the index of the first corresponding rule if any
fn find_rule(&self, selector: &str) -> Option<usize> {
let mut input = Parser::new(selector);
let mut input = ParserInput::new(selector);
let mut input = Parser::new(&mut input);
if let Ok(sel) = KeyframeSelector::parse(&mut input) {
let guard = self.cssrule.shared_lock().read();
// This finds the *last* element matching a selector

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cssparser::Parser;
use cssparser::{Parser, ParserInput};
use dom::bindings::codegen::Bindings::CSSMediaRuleBinding;
use dom::bindings::codegen::Bindings::CSSMediaRuleBinding::CSSMediaRuleMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
@ -69,7 +69,8 @@ impl CSSMediaRule {
/// https://drafts.csswg.org/css-conditional-3/#the-cssmediarule-interface
pub fn set_condition_text(&self, text: DOMString) {
let mut input = Parser::new(&text);
let mut input = ParserInput::new(&text);
let mut input = Parser::new(&mut input);
let global = self.global();
let win = global.as_window();
let url = win.get_url();

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cssparser::Parser;
use cssparser::{Parser, ParserInput};
use dom::bindings::codegen::Bindings::CSSSupportsRuleBinding;
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
use dom::bindings::js::Root;
@ -55,7 +55,8 @@ impl CSSSupportsRule {
/// https://drafts.csswg.org/css-conditional-3/#the-csssupportsrule-interface
pub fn set_condition_text(&self, text: DOMString) {
let mut input = Parser::new(&text);
let mut input = ParserInput::new(&text);
let mut input = Parser::new(&mut input);
let cond = SupportsCondition::parse(&mut input);
if let Ok(cond) = cond {
let global = self.global();

Просмотреть файл

@ -2061,7 +2061,7 @@ impl ElementMethods for Element {
// https://dom.spec.whatwg.org/#dom-element-matches
fn Matches(&self, selectors: DOMString) -> Fallible<bool> {
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
Err(()) => Err(Error::Syntax),
Err(_) => Err(Error::Syntax),
Ok(selectors) => {
let mut ctx = MatchingContext::new(MatchingMode::Normal, None);
Ok(matches_selector_list(&selectors, &Root::from_ref(self), &mut ctx))
@ -2077,7 +2077,7 @@ impl ElementMethods for Element {
// https://dom.spec.whatwg.org/#dom-element-closest
fn Closest(&self, selectors: DOMString) -> Fallible<Option<Root<Element>>> {
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
Err(()) => Err(Error::Syntax),
Err(_) => Err(Error::Syntax),
Ok(selectors) => {
let root = self.upcast::<Node>();
for element in root.inclusive_ancestors() {

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cssparser::Parser as CssParser;
use cssparser::{Parser as CssParser, ParserInput};
use dom::attr::Attr;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListBinding::DOMTokenListMethods;
@ -278,7 +278,8 @@ impl HTMLLinkElement {
None => "",
};
let mut css_parser = CssParser::new(&mq_str);
let mut input = ParserInput::new(&mq_str);
let mut css_parser = CssParser::new(&mut input);
let win = document.window();
let doc_url = document.url();
let context = CssParserContext::new_for_cssom(&doc_url, win.css_error_reporter(), Some(CssRuleType::Media),

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cssparser::Parser as CssParser;
use cssparser::{Parser as CssParser, ParserInput};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::HTMLStyleElementBinding;
use dom::bindings::codegen::Bindings::HTMLStyleElementBinding::HTMLStyleElementMethods;
@ -91,8 +91,9 @@ impl HTMLStyleElement {
PARSING_MODE_DEFAULT,
doc.quirks_mode());
let shared_lock = node.owner_doc().style_shared_lock().clone();
let mut input = ParserInput::new(&mq_str);
let mq = Arc::new(shared_lock.wrap(
parse_media_query_list(&context, &mut CssParser::new(&mq_str))));
parse_media_query_list(&context, &mut CssParser::new(&mut input))));
let loader = StylesheetLoader::for_element(self.upcast());
let sheet = Stylesheet::from_str(&data, win.get_url(), Origin::Author, mq,
shared_lock, Some(&loader),

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cssparser::Parser;
use cssparser::{Parser, ParserInput};
use dom::bindings::codegen::Bindings::MediaListBinding;
use dom::bindings::codegen::Bindings::MediaListBinding::MediaListMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
@ -71,7 +71,8 @@ impl MediaListMethods for MediaList {
return;
}
// Step 3
let mut parser = Parser::new(&value);
let mut input = ParserInput::new(&value);
let mut parser = Parser::new(&mut input);
let global = self.global();
let win = global.as_window();
let url = win.get_url();
@ -107,7 +108,8 @@ impl MediaListMethods for MediaList {
// https://drafts.csswg.org/cssom/#dom-medialist-appendmedium
fn AppendMedium(&self, medium: DOMString) {
// Step 1
let mut parser = Parser::new(&medium);
let mut input = ParserInput::new(&medium);
let mut parser = Parser::new(&mut input);
let global = self.global();
let win = global.as_window();
let url = win.get_url();
@ -135,7 +137,8 @@ impl MediaListMethods for MediaList {
// https://drafts.csswg.org/cssom/#dom-medialist-deletemedium
fn DeleteMedium(&self, medium: DOMString) {
// Step 1
let mut parser = Parser::new(&medium);
let mut input = ParserInput::new(&medium);
let mut parser = Parser::new(&mut input);
let global = self.global();
let win = global.as_window();
let url = win.get_url();

Просмотреть файл

@ -717,7 +717,7 @@ impl Node {
// Step 1.
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
// Step 2.
Err(()) => Err(Error::Syntax),
Err(_) => Err(Error::Syntax),
// Step 3.
Ok(selectors) => {
let mut ctx = MatchingContext::new(MatchingMode::Normal, None);
@ -737,7 +737,7 @@ impl Node {
// Step 1.
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
// Step 2.
Err(()) => Err(Error::Syntax),
Err(_) => Err(Error::Syntax),
// Step 3.
Ok(selectors) => {
let mut descendants = self.traverse_preorder();

Просмотреть файл

@ -5,7 +5,7 @@
use app_units::Au;
use base64;
use bluetooth_traits::BluetoothRequest;
use cssparser::Parser;
use cssparser::{Parser, ParserInput};
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
@ -1003,7 +1003,8 @@ impl WindowMethods for Window {
// https://drafts.csswg.org/cssom-view/#dom-window-matchmedia
fn MatchMedia(&self, query: DOMString) -> Root<MediaQueryList> {
let mut parser = Parser::new(&query);
let mut input = ParserInput::new(&query);
let mut parser = Parser::new(&mut input);
let url = self.get_url();
let quirks_mode = self.Document().quirks_mode();
let context = CssParserContext::new_for_cssom(&url, self.css_error_reporter(), Some(CssRuleType::Media),

Просмотреть файл

@ -13,7 +13,7 @@ path = "lib.rs"
app_units = "0.4.1"
atomic_refcell = "0.1"
canvas_traits = {path = "../canvas_traits"}
cssparser = "0.13.7"
cssparser = "0.14.0"
euclid = "0.13"
gfx_traits = {path = "../gfx_traits"}
heapsize = "0.4"

Просмотреть файл

@ -9,7 +9,7 @@ use msg::constellation_msg::PipelineId;
use script_traits::ConstellationControlMsg;
use servo_url::ServoUrl;
use std::sync::{Mutex, Arc};
use style::error_reporting::ParseErrorReporter;
use style::error_reporting::{ParseErrorReporter, ContextualParseError};
#[derive(HeapSizeOf, Clone)]
pub struct CSSErrorReporter {
@ -22,12 +22,12 @@ pub struct CSSErrorReporter {
}
impl ParseErrorReporter for CSSErrorReporter {
fn report_error(&self,
input: &mut Parser,
position: SourcePosition,
message: &str,
url: &ServoUrl,
line_number_offset: u64) {
fn report_error<'a>(&self,
input: &mut Parser,
position: SourcePosition,
error: ContextualParseError<'a>,
url: &ServoUrl,
line_number_offset: u64) {
let location = input.source_location(position);
let line_offset = location.line + line_number_offset as usize;
if log_enabled!(log::LogLevel::Info) {
@ -35,7 +35,7 @@ impl ParseErrorReporter for CSSErrorReporter {
url.as_str(),
line_offset,
location.column,
message)
error.to_string())
}
//TODO: report a real filename
@ -44,6 +44,6 @@ impl ParseErrorReporter for CSSErrorReporter {
"".to_owned(),
location.line,
location.column,
message.to_owned()));
error.to_string()));
}
}

Просмотреть файл

@ -24,7 +24,7 @@ gecko_like_types = []
[dependencies]
bitflags = "0.7"
matches = "0.1"
cssparser = "0.13.7"
cssparser = "0.14.0"
log = "0.3"
fnv = "1.0"
phf = "0.7.18"

Просмотреть файл

@ -4,6 +4,7 @@
use attr::{AttrSelectorWithNamespace, ParsedAttrSelectorOperation, AttrSelectorOperator};
use attr::{ParsedCaseSensitivity, SELECTOR_WHITESPACE, NamespaceConstraint};
use cssparser::{ParseError, BasicParseError};
use cssparser::{Token, Parser as CssParser, parse_nth, ToCss, serialize_identifier, CssStringWriter};
use precomputed_hash::PrecomputedHash;
use servo_arc::{Arc, HeaderWithLength, ThinArc};
@ -43,6 +44,30 @@ fn to_ascii_lowercase(s: &str) -> Cow<str> {
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum SelectorParseError<'i, T> {
PseudoElementInComplexSelector,
NoQualifiedNameInAttributeSelector,
TooManyCompoundSelectorComponentsInNegation,
NegationSelectorComponentNotNamespace,
NegationSelectorComponentNotLocalName,
EmptySelector,
NonSimpleSelectorInNegation,
UnexpectedTokenInAttributeSelector,
PseudoElementExpectedColon,
PseudoElementExpectedIdent,
UnsupportedPseudoClass,
UnexpectedIdent(Cow<'i, str>),
ExpectedNamespace,
Custom(T),
}
impl<'a, T> Into<ParseError<'a, SelectorParseError<'a, T>>> for SelectorParseError<'a, T> {
fn into(self) -> ParseError<'a, SelectorParseError<'a, T>> {
ParseError::Custom(self)
}
}
macro_rules! with_all_bounds {
(
[ $( $InSelector: tt )* ]
@ -97,26 +122,30 @@ with_bounds! {
[From<String> + for<'a> From<&'a str>]
}
pub trait Parser {
pub trait Parser<'i> {
type Impl: SelectorImpl;
type Error: 'i;
/// This function can return an "Err" pseudo-element in order to support CSS2.1
/// pseudo-elements.
fn parse_non_ts_pseudo_class(&self, _name: Cow<str>)
-> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass, ()> {
Err(())
fn parse_non_ts_pseudo_class(&self, name: Cow<'i, str>)
-> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass,
ParseError<'i, SelectorParseError<'i, Self::Error>>> {
Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
}
fn parse_non_ts_functional_pseudo_class
(&self, _name: Cow<str>, _arguments: &mut CssParser)
-> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass, ()>
fn parse_non_ts_functional_pseudo_class<'t>
(&self, name: Cow<'i, str>, _arguments: &mut CssParser<'i, 't>)
-> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass,
ParseError<'i, SelectorParseError<'i, Self::Error>>>
{
Err(())
Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
}
fn parse_pseudo_element(&self, _name: Cow<str>)
-> Result<<Self::Impl as SelectorImpl>::PseudoElement, ()> {
Err(())
fn parse_pseudo_element(&self, name: Cow<'i, str>)
-> Result<<Self::Impl as SelectorImpl>::PseudoElement,
ParseError<'i, SelectorParseError<'i, Self::Error>>> {
Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
}
fn default_namespace(&self) -> Option<<Self::Impl as SelectorImpl>::NamespaceUrl> {
@ -157,8 +186,9 @@ impl<Impl: SelectorImpl> SelectorList<Impl> {
/// https://drafts.csswg.org/selectors/#grouping
///
/// Return the Selectors or Err if there is an invalid selector.
pub fn parse<P>(parser: &P, input: &mut CssParser) -> Result<Self, ()>
where P: Parser<Impl=Impl> {
pub fn parse<'i, 't, P, E>(parser: &P, input: &mut CssParser<'i, 't>)
-> Result<Self, ParseError<'i, SelectorParseError<'i, E>>>
where P: Parser<'i, Impl=Impl, Error=E> {
input.parse_comma_separated(|input| parse_selector(parser, input).map(SelectorAndHashes::new))
.map(SelectorList)
}
@ -960,11 +990,11 @@ type ParseVec<Impl> = SmallVec<[Component<Impl>; 32]>;
/// selector : simple_selector_sequence [ combinator simple_selector_sequence ]* ;
///
/// `Err` means invalid selector.
fn parse_selector<P, Impl>(
fn parse_selector<'i, 't, P, E, Impl>(
parser: &P,
input: &mut CssParser)
-> Result<Selector<Impl>, ()>
where P: Parser<Impl=Impl>, Impl: SelectorImpl
input: &mut CssParser<'i, 't>)
-> Result<Selector<Impl>, ParseError<'i, SelectorParseError<'i, E>>>
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
{
let mut sequence = ParseVec::new();
let mut parsed_pseudo_element;
@ -983,7 +1013,7 @@ fn parse_selector<P, Impl>(
loop {
let position = input.position();
match input.next_including_whitespace() {
Err(()) => break 'outer_loop,
Err(_e) => break 'outer_loop,
Ok(Token::WhiteSpace(_)) => any_whitespace = true,
Ok(Token::Delim('>')) => {
combinator = Combinator::Child;
@ -1026,12 +1056,13 @@ fn parse_selector<P, Impl>(
impl<Impl: SelectorImpl> Selector<Impl> {
/// Parse a selector, without any pseudo-element.
pub fn parse<P>(parser: &P, input: &mut CssParser) -> Result<Self, ()>
where P: Parser<Impl=Impl>
pub fn parse<'i, 't, P, E>(parser: &P, input: &mut CssParser<'i, 't>)
-> Result<Self, ParseError<'i, SelectorParseError<'i, E>>>
where P: Parser<'i, Impl=Impl, Error=E>
{
let selector = parse_selector(parser, input)?;
if selector.has_pseudo_element() {
return Err(())
return Err(ParseError::Custom(SelectorParseError::PseudoElementInComplexSelector))
}
Ok(selector)
}
@ -1040,9 +1071,10 @@ impl<Impl: SelectorImpl> Selector<Impl> {
/// * `Err(())`: Invalid selector, abort
/// * `Ok(None)`: Not a type selector, could be something else. `input` was not consumed.
/// * `Ok(Some(vec))`: Length 0 (`*|*`), 1 (`*|E` or `ns|*`) or 2 (`|E` or `ns|E`)
fn parse_type_selector<P, Impl>(parser: &P, input: &mut CssParser, sequence: &mut ParseVec<Impl>)
-> Result<bool, ()>
where P: Parser<Impl=Impl>, Impl: SelectorImpl
fn parse_type_selector<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParser<'i, 't>,
sequence: &mut ParseVec<Impl>)
-> Result<bool, ParseError<'i, SelectorParseError<'i, E>>>
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
{
match parse_qualified_name(parser, input, /* in_attr_selector = */ false)? {
None => Ok(false),
@ -1100,11 +1132,12 @@ enum QNamePrefix<Impl: SelectorImpl> {
/// * `Err(())`: Invalid selector, abort
/// * `Ok(None)`: Not a simple selector, could be something else. `input` was not consumed.
/// * `Ok(Some((namespace, local_name)))`: `None` for the local name means a `*` universal selector
fn parse_qualified_name<'i, 't, P, Impl>
fn parse_qualified_name<'i, 't, P, E, Impl>
(parser: &P, input: &mut CssParser<'i, 't>,
in_attr_selector: bool)
-> Result<Option<(QNamePrefix<Impl>, Option<Cow<'i, str>>)>, ()>
where P: Parser<Impl=Impl>, Impl: SelectorImpl
-> Result<Option<(QNamePrefix<Impl>, Option<Cow<'i, str>>)>,
ParseError<'i, SelectorParseError<'i, E>>>
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
{
let default_namespace = |local_name| {
let namespace = match parser.default_namespace() {
@ -1122,7 +1155,8 @@ fn parse_qualified_name<'i, 't, P, Impl>
Ok(Token::Ident(local_name)) => {
Ok(Some((namespace, Some(local_name))))
},
_ => Err(()),
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
Err(e) => Err(ParseError::Basic(e)),
}
};
@ -1134,7 +1168,7 @@ fn parse_qualified_name<'i, 't, P, Impl>
Ok(Token::Delim('|')) => {
let prefix = from_cow_str(value);
let result = parser.namespace_for_prefix(&prefix);
let url = result.ok_or(())?;
let url = result.ok_or(ParseError::Custom(SelectorParseError::ExpectedNamespace))?;
explicit_namespace(input, QNamePrefix::ExplicitNamespace(prefix, url))
},
_ => {
@ -1153,10 +1187,13 @@ fn parse_qualified_name<'i, 't, P, Impl>
Ok(Token::Delim('|')) => {
explicit_namespace(input, QNamePrefix::ExplicitAnyNamespace)
}
_ => {
result => {
input.reset(position);
if in_attr_selector {
Err(())
match result {
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
Err(e) => Err(ParseError::Basic(e)),
}
} else {
default_namespace(None)
}
@ -1174,14 +1211,15 @@ fn parse_qualified_name<'i, 't, P, Impl>
}
fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
-> Result<Component<Impl>, ()>
where P: Parser<Impl=Impl>, Impl: SelectorImpl
fn parse_attribute_selector<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParser<'i, 't>)
-> Result<Component<Impl>,
ParseError<'i, SelectorParseError<'i, E>>>
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
{
let namespace;
let local_name;
match parse_qualified_name(parser, input, /* in_attr_selector = */ true)? {
None => return Err(()),
None => return Err(ParseError::Custom(SelectorParseError::NoQualifiedNameInAttributeSelector)),
Some((_, None)) => unreachable!(),
Some((ns, Some(ln))) => {
local_name = ln;
@ -1209,7 +1247,7 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
let never_matches;
match input.next() {
// [foo]
Err(()) => {
Err(_) => {
let local_name_lower = from_cow_str(to_ascii_lowercase(&local_name));
let local_name = from_cow_str(local_name);
if let Some(namespace) = namespace {
@ -1264,7 +1302,7 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
never_matches = value.is_empty();
operator = AttrSelectorOperator::Suffix;
}
_ => return Err(())
_ => return Err(SelectorParseError::UnexpectedTokenInAttributeSelector.into())
}
let mut case_sensitivity = parse_attribute_flags(input)?;
@ -1310,23 +1348,26 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
}
fn parse_attribute_flags(input: &mut CssParser) -> Result<ParsedCaseSensitivity, ()> {
fn parse_attribute_flags<'i, 't, E>(input: &mut CssParser<'i, 't>)
-> Result<ParsedCaseSensitivity,
ParseError<'i, SelectorParseError<'i, E>>> {
match input.next() {
Err(()) => Ok(ParsedCaseSensitivity::CaseSensitive),
Err(_) => Ok(ParsedCaseSensitivity::CaseSensitive),
Ok(Token::Ident(ref value)) if value.eq_ignore_ascii_case("i") => {
Ok(ParsedCaseSensitivity::AsciiCaseInsensitive)
}
_ => Err(())
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t)))
}
}
/// Level 3: Parse **one** simple_selector. (Though we might insert a second
/// implied "<defaultns>|*" type selector.)
fn parse_negation<P, Impl>(parser: &P,
input: &mut CssParser)
-> Result<Component<Impl>, ()>
where P: Parser<Impl=Impl>, Impl: SelectorImpl
fn parse_negation<'i, 't, P, E, Impl>(parser: &P,
input: &mut CssParser<'i, 't>)
-> Result<Component<Impl>,
ParseError<'i, SelectorParseError<'i, E>>>
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
{
let mut v = ParseVec::new();
parse_compound_selector(parser, input, &mut v, /* inside_negation = */ true)?;
@ -1334,7 +1375,7 @@ fn parse_negation<P, Impl>(parser: &P,
if single_simple_selector(&v) {
Ok(Component::Negation(v.into_vec().into_boxed_slice()))
} else {
Err(())
Err(ParseError::Custom(SelectorParseError::NonSimpleSelectorInNegation))
}
}
@ -1365,13 +1406,13 @@ fn single_simple_selector<Impl: SelectorImpl>(v: &[Component<Impl>]) -> bool {
/// `Err(())` means invalid selector.
///
/// The boolean represent whether a pseudo-element has been parsed.
fn parse_compound_selector<P, Impl>(
fn parse_compound_selector<'i, 't, P, E, Impl>(
parser: &P,
input: &mut CssParser,
input: &mut CssParser<'i, 't>,
mut sequence: &mut ParseVec<Impl>,
inside_negation: bool)
-> Result<bool, ()>
where P: Parser<Impl=Impl>, Impl: SelectorImpl
-> Result<bool, ParseError<'i, SelectorParseError<'i, E>>>
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
{
// Consume any leading whitespace.
loop {
@ -1412,21 +1453,21 @@ fn parse_compound_selector<P, Impl>(
loop {
match input.next_including_whitespace() {
Ok(Token::Colon) => {},
Ok(Token::WhiteSpace(_)) | Err(()) => break,
_ => return Err(()),
Ok(Token::WhiteSpace(_)) | Err(_) => break,
_ => return Err(SelectorParseError::PseudoElementExpectedColon.into()),
}
// TODO(emilio): Functional pseudo-classes too?
// We don't need it for now.
let name = match input.next_including_whitespace() {
Ok(Token::Ident(name)) => name,
_ => return Err(()),
_ => return Err(SelectorParseError::PseudoElementExpectedIdent.into()),
};
let pseudo_class =
P::parse_non_ts_pseudo_class(parser, name)?;
if !p.supports_pseudo_class(&pseudo_class) {
return Err(());
return Err(SelectorParseError::UnsupportedPseudoClass.into());
}
state_selectors.push(Component::NonTSPseudoClass(pseudo_class));
}
@ -1448,18 +1489,19 @@ fn parse_compound_selector<P, Impl>(
}
if empty {
// An empty selector is invalid.
Err(())
Err(ParseError::Custom(SelectorParseError::EmptySelector))
} else {
Ok(pseudo)
}
}
fn parse_functional_pseudo_class<P, Impl>(parser: &P,
input: &mut CssParser,
name: Cow<str>,
inside_negation: bool)
-> Result<Component<Impl>, ()>
where P: Parser<Impl=Impl>, Impl: SelectorImpl
fn parse_functional_pseudo_class<'i, 't, P, E, Impl>(parser: &P,
input: &mut CssParser<'i, 't>,
name: Cow<'i, str>,
inside_negation: bool)
-> Result<Component<Impl>,
ParseError<'i, SelectorParseError<'i, E>>>
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
{
match_ignore_ascii_case! { &name,
"nth-child" => return parse_nth_pseudo_class(input, Component::NthChild),
@ -1468,7 +1510,7 @@ fn parse_functional_pseudo_class<P, Impl>(parser: &P,
"nth-last-of-type" => return parse_nth_pseudo_class(input, Component::NthLastOfType),
"not" => {
if inside_negation {
return Err(())
return Err(ParseError::Custom(SelectorParseError::UnexpectedIdent("not".into())));
}
return parse_negation(parser, input)
},
@ -1479,8 +1521,9 @@ fn parse_functional_pseudo_class<P, Impl>(parser: &P,
}
fn parse_nth_pseudo_class<Impl, F>(input: &mut CssParser, selector: F)
-> Result<Component<Impl>, ()>
fn parse_nth_pseudo_class<'i, 't, Impl, F, E>(input: &mut CssParser<'i, 't>, selector: F)
-> Result<Component<Impl>,
ParseError<'i, SelectorParseError<'i, E>>>
where Impl: SelectorImpl, F: FnOnce(i32, i32) -> Component<Impl> {
let (a, b) = parse_nth(input)?;
Ok(selector(a, b))
@ -1492,11 +1535,12 @@ where Impl: SelectorImpl, F: FnOnce(i32, i32) -> Component<Impl> {
/// * `Err(())`: Invalid selector, abort
/// * `Ok(None)`: Not a simple selector, could be something else. `input` was not consumed.
/// * `Ok(Some(_))`: Parsed a simple selector or pseudo-element
fn parse_one_simple_selector<P, Impl>(parser: &P,
input: &mut CssParser,
inside_negation: bool)
-> Result<Option<SimpleSelectorParseResult<Impl>>, ()>
where P: Parser<Impl=Impl>, Impl: SelectorImpl
fn parse_one_simple_selector<'i, 't, P, E, Impl>(parser: &P,
input: &mut CssParser<'i, 't>,
inside_negation: bool)
-> Result<Option<SimpleSelectorParseResult<Impl>>,
ParseError<'i, SelectorParseError<'i, E>>>
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
{
let start_position = input.position();
match input.next_including_whitespace() {
@ -1510,7 +1554,8 @@ fn parse_one_simple_selector<P, Impl>(parser: &P,
let class = Component::Class(from_cow_str(class));
Ok(Some(SimpleSelectorParseResult::SimpleSelector(class)))
}
_ => Err(()),
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
Err(e) => Err(ParseError::Basic(e)),
}
}
Ok(Token::SquareBracketBlock) => {
@ -1545,10 +1590,12 @@ fn parse_one_simple_selector<P, Impl>(parser: &P,
let pseudo = P::parse_pseudo_element(parser, name)?;
Ok(Some(SimpleSelectorParseResult::PseudoElement(pseudo)))
}
_ => Err(())
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
Err(e) => Err(ParseError::Basic(e)),
}
}
_ => Err(())
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
Err(e) => Err(ParseError::Basic(e)),
}
}
_ => {
@ -1558,8 +1605,10 @@ fn parse_one_simple_selector<P, Impl>(parser: &P,
}
}
fn parse_simple_pseudo_class<P, Impl>(parser: &P, name: Cow<str>) -> Result<Component<Impl>, ()>
where P: Parser<Impl=Impl>, Impl: SelectorImpl
fn parse_simple_pseudo_class<'i, P, E, Impl>(parser: &P, name: Cow<'i, str>)
-> Result<Component<Impl>,
ParseError<'i, SelectorParseError<'i, E>>>
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
{
(match_ignore_ascii_case! { &name,
"first-child" => Ok(Component::FirstChild),
@ -1580,7 +1629,7 @@ fn parse_simple_pseudo_class<P, Impl>(parser: &P, name: Cow<str>) -> Result<Comp
// NB: pub module in order to access the DummyParser
#[cfg(test)]
pub mod tests {
use cssparser::{Parser as CssParser, ToCss, serialize_identifier};
use cssparser::{Parser as CssParser, ToCss, serialize_identifier, ParserInput};
use parser;
use std::borrow::Cow;
use std::collections::HashMap;
@ -1691,32 +1740,37 @@ pub mod tests {
}
}
impl Parser for DummyParser {
impl<'i> Parser<'i> for DummyParser {
type Impl = DummySelectorImpl;
type Error = ();
fn parse_non_ts_pseudo_class(&self, name: Cow<str>)
-> Result<PseudoClass, ()> {
fn parse_non_ts_pseudo_class(&self, name: Cow<'i, str>)
-> Result<PseudoClass,
ParseError<'i, SelectorParseError<'i, ()>>> {
match_ignore_ascii_case! { &name,
"hover" => Ok(PseudoClass::Hover),
"active" => Ok(PseudoClass::Active),
_ => Err(())
_ => Err(SelectorParseError::Custom(()).into())
}
}
fn parse_non_ts_functional_pseudo_class(&self, name: Cow<str>,
parser: &mut CssParser)
-> Result<PseudoClass, ()> {
fn parse_non_ts_functional_pseudo_class<'t>(&self, name: Cow<'i, str>,
parser: &mut CssParser<'i, 't>)
-> Result<PseudoClass,
ParseError<'i, SelectorParseError<'i, ()>>> {
match_ignore_ascii_case! { &name,
"lang" => Ok(PseudoClass::Lang(try!(parser.expect_ident_or_string()).into_owned())),
_ => Err(())
_ => Err(SelectorParseError::Custom(()).into())
}
}
fn parse_pseudo_element(&self, name: Cow<str>) -> Result<PseudoElement, ()> {
fn parse_pseudo_element(&self, name: Cow<'i, str>)
-> Result<PseudoElement,
ParseError<'i, SelectorParseError<'i, ()>>> {
match_ignore_ascii_case! { &name,
"before" => Ok(PseudoElement::Before),
"after" => Ok(PseudoElement::After),
_ => Err(())
_ => Err(SelectorParseError::Custom(()).into())
}
}
@ -1729,13 +1783,16 @@ pub mod tests {
}
}
fn parse(input: &str) -> Result<SelectorList<DummySelectorImpl>, ()> {
fn parse<'i>(input: &'i str) -> Result<SelectorList<DummySelectorImpl>,
ParseError<'i, SelectorParseError<'i, ()>>> {
parse_ns(input, &DummyParser::default())
}
fn parse_ns(input: &str, parser: &DummyParser)
-> Result<SelectorList<DummySelectorImpl>, ()> {
let result = SelectorList::parse(parser, &mut CssParser::new(input));
fn parse_ns<'i>(input: &'i str, parser: &DummyParser)
-> Result<SelectorList<DummySelectorImpl>,
ParseError<'i, SelectorParseError<'i, ()>>> {
let mut parser_input = ParserInput::new(input);
let result = SelectorList::parse(parser, &mut CssParser::new(&mut parser_input));
if let Ok(ref selectors) = result {
assert_eq!(selectors.0.len(), 1);
assert_eq!(selectors.0[0].selector.to_css_string(), input);
@ -1749,7 +1806,8 @@ pub mod tests {
#[test]
fn test_empty() {
let list = SelectorList::parse(&DummyParser::default(), &mut CssParser::new(":empty"));
let mut input = ParserInput::new(":empty");
let list = SelectorList::parse(&DummyParser::default(), &mut CssParser::new(&mut input));
assert!(list.is_ok());
}
@ -1758,9 +1816,9 @@ pub mod tests {
#[test]
fn test_parsing() {
assert_eq!(parse(""), Err(())) ;
assert_eq!(parse(":lang(4)"), Err(())) ;
assert_eq!(parse(":lang(en US)"), Err(())) ;
assert!(parse("").is_err()) ;
assert!(parse(":lang(4)").is_err()) ;
assert!(parse(":lang(en US)").is_err()) ;
assert_eq!(parse("EeÉ"), Ok(SelectorList::from_vec(vec!(
Selector::from_vec(vec!(
Component::LocalName(LocalName {
@ -1846,7 +1904,7 @@ pub mod tests {
}
), specificity(0, 1, 0))
))));
assert_eq!(parse_ns("svg|circle", &parser), Err(()));
assert!(parse_ns("svg|circle", &parser).is_err());
parser.ns_prefixes.insert(DummyAtom("svg".into()), DummyAtom(SVG.into()));
assert_eq!(parse_ns("svg|circle", &parser), Ok(SelectorList::from_vec(vec!(
Selector::from_vec(vec!(
@ -1960,14 +2018,14 @@ pub mod tests {
Component::NonTSPseudoClass(PseudoClass::Hover),
), specificity(0, 2, 1) | HAS_PSEUDO_BIT)
))));
assert_eq!(parse("::before:hover:active"), Err(()));
assert_eq!(parse("::before:hover .foo"), Err(()));
assert_eq!(parse("::before .foo"), Err(()));
assert_eq!(parse("::before ~ bar"), Err(()));
assert_eq!(parse("::before:active"), Err(()));
assert!(parse("::before:hover:active").is_err());
assert!(parse("::before:hover .foo").is_err());
assert!(parse("::before .foo").is_err());
assert!(parse("::before ~ bar").is_err());
assert!(parse("::before:active").is_err());
// https://github.com/servo/servo/issues/15335
assert_eq!(parse(":: before"), Err(()));
assert!(parse(":: before").is_err());
assert_eq!(parse("div ::after"), Ok(SelectorList::from_vec(vec!(
Selector::from_vec(vec!(
Component::LocalName(LocalName {
@ -1986,8 +2044,8 @@ pub mod tests {
), (1 << 20) + (1 << 10) + (0 << 0))
))));
parser.default_ns = None;
assert_eq!(parse(":not(#provel.old)"), Err(()));
assert_eq!(parse(":not(#provel > old)"), Err(()));
assert!(parse(":not(#provel.old)").is_err());
assert!(parse(":not(#provel > old)").is_err());
assert!(parse("table[rules]:not([rules = \"none\"]):not([rules = \"\"])").is_ok());
assert_eq!(parse(":not(#provel)"), Ok(SelectorList::from_vec(vec!(
Selector::from_vec(vec!(Component::Negation(vec!(

Просмотреть файл

@ -38,7 +38,7 @@ bitflags = "0.7"
bit-vec = "0.4.3"
byteorder = "1.0"
cfg-if = "0.1.0"
cssparser = "0.13.7"
cssparser = "0.14.0"
encoding = {version = "0.2", optional = true}
euclid = "0.13"
fnv = "1.0"

Просмотреть файл

@ -8,20 +8,22 @@
use Atom;
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser};
use cssparser::{Parser, Token, serialize_identifier};
use cssparser::{Parser, Token, serialize_identifier, BasicParseError};
use error_reporting::ContextualParseError;
#[cfg(feature = "gecko")] use gecko::rules::CounterStyleDescriptors;
#[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSCounterDesc;
use parser::{ParserContext, log_css_error, Parse};
use selectors::parser::SelectorParseError;
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::fmt;
use std::ops::Range;
use style_traits::{ToCss, OneOrMoreCommaSeparated};
use style_traits::{ToCss, OneOrMoreCommaSeparated, ParseError, StyleParseError};
use values::CustomIdent;
/// Parse the prelude of an @counter-style rule
pub fn parse_counter_style_name(input: &mut Parser) -> Result<CustomIdent, ()> {
pub fn parse_counter_style_name<'i, 't>(input: &mut Parser<'i, 't>) -> Result<CustomIdent, ParseError<'i>> {
macro_rules! predefined {
($($name: expr,)+) => {
{
@ -48,8 +50,8 @@ pub fn parse_counter_style_name(input: &mut Parser) -> Result<CustomIdent, ()> {
}
/// Parse the body (inside `{}`) of an @counter-style rule
pub fn parse_counter_style_body(name: CustomIdent, context: &ParserContext, input: &mut Parser)
-> Result<CounterStyleRuleData, ()> {
pub fn parse_counter_style_body<'i, 't>(name: CustomIdent, context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<CounterStyleRuleData, ParseError<'i>> {
let start = input.position();
let mut rule = CounterStyleRuleData::empty(name);
{
@ -59,11 +61,11 @@ pub fn parse_counter_style_body(name: CustomIdent, context: &ParserContext, inpu
};
let mut iter = DeclarationListParser::new(input, parser);
while let Some(declaration) = iter.next() {
if let Err(range) = declaration {
let pos = range.start;
let message = format!("Unsupported @counter-style descriptor declaration: '{}'",
iter.input.slice(range));
log_css_error(iter.input, pos, &*message, context);
if let Err(err) = declaration {
let pos = err.span.start;
let error = ContextualParseError::UnsupportedCounterStyleDescriptorDeclaration(
iter.input.slice(err.span), err.error);
log_css_error(iter.input, pos, error, context);
}
}
}
@ -75,32 +77,28 @@ pub fn parse_counter_style_body(name: CustomIdent, context: &ParserContext, inpu
ref system @ System::Numeric
if rule.symbols.is_none() => {
let system = system.to_css_string();
Some(format!("Invalid @counter-style rule: 'system: {}' without 'symbols'", system))
Some(ContextualParseError::InvalidCounterStyleWithoutSymbols(system))
}
ref system @ System::Alphabetic |
ref system @ System::Numeric
if rule.symbols().unwrap().0.len() < 2 => {
let system = system.to_css_string();
Some(format!("Invalid @counter-style rule: 'system: {}' less than two 'symbols'",
system))
Some(ContextualParseError::InvalidCounterStyleNotEnoughSymbols(system))
}
System::Additive if rule.additive_symbols.is_none() => {
let s = "Invalid @counter-style rule: 'system: additive' without 'additive-symbols'";
Some(s.to_owned())
Some(ContextualParseError::InvalidCounterStyleWithoutAdditiveSymbols)
}
System::Extends(_) if rule.symbols.is_some() => {
let s = "Invalid @counter-style rule: 'system: extends …' with 'symbols'";
Some(s.to_owned())
Some(ContextualParseError::InvalidCounterStyleExtendsWithSymbols)
}
System::Extends(_) if rule.additive_symbols.is_some() => {
let s = "Invalid @counter-style rule: 'system: extends …' with 'additive-symbols'";
Some(s.to_owned())
Some(ContextualParseError::InvalidCounterStyleExtendsWithAdditiveSymbols)
}
_ => None
};
if let Some(message) = error {
log_css_error(input, start, &message, context);
Err(())
if let Some(error) = error {
log_css_error(input, start, error, context);
Err(StyleParseError::UnspecifiedError.into())
} else {
Ok(rule)
}
@ -112,9 +110,10 @@ struct CounterStyleRuleParser<'a, 'b: 'a> {
}
/// Default methods reject all at rules.
impl<'a, 'b> AtRuleParser for CounterStyleRuleParser<'a, 'b> {
impl<'a, 'b, 'i> AtRuleParser<'i> for CounterStyleRuleParser<'a, 'b> {
type Prelude = ();
type AtRule = ();
type Error = SelectorParseError<'i, StyleParseError<'i>>;
}
macro_rules! accessor {
@ -181,11 +180,13 @@ macro_rules! counter_style_descriptors {
}
}
impl<'a, 'b> DeclarationParser for CounterStyleRuleParser<'a, 'b> {
impl<'a, 'b, 'i> DeclarationParser<'i> for CounterStyleRuleParser<'a, 'b> {
type Declaration = ();
type Error = SelectorParseError<'i, StyleParseError<'i>>;
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<(), ()> {
match_ignore_ascii_case! { name,
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
-> Result<(), ParseError<'i>> {
match_ignore_ascii_case! { &*name,
$(
$name => {
// DeclarationParser also calls parse_entirely
@ -196,7 +197,7 @@ macro_rules! counter_style_descriptors {
self.rule.$ident = Some(value)
}
)*
_ => return Err(())
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
Ok(())
}
@ -293,8 +294,9 @@ pub enum System {
}
impl Parse for System {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
match_ignore_ascii_case! { &input.expect_ident()?,
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let ident = input.expect_ident()?;
(match_ignore_ascii_case! { &ident,
"cyclic" => Ok(System::Cyclic),
"numeric" => Ok(System::Numeric),
"alphabetic" => Ok(System::Alphabetic),
@ -309,7 +311,7 @@ impl Parse for System {
Ok(System::Extends(other))
}
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
}
@ -349,11 +351,12 @@ pub enum Symbol {
}
impl Parse for Symbol {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
match input.next() {
Ok(Token::QuotedString(s)) => Ok(Symbol::String(s.into_owned())),
Ok(Token::Ident(s)) => Ok(Symbol::Ident(s.into_owned())),
_ => Err(())
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
Err(e) => Err(e.into()),
}
}
}
@ -383,7 +386,7 @@ impl Symbol {
pub struct Negative(pub Symbol, pub Option<Symbol>);
impl Parse for Negative {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Ok(Negative(
Symbol::parse(context, input)?,
input.try(|input| Symbol::parse(context, input)).ok(),
@ -409,7 +412,7 @@ impl ToCss for Negative {
pub struct Ranges(pub Vec<Range<Option<i32>>>);
impl Parse for Ranges {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
Ok(Ranges(Vec::new()))
} else {
@ -418,7 +421,7 @@ impl Parse for Ranges {
let opt_end = parse_bound(input)?;
if let (Some(start), Some(end)) = (opt_start, opt_end) {
if start > end {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
}
Ok(opt_start..opt_end)
@ -427,11 +430,12 @@ impl Parse for Ranges {
}
}
fn parse_bound(input: &mut Parser) -> Result<Option<i32>, ()> {
fn parse_bound<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Option<i32>, ParseError<'i>> {
match input.next() {
Ok(Token::Number(ref v)) if v.int_value.is_some() => Ok(Some(v.int_value.unwrap())),
Ok(Token::Ident(ref ident)) if ident.eq_ignore_ascii_case("infinite") => Ok(None),
_ => Err(())
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
Err(e) => Err(e.into()),
}
}
@ -471,13 +475,13 @@ fn bound_to_css<W>(range: Option<i32>, dest: &mut W) -> fmt::Result where W: fmt
pub struct Pad(pub u32, pub Symbol);
impl Parse for Pad {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let pad_with = input.try(|input| Symbol::parse(context, input));
let min_length = input.expect_integer()?;
if min_length < 0 {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
let pad_with = pad_with.or_else(|()| Symbol::parse(context, input))?;
let pad_with = pad_with.or_else(|_| Symbol::parse(context, input))?;
Ok(Pad(min_length as u32, pad_with))
}
}
@ -494,7 +498,7 @@ impl ToCss for Pad {
pub struct Fallback(pub CustomIdent);
impl Parse for Fallback {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
parse_counter_style_name(input).map(Fallback)
}
}
@ -510,14 +514,14 @@ impl ToCss for Fallback {
pub struct Symbols(pub Vec<Symbol>);
impl Parse for Symbols {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let mut symbols = Vec::new();
loop {
if let Ok(s) = input.try(|input| Symbol::parse(context, input)) {
symbols.push(s)
} else {
if symbols.is_empty() {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
} else {
return Ok(Symbols(symbols))
}
@ -544,11 +548,11 @@ impl ToCss for Symbols {
pub struct AdditiveSymbols(pub Vec<AdditiveTuple>);
impl Parse for AdditiveSymbols {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let tuples = Vec::<AdditiveTuple>::parse(context, input)?;
// FIXME maybe? https://github.com/w3c/csswg-drafts/issues/1220
if tuples.windows(2).any(|window| window[0].weight <= window[1].weight) {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
Ok(AdditiveSymbols(tuples))
}
@ -572,13 +576,13 @@ pub struct AdditiveTuple {
impl OneOrMoreCommaSeparated for AdditiveTuple {}
impl Parse for AdditiveTuple {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let symbol = input.try(|input| Symbol::parse(context, input));
let weight = input.expect_integer()?;
if weight < 0 {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
let symbol = symbol.or_else(|()| Symbol::parse(context, input))?;
let symbol = symbol.or_else(|_| Symbol::parse(context, input))?;
Ok(AdditiveTuple {
weight: weight as u32,
symbol: symbol,
@ -611,10 +615,11 @@ pub enum SpeakAs {
}
impl Parse for SpeakAs {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let mut is_spell_out = false;
let result = input.try(|input| {
match_ignore_ascii_case! { &input.expect_ident()?,
let result: Result<_, ParseError> = input.try(|input| {
let ident = input.expect_ident()?;
(match_ignore_ascii_case! { &ident,
"auto" => Ok(SpeakAs::Auto),
"bullets" => Ok(SpeakAs::Bullets),
"numbers" => Ok(SpeakAs::Numbers),
@ -624,14 +629,14 @@ impl Parse for SpeakAs {
Err(())
}
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
});
if is_spell_out {
// spell-out is not supported, but dont parse it as a <counter-style-name>.
// See bug 1024178.
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
result.or_else(|()| {
result.or_else(|_| {
Ok(SpeakAs::Other(parse_counter_style_name(input)?))
})
}

Просмотреть файл

@ -7,14 +7,15 @@
//! [custom]: https://drafts.csswg.org/css-variables/
use Atom;
use cssparser::{Delimiter, Parser, SourcePosition, Token, TokenSerializationType};
use cssparser::{Delimiter, Parser, ParserInput, SourcePosition, Token, TokenSerializationType};
use parser::ParserContext;
use properties::{CSSWideKeyword, DeclaredValue};
use selectors::parser::SelectorParseError;
use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
use std::fmt;
use style_traits::{HasViewportPercentage, ToCss};
use style_traits::{HasViewportPercentage, ToCss, StyleParseError, ParseError};
use stylearc::Arc;
/// A custom property name is just an `Atom`.
@ -131,7 +132,8 @@ impl ComputedValue {
impl SpecifiedValue {
/// Parse a custom property SpecifiedValue.
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Box<Self>, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Box<Self>, ParseError<'i>> {
let mut references = Some(HashSet::new());
let (first, css, last) = try!(parse_self_contained_declaration_value(input, &mut references));
Ok(Box::new(SpecifiedValue {
@ -146,7 +148,7 @@ impl SpecifiedValue {
/// Parse the value of a non-custom property that contains `var()` references.
pub fn parse_non_custom_with_var<'i, 't>
(input: &mut Parser<'i, 't>)
-> Result<(TokenSerializationType, Cow<'i, str>), ()> {
-> Result<(TokenSerializationType, Cow<'i, str>), ParseError<'i>> {
let (first_token_type, css, _) = try!(parse_self_contained_declaration_value(input, &mut None));
Ok((first_token_type, css))
}
@ -158,7 +160,7 @@ fn parse_self_contained_declaration_value<'i, 't>
TokenSerializationType,
Cow<'i, str>,
TokenSerializationType
), ()> {
), ParseError<'i>> {
let start_position = input.position();
let mut missing_closing_characters = String::new();
let (first, last) = try!(
@ -179,7 +181,7 @@ fn parse_declaration_value<'i, 't>
(input: &mut Parser<'i, 't>,
references: &mut Option<HashSet<Name>>,
missing_closing_characters: &mut String)
-> Result<(TokenSerializationType, TokenSerializationType), ()> {
-> Result<(TokenSerializationType, TokenSerializationType), ParseError<'i>> {
input.parse_until_before(Delimiter::Bang | Delimiter::Semicolon, |input| {
// Need at least one token
let start_position = input.position();
@ -192,14 +194,16 @@ fn parse_declaration_value<'i, 't>
/// Like parse_declaration_value, but accept `!` and `;` since they are only
/// invalid at the top level
fn parse_declaration_value_block(input: &mut Parser,
fn parse_declaration_value_block<'i, 't>
(input: &mut Parser<'i, 't>,
references: &mut Option<HashSet<Name>>,
missing_closing_characters: &mut String)
-> Result<(TokenSerializationType, TokenSerializationType), ()> {
-> Result<(TokenSerializationType, TokenSerializationType),
ParseError<'i>> {
let mut token_start = input.position();
let mut token = match input.next_including_whitespace_and_comments() {
Ok(token) => token,
Err(()) => return Ok((TokenSerializationType::nothing(), TokenSerializationType::nothing()))
Err(_) => return Ok((TokenSerializationType::nothing(), TokenSerializationType::nothing()))
};
let first_token_type = token.serialization_type();
loop {
@ -226,13 +230,16 @@ fn parse_declaration_value_block(input: &mut Parser,
}
token.serialization_type()
}
Token::BadUrl |
Token::BadString |
Token::CloseParenthesis |
Token::CloseSquareBracket |
Token::CloseCurlyBracket => {
return Err(())
}
Token::BadUrl =>
return Err(StyleParseError::BadUrlInDeclarationValueBlock.into()),
Token::BadString =>
return Err(StyleParseError::BadStringInDeclarationValueBlock.into()),
Token::CloseParenthesis =>
return Err(StyleParseError::UnbalancedCloseParenthesisInDeclarationValueBlock.into()),
Token::CloseSquareBracket =>
return Err(StyleParseError::UnbalancedCloseSquareBracketInDeclarationValueBlock.into()),
Token::CloseCurlyBracket =>
return Err(StyleParseError::UnbalancedCloseCurlyBracketInDeclarationValueBlock.into()),
Token::Function(ref name) => {
if name.eq_ignore_ascii_case("var") {
let position = input.position();
@ -303,9 +310,12 @@ fn parse_declaration_value_block(input: &mut Parser,
// If the var function is valid, return Ok((custom_property_name, fallback))
fn parse_var_function<'i, 't>(input: &mut Parser<'i, 't>,
references: &mut Option<HashSet<Name>>)
-> Result<(), ()> {
-> Result<(), ParseError<'i>> {
let name = try!(input.expect_ident());
let name = try!(parse_name(&name));
let name: Result<_, ParseError> =
parse_name(&name)
.map_err(|()| SelectorParseError::UnexpectedIdent(name.clone()).into());
let name = try!(name);
if input.try(|input| input.expect_comma()).is_ok() {
// Exclude `!` and `;` at the top level
// https://drafts.csswg.org/css-syntax/#typedef-declaration-value
@ -474,7 +484,8 @@ fn substitute_one(name: &Name,
}
let computed_value = if specified_value.references.map(|set| set.is_empty()) == Some(false) {
let mut partial_computed_value = ComputedValue::empty();
let mut input = Parser::new(&specified_value.css);
let mut input = ParserInput::new(&specified_value.css);
let mut input = Parser::new(&mut input);
let mut position = (input.position(), specified_value.first_token_type);
let result = substitute_block(
&mut input, &mut position, &mut partial_computed_value,
@ -525,11 +536,11 @@ fn substitute_one(name: &Name,
///
/// Return `Err(())` if `input` is invalid at computed-value time.
/// or `Ok(last_token_type that was pushed to partial_computed_value)` otherwise.
fn substitute_block<F>(input: &mut Parser,
position: &mut (SourcePosition, TokenSerializationType),
partial_computed_value: &mut ComputedValue,
substitute_one: &mut F)
-> Result<TokenSerializationType, ()>
fn substitute_block<'i, 't, F>(input: &mut Parser<'i, 't>,
position: &mut (SourcePosition, TokenSerializationType),
partial_computed_value: &mut ComputedValue,
substitute_one: &mut F)
-> Result<TokenSerializationType, ParseError<'i>>
where F: FnMut(&Name, &mut ComputedValue) -> Result<TokenSerializationType, ()> {
let mut last_token_type = TokenSerializationType::nothing();
let mut set_position_at_next_iteration = false;
@ -539,7 +550,7 @@ fn substitute_block<F>(input: &mut Parser,
if set_position_at_next_iteration {
*position = (before_this_token, match next {
Ok(ref token) => token.serialization_type(),
Err(()) => TokenSerializationType::nothing(),
Err(_) => TokenSerializationType::nothing(),
});
set_position_at_next_iteration = false;
}
@ -605,11 +616,12 @@ fn substitute_block<F>(input: &mut Parser,
/// Replace `var()` functions for a non-custom property.
/// Return `Err(())` for invalid at computed time.
pub fn substitute(input: &str, first_token_type: TokenSerializationType,
computed_values_map: &Option<Arc<HashMap<Name, ComputedValue>>>)
-> Result<String, ()> {
pub fn substitute<'i>(input: &'i str, first_token_type: TokenSerializationType,
computed_values_map: &Option<Arc<HashMap<Name, ComputedValue>>>)
-> Result<String, ParseError<'i>> {
let mut substituted = ComputedValue::empty();
let mut input = Parser::new(input);
let mut input = ParserInput::new(input);
let mut input = Parser::new(&mut input);
let mut position = (input.position(), first_token_type);
let last_token_type = try!(substitute_block(
&mut input, &mut position, &mut substituted, &mut |name, substituted| {

Просмотреть файл

@ -6,22 +6,150 @@
#![deny(missing_docs)]
use cssparser::{Parser, SourcePosition};
use cssparser::{Parser, SourcePosition, BasicParseError, Token, NumericValue, PercentageValue};
use cssparser::ParseError as CssParseError;
use log;
use style_traits::ParseError;
use stylesheets::UrlExtraData;
/// Errors that can be encountered while parsing CSS.
pub enum ContextualParseError<'a> {
/// A property declaration was not recognized.
UnsupportedPropertyDeclaration(&'a str, ParseError<'a>),
/// A font face descriptor was not recognized.
UnsupportedFontFaceDescriptor(&'a str, ParseError<'a>),
/// A keyframe rule was not valid.
InvalidKeyframeRule(&'a str, ParseError<'a>),
/// A keyframe property declaration was not recognized.
UnsupportedKeyframePropertyDeclaration(&'a str, ParseError<'a>),
/// A rule was invalid for some reason.
InvalidRule(&'a str, ParseError<'a>),
/// A rule was not recognized.
UnsupportedRule(&'a str, ParseError<'a>),
/// A viewport descriptor declaration was not recognized.
UnsupportedViewportDescriptorDeclaration(&'a str, ParseError<'a>),
/// A counter style descriptor declaration was not recognized.
UnsupportedCounterStyleDescriptorDeclaration(&'a str, ParseError<'a>),
/// A counter style rule had no symbols.
InvalidCounterStyleWithoutSymbols(String),
/// A counter style rule had less than two symbols.
InvalidCounterStyleNotEnoughSymbols(String),
/// A counter style rule did not have additive-symbols.
InvalidCounterStyleWithoutAdditiveSymbols,
/// A counter style rule had extends with symbols.
InvalidCounterStyleExtendsWithSymbols,
/// A counter style rule had extends with additive-symbols.
InvalidCounterStyleExtendsWithAdditiveSymbols
}
impl<'a> ContextualParseError<'a> {
/// Turn a parse error into a string representation.
pub fn to_string(&self) -> String {
fn token_to_str(t: &Token) -> String {
match *t {
Token::Ident(ref i) => format!("identifier {}", i),
Token::AtKeyword(ref kw) => format!("keyword @{}", kw),
Token::Hash(ref h) => format!("hash #{}", h),
Token::IDHash(ref h) => format!("id selector #{}", h),
Token::QuotedString(ref s) => format!("quoted string \"{}\"", s),
Token::UnquotedUrl(ref u) => format!("url {}", u),
Token::Delim(ref d) => format!("delimiter {}", d),
Token::Number(NumericValue { int_value: Some(i), .. }) => format!("number {}", i),
Token::Number(ref n) => format!("number {}", n.value),
Token::Percentage(PercentageValue { int_value: Some(i), .. }) => format!("percentage {}", i),
Token::Percentage(ref p) => format!("percentage {}", p.unit_value),
Token::Dimension(_, ref d) => format!("dimension {}", d),
Token::WhiteSpace(_) => format!("whitespace"),
Token::Comment(_) => format!("comment"),
Token::Colon => format!("colon (:)"),
Token::Semicolon => format!("semicolon (;)"),
Token::Comma => format!("comma (,)"),
Token::IncludeMatch => format!("include match (~=)"),
Token::DashMatch => format!("dash match (|=)"),
Token::PrefixMatch => format!("prefix match (^=)"),
Token::SuffixMatch => format!("suffix match ($=)"),
Token::SubstringMatch => format!("substring match (*=)"),
Token::Column => format!("column (||)"),
Token::CDO => format!("CDO (<!--)"),
Token::CDC => format!("CDC (-->)"),
Token::Function(ref f) => format!("function {}", f),
Token::ParenthesisBlock => format!("parenthesis ("),
Token::SquareBracketBlock => format!("square bracket ["),
Token::CurlyBracketBlock => format!("curly bracket {{"),
Token::BadUrl => format!("bad url parse error"),
Token::BadString => format!("bad string parse error"),
Token::CloseParenthesis => format!("unmatched close parenthesis"),
Token::CloseSquareBracket => format!("unmatched close square bracket"),
Token::CloseCurlyBracket => format!("unmatched close curly bracket"),
}
}
fn parse_error_to_str(err: &ParseError) -> String {
match *err {
CssParseError::Basic(BasicParseError::UnexpectedToken(ref t)) =>
format!("found unexpected {}", token_to_str(t)),
CssParseError::Basic(BasicParseError::ExpectedToken(ref t)) =>
format!("expected {}", token_to_str(t)),
CssParseError::Basic(BasicParseError::EndOfInput) =>
format!("unexpected end of input"),
CssParseError::Basic(BasicParseError::AtRuleInvalid) =>
format!("@ rule invalid"),
CssParseError::Basic(BasicParseError::QualifiedRuleInvalid) =>
format!("qualified rule invalid"),
CssParseError::Custom(ref err) =>
format!("{:?}", err)
}
}
match *self {
ContextualParseError::UnsupportedPropertyDeclaration(decl, ref err) =>
format!("Unsupported property declaration: '{}', {}", decl,
parse_error_to_str(err)),
ContextualParseError::UnsupportedFontFaceDescriptor(decl, ref err) =>
format!("Unsupported @font-face descriptor declaration: '{}', {}", decl,
parse_error_to_str(err)),
ContextualParseError::InvalidKeyframeRule(rule, ref err) =>
format!("Invalid keyframe rule: '{}', {}", rule,
parse_error_to_str(err)),
ContextualParseError::UnsupportedKeyframePropertyDeclaration(decl, ref err) =>
format!("Unsupported keyframe property declaration: '{}', {}", decl,
parse_error_to_str(err)),
ContextualParseError::InvalidRule(rule, ref err) =>
format!("Invalid rule: '{}', {}", rule, parse_error_to_str(err)),
ContextualParseError::UnsupportedRule(rule, ref err) =>
format!("Unsupported rule: '{}', {}", rule, parse_error_to_str(err)),
ContextualParseError::UnsupportedViewportDescriptorDeclaration(decl, ref err) =>
format!("Unsupported @viewport descriptor declaration: '{}', {}", decl,
parse_error_to_str(err)),
ContextualParseError::UnsupportedCounterStyleDescriptorDeclaration(decl, ref err) =>
format!("Unsupported @counter-style descriptor declaration: '{}', {}", decl,
parse_error_to_str(err)),
ContextualParseError::InvalidCounterStyleWithoutSymbols(ref system) =>
format!("Invalid @counter-style rule: 'system: {}' without 'symbols'", system),
ContextualParseError::InvalidCounterStyleNotEnoughSymbols(ref system) =>
format!("Invalid @counter-style rule: 'system: {}' less than two 'symbols'", system),
ContextualParseError::InvalidCounterStyleWithoutAdditiveSymbols =>
"Invalid @counter-style rule: 'system: additive' without 'additive-symbols'".into(),
ContextualParseError::InvalidCounterStyleExtendsWithSymbols =>
"Invalid @counter-style rule: 'system: extends …' with 'symbols'".into(),
ContextualParseError::InvalidCounterStyleExtendsWithAdditiveSymbols =>
"Invalid @counter-style rule: 'system: extends …' with 'additive-symbols'".into(),
}
}
}
/// A generic trait for an error reporter.
pub trait ParseErrorReporter : Sync + Send {
pub trait ParseErrorReporter : Sync {
/// Called when the style engine detects an error.
///
/// Returns the current input being parsed, the source position it was
/// reported from, and a message.
fn report_error(&self,
input: &mut Parser,
position: SourcePosition,
message: &str,
url: &UrlExtraData,
line_number_offset: u64);
fn report_error<'a>(&self,
input: &mut Parser,
position: SourcePosition,
error: ContextualParseError<'a>,
url: &UrlExtraData,
line_number_offset: u64);
}
/// An error reporter that uses [the `log` crate](https://github.com/rust-lang-nursery/log)
@ -33,16 +161,16 @@ pub trait ParseErrorReporter : Sync + Send {
pub struct RustLogReporter;
impl ParseErrorReporter for RustLogReporter {
fn report_error(&self,
input: &mut Parser,
position: SourcePosition,
message: &str,
url: &UrlExtraData,
line_number_offset: u64) {
fn report_error<'a>(&self,
input: &mut Parser,
position: SourcePosition,
error: ContextualParseError<'a>,
url: &UrlExtraData,
line_number_offset: u64) {
if log_enabled!(log::LogLevel::Info) {
let location = input.source_location(position);
let line_offset = location.line + line_number_offset as usize;
info!("Url:\t{}\n{}:{} {}", url.as_str(), line_offset, location.column, message)
info!("Url:\t{}\n{}:{} {}", url.as_str(), line_offset, location.column, error.to_string())
}
}
}
@ -51,12 +179,17 @@ impl ParseErrorReporter for RustLogReporter {
pub struct NullReporter;
impl ParseErrorReporter for NullReporter {
fn report_error(&self,
fn report_error<'a>(&self,
_: &mut Parser,
_: SourcePosition,
_: &str,
_: ContextualParseError<'a>,
_: &UrlExtraData,
_: u64) {
// do nothing
}
}
/// Create an instance of the default error reporter.
pub fn create_error_reporter() -> RustLogReporter {
RustLogReporter
}

Просмотреть файл

@ -13,12 +13,15 @@ use computed_values::{font_feature_settings, font_stretch, font_style, font_weig
use computed_values::font_family::FamilyName;
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
use cssparser::SourceLocation;
use error_reporting::ContextualParseError;
#[cfg(feature = "gecko")] use gecko_bindings::structs::CSSFontFaceDescriptors;
#[cfg(feature = "gecko")] use cssparser::UnicodeRange;
use parser::{ParserContext, log_css_error, Parse};
use selectors::parser::SelectorParseError;
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
use std::borrow::Cow;
use std::fmt;
use style_traits::{ToCss, OneOrMoreCommaSeparated};
use style_traits::{ToCss, OneOrMoreCommaSeparated, ParseError, StyleParseError};
use values::specified::url::SpecifiedUrl;
/// A source for a font-face rule.
@ -97,11 +100,11 @@ pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser, locati
};
let mut iter = DeclarationListParser::new(input, parser);
while let Some(declaration) = iter.next() {
if let Err(range) = declaration {
let pos = range.start;
let message = format!("Unsupported @font-face descriptor declaration: '{}'",
iter.input.slice(range));
log_css_error(iter.input, pos, &*message, context);
if let Err(err) = declaration {
let pos = err.span.start;
let error = ContextualParseError::UnsupportedFontFaceDescriptor(
iter.input.slice(err.span), err.error);
log_css_error(iter.input, pos, error, context);
}
}
}
@ -154,13 +157,15 @@ struct FontFaceRuleParser<'a, 'b: 'a> {
}
/// Default methods reject all at rules.
impl<'a, 'b> AtRuleParser for FontFaceRuleParser<'a, 'b> {
impl<'a, 'b, 'i> AtRuleParser<'i> for FontFaceRuleParser<'a, 'b> {
type Prelude = ();
type AtRule = ();
type Error = SelectorParseError<'i, StyleParseError<'i>>;
}
impl Parse for Source {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Source, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Source, ParseError<'i>> {
if input.try(|input| input.expect_function_matching("local")).is_ok() {
return input.parse_nested_block(|input| {
FamilyName::parse(context, input)
@ -247,11 +252,13 @@ macro_rules! font_face_descriptors_common {
}
}
impl<'a, 'b> DeclarationParser for FontFaceRuleParser<'a, 'b> {
type Declaration = ();
impl<'a, 'b, 'i> DeclarationParser<'i> for FontFaceRuleParser<'a, 'b> {
type Declaration = ();
type Error = SelectorParseError<'i, StyleParseError<'i>>;
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<(), ()> {
match_ignore_ascii_case! { name,
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
-> Result<(), ParseError<'i>> {
match_ignore_ascii_case! { &*name,
$(
$name => {
// DeclarationParser also calls parse_entirely
@ -262,7 +269,7 @@ macro_rules! font_face_descriptors_common {
self.rule.$ident = Some(value)
}
)*
_ => return Err(())
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
Ok(())
}

Просмотреть файл

@ -6,7 +6,7 @@
use app_units::Au;
use context::QuirksMode;
use cssparser::{CssStringWriter, Parser, RGBA, Token};
use cssparser::{CssStringWriter, Parser, RGBA, Token, BasicParseError};
use euclid::Size2D;
use font_metrics::get_metrics_provider_for_product;
use gecko::values::convert_nscolor_to_rgba;
@ -19,11 +19,12 @@ use media_queries::MediaType;
use parser::ParserContext;
use properties::{ComputedValues, StyleBuilder};
use properties::longhands::font_size;
use selectors::parser::SelectorParseError;
use std::fmt::{self, Write};
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
use str::starts_with_ignore_ascii_case;
use string_cache::Atom;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
use style_traits::viewport::ViewportConstraints;
use stylearc::Arc;
use values::{CSSFloat, specified};
@ -228,24 +229,25 @@ impl Resolution {
}
}
fn parse(input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let (value, unit) = match try!(input.next()) {
Token::Dimension(value, unit) => {
(value.value, unit)
(value, unit)
},
_ => return Err(()),
t => return Err(BasicParseError::UnexpectedToken(t).into()),
};
if value <= 0. {
return Err(())
let inner_value = value.value;
if inner_value <= 0. {
return Err(StyleParseError::UnspecifiedError.into())
}
Ok(match_ignore_ascii_case! { &unit,
"dpi" => Resolution::Dpi(value),
"dppx" => Resolution::Dppx(value),
"dpcm" => Resolution::Dpcm(value),
_ => return Err(())
})
(match_ignore_ascii_case! { &unit,
"dpi" => Ok(Resolution::Dpi(inner_value)),
"dppx" => Ok(Resolution::Dppx(inner_value)),
"dpcm" => Ok(Resolution::Dpcm(inner_value)),
_ => Err(())
}).map_err(|()| StyleParseError::UnexpectedDimension(unit).into())
}
}
@ -459,44 +461,51 @@ impl Expression {
/// ```
/// (media-feature: media-value)
/// ```
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
try!(input.expect_parenthesis_block());
input.parse_nested_block(|input| {
let ident = try!(input.expect_ident());
let mut flags = 0;
let mut feature_name = &*ident;
let result = {
let mut feature_name = &*ident;
// TODO(emilio): this is under a pref in Gecko.
if starts_with_ignore_ascii_case(feature_name, "-webkit-") {
feature_name = &feature_name[8..];
flags |= nsMediaFeature_RequirementFlags::eHasWebkitPrefix as u8;
}
// TODO(emilio): this is under a pref in Gecko.
if starts_with_ignore_ascii_case(feature_name, "-webkit-") {
feature_name = &feature_name[8..];
flags |= nsMediaFeature_RequirementFlags::eHasWebkitPrefix as u8;
}
let range = if starts_with_ignore_ascii_case(feature_name, "min-") {
feature_name = &feature_name[4..];
nsMediaExpression_Range::eMin
} else if starts_with_ignore_ascii_case(feature_name, "max-") {
feature_name = &feature_name[4..];
nsMediaExpression_Range::eMax
} else {
nsMediaExpression_Range::eEqual
};
let atom = Atom::from(feature_name);
let feature =
match find_feature(|f| atom.as_ptr() == unsafe { *f.mName }) {
Some(f) => f,
None => return Err(()),
let range = if starts_with_ignore_ascii_case(feature_name, "min-") {
feature_name = &feature_name[4..];
nsMediaExpression_Range::eMin
} else if starts_with_ignore_ascii_case(feature_name, "max-") {
feature_name = &feature_name[4..];
nsMediaExpression_Range::eMax
} else {
nsMediaExpression_Range::eEqual
};
let atom = Atom::from(feature_name);
match find_feature(|f| atom.as_ptr() == unsafe { *f.mName }) {
Some(f) => Ok((f, range)),
None => Err(()),
}
};
let (feature, range) = match result {
Ok((feature, range)) => (feature, range),
Err(()) => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
};
if (feature.mReqFlags & !flags) != 0 {
return Err(());
return Err(SelectorParseError::UnexpectedIdent(ident).into());
}
if range != nsMediaExpression_Range::eEqual &&
feature.mRangeType != nsMediaFeature_RangeType::eMinMaxAllowed {
return Err(());
return Err(SelectorParseError::UnexpectedIdent(ident).into());
}
// If there's no colon, this is a media query of the form
@ -506,7 +515,7 @@ impl Expression {
// reject them here too.
if input.try(|i| i.expect_colon()).is_err() {
if range != nsMediaExpression_Range::eEqual {
return Err(())
return Err(StyleParseError::RangedExpressionWithNoValue.into())
}
return Ok(Expression::new(feature, None, range));
}
@ -519,14 +528,14 @@ impl Expression {
nsMediaFeature_ValueType::eInteger => {
let i = input.expect_integer()?;
if i < 0 {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
MediaExpressionValue::Integer(i as u32)
}
nsMediaFeature_ValueType::eBoolInteger => {
let i = input.expect_integer()?;
if i < 0 || i > 1 {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
MediaExpressionValue::BoolInteger(i == 1)
}
@ -536,14 +545,14 @@ impl Expression {
nsMediaFeature_ValueType::eIntRatio => {
let a = input.expect_integer()?;
if a <= 0 {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
input.expect_delim('/')?;
let b = input.expect_integer()?;
if b <= 0 {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
MediaExpressionValue::IntRatio(a as u32, b as u32)
}
@ -566,7 +575,7 @@ impl Expression {
Some((_kw, value)) => {
value
}
None => return Err(()),
None => return Err(StyleParseError::UnspecifiedError.into()),
};
MediaExpressionValue::Enumerated(value)

Просмотреть файл

@ -8,11 +8,12 @@ use cssparser::{Parser, ToCss};
use element_state::ElementState;
use gecko_bindings::structs::CSSPseudoClassType;
use selector_parser::{SelectorParser, PseudoElementCascadeType};
use selectors::parser::{Selector, SelectorMethods};
use selectors::parser::{Selector, SelectorMethods, SelectorParseError};
use selectors::visitor::SelectorVisitor;
use std::borrow::Cow;
use std::fmt;
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
use style_traits::{ParseError, StyleParseError};
pub use gecko::pseudo_element::{PseudoElement, EAGER_PSEUDOS, EAGER_PSEUDO_COUNT};
pub use gecko::snapshot::SnapshotMap;
@ -238,17 +239,20 @@ impl ::selectors::SelectorImpl for SelectorImpl {
type NonTSPseudoClass = NonTSPseudoClass;
}
impl<'a> ::selectors::Parser for SelectorParser<'a> {
impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
type Impl = SelectorImpl;
type Error = StyleParseError<'i>;
fn parse_non_ts_pseudo_class(&self, name: Cow<str>) -> Result<NonTSPseudoClass, ()> {
fn parse_non_ts_pseudo_class(&self, name: Cow<'i, str>)
-> Result<NonTSPseudoClass, ParseError<'i>> {
macro_rules! pseudo_class_parse {
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*],
keyword: [$(($k_css:expr, $k_name:ident, $k_gecko_type:tt, $k_state:tt, $k_flags:tt),)*]) => {
match_ignore_ascii_case! { &name,
$($css => NonTSPseudoClass::$name,)*
_ => return Err(())
_ => return Err(::selectors::parser::SelectorParseError::UnexpectedIdent(
name.clone()).into())
}
}
}
@ -256,14 +260,14 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
if !pseudo_class.is_internal() || self.in_user_agent_stylesheet() {
Ok(pseudo_class)
} else {
Err(())
Err(SelectorParseError::UnexpectedIdent(name).into())
}
}
fn parse_non_ts_functional_pseudo_class(&self,
name: Cow<str>,
parser: &mut Parser)
-> Result<NonTSPseudoClass, ()> {
fn parse_non_ts_functional_pseudo_class<'t>(&self,
name: Cow<'i, str>,
parser: &mut Parser<'i, 't>)
-> Result<NonTSPseudoClass, ParseError<'i>> {
macro_rules! pseudo_class_string_parse {
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*],
@ -289,11 +293,11 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
})?;
// Selectors inside `:-moz-any` may not include combinators.
if selectors.iter().flat_map(|x| x.iter_raw()).any(|s| s.is_combinator()) {
return Err(())
return Err(SelectorParseError::UnexpectedIdent("-moz-any".into()).into())
}
NonTSPseudoClass::MozAny(selectors.into_boxed_slice())
}
_ => return Err(())
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
}
}
@ -301,13 +305,13 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
if !pseudo_class.is_internal() || self.in_user_agent_stylesheet() {
Ok(pseudo_class)
} else {
Err(())
Err(SelectorParseError::UnexpectedIdent(name).into())
}
}
fn parse_pseudo_element(&self, name: Cow<str>) -> Result<PseudoElement, ()> {
fn parse_pseudo_element(&self, name: Cow<'i, str>) -> Result<PseudoElement, ParseError<'i>> {
PseudoElement::from_slice(&name, self.in_user_agent_stylesheet())
.ok_or(())
.ok_or(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
fn default_namespace(&self) -> Option<Namespace> {

Просмотреть файл

@ -11,7 +11,7 @@ use gecko_bindings::sugar::refptr::RefPtr;
use parser::ParserContext;
use std::borrow::Cow;
use std::fmt::{self, Write};
use style_traits::ToCss;
use style_traits::{ToCss, ParseError};
use stylearc::Arc;
/// A specified url() value for gecko. Gecko does not eagerly resolve SpecifiedUrls.
@ -38,7 +38,7 @@ impl SpecifiedUrl {
/// Returns `Err` in the case that extra_data is incomplete.
pub fn parse_from_string<'a>(url: Cow<'a, str>,
context: &ParserContext)
-> Result<Self, ()> {
-> Result<Self, ParseError<'a>> {
Ok(SpecifiedUrl {
serialization: Arc::new(url.into_owned()),
extra_data: context.url_data.clone(),

Просмотреть файл

@ -21,7 +21,7 @@ use data::ElementData;
use dom::{self, DescendantsBit, LayoutIterator, NodeInfo, TElement, TNode, UnsafeNode};
use dom::{OpaqueNode, PresentationalHintsSynthesizer};
use element_state::ElementState;
use error_reporting::RustLogReporter;
use error_reporting::create_error_reporter;
use font_metrics::{FontMetrics, FontMetricsProvider, FontMetricsQueryResult};
use gecko::data::PerDocumentStyleData;
use gecko::global_style_data::GLOBAL_STYLE_DATA;
@ -416,7 +416,7 @@ impl<'le> GeckoElement<'le> {
pub fn parse_style_attribute(value: &str,
url_data: &UrlExtraData,
quirks_mode: QuirksMode) -> PropertyDeclarationBlock {
parse_style_attribute(value, url_data, &RustLogReporter, quirks_mode)
parse_style_attribute(value, url_data, &create_error_reporter(), quirks_mode)
}
fn flags(&self) -> u32 {

Просмотреть файл

@ -18,11 +18,14 @@ macro_rules! define_numbered_css_keyword_enum {
impl $crate::parser::Parse for $name {
#[allow(missing_docs)]
fn parse(_context: &$crate::parser::ParserContext, input: &mut ::cssparser::Parser) -> Result<$name, ()> {
match_ignore_ascii_case! { &try!(input.expect_ident()),
fn parse<'i, 't>(_context: &$crate::parser::ParserContext,
input: &mut ::cssparser::Parser<'i, 't>)
-> Result<$name, ::style_traits::ParseError<'i>> {
let ident = try!(input.expect_ident());
(match_ignore_ascii_case! { &ident,
$( $css => Ok($name::$variant), )+
_ => Err(())
}
}).map_err(|()| ::selectors::parser::SelectorParseError::UnexpectedIdent(ident).into())
}
}
@ -49,9 +52,9 @@ macro_rules! add_impls_for_keyword_enum {
($name:ident) => {
impl $crate::parser::Parse for $name {
#[inline]
fn parse(_context: &$crate::parser::ParserContext,
input: &mut ::cssparser::Parser)
-> Result<Self, ()> {
fn parse<'i, 't>(_context: &$crate::parser::ParserContext,
input: &mut ::cssparser::Parser<'i, 't>)
-> Result<Self, ::style_traits::ParseError<'i>> {
$name::parse(input)
}
}
@ -89,10 +92,10 @@ macro_rules! define_keyword_type {
}
impl $crate::parser::Parse for $name {
fn parse(_context: &$crate::parser::ParserContext,
input: &mut ::cssparser::Parser)
-> Result<$name, ()> {
input.expect_ident_matching($css).map(|_| $name)
fn parse<'i, 't>(_context: &$crate::parser::ParserContext,
input: &mut ::cssparser::Parser<'i, 't>)
-> Result<$name, ::style_traits::ParseError<'i>> {
input.expect_ident_matching($css).map(|_| $name).map_err(|e| e.into())
}
}

Просмотреть файл

@ -8,12 +8,13 @@
use Atom;
use context::QuirksMode;
use cssparser::{Delimiter, Parser, Token};
use cssparser::{Delimiter, Parser, Token, ParserInput};
use parser::ParserContext;
use selectors::parser::SelectorParseError;
use serialize_comma_separated_list;
use std::ascii::AsciiExt;
use std::fmt;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
#[cfg(feature = "servo")]
pub use servo::media_queries::{Device, Expression};
@ -209,7 +210,8 @@ impl MediaQuery {
/// Parse a media query given css input.
///
/// Returns an error if any of the expressions is unknown.
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<MediaQuery, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<MediaQuery, ParseError<'i>> {
let mut expressions = vec![];
let qualifier = if input.try(|input| input.expect_ident_matching("only")).is_ok() {
@ -221,11 +223,15 @@ impl MediaQuery {
};
let media_type = match input.try(|input| input.expect_ident()) {
Ok(ident) => try!(MediaQueryType::parse(&*ident)),
Err(()) => {
Ok(ident) => {
let result: Result<_, ParseError> = MediaQueryType::parse(&*ident)
.map_err(|()| SelectorParseError::UnexpectedIdent(ident).into());
try!(result)
}
Err(_) => {
// Media type is only optional if qualifier is not specified.
if qualifier.is_some() {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
// Without a media type, require at least one expression.
@ -270,7 +276,7 @@ pub fn parse_media_query_list(context: &ParserContext, input: &mut Parser) -> Me
match input.next() {
Ok(Token::Comma) => {},
Ok(_) => unreachable!(),
Err(()) => break,
Err(_) => break,
}
}
@ -311,7 +317,8 @@ impl MediaList {
///
/// Returns true if added, false if fail to parse the medium string.
pub fn append_medium(&mut self, context: &ParserContext, new_medium: &str) -> bool {
let mut parser = Parser::new(new_medium);
let mut input = ParserInput::new(new_medium);
let mut parser = Parser::new(&mut input);
let new_query = match MediaQuery::parse(&context, &mut parser) {
Ok(query) => query,
Err(_) => { return false; }
@ -329,7 +336,8 @@ impl MediaList {
///
/// Returns true if found and deleted, false otherwise.
pub fn delete_medium(&mut self, context: &ParserContext, old_medium: &str) -> bool {
let mut parser = Parser::new(old_medium);
let mut input = ParserInput::new(old_medium);
let mut parser = Parser::new(&mut input);
let old_query = match MediaQuery::parse(context, &mut parser) {
Ok(query) => query,
Err(_) => { return false; }

Просмотреть файл

@ -6,8 +6,8 @@
use context::QuirksMode;
use cssparser::{Parser, SourcePosition, UnicodeRange};
use error_reporting::ParseErrorReporter;
use style_traits::OneOrMoreCommaSeparated;
use error_reporting::{ParseErrorReporter, ContextualParseError};
use style_traits::{OneOrMoreCommaSeparated, ParseError};
use stylesheets::{CssRuleType, Origin, UrlExtraData, Namespaces};
bitflags! {
@ -164,14 +164,14 @@ impl<'a> ParserContext<'a> {
/// Defaults to a no-op.
/// Set a `RUST_LOG=style::errors` environment variable
/// to log CSS parse errors to stderr.
pub fn log_css_error(input: &mut Parser,
position: SourcePosition,
message: &str,
parsercontext: &ParserContext) {
pub fn log_css_error<'a>(input: &mut Parser,
position: SourcePosition,
error: ContextualParseError<'a>,
parsercontext: &ParserContext) {
let url_data = parsercontext.url_data;
let line_number_offset = parsercontext.line_number_offset;
parsercontext.error_reporter.report_error(input, position,
message, url_data,
error, url_data,
line_number_offset);
}
@ -183,19 +183,21 @@ pub trait Parse : Sized {
/// Parse a value of this type.
///
/// Returns an error on failure.
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()>;
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>>;
}
impl<T> Parse for Vec<T> where T: Parse + OneOrMoreCommaSeparated {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
input.parse_comma_separated(|input| T::parse(context, input))
}
}
/// Parse a non-empty space-separated or comma-separated list of objects parsed by parse_one
pub fn parse_space_or_comma_separated<F, T>(input: &mut Parser, mut parse_one: F)
-> Result<Vec<T>, ()>
where F: FnMut(&mut Parser) -> Result<T, ()> {
pub fn parse_space_or_comma_separated<'i, 't, F, T>(input: &mut Parser<'i, 't>, mut parse_one: F)
-> Result<Vec<T>, ParseError<'i>>
where F: for<'ii, 'tt> FnMut(&mut Parser<'ii, 'tt>) -> Result<T, ParseError<'ii>> {
let first = parse_one(input)?;
let mut vec = vec![first];
loop {
@ -209,7 +211,8 @@ pub fn parse_space_or_comma_separated<F, T>(input: &mut Parser, mut parse_one: F
Ok(vec)
}
impl Parse for UnicodeRange {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
UnicodeRange::parse(input)
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
UnicodeRange::parse(input).map_err(|e| e.into())
}
}

Просмотреть файл

@ -7,15 +7,16 @@
#![deny(missing_docs)]
use context::QuirksMode;
use cssparser::{DeclarationListParser, parse_important};
use cssparser::{DeclarationListParser, parse_important, ParserInput};
use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter};
use error_reporting::ParseErrorReporter;
use error_reporting::{ParseErrorReporter, ContextualParseError};
use parser::{PARSING_MODE_DEFAULT, ParsingMode, ParserContext, log_css_error};
use properties::animated_properties::AnimationValue;
use selectors::parser::SelectorParseError;
use shared_lock::Locked;
use std::fmt;
use std::slice::Iter;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
use stylesheets::{CssRuleType, Origin, UrlExtraData};
use stylesheets::{MallocSizeOf, MallocSizeOfFn};
use super::*;
@ -875,7 +876,8 @@ pub fn parse_style_attribute(input: &str,
Some(CssRuleType::Style),
PARSING_MODE_DEFAULT,
quirks_mode);
parse_property_declaration_list(&context, &mut Parser::new(input))
let mut input = ParserInput::new(input);
parse_property_declaration_list(&context, &mut Parser::new(&mut input))
}
/// Parse a given property declaration. Can result in multiple
@ -896,10 +898,11 @@ pub fn parse_one_declaration_into(declarations: &mut SourcePropertyDeclaration,
Some(CssRuleType::Style),
parsing_mode,
quirks_mode);
Parser::new(input).parse_entirely(|parser| {
let mut input = ParserInput::new(input);
Parser::new(&mut input).parse_entirely(|parser| {
PropertyDeclaration::parse_into(declarations, id, &context, parser)
.map_err(|_| ())
})
.map_err(|e| e.into())
}).map_err(|_| ())
}
/// A struct to parse property declarations.
@ -910,23 +913,26 @@ struct PropertyDeclarationParser<'a, 'b: 'a> {
/// Default methods reject all at rules.
impl<'a, 'b> AtRuleParser for PropertyDeclarationParser<'a, 'b> {
impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b> {
type Prelude = ();
type AtRule = Importance;
type Error = SelectorParseError<'i, StyleParseError<'i>>;
}
impl<'a, 'b> DeclarationParser for PropertyDeclarationParser<'a, 'b> {
impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> {
type Declaration = Importance;
type Error = SelectorParseError<'i, StyleParseError<'i>>;
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<Importance, ()> {
let id = try!(PropertyId::parse(name.into()));
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
-> Result<Importance, ParseError<'i>> {
let id = try!(PropertyId::parse(name));
input.parse_until_before(Delimiter::Bang, |input| {
PropertyDeclaration::parse_into(self.declarations, id, self.context, input)
.map_err(|_| ())
.map_err(|e| e.into())
})?;
let importance = match input.try(parse_important) {
Ok(()) => Importance::Important,
Err(()) => Importance::Normal,
Err(_) => Importance::Normal,
};
// In case there is still unparsed text in the declaration, we should roll back.
input.expect_exhausted()?;
@ -952,12 +958,12 @@ pub fn parse_property_declaration_list(context: &ParserContext,
Ok(importance) => {
block.extend(iter.parser.declarations.drain(), importance);
}
Err(range) => {
Err(err) => {
iter.parser.declarations.clear();
let pos = range.start;
let message = format!("Unsupported property declaration: '{}'",
iter.input.slice(range));
log_css_error(iter.input, pos, &*message, &context);
let pos = err.span.start;
let error = ContextualParseError::UnsupportedPropertyDeclaration(
iter.input.slice(err.span), err.error);
log_css_error(iter.input, pos, error, &context);
}
}
}

Просмотреть файл

@ -33,9 +33,9 @@
% endif
#[allow(unused_variables)]
#[inline]
pub fn parse(context: &ParserContext,
input: &mut Parser)
-> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
% if allow_quirks:
specified::${type}::${parse_method}_quirky(context, input, AllowQuirks::Yes)
% elif needs_context:
@ -87,12 +87,16 @@
pub mod single_value {
#[allow(unused_imports)]
use cssparser::Parser;
use cssparser::{Parser, BasicParseError};
#[allow(unused_imports)]
use parser::{Parse, ParserContext};
#[allow(unused_imports)]
use properties::ShorthandId;
#[allow(unused_imports)]
use selectors::parser::SelectorParseError;
#[allow(unused_imports)]
use style_traits::{ParseError, StyleParseError};
#[allow(unused_imports)]
use values::computed::{Context, ToComputedValue};
#[allow(unused_imports)]
use values::{computed, specified};
@ -207,7 +211,8 @@
% endif
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
#[allow(unused_imports)]
use parser::parse_space_or_comma_separated;
@ -266,7 +271,7 @@
pub mod ${property.ident} {
% if not property.derived_from:
#[allow(unused_imports)]
use cssparser::Parser;
use cssparser::{Parser, BasicParseError, Token};
#[allow(unused_imports)]
use parser::{Parse, ParserContext};
#[allow(unused_imports)]
@ -287,8 +292,12 @@
#[allow(unused_imports)]
use properties::style_structs;
#[allow(unused_imports)]
use selectors::parser::SelectorParseError;
#[allow(unused_imports)]
use stylearc::Arc;
#[allow(unused_imports)]
use style_traits::{ParseError, StyleParseError};
#[allow(unused_imports)]
use values::computed::{Context, ToComputedValue};
#[allow(unused_imports)]
use values::{computed, generics, specified};
@ -423,12 +432,12 @@
% endif
}
% if not property.derived_from:
pub fn parse_specified(context: &ParserContext, input: &mut Parser)
pub fn parse_specified<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
% if property.boxed:
-> Result<Box<SpecifiedValue>, ()> {
-> Result<Box<SpecifiedValue>, ParseError<'i>> {
parse(context, input).map(|result| Box::new(result))
% else:
-> Result<SpecifiedValue, ()> {
-> Result<SpecifiedValue, ParseError<'i>> {
% if property.allow_quirks:
parse_quirky(context, input, specified::AllowQuirks::Yes)
% else:
@ -436,11 +445,11 @@
% endif
% endif
}
pub fn parse_declared(context: &ParserContext, input: &mut Parser)
-> Result<PropertyDeclaration, ()> {
pub fn parse_declared<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<PropertyDeclaration, ParseError<'i>> {
match input.try(|i| CSSWideKeyword::parse(context, i)) {
Ok(keyword) => Ok(PropertyDeclaration::CSSWideKeyword(LonghandId::${property.camel_case}, keyword)),
Err(()) => {
Err(_) => {
input.look_for_var_functions();
let start = input.position();
let specified = parse_specified(context, input);
@ -487,7 +496,7 @@
use cssparser::Parser;
use parser::{Parse, ParserContext};
use style_traits::ToCss;
use style_traits::{ToCss, ParseError};
define_css_keyword_enum! { T:
% for value in keyword.values_for(product):
"${value}" => ${to_rust_ident(value)},
@ -495,7 +504,7 @@
}
impl Parse for T {
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
T::parse(input)
}
}
@ -518,7 +527,7 @@
}
}
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<SpecifiedValue, ParseError<'i>> {
Ok(SpecifiedValue::Keyword(computed_value::T::parse(input)?))
}
@ -716,14 +725,14 @@
SpecifiedValue::${to_rust_ident(values.split()[0])}
}
#[inline]
pub fn parse(_context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
SpecifiedValue::parse(input)
}
impl Parse for SpecifiedValue {
#[inline]
fn parse(_context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
SpecifiedValue::parse(input)
}
}
@ -764,9 +773,11 @@
use parser::ParserContext;
use properties::{PropertyDeclaration, SourcePropertyDeclaration, MaybeBoxed};
use properties::{ShorthandId, LonghandId, UnparsedValue, longhands};
#[allow(unused_imports)]
use selectors::parser::SelectorParseError;
use std::fmt;
use stylearc::Arc;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
pub struct Longhands {
% for sub_property in shorthand.sub_properties:
@ -838,8 +849,8 @@
/// Parse the given shorthand and fill the result into the
/// `declarations` vector.
pub fn parse_into(declarations: &mut SourcePropertyDeclaration,
context: &ParserContext, input: &mut Parser) -> Result<(), ()> {
pub fn parse_into<'i, 't>(declarations: &mut SourcePropertyDeclaration,
context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<(), ParseError<'i>> {
input.look_for_var_functions();
let start = input.position();
let value = input.parse_entirely(|input| parse_value(context, input));
@ -872,7 +883,7 @@
% endfor
Ok(())
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -890,7 +901,8 @@
use values::generics::rect::Rect;
use values::specified;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let rect = Rect::parse_with(context, input, |_c, i| {
% if allow_quirks:
${parser_function}_quirky(_c, i, specified::AllowQuirks::Yes)
@ -1114,7 +1126,8 @@
use values::computed::${length_type};
${length_type}::${initial_value}
}
fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
% if logical:
let ret = ${length_type}::parse(context, input);
% else:
@ -1123,7 +1136,7 @@
// Keyword values don't make sense in the block direction; don't parse them
% if "block" in name:
if let Ok(${length_type}::ExtremumLength(..)) = ret {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
% endif
ret.map(SpecifiedValue)

Просмотреть файл

@ -27,12 +27,13 @@ use properties::longhands::transform::computed_value::T as TransformList;
use properties::longhands::vertical_align::computed_value::T as VerticalAlign;
use properties::longhands::visibility::computed_value::T as Visibility;
#[cfg(feature = "gecko")] use properties::{PropertyDeclarationId, LonghandId};
use selectors::parser::SelectorParseError;
#[cfg(feature = "servo")] use servo_atoms::Atom;
use smallvec::SmallVec;
use std::cmp;
#[cfg(feature = "gecko")] use std::collections::HashMap;
use std::fmt;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError};
use super::ComputedValues;
use values::CSSFloat;
use values::{Auto, Either};
@ -99,9 +100,9 @@ impl TransitionProperty {
}
/// Parse a transition-property value.
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let ident = try!(input.expect_ident());
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"all" => Ok(TransitionProperty::All),
% for prop in data.longhands:
% if prop.animatable:
@ -118,7 +119,7 @@ impl TransitionProperty {
None => Ok(TransitionProperty::Unsupported((&*ident).into()))
}
}
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident.into()).into())
}
/// Get a transition property from a property declaration.
@ -476,7 +477,7 @@ impl AnimationValue {
/// Construct an AnimationValue from a property declaration
pub fn from_declaration(decl: &PropertyDeclaration, context: &mut Context,
initial: &ComputedValues) -> Option<Self> {
use error_reporting::RustLogReporter;
use error_reporting::create_error_reporter;
use properties::LonghandId;
use properties::DeclaredValue;
@ -539,7 +540,7 @@ impl AnimationValue {
},
PropertyDeclaration::WithVariables(id, ref variables) => {
let custom_props = context.style().custom_properties();
let reporter = RustLogReporter;
let reporter = create_error_reporter();
match id {
% for prop in data.longhands:
% if prop.animatable:

Просмотреть файл

@ -128,17 +128,20 @@ ${helpers.predefined_type("background-image", "ImageLayer",
}
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"repeat-x" => Ok(SpecifiedValue::RepeatX),
"repeat-y" => Ok(SpecifiedValue::RepeatY),
_ => {
let horizontal = try!(RepeatKeyword::from_ident(&ident));
let vertical = input.try(RepeatKeyword::parse).ok();
Ok(SpecifiedValue::Other(horizontal, vertical))
}
}
_ => Err(()),
}).or_else(|()| {
let horizontal: Result<_, ParseError> = RepeatKeyword::from_ident(&ident)
.map_err(|()| SelectorParseError::UnexpectedIdent(ident).into());
let horizontal = try!(horizontal);
let vertical = input.try(RepeatKeyword::parse).ok();
Ok(SpecifiedValue::Other(horizontal, vertical))
})
}
</%helpers:vector_longhand>

Просмотреть файл

@ -161,8 +161,8 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style',
}
#[inline]
pub fn parse(context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue::None)
}
@ -175,7 +175,7 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style',
if !result.is_empty() {
Ok(SpecifiedValue::Colors(result))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
</%helpers:longhand>
@ -272,7 +272,8 @@ ${helpers.predefined_type("border-image-outset", "LengthOrNumberRect",
}
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let first = try!(RepeatKeyword::parse(input));
let second = input.try(RepeatKeyword::parse).ok();

Просмотреть файл

@ -113,16 +113,17 @@
}
/// Parse a display value.
pub fn parse(_context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
match_ignore_ascii_case! { &try!(input.expect_ident()),
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let ident = try!(input.expect_ident());
(match_ignore_ascii_case! { &ident,
% for value in values:
"${value}" => {
Ok(computed_value::T::${to_rust_ident(value)})
},
% endfor
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
impl ComputedValueAsSpecified for SpecifiedValue {}
@ -292,16 +293,18 @@ ${helpers.single_keyword("position", "static absolute relative fixed",
}
/// baseline | sub | super | top | text-top | middle | bottom | text-bottom
/// | <percentage> | <length>
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
input.try(|i| specified::LengthOrPercentage::parse_quirky(context, i, AllowQuirks::Yes))
.map(SpecifiedValue::LengthOrPercentage)
.or_else(|_| {
match_ignore_ascii_case! { &try!(input.expect_ident()),
let ident = try!(input.expect_ident());
(match_ignore_ascii_case! { &ident,
% for keyword in vertical_align_keywords:
"${keyword}" => Ok(SpecifiedValue::${to_rust_ident(keyword)}),
% endfor
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
})
}
@ -500,17 +503,19 @@ ${helpers.predefined_type("transition-delay",
}
impl Parse for SpecifiedValue {
fn parse(context: &ParserContext, input: &mut ::cssparser::Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut ::cssparser::Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
if let Ok(name) = input.try(|input| KeyframesName::parse(context, input)) {
Ok(SpecifiedValue(Some(name)))
} else {
input.expect_ident_matching("none").map(|()| SpecifiedValue(None))
input.expect_ident_matching("none").map(|_| SpecifiedValue(None)).map_err(|e| e.into())
}
}
}
no_viewport_percentage!(SpecifiedValue);
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
SpecifiedValue::parse(context, input)
}
@ -560,14 +565,15 @@ ${helpers.predefined_type("animation-timing-function",
}
impl Parse for SpecifiedValue {
fn parse(_context: &ParserContext, input: &mut ::cssparser::Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut ::cssparser::Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("infinite")).is_ok() {
return Ok(SpecifiedValue::Infinite)
}
let number = try!(input.expect_number());
if number < 0.0 {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(SpecifiedValue::Number(number))
@ -587,7 +593,8 @@ ${helpers.predefined_type("animation-timing-function",
}
#[inline]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
SpecifiedValue::parse(context, input)
}
@ -948,8 +955,8 @@ ${helpers.predefined_type("scroll-snap-coordinate",
}
// Allow unitless zero angle for rotate() and skew() to align with gecko
fn parse_internal(context: &ParserContext, input: &mut Parser, prefixed: bool)
-> Result<SpecifiedValue,()> {
fn parse_internal<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>, prefixed: bool)
-> Result<SpecifiedValue,ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue(Vec::new()))
}
@ -960,7 +967,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
Ok(name) => name,
Err(_) => break,
};
match_ignore_ascii_case! {
let valid_fn = match_ignore_ascii_case! {
&name,
"matrix" => {
try!(input.parse_nested_block(|input| {
@ -970,7 +977,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
specified::parse_number(context, input)
}));
if values.len() != 6 {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
result.push(SpecifiedOperation::Matrix {
@ -981,7 +988,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
e: values[4],
f: values[5],
});
return Ok(());
return Ok(true);
}
// Non-standard prefixed matrix parsing.
@ -1014,7 +1021,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
e: lengths[0].clone(),
f: lengths[1].clone(),
});
Ok(())
Ok(true)
}))
},
"matrix3d" => {
@ -1023,7 +1030,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
if !prefixed {
let values = try!(input.parse_comma_separated(|i| specified::parse_number(context, i)));
if values.len() != 16 {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
result.push(SpecifiedOperation::Matrix3D {
@ -1032,7 +1039,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
m31: values[ 8], m32: values[ 9], m33: values[10], m34: values[11],
m41: values[12], m42: values[13], m43: values[14], m44: values[15]
});
return Ok(());
return Ok(true);
}
// Non-standard prefixed matrix3d parsing.
@ -1069,7 +1076,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
m41: lops[0].clone(), m42: lops[1].clone(), m43: length_or_number.unwrap(),
m44: values[12]
});
Ok(())
Ok(true)
}))
},
"translate" => {
@ -1081,28 +1088,28 @@ ${helpers.predefined_type("scroll-snap-coordinate",
} else {
result.push(SpecifiedOperation::Translate(sx, None));
}
Ok(())
Ok(true)
}))
},
"translatex" => {
try!(input.parse_nested_block(|input| {
let tx = try!(specified::LengthOrPercentage::parse(context, input));
result.push(SpecifiedOperation::TranslateX(tx));
Ok(())
Ok(true)
}))
},
"translatey" => {
try!(input.parse_nested_block(|input| {
let ty = try!(specified::LengthOrPercentage::parse(context, input));
result.push(SpecifiedOperation::TranslateY(ty));
Ok(())
Ok(true)
}))
},
"translatez" => {
try!(input.parse_nested_block(|input| {
let tz = try!(specified::Length::parse(context, input));
result.push(SpecifiedOperation::TranslateZ(tz));
Ok(())
Ok(true)
}))
},
"translate3d" => {
@ -1113,7 +1120,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
try!(input.expect_comma());
let tz = try!(specified::Length::parse(context, input));
result.push(SpecifiedOperation::Translate3D(tx, ty, tz));
Ok(())
Ok(true)
}))
},
"scale" => {
@ -1125,28 +1132,28 @@ ${helpers.predefined_type("scroll-snap-coordinate",
} else {
result.push(SpecifiedOperation::Scale(sx, None));
}
Ok(())
Ok(true)
}))
},
"scalex" => {
try!(input.parse_nested_block(|input| {
let sx = try!(specified::parse_number(context, input));
result.push(SpecifiedOperation::ScaleX(sx));
Ok(())
Ok(true)
}))
},
"scaley" => {
try!(input.parse_nested_block(|input| {
let sy = try!(specified::parse_number(context, input));
result.push(SpecifiedOperation::ScaleY(sy));
Ok(())
Ok(true)
}))
},
"scalez" => {
try!(input.parse_nested_block(|input| {
let sz = try!(specified::parse_number(context, input));
result.push(SpecifiedOperation::ScaleZ(sz));
Ok(())
Ok(true)
}))
},
"scale3d" => {
@ -1157,35 +1164,35 @@ ${helpers.predefined_type("scroll-snap-coordinate",
try!(input.expect_comma());
let sz = try!(specified::parse_number(context, input));
result.push(SpecifiedOperation::Scale3D(sx, sy, sz));
Ok(())
Ok(true)
}))
},
"rotate" => {
try!(input.parse_nested_block(|input| {
let theta = try!(specified::Angle::parse_with_unitless(context, input));
result.push(SpecifiedOperation::Rotate(theta));
Ok(())
Ok(true)
}))
},
"rotatex" => {
try!(input.parse_nested_block(|input| {
let theta = try!(specified::Angle::parse_with_unitless(context, input));
result.push(SpecifiedOperation::RotateX(theta));
Ok(())
Ok(true)
}))
},
"rotatey" => {
try!(input.parse_nested_block(|input| {
let theta = try!(specified::Angle::parse_with_unitless(context, input));
result.push(SpecifiedOperation::RotateY(theta));
Ok(())
Ok(true)
}))
},
"rotatez" => {
try!(input.parse_nested_block(|input| {
let theta = try!(specified::Angle::parse_with_unitless(context, input));
result.push(SpecifiedOperation::RotateZ(theta));
Ok(())
Ok(true)
}))
},
"rotate3d" => {
@ -1199,7 +1206,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
let theta = try!(specified::Angle::parse_with_unitless(context, input));
// TODO(gw): Check the axis can be normalized!!
result.push(SpecifiedOperation::Rotate3D(ax, ay, az, theta));
Ok(())
Ok(true)
}))
},
"skew" => {
@ -1211,51 +1218,56 @@ ${helpers.predefined_type("scroll-snap-coordinate",
} else {
result.push(SpecifiedOperation::Skew(theta_x, None));
}
Ok(())
Ok(true)
}))
},
"skewx" => {
try!(input.parse_nested_block(|input| {
let theta_x = try!(specified::Angle::parse_with_unitless(context, input));
result.push(SpecifiedOperation::SkewX(theta_x));
Ok(())
Ok(true)
}))
},
"skewy" => {
try!(input.parse_nested_block(|input| {
let theta_y = try!(specified::Angle::parse_with_unitless(context, input));
result.push(SpecifiedOperation::SkewY(theta_y));
Ok(())
Ok(true)
}))
},
"perspective" => {
try!(input.parse_nested_block(|input| {
let d = try!(specified::Length::parse_non_negative(context, input));
result.push(SpecifiedOperation::Perspective(d));
Ok(())
Ok(true)
}))
},
_ => return Err(())
_ => false
};
if !valid_fn {
return Err(StyleParseError::UnexpectedFunction(name).into());
}
}
if !result.is_empty() {
Ok(SpecifiedValue(result))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
/// Parses `transform` property.
#[inline]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
parse_internal(context, input, false)
}
/// Parses `-moz-transform` property. This prefixed property also accepts LengthOrPercentage
/// in the nondiagonal homogeneous components of matrix and matrix3d.
#[inline]
pub fn parse_prefixed(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse_prefixed<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
parse_internal(context, input, true)
}
@ -1771,7 +1783,8 @@ ${helpers.predefined_type("transform-origin",
}
/// none | strict | content | [ size || layout || style || paint ]
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut result = SpecifiedValue::empty();
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
@ -1784,21 +1797,22 @@ ${helpers.predefined_type("transform-origin",
while let Ok(name) = input.try(|input| input.expect_ident()) {
let flag = match_ignore_ascii_case! { &name,
"layout" => LAYOUT,
"style" => STYLE,
"paint" => PAINT,
_ => return Err(())
"layout" => Some(LAYOUT),
"style" => Some(STYLE),
"paint" => Some(PAINT),
_ => None
};
let flag = match flag {
Some(flag) if !result.contains(flag) => flag,
_ => return Err(SelectorParseError::UnexpectedIdent(name).into())
};
if result.contains(flag) {
return Err(())
}
result.insert(flag);
}
if !result.is_empty() {
Ok(result)
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
</%helpers:longhand>
@ -1900,18 +1914,23 @@ ${helpers.single_keyword("-moz-orient",
}
/// auto | <animateable-feature>#
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
Ok(computed_value::T::Auto)
} else {
input.parse_comma_separated(|i| {
let ident = i.expect_ident()?;
match_ignore_ascii_case! { &ident,
let bad_keyword = match_ignore_ascii_case! { &ident,
"will-change" | "none" | "all" | "auto" |
"initial" | "inherit" | "unset" | "default" => return Err(()),
_ => {},
"initial" | "inherit" | "unset" | "default" => true,
_ => false,
};
if bad_keyword {
Err(SelectorParseError::UnexpectedIdent(ident.into()).into())
} else {
Ok(Atom::from(ident))
}
Ok((Atom::from(ident)))
}).map(SpecifiedValue::AnimateableFeatures)
}
}
@ -1976,9 +1995,10 @@ ${helpers.predefined_type("shape-outside", "basic_shape::FloatAreaShape",
TOUCH_ACTION_AUTO
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"auto" => Ok(TOUCH_ACTION_AUTO),
"none" => Ok(TOUCH_ACTION_NONE),
"manipulation" => Ok(TOUCH_ACTION_MANIPULATION),
@ -1997,7 +2017,7 @@ ${helpers.predefined_type("shape-outside", "basic_shape::FloatAreaShape",
}
},
_ => Err(()),
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
#[cfg(feature = "gecko")]

Просмотреть файл

@ -43,7 +43,8 @@
pub fn get_initial_value() -> computed_value::T {
RGBA::new(0, 0, 0, 255) // black
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
Color::parse_quirky(context, input, AllowQuirks::Yes).map(SpecifiedValue)
}
@ -118,7 +119,7 @@
}
impl SystemColor {
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
#[cfg(feature = "gecko")]
use std::ascii::AsciiExt;
static PARSE_ARRAY: &'static [(&'static str, SystemColor); ${len(system_colors)}] = &[
@ -133,7 +134,7 @@
return Ok(color)
}
}
Err(())
Err(SelectorParseError::UnexpectedIdent(ident).into())
}
}
% endif

Просмотреть файл

@ -8,7 +8,6 @@
<%helpers:longhand name="content" boxed="True" animation_value_type="none"
spec="https://drafts.csswg.org/css-content/#propdef-content">
use cssparser::Token;
use values::computed::ComputedValueAsSpecified;
#[cfg(feature = "gecko")]
use values::generics::CounterStyleOrNone;
@ -157,8 +156,8 @@
// normal | none | [ <string> | <counter> | open-quote | close-quote | no-open-quote |
// no-close-quote ]+
// TODO: <uri>, attr(<identifier>)
pub fn parse(context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
return Ok(SpecifiedValue::Normal)
}
@ -185,43 +184,50 @@
content.push(ContentItem::String(value.into_owned()))
}
Ok(Token::Function(name)) => {
content.push(try!(match_ignore_ascii_case! { &name,
"counter" => input.parse_nested_block(|input| {
let result = match_ignore_ascii_case! { &name,
"counter" => Some(input.parse_nested_block(|input| {
let name = try!(input.expect_ident()).into_owned();
let style = parse_counter_style(context, input);
Ok(ContentItem::Counter(name, style))
}),
"counters" => input.parse_nested_block(|input| {
})),
"counters" => Some(input.parse_nested_block(|input| {
let name = try!(input.expect_ident()).into_owned();
try!(input.expect_comma());
let separator = try!(input.expect_string()).into_owned();
let style = parse_counter_style(context, input);
Ok(ContentItem::Counters(name, separator, style))
}),
})),
% if product == "gecko":
"attr" => input.parse_nested_block(|input| {
"attr" => Some(input.parse_nested_block(|input| {
Ok(ContentItem::Attr(Attr::parse_function(context, input)?))
}),
})),
% endif
_ => return Err(())
}));
_ => None
};
match result {
Some(result) => content.push(try!(result)),
None => return Err(StyleParseError::UnexpectedFunction(name).into())
}
}
Ok(Token::Ident(ident)) => {
match_ignore_ascii_case! { &ident,
"open-quote" => content.push(ContentItem::OpenQuote),
"close-quote" => content.push(ContentItem::CloseQuote),
"no-open-quote" => content.push(ContentItem::NoOpenQuote),
"no-close-quote" => content.push(ContentItem::NoCloseQuote),
let valid = match_ignore_ascii_case! { &ident,
"open-quote" => { content.push(ContentItem::OpenQuote); true },
"close-quote" => { content.push(ContentItem::CloseQuote); true },
"no-open-quote" => { content.push(ContentItem::NoOpenQuote); true },
"no-close-quote" => { content.push(ContentItem::NoCloseQuote); true },
_ => return Err(())
_ => false,
};
if !valid {
return Err(SelectorParseError::UnexpectedIdent(ident).into())
}
}
Err(_) => break,
_ => return Err(())
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into())
}
}
if content.is_empty() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(SpecifiedValue::Items(content))
}
@ -233,8 +239,6 @@
use style_traits::ToCss;
use values::CustomIdent;
use cssparser::Token;
#[derive(Debug, Clone, PartialEq)]
pub struct SpecifiedValue(pub Vec<(CustomIdent, specified::Integer)>);
@ -315,11 +319,13 @@
}
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
parse_common(context, 1, input)
}
pub fn parse_common(context: &ParserContext, default_value: i32, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse_common<'i, 't>(context: &ParserContext, default_value: i32, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue(Vec::new()))
}
@ -328,7 +334,7 @@
loop {
let counter_name = match input.next() {
Ok(Token::Ident(ident)) => CustomIdent::from_ident(ident, &["none"])?,
Ok(_) => return Err(()),
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
Err(_) => break,
};
let counter_delta = input.try(|input| specified::parse_integer(context, input))
@ -339,7 +345,7 @@
if !counters.is_empty() {
Ok(SpecifiedValue(counters))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
</%helpers:longhand>
@ -349,7 +355,8 @@
pub use super::counter_increment::{SpecifiedValue, computed_value, get_initial_value};
use super::counter_increment::parse_common;
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
parse_common(context, 0, input)
}
</%helpers:longhand>

Просмотреть файл

@ -27,7 +27,8 @@ ${helpers.predefined_type("opacity",
pub type T = Shadow;
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<specified::Shadow, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<specified::Shadow, ParseError<'i>> {
specified::Shadow::parse(context, input, false)
}
</%helpers:vector_longhand>
@ -263,7 +264,8 @@ ${helpers.predefined_type("clip",
computed_value::T::new(Vec::new())
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut filters = Vec::new();
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue(filters))
@ -290,23 +292,24 @@ ${helpers.predefined_type("clip",
"drop-shadow" => specified::Shadow::parse(context, input, true)
.map(SpecifiedFilter::DropShadow),
% endif
_ => Err(())
_ => Err(StyleParseError::UnexpectedFunction(function_name.clone()).into())
}
})));
} else if filters.is_empty() {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
} else {
return Ok(SpecifiedValue(filters))
}
}
}
fn parse_factor(input: &mut Parser) -> Result<::values::CSSFloat, ()> {
fn parse_factor<'i, 't>(input: &mut Parser<'i, 't>) -> Result<::values::CSSFloat, ParseError<'i>> {
use cssparser::Token;
match input.next() {
Ok(Token::Number(value)) if value.value.is_sign_positive() => Ok(value.value),
Ok(Token::Percentage(value)) if value.unit_value.is_sign_positive() => Ok(value.unit_value),
_ => Err(())
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
Err(e) => Err(e.into())
}
}

Просмотреть файл

@ -92,7 +92,7 @@ macro_rules! impl_gecko_keyword_from_trait {
use cssparser::{CssStringWriter, Parser, serialize_identifier};
use std::fmt::{self, Write};
use Atom;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError};
pub use self::FontFamily as SingleComputedValue;
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
@ -154,7 +154,7 @@ macro_rules! impl_gecko_keyword_from_trait {
}
/// Parse a font-family value
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if let Ok(value) = input.try(|input| input.expect_string()) {
return Ok(FontFamily::FamilyName(FamilyName {
name: Atom::from(&*value),
@ -294,7 +294,8 @@ macro_rules! impl_gecko_keyword_from_trait {
/// <family-name>#
/// <family-name> = <string> | [ <ident>+ ]
/// TODO: <generic-family>
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
SpecifiedValue::parse(input)
}
@ -348,7 +349,7 @@ macro_rules! impl_gecko_keyword_from_trait {
}
}
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
input.parse_comma_separated(|input| FontFamily::parse(input)).map(SpecifiedValue::Values)
}
}
@ -374,11 +375,11 @@ macro_rules! impl_gecko_keyword_from_trait {
/// `FamilyName::parse` is based on `FontFamily::parse` and not the other way around
/// because we want the former to exclude generic family keywords.
impl Parse for FamilyName {
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
match FontFamily::parse(input) {
Ok(FontFamily::FamilyName(name)) => Ok(name),
Ok(FontFamily::Generic(_)) |
Err(()) => Err(())
Ok(FontFamily::Generic(_)) => Err(StyleParseError::UnspecifiedError.into()),
Err(e) => Err(e)
}
}
}
@ -444,17 +445,21 @@ ${helpers.single_keyword_system("font-variant-caps",
}
/// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
input.try(|input| {
match_ignore_ascii_case! { &try!(input.expect_ident()),
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let result: Result<_, ParseError> = input.try(|input| {
let ident = try!(input.expect_ident());
(match_ignore_ascii_case! { &ident,
"normal" => Ok(SpecifiedValue::Normal),
"bold" => Ok(SpecifiedValue::Bold),
"bolder" => Ok(SpecifiedValue::Bolder),
"lighter" => Ok(SpecifiedValue::Lighter),
_ => Err(())
}
}).or_else(|()| {
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
});
result.or_else(|_| {
SpecifiedValue::from_int(input.expect_integer()?)
.map_err(|()| StyleParseError::UnspecifiedError.into())
})
}
@ -489,7 +494,7 @@ ${helpers.single_keyword_system("font-variant-caps",
/// Used in @font-face, where relative keywords are not allowed.
impl Parse for computed_value::T {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
match parse(context, input)? {
% for weight in range(100, 901, 100):
SpecifiedValue::Weight${weight} => Ok(computed_value::T::Weight${weight}),
@ -497,7 +502,7 @@ ${helpers.single_keyword_system("font-variant-caps",
SpecifiedValue::Normal => Ok(computed_value::T::Weight400),
SpecifiedValue::Bold => Ok(computed_value::T::Weight700),
SpecifiedValue::Bolder |
SpecifiedValue::Lighter => Err(()),
SpecifiedValue::Lighter => Err(StyleParseError::UnspecifiedError.into()),
SpecifiedValue::System(..) => unreachable!(),
}
}
@ -683,17 +688,18 @@ ${helpers.single_keyword_system("font-variant-caps",
pub use self::KeywordSize::*;
impl KeywordSize {
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
Ok(match_ignore_ascii_case! {&*input.expect_ident()?,
"xx-small" => XXSmall,
"x-small" => XSmall,
"small" => Small,
"medium" => Medium,
"large" => Large,
"x-large" => XLarge,
"xx-large" => XXLarge,
_ => return Err(())
})
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let ident = input.expect_ident()?;
(match_ignore_ascii_case! {&*ident,
"xx-small" => Ok(XXSmall),
"x-small" => Ok(XSmall),
"small" => Ok(Small),
"medium" => Ok(Medium),
"large" => Ok(Large),
"x-large" => Ok(XLarge),
"xx-large" => Ok(XXLarge),
_ => Err(())
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
}
@ -906,15 +912,16 @@ ${helpers.single_keyword_system("font-variant-caps",
}
/// <length> | <percentage> | <absolute-size> | <relative-size>
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
parse_quirky(context, input, AllowQuirks::No)
}
/// Parses a font-size, with quirks.
pub fn parse_quirky(context: &ParserContext,
input: &mut Parser,
allow_quirks: AllowQuirks)
-> Result<SpecifiedValue, ()> {
pub fn parse_quirky<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks)
-> Result<SpecifiedValue, ParseError<'i>> {
use self::specified::LengthOrPercentage;
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative_quirky(context, i, allow_quirks)) {
return Ok(SpecifiedValue::Length(lop))
@ -924,11 +931,12 @@ ${helpers.single_keyword_system("font-variant-caps",
return Ok(SpecifiedValue::Keyword(kw, 1.))
}
match_ignore_ascii_case! {&*input.expect_ident()?,
let ident = input.expect_ident()?;
(match_ignore_ascii_case! {&*ident,
"smaller" => Ok(SpecifiedValue::Smaller),
"larger" => Ok(SpecifiedValue::Larger),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
impl SpecifiedValue {
@ -1150,7 +1158,8 @@ ${helpers.single_keyword_system("font-variant-caps",
}
/// none | <number>
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
use values::specified::Number;
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
@ -1200,9 +1209,11 @@ ${helpers.single_keyword_system("font-variant-caps",
SpecifiedValue { weight: true, style: true }
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut result = SpecifiedValue { weight: false, style: false };
match_ignore_ascii_case! { &try!(input.expect_ident()),
let ident = try!(input.expect_ident());
(match_ignore_ascii_case! { &ident,
"none" => Ok(result),
"weight" => {
result.weight = true;
@ -1219,7 +1230,7 @@ ${helpers.single_keyword_system("font-variant-caps",
Ok(result)
},
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
#[cfg(feature = "gecko")]
@ -1364,7 +1375,8 @@ ${helpers.single_keyword_system("font-kerning",
/// swash(<feature-value-name>) ||
/// ornaments(<feature-value-name>) ||
/// annotation(<feature-value-name>) ]
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut result = VariantAlternates::empty();
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
@ -1373,25 +1385,26 @@ ${helpers.single_keyword_system("font-kerning",
while let Ok(ident) = input.try(|input| input.expect_ident()) {
let flag = match_ignore_ascii_case! { &ident,
"stylistic" => STYLISTIC,
"historical-forms" => HISTORICAL_FORMS,
"styleset" => STYLESET,
"character-variant" => CHARACTER_VARIANT,
"swash" => SWASH,
"ornaments" => ORNAMENTS,
"annotation" => ANNOTATION,
_ => return Err(()),
"stylistic" => Some(STYLISTIC),
"historical-forms" => Some(HISTORICAL_FORMS),
"styleset" => Some(STYLESET),
"character-variant" => Some(CHARACTER_VARIANT),
"swash" => Some(SWASH),
"ornaments" => Some(ORNAMENTS),
"annotation" => Some(ANNOTATION),
_ => None,
};
let flag = match flag {
Some(flag) if !result.intersects(flag) => flag,
_ => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
};
if result.intersects(flag) {
return Err(())
}
result.insert(flag);
}
if !result.is_empty() {
Ok(SpecifiedValue::Value(result))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
</%helpers:longhand>
@ -1400,9 +1413,9 @@ ${helpers.single_keyword_system("font-kerning",
macro_rules! exclusive_value {
(($value:ident, $set:expr) => $ident:ident) => {
if $value.intersects($set) {
return Err(())
None
} else {
$ident
Some($ident)
}
}
}
@ -1507,7 +1520,8 @@ macro_rules! exclusive_value {
/// <east-asian-width-values> = [ full-width | proportional-width ]
<% east_asian_variant_values = "JIS78 | JIS83 | JIS90 | JIS04 | SIMPLIFIED | TRADITIONAL" %>
<% east_asian_width_values = "FULL_WIDTH | PROPORTIONAL_WIDTH" %>
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut result = VariantEastAsian::empty();
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
@ -1534,7 +1548,11 @@ macro_rules! exclusive_value {
exclusive_value!((result, ${east_asian_width_values}) => PROPORTIONAL_WIDTH),
"ruby" =>
exclusive_value!((result, RUBY) => RUBY),
_ => return Err(()),
_ => None,
};
let flag = match flag {
Some(flag) => flag,
None => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
};
result.insert(flag);
}
@ -1542,7 +1560,7 @@ macro_rules! exclusive_value {
if !result.is_empty() {
Ok(SpecifiedValue::Value(result))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -1659,7 +1677,8 @@ macro_rules! exclusive_value {
<% discretionary_lig_values = "DISCRETIONARY_LIGATURES | NO_DISCRETIONARY_LIGATURES" %>
<% historical_lig_values = "HISTORICAL_LIGATURES | NO_HISTORICAL_LIGATURES" %>
<% contextual_alt_values = "CONTEXTUAL | NO_CONTEXTUAL" %>
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut result = VariantLigatures::empty();
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
@ -1687,7 +1706,11 @@ macro_rules! exclusive_value {
exclusive_value!((result, ${contextual_alt_values}) => CONTEXTUAL),
"no-contextual" =>
exclusive_value!((result, ${contextual_alt_values}) => NO_CONTEXTUAL),
_ => return Err(()),
_ => None,
};
let flag = match flag {
Some(flag) => flag,
None => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
};
result.insert(flag);
}
@ -1695,7 +1718,7 @@ macro_rules! exclusive_value {
if !result.is_empty() {
Ok(SpecifiedValue::Value(result))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -1808,7 +1831,8 @@ macro_rules! exclusive_value {
<% numeric_figure_values = "LINING_NUMS | OLDSTYLE_NUMS" %>
<% numeric_spacing_values = "PROPORTIONAL_NUMS | TABULAR_NUMS" %>
<% numeric_fraction_values = "DIAGONAL_FRACTIONS | STACKED_FRACTIONS" %>
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut result = VariantNumeric::empty();
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
@ -1824,16 +1848,20 @@ macro_rules! exclusive_value {
"lining-nums" =>
exclusive_value!((result, ${numeric_figure_values}) => LINING_NUMS ),
"oldstyle-nums" =>
exclusive_value!((result, ${numeric_figure_values}) => OLDSTYLE_NUMS ),
exclusive_value!((result, ${numeric_figure_values}) => OLDSTYLE_NUMS),
"proportional-nums" =>
exclusive_value!((result, ${numeric_spacing_values}) => PROPORTIONAL_NUMS ),
exclusive_value!((result, ${numeric_spacing_values}) => PROPORTIONAL_NUMS),
"tabular-nums" =>
exclusive_value!((result, ${numeric_spacing_values}) => TABULAR_NUMS ),
exclusive_value!((result, ${numeric_spacing_values}) => TABULAR_NUMS),
"diagonal-fractions" =>
exclusive_value!((result, ${numeric_fraction_values}) => DIAGONAL_FRACTIONS ),
exclusive_value!((result, ${numeric_fraction_values}) => DIAGONAL_FRACTIONS),
"stacked-fractions" =>
exclusive_value!((result, ${numeric_fraction_values}) => STACKED_FRACTIONS ),
_ => return Err(()),
exclusive_value!((result, ${numeric_fraction_values}) => STACKED_FRACTIONS),
_ => None,
};
let flag = match flag {
Some(flag) => flag,
None => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
};
result.insert(flag);
}
@ -1841,7 +1869,7 @@ macro_rules! exclusive_value {
if !result.is_empty() {
Ok(SpecifiedValue::Value(result))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -1890,7 +1918,8 @@ ${helpers.single_keyword_system("font-variant-position",
}
/// normal | <feature-tag-value>#
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
computed_value::T::parse(context, input).map(SpecifiedValue::Value)
}
</%helpers:longhand>
@ -1924,7 +1953,8 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
}
/// normal | <feature-tag-value>#
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
computed_value::T::parse(context, input)
}
</%helpers:longhand>
@ -2054,13 +2084,14 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
}
/// normal | <string>
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
Ok(SpecifiedValue::Normal)
} else {
input.expect_string().map(|cow| {
SpecifiedValue::Override(cow.into_owned())
})
}).map_err(|e| e.into())
}
}
@ -2108,9 +2139,10 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
computed_value::T(atom!(""))
}
pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, _input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
debug_assert!(false, "Should be set directly by presentation attributes only.");
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
</%helpers:longhand>
@ -2133,9 +2165,10 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
::gecko_bindings::structs::NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER as f32
}
pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, _input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
debug_assert!(false, "Should be set directly by presentation attributes only.");
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
</%helpers:longhand>
@ -2206,7 +2239,8 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
}
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if let Ok(i) = input.try(|i| i.expect_integer()) {
return Ok(SpecifiedValue::Relative(i))
}
@ -2281,9 +2315,10 @@ ${helpers.single_keyword("-moz-math-variant",
Au((NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT as f32 * AU_PER_PT) as i32)
}
pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, _input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
debug_assert!(false, "Should be set directly by presentation attributes only.");
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
</%helpers:longhand>
@ -2308,7 +2343,9 @@ ${helpers.single_keyword("-moz-math-variant",
use app_units::Au;
use cssparser::Parser;
use properties::longhands;
use selectors::parser::SelectorParseError;
use std::hash::{Hash, Hasher};
use style_traits::ParseError;
use values::computed::{ToComputedValue, Context};
<%
system_fonts = """caption icon menu message-box small-caption status-bar
@ -2427,13 +2464,14 @@ ${helpers.single_keyword("-moz-math-variant",
}
impl SystemFont {
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
Ok(match_ignore_ascii_case! { &*input.expect_ident()?,
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let ident = input.expect_ident()?;
(match_ignore_ascii_case! { &*ident,
% for font in system_fonts:
"${font}" => SystemFont::${to_camel_case(font)},
"${font}" => Ok(SystemFont::${to_camel_case(font)}),
% endfor
_ => return Err(())
})
_ => Err(())
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
}
}

Просмотреть файл

@ -174,7 +174,8 @@ ${helpers.single_keyword("image-rendering",
}
// from-image | <angle> | [<angle>? flip]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("from-image")).is_ok() {
// Handle from-image
Ok(SpecifiedValue { angle: None, flipped: false })
@ -185,7 +186,7 @@ ${helpers.single_keyword("image-rendering",
// Handle <angle> | <angle> flip
let angle = input.try(|input| Angle::parse(context, input)).ok();
if angle.is_none() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
let flipped = input.try(|input| input.expect_ident_matching("flip")).is_ok();

Просмотреть файл

@ -183,7 +183,8 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)",
}
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
if let Ok(()) = input.try(|i| i.expect_ident_matching("normal")) {
Ok(SpecifiedValue(0))
} else {
@ -195,33 +196,34 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)",
loop {
let result = input.try(|i| {
match_ignore_ascii_case! { &i.expect_ident()?,
let result: Result<_, ParseError> = input.try(|i| {
let ident = i.expect_ident()?;
(match_ignore_ascii_case! { &ident,
"fill" => Ok(FILL),
"stroke" => Ok(STROKE),
"markers" => Ok(MARKERS),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident.into()).into())
});
match result {
Ok(val) => {
if (seen & (1 << val)) != 0 {
// don't parse the same ident twice
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
} else {
value |= val << (pos * SHIFT);
seen |= 1 << val;
pos += 1;
}
}
Err(()) => break,
Err(_) => break,
}
}
if value == 0 {
// couldn't find any keyword
Err(())
Err(StyleParseError::UnspecifiedError.into())
} else {
// fill in rest
for i in pos..COUNT {
@ -285,7 +287,8 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)",
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let i = input.expect_ident()?;
CustomIdent::from_ident(i, &["all", "none", "auto"])
}

Просмотреть файл

@ -113,11 +113,12 @@ ${helpers.single_keyword("caption-side", "top bottom",
}
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
let mut first = None;
let mut second = None;
match Length::parse_non_negative_quirky(context, input, AllowQuirks::Yes) {
Err(()) => (),
Err(_) => (),
Ok(length) => {
first = Some(length);
if let Ok(len) = input.try(|i| Length::parse_non_negative_quirky(context, i, AllowQuirks::Yes)) {
@ -126,7 +127,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
}
}
match (first, second) {
(None, None) => Err(()),
(None, None) => Err(StyleParseError::UnspecifiedError.into()),
(Some(length), None) => {
Ok(SpecifiedValue {
horizontal: length,

Просмотреть файл

@ -179,7 +179,8 @@ ${helpers.single_keyword("text-align-last",
MatchParent,
MozCenterOrInherit,
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
// MozCenterOrInherit cannot be parsed, only set directly on th elements
if let Ok(key) = input.try(computed_value::T::parse) {
Ok(SpecifiedValue::Keyword(key))
@ -255,7 +256,8 @@ ${helpers.single_keyword("text-align-last",
use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {}
pub use self::computed_value::T as SpecifiedValue;
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
computed_value::T::parse(input)
}
% endif
@ -415,7 +417,8 @@ ${helpers.predefined_type("word-spacing",
pub type T = Shadow;
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<specified::Shadow, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<specified::Shadow, ParseError<'i>> {
specified::Shadow::parse(context, input, true)
}
</%helpers:vector_longhand>
@ -577,7 +580,8 @@ ${helpers.predefined_type("word-spacing",
}
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue::None);
}
@ -603,7 +607,7 @@ ${helpers.predefined_type("word-spacing",
(Some(fill), Ok(shape)) => KeywordValue::FillAndShape(fill,shape),
(Some(fill), Err(_)) => KeywordValue::Fill(fill),
(None, Ok(shape)) => KeywordValue::Shape(shape),
_ => return Err(()),
_ => return Err(StyleParseError::UnspecifiedError.into()),
};
Ok(SpecifiedValue::Keyword(keyword_value))
}
@ -636,7 +640,8 @@ ${helpers.predefined_type("word-spacing",
SpecifiedValue(HorizontalWritingModeValue::Over, VerticalWritingModeValue::Right)
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if let Ok(horizontal) = input.try(|input| HorizontalWritingModeValue::parse(input)) {
let vertical = try!(VerticalWritingModeValue::parse(input));
Ok(SpecifiedValue(horizontal, vertical))

Просмотреть файл

@ -89,7 +89,8 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
SpecifiedValue::CounterStyle(CounterStyleOrNone::disc())
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
Ok(if let Ok(style) = input.try(|i| CounterStyleOrNone::parse(context, i)) {
SpecifiedValue::CounterStyle(style)
} else {
@ -126,7 +127,8 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
pub fn get_initial_specified_value() -> SpecifiedValue {
SpecifiedValue(Either::Second(None_))
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
% if product == "gecko":
let mut value = input.try(|input| UrlOrNone::parse(context, input))?;
if let Either::First(ref mut url) = value {
@ -142,7 +144,6 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
<%helpers:longhand name="quotes" animation_value_type="none"
spec="https://drafts.csswg.org/css-content/#propdef-quotes">
use cssparser::Token;
use std::borrow::Cow;
use std::fmt;
use style_traits::ToCss;
@ -187,7 +188,8 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
])
}
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue(Vec::new()))
}
@ -196,19 +198,20 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
loop {
let first = match input.next() {
Ok(Token::QuotedString(value)) => value.into_owned(),
Ok(_) => return Err(()),
Err(()) => break,
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
Err(_) => break,
};
let second = match input.next() {
Ok(Token::QuotedString(value)) => value.into_owned(),
_ => return Err(()),
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
Err(e) => return Err(e.into()),
};
quotes.push((first, second))
}
if !quotes.is_empty() {
Ok(SpecifiedValue(quotes))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
</%helpers:longhand>

Просмотреть файл

@ -46,14 +46,15 @@ ${helpers.predefined_type("outline-color", "Color", "computed_value::T::currentc
pub type T = super::SpecifiedValue;
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
SpecifiedValue::parse(context, input)
.and_then(|result| {
if let Either::Second(BorderStyle::hidden) = result {
// The outline-style property accepts the same values as
// border-style, except that 'hidden' is not a legal outline
// style.
Err(())
Err(SelectorParseError::UnexpectedIdent("hidden".into()).into())
} else {
Ok(result)
}

Просмотреть файл

@ -91,37 +91,43 @@
}
impl Parse for computed_value::Keyword {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<computed_value::Keyword, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<computed_value::Keyword, ParseError<'i>> {
use std::ascii::AsciiExt;
use style_traits::cursor::Cursor;
let ident = try!(input.expect_ident());
if ident.eq_ignore_ascii_case("auto") {
Ok(computed_value::Keyword::Auto)
} else {
Cursor::from_css_keyword(&ident).map(computed_value::Keyword::Cursor)
Cursor::from_css_keyword(&ident)
.map(computed_value::Keyword::Cursor)
.map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
}
}
#[cfg(feature = "gecko")]
fn parse_image(context: &ParserContext, input: &mut Parser) -> Result<computed_value::Image, ()> {
fn parse_image<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<computed_value::Image, ParseError<'i>> {
Ok(computed_value::Image {
url: try!(SpecifiedUrl::parse(context, input)),
hotspot: match input.try(|input| input.expect_number()) {
Ok(number) => Some((number, try!(input.expect_number()))),
Err(()) => None,
Err(_) => None,
},
})
}
#[cfg(not(feature = "gecko"))]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
computed_value::Keyword::parse(context, input)
}
/// cursor: [<url> [<number> <number>]?]# [auto | default | ...]
#[cfg(feature = "gecko")]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut images = vec![];
loop {
match input.try(|input| parse_image(context, input)) {
@ -129,7 +135,7 @@
image.url.build_image_value();
images.push(image)
}
Err(()) => break,
Err(_) => break,
}
try!(input.expect_comma());
}

Просмотреть файл

@ -339,27 +339,32 @@ ${helpers.predefined_type("object-position",
}
/// [ row | column ] || dense
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
use self::computed_value::AutoFlow;
let mut value = None;
let mut dense = false;
while !input.is_exhausted() {
match_ignore_ascii_case! { &input.expect_ident()?,
let ident = input.expect_ident()?;
let success = match_ignore_ascii_case! { &ident,
"row" if value.is_none() => {
value = Some(AutoFlow::Row);
continue
true
},
"column" if value.is_none() => {
value = Some(AutoFlow::Column);
continue
true
},
"dense" if !dense => {
dense = true;
continue
true
},
_ => return Err(())
_ => false
};
if !success {
return Err(SelectorParseError::UnexpectedIdent(ident).into());
}
}
@ -369,7 +374,7 @@ ${helpers.predefined_type("object-position",
dense: dense,
})
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -435,7 +440,8 @@ ${helpers.predefined_type("object-position",
Either::Second(None_)
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
SpecifiedValue::parse(context, input)
}
@ -457,13 +463,15 @@ ${helpers.predefined_type("object-position",
impl ComputedValueAsSpecified for TemplateAreas {}
impl Parse for TemplateAreas {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
let mut strings = vec![];
while let Ok(string) = input.try(Parser::expect_string) {
strings.push(string.into_owned().into_boxed_str());
}
TemplateAreas::from_vec(strings)
.map_err(|()| StyleParseError::UnspecifiedError.into())
}
}

Просмотреть файл

@ -129,7 +129,8 @@ ${helpers.single_keyword("mask-origin",
background_size::get_initial_value()
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
background_size::parse(context, input)
}
</%helpers:longhand>

Просмотреть файл

@ -40,7 +40,8 @@ ${helpers.single_keyword("table-layout", "auto fixed",
}
// never parse it, only set via presentation attribute
fn parse(_: &ParserContext, _: &mut Parser) -> Result<SpecifiedValue, ()> {
Err(())
fn parse<'i, 't>(_: &ParserContext, _: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
Err(StyleParseError::UnspecifiedError.into())
}
</%helpers:longhand>

Просмотреть файл

@ -104,7 +104,8 @@
sides_are_logical: true,
}
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let first = try!(Side::parse(context, input));
let second = input.try(|input| Side::parse(context, input)).ok();
Ok(SpecifiedValue {
@ -113,13 +114,14 @@
})
}
impl Parse for Side {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Side, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Side, ParseError<'i>> {
if let Ok(ident) = input.try(|input| input.expect_ident()) {
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"clip" => Ok(Side::Clip),
"ellipsis" => Ok(Side::Ellipsis),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
} else {
Ok(Side::String(try!(input.expect_string()).into_owned().into_boxed_str()))
}
@ -216,34 +218,39 @@ ${helpers.single_keyword("unicode-bidi",
SpecifiedValue::empty()
}
/// none | [ underline || overline || line-through || blink ]
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let mut result = SpecifiedValue::empty();
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(result)
}
let mut empty = true;
while input.try(|input| {
if let Ok(ident) = input.expect_ident() {
match_ignore_ascii_case! { &ident,
"underline" => if result.contains(UNDERLINE) { return Err(()) }
else { empty = false; result.insert(UNDERLINE) },
"overline" => if result.contains(OVERLINE) { return Err(()) }
else { empty = false; result.insert(OVERLINE) },
"line-through" => if result.contains(LINE_THROUGH) { return Err(()) }
else { empty = false; result.insert(LINE_THROUGH) },
"blink" => if result.contains(BLINK) { return Err(()) }
else { empty = false; result.insert(BLINK) },
_ => return Err(())
loop {
let result: Result<_, ParseError> = input.try(|input| {
match input.expect_ident() {
Ok(ident) => {
(match_ignore_ascii_case! { &ident,
"underline" => if result.contains(UNDERLINE) { Err(()) }
else { empty = false; result.insert(UNDERLINE); Ok(()) },
"overline" => if result.contains(OVERLINE) { Err(()) }
else { empty = false; result.insert(OVERLINE); Ok(()) },
"line-through" => if result.contains(LINE_THROUGH) { Err(()) }
else { empty = false; result.insert(LINE_THROUGH); Ok(()) },
"blink" => if result.contains(BLINK) { Err(()) }
else { empty = false; result.insert(BLINK); Ok(()) },
_ => Err(())
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
} else {
return Err(());
Err(e) => return Err(e.into())
}
Ok(())
}).is_ok() {
});
if result.is_err() {
break;
}
}
if !empty { Ok(result) } else { Err(()) }
if !empty { Ok(result) } else { Err(StyleParseError::UnspecifiedError.into()) }
}
% if product == "servo":

Просмотреть файл

@ -76,11 +76,12 @@ ${helpers.single_keyword("-moz-window-shadow", "none default menu tooltip sheet"
impl ComputedValueAsSpecified for SpecifiedValue {}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
match try!(input.expect_integer()) {
0 => Ok(computed_value::T(false)),
1 => Ok(computed_value::T(true)),
_ => Err(()),
_ => Err(StyleParseError::UnspecifiedError.into()),
}
}

Просмотреть файл

@ -20,6 +20,7 @@ use stylearc::{Arc, UniqueArc};
use app_units::Au;
#[cfg(feature = "servo")] use cssparser::RGBA;
use cssparser::{Parser, TokenSerializationType, serialize_identifier};
use cssparser::ParserInput;
use error_reporting::ParseErrorReporter;
#[cfg(feature = "servo")] use euclid::side_offsets::SideOffsets2D;
use computed_values;
@ -33,9 +34,10 @@ use media_queries::Device;
use parser::{PARSING_MODE_DEFAULT, Parse, ParserContext};
use properties::animated_properties::TransitionProperty;
#[cfg(feature = "gecko")] use properties::longhands::system_font::SystemFont;
use selectors::parser::SelectorParseError;
#[cfg(feature = "servo")] use servo_config::prefs::PREFS;
use shared_lock::StylesheetGuards;
use style_traits::{HasViewportPercentage, ToCss};
use style_traits::{HasViewportPercentage, ToCss, ParseError, PropertyDeclarationParseError};
use stylesheets::{CssRuleType, MallocSizeOf, MallocSizeOfFn, Origin, UrlExtraData};
#[cfg(feature = "servo")] use values::Either;
use values::generics::text::LineHeight;
@ -185,6 +187,7 @@ macro_rules! unwrap_or_initial {
pub mod shorthands {
use cssparser::Parser;
use parser::{Parse, ParserContext};
use style_traits::{ParseError, StyleParseError};
use values::specified;
<%include file="/shorthand/serialize.mako.rs" />
@ -213,9 +216,11 @@ pub mod shorthands {
use parser::ParserContext;
use properties::{SourcePropertyDeclaration, AllShorthand, ShorthandId, UnparsedValue};
use stylearc::Arc;
use style_traits::{ParseError, StyleParseError};
pub fn parse_into(declarations: &mut SourcePropertyDeclaration,
context: &ParserContext, input: &mut Parser) -> Result<(), ()> {
pub fn parse_into<'i, 't>(declarations: &mut SourcePropertyDeclaration,
context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<(), ParseError<'i>> {
// This function is like the parse() that is generated by
// helpers:shorthand, but since the only values for the 'all'
// shorthand when not just a single CSS-wide keyword is one
@ -239,7 +244,7 @@ pub mod shorthands {
}));
Ok(())
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
}
@ -414,6 +419,7 @@ impl PropertyDeclarationIdSet {
{
f(&
::custom_properties::substitute(css, first_token_type, custom_properties)
.ok()
.and_then(|css| {
// As of this writing, only the base URL is used for property values:
//
@ -425,7 +431,8 @@ impl PropertyDeclarationIdSet {
None,
PARSING_MODE_DEFAULT,
quirks_mode);
Parser::new(&css).parse_entirely(|input| {
let mut input = ParserInput::new(&css);
Parser::new(&mut input).parse_entirely(|input| {
match from_shorthand {
None => {
longhands::${property.ident}
@ -434,7 +441,7 @@ impl PropertyDeclarationIdSet {
Some(ShorthandId::All) => {
// No need to parse the 'all' shorthand as anything other than a CSS-wide
// keyword, after variable substitution.
Err(())
Err(SelectorParseError::UnexpectedIdent("all".into()).into())
}
% for shorthand in data.shorthands_except_all():
% if property in shorthand.sub_properties:
@ -448,7 +455,7 @@ impl PropertyDeclarationIdSet {
% endfor
_ => unreachable!()
}
})
}).ok()
})
.unwrap_or(
// Invalid at computed-value time.
@ -500,10 +507,11 @@ impl CSSWideKeyword {
}
impl Parse for CSSWideKeyword {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let ident = input.expect_ident()?;
input.expect_exhausted()?;
CSSWideKeyword::from_ident(&ident).ok_or(())
CSSWideKeyword::from_ident(&ident)
.ok_or(SelectorParseError::UnexpectedIdent(ident).into())
}
}
@ -946,7 +954,7 @@ impl PropertyId {
/// Returns a given property from the string `s`.
///
/// Returns Err(()) for unknown non-custom properties
pub fn parse(property_name: Cow<str>) -> Result<Self, ()> {
pub fn parse<'i>(property_name: Cow<'i, str>) -> Result<Self, ParseError<'i>> {
if let Ok(name) = ::custom_properties::parse_name(&property_name) {
return Ok(PropertyId::Custom(::custom_properties::Name::from(name)))
}
@ -971,7 +979,7 @@ impl PropertyId {
match static_id(&property_name) {
Some(&StaticId::Longhand(id)) => Ok(PropertyId::Longhand(id)),
Some(&StaticId::Shorthand(id)) => Ok(PropertyId::Shorthand(id)),
None => Err(()),
None => Err(SelectorParseError::UnexpectedIdent(property_name).into()),
}
}
@ -1095,24 +1103,6 @@ impl HasViewportPercentage for PropertyDeclaration {
}
}
/// The result of parsing a property declaration.
#[derive(Eq, PartialEq, Copy, Clone)]
pub enum PropertyDeclarationParseError {
/// The property declaration was for an unknown property.
UnknownProperty,
/// The property declaration was for a disabled experimental property.
ExperimentalProperty,
/// The property declaration contained an invalid value.
InvalidValue,
/// The declaration contained an animation property, and we were parsing
/// this as a keyframe block (so that property should be ignored).
///
/// See: https://drafts.csswg.org/css-animations/#keyframes
AnimationPropertyInKeyframeBlock,
/// The property is not allowed within a page rule.
NotAllowedInPageRule,
}
impl fmt::Debug for PropertyDeclaration {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(self.id().to_css(f));
@ -1407,9 +1397,9 @@ impl PropertyDeclaration {
PropertyId::Custom(name) => {
let value = match input.try(|i| CSSWideKeyword::parse(context, i)) {
Ok(keyword) => DeclaredValueOwned::CSSWideKeyword(keyword),
Err(()) => match ::custom_properties::SpecifiedValue::parse(context, input) {
Err(_) => match ::custom_properties::SpecifiedValue::parse(context, input) {
Ok(value) => DeclaredValueOwned::Value(value),
Err(()) => return Err(PropertyDeclarationParseError::InvalidValue),
Err(_) => return Err(PropertyDeclarationParseError::InvalidValue),
}
};
declarations.push(PropertyDeclaration::Custom(name, value));
@ -1442,7 +1432,7 @@ impl PropertyDeclaration {
declarations.push(value);
Ok(())
},
Err(()) => Err(PropertyDeclarationParseError::InvalidValue),
Err(_) => Err(PropertyDeclarationParseError::InvalidValue),
}
% else:
Err(PropertyDeclarationParseError::UnknownProperty)
@ -1485,9 +1475,9 @@ impl PropertyDeclaration {
% endif
Ok(())
},
Err(()) => {
Err(_) => {
shorthands::${shorthand.ident}::parse_into(declarations, context, input)
.map_err(|()| PropertyDeclarationParseError::InvalidValue)
.map_err(|_| PropertyDeclarationParseError::InvalidValue)
}
}
}

Просмотреть файл

@ -32,7 +32,8 @@
}
}
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut background_color = None;
% for name in "image position_x position_y repeat size attachment origin clip".split():
@ -42,7 +43,7 @@
// background-color can only be in the last element, so if it
// is parsed anywhere before, the value is invalid.
if background_color.is_some() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
% for name in "image position repeat size attachment origin clip".split():
@ -107,7 +108,7 @@
% endfor
Ok(())
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}));
@ -194,7 +195,8 @@
use values::specified::AllowQuirks;
use values::specified::position::Position;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut position_x = background_position_x::SpecifiedValue(Vec::new());
let mut position_y = background_position_y::SpecifiedValue(Vec::new());
let mut any = false;
@ -207,7 +209,7 @@
Ok(())
})?;
if !any {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(expanded! {

Просмотреть файл

@ -20,7 +20,8 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style",
use values::generics::rect::Rect;
use values::specified::{AllowQuirks, BorderSideWidth};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let rect = Rect::parse_with(context, input, |_, i| {
BorderSideWidth::parse_quirky(context, i, AllowQuirks::Yes)
})?;
@ -43,10 +44,10 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style",
</%helpers:shorthand>
pub fn parse_border(context: &ParserContext, input: &mut Parser)
-> Result<(specified::Color,
specified::BorderStyle,
specified::BorderSideWidth), ()> {
pub fn parse_border<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<(specified::Color,
specified::BorderStyle,
specified::BorderSideWidth), ParseError<'i>> {
use values::specified::{Color, BorderStyle, BorderSideWidth};
let _unused = context;
let mut color = None;
@ -82,7 +83,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
style.unwrap_or(BorderStyle::none),
width.unwrap_or(BorderSideWidth::Medium)))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -101,7 +102,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
alias="${maybe_moz_logical_alias(product, (side, logical), '-moz-border-%s')}"
spec="${spec}">
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let (color, style, width) = try!(super::parse_border(context, input));
Ok(expanded! {
border_${to_rust_ident(side)}_color: color,
@ -139,7 +141,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
_moz_border_bottom_colors, _moz_border_left_colors};
% endif
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
use properties::longhands::{border_image_outset, border_image_repeat, border_image_slice};
use properties::longhands::{border_image_source, border_image_width};
@ -209,7 +212,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
use values::specified::border::BorderRadius;
use parser::Parse;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let radii = try!(BorderRadius::parse(context, input));
Ok(expanded! {
border_top_left_radius: radii.top_left,
@ -242,12 +246,13 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
use properties::longhands::{border_image_outset, border_image_repeat, border_image_slice};
use properties::longhands::{border_image_source, border_image_width};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
% for name in "outset repeat slice source width".split():
let mut border_image_${name} = border_image_${name}::get_initial_specified_value();
% endfor
try!(input.try(|input| {
let result: Result<_, ParseError> = input.try(|input| {
% for name in "outset repeat slice source width".split():
let mut ${name} = None;
% endfor
@ -256,7 +261,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
if let Ok(value) = input.try(|input| border_image_slice::parse(context, input)) {
slice = Some(value);
// Parse border image width and outset, if applicable.
let maybe_width_outset: Result<_, ()> = input.try(|input| {
let maybe_width_outset: Result<_, ParseError> = input.try(|input| {
try!(input.expect_delim('/'));
// Parse border image width, if applicable.
@ -269,7 +274,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
border_image_outset::parse(context, input)
}).ok();
if w.is_none() && o.is_none() {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
else {
Ok((w, o))
@ -305,9 +310,10 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
% endfor
Ok(())
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}));
});
try!(result);
Ok(expanded! {
% for name in "outset repeat slice source width".split():

Просмотреть файл

@ -11,29 +11,33 @@
use properties::longhands::overflow_x::SpecifiedValue;
% endif
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
% if product == "gecko":
let moz_kw_found = input.try(|i| match_ignore_ascii_case! {
&i.expect_ident()?,
"-moz-scrollbars-horizontal" => {
Ok(expanded! {
overflow_x: SpecifiedValue::scroll,
overflow_y: SpecifiedValue::hidden,
})
}
"-moz-scrollbars-vertical" => {
Ok(expanded! {
overflow_x: SpecifiedValue::hidden,
overflow_y: SpecifiedValue::scroll,
})
}
"-moz-scrollbars-none" => {
Ok(expanded! {
overflow_x: SpecifiedValue::hidden,
overflow_y: SpecifiedValue::hidden,
})
}
_ => Err(())
let moz_kw_found = input.try(|i| {
let ident = i.expect_ident()?;
(match_ignore_ascii_case! {
&ident,
"-moz-scrollbars-horizontal" => {
Ok(expanded! {
overflow_x: SpecifiedValue::scroll,
overflow_y: SpecifiedValue::hidden,
})
}
"-moz-scrollbars-vertical" => {
Ok(expanded! {
overflow_x: SpecifiedValue::hidden,
overflow_y: SpecifiedValue::scroll,
})
}
"-moz-scrollbars-none" => {
Ok(expanded! {
overflow_x: SpecifiedValue::hidden,
overflow_y: SpecifiedValue::hidden,
})
}
_ => Err(())
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
});
if moz_kw_found.is_ok() {
return moz_kw_found
@ -88,14 +92,16 @@ macro_rules! try_parse_one {
use properties::longhands::transition_${prop};
% endfor
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
struct SingleTransition {
% for prop in "property duration timing_function delay".split():
transition_${prop}: transition_${prop}::SingleSpecifiedValue,
% endfor
}
fn parse_one_transition(context: &ParserContext, input: &mut Parser) -> Result<SingleTransition,()> {
fn parse_one_transition<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SingleTransition,ParseError<'i>> {
% for prop in "property duration timing_function delay".split():
let mut ${prop} = None;
% endfor
@ -123,7 +129,7 @@ macro_rules! try_parse_one {
% endfor
})
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -202,14 +208,16 @@ macro_rules! try_parse_one {
use properties::longhands::animation_${prop};
% endfor
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
struct SingleAnimation {
% for prop in props:
animation_${prop}: animation_${prop}::SingleSpecifiedValue,
% endfor
}
fn parse_one_animation(context: &ParserContext, input: &mut Parser) -> Result<SingleAnimation,()> {
fn parse_one_animation<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SingleAnimation,ParseError<'i>> {
% for prop in props:
let mut ${prop} = None;
% endfor
@ -237,7 +245,7 @@ macro_rules! try_parse_one {
// If nothing is parsed, this is an invalid entry.
if parsed == 0 {
Err(())
Err(StyleParseError::UnspecifiedError.into())
} else {
Ok(SingleAnimation {
% for prop in props:
@ -303,7 +311,8 @@ macro_rules! try_parse_one {
spec="https://drafts.csswg.org/css-scroll-snap/#propdef-scroll-snap-type">
use properties::longhands::scroll_snap_type_x;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let result = try!(scroll_snap_type_x::parse(context, input));
Ok(expanded! {
scroll_snap_type_x: result,
@ -331,7 +340,8 @@ macro_rules! try_parse_one {
spec="Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/transform">
use properties::longhands::transform;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
Ok(expanded! {
transform: transform::parse_prefixed(context, input)?,
})

Просмотреть файл

@ -8,7 +8,8 @@
extra_prefixes="moz" spec="https://drafts.csswg.org/css-multicol/#propdef-columns">
use properties::longhands::{column_count, column_width};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut column_count = None;
let mut column_width = None;
@ -40,7 +41,7 @@
let values = autos + column_count.iter().len() + column_width.iter().len();
if values == 0 || values > 2 {
Err(())
Err(StyleParseError::UnspecifiedError.into())
} else {
Ok(expanded! {
column_count: unwrap_or_initial!(column_count),
@ -65,7 +66,8 @@
use properties::longhands::{column_rule_width, column_rule_style};
use properties::longhands::column_rule_color;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
% for name in "width style color".split():
let mut column_rule_${name} = None;
% endfor
@ -92,7 +94,7 @@
column_rule_color: unwrap_or_initial!(column_rule_color),
})
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}

Просмотреть файл

@ -38,7 +38,8 @@
% endif
use self::font_family::SpecifiedValue as FontFamily;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut nb_normals = 0;
let mut style = None;
let mut variant_caps = None;
@ -97,7 +98,7 @@
}
if size.is_none() ||
(count(&style) + count(&weight) + count(&variant_caps) + count(&stretch) + nb_normals) > 4 {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
let line_height = if input.try(|input| input.expect_delim('/')).is_ok() {
Some(try!(LineHeight::parse(context, input)))
@ -239,7 +240,8 @@
% endfor
% endif
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut nb_normals = 0;
let mut caps = None;
loop {
@ -264,7 +266,7 @@
}
let count = count(&caps) + nb_normals;
if count == 0 || count > 1 {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
Ok(expanded! {
font_variant_caps: unwrap_or_initial!(font_variant_caps, caps),

Просмотреть файл

@ -9,7 +9,8 @@
spec="https://www.w3.org/TR/SVG2/painting.html#MarkerShorthand">
use values::specified::UrlOrNone;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
use parser::Parse;
let url = UrlOrNone::parse(context, input)?;

Просмотреть файл

@ -9,7 +9,8 @@
spec="https://drafts.csswg.org/css-text-decor-3/#text-emphasis-property">
use properties::longhands::{text_emphasis_color, text_emphasis_style};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut color = None;
let mut style = None;
@ -34,7 +35,7 @@
text_emphasis_style: unwrap_or_initial!(text_emphasis_style, style),
})
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -56,7 +57,8 @@
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke">
use properties::longhands::{_webkit_text_stroke_color, _webkit_text_stroke_width};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut color = None;
let mut width = None;
loop {
@ -82,7 +84,7 @@
_webkit_text_stroke_width: unwrap_or_initial!(_webkit_text_stroke_width, width),
})
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}

Просмотреть файл

@ -10,7 +10,8 @@
use properties::longhands::{list_style_image, list_style_position, list_style_type};
use values::{Either, None_};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
// `none` is ambiguous until we've finished parsing the shorthands, so we count the number
// of times we see it.
let mut nones = 0u8;
@ -19,7 +20,7 @@
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
nones = nones + 1;
if nones > 2 {
return Err(())
return Err(SelectorParseError::UnexpectedIdent("none".into()).into())
}
any = true;
continue
@ -104,7 +105,7 @@
list_style_type: unwrap_or_initial!(list_style_type),
})
}
_ => Err(()),
_ => Err(StyleParseError::UnspecifiedError.into()),
}
}

Просмотреть файл

@ -35,7 +35,8 @@
}
}
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
% for name in "image mode position_x position_y size repeat origin clip composite".split():
let mut mask_${name} = mask_${name}::SpecifiedValue(Vec::new());
% endfor
@ -103,7 +104,7 @@
% endfor
Ok(())
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}));
@ -180,7 +181,8 @@
use values::specified::position::Position;
use parser::Parse;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut position_x = mask_position_x::SpecifiedValue(Vec::new());
let mut position_y = mask_position_y::SpecifiedValue(Vec::new());
let mut any = false;
@ -193,7 +195,7 @@
Ok(())
})?;
if any == false {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(expanded! {

Просмотреть файл

@ -10,7 +10,8 @@
use values::specified;
use parser::Parse;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let _unused = context;
let mut color = None;
let mut style = None;
@ -47,7 +48,7 @@
outline_width: unwrap_or_initial!(outline_width, width),
})
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -71,7 +72,8 @@
use values::specified::border::BorderRadius;
use parser::Parse;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let radii = try!(BorderRadius::parse(context, input));
Ok(expanded! {
_moz_outline_radius_topleft: radii.top_left,

Просмотреть файл

@ -8,7 +8,8 @@
spec="https://drafts.csswg.org/css-flexbox/#flex-flow-property">
use properties::longhands::{flex_direction, flex_wrap};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut direction = None;
let mut wrap = None;
loop {
@ -28,7 +29,7 @@
}
if direction.is_none() && wrap.is_none() {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
Ok(expanded! {
flex_direction: unwrap_or_initial!(flex_direction, direction),
@ -50,14 +51,15 @@
spec="https://drafts.csswg.org/css-flexbox/#flex-property">
use values::specified::Number;
fn parse_flexibility(context: &ParserContext, input: &mut Parser)
-> Result<(Number, Option<Number>),()> {
fn parse_flexibility<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<(Number, Option<Number>),ParseError<'i>> {
let grow = try!(Number::parse_non_negative(context, input));
let shrink = input.try(|i| Number::parse_non_negative(context, i)).ok();
Ok((grow, shrink))
}
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut grow = None;
let mut shrink = None;
let mut basis = None;
@ -87,7 +89,7 @@
}
if grow.is_none() && basis.is_none() {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
Ok(expanded! {
flex_grow: grow.unwrap_or(Number::new(1.0)),
@ -118,7 +120,8 @@
products="gecko">
use properties::longhands::{grid_row_gap, grid_column_gap};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let row_gap = grid_row_gap::parse(context, input)?;
let column_gap = input.try(|input| grid_column_gap::parse(context, input)).unwrap_or(row_gap.clone());
@ -152,7 +155,8 @@
// NOTE: Since both the shorthands have the same code, we should (re-)use code from one to implement
// the other. This might not be a big deal for now, but we should consider looking into this in the future
// to limit the amount of code generated.
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let start = input.try(|i| GridLine::parse(context, i))?;
let end = if input.try(|i| i.expect_delim('/')).is_ok() {
GridLine::parse(context, input)?
@ -189,7 +193,8 @@
use parser::Parse;
// The code is the same as `grid-{row,column}` except that this can have four values at most.
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
fn line_with_ident_from(other: &GridLine) -> GridLine {
let mut this = GridLine::default();
if other.line_num.is_none() && !other.is_span {
@ -259,8 +264,9 @@
use values::specified::grid::parse_line_names;
/// Parsing for `<grid-template>` shorthand (also used by `grid` shorthand).
pub fn parse_grid_template(context: &ParserContext, input: &mut Parser)
-> Result<(TrackListOrNone, TrackListOrNone, Either<TemplateAreas, None_>), ()> {
pub fn parse_grid_template<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<(TrackListOrNone, TrackListOrNone, Either<TemplateAreas, None_>),
ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
return Ok((Either::Second(None_), Either::Second(None_), Either::Second(None_)))
}
@ -295,7 +301,8 @@
line_names.push(vec![]); // should be one longer than track sizes
}
let template_areas = TemplateAreas::from_vec(strings)?;
let template_areas = TemplateAreas::from_vec(strings)
.map_err(|()| StyleParseError::UnspecifiedError)?;
let template_rows = TrackList {
list_type: TrackListType::Normal,
values: values,
@ -306,7 +313,7 @@
let template_cols = if input.try(|i| i.expect_delim('/')).is_ok() {
let track_list = TrackList::parse(context, input)?;
if track_list.list_type != TrackListType::Explicit {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
Either::First(track_list)
@ -326,7 +333,8 @@
}
#[inline]
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let (rows, columns, areas) = parse_grid_template(context, input)?;
Ok(expanded! {
grid_template_rows: rows,
@ -410,7 +418,8 @@
use values::{Either, None_};
use values::specified::{LengthOrPercentage, TrackSize};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let mut temp_rows = Either::Second(None_);
let mut temp_cols = Either::Second(None_);
let mut temp_areas = Either::Second(None_);
@ -418,7 +427,8 @@
let mut auto_cols = TrackSize::default();
let mut flow = grid_auto_flow::get_initial_value();
fn parse_auto_flow(input: &mut Parser, is_row: bool) -> Result<SpecifiedAutoFlow, ()> {
fn parse_auto_flow<'i, 't>(input: &mut Parser<'i, 't>, is_row: bool)
-> Result<SpecifiedAutoFlow, ParseError<'i>> {
let mut auto_flow = None;
let mut dense = false;
for _ in 0..2 {
@ -440,7 +450,7 @@
autoflow: flow,
dense: dense,
}
}).ok_or(())
}).ok_or(StyleParseError::UnspecifiedError.into())
}
if let Ok((rows, cols, areas)) = input.try(|i| super::grid_template::parse_grid_template(context, i)) {
@ -506,15 +516,16 @@
use properties::longhands::align_content;
use properties::longhands::justify_content;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let align = align_content::parse(context, input)?;
if align.has_extra_flags() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
let justify = input.try(|input| justify_content::parse(context, input))
.unwrap_or(justify_content::SpecifiedValue::from(align));
if justify.has_extra_flags() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(expanded! {
@ -541,14 +552,15 @@
use values::specified::align::AlignJustifySelf;
use parser::Parse;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let align = AlignJustifySelf::parse(context, input)?;
if align.has_extra_flags() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
let justify = input.try(|input| AlignJustifySelf::parse(context, input)).unwrap_or(align.clone());
if justify.has_extra_flags() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(expanded! {
@ -582,15 +594,16 @@
}
}
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
let align = AlignItems::parse(context, input)?;
if align.has_extra_flags() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
let justify = input.try(|input| JustifyItems::parse(context, input))
.unwrap_or(JustifyItems::from(align));
if justify.has_extra_flags() {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(expanded! {

Просмотреть файл

@ -16,7 +16,8 @@
use properties::longhands::text_decoration_line;
% endif
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Longhands, ParseError<'i>> {
% if product == "gecko" or data.testing:
let (mut line, mut style, mut color, mut any) = (None, None, None, false);
% else:
@ -47,7 +48,7 @@
}
if !any {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(expanded! {

Просмотреть файл

@ -6,10 +6,11 @@
#![deny(missing_docs)]
use cssparser::Parser as CssParser;
use cssparser::{Parser as CssParser, ParserInput};
use selectors::Element;
use selectors::parser::SelectorList;
use std::fmt::Debug;
use style_traits::ParseError;
use stylesheets::{Origin, Namespaces};
/// A convenient alias for the type that represents an attribute value used for
@ -59,13 +60,14 @@ impl<'a> SelectorParser<'a> {
///
/// This is used for some DOM APIs like `querySelector`.
pub fn parse_author_origin_no_namespace(input: &str)
-> Result<SelectorList<SelectorImpl>, ()> {
-> Result<SelectorList<SelectorImpl>, ParseError> {
let namespaces = Namespaces::default();
let parser = SelectorParser {
stylesheet_origin: Origin::Author,
namespaces: &namespaces,
};
SelectorList::parse(&parser, &mut CssParser::new(input))
let mut input = ParserInput::new(input);
SelectorList::parse(&parser, &mut CssParser::new(&mut input))
}
/// Whether we're parsing selectors in a user-agent stylesheet.

Просмотреть файл

@ -13,9 +13,10 @@ use media_queries::MediaType;
use parser::ParserContext;
use properties::{ComputedValues, StyleBuilder};
use properties::longhands::font_size;
use selectors::parser::SelectorParseError;
use std::fmt;
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
use style_traits::{CSSPixel, ToCss};
use style_traits::{CSSPixel, ToCss, ParseError};
use style_traits::viewport::ViewportConstraints;
use values::computed::{self, ToComputedValue};
use values::specified;
@ -151,7 +152,8 @@ impl Expression {
/// ```
///
/// Only supports width and width ranges for now.
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
try!(input.expect_parenthesis_block());
input.parse_nested_block(|input| {
let name = try!(input.expect_ident());
@ -167,7 +169,7 @@ impl Expression {
"width" => {
ExpressionKind::Width(Range::Eq(try!(specified::Length::parse_non_negative(context, input))))
},
_ => return Err(())
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}))
})
}

Просмотреть файл

@ -16,7 +16,7 @@ use restyle_hints::ElementSnapshot;
use selector_parser::{AttrValue as SelectorAttrValue, ElementExt, PseudoElementCascadeType, SelectorParser};
use selectors::Element;
use selectors::attr::{AttrSelectorOperation, NamespaceConstraint};
use selectors::parser::SelectorMethods;
use selectors::parser::{SelectorMethods, SelectorParseError};
use selectors::visitor::SelectorVisitor;
use std::ascii::AsciiExt;
use std::borrow::Cow;
@ -24,6 +24,7 @@ use std::fmt;
use std::fmt::Debug;
use std::mem;
use std::ops::{Deref, DerefMut};
use style_traits::{ParseError, StyleParseError};
/// A pseudo-element, both public and private.
///
@ -300,10 +301,12 @@ impl ::selectors::SelectorImpl for SelectorImpl {
type BorrowedNamespaceUrl = Namespace;
}
impl<'a> ::selectors::Parser for SelectorParser<'a> {
impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
type Impl = SelectorImpl;
type Error = StyleParseError<'i>;
fn parse_non_ts_pseudo_class(&self, name: Cow<str>) -> Result<NonTSPseudoClass, ()> {
fn parse_non_ts_pseudo_class(&self, name: Cow<'i, str>)
-> Result<NonTSPseudoClass, ParseError<'i>> {
use self::NonTSPseudoClass::*;
let pseudo_class = match_ignore_ascii_case! { &name,
"active" => Active,
@ -323,20 +326,21 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
"visited" => Visited,
"-servo-nonzero-border" => {
if !self.in_user_agent_stylesheet() {
return Err(());
return Err(SelectorParseError::UnexpectedIdent(
"-servo-nonzero-border".into()).into());
}
ServoNonZeroBorder
},
_ => return Err(())
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into()),
};
Ok(pseudo_class)
}
fn parse_non_ts_functional_pseudo_class(&self,
name: Cow<str>,
parser: &mut CssParser)
-> Result<NonTSPseudoClass, ()> {
fn parse_non_ts_functional_pseudo_class<'t>(&self,
name: Cow<'i, str>,
parser: &mut CssParser<'i, 't>)
-> Result<NonTSPseudoClass, ParseError<'i>> {
use self::NonTSPseudoClass::*;
let pseudo_class = match_ignore_ascii_case!{ &name,
"lang" => {
@ -344,18 +348,17 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
}
"-servo-case-sensitive-type-attr" => {
if !self.in_user_agent_stylesheet() {
return Err(());
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into());
}
ServoCaseSensitiveTypeAttr(Atom::from(parser.expect_ident()?))
}
_ => return Err(())
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
};
Ok(pseudo_class)
}
fn parse_pseudo_element(&self, name: Cow<str>)
-> Result<PseudoElement, ()> {
fn parse_pseudo_element(&self, name: Cow<'i, str>) -> Result<PseudoElement, ParseError<'i>> {
use self::PseudoElement::*;
let pseudo_element = match_ignore_ascii_case! { &name,
"before" => Before,
@ -363,77 +366,78 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
"selection" => Selection,
"-servo-details-summary" => {
if !self.in_user_agent_stylesheet() {
return Err(())
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
DetailsSummary
},
"-servo-details-content" => {
if !self.in_user_agent_stylesheet() {
return Err(())
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
DetailsContent
},
"-servo-text" => {
if !self.in_user_agent_stylesheet() {
return Err(())
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
ServoText
},
"-servo-input-text" => {
if !self.in_user_agent_stylesheet() {
return Err(())
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
ServoInputText
},
"-servo-table-wrapper" => {
if !self.in_user_agent_stylesheet() {
return Err(())
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
ServoTableWrapper
},
"-servo-anonymous-table-wrapper" => {
if !self.in_user_agent_stylesheet() {
return Err(())
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
ServoAnonymousTableWrapper
},
"-servo-anonymous-table" => {
if !self.in_user_agent_stylesheet() {
return Err(())
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
ServoAnonymousTable
},
"-servo-anonymous-table-row" => {
if !self.in_user_agent_stylesheet() {
return Err(())
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
ServoAnonymousTableRow
},
"-servo-anonymous-table-cell" => {
if !self.in_user_agent_stylesheet() {
return Err(())
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
ServoAnonymousTableCell
},
"-servo-anonymous-block" => {
if !self.in_user_agent_stylesheet() {
return Err(())
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
ServoAnonymousBlock
},
"-servo-inline-block-wrapper" => {
if !self.in_user_agent_stylesheet() {
return Err(())
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
ServoInlineBlockWrapper
},
"-servo-input-absolute" => {
if !self.in_user_agent_stylesheet() {
return Err(())
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
ServoInlineAbsolute
},
_ => return Err(())
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
};
Ok(pseudo_element)

Просмотреть файл

@ -13,7 +13,7 @@ use std::fmt::{self, Write};
// nonzero optimization is important in keeping the size of SpecifiedUrl below
// the threshold.
use std::sync::Arc;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError};
/// A specified url() value for servo.
///
@ -43,7 +43,7 @@ impl SpecifiedUrl {
/// gecko version.
pub fn parse_from_string<'a>(url: Cow<'a, str>,
context: &ParserContext)
-> Result<Self, ()> {
-> Result<Self, ParseError<'a>> {
let serialization = Arc::new(url.into_owned());
let resolved = context.url_data.join(&serialization).ok();
Ok(SpecifiedUrl {

Просмотреть файл

@ -6,12 +6,12 @@
//! initially in CSS Conditional Rules Module Level 3, @document has been postponed to the level 4.
//! We implement the prefixed `@-moz-document`.
use cssparser::{Parser, Token, SourceLocation};
use cssparser::{Parser, Token, SourceLocation, BasicParseError};
use media_queries::Device;
use parser::{Parse, ParserContext};
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use std::fmt;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
use stylearc::Arc;
use stylesheets::CssRules;
use values::specified::url::SpecifiedUrl;
@ -90,9 +90,10 @@ macro_rules! parse_quoted_or_unquoted_string {
match input.next() {
Ok(Token::QuotedString(value)) =>
Ok($url_matching_function(value.into_owned())),
_ => Err(()),
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
Err(e) => Err(e.into()),
}
}).or_else(|_| {
}).or_else(|_: ParseError| {
while let Ok(_) = input.next() {}
Ok($url_matching_function(input.slice_from(start).to_string()))
})
@ -102,8 +103,8 @@ macro_rules! parse_quoted_or_unquoted_string {
impl UrlMatchingFunction {
/// Parse a URL matching function for a`@document` rule's condition.
pub fn parse(context: &ParserContext, input: &mut Parser)
-> Result<UrlMatchingFunction, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<UrlMatchingFunction, ParseError<'i>> {
if input.try(|input| input.expect_function_matching("url-prefix")).is_ok() {
parse_quoted_or_unquoted_string!(input, UrlMatchingFunction::UrlPrefix)
} else if input.try(|input| input.expect_function_matching("domain")).is_ok() {
@ -115,7 +116,7 @@ impl UrlMatchingFunction {
} else if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
Ok(UrlMatchingFunction::Url(url))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -189,8 +190,8 @@ pub struct DocumentCondition(Vec<UrlMatchingFunction>);
impl DocumentCondition {
/// Parse a document condition.
pub fn parse(context: &ParserContext, input: &mut Parser)
-> Result<Self, ()> {
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
input.parse_comma_separated(|input| UrlMatchingFunction::parse(context, input))
.map(DocumentCondition)
}

Просмотреть файл

@ -4,18 +4,20 @@
//! Keyframes: https://drafts.csswg.org/css-animations/#keyframes
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser};
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser, ParserInput};
use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule, SourceLocation};
use error_reporting::NullReporter;
use error_reporting::{NullReporter, ContextualParseError};
use parser::{PARSING_MODE_DEFAULT, ParserContext, log_css_error};
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock, PropertyId};
use properties::{PropertyDeclarationId, LonghandId, SourcePropertyDeclaration};
use properties::LonghandIdSet;
use properties::animated_properties::TransitionProperty;
use properties::longhands::transition_timing_function::single_value::SpecifiedValue as SpecifiedTimingFunction;
use selectors::parser::SelectorParseError;
use shared_lock::{DeepCloneWithLock, SharedRwLock, SharedRwLockReadGuard, Locked, ToCssWithGuard};
use std::borrow::Cow;
use std::fmt;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
use stylearc::Arc;
use stylesheets::{CssRuleType, Stylesheet};
use stylesheets::rule_parser::VendorPrefix;
@ -61,7 +63,8 @@ impl KeyframesRule {
/// Related spec:
/// https://drafts.csswg.org/css-animations-1/#interface-csskeyframesrule-findrule
pub fn find_rule(&self, guard: &SharedRwLockReadGuard, selector: &str) -> Option<usize> {
if let Ok(selector) = Parser::new(selector).parse_entirely(KeyframeSelector::parse) {
let mut input = ParserInput::new(selector);
if let Ok(selector) = Parser::new(&mut input).parse_entirely(KeyframeSelector::parse) {
for (i, keyframe) in self.keyframes.iter().enumerate().rev() {
if keyframe.read_with(guard).selector == selector {
return Some(i);
@ -120,7 +123,7 @@ impl KeyframePercentage {
KeyframePercentage(value)
}
fn parse(input: &mut Parser) -> Result<KeyframePercentage, ()> {
fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<KeyframePercentage, ParseError<'i>> {
let percentage = if input.try(|input| input.expect_ident_matching("from")).is_ok() {
KeyframePercentage::new(0.)
} else if input.try(|input| input.expect_ident_matching("to")).is_ok() {
@ -130,7 +133,7 @@ impl KeyframePercentage {
if percentage >= 0. && percentage <= 1. {
KeyframePercentage::new(percentage)
} else {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
};
@ -168,7 +171,7 @@ impl KeyframeSelector {
}
/// Parse a keyframe selector from CSS input.
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
input.parse_comma_separated(KeyframePercentage::parse)
.map(KeyframeSelector)
}
@ -200,8 +203,8 @@ impl ToCssWithGuard for Keyframe {
impl Keyframe {
/// Parse a CSS keyframe.
pub fn parse(css: &str, parent_stylesheet: &Stylesheet)
-> Result<Arc<Locked<Self>>, ()> {
pub fn parse<'i>(css: &'i str, parent_stylesheet: &Stylesheet)
-> Result<Arc<Locked<Self>>, ParseError<'i>> {
let error_reporter = NullReporter;
let context = ParserContext::new(parent_stylesheet.origin,
&parent_stylesheet.url_data,
@ -209,7 +212,8 @@ impl Keyframe {
Some(CssRuleType::Keyframe),
PARSING_MODE_DEFAULT,
parent_stylesheet.quirks_mode);
let mut input = Parser::new(css);
let mut input = ParserInput::new(css);
let mut input = Parser::new(&mut input);
let mut declarations = SourcePropertyDeclaration::new();
let mut rule_parser = KeyframeListParser {
@ -445,29 +449,31 @@ pub fn parse_keyframe_list(context: &ParserContext, input: &mut Parser, shared_l
}
enum Void {}
impl<'a> AtRuleParser for KeyframeListParser<'a> {
impl<'a, 'i> AtRuleParser<'i> for KeyframeListParser<'a> {
type Prelude = Void;
type AtRule = Arc<Locked<Keyframe>>;
type Error = SelectorParseError<'i, StyleParseError<'i>>;
}
impl<'a> QualifiedRuleParser for KeyframeListParser<'a> {
impl<'a, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a> {
type Prelude = KeyframeSelector;
type QualifiedRule = Arc<Locked<Keyframe>>;
type Error = SelectorParseError<'i, StyleParseError<'i>>;
fn parse_prelude(&mut self, input: &mut Parser) -> Result<Self::Prelude, ()> {
fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>) -> Result<Self::Prelude, ParseError<'i>> {
let start = input.position();
match KeyframeSelector::parse(input) {
Ok(sel) => Ok(sel),
Err(()) => {
let message = format!("Invalid keyframe rule: '{}'", input.slice_from(start));
log_css_error(input, start, &message, self.context);
Err(())
Err(e) => {
let error = ContextualParseError::InvalidKeyframeRule(input.slice_from(start), e.clone());
log_css_error(input, start, error, self.context);
Err(e)
}
}
}
fn parse_block(&mut self, prelude: Self::Prelude, input: &mut Parser)
-> Result<Self::QualifiedRule, ()> {
fn parse_block<'t>(&mut self, prelude: Self::Prelude, input: &mut Parser<'i, 't>)
-> Result<Self::QualifiedRule, ParseError<'i>> {
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Keyframe));
let parser = KeyframeDeclarationParser {
context: &context,
@ -480,12 +486,12 @@ impl<'a> QualifiedRuleParser for KeyframeListParser<'a> {
Ok(()) => {
block.extend(iter.parser.declarations.drain(), Importance::Normal);
}
Err(range) => {
Err(err) => {
iter.parser.declarations.clear();
let pos = range.start;
let message = format!("Unsupported keyframe property declaration: '{}'",
iter.input.slice(range));
log_css_error(iter.input, pos, &*message, &context);
let pos = err.span.start;
let error = ContextualParseError::UnsupportedKeyframePropertyDeclaration(
iter.input.slice(err.span), err.error);
log_css_error(iter.input, pos, error, &context);
}
}
// `parse_important` is not called here, `!important` is not allowed in keyframe blocks.
@ -503,22 +509,25 @@ struct KeyframeDeclarationParser<'a, 'b: 'a> {
}
/// Default methods reject all at rules.
impl<'a, 'b> AtRuleParser for KeyframeDeclarationParser<'a, 'b> {
impl<'a, 'b, 'i> AtRuleParser<'i> for KeyframeDeclarationParser<'a, 'b> {
type Prelude = ();
type AtRule = ();
type Error = SelectorParseError<'i, StyleParseError<'i>>;
}
impl<'a, 'b> DeclarationParser for KeyframeDeclarationParser<'a, 'b> {
impl<'a, 'b, 'i> DeclarationParser<'i> for KeyframeDeclarationParser<'a, 'b> {
type Declaration = ();
type Error = SelectorParseError<'i, StyleParseError<'i>>;
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<(), ()> {
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
-> Result<(), ParseError<'i>> {
let id = try!(PropertyId::parse(name.into()));
match PropertyDeclaration::parse_into(self.declarations, id, self.context, input) {
Ok(()) => {
// In case there is still unparsed text in the declaration, we should roll back.
input.expect_exhausted()
input.expect_exhausted().map_err(|e| e.into())
}
Err(_) => Err(())
Err(_e) => Err(StyleParseError::UnspecifiedError.into())
}
}
}

Просмотреть файл

@ -22,7 +22,7 @@ mod stylesheet;
pub mod supports_rule;
pub mod viewport_rule;
use cssparser::{parse_one_rule, Parser};
use cssparser::{parse_one_rule, Parser, ParserInput};
use error_reporting::NullReporter;
use parser::{ParserContext, PARSING_MODE_DEFAULT};
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
@ -234,7 +234,8 @@ impl CssRule {
parent_stylesheet.quirks_mode
);
let mut input = Parser::new(css);
let mut input = ParserInput::new(css);
let mut input = Parser::new(&mut input);
let mut guard = parent_stylesheet.namespaces.write();

Просмотреть файл

@ -7,6 +7,7 @@
use {Namespace, Prefix};
use counter_style::{parse_counter_style_body, parse_counter_style_name};
use cssparser::{AtRuleParser, AtRuleType, Parser, QualifiedRuleParser, RuleListParser, SourceLocation};
use error_reporting::ContextualParseError;
use font_face::parse_font_face_block;
use media_queries::{parse_media_query_list, MediaList};
use parking_lot::RwLock;
@ -14,9 +15,12 @@ use parser::{Parse, ParserContext, log_css_error};
use properties::parse_property_declaration_list;
use selector_parser::{SelectorImpl, SelectorParser};
use selectors::SelectorList;
use selectors::parser::SelectorParseError;
use shared_lock::{Locked, SharedRwLock};
use std::borrow::Cow;
use std::sync::atomic::AtomicBool;
use str::starts_with_ignore_ascii_case;
use style_traits::{StyleParseError, ParseError};
use stylearc::Arc;
use stylesheets::{CssRule, CssRules, CssRuleType, Origin, StylesheetLoader};
use stylesheets::{DocumentRule, ImportRule, KeyframesRule, MediaRule, NamespaceRule, PageRule};
@ -132,22 +136,24 @@ fn register_namespace(_: &Namespace) -> Result<(), ()> {
Ok(()) // servo doesn't use namespace ids
}
impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> {
type Prelude = AtRulePrelude;
type AtRule = CssRule;
type Error = SelectorParseError<'i, StyleParseError<'i>>;
fn parse_prelude(
fn parse_prelude<'t>(
&mut self,
name: &str,
input: &mut Parser
) -> Result<AtRuleType<AtRulePrelude, CssRule>, ()> {
name: Cow<'i, str>,
input: &mut Parser<'i, 't>
) -> Result<AtRuleType<AtRulePrelude, CssRule>, ParseError<'i>> {
let location = get_location_with_offset(input.current_source_location(),
self.context.line_number_offset);
match_ignore_ascii_case! { name,
match_ignore_ascii_case! { &*name,
"import" => {
if self.state > State::Imports {
self.state = State::Invalid;
return Err(()) // "@import must be before any rule but @charset"
// "@import must be before any rule but @charset"
return Err(StyleParseError::UnexpectedImportRule.into())
}
self.state = State::Imports;
@ -190,14 +196,16 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
"namespace" => {
if self.state > State::Namespaces {
self.state = State::Invalid;
return Err(()) // "@namespace must be before any rule but @charset and @import"
// "@namespace must be before any rule but @charset and @import"
return Err(StyleParseError::UnexpectedNamespaceRule.into())
}
self.state = State::Namespaces;
let prefix_result = input.try(|input| input.expect_ident());
let url = Namespace::from(try!(input.expect_url_or_string()));
let id = register_namespace(&url)?;
let id = register_namespace(&url)
.map_err(|()| StyleParseError::UnspecifiedError)?;
let mut namespaces = self.namespaces.as_mut().unwrap();
@ -222,13 +230,13 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
},
// @charset is removed by rust-cssparser if its the first rule in the stylesheet
// anything left is invalid.
"charset" => return Err(()), // (insert appropriate error message)
"charset" => return Err(StyleParseError::UnexpectedCharsetRule.into()),
_ => {}
}
// Don't allow starting with an invalid state
if self.state > State::Body {
self.state = State::Invalid;
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
self.state = State::Body;
@ -242,18 +250,21 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
}
#[inline]
fn parse_block(&mut self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CssRule, ()> {
fn parse_block<'t>(&mut self, prelude: AtRulePrelude, input: &mut Parser<'i, 't>)
-> Result<CssRule, ParseError<'i>> {
AtRuleParser::parse_block(&mut self.nested(), prelude, input)
}
}
impl<'a> QualifiedRuleParser for TopLevelRuleParser<'a> {
impl<'a, 'i> QualifiedRuleParser<'i> for TopLevelRuleParser<'a> {
type Prelude = SelectorList<SelectorImpl>;
type QualifiedRule = CssRule;
type Error = SelectorParseError<'i, StyleParseError<'i>>;
#[inline]
fn parse_prelude(&mut self, input: &mut Parser) -> Result<SelectorList<SelectorImpl>, ()> {
fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>)
-> Result<SelectorList<SelectorImpl>, ParseError<'i>> {
self.state = State::Body;
// "Freeze" the namespace map (no more namespace rules can be parsed
@ -267,11 +278,11 @@ impl<'a> QualifiedRuleParser for TopLevelRuleParser<'a> {
}
#[inline]
fn parse_block(
fn parse_block<'t>(
&mut self,
prelude: SelectorList<SelectorImpl>,
input: &mut Parser
) -> Result<CssRule, ()> {
input: &mut Parser<'i, 't>
) -> Result<CssRule, ParseError<'i>> {
QualifiedRuleParser::parse_block(&mut self.nested(), prelude, input)
}
}
@ -302,10 +313,11 @@ impl<'a, 'b> NestedRuleParser<'a, 'b> {
while let Some(result) = iter.next() {
match result {
Ok(rule) => rules.push(rule),
Err(range) => {
let pos = range.start;
let message = format!("Unsupported rule: '{}'", iter.input.slice(range));
log_css_error(iter.input, pos, &*message, self.context);
Err(err) => {
let pos = err.span.start;
let error = ContextualParseError::UnsupportedRule(
iter.input.slice(err.span), err.error);
log_css_error(iter.input, pos, error, self.context);
}
}
}
@ -324,22 +336,23 @@ fn is_viewport_enabled() -> bool {
false // Gecko doesn't support @viewport.
}
impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> {
type Prelude = AtRulePrelude;
type AtRule = CssRule;
type Error = SelectorParseError<'i, StyleParseError<'i>>;
fn parse_prelude(
fn parse_prelude<'t>(
&mut self,
name: &str,
input: &mut Parser
) -> Result<AtRuleType<AtRulePrelude, CssRule>, ()> {
name: Cow<'i, str>,
input: &mut Parser<'i, 't>
) -> Result<AtRuleType<AtRulePrelude, CssRule>, ParseError<'i>> {
let location =
get_location_with_offset(
input.current_source_location(),
self.context.line_number_offset
);
match_ignore_ascii_case! { name,
match_ignore_ascii_case! { &*name,
"media" => {
let media_queries = parse_media_query_list(self.context, input);
let arc = Arc::new(self.shared_lock.wrap(media_queries));
@ -355,14 +368,14 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
"counter-style" => {
if !cfg!(feature = "gecko") {
// Support for this rule is not fully implemented in Servo yet.
return Err(())
return Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
}
let name = parse_counter_style_name(input)?;
// ASCII-case-insensitive matches for "decimal" are already
// lower-cased by `parse_counter_style_name`, so we can use ==
// here.
if name.0 == atom!("decimal") {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
Ok(AtRuleType::WithBlock(AtRulePrelude::CounterStyle(name)))
},
@ -370,13 +383,13 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
if is_viewport_enabled() {
Ok(AtRuleType::WithBlock(AtRulePrelude::Viewport))
} else {
Err(())
Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
}
},
"keyframes" | "-webkit-keyframes" | "-moz-keyframes" => {
let prefix = if starts_with_ignore_ascii_case(name, "-webkit-") {
let prefix = if starts_with_ignore_ascii_case(&*name, "-webkit-") {
Some(VendorPrefix::WebKit)
} else if starts_with_ignore_ascii_case(name, "-moz-") {
} else if starts_with_ignore_ascii_case(&*name, "-moz-") {
Some(VendorPrefix::Moz)
} else {
None
@ -384,7 +397,7 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
if cfg!(feature = "servo") &&
prefix.as_ref().map_or(false, |p| matches!(*p, VendorPrefix::Moz)) {
// Servo should not support @-moz-keyframes.
return Err(())
return Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
}
let name = KeyframesName::parse(self.context, input)?;
@ -394,7 +407,7 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
if cfg!(feature = "gecko") {
Ok(AtRuleType::WithBlock(AtRulePrelude::Page(location)))
} else {
Err(())
Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
}
},
"-moz-document" => {
@ -402,18 +415,18 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
let cond = DocumentCondition::parse(self.context, input)?;
Ok(AtRuleType::WithBlock(AtRulePrelude::Document(cond, location)))
} else {
Err(())
Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
}
},
_ => Err(())
_ => Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
}
}
fn parse_block(
fn parse_block<'t>(
&mut self,
prelude: AtRulePrelude,
input: &mut Parser
) -> Result<CssRule, ()> {
input: &mut Parser<'i, 't>
) -> Result<CssRule, ParseError<'i>> {
match prelude {
AtRulePrelude::FontFace(location) => {
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::FontFace));
@ -478,11 +491,13 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
}
}
impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> {
impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> {
type Prelude = SelectorList<SelectorImpl>;
type QualifiedRule = CssRule;
type Error = SelectorParseError<'i, StyleParseError<'i>>;
fn parse_prelude(&mut self, input: &mut Parser) -> Result<SelectorList<SelectorImpl>, ()> {
fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>)
-> Result<SelectorList<SelectorImpl>, ParseError<'i>> {
let selector_parser = SelectorParser {
stylesheet_origin: self.stylesheet_origin,
namespaces: self.context.namespaces.unwrap(),
@ -491,11 +506,11 @@ impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> {
SelectorList::parse(&selector_parser, input)
}
fn parse_block(
fn parse_block<'t>(
&mut self,
prelude: SelectorList<SelectorImpl>,
input: &mut Parser
) -> Result<CssRule, ()> {
input: &mut Parser<'i, 't>
) -> Result<CssRule, ParseError<'i>> {
let location = get_location_with_offset(input.current_source_location(),
self.context.line_number_offset);
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Style));

Просмотреть файл

@ -4,8 +4,8 @@
use {Prefix, Namespace};
use context::QuirksMode;
use cssparser::{Parser, RuleListParser};
use error_reporting::ParseErrorReporter;
use cssparser::{Parser, RuleListParser, ParserInput};
use error_reporting::{ParseErrorReporter, ContextualParseError};
use fnv::FnvHashMap;
use media_queries::{MediaList, Device};
use parking_lot::RwLock;
@ -110,7 +110,8 @@ impl Stylesheet {
line_number_offset: u64
) -> (Vec<CssRule>, bool) {
let mut rules = Vec::new();
let mut input = Parser::new(css);
let mut input = ParserInput::new(css);
let mut input = Parser::new(&mut input);
let context =
ParserContext::new_with_line_number_offset(
@ -140,10 +141,11 @@ impl Stylesheet {
while let Some(result) = iter.next() {
match result {
Ok(rule) => rules.push(rule),
Err(range) => {
let pos = range.start;
let message = format!("Invalid rule: '{}'", iter.input.slice(range));
log_css_error(iter.input, pos, &*message, iter.parser.context());
Err(err) => {
let pos = err.span.start;
let error = ContextualParseError::InvalidRule(
iter.input.slice(err.span), err.error);
log_css_error(iter.input, pos, error, iter.parser.context());
}
}
}

Просмотреть файл

@ -4,12 +4,14 @@
//! [@supports rules](https://drafts.csswg.org/css-conditional-3/#at-supports)
use cssparser::{BasicParseError, ParseError as CssParseError, ParserInput};
use cssparser::{Delimiter, parse_important, Parser, SourceLocation, Token};
use parser::ParserContext;
use properties::{PropertyId, PropertyDeclaration, SourcePropertyDeclaration};
use selectors::parser::SelectorParseError;
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use std::fmt;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
use stylearc::Arc;
use stylesheets::{CssRuleType, CssRules};
@ -81,7 +83,7 @@ impl SupportsCondition {
/// Parse a condition
///
/// https://drafts.csswg.org/css-conditional/#supports_condition
pub fn parse(input: &mut Parser) -> Result<SupportsCondition, ()> {
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<SupportsCondition, ParseError<'i>> {
if let Ok(_) = input.try(|i| i.expect_ident_matching("not")) {
let inner = SupportsCondition::parse_in_parens(input)?;
return Ok(SupportsCondition::Not(Box::new(inner)));
@ -90,7 +92,7 @@ impl SupportsCondition {
let in_parens = SupportsCondition::parse_in_parens(input)?;
let (keyword, wrapper) = match input.next() {
Err(()) => {
Err(_) => {
// End of input
return Ok(in_parens)
}
@ -98,10 +100,10 @@ impl SupportsCondition {
match_ignore_ascii_case! { &ident,
"and" => ("and", SupportsCondition::And as fn(_) -> _),
"or" => ("or", SupportsCondition::Or as fn(_) -> _),
_ => return Err(())
_ => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into())
}
}
_ => return Err(())
Ok(t) => return Err(CssParseError::Basic(BasicParseError::UnexpectedToken(t)))
};
let mut conditions = Vec::with_capacity(2);
@ -118,7 +120,7 @@ impl SupportsCondition {
}
/// https://drafts.csswg.org/css-conditional-3/#supports_condition_in_parens
fn parse_in_parens(input: &mut Parser) -> Result<SupportsCondition, ()> {
fn parse_in_parens<'i, 't>(input: &mut Parser<'i, 't>) -> Result<SupportsCondition, ParseError<'i>> {
// Whitespace is normally taken care of in `Parser::next`,
// but we want to not include it in `pos` for the SupportsCondition::FutureSyntax cases.
while input.try(Parser::expect_whitespace).is_ok() {}
@ -127,17 +129,18 @@ impl SupportsCondition {
Token::ParenthesisBlock => {
input.parse_nested_block(|input| {
// `input.try()` not needed here since the alternative uses `consume_all()`.
parse_condition_or_declaration(input).or_else(|()| {
parse_condition_or_declaration(input).or_else(|_| {
consume_all(input);
Ok(SupportsCondition::FutureSyntax(input.slice_from(pos).to_owned()))
})
})
}
Token::Function(_) => {
input.parse_nested_block(|i| Ok(consume_all(i))).unwrap();
let result: Result<_, ParseError> = input.parse_nested_block(|i| Ok(consume_all(i)));
result.unwrap();
Ok(SupportsCondition::FutureSyntax(input.slice_from(pos).to_owned()))
}
_ => Err(())
t => Err(CssParseError::Basic(BasicParseError::UnexpectedToken(t)))
}
}
@ -156,7 +159,8 @@ impl SupportsCondition {
/// supports_condition | declaration
/// https://drafts.csswg.org/css-conditional/#dom-css-supports-conditiontext-conditiontext
pub fn parse_condition_or_declaration(input: &mut Parser) -> Result<SupportsCondition, ()> {
pub fn parse_condition_or_declaration<'i, 't>(input: &mut Parser<'i, 't>)
-> Result<SupportsCondition, ParseError<'i>> {
if let Ok(condition) = input.try(SupportsCondition::parse) {
Ok(SupportsCondition::Parenthesized(Box::new(condition)))
} else {
@ -244,7 +248,7 @@ fn consume_all(input: &mut Parser) {
impl Declaration {
/// Parse a declaration
pub fn parse(input: &mut Parser) -> Result<Declaration, ()> {
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Declaration, ParseError<'i>> {
let prop = input.expect_ident()?.into_owned();
input.expect_colon()?;
let val = parse_anything(input);
@ -260,12 +264,13 @@ impl Declaration {
} else {
return false
};
let mut input = Parser::new(&self.val);
let mut input = ParserInput::new(&self.val);
let mut input = Parser::new(&mut input);
let context = ParserContext::new_with_rule_type(cx, Some(CssRuleType::Style));
let mut declarations = SourcePropertyDeclaration::new();
let res = input.parse_until_before(Delimiter::Bang, |input| {
PropertyDeclaration::parse_into(&mut declarations, id, &context, input)
.map_err(|_| ())
.map_err(|e| StyleParseError::PropertyDeclaration(e).into())
});
let _ = input.try(parse_important);
res.is_ok() && input.is_exhausted()

Просмотреть файл

@ -11,18 +11,20 @@ use app_units::Au;
use context::QuirksMode;
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important};
use cssparser::ToCss as ParserToCss;
use error_reporting::ContextualParseError;
use euclid::size::TypedSize2D;
use font_metrics::get_metrics_provider_for_product;
use media_queries::Device;
use parser::{Parse, ParserContext, log_css_error};
use properties::StyleBuilder;
use selectors::parser::SelectorParseError;
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::fmt;
use std::iter::Enumerate;
use std::str::Chars;
use style_traits::{PinchZoomFactor, ToCss};
use style_traits::{PinchZoomFactor, ToCss, ParseError, StyleParseError};
use style_traits::viewport::{Orientation, UserZoom, ViewportConstraints, Zoom};
use stylearc::Arc;
use stylesheets::{Stylesheet, Origin};
@ -167,7 +169,8 @@ impl FromMeta for ViewportLength {
}
impl ViewportLength {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
// we explicitly do not accept 'extend-to-zoom', since it is a UA
// internal value for <META> viewport translation
LengthOrPercentageOrAuto::parse_non_negative(context, input).map(ViewportLength::Specified)
@ -246,23 +249,27 @@ impl ToCss for ViewportDescriptorDeclaration {
}
}
fn parse_shorthand(context: &ParserContext, input: &mut Parser) -> Result<(ViewportLength, ViewportLength), ()> {
fn parse_shorthand<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<(ViewportLength, ViewportLength), ParseError<'i>> {
let min = try!(ViewportLength::parse(context, input));
match input.try(|i| ViewportLength::parse(context, i)) {
Err(()) => Ok((min.clone(), min)),
Err(_) => Ok((min.clone(), min)),
Ok(max) => Ok((min, max))
}
}
impl<'a, 'b> AtRuleParser for ViewportRuleParser<'a, 'b> {
impl<'a, 'b, 'i> AtRuleParser<'i> for ViewportRuleParser<'a, 'b> {
type Prelude = ();
type AtRule = Vec<ViewportDescriptorDeclaration>;
type Error = SelectorParseError<'i, StyleParseError<'i>>;
}
impl<'a, 'b> DeclarationParser for ViewportRuleParser<'a, 'b> {
impl<'a, 'b, 'i> DeclarationParser<'i> for ViewportRuleParser<'a, 'b> {
type Declaration = Vec<ViewportDescriptorDeclaration>;
type Error = SelectorParseError<'i, StyleParseError<'i>>;
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<Vec<ViewportDescriptorDeclaration>, ()> {
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
-> Result<Vec<ViewportDescriptorDeclaration>, ParseError<'i>> {
macro_rules! declaration {
($declaration:ident($parse:expr)) => {
declaration!($declaration(value: try!($parse(input)),
@ -289,7 +296,7 @@ impl<'a, 'b> DeclarationParser for ViewportRuleParser<'a, 'b> {
}}
}
match_ignore_ascii_case! { name,
match_ignore_ascii_case! { &*name,
"min-width" => ok!(MinWidth(|i| ViewportLength::parse(self.context, i))),
"max-width" => ok!(MaxWidth(|i| ViewportLength::parse(self.context, i))),
"width" => ok!(shorthand -> [MinWidth, MaxWidth]),
@ -301,7 +308,7 @@ impl<'a, 'b> DeclarationParser for ViewportRuleParser<'a, 'b> {
"max-zoom" => ok!(MaxZoom(Zoom::parse)),
"user-zoom" => ok!(UserZoom(UserZoom::parse)),
"orientation" => ok!(Orientation(Orientation::parse)),
_ => Err(()),
_ => Err(SelectorParseError::UnexpectedIdent(name.clone()).into()),
}
}
}
@ -328,7 +335,7 @@ fn is_whitespace_separator_or_equals(c: &char) -> bool {
}
impl Parse for ViewportRule {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let parser = ViewportRuleParser { context: context };
let mut cascade = Cascade::new();
@ -340,11 +347,11 @@ impl Parse for ViewportRule {
cascade.add(Cow::Owned(declarations))
}
}
Err(range) => {
let pos = range.start;
let message = format!("Unsupported @viewport descriptor declaration: '{}'",
parser.input.slice(range));
log_css_error(parser.input, pos, &*message, &context);
Err(err) => {
let pos = err.span.start;
let error = ContextualParseError::UnsupportedViewportDescriptorDeclaration(
parser.input.slice(err.span), err.error);
log_css_error(parser.input, pos, error, &context);
}
}
}

Просмотреть файл

@ -10,7 +10,7 @@ use context::{QuirksMode, SharedStyleContext};
use data::ComputedStyle;
use dom::TElement;
use element_state::ElementState;
use error_reporting::RustLogReporter;
use error_reporting::create_error_reporter;
use font_metrics::FontMetricsProvider;
#[cfg(feature = "gecko")]
use gecko_bindings::structs::{nsIAtom, StyleRuleInclusion};
@ -595,7 +595,7 @@ impl Stylist {
parent.map(|p| &**p),
None,
None,
&RustLogReporter,
&create_error_reporter(),
font_metrics,
cascade_flags,
self.quirks_mode);
@ -676,7 +676,7 @@ impl Stylist {
Some(parent_style),
None,
None,
&RustLogReporter,
&create_error_reporter(),
font_metrics,
CascadeFlags::empty(),
self.quirks_mode);
@ -1216,7 +1216,7 @@ impl Stylist {
Some(parent_style),
None,
None,
&RustLogReporter,
&create_error_reporter(),
&metrics,
CascadeFlags::empty(),
self.quirks_mode))

Просмотреть файл

@ -7,8 +7,9 @@
use cssparser::{Parser, serialize_identifier};
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseError;
use std::{fmt, mem, usize};
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
use values::{CSSFloat, CustomIdent};
use values::computed::{self, ComputedValueAsSpecified, Context, ToComputedValue};
use values::specified::Integer;
@ -70,7 +71,7 @@ impl ToCss for GridLine {
}
impl Parse for GridLine {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let mut grid_line = Default::default();
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
return Ok(grid_line)
@ -85,7 +86,7 @@ impl Parse for GridLine {
for _ in 0..3 { // Maximum possible entities for <grid-line>
if input.try(|i| i.expect_ident_matching("span")).is_ok() {
if grid_line.is_span {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
if grid_line.line_num.is_some() || grid_line.ident.is_some() {
@ -95,14 +96,14 @@ impl Parse for GridLine {
grid_line.is_span = true;
} else if let Ok(i) = input.try(|i| Integer::parse(context, i)) {
if i.value() == 0 || val_before_span || grid_line.line_num.is_some() {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
grid_line.line_num = Some(i);
} else if let Ok(name) = input.try(|i| i.expect_ident()) {
if val_before_span || grid_line.ident.is_some() ||
CustomIdent::from_ident((&*name).into(), &[]).is_err() {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
grid_line.ident = Some(name.into_owned());
@ -112,18 +113,18 @@ impl Parse for GridLine {
}
if grid_line.is_auto() {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
if grid_line.is_span {
if let Some(i) = grid_line.line_num {
if i.value() <= 0 { // disallow negative integers for grid spans
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
} else if grid_line.ident.is_some() { // integer could be omitted
grid_line.line_num = Some(Integer::new(1));
} else {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
}
@ -341,19 +342,20 @@ pub enum RepeatCount {
}
impl Parse for RepeatCount {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if let Ok(i) = input.try(|i| Integer::parse(context, i)) {
if i.value() > 0 {
Ok(RepeatCount::Number(i))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
} else {
match_ignore_ascii_case! { &input.expect_ident()?,
let ident = input.expect_ident()?;
(match_ignore_ascii_case! { &ident,
"auto-fill" => Ok(RepeatCount::AutoFill),
"auto-fit" => Ok(RepeatCount::AutoFit),
_ => Err(()),
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
}
}

Просмотреть файл

@ -8,8 +8,9 @@
use counter_style::{Symbols, parse_counter_style_name};
use cssparser::Parser;
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseError;
use std::fmt;
use style_traits::{OneOrMoreCommaSeparated, ToCss};
use style_traits::{OneOrMoreCommaSeparated, ToCss, ParseError, StyleParseError};
use super::CustomIdent;
use values::specified::url::SpecifiedUrl;
@ -79,7 +80,7 @@ impl CounterStyleOrNone {
no_viewport_percentage!(CounterStyleOrNone);
impl Parse for CounterStyleOrNone {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if let Ok(name) = input.try(|i| parse_counter_style_name(i)) {
return Ok(CounterStyleOrNone::Name(name));
}
@ -95,16 +96,16 @@ impl Parse for CounterStyleOrNone {
// numeric system.
if (symbols_type == SymbolsType::Alphabetic ||
symbols_type == SymbolsType::Numeric) && symbols.0.len() < 2 {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
// Identifier is not allowed in symbols() function.
if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(CounterStyleOrNone::Symbols(symbols_type, symbols))
});
}
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -159,7 +160,7 @@ impl<T: Parse> Parse for FontSettingTag<T> {
/// settings-control-the-font-variation-settings-property
/// <string> [ on | off | <integer> ]
/// <string> <number>
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
use byteorder::{ReadBytesExt, BigEndian};
use std::io::Cursor;
@ -169,7 +170,7 @@ impl<T: Parse> Parse for FontSettingTag<T> {
if tag.len() != 4 ||
tag.chars().any(|c| c < ' ' || c > '~')
{
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
let mut raw = Cursor::new(tag.as_bytes());
@ -192,7 +193,7 @@ pub enum FontSettings<T> {
impl<T: Parse> Parse for FontSettings<T> {
/// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
return Ok(FontSettings::Normal);
}
@ -227,13 +228,13 @@ impl ToCss for FontSettingTagInt {
}
impl Parse for FontSettingTagInt {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if let Ok(value) = input.try(|input| input.expect_integer()) {
// handle integer, throw if it is negative
if value >= 0 {
Ok(FontSettingTagInt(value as u32))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
} else if let Ok(_) = input.try(|input| input.expect_ident_matching("on")) {
// on is an alias for '1'
@ -250,8 +251,8 @@ impl Parse for FontSettingTagInt {
impl Parse for FontSettingTagFloat {
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
input.expect_number().map(FontSettingTagFloat)
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
input.expect_number().map(FontSettingTagFloat).map_err(|e| e.into())
}
}
@ -326,18 +327,19 @@ impl<ColorType> SVGPaint<ColorType> {
impl<ColorType> SVGPaintKind<ColorType> {
/// Parse a keyword value only
fn parse_ident(input: &mut Parser) -> Result<Self, ()> {
Ok(match_ignore_ascii_case! { &input.expect_ident()?,
"none" => SVGPaintKind::None,
"context-fill" => SVGPaintKind::ContextFill,
"context-stroke" => SVGPaintKind::ContextStroke,
_ => return Err(())
})
fn parse_ident<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let ident = input.expect_ident()?;
(match_ignore_ascii_case! { &ident,
"none" => Ok(SVGPaintKind::None),
"context-fill" => Ok(SVGPaintKind::ContextFill),
"context-stroke" => Ok(SVGPaintKind::ContextStroke),
_ => Err(())
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
}
impl<ColorType: Parse> Parse for SVGPaint<ColorType> {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) {
let fallback = input.try(|i| ColorType::parse(context, i));
Ok(SVGPaint {
@ -363,7 +365,7 @@ impl<ColorType: Parse> Parse for SVGPaint<ColorType> {
fallback: None,
})
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
}

Просмотреть файл

@ -7,7 +7,7 @@
use cssparser::Parser;
use parser::{Parse, ParserContext};
use std::fmt;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError};
/// A CSS value made of four components, where its `ToCss` impl will try to
/// serialize as few components as possible, like for example in `border-width`.
@ -26,12 +26,12 @@ impl<T> Rect<T>
where T: Clone
{
/// Parses a new `Rect<T>` value with the given parse function.
pub fn parse_with<Parse>(
pub fn parse_with<'i, 't, Parse>(
context: &ParserContext,
input: &mut Parser,
input: &mut Parser<'i, 't>,
parse: Parse)
-> Result<Self, ()>
where Parse: Fn(&ParserContext, &mut Parser) -> Result<T, ()>
-> Result<Self, ParseError<'i>>
where Parse: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>
{
let first = parse(context, input)?;
let second = if let Ok(second) = input.try(|i| parse(context, i)) { second } else {
@ -64,7 +64,7 @@ impl<T> Parse for Rect<T>
where T: Clone + Parse
{
#[inline]
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Self::parse_with(context, input, T::parse)
}
}

Просмотреть файл

@ -9,7 +9,7 @@ use cssparser::Parser;
use parser::ParserContext;
use properties::animated_properties::Animatable;
use std::fmt;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError};
/// A generic value for the `initial-letter` property.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -71,12 +71,12 @@ impl<Value> Spacing<Value> {
/// Parses.
#[inline]
pub fn parse_with<F>(
pub fn parse_with<'i, 't, F>(
context: &ParserContext,
input: &mut Parser,
input: &mut Parser<'i, 't>,
parse: F)
-> Result<Self, ()>
where F: FnOnce(&ParserContext, &mut Parser) -> Result<Value, ()>
-> Result<Self, ParseError<'i>>
where F: FnOnce(&ParserContext, &mut Parser<'i, 't>) -> Result<Value, ParseError<'i>>
{
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
return Ok(Spacing::Normal);

Просмотреть файл

@ -9,13 +9,14 @@
#![deny(missing_docs)]
use Atom;
pub use cssparser::{RGBA, Token, Parser, serialize_identifier};
pub use cssparser::{RGBA, Token, Parser, serialize_identifier, BasicParseError};
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseError;
use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::fmt::{self, Debug};
use std::hash;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
pub mod computed;
pub mod generics;
@ -54,7 +55,8 @@ impl<A: Debug, B: Debug> Debug for Either<A, B> {
}
impl<A: Parse, B: Parse> Parse for Either<A, B> {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Either<A, B>, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Either<A, B>, ParseError<'i>> {
if let Ok(v) = input.try(|i| A::parse(context, i)) {
Ok(Either::First(v))
} else {
@ -91,13 +93,16 @@ pub struct CustomIdent(pub Atom);
impl CustomIdent {
/// Parse an already-tokenizer identifier
pub fn from_ident(ident: Cow<str>, excluding: &[&str]) -> Result<Self, ()> {
match_ignore_ascii_case! { &ident,
"initial" | "inherit" | "unset" | "default" => return Err(()),
_ => {}
pub fn from_ident<'i>(ident: Cow<'i, str>, excluding: &[&str]) -> Result<Self, ParseError<'i>> {
let valid = match_ignore_ascii_case! { &ident,
"initial" | "inherit" | "unset" | "default" => false,
_ => true
};
if !valid {
return Err(SelectorParseError::UnexpectedIdent(ident).into());
}
if excluding.iter().any(|s| ident.eq_ignore_ascii_case(s)) {
Err(())
Err(StyleParseError::UnspecifiedError.into())
} else {
Ok(CustomIdent(ident.into()))
}
@ -125,7 +130,7 @@ impl KeyframesName {
pub fn from_ident(value: String) -> Self {
match CustomIdent::from_ident((&*value).into(), &["none"]) {
Ok(ident) => KeyframesName::Ident(ident),
Err(()) => KeyframesName::QuotedString(value.into()),
Err(_) => KeyframesName::QuotedString(value.into()),
}
}
@ -153,11 +158,12 @@ impl hash::Hash for KeyframesName {
}
impl Parse for KeyframesName {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
match input.next() {
Ok(Token::Ident(s)) => Ok(KeyframesName::Ident(CustomIdent::from_ident(s, &["none"])?)),
Ok(Token::QuotedString(s)) => Ok(KeyframesName::QuotedString(s.into())),
_ => Err(())
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
Err(e) => Err(e.into()),
}
}
}

Просмотреть файл

@ -9,9 +9,10 @@
use cssparser::Parser;
use gecko_bindings::structs;
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseError;
use std::ascii::AsciiExt;
use std::fmt;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
bitflags! {
/// Constants shared by multiple CSS Box Alignment properties
@ -177,7 +178,7 @@ no_viewport_percentage!(AlignJustifyContent);
impl Parse for AlignJustifyContent {
// normal | <baseline-position> |
// [ <content-distribution> || [ <overflow-position>? && <content-position> ] ]
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
// normal | <baseline-position>
if let Ok(value) = input.try(|input| parse_normal_or_baseline(input)) {
return Ok(AlignJustifyContent::new(value))
@ -198,7 +199,7 @@ impl Parse for AlignJustifyContent {
}
return Ok(AlignJustifyContent::new(fallback))
}
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -227,7 +228,7 @@ no_viewport_percentage!(AlignJustifySelf);
impl Parse for AlignJustifySelf {
// auto | normal | stretch | <baseline-position> |
// [ <overflow-position>? && <self-position> ]
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
// auto | normal | stretch | <baseline-position>
if let Ok(value) = input.try(parse_auto_normal_stretch_baseline) {
return Ok(AlignJustifySelf(value))
@ -236,7 +237,7 @@ impl Parse for AlignJustifySelf {
if let Ok(value) = input.try(parse_overflow_self_position) {
return Ok(AlignJustifySelf(value))
}
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -265,7 +266,7 @@ no_viewport_percentage!(AlignItems);
impl Parse for AlignItems {
// normal | stretch | <baseline-position> |
// [ <overflow-position>? && <self-position> ]
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
// normal | stretch | <baseline-position>
if let Ok(value) = input.try(parse_normal_stretch_baseline) {
return Ok(AlignItems(value))
@ -274,7 +275,7 @@ impl Parse for AlignItems {
if let Ok(value) = input.try(parse_overflow_self_position) {
return Ok(AlignItems(value))
}
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -304,7 +305,7 @@ impl Parse for JustifyItems {
// auto | normal | stretch | <baseline-position> |
// [ <overflow-position>? && <self-position> ]
// [ legacy && [ left | right | center ] ]
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
// auto | normal | stretch | <baseline-position>
if let Ok(value) = input.try(parse_auto_normal_stretch_baseline) {
return Ok(JustifyItems(value))
@ -317,7 +318,7 @@ impl Parse for JustifyItems {
if let Ok(value) = parse_overflow_self_position(input) {
return Ok(JustifyItems(value))
}
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -336,72 +337,73 @@ impl From<AlignJustifyContent> for u16 {
}
// auto | normal | stretch | <baseline-position>
fn parse_auto_normal_stretch_baseline(input: &mut Parser) -> Result<AlignFlags, ()> {
fn parse_auto_normal_stretch_baseline<'i, 't>(input: &mut Parser<'i, 't>)
-> Result<AlignFlags, ParseError<'i>> {
if let Ok(baseline) = input.try(parse_baseline) {
return Ok(baseline);
}
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"auto" => Ok(ALIGN_AUTO),
"normal" => Ok(ALIGN_NORMAL),
"stretch" => Ok(ALIGN_STRETCH),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
// normal | stretch | <baseline-position>
fn parse_normal_stretch_baseline(input: &mut Parser) -> Result<AlignFlags, ()> {
fn parse_normal_stretch_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
if let Ok(baseline) = input.try(parse_baseline) {
return Ok(baseline);
}
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"normal" => Ok(ALIGN_NORMAL),
"stretch" => Ok(ALIGN_STRETCH),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
// normal | <baseline-position>
fn parse_normal_or_baseline(input: &mut Parser) -> Result<AlignFlags, ()> {
fn parse_normal_or_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
if let Ok(baseline) = input.try(parse_baseline) {
return Ok(baseline);
}
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"normal" => Ok(ALIGN_NORMAL),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
// <baseline-position>
fn parse_baseline(input: &mut Parser) -> Result<AlignFlags, ()> {
fn parse_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"baseline" => Ok(ALIGN_BASELINE),
"first" => input.expect_ident_matching("baseline").map(|_| ALIGN_BASELINE),
"last" => input.expect_ident_matching("baseline").map(|_| ALIGN_LAST_BASELINE),
"first" => return input.expect_ident_matching("baseline").map(|_| ALIGN_BASELINE).map_err(|e| e.into()),
"last" => return input.expect_ident_matching("baseline").map(|_| ALIGN_LAST_BASELINE).map_err(|e| e.into()),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
// <content-distribution>
fn parse_content_distribution(input: &mut Parser) -> Result<AlignFlags, ()> {
fn parse_content_distribution<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"stretch" => Ok(ALIGN_STRETCH),
"space-between" => Ok(ALIGN_SPACE_BETWEEN),
"space-around" => Ok(ALIGN_SPACE_AROUND),
"space-evenly" => Ok(ALIGN_SPACE_EVENLY),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
// [ <overflow-position>? && <content-position> ]
fn parse_overflow_content_position(input: &mut Parser) -> Result<AlignFlags, ()> {
fn parse_overflow_content_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
// <content-position> followed by optional <overflow-position>
if let Ok(mut content) = input.try(parse_content_position) {
if let Ok(overflow) = input.try(parse_overflow_position) {
@ -415,13 +417,13 @@ fn parse_overflow_content_position(input: &mut Parser) -> Result<AlignFlags, ()>
return Ok(overflow | content)
}
}
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
// <content-position>
fn parse_content_position(input: &mut Parser) -> Result<AlignFlags, ()> {
fn parse_content_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"start" => Ok(ALIGN_START),
"end" => Ok(ALIGN_END),
"flex-start" => Ok(ALIGN_FLEX_START),
@ -430,21 +432,21 @@ fn parse_content_position(input: &mut Parser) -> Result<AlignFlags, ()> {
"left" => Ok(ALIGN_LEFT),
"right" => Ok(ALIGN_RIGHT),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
// <overflow-position>
fn parse_overflow_position(input: &mut Parser) -> Result<AlignFlags, ()> {
fn parse_overflow_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"safe" => Ok(ALIGN_SAFE),
"unsafe" => Ok(ALIGN_UNSAFE),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
// [ <overflow-position>? && <self-position> ]
fn parse_overflow_self_position(input: &mut Parser) -> Result<AlignFlags, ()> {
fn parse_overflow_self_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
// <self-position> followed by optional <overflow-position>
if let Ok(mut self_position) = input.try(parse_self_position) {
if let Ok(overflow) = input.try(parse_overflow_position) {
@ -458,13 +460,13 @@ fn parse_overflow_self_position(input: &mut Parser) -> Result<AlignFlags, ()> {
return Ok(overflow | self_position)
}
}
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
// <self-position>
fn parse_self_position(input: &mut Parser) -> Result<AlignFlags, ()> {
fn parse_self_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
(match_ignore_ascii_case! { &ident,
"start" => Ok(ALIGN_START),
"end" => Ok(ALIGN_END),
"flex-start" => Ok(ALIGN_FLEX_START),
@ -475,28 +477,28 @@ fn parse_self_position(input: &mut Parser) -> Result<AlignFlags, ()> {
"self-start" => Ok(ALIGN_SELF_START),
"self-end" => Ok(ALIGN_SELF_END),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
// [ legacy && [ left | right | center ] ]
fn parse_legacy(input: &mut Parser) -> Result<AlignFlags, ()> {
fn parse_legacy<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
let a = input.expect_ident()?;
let b = input.expect_ident()?;
if a.eq_ignore_ascii_case("legacy") {
match_ignore_ascii_case! { &b,
(match_ignore_ascii_case! { &b,
"left" => Ok(ALIGN_LEGACY | ALIGN_LEFT),
"right" => Ok(ALIGN_LEGACY | ALIGN_RIGHT),
"center" => Ok(ALIGN_LEGACY | ALIGN_CENTER),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(b).into())
} else if b.eq_ignore_ascii_case("legacy") {
match_ignore_ascii_case! { &a,
(match_ignore_ascii_case! { &a,
"left" => Ok(ALIGN_LEGACY | ALIGN_LEFT),
"right" => Ok(ALIGN_LEGACY | ALIGN_RIGHT),
"center" => Ok(ALIGN_LEGACY | ALIGN_CENTER),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(a).into())
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}

Просмотреть файл

@ -6,6 +6,8 @@
use cssparser::Parser;
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseError;
use style_traits::ParseError;
use values::generics::background::BackgroundSize as GenericBackgroundSize;
use values::specified::length::LengthOrPercentageOrAuto;
@ -13,17 +15,18 @@ use values::specified::length::LengthOrPercentageOrAuto;
pub type BackgroundSize = GenericBackgroundSize<LengthOrPercentageOrAuto>;
impl Parse for BackgroundSize {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if let Ok(width) = input.try(|i| LengthOrPercentageOrAuto::parse_non_negative(context, i)) {
let height = input
.try(|i| LengthOrPercentageOrAuto::parse_non_negative(context, i))
.unwrap_or(LengthOrPercentageOrAuto::Auto);
return Ok(GenericBackgroundSize::Explicit { width: width, height: height });
}
match_ignore_ascii_case! { &input.expect_ident()?,
let ident = input.expect_ident()?;
(match_ignore_ascii_case! { &ident,
"cover" => Ok(GenericBackgroundSize::Cover),
"contain" => Ok(GenericBackgroundSize::Contain),
_ => Err(()),
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
}

Просмотреть файл

@ -9,9 +9,10 @@
use cssparser::Parser;
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseError;
use std::borrow::Cow;
use std::fmt;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
use values::generics::basic_shape::{Circle as GenericCircle};
use values::generics::basic_shape::{ClippingShape as GenericClippingShape, Ellipse as GenericEllipse};
use values::generics::basic_shape::{FillRule, BasicShape as GenericBasicShape};
@ -49,7 +50,7 @@ pub type ShapeRadius = GenericShapeRadius<LengthOrPercentage>;
pub type Polygon = GenericPolygon<LengthOrPercentage>;
impl<ReferenceBox: Parse> Parse for ShapeSource<BasicShape, ReferenceBox> {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
return Ok(ShapeSource::None)
}
@ -80,42 +81,43 @@ impl<ReferenceBox: Parse> Parse for ShapeSource<BasicShape, ReferenceBox> {
return Ok(ShapeSource::Shape(shp, ref_box))
}
ref_box.map(|v| ShapeSource::Box(v)).ok_or(())
ref_box.map(|v| ShapeSource::Box(v)).ok_or(StyleParseError::UnspecifiedError.into())
}
}
impl Parse for GeometryBox {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if let Ok(shape_box) = input.try(|i| ShapeBox::parse(i)) {
return Ok(GeometryBox::ShapeBox(shape_box))
}
match_ignore_ascii_case! { &input.expect_ident()?,
let ident = input.expect_ident()?;
(match_ignore_ascii_case! { &ident,
"fill-box" => Ok(GeometryBox::FillBox),
"stroke-box" => Ok(GeometryBox::StrokeBox),
"view-box" => Ok(GeometryBox::ViewBox),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
}
impl Parse for BasicShape {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let function = input.expect_function()?;
input.parse_nested_block(|i| {
match_ignore_ascii_case! { &function,
"inset" => InsetRect::parse_function_arguments(context, i).map(GenericBasicShape::Inset),
"circle" => Circle::parse_function_arguments(context, i).map(GenericBasicShape::Circle),
"ellipse" => Ellipse::parse_function_arguments(context, i).map(GenericBasicShape::Ellipse),
"polygon" => Polygon::parse_function_arguments(context, i).map(GenericBasicShape::Polygon),
input.parse_nested_block(move |i| {
(match_ignore_ascii_case! { &function,
"inset" => return InsetRect::parse_function_arguments(context, i).map(GenericBasicShape::Inset),
"circle" => return Circle::parse_function_arguments(context, i).map(GenericBasicShape::Circle),
"ellipse" => return Ellipse::parse_function_arguments(context, i).map(GenericBasicShape::Ellipse),
"polygon" => return Polygon::parse_function_arguments(context, i).map(GenericBasicShape::Polygon),
_ => Err(())
}
}).map_err(|()| StyleParseError::UnexpectedFunction(function).into())
})
}
}
impl Parse for InsetRect {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
input.expect_function_matching("inset")?;
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
}
@ -123,7 +125,8 @@ impl Parse for InsetRect {
impl InsetRect {
/// Parse the inner function arguments of `inset()`
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
pub fn parse_function_arguments<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
let rect = Rect::parse_with(context, input, LengthOrPercentage::parse)?;
let round = if input.try(|i| i.expect_ident_matching("round")).is_ok() {
Some(BorderRadius::parse(context, input)?)
@ -138,7 +141,8 @@ impl InsetRect {
}
impl Parse for Circle {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
input.expect_function_matching("circle")?;
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
}
@ -146,7 +150,8 @@ impl Parse for Circle {
impl Circle {
#[allow(missing_docs)]
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
pub fn parse_function_arguments<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
let radius = input.try(|i| ShapeRadius::parse(context, i)).ok().unwrap_or_default();
let position = if input.try(|i| i.expect_ident_matching("at")).is_ok() {
Position::parse(context, input)?
@ -176,7 +181,7 @@ impl ToCss for Circle {
}
impl Parse for Ellipse {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
input.expect_function_matching("ellipse")?;
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
}
@ -184,8 +189,9 @@ impl Parse for Ellipse {
impl Ellipse {
#[allow(missing_docs)]
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
let (a, b) = input.try(|i| -> Result<_, ()> {
pub fn parse_function_arguments<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
let (a, b) = input.try(|i| -> Result<_, ParseError> {
Ok((ShapeRadius::parse(context, i)?, ShapeRadius::parse(context, i)?))
}).ok().unwrap_or_default();
let position = if input.try(|i| i.expect_ident_matching("at")).is_ok() {
@ -219,16 +225,18 @@ impl ToCss for Ellipse {
}
impl Parse for ShapeRadius {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
return Ok(GenericShapeRadius::Length(lop))
}
match_ignore_ascii_case! { &input.expect_ident()?,
let ident = input.expect_ident()?;
(match_ignore_ascii_case! { &ident,
"closest-side" => Ok(GenericShapeRadius::ClosestSide),
"farthest-side" => Ok(GenericShapeRadius::FarthestSide),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
}
@ -300,7 +308,7 @@ fn serialize_basicshape_position<W>(position: &Position, dest: &mut W) -> fmt::R
}
impl Parse for Polygon {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
input.expect_function_matching("polygon")?;
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
}
@ -308,8 +316,9 @@ impl Parse for Polygon {
impl Polygon {
/// Parse the inner arguments of a `polygon` function.
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
let fill = input.try(|i| -> Result<_, ()> {
pub fn parse_function_arguments<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
let fill = input.try(|i| -> Result<_, ParseError> {
let fill = FillRule::parse(i)?;
i.expect_comma()?; // only eat the comma if there is something before it
Ok(fill)

Просмотреть файл

@ -7,6 +7,8 @@
use app_units::Au;
use cssparser::Parser;
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseError;
use style_traits::ParseError;
use values::computed::{Context, ToComputedValue};
use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
use values::generics::border::BorderImageSideWidth as GenericBorderImageSideWidth;
@ -47,26 +49,27 @@ pub type BorderCornerRadius = GenericBorderCornerRadius<LengthOrPercentage>;
impl BorderSideWidth {
/// Parses, with quirks.
pub fn parse_quirky(
pub fn parse_quirky<'i, 't>(
context: &ParserContext,
input: &mut Parser,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks)
-> Result<Self, ()>
-> Result<Self, ParseError<'i>>
{
if let Ok(length) = input.try(|i| Length::parse_non_negative_quirky(context, i, allow_quirks)) {
return Ok(BorderSideWidth::Length(length));
}
match_ignore_ascii_case! { &input.expect_ident()?,
let ident = input.expect_ident()?;
(match_ignore_ascii_case! { &ident,
"thin" => Ok(BorderSideWidth::Thin),
"medium" => Ok(BorderSideWidth::Medium),
"thick" => Ok(BorderSideWidth::Thick),
_ => Err(())
}
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
}
}
impl Parse for BorderSideWidth {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Self::parse_quirky(context, input, AllowQuirks::No)
}
}
@ -102,7 +105,7 @@ impl BorderImageSideWidth {
}
impl Parse for BorderImageSideWidth {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
return Ok(GenericBorderImageSideWidth::Auto);
}
@ -117,7 +120,7 @@ impl Parse for BorderImageSideWidth {
}
impl Parse for BorderImageSlice {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let mut fill = input.try(|i| i.expect_ident_matching("fill")).is_ok();
let offsets = Rect::parse_with(context, input, NumberOrPercentage::parse_non_negative)?;
if !fill {
@ -131,7 +134,7 @@ impl Parse for BorderImageSlice {
}
impl Parse for BorderRadius {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let widths = Rect::parse_with(context, input, LengthOrPercentage::parse_non_negative)?;
let heights = if input.try(|i| i.expect_delim('/')).is_ok() {
Rect::parse_with(context, input, LengthOrPercentage::parse_non_negative)?
@ -149,11 +152,11 @@ impl Parse for BorderRadius {
}
impl Parse for BorderCornerRadius {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let first = LengthOrPercentage::parse_non_negative(context, input)?;
let second = input
.try(|i| LengthOrPercentage::parse_non_negative(context, i))
.unwrap_or_else(|()| first.clone());
.unwrap_or_else(|_| first.clone());
Ok(Self::new(first, second))
}
}

Просмотреть файл

@ -7,11 +7,11 @@
//! [calc]: https://drafts.csswg.org/css-values/#calc-notation
use app_units::Au;
use cssparser::{Parser, Token};
use cssparser::{Parser, Token, BasicParseError};
use parser::ParserContext;
use std::ascii::AsciiExt;
use std::fmt;
use style_traits::{HasViewportPercentage, ToCss};
use style_traits::{HasViewportPercentage, ToCss, ParseError, StyleParseError};
use style_traits::values::specified::AllowedLengthType;
use values::{CSSInteger, CSSFloat};
use values::specified::{Angle, Time};
@ -142,11 +142,11 @@ impl CalcNode {
///
/// May return a "complex" `CalcNode`, in the presence of a parenthesized
/// expression, for example.
fn parse_one(
fn parse_one<'i, 't>(
context: &ParserContext,
input: &mut Parser,
input: &mut Parser<'i, 't>,
expected_unit: CalcUnit)
-> Result<Self, ()>
-> Result<Self, ParseError<'i>>
{
match (try!(input.next()), expected_unit) {
(Token::Number(ref value), _) => Ok(CalcNode::Number(value.value)),
@ -154,18 +154,21 @@ impl CalcNode {
(Token::Dimension(ref value, ref unit), CalcUnit::LengthOrPercentage) => {
NoCalcLength::parse_dimension(context, value.value, unit)
.map(CalcNode::Length)
.map_err(|()| StyleParseError::UnspecifiedError.into())
}
(Token::Dimension(ref value, ref unit), CalcUnit::Angle) => {
Angle::parse_dimension(value.value,
unit,
/* from_calc = */ true)
.map(CalcNode::Angle)
.map_err(|()| StyleParseError::UnspecifiedError.into())
}
(Token::Dimension(ref value, ref unit), CalcUnit::Time) => {
Time::parse_dimension(value.value,
unit,
/* from_calc = */ true)
.map(CalcNode::Time)
.map_err(|()| StyleParseError::UnspecifiedError.into())
}
(Token::Percentage(ref value), CalcUnit::LengthOrPercentage) => {
Ok(CalcNode::Percentage(value.unit_value))
@ -180,18 +183,18 @@ impl CalcNode {
CalcNode::parse(context, i, expected_unit)
})
}
_ => Err(())
(t, _) => Err(BasicParseError::UnexpectedToken(t).into())
}
}
/// Parse a top-level `calc` expression, with all nested sub-expressions.
///
/// This is in charge of parsing, for example, `2 + 3 * 100%`.
fn parse(
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser,
input: &mut Parser<'i, 't>,
expected_unit: CalcUnit)
-> Result<Self, ()>
-> Result<Self, ParseError<'i>>
{
let mut root = Self::parse_product(context, input, expected_unit)?;
@ -217,7 +220,7 @@ impl CalcNode {
CalcNode::Sub(Box::new(root), Box::new(rhs));
root = new_root;
}
_ => return Err(()),
t => return Err(BasicParseError::UnexpectedToken(t).into()),
}
}
_ => {
@ -239,11 +242,11 @@ impl CalcNode {
/// * `2 * 2`
/// * `2 * 2 + 2` (but will leave the `+ 2` unparsed).
///
fn parse_product(
fn parse_product<'i, 't>(
context: &ParserContext,
input: &mut Parser,
input: &mut Parser<'i, 't>,
expected_unit: CalcUnit)
-> Result<Self, ()>
-> Result<Self, ParseError<'i>>
{
let mut root = Self::parse_one(context, input, expected_unit)?;
@ -491,65 +494,71 @@ impl CalcNode {
}
/// Convenience parsing function for integers.
pub fn parse_integer(
pub fn parse_integer<'i, 't>(
context: &ParserContext,
input: &mut Parser)
-> Result<CSSInteger, ()>
input: &mut Parser<'i, 't>)
-> Result<CSSInteger, ParseError<'i>>
{
Self::parse(context, input, CalcUnit::Integer)?
.to_number()
.map(|n| n as CSSInteger)
.map_err(|()| StyleParseError::UnspecifiedError.into())
}
/// Convenience parsing function for `<length> | <percentage>`.
pub fn parse_length_or_percentage(
pub fn parse_length_or_percentage<'i, 't>(
context: &ParserContext,
input: &mut Parser,
input: &mut Parser<'i, 't>,
clamping_mode: AllowedLengthType)
-> Result<CalcLengthOrPercentage, ()>
-> Result<CalcLengthOrPercentage, ParseError<'i>>
{
Self::parse(context, input, CalcUnit::LengthOrPercentage)?
.to_length_or_percentage(clamping_mode)
.map_err(|()| StyleParseError::UnspecifiedError.into())
}
/// Convenience parsing function for `<length>`.
pub fn parse_length(
pub fn parse_length<'i, 't>(
context: &ParserContext,
input: &mut Parser,
input: &mut Parser<'i, 't>,
clamping_mode: AllowedLengthType)
-> Result<CalcLengthOrPercentage, ()>
-> Result<CalcLengthOrPercentage, ParseError<'i>>
{
Self::parse(context, input, CalcUnit::Length)?
.to_length_or_percentage(clamping_mode)
.map_err(|()| StyleParseError::UnspecifiedError.into())
}
/// Convenience parsing function for `<number>`.
pub fn parse_number(
pub fn parse_number<'i, 't>(
context: &ParserContext,
input: &mut Parser)
-> Result<CSSFloat, ()>
input: &mut Parser<'i, 't>)
-> Result<CSSFloat, ParseError<'i>>
{
Self::parse(context, input, CalcUnit::Number)?
.to_number()
.map_err(|()| StyleParseError::UnspecifiedError.into())
}
/// Convenience parsing function for `<angle>`.
pub fn parse_angle(
pub fn parse_angle<'i, 't>(
context: &ParserContext,
input: &mut Parser)
-> Result<Angle, ()>
input: &mut Parser<'i, 't>)
-> Result<Angle, ParseError<'i>>
{
Self::parse(context, input, CalcUnit::Angle)?
.to_angle()
.map_err(|()| StyleParseError::UnspecifiedError.into())
}
/// Convenience parsing function for `<time>`.
pub fn parse_time(
pub fn parse_time<'i, 't>(
context: &ParserContext,
input: &mut Parser)
-> Result<Time, ()>
input: &mut Parser<'i, 't>)
-> Result<Time, ParseError<'i>>
{
Self::parse(context, input, CalcUnit::Time)?
.to_time()
.map_err(|()| StyleParseError::UnspecifiedError.into())
}
}

Просмотреть файл

@ -4,7 +4,7 @@
//! Specified color values.
use cssparser::{Color as CSSParserColor, Parser, RGBA, Token};
use cssparser::{Color as CSSParserColor, Parser, RGBA, Token, BasicParseError};
#[cfg(feature = "gecko")]
use gecko_bindings::structs::nscolor;
use itoa;
@ -13,7 +13,7 @@ use parser::{ParserContext, Parse};
use properties::longhands::color::SystemColor;
use std::fmt;
use std::io::Write;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
use super::AllowQuirks;
use values::computed::{Color as ComputedColor, Context, ToComputedValue};
@ -66,7 +66,7 @@ impl From<RGBA> for Color {
}
impl Parse for Color {
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
// Currently we only store authored value for color keywords,
// because all browsers serialize those values as keywords for
// specified value.
@ -93,7 +93,7 @@ impl Parse for Color {
}
}
#[cfg(not(feature = "gecko"))] {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
}
@ -157,13 +157,13 @@ impl Color {
/// Parse a color, with quirks.
///
/// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
pub fn parse_quirky(context: &ParserContext,
input: &mut Parser,
allow_quirks: AllowQuirks)
-> Result<Self, ()> {
pub fn parse_quirky<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks)
-> Result<Self, ParseError<'i>> {
input.try(|i| Self::parse(context, i)).or_else(|_| {
if !allow_quirks.allowed(context.quirks_mode) {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Color::parse_quirky_color(input).map(|rgba| Color::rgba(rgba))
})
@ -172,7 +172,7 @@ impl Color {
/// Parse a <quirky-color> value.
///
/// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
fn parse_quirky_color(input: &mut Parser) -> Result<RGBA, ()> {
fn parse_quirky_color<'i, 't>(input: &mut Parser<'i, 't>) -> Result<RGBA, ParseError<'i>> {
let (number, dimension) = match input.next()? {
Token::Number(number) => {
(number, None)
@ -182,17 +182,18 @@ impl Color {
},
Token::Ident(ident) => {
if ident.len() != 3 && ident.len() != 6 {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
return parse_hash_color(ident.as_bytes());
return parse_hash_color(ident.as_bytes())
.map_err(|()| StyleParseError::UnspecifiedError.into());
}
_ => {
return Err(());
t => {
return Err(BasicParseError::UnexpectedToken(t).into());
},
};
let value = number.int_value.ok_or(())?;
let value = number.int_value.ok_or(StyleParseError::UnspecifiedError)?;
if value < 0 {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
let length = if value <= 9 {
1
@ -207,11 +208,11 @@ impl Color {
} else if value <= 999999 {
6
} else {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
};
let total = length + dimension.as_ref().map_or(0, |d| d.len());
if total > 6 {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
let mut serialization = [b'0'; 6];
let space_padding = 6 - total;
@ -221,7 +222,7 @@ impl Color {
written += (&mut serialization[written..]).write(dimension.as_bytes()).unwrap();
}
debug_assert!(written == 6);
parse_hash_color(&serialization)
parse_hash_color(&serialization).map_err(|()| StyleParseError::UnspecifiedError.into())
}
/// Returns false if the color is completely transparent, and
@ -306,7 +307,7 @@ pub struct RGBAColor(pub Color);
no_viewport_percentage!(RGBAColor);
impl Parse for RGBAColor {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Color::parse(context, input).map(RGBAColor)
}
}

Просмотреть файл

@ -6,6 +6,7 @@
use cssparser::Parser;
use parser::{Parse, ParserContext};
use style_traits::ParseError;
use values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint;
use values::specified::length::LengthOrPercentage;
@ -13,7 +14,7 @@ use values::specified::length::LengthOrPercentage;
pub type ScrollSnapPoint = GenericScrollSnapPoint<LengthOrPercentage>;
impl Parse for ScrollSnapPoint {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
return Ok(GenericScrollSnapPoint::None);
}

Просмотреть файл

@ -5,11 +5,11 @@
//! CSS handling for the computed value of
//! [grids](https://drafts.csswg.org/css-grid/)
use cssparser::{Parser, Token};
use cssparser::{Parser, Token, BasicParseError};
use parser::{Parse, ParserContext};
use std::{mem, usize};
use std::ascii::AsciiExt;
use style_traits::HasViewportPercentage;
use style_traits::{HasViewportPercentage, ParseError, StyleParseError};
use values::{CSSFloat, CustomIdent, Either};
use values::computed::{self, Context, ToComputedValue};
use values::generics::grid::{RepeatCount, TrackBreadth, TrackKeyword, TrackRepeat};
@ -17,16 +17,16 @@ use values::generics::grid::{TrackSize, TrackList, TrackListType};
use values::specified::LengthOrPercentage;
/// Parse a single flexible length.
pub fn parse_flex(input: &mut Parser) -> Result<CSSFloat, ()> {
pub fn parse_flex<'i, 't>(input: &mut Parser<'i, 't>) -> Result<CSSFloat, ParseError<'i>> {
match input.next()? {
Token::Dimension(ref value, ref unit) if unit.eq_ignore_ascii_case("fr") && value.value.is_sign_positive()
=> Ok(value.value),
_ => Err(()),
t => Err(BasicParseError::UnexpectedToken(t).into()),
}
}
impl Parse for TrackBreadth<LengthOrPercentage> {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
return Ok(TrackBreadth::Breadth(lop))
}
@ -51,7 +51,7 @@ impl HasViewportPercentage for TrackBreadth<LengthOrPercentage> {
}
impl Parse for TrackSize<LengthOrPercentage> {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if let Ok(b) = input.try(|i| TrackBreadth::parse(context, i)) {
return Ok(TrackSize::Breadth(b))
}
@ -81,13 +81,13 @@ impl Parse for TrackSize<LengthOrPercentage> {
/// Parse the grid line names into a vector of owned strings.
///
/// https://drafts.csswg.org/css-grid/#typedef-line-names
pub fn parse_line_names(input: &mut Parser) -> Result<Vec<String>, ()> {
pub fn parse_line_names<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Vec<String>, ParseError<'i>> {
input.expect_square_bracket_block()?;
input.parse_nested_block(|input| {
let mut values = vec![];
while let Ok(ident) = input.try(|i| i.expect_ident()) {
if CustomIdent::from_ident((&*ident).into(), &["span"]).is_err() {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
values.push(ident.into_owned());
@ -112,9 +112,10 @@ enum RepeatType {
}
impl TrackRepeat<LengthOrPercentage> {
fn parse_with_repeat_type(context: &ParserContext, input: &mut Parser)
-> Result<(TrackRepeat<LengthOrPercentage>, RepeatType), ()> {
input.try(|i| i.expect_function_matching("repeat")).and_then(|_| {
fn parse_with_repeat_type<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<(TrackRepeat<LengthOrPercentage>, RepeatType),
ParseError<'i>> {
input.try(|i| i.expect_function_matching("repeat").map_err(|e| e.into())).and_then(|_| {
input.parse_nested_block(|input| {
let count = RepeatCount::parse(context, input)?;
input.expect_comma()?;
@ -135,7 +136,8 @@ impl TrackRepeat<LengthOrPercentage> {
if let Ok(track_size) = input.try(|i| TrackSize::parse(context, i)) {
if !track_size.is_fixed() {
if is_auto {
return Err(()) // should be <fixed-size> for <auto-repeat>
// should be <fixed-size> for <auto-repeat>
return Err(StyleParseError::UnspecifiedError.into())
}
if repeat_type == RepeatType::Fixed {
@ -147,7 +149,8 @@ impl TrackRepeat<LengthOrPercentage> {
names.push(current_names);
} else {
if values.is_empty() {
return Err(()) // expecting at least one <track-size>
// expecting at least one <track-size>
return Err(StyleParseError::UnspecifiedError.into())
}
names.push(current_names); // final `<line-names>`
@ -181,7 +184,7 @@ impl HasViewportPercentage for TrackRepeat<LengthOrPercentage> {
pub type TrackSizeOrRepeat = Either<TrackSize<LengthOrPercentage>, TrackRepeat<LengthOrPercentage>>;
impl Parse for TrackList<TrackSizeOrRepeat> {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let mut current_names;
let mut names = vec![];
let mut values = vec![];
@ -198,7 +201,8 @@ impl Parse for TrackList<TrackSizeOrRepeat> {
if !track_size.is_fixed() {
atleast_one_not_fixed = true;
if is_auto {
return Err(()) // <auto-track-list> only accepts <fixed-size> and <fixed-repeat>
// <auto-track-list> only accepts <fixed-size> and <fixed-repeat>
return Err(StyleParseError::UnspecifiedError.into())
}
}
@ -213,13 +217,13 @@ impl Parse for TrackList<TrackSizeOrRepeat> {
RepeatType::Normal => {
atleast_one_not_fixed = true;
if is_auto { // only <fixed-repeat>
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
},
RepeatType::Auto => {
if is_auto || atleast_one_not_fixed {
// We've either seen <auto-repeat> earlier, or there's at least one non-fixed value
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
is_auto = true;
@ -232,7 +236,7 @@ impl Parse for TrackList<TrackSizeOrRepeat> {
values.push(Either::Second(repeat));
} else {
if values.is_empty() {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
names.push(current_names);

Просмотреть файл

@ -8,14 +8,15 @@
//! [image]: https://drafts.csswg.org/css-images/#image-values
use Atom;
use cssparser::{Parser, Token};
use cssparser::{Parser, Token, BasicParseError};
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseError;
#[cfg(feature = "servo")]
use servo_url::ServoUrl;
use std::cmp::Ordering;
use std::f32::consts::PI;
use std::fmt;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
use values::{Either, None_};
use values::generics::image::{Circle, CompatMode, Ellipse, ColorStop as GenericColorStop};
use values::generics::image::{EndingShape as GenericEndingShape, Gradient as GenericGradient};
@ -82,7 +83,7 @@ pub type ColorStop = GenericColorStop<RGBAColor, LengthOrPercentage>;
pub type ImageRect = GenericImageRect<NumberOrPercentage>;
impl Parse for Image {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Image, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Image, ParseError<'i>> {
#[cfg(feature = "gecko")]
{
if let Ok(mut url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
@ -132,53 +133,59 @@ impl Image {
}
/// Parses a `-moz-element(# <element-id>)`.
fn parse_element(input: &mut Parser) -> Result<Atom, ()> {
fn parse_element<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Atom, ParseError<'i>> {
input.try(|i| i.expect_function_matching("-moz-element"))?;
input.parse_nested_block(|i| {
match i.next()? {
Token::IDHash(id) => Ok(Atom::from(id)),
_ => Err(()),
t => Err(BasicParseError::UnexpectedToken(t).into()),
}
})
}
}
impl Parse for Gradient {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
enum Shape {
Linear,
Radial,
}
let (shape, repeating, compat_mode) = match_ignore_ascii_case! { &try!(input.expect_function()),
let func = try!(input.expect_function());
let result = match_ignore_ascii_case! { &func,
"linear-gradient" => {
(Shape::Linear, false, CompatMode::Modern)
Some((Shape::Linear, false, CompatMode::Modern))
},
"-webkit-linear-gradient" => {
(Shape::Linear, false, CompatMode::WebKit)
Some((Shape::Linear, false, CompatMode::WebKit))
},
"repeating-linear-gradient" => {
(Shape::Linear, true, CompatMode::Modern)
Some((Shape::Linear, true, CompatMode::Modern))
},
"-webkit-repeating-linear-gradient" => {
(Shape::Linear, true, CompatMode::WebKit)
Some((Shape::Linear, true, CompatMode::WebKit))
},
"radial-gradient" => {
(Shape::Radial, false, CompatMode::Modern)
Some((Shape::Radial, false, CompatMode::Modern))
},
"-webkit-radial-gradient" => {
(Shape::Radial, false, CompatMode::WebKit)
Some((Shape::Radial, false, CompatMode::WebKit))
},
"repeating-radial-gradient" => {
(Shape::Radial, true, CompatMode::Modern)
Some((Shape::Radial, true, CompatMode::Modern))
},
"-webkit-repeating-radial-gradient" => {
(Shape::Radial, true, CompatMode::WebKit)
Some((Shape::Radial, true, CompatMode::WebKit))
},
"-webkit-gradient" => {
return input.parse_nested_block(|i| Self::parse_webkit_gradient_argument(context, i));
},
_ => { return Err(()); }
_ => None,
};
let (shape, repeating, compat_mode) = match result {
Some(result) => result,
None => return Err(StyleParseError::UnexpectedFunction(func).into()),
};
let (kind, items) = input.parse_nested_block(|i| {
@ -191,7 +198,7 @@ impl Parse for Gradient {
})?;
if items.len() < 2 {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(Gradient {
@ -204,7 +211,8 @@ impl Parse for Gradient {
}
impl Gradient {
fn parse_webkit_gradient_argument(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse_webkit_gradient_argument<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
type Point = GenericPosition<Component<X>, Component<Y>>;
#[derive(Clone, Copy)]
@ -259,7 +267,8 @@ impl Gradient {
}
impl Parse for Point {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
input.try(|i| {
let x = Component::parse(context, i)?;
let y = Component::parse(context, i)?;
@ -318,7 +327,8 @@ impl Gradient {
}
impl<S: Parse> Parse for Component<S> {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
if let Ok(side) = input.try(|i| S::parse(context, i)) {
return Ok(Component::Side(side));
}
@ -365,7 +375,7 @@ impl Gradient {
(kind, reverse_stops)
},
_ => return Err(()),
_ => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()),
};
let mut items = input.try(|i| {
@ -384,11 +394,11 @@ impl Gradient {
},
"from" => 0.,
"to" => 1.,
_ => return Err(()),
_ => return Err(StyleParseError::UnexpectedFunction(function.clone()).into()),
};
let color = Color::parse(context, i)?;
if color == Color::CurrentColor {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok((color.into(), p))
})?;
@ -450,10 +460,10 @@ impl Gradient {
}
impl GradientKind {
fn parse_linear(context: &ParserContext,
input: &mut Parser,
compat_mode: CompatMode)
-> Result<Self, ()> {
fn parse_linear<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
compat_mode: CompatMode)
-> Result<Self, ParseError<'i>> {
let direction = if let Ok(d) = input.try(|i| LineDirection::parse(context, i, compat_mode)) {
input.expect_comma()?;
d
@ -463,10 +473,10 @@ impl GradientKind {
Ok(GenericGradientKind::Linear(direction))
}
fn parse_radial(context: &ParserContext,
input: &mut Parser,
compat_mode: CompatMode)
-> Result<Self, ()> {
fn parse_radial<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
compat_mode: CompatMode)
-> Result<Self, ParseError<'i>> {
let (shape, position) = if compat_mode == CompatMode::Modern {
let shape = input.try(|i| EndingShape::parse(context, i, compat_mode));
let position = input.try(|i| {
@ -538,10 +548,10 @@ impl GenericsLineDirection for LineDirection {
}
impl LineDirection {
fn parse(context: &ParserContext,
input: &mut Parser,
compat_mode: CompatMode)
-> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
compat_mode: CompatMode)
-> Result<Self, ParseError<'i>> {
if let Ok(angle) = input.try(|i| Angle::parse_with_unitless(context, i)) {
return Ok(LineDirection::Angle(angle));
}
@ -565,10 +575,10 @@ impl LineDirection {
}
impl EndingShape {
fn parse(context: &ParserContext,
input: &mut Parser,
compat_mode: CompatMode)
-> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
compat_mode: CompatMode)
-> Result<Self, ParseError<'i>> {
if let Ok(extent) = input.try(|i| ShapeExtent::parse_with_compat_mode(i, compat_mode)) {
if input.try(|i| i.expect_ident_matching("circle")).is_ok() {
return Ok(GenericEndingShape::Circle(Circle::Extent(extent)));
@ -592,7 +602,7 @@ impl EndingShape {
return Ok(GenericEndingShape::Ellipse(Ellipse::Extent(extent)));
}
if compat_mode == CompatMode::Modern {
let pair: Result<_, ()> = input.try(|i| {
let pair: Result<_, ParseError> = input.try(|i| {
let x = LengthOrPercentage::parse(context, i)?;
let y = LengthOrPercentage::parse(context, i)?;
Ok((x, y))
@ -641,18 +651,20 @@ impl EndingShape {
}
impl ShapeExtent {
fn parse_with_compat_mode(input: &mut Parser,
compat_mode: CompatMode)
-> Result<Self, ()> {
fn parse_with_compat_mode<'i, 't>(input: &mut Parser<'i, 't>,
compat_mode: CompatMode)
-> Result<Self, ParseError<'i>> {
match try!(Self::parse(input)) {
ShapeExtent::Contain | ShapeExtent::Cover if compat_mode == CompatMode::Modern => Err(()),
ShapeExtent::Contain | ShapeExtent::Cover if compat_mode == CompatMode::Modern =>
Err(StyleParseError::UnspecifiedError.into()),
keyword => Ok(keyword),
}
}
}
impl GradientItem {
fn parse_comma_separated(context: &ParserContext, input: &mut Parser) -> Result<Vec<Self>, ()> {
fn parse_comma_separated<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Vec<Self>, ParseError<'i>> {
let mut seen_stop = false;
let items = try!(input.parse_comma_separated(|input| {
if seen_stop {
@ -665,14 +677,15 @@ impl GradientItem {
ColorStop::parse(context, input).map(GenericGradientItem::ColorStop)
}));
if !seen_stop || items.len() < 2 {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
Ok(items)
}
}
impl Parse for ColorStop {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
Ok(ColorStop {
color: try!(RGBAColor::parse(context, input)),
position: input.try(|i| LengthOrPercentage::parse(context, i)).ok(),
@ -681,7 +694,7 @@ impl Parse for ColorStop {
}
impl Parse for PaintWorklet {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
input.expect_function_matching("paint")?;
input.parse_nested_block(|i| {
let name = i.expect_ident()?;
@ -693,7 +706,7 @@ impl Parse for PaintWorklet {
}
impl Parse for ImageRect {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
input.try(|i| i.expect_function_matching("-moz-image-rect"))?;
input.parse_nested_block(|i| {
let string = i.expect_url_or_string()?;

Просмотреть файл

@ -7,14 +7,14 @@
//! [length]: https://drafts.csswg.org/css-values/#lengths
use app_units::Au;
use cssparser::{Parser, Token};
use cssparser::{Parser, Token, BasicParseError};
use euclid::size::Size2D;
use font_metrics::FontMetricsQueryResult;
use parser::{Parse, ParserContext};
use std::{cmp, fmt, mem};
use std::ascii::AsciiExt;
use std::ops::Mul;
use style_traits::{HasViewportPercentage, ToCss};
use style_traits::{HasViewportPercentage, ToCss, ParseError, StyleParseError};
use style_traits::values::specified::{AllowedLengthType, AllowedNumericType};
use stylesheets::CssRuleType;
use super::{AllowQuirks, Number, ToComputedValue};
@ -451,7 +451,8 @@ impl Mul<CSSFloat> for NoCalcLength {
impl NoCalcLength {
/// Parse a given absolute or relative dimension.
pub fn parse_dimension(context: &ParserContext, value: CSSFloat, unit: &str) -> Result<NoCalcLength, ()> {
pub fn parse_dimension(context: &ParserContext, value: CSSFloat, unit: &str)
-> Result<NoCalcLength, ()> {
let in_page_rule = context.rule_type.map_or(false, |rule_type| rule_type == CssRuleType::Page);
match_ignore_ascii_case! { unit,
"px" => Ok(NoCalcLength::Absolute(AbsoluteLength::Px(value))),
@ -597,47 +598,50 @@ impl Length {
}
/// Parse a given absolute or relative dimension.
pub fn parse_dimension(context: &ParserContext, value: CSSFloat, unit: &str) -> Result<Length, ()> {
pub fn parse_dimension(context: &ParserContext, value: CSSFloat, unit: &str)
-> Result<Length, ()> {
NoCalcLength::parse_dimension(context, value, unit).map(Length::NoCalc)
}
#[inline]
fn parse_internal(context: &ParserContext,
input: &mut Parser,
num_context: AllowedLengthType,
allow_quirks: AllowQuirks)
-> Result<Length, ()> {
match try!(input.next()) {
fn parse_internal<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
num_context: AllowedLengthType,
allow_quirks: AllowQuirks)
-> Result<Length, ParseError<'i>> {
let token = try!(input.next());
match token {
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
Length::parse_dimension(context, value.value, unit),
Token::Number(ref value) if num_context.is_ok(value.value) => {
if value.value != 0. &&
!context.parsing_mode.allows_unitless_lengths() &&
!allow_quirks.allowed(context.quirks_mode) {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
Ok(Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(value.value))))
},
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") =>
input.parse_nested_block(|input| {
return input.parse_nested_block(|input| {
CalcNode::parse_length(context, input, num_context).map(|calc| Length::Calc(Box::new(calc)))
}),
_ => Err(())
}
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
}
/// Parse a non-negative length
#[inline]
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Length, ()> {
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Length, ParseError<'i>> {
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
}
/// Parse a non-negative length, allowing quirks.
#[inline]
pub fn parse_non_negative_quirky(context: &ParserContext,
input: &mut Parser,
allow_quirks: AllowQuirks)
-> Result<Length, ()> {
pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks)
-> Result<Length, ParseError<'i>> {
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
}
@ -657,17 +661,17 @@ impl Length {
}
impl Parse for Length {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Self::parse_quirky(context, input, AllowQuirks::No)
}
}
impl Length {
/// Parses a length, with quirks.
pub fn parse_quirky(context: &ParserContext,
input: &mut Parser,
allow_quirks: AllowQuirks)
-> Result<Self, ()> {
pub fn parse_quirky<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks)
-> Result<Self, ParseError<'i>> {
Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks)
}
}
@ -675,7 +679,8 @@ impl Length {
impl<T: Parse> Either<Length, T> {
/// Parse a non-negative length
#[inline]
pub fn parse_non_negative_length(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
pub fn parse_non_negative_length<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
if let Ok(v) = input.try(|input| T::parse(context, input)) {
return Ok(Either::Second(v));
}
@ -710,19 +715,19 @@ impl ToCss for Percentage {
impl Percentage {
/// Parse a specific kind of percentage.
pub fn parse_with_clamping_mode(input: &mut Parser,
context: AllowedNumericType)
-> Result<Self, ()> {
pub fn parse_with_clamping_mode<'i, 't>(input: &mut Parser<'i, 't>,
context: AllowedNumericType)
-> Result<Self, ParseError<'i>> {
match try!(input.next()) {
Token::Percentage(ref value) if context.is_ok(value.unit_value) => {
Ok(Percentage(value.unit_value))
}
_ => Err(())
t => Err(BasicParseError::UnexpectedToken(t).into())
}
}
/// Parses a percentage token, but rejects it if it's negative.
pub fn parse_non_negative(input: &mut Parser) -> Result<Self, ()> {
pub fn parse_non_negative<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Self::parse_with_clamping_mode(input, AllowedNumericType::NonNegative)
}
@ -741,7 +746,7 @@ impl Percentage {
impl Parse for Percentage {
#[inline]
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Self::parse_with_clamping_mode(input, AllowedNumericType::All)
}
}
@ -788,54 +793,58 @@ impl LengthOrPercentage {
LengthOrPercentage::Length(NoCalcLength::zero())
}
fn parse_internal(context: &ParserContext,
input: &mut Parser,
num_context: AllowedLengthType,
allow_quirks: AllowQuirks)
-> Result<LengthOrPercentage, ()>
fn parse_internal<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
num_context: AllowedLengthType,
allow_quirks: AllowQuirks)
-> Result<LengthOrPercentage, ParseError<'i>>
{
match try!(input.next()) {
let token = try!(input.next());
match token {
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentage::Length),
Token::Percentage(ref value) if num_context.is_ok(value.unit_value) =>
Ok(LengthOrPercentage::Percentage(Percentage(value.unit_value))),
return Ok(LengthOrPercentage::Percentage(Percentage(value.unit_value))),
Token::Number(value) if num_context.is_ok(value.value) => {
if value.value != 0. &&
!context.parsing_mode.allows_unitless_lengths() &&
!allow_quirks.allowed(context.quirks_mode) {
return Err(())
Err(())
} else {
return Ok(LengthOrPercentage::Length(NoCalcLength::from_px(value.value)))
}
Ok(LengthOrPercentage::Length(NoCalcLength::from_px(value.value)))
}
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
let calc = try!(input.parse_nested_block(|i| {
CalcNode::parse_length_or_percentage(context, i, num_context)
}));
Ok(LengthOrPercentage::Calc(Box::new(calc)))
return Ok(LengthOrPercentage::Calc(Box::new(calc)))
},
_ => Err(())
}
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
}
/// Parse a non-negative length.
#[inline]
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<LengthOrPercentage, ()> {
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<LengthOrPercentage, ParseError<'i>> {
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
}
/// Parse a non-negative length, with quirks.
#[inline]
pub fn parse_non_negative_quirky(context: &ParserContext,
input: &mut Parser,
allow_quirks: AllowQuirks)
-> Result<LengthOrPercentage, ()> {
pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks)
-> Result<LengthOrPercentage, ParseError<'i>> {
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
}
/// Parse a length, treating dimensionless numbers as pixels
///
/// https://www.w3.org/TR/SVG2/types.html#presentation-attribute-css-value
pub fn parse_numbers_are_pixels(context: &ParserContext, input: &mut Parser) -> Result<LengthOrPercentage, ()> {
pub fn parse_numbers_are_pixels<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<LengthOrPercentage, ParseError<'i>> {
if let Ok(lop) = input.try(|i| Self::parse(context, i)) {
return Ok(lop)
}
@ -849,9 +858,9 @@ impl LengthOrPercentage {
/// Parse a non-negative length, treating dimensionless numbers as pixels
///
/// This is nonstandard behavior used by Firefox for SVG
pub fn parse_numbers_are_pixels_non_negative(context: &ParserContext,
input: &mut Parser)
-> Result<LengthOrPercentage, ()> {
pub fn parse_numbers_are_pixels_non_negative<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>)
-> Result<LengthOrPercentage, ParseError<'i>> {
if let Ok(lop) = input.try(|i| Self::parse_non_negative(context, i)) {
return Ok(lop)
}
@ -862,7 +871,7 @@ impl LengthOrPercentage {
if num >= 0. {
Ok(LengthOrPercentage::Length(NoCalcLength::Absolute(AbsoluteLength::Px(num))))
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
@ -877,7 +886,7 @@ impl LengthOrPercentage {
impl Parse for LengthOrPercentage {
#[inline]
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Self::parse_quirky(context, input, AllowQuirks::No)
}
}
@ -886,9 +895,9 @@ impl LengthOrPercentage {
/// Parses a length or a percentage, allowing the unitless length quirk.
/// https://quirks.spec.whatwg.org/#the-unitless-length-quirk
#[inline]
pub fn parse_quirky(context: &ParserContext,
input: &mut Parser,
allow_quirks: AllowQuirks) -> Result<Self, ()> {
pub fn parse_quirky<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks)
}
}
@ -919,12 +928,13 @@ impl From<Percentage> for LengthOrPercentageOrAuto {
}
impl LengthOrPercentageOrAuto {
fn parse_internal(context: &ParserContext,
input: &mut Parser,
num_context: AllowedLengthType,
allow_quirks: AllowQuirks)
-> Result<Self, ()> {
match try!(input.next()) {
fn parse_internal<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
num_context: AllowedLengthType,
allow_quirks: AllowQuirks)
-> Result<Self, ParseError<'i>> {
let token = try!(input.next());
match token {
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentageOrAuto::Length),
Token::Percentage(ref value) if num_context.is_ok(value.unit_value) =>
@ -933,7 +943,7 @@ impl LengthOrPercentageOrAuto {
if value.value != 0. &&
!context.parsing_mode.allows_unitless_lengths() &&
!allow_quirks.allowed(context.quirks_mode) {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
Ok(LengthOrPercentageOrAuto::Length(
NoCalcLength::Absolute(AbsoluteLength::Px(value.value))
@ -948,21 +958,22 @@ impl LengthOrPercentageOrAuto {
Ok(LengthOrPercentageOrAuto::Calc(Box::new(calc)))
},
_ => Err(())
}
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
}
/// Parse a non-negative length, percentage, or auto.
#[inline]
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<LengthOrPercentageOrAuto, ()> {
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<LengthOrPercentageOrAuto, ParseError<'i>> {
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
}
/// Parse a non-negative length, percentage, or auto.
#[inline]
pub fn parse_non_negative_quirky(context: &ParserContext,
input: &mut Parser,
allow_quirks: AllowQuirks)
-> Result<Self, ()> {
pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks)
-> Result<Self, ParseError<'i>> {
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
}
@ -984,7 +995,7 @@ impl LengthOrPercentageOrAuto {
impl Parse for LengthOrPercentageOrAuto {
#[inline]
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Self::parse_quirky(context, input, AllowQuirks::No)
}
}
@ -992,10 +1003,10 @@ impl Parse for LengthOrPercentageOrAuto {
impl LengthOrPercentageOrAuto {
/// Parses, with quirks.
#[inline]
pub fn parse_quirky(context: &ParserContext,
input: &mut Parser,
allow_quirks: AllowQuirks)
-> Result<Self, ()> {
pub fn parse_quirky<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks)
-> Result<Self, ParseError<'i>> {
Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks)
}
}
@ -1012,13 +1023,14 @@ pub enum LengthOrPercentageOrNone {
}
impl LengthOrPercentageOrNone {
fn parse_internal(context: &ParserContext,
input: &mut Parser,
num_context: AllowedLengthType,
allow_quirks: AllowQuirks)
-> Result<LengthOrPercentageOrNone, ()>
fn parse_internal<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
num_context: AllowedLengthType,
allow_quirks: AllowQuirks)
-> Result<LengthOrPercentageOrNone, ParseError<'i>>
{
match try!(input.next()) {
let token = try!(input.next());
match token {
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentageOrNone::Length),
Token::Percentage(ref value) if num_context.is_ok(value.unit_value) =>
@ -1026,7 +1038,7 @@ impl LengthOrPercentageOrNone {
Token::Number(value) if num_context.is_ok(value.value) => {
if value.value != 0. && !context.parsing_mode.allows_unitless_lengths() &&
!allow_quirks.allowed(context.quirks_mode) {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
Ok(LengthOrPercentageOrNone::Length(
NoCalcLength::Absolute(AbsoluteLength::Px(value.value))
@ -1041,28 +1053,29 @@ impl LengthOrPercentageOrNone {
Token::Ident(ref value) if value.eq_ignore_ascii_case("none") =>
Ok(LengthOrPercentageOrNone::None),
_ => Err(())
}
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
}
/// Parse a non-negative LengthOrPercentageOrNone.
#[inline]
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
}
/// Parse a non-negative LengthOrPercentageOrNone, with quirks.
#[inline]
pub fn parse_non_negative_quirky(context: &ParserContext,
input: &mut Parser,
allow_quirks: AllowQuirks)
-> Result<Self, ()> {
pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks)
-> Result<Self, ParseError<'i>> {
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
}
}
impl Parse for LengthOrPercentageOrNone {
#[inline]
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Self::parse_internal(context, input, AllowedLengthType::All, AllowQuirks::No)
}
}
@ -1095,9 +1108,11 @@ pub enum LengthOrPercentageOrAutoOrContent {
impl LengthOrPercentageOrAutoOrContent {
/// Parse a non-negative LengthOrPercentageOrAutoOrContent.
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
let num_context = AllowedLengthType::NonNegative;
match try!(input.next()) {
let token = try!(input.next());
match token {
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
NoCalcLength::parse_dimension(context, value.value, unit)
.map(LengthOrPercentageOrAutoOrContent::Length),
@ -1116,7 +1131,7 @@ impl LengthOrPercentageOrAutoOrContent {
Ok(LengthOrPercentageOrAutoOrContent::Calc(Box::new(calc)))
},
_ => Err(())
}
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
}
/// Returns the `auto` value.
@ -1140,7 +1155,8 @@ pub type LengthOrNumber = Either<Length, Number>;
impl LengthOrNumber {
/// Parse a non-negative LengthOrNumber.
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
// We try to parse as a Number first because, for cases like
// LengthOrNumber, we want "0" to be parsed as a plain Number rather
// than a Length (0px); this matches the behaviour of all major browsers
@ -1170,18 +1186,18 @@ pub enum MozLength {
}
impl Parse for MozLength {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
MozLength::parse_quirky(context, input, AllowQuirks::No)
}
}
impl MozLength {
/// Parses, with quirks.
pub fn parse_quirky(context: &ParserContext,
input: &mut Parser,
allow_quirks: AllowQuirks) -> Result<Self, ()> {
pub fn parse_quirky<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
input.try(ExtremumLength::parse).map(MozLength::ExtremumLength)
.or_else(|()| input.try(|i| LengthOrPercentageOrAuto::parse_non_negative_quirky(context, i, allow_quirks))
.or_else(|_| input.try(|i| LengthOrPercentageOrAuto::parse_non_negative_quirky(context, i, allow_quirks))
.map(MozLength::LengthOrPercentageOrAuto))
}
}
@ -1196,18 +1212,18 @@ pub enum MaxLength {
}
impl Parse for MaxLength {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
MaxLength::parse_quirky(context, input, AllowQuirks::No)
}
}
impl MaxLength {
/// Parses, with quirks.
pub fn parse_quirky(context: &ParserContext,
input: &mut Parser,
allow_quirks: AllowQuirks) -> Result<Self, ()> {
pub fn parse_quirky<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
input.try(ExtremumLength::parse).map(MaxLength::ExtremumLength)
.or_else(|()| input.try(|i| LengthOrPercentageOrNone::parse_non_negative_quirky(context, i, allow_quirks))
.or_else(|_| input.try(|i| LengthOrPercentageOrNone::parse_non_negative_quirky(context, i, allow_quirks))
.map(MaxLength::LengthOrPercentageOrNone))
}
}

Просмотреть файл

@ -8,14 +8,14 @@
use Namespace;
use context::QuirksMode;
use cssparser::{Parser, Token, serialize_identifier};
use cssparser::{Parser, Token, serialize_identifier, BasicParseError};
use parser::{ParserContext, Parse};
use self::grid::TrackSizeOrRepeat;
use self::url::SpecifiedUrl;
use std::ascii::AsciiExt;
use std::f32;
use std::fmt;
use style_traits::ToCss;
use style_traits::{ToCss, ParseError, StyleParseError};
use style_traits::values::specified::AllowedNumericType;
use super::{Auto, CSSFloat, CSSInteger, Either, None_};
use super::computed::{self, Context};
@ -68,6 +68,7 @@ pub mod transform;
pub mod url {
use cssparser::Parser;
use parser::{Parse, ParserContext};
use style_traits::ParseError;
use values::computed::ComputedValueAsSpecified;
#[cfg(feature = "servo")]
@ -76,7 +77,7 @@ pub use ::servo::url::*;
pub use ::gecko::url::*;
impl Parse for SpecifiedUrl {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let url = try!(input.expect_url());
Self::parse_from_string(url, context)
}
@ -91,9 +92,10 @@ no_viewport_percentage!(SpecifiedUrl);
}
/// Parse an `<integer>` value, handling `calc()` correctly.
pub fn parse_integer(context: &ParserContext, input: &mut Parser) -> Result<Integer, ()> {
pub fn parse_integer<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Integer, ParseError<'i>> {
match try!(input.next()) {
Token::Number(ref value) => value.int_value.ok_or(()).map(Integer::new),
Token::Number(ref value) => value.int_value.ok_or(StyleParseError::UnspecifiedError.into()).map(Integer::new),
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
let result = try!(input.parse_nested_block(|i| {
CalcNode::parse_integer(context, i)
@ -101,21 +103,22 @@ pub fn parse_integer(context: &ParserContext, input: &mut Parser) -> Result<Inte
Ok(Integer::from_calc(result))
}
_ => Err(())
t => Err(BasicParseError::UnexpectedToken(t).into())
}
}
/// Parse a `<number>` value, handling `calc()` correctly, and without length
/// limitations.
pub fn parse_number(context: &ParserContext, input: &mut Parser) -> Result<Number, ()> {
pub fn parse_number<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Number, ParseError<'i>> {
parse_number_with_clamping_mode(context, input, AllowedNumericType::All)
}
/// Parse a `<number>` value, with a given clamping mode.
pub fn parse_number_with_clamping_mode(context: &ParserContext,
input: &mut Parser,
clamping_mode: AllowedNumericType)
-> Result<Number, ()> {
pub fn parse_number_with_clamping_mode<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
clamping_mode: AllowedNumericType)
-> Result<Number, ParseError<'i>> {
match try!(input.next()) {
Token::Number(ref value) if clamping_mode.is_ok(value.value) => {
Ok(Number {
@ -133,7 +136,7 @@ pub fn parse_number_with_clamping_mode(context: &ParserContext,
calc_clamping_mode: Some(clamping_mode),
})
}
_ => Err(())
t => Err(BasicParseError::UnexpectedToken(t).into())
}
}
@ -220,18 +223,19 @@ impl Angle {
impl Parse for Angle {
/// Parses an angle according to CSS-VALUES § 6.1.
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
match try!(input.next()) {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let token = try!(input.next());
match token {
Token::Dimension(ref value, ref unit) => {
Angle::parse_dimension(value.value,
unit,
/* from_calc = */ false)
}
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
input.parse_nested_block(|i| CalcNode::parse_angle(context, i))
return input.parse_nested_block(|i| CalcNode::parse_angle(context, i))
}
_ => Err(())
}
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
}
}
@ -260,8 +264,10 @@ impl Angle {
///
/// We can remove this and get back to the unified version Angle::parse once
/// https://github.com/w3c/csswg-drafts/issues/1162 is resolved.
pub fn parse_with_unitless(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
match try!(input.next()) {
pub fn parse_with_unitless<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
let token = try!(input.next());
match token {
Token::Dimension(ref value, ref unit) => {
Angle::parse_dimension(value.value,
unit,
@ -269,10 +275,10 @@ impl Angle {
}
Token::Number(ref value) if value.value == 0. => Ok(Angle::zero()),
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
input.parse_nested_block(|i| CalcNode::parse_angle(context, i))
return input.parse_nested_block(|i| CalcNode::parse_angle(context, i))
}
_ => Err(())
}
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
}
}
@ -337,7 +343,7 @@ impl Time {
let seconds = match_ignore_ascii_case! { unit,
"s" => value,
"ms" => value / 1000.0,
_ => return Err(()),
_ => return Err(())
};
Ok(Time {
@ -354,25 +360,29 @@ impl Time {
}
}
fn parse_with_clamping_mode(context: &ParserContext,
input: &mut Parser,
clamping_mode: AllowedNumericType) -> Result<Self, ()> {
fn parse_with_clamping_mode<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
clamping_mode: AllowedNumericType)
-> Result<Self, ParseError<'i>> {
match input.next() {
Ok(Token::Dimension(ref value, ref unit)) if clamping_mode.is_ok(value.value) => {
Time::parse_dimension(value.value, &unit, /* from_calc = */ false)
.map_err(|()| StyleParseError::UnspecifiedError.into())
}
Ok(Token::Function(ref name)) if name.eq_ignore_ascii_case("calc") => {
match input.parse_nested_block(|i| CalcNode::parse_time(context, i)) {
Ok(time) if clamping_mode.is_ok(time.seconds) => Ok(time),
_ => Err(()),
_ => Err(StyleParseError::UnspecifiedError.into()),
}
}
_ => Err(())
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
Err(e) => Err(e.into())
}
}
/// Parse <time> that values are non-negative.
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
Self::parse_with_clamping_mode(context, input, AllowedNumericType::NonNegative)
}
}
@ -393,7 +403,7 @@ impl ToComputedValue for Time {
}
impl Parse for Time {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Self::parse_with_clamping_mode(context, input, AllowedNumericType::All)
}
}
@ -425,7 +435,7 @@ pub struct Number {
no_viewport_percentage!(Number);
impl Parse for Number {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
parse_number(context, input)
}
}
@ -445,7 +455,8 @@ impl Number {
}
#[allow(missing_docs)]
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Number, ()> {
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Number, ParseError<'i>> {
if context.parsing_mode.allows_all_numeric_values() {
parse_number(context, input)
} else {
@ -454,7 +465,8 @@ impl Number {
}
#[allow(missing_docs)]
pub fn parse_at_least_one(context: &ParserContext, input: &mut Parser) -> Result<Number, ()> {
pub fn parse_at_least_one<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Number, ParseError<'i>> {
if context.parsing_mode.allows_all_numeric_values() {
parse_number(context, input)
} else {
@ -506,10 +518,10 @@ pub enum NumberOrPercentage {
no_viewport_percentage!(NumberOrPercentage);
impl NumberOrPercentage {
fn parse_with_clamping_mode(context: &ParserContext,
input: &mut Parser,
type_: AllowedNumericType)
-> Result<Self, ()> {
fn parse_with_clamping_mode<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
type_: AllowedNumericType)
-> Result<Self, ParseError<'i>> {
if let Ok(per) = input.try(|i| Percentage::parse_with_clamping_mode(i, type_)) {
return Ok(NumberOrPercentage::Percentage(per));
}
@ -518,13 +530,14 @@ impl NumberOrPercentage {
}
/// Parse a non-negative number or percentage.
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
Self::parse_with_clamping_mode(context, input, AllowedNumericType::NonNegative)
}
}
impl Parse for NumberOrPercentage {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Self::parse_with_clamping_mode(context, input, AllowedNumericType::All)
}
}
@ -537,7 +550,7 @@ pub struct Opacity(Number);
no_viewport_percentage!(Opacity);
impl Parse for Opacity {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
parse_number(context, input).map(Opacity)
}
}
@ -590,27 +603,31 @@ impl Integer {
no_viewport_percentage!(Integer);
impl Parse for Integer {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
parse_integer(context, input)
}
}
impl Integer {
#[allow(missing_docs)]
pub fn parse_with_minimum(context: &ParserContext, input: &mut Parser, min: i32) -> Result<Integer, ()> {
pub fn parse_with_minimum<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>, min: i32)
-> Result<Integer, ParseError<'i>> {
match parse_integer(context, input) {
Ok(value) if value.value() >= min => Ok(value),
_ => Err(()),
Ok(_value) => Err(StyleParseError::UnspecifiedError.into()),
Err(e) => Err(e),
}
}
#[allow(missing_docs)]
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Integer, ()> {
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Integer, ParseError<'i>> {
Integer::parse_with_minimum(context, input, 0)
}
#[allow(missing_docs)]
pub fn parse_positive(context: &ParserContext, input: &mut Parser) -> Result<Integer, ()> {
pub fn parse_positive<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Integer, ParseError<'i>> {
Integer::parse_with_minimum(context, input, 1)
}
}
@ -647,11 +664,11 @@ pub type IntegerOrAuto = Either<Integer, Auto>;
impl IntegerOrAuto {
#[allow(missing_docs)]
pub fn parse_positive(context: &ParserContext,
input: &mut Parser)
-> Result<IntegerOrAuto, ()> {
pub fn parse_positive<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>)
-> Result<IntegerOrAuto, ParseError<'i>> {
match IntegerOrAuto::parse(context, input) {
Ok(Either::First(integer)) if integer.value() <= 0 => Err(()),
Ok(Either::First(integer)) if integer.value() <= 0 => Err(StyleParseError::UnspecifiedError.into()),
result => result,
}
}
@ -739,7 +756,10 @@ impl ToCss for Shadow {
impl Shadow {
// disable_spread_and_inset is for filter: drop-shadow(...)
#[allow(missing_docs)]
pub fn parse(context: &ParserContext, input: &mut Parser, disable_spread_and_inset: bool) -> Result<Shadow, ()> {
pub fn parse<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
disable_spread_and_inset: bool)
-> Result<Shadow, ParseError<'i>> {
let mut lengths = [Length::zero(), Length::zero(), Length::zero(), Length::zero()];
let mut lengths_parsed = false;
let mut color = None;
@ -779,7 +799,7 @@ impl Shadow {
// Lengths must be specified.
if !lengths_parsed {
return Err(())
return Err(StyleParseError::UnspecifiedError.into())
}
debug_assert!(!disable_spread_and_inset || lengths[3] == Length::zero());
@ -841,7 +861,8 @@ pub type LengthOrPercentageOrNumber = Either<Number, LengthOrPercentage>;
impl LengthOrPercentageOrNumber {
/// parse a <length-percentage> | <number> enforcing that the contents aren't negative
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
// NB: Parse numbers before Lengths so we are consistent about how to
// recognize and serialize "0".
if let Ok(num) = input.try(|i| Number::parse_non_negative(context, i)) {
@ -928,19 +949,19 @@ impl ToComputedValue for ClipRect {
}
impl Parse for ClipRect {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Self::parse_quirky(context, input, AllowQuirks::No)
}
}
impl ClipRect {
/// Parses a rect(<top>, <left>, <bottom>, <right>), allowing quirks.
pub fn parse_quirky(context: &ParserContext, input: &mut Parser,
allow_quirks: AllowQuirks) -> Result<Self, ()> {
pub fn parse_quirky<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
use values::specified::Length;
fn parse_argument(context: &ParserContext, input: &mut Parser,
allow_quirks: AllowQuirks) -> Result<Option<Length>, ()> {
fn parse_argument<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks) -> Result<Option<Length>, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
Ok(None)
} else {
@ -948,8 +969,9 @@ impl ClipRect {
}
}
if !try!(input.expect_function()).eq_ignore_ascii_case("rect") {
return Err(())
let func = try!(input.expect_function());
if !func.eq_ignore_ascii_case("rect") {
return Err(StyleParseError::UnexpectedFunction(func).into())
}
input.parse_nested_block(|input| {
@ -984,8 +1006,8 @@ pub type ClipRectOrAuto = Either<ClipRect, Auto>;
impl ClipRectOrAuto {
/// Parses a ClipRect or Auto, allowing quirks.
pub fn parse_quirky(context: &ParserContext, input: &mut Parser,
allow_quirks: AllowQuirks) -> Result<Self, ()> {
pub fn parse_quirky<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
if let Ok(v) = input.try(|i| ClipRect::parse_quirky(context, i, allow_quirks)) {
Ok(Either::First(v))
} else {
@ -1035,7 +1057,7 @@ pub struct Attr {
}
impl Parse for Attr {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Attr, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Attr, ParseError<'i>> {
input.expect_function_matching("attr")?;
input.parse_nested_block(|i| Attr::parse_function(context, i))
}
@ -1068,25 +1090,28 @@ fn get_id_for_namespace(_: &Namespace, _: &ParserContext) -> Result<NamespaceId,
impl Attr {
/// Parse contents of attr() assuming we have already parsed `attr` and are
/// within a parse_nested_block()
pub fn parse_function(context: &ParserContext, input: &mut Parser) -> Result<Attr, ()> {
pub fn parse_function<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Attr, ParseError<'i>> {
// Syntax is `[namespace? `|`]? ident`
// no spaces allowed
let first = input.try(|i| i.expect_ident()).ok();
if let Ok(token) = input.try(|i| i.next_including_whitespace()) {
match token {
Token::Delim('|') => {}
_ => return Err(()),
t => return Err(BasicParseError::UnexpectedToken(t).into()),
}
// must be followed by an ident
let second_token = match input.next_including_whitespace()? {
Token::Ident(second) => second,
_ => return Err(()),
t => return Err(BasicParseError::UnexpectedToken(t).into()),
};
let ns_with_id = if let Some(ns) = first {
let ns: Namespace = ns.into();
let id = get_id_for_namespace(&ns, context)?;
Some((ns, id))
let id: Result<_, ParseError> =
get_id_for_namespace(&ns, context)
.map_err(|()| StyleParseError::UnspecifiedError.into());
Some((ns, id?))
} else {
None
};
@ -1102,7 +1127,7 @@ impl Attr {
attribute: first.into_owned(),
})
} else {
Err(())
Err(StyleParseError::UnspecifiedError.into())
}
}
}

Просмотреть файл

@ -10,7 +10,7 @@
use cssparser::Parser;
use parser::{Parse, ParserContext};
use std::fmt;
use style_traits::{HasViewportPercentage, ToCss};
use style_traits::{HasViewportPercentage, ToCss, ParseError};
use values::computed::{CalcLengthOrPercentage, LengthOrPercentage as ComputedLengthOrPercentage};
use values::computed::{Context, ToComputedValue};
use values::generics::position::Position as GenericPosition;
@ -50,17 +50,17 @@ define_css_keyword_enum! { Y:
add_impls_for_keyword_enum!(Y);
impl Parse for Position {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Self::parse_quirky(context, input, AllowQuirks::No)
}
}
impl Position {
/// Parses a `<position>`, with quirks.
pub fn parse_quirky(context: &ParserContext,
input: &mut Parser,
allow_quirks: AllowQuirks)
-> Result<Self, ()> {
pub fn parse_quirky<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks)
-> Result<Self, ParseError<'i>> {
match input.try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) {
Ok(x_pos @ PositionComponent::Center) => {
if let Ok(y_pos) = input.try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) {
@ -104,7 +104,7 @@ impl Position {
Err(_) => {},
}
let y_keyword = Y::parse(input)?;
let lop_and_x_pos: Result<_, ()> = input.try(|i| {
let lop_and_x_pos: Result<_, ParseError> = input.try(|i| {
let y_lop = i.try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)).ok();
if let Ok(x_keyword) = i.try(X::parse) {
let x_lop = i.try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)).ok();
@ -167,17 +167,17 @@ impl<S> HasViewportPercentage for PositionComponent<S> {
}
impl<S: Parse> Parse for PositionComponent<S> {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Self::parse_quirky(context, input, AllowQuirks::No)
}
}
impl<S: Parse> PositionComponent<S> {
/// Parses a component of a CSS position, with quirks.
pub fn parse_quirky(context: &ParserContext,
input: &mut Parser,
allow_quirks: AllowQuirks)
-> Result<Self, ()> {
pub fn parse_quirky<'i, 't>(context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks)
-> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("center")).is_ok() {
return Ok(PositionComponent::Center);
}

Просмотреть файл

@ -6,6 +6,7 @@
use cssparser::Parser;
use parser::ParserContext;
use style_traits::ParseError;
use values::generics::rect::Rect;
use values::specified::length::LengthOrNumber;
@ -15,7 +16,8 @@ pub type LengthOrNumberRect = Rect<LengthOrNumber>;
impl LengthOrNumberRect {
/// Parses a `LengthOrNumberRect`, rejecting negative values.
#[inline]
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
Rect::parse_with(context, input, LengthOrNumber::parse_non_negative)
}
}

Просмотреть файл

@ -6,7 +6,9 @@
use cssparser::Parser;
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseError;
use std::ascii::AsciiExt;
use style_traits::ParseError;
use values::computed::{Context, ToComputedValue};
use values::computed::text::LineHeight as ComputedLineHeight;
use values::generics::text::InitialLetter as GenericInitialLetter;
@ -28,7 +30,7 @@ pub type WordSpacing = Spacing<LengthOrPercentage>;
pub type LineHeight = GenericLineHeight<Number, LengthOrPercentage>;
impl Parse for InitialLetter {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
return Ok(GenericInitialLetter::Normal);
}
@ -39,7 +41,7 @@ impl Parse for InitialLetter {
}
impl Parse for LetterSpacing {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Spacing::parse_with(context, input, |c, i| {
Length::parse_quirky(c, i, AllowQuirks::Yes)
})
@ -47,7 +49,7 @@ impl Parse for LetterSpacing {
}
impl Parse for WordSpacing {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Spacing::parse_with(context, input, |c, i| {
LengthOrPercentage::parse_quirky(c, i, AllowQuirks::Yes)
})
@ -55,22 +57,23 @@ impl Parse for WordSpacing {
}
impl Parse for LineHeight {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if let Ok(number) = input.try(|i| Number::parse_non_negative(context, i)) {
return Ok(GenericLineHeight::Number(number))
}
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
return Ok(GenericLineHeight::Length(lop))
}
match &input.expect_ident()? {
ident if ident.eq_ignore_ascii_case("normal") => {
let ident = input.expect_ident()?;
match ident {
ref ident if ident.eq_ignore_ascii_case("normal") => {
Ok(GenericLineHeight::Normal)
},
#[cfg(feature = "gecko")]
ident if ident.eq_ignore_ascii_case("-moz-block-height") => {
ref ident if ident.eq_ignore_ascii_case("-moz-block-height") => {
Ok(GenericLineHeight::MozBlockHeight)
},
_ => Err(()),
ident => Err(SelectorParseError::UnexpectedIdent(ident).into()),
}
}
}

Просмотреть файл

@ -7,6 +7,8 @@
use cssparser::Parser;
use euclid::Point2D;
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseError;
use style_traits::{ParseError, StyleParseError};
use values::computed::{LengthOrPercentage as ComputedLengthOrPercentage, Context, ToComputedValue};
use values::computed::transform::TimingFunction as ComputedTimingFunction;
use values::generics::transform::{StepPosition, TimingFunction as GenericTimingFunction};
@ -34,7 +36,7 @@ pub enum OriginComponent<S> {
pub type TimingFunction = GenericTimingFunction<Integer, Number>;
impl Parse for TransformOrigin {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let parse_depth = |input: &mut Parser| {
input.try(|i| Length::parse(context, i)).unwrap_or(Length::from_px(0.))
};
@ -85,7 +87,7 @@ impl Parse for TransformOrigin {
impl<S> Parse for OriginComponent<S>
where S: Parse,
{
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("center")).is_ok() {
return Ok(OriginComponent::Center);
}
@ -123,7 +125,7 @@ impl<S> ToComputedValue for OriginComponent<S>
}
impl Parse for TimingFunction {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if let Ok(keyword) = input.try(TimingKeyword::parse) {
return Ok(GenericTimingFunction::Keyword(keyword));
}
@ -131,13 +133,13 @@ impl Parse for TimingFunction {
let position = match_ignore_ascii_case! { &ident,
"step-start" => StepPosition::Start,
"step-end" => StepPosition::End,
_ => return Err(()),
_ => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()),
};
return Ok(GenericTimingFunction::Steps(Integer::new(1), position));
}
let function = input.expect_function()?;
input.parse_nested_block(|i| {
match_ignore_ascii_case! { &function,
input.parse_nested_block(move |i| {
(match_ignore_ascii_case! { &function,
"cubic-bezier" => {
let p1x = Number::parse(context, i)?;
i.expect_comma()?;
@ -148,7 +150,7 @@ impl Parse for TimingFunction {
let p2y = Number::parse(context, i)?;
if p1x.get() < 0.0 || p1x.get() > 1.0 || p2x.get() < 0.0 || p2x.get() > 1.0 {
return Err(());
return Err(StyleParseError::UnspecifiedError.into());
}
let (p1, p2) = (Point2D::new(p1x, p1y), Point2D::new(p2x, p2y));
@ -167,7 +169,7 @@ impl Parse for TimingFunction {
Ok(GenericTimingFunction::Frames(frames))
},
_ => Err(()),
}
}).map_err(|()| StyleParseError::UnexpectedFunction(function).into())
})
}
}

Просмотреть файл

@ -16,9 +16,10 @@ gecko = []
[dependencies]
app_units = "0.4.1"
cssparser = "0.13.7"
cssparser = "0.14.0"
euclid = "0.13"
heapsize = {version = "0.4", optional = true}
heapsize_derive = {version = "0.1", optional = true}
selectors = { path = "../selectors" }
serde = {version = "0.9", optional = true}
serde_derive = {version = "0.9", optional = true}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше