Skip to content

Commit 8bf3326

Browse files
committed
Add Parser::expect_no_error_token
1 parent 88585f8 commit 8bf3326

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

src/parser.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,27 @@ impl<'i, 't> Parser<'i, 't> {
620620
_ => Err(())
621621
}
622622
}
623+
624+
/// Parse the input until exhaustion and check that it contains no “error” token.
625+
///
626+
/// See `Token::is_parse_error`. This also checks nested blocks and functions recursively.
627+
#[inline]
628+
pub fn expect_no_error_token(&mut self) -> Result<(), ()> {
629+
loop {
630+
match self.next_including_whitespace_and_comments() {
631+
Ok(Token::Function(_)) | Ok(Token::ParenthesisBlock) |
632+
Ok(Token::SquareBracketBlock) | Ok(Token::CurlyBracketBlock) => {
633+
try!(self.parse_nested_block(|input| input.expect_no_error_token()))
634+
}
635+
Ok(token) => {
636+
if token.is_parse_error() {
637+
return Err(())
638+
}
639+
}
640+
Err(()) => return Ok(())
641+
}
642+
}
643+
}
623644
}
624645

625646

src/tests.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,19 @@ fn stylesheet_from_bytes() {
267267
}
268268

269269

270+
#[test]
271+
fn expect_no_error_token() {
272+
assert!(Parser::new("foo 4px ( / { !bar }").expect_no_error_token().is_ok());
273+
assert!(Parser::new(")").expect_no_error_token().is_err());
274+
assert!(Parser::new("}").expect_no_error_token().is_err());
275+
assert!(Parser::new("(a){]").expect_no_error_token().is_err());
276+
assert!(Parser::new("'\n'").expect_no_error_token().is_err());
277+
assert!(Parser::new("url('\n'").expect_no_error_token().is_err());
278+
assert!(Parser::new("url(a b)").expect_no_error_token().is_err());
279+
assert!(Parser::new("url(\u{7F})").expect_no_error_token().is_err());
280+
}
281+
282+
270283
fn run_color_tests<F: Fn(Result<Color, ()>) -> Json>(json_data: &str, to_json: F) {
271284
run_json_tests(json_data, |input| {
272285
to_json(input.parse_entirely(Color::parse))

src/tokenizer.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,22 @@ pub enum Token<'a> {
158158
}
159159

160160

161+
impl<'a> Token<'a> {
162+
/// Return whether this token represents a parse error.
163+
///
164+
/// `BadUrl` and `BadString` are tokenizer-level parse errors.
165+
///
166+
/// `CloseParenthesis`, `CloseSquareBracket`, and `CloseCurlyBracket` are *unmatched*
167+
/// and therefore parse errors when returned by one of the `Parser::next*` methods.
168+
pub fn is_parse_error(&self) -> bool {
169+
matches!(
170+
*self,
171+
BadUrl | BadString | CloseParenthesis | CloseSquareBracket | CloseCurlyBracket
172+
)
173+
}
174+
}
175+
176+
161177
/// The numeric value of `Number` and `Dimension` tokens.
162178
#[derive(PartialEq, Debug, Copy, Clone)]
163179
pub struct NumericValue {

0 commit comments

Comments
 (0)