[librsvg] parsers.rs: Start a parser for SVG's list-of-points
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] parsers.rs: Start a parser for SVG's list-of-points
- Date: Fri, 24 Feb 2017 17:08:26 +0000 (UTC)
commit 6cfbc00b400fbad789671162514084063c6184c3
Author: Federico Mena Quintero <federico gnome org>
Date: Thu Feb 23 17:27:04 2017 -0600
parsers.rs: Start a parser for SVG's list-of-points
Thanks to Sebastian Köln in #rust for the help with nom.
We are still missing optional whitespace at the beginning
and end of the list-of-points, but I can't get nom to do that.
rust/src/parsers.rs | 148 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 144 insertions(+), 4 deletions(-)
---
diff --git a/rust/src/parsers.rs b/rust/src/parsers.rs
index f8a5681..bda6c36 100644
--- a/rust/src/parsers.rs
+++ b/rust/src/parsers.rs
@@ -1,4 +1,4 @@
-use nom::{IResult, is_digit, double, ErrorKind};
+use nom::{IResult, is_digit, double, double_s, ErrorKind, space, sp};
use std::str;
#[derive(Debug, PartialEq, Eq)]
@@ -48,8 +48,26 @@ named! (pub floating_point_constant<FloatingPointConstant>,
((Some (d), None), Some (e))))
);
-named! (pub comma,
- tag! (b","));
+fn is_whitespace (c: u8) -> bool {
+ match c as char {
+ ' ' | '\t' | '\r' | '\n' => true,
+ _ => false
+ }
+}
+
+// comma-wsp:
+// (wsp+ comma? wsp*) | (comma wsp*)
+
+named! (comma, complete! (tag! (",")));
+named! (wsp, recognize! (take_while1! (is_whitespace)));
+named! (wsp_opt, recognize! (take_while! (is_whitespace)));
+
+named! (comma_wsp,
+ alt! (recognize! (tuple! (comma,
+ wsp_opt))
+ | recognize! (tuple! (wsp,
+ opt! (comma),
+ wsp_opt))));
// Parse a viewBox attribute
// https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
@@ -71,6 +89,26 @@ named! (pub view_box<(f64, f64, f64, f64)>,
eof! () >>
(x, y, w, h))));
+// Coordinate pairs, separated by optional (whitespace-and/or comma)
+//
+// All of these yield (1, -2): "1 -2", "1, -2", "1-2"
+
+named! (pub coordinate_pair<(f64, f64)>,
+ do_parse! (x: double >>
+ opt! (comma_wsp) >>
+ y: double >>
+ (x, y)));
+
+// Parse a list-of-points as for polyline and polygon elements
+// https://www.w3.org/TR/SVG/shapes.html#PointsBNF
+
+named! (pub list_of_points<Vec<(f64, f64)>>,
+ terminated! (separated_list! (comma_wsp, coordinate_pair),
+ eof! ()));
+
+named! (pub separated_numbers<Vec<f64>>,
+ separated_list! (comma_wsp, double));
+
#[cfg(test)]
mod tests {
use super::*;
@@ -94,12 +132,114 @@ mod tests {
fn parses_view_box () {
assert_eq! (view_box (b"1 2 3 4"), IResult::Done (&b""[..], (1.0, 2.0, 3.0, 4.0)));
assert_eq! (view_box (b"1,2,3 4"), IResult::Done (&b""[..], (1.0, 2.0, 3.0, 4.0)));
+ assert_eq! (view_box (b" 1,2,3 4 "), IResult::Done (&b""[..], (1.0, 2.0, 3.0, 4.0)));
let result = view_box (b"1 2 3 4 5");
match result {
IResult::Error (_) => { },
- _ => { panic! ("{:?}", result); }
+ _ => { panic! ("{:?} should be an invalid viewBox", result); }
+ }
+ }
+
+ #[test]
+ fn parses_coordinate_pairs () {
+ assert_eq! (coordinate_pair (b"1 2"), IResult::Done (&b""[..], (1.0, 2.0)));
+ assert_eq! (coordinate_pair (b"1-2"), IResult::Done (&b""[..], (1.0, -2.0)));
+ assert_eq! (coordinate_pair (b"1,2"), IResult::Done (&b""[..], (1.0, 2.0)));
+ assert_eq! (coordinate_pair (b"1, 2"), IResult::Done (&b""[..], (1.0, 2.0)));
+ assert_eq! (coordinate_pair (b"1 ,2"), IResult::Done (&b""[..], (1.0, 2.0)));
+ assert_eq! (coordinate_pair (b"1 , 2"), IResult::Done (&b""[..], (1.0, 2.0)));
+ assert_eq! (coordinate_pair (b"1 -2"), IResult::Done (&b""[..], (1.0, -2.0)));
+ assert_eq! (coordinate_pair (b"1,-2"), IResult::Done (&b""[..], (1.0, -2.0)));
+ assert_eq! (coordinate_pair (b"1, -2"), IResult::Done (&b""[..], (1.0, -2.0)));
+ assert_eq! (coordinate_pair (b"1 , -2"), IResult::Done (&b""[..], (1.0, -2.0)));
+ }
+
+ #[test]
+ fn detects_incomplete_coordinate_pair () {
+ let result = coordinate_pair (b"1");
+ match result {
+ IResult::Incomplete (_) => { },
+ _ => { panic! ("{:?} should be an incomplete coordinate-pair", result); }
+ }
+
+ let result = coordinate_pair (b"1,");
+ match result {
+ IResult::Incomplete (_) => { },
+ _ => { panic! ("{:?} should be an incomplete coordinate-pair", result); }
+ }
+
+ let result = coordinate_pair (b"1, ");
+ match result {
+ IResult::Incomplete (_) => { },
+ _ => { panic! ("{:?} should be an incomplete coordinate-pair", result); }
+ }
+
+ let result = coordinate_pair (b"1-");
+ match result {
+ IResult::Incomplete (_) => { },
+ _ => { panic! ("{:?} should be an incomplete coordinate-pair", result); }
+ }
+
+ let result = coordinate_pair (b"1,-");
+ match result {
+ IResult::Incomplete (_) => { },
+ _ => { panic! ("{:?} should be an incomplete coordinate-pair", result); }
+ }
+
+ let result = coordinate_pair (b"-1 -");
+ match result {
+ IResult::Incomplete (_) => { },
+ _ => { panic! ("{:?} should be an incomplete coordinate-pair", result); }
+ }
+ }
+
+ #[test]
+ fn parses_comma_wsp () {
+ assert_eq! (comma_wsp (b" , "), IResult::Done (&b""[..], &b" , "[..]));
+ assert_eq! (comma_wsp (b","), IResult::Done (&b""[..], &b","[..]));
+ assert_eq! (comma_wsp (b" "), IResult::Done (&b""[..], &b" "[..]));
+ assert_eq! (comma_wsp (b", "), IResult::Done (&b""[..], &b", "[..]));
+ assert_eq! (comma_wsp (b" ,"), IResult::Done (&b""[..], &b" ,"[..]));
+ }
+
+ #[test]
+ fn parses_separated_numbers () {
+ assert_eq! (separated_numbers (b"1 2 3 4"), IResult::Done (&b""[..], vec! [1.0, 2.0, 3.0, 4.0]));
+ assert_eq! (separated_numbers (b"1,2,3,4"), IResult::Done (&b""[..], vec! [1.0, 2.0, 3.0, 4.0]));
+ assert_eq! (separated_numbers (b"1 ,2 ,3 ,4"), IResult::Done (&b""[..], vec! [1.0, 2.0, 3.0, 4.0]));
+ assert_eq! (separated_numbers (b"1 ,2 ,3 ,4"), IResult::Done (&b""[..], vec! [1.0, 2.0, 3.0,
4.0]));
+ assert_eq! (separated_numbers (b"1, 2, 3, 4"), IResult::Done (&b""[..], vec! [1.0, 2.0, 3.0, 4.0]));
+ assert_eq! (separated_numbers (b"1, 2, 3, 4"), IResult::Done (&b""[..], vec! [1.0, 2.0, 3.0,
4.0]));
+ assert_eq! (separated_numbers (b"1 , 2 , 3 , 4"), IResult::Done (&b""[..], vec! [1.0, 2.0, 3.0,
4.0]));
+ assert_eq! (separated_numbers (b"1 , 2 , 3 , 4"), IResult::Done (&b""[..], vec! [1.0, 2.0, 3.0,
4.0]));
+ assert_eq! (separated_numbers (b"1 , 2 , 3 , 4"), IResult::Done (&b""[..], vec! [1.0, 2.0,
3.0, 4.0]));
+ }
+
+ #[test]
+ fn parses_list_of_points () {
+ // FIXME: we are missing optional whitespace at the beginning and end of the list
+ assert_eq! (list_of_points (b"1 2"), IResult::Done (&b""[..], vec! [(1.0, 2.0)]));
+ assert_eq! (list_of_points (b"1 2 3 4"), IResult::Done (&b""[..], vec! [(1.0, 2.0), (3.0, 4.0)]));
+ assert_eq! (list_of_points (b"1,2,3,4"), IResult::Done (&b""[..], vec! [(1.0, 2.0), (3.0, 4.0)]));
+ assert_eq! (list_of_points (b"1,2 3,4"), IResult::Done (&b""[..], vec! [(1.0, 2.0), (3.0, 4.0)]));
+ assert_eq! (list_of_points (b"1,2 -3,4"), IResult::Done (&b""[..], vec! [(1.0, 2.0), (-3.0, 4.0)]));
+ assert_eq! (list_of_points (b"1,2,-3,4"), IResult::Done (&b""[..], vec! [(1.0, 2.0), (-3.0, 4.0)]));
+ }
+
+ #[test]
+ fn errors_on_invalid_list_of_points () {
+ let result = list_of_points (b"-1-2-3-4");
+ match result {
+ IResult::Error (_) => { },
+ _ => { panic! ("{:?} should be an invalid list-of-points", result); }
+ }
+
+ let result = list_of_points (b"1 2-3,-4");
+ match result {
+ IResult::Error (_) => { },
+ _ => { panic! ("{:?} should be an invalid list-of-points", result); }
}
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]