[librsvg: 1/28] path_parser.rs: Big refactor; return Result<> at every step instead of bool
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 1/28] path_parser.rs: Big refactor; return Result<> at every step instead of bool
- Date: Tue, 23 Jan 2018 17:59:18 +0000 (UTC)
commit a36569d1b52648847293d8bb0b857b8c663c0e5b
Author: Federico Mena Quintero <federico gnome org>
Date: Mon Jan 22 19:56:55 2018 -0600
path_parser.rs: Big refactor; return Result<> at every step instead of bool
In the recursive-descent parser, we used to return a bool from each
function that expects a terminal or a nonterminal.
Now we return a Result<_, ParseError> instead. This makes the code
much easier to read, since the "?" let us bail out at the appropriate
times without having deeply-nested if statements.
Also, fixed the handles_relative_moveto_lineto_lineto_abs_lineto()
test - it had incorrect path syntax.
rust/src/path_parser.rs | 719 +++++++++++++++++++++---------------------------
1 file changed, 312 insertions(+), 407 deletions(-)
---
diff --git a/rust/src/path_parser.rs b/rust/src/path_parser.rs
index 857e3a2..772bcdf 100644
--- a/rust/src/path_parser.rs
+++ b/rust/src/path_parser.rs
@@ -10,9 +10,6 @@ struct PathParser<'b> {
builder: &'b mut RsvgPathBuilder,
- error_message: &'static str,
- has_error: bool,
-
/* Current point; adjusted at every command */
current_x: f64,
current_y: f64,
@@ -70,9 +67,6 @@ impl<'b> PathParser<'b> {
builder: builder,
- error_message: "",
- has_error: false,
-
current_x: 0.0,
current_y: 0.0,
@@ -87,12 +81,11 @@ impl<'b> PathParser<'b> {
}
}
- fn parse (&mut self) -> bool {
+ fn parse (&mut self) -> Result<(), ParseError> {
self.getchar ();
- self.optional_whitespace () &&
- self.moveto_drawto_command_groups () &&
- self.optional_whitespace ()
+ self.optional_whitespace()?;
+ self.moveto_drawto_command_groups()
}
fn getchar (&mut self) {
@@ -105,10 +98,11 @@ impl<'b> PathParser<'b> {
}
}
- fn error (&mut self, message: &'static str) -> bool {
- self.error_message = message;
- self.has_error = true;
- false
+ fn error(&self, message: &'static str) -> ParseError {
+ ParseError {
+ position: self.current_pos,
+ message: message
+ }
}
fn match_char (&mut self, c: char) -> bool {
@@ -122,7 +116,7 @@ impl<'b> PathParser<'b> {
false
}
- fn whitespace (&mut self) -> bool {
+ fn whitespace (&mut self) -> Result<(), ParseError> {
if let Some (c) = self.lookahead {
if c.is_whitespace () {
assert! (self.match_char (c));
@@ -136,25 +130,24 @@ impl<'b> PathParser<'b> {
}
}
- return true;
- } else {
- return false;
}
+
+ return Ok(());
}
- false
+ Err(self.error("Unexpected end of data"))
}
- fn optional_whitespace (&mut self) -> bool {
- self.whitespace ();
- true
+ fn optional_whitespace (&mut self) -> Result<(), ParseError> {
+ let _ = self.whitespace();
+ Ok(())
}
- fn optional_comma_whitespace (&mut self) -> bool {
- assert! (self.optional_whitespace ());
+ fn optional_comma_whitespace (&mut self) -> Result<(), ParseError> {
+ self.optional_whitespace()?;
self.match_char (',');
- assert! (self.optional_whitespace ());
- true
+ self.optional_whitespace()?;
+ Ok(())
}
fn lookahead_is (&self, c: char) -> bool {
@@ -178,33 +171,30 @@ impl<'b> PathParser<'b> {
false
}
- fn number (&mut self) -> Option <f64> {
- let mut has_sign: bool;
+ fn lookahead_is_start_of_number(&mut self) -> bool {
+ let mut c = ' ';
+ self.lookahead_is_digit(&mut c) ||
+ self.lookahead_is('.') ||
+ self.lookahead_is('+') ||
+ self.lookahead_is('-')
+ }
+
+ fn number (&mut self) -> Result<f64, ParseError> {
let mut sign: f64;
- has_sign = false;
sign = 1.0;
if self.match_char ('+') {
sign = 1.0;
- has_sign = true;
} else if self.match_char ('-') {
sign = -1.0;
- has_sign = true;
}
- if let Some (num) = self.nonnegative_number () {
- return Some (num * sign);
- } else {
- if has_sign {
- self.error ("Expected number after sign");
- }
-
- None
- }
+ let num = self.nonnegative_number()?;
+ Ok(num * sign)
}
- fn nonnegative_number (&mut self) -> Option<f64> {
+ fn nonnegative_number (&mut self) -> Result<f64, ParseError> {
let mut value: f64;
let mut exponent_sign: f64;
let mut exponent: f64;
@@ -259,40 +249,32 @@ impl<'b> PathParser<'b> {
assert! (self.match_char (c));
}
} else {
- self.error ("Expected digits for exponent");
- return None;
+ return Err(self.error("Expected digits for exponent"));
}
}
- Some (value * 10.0f64.powf (exponent * exponent_sign))
+ Ok (value * 10.0f64.powf (exponent * exponent_sign))
} else {
- None
+ Err(self.error("Expected number"))
}
}
- fn flag (&mut self) -> Option <bool> {
+ fn flag (&mut self) -> Result<bool, ParseError> {
if self.match_char ('0') {
- Some (false)
+ Ok(false)
} else if self.match_char ('1') {
- Some (true)
+ Ok(true)
} else {
- None
+ Err(self.error("Expected flag"))
}
}
- fn coordinate_pair (&mut self) -> Option<(f64, f64)> {
- if let Some (num1) = self.number () {
- assert! (self.optional_comma_whitespace ());
-
- if let Some (num2) = self.number () {
- return Some ((num1, num2));
- } else {
- self.error ("Expected second coordinate of coordinate pair");
- return None
- }
- }
+ fn coordinate_pair (&mut self) -> Result<(f64, f64), ParseError> {
+ let a = self.number()?;
+ self.optional_comma_whitespace()?;
+ let b = self.number()?;
- None
+ Ok((a, b))
}
fn set_current_point (&mut self, x: f64, y: f64) {
@@ -384,8 +366,10 @@ impl<'b> PathParser<'b> {
self.builder.close_path ();
}
- fn lineto_argument_sequence (&mut self, absolute: bool) -> bool {
- if let Some ((mut x, mut y)) = self.coordinate_pair () {
+ fn lineto_argument_sequence (&mut self, absolute: bool) -> Result<(), ParseError> {
+ loop {
+ let (mut x, mut y) = self.coordinate_pair()?;
+
if !absolute {
x += self.current_x;
y += self.current_y;
@@ -393,58 +377,51 @@ impl<'b> PathParser<'b> {
self.emit_line_to (x, y);
- self.whitespace ();
+ self.whitespace()?;
if self.lookahead_is (',') {
assert! (self.match_char (','));
- assert! (self.optional_whitespace ());
-
- if !self.lineto_argument_sequence (absolute) {
- self.error ("Expected coordinate pair after comma");
- return false;
+ self.optional_whitespace()?;
+ } else {
+ if !self.lookahead_is_start_of_number() {
+ break;
}
}
-
- self.lineto_argument_sequence (absolute);
- true
- } else {
- false
}
+
+ Ok(())
}
- fn moveto_argument_sequence (&mut self, absolute: bool, is_initial_moveto: bool) -> bool {
- if let Some ((mut x, mut y)) = self.coordinate_pair () {
- if is_initial_moveto {
- self.emit_move_to (x, y);
- } else {
- if !absolute {
- x += self.current_x;
- y += self.current_y;
- }
+ fn moveto_argument_sequence (&mut self, absolute: bool, is_initial_moveto: bool) -> Result<(),
ParseError> {
+ let (mut x, mut y) = self.coordinate_pair ()?;
- self.emit_move_to (x, y);
+ if is_initial_moveto {
+ self.emit_move_to (x, y);
+ } else {
+ if !absolute {
+ x += self.current_x;
+ y += self.current_y;
}
- self.whitespace ();
-
- if self.lookahead_is (',') {
- assert! (self.match_char (','));
- assert! (self.optional_whitespace ());
+ self.emit_move_to (x, y);
+ }
- if !self.lineto_argument_sequence (absolute) {
- self.error ("Expected coordinate pair after comma");
- return false;
- }
- }
+ self.whitespace()?;
- self.lineto_argument_sequence (absolute);
- true
+ if self.lookahead_is (',') {
+ assert! (self.match_char (','));
+ self.optional_whitespace()?;
+ self.lineto_argument_sequence(absolute)
} else {
- self.error ("Expected coordinate pair after moveto")
+ if self.lookahead_is_start_of_number() {
+ self.lineto_argument_sequence(absolute)
+ } else {
+ Ok(())
+ }
}
}
- fn moveto (&mut self, is_initial_moveto: bool) -> bool {
+ fn moveto (&mut self, is_initial_moveto: bool) -> Result<(), ParseError> {
if self.lookahead_is ('M') || self.lookahead_is ('m') {
let absolute = if self.match_char ('M') {
true
@@ -453,72 +430,66 @@ impl<'b> PathParser<'b> {
false
};
- return self.optional_whitespace () &&
- self.moveto_argument_sequence (absolute, is_initial_moveto);
+ self.optional_whitespace()?;
+ self.moveto_argument_sequence(absolute, is_initial_moveto)
+ } else {
+ Err(self.error("Expected M or m command"))
}
-
- false
}
- fn moveto_drawto_command_group (&mut self, is_initial_moveto: bool) -> bool {
- if self.moveto (is_initial_moveto) {
- self.optional_whitespace () &&
- self.optional_drawto_commands ()
- } else {
- false
- }
+ fn moveto_drawto_command_group (&mut self, is_initial_moveto: bool) -> Result<(), ParseError> {
+ self.moveto(is_initial_moveto)?;
+ self.optional_whitespace()?;
+
+ self.optional_drawto_commands().map(|_| ())
}
- fn moveto_drawto_command_groups (&mut self) -> bool {
- if self.moveto_drawto_command_group (true) {
- loop {
- self.optional_whitespace ();
- if !self.moveto_drawto_command_group (false) {
- break;
- }
- }
+ fn moveto_drawto_command_groups(&mut self) -> Result<(), ParseError> {
+ let mut initial = true;
- true
- } else {
- self.error ("Expected moveto command")
+ loop {
+ self.moveto_drawto_command_group(initial)?;
+ initial = false;
+
+ self.optional_whitespace()?;
+ if self.lookahead.is_none() {
+ break;
+ }
}
+
+ Ok(())
}
- fn optional_drawto_commands (&mut self) -> bool {
- if self.drawto_command () {
- loop {
- self.optional_whitespace ();
- if !self.drawto_command () {
- break;
- }
- }
+ fn optional_drawto_commands (&mut self) -> Result<bool, ParseError> {
+ while self.drawto_command()? {
+ self.optional_whitespace()?;
}
- true
+ Ok(false)
}
- fn drawto_command (&mut self) -> bool {
- self.close_path () ||
- self.line_to () ||
- self.horizontal_line_to () ||
- self.vertical_line_to () ||
- self.curve_to () ||
- self.smooth_curve_to () ||
- self.quadratic_bezier_curve_to () ||
- self.smooth_quadratic_bezier_curve_to () ||
- self.elliptical_arc ()
+ fn drawto_command (&mut self) -> Result<bool, ParseError> {
+ Ok(self.close_path()? ||
+ self.line_to()? ||
+ self.horizontal_line_to()? ||
+ self.vertical_line_to()? ||
+ self.curve_to()? ||
+ self.smooth_curve_to()? ||
+ self.quadratic_bezier_curve_to()? ||
+ self.smooth_quadratic_bezier_curve_to()? ||
+ self.elliptical_arc()?)
}
- fn close_path (&mut self) -> bool {
+ fn close_path (&mut self) -> Result<bool, ParseError> {
if self.match_char ('Z') || self.match_char ('z') {
self.emit_close_path ();
- true
+ Ok(true)
} else {
- false
+ Ok(false)
}
}
- fn line_to (&mut self) -> bool {
+ fn line_to (&mut self) -> Result<bool, ParseError> {
if self.lookahead_is ('L') || self.lookahead_is ('l') {
let absolute = if self.match_char ('L') {
true
@@ -527,20 +498,19 @@ impl<'b> PathParser<'b> {
false
};
- self.optional_whitespace ();
+ self.optional_whitespace()?;
- if self.lineto_argument_sequence (absolute) {
- return true;
- } else {
- return self.error ("Expected coordinate pair after lineto");
- }
+ self.lineto_argument_sequence(absolute)?;
+ Ok(true)
+ } else {
+ Ok(false)
}
-
- false
}
- fn horizontal_lineto_argument_sequence (&mut self, absolute: bool) -> bool {
- if let Some (mut x) = self.number () {
+ fn horizontal_lineto_argument_sequence (&mut self, absolute: bool) -> Result<(), ParseError> {
+ loop {
+ let mut x = self.number()?;
+
if !absolute {
x += self.current_x;
}
@@ -549,26 +519,22 @@ impl<'b> PathParser<'b> {
self.emit_line_to (x, y);
- self.whitespace ();
+ self.whitespace()?;
if self.lookahead_is (',') {
assert! (self.match_char (','));
- assert! (self.optional_whitespace ());
-
- if !self.horizontal_lineto_argument_sequence (absolute) {
- self.error ("Expected offset after comma");
- return false;
+ self.optional_whitespace()?;
+ } else {
+ if !self.lookahead_is_start_of_number() {
+ break;
}
}
-
- self.horizontal_lineto_argument_sequence (absolute);
- true
- } else {
- false
}
+
+ Ok(())
}
- fn horizontal_line_to (&mut self) -> bool {
+ fn horizontal_line_to (&mut self) -> Result<bool, ParseError> {
if self.lookahead_is ('H') || self.lookahead_is ('h') {
let absolute = if self.match_char ('H') {
true
@@ -577,48 +543,43 @@ impl<'b> PathParser<'b> {
false
};
- self.optional_whitespace ();
+ self.optional_whitespace()?;
- if self.horizontal_lineto_argument_sequence (absolute) {
- return true;
- } else {
- return self.error ("Expected offset after horizontal lineto");
- }
+ self.horizontal_lineto_argument_sequence(absolute)?;
+ Ok(true)
+ } else {
+ Ok(false)
}
-
- false
}
- fn vertical_lineto_argument_sequence (&mut self, absolute: bool) -> bool {
- if let Some (mut y) = self.number () {
- let x = self.current_x;
+ fn vertical_lineto_argument_sequence (&mut self, absolute: bool) -> Result<(), ParseError> {
+ loop {
+ let mut y = self.number()?;
if !absolute {
y += self.current_y;
}
+ let x = self.current_x;
+
self.emit_line_to (x, y);
- self.whitespace ();
+ self.whitespace()?;
if self.lookahead_is (',') {
assert! (self.match_char (','));
- assert! (self.optional_whitespace ());
-
- if !self.vertical_lineto_argument_sequence (absolute) {
- self.error ("Expected offset after comma");
- return false;
+ self.optional_whitespace()?;
+ } else {
+ if !self.lookahead_is_start_of_number() {
+ break;
}
}
-
- self.vertical_lineto_argument_sequence (absolute);
- true
- } else {
- false
}
+
+ Ok(())
}
- fn vertical_line_to (&mut self) -> bool {
+ fn vertical_line_to (&mut self) -> Result<bool, ParseError> {
if self.lookahead_is ('V') || self.lookahead_is ('v') {
let absolute = if self.match_char ('V') {
true
@@ -627,101 +588,89 @@ impl<'b> PathParser<'b> {
false
};
- self.optional_whitespace ();
+ self.optional_whitespace()?;
- if self.vertical_lineto_argument_sequence (absolute) {
- return true;
- } else {
- return self.error ("Expected offset after vertical lineto");
- }
+ self.vertical_lineto_argument_sequence(absolute)?;
+ Ok(true)
+ } else {
+ Ok(false)
}
-
- false
}
- fn curveto_argument_sequence (&mut self, absolute: bool) -> bool {
- if let Some ((mut x2, mut y2)) = self.coordinate_pair () {
- assert! (self.optional_comma_whitespace ());
+ fn curveto_argument_sequence (&mut self, absolute: bool) -> Result<(), ParseError> {
+ loop {
+ let (mut x2, mut y2) = self.coordinate_pair()?;
- if let Some ((mut x3, mut y3)) = self.coordinate_pair () {
- assert! (self.optional_comma_whitespace ());
+ self.optional_comma_whitespace()?;
- if let Some ((mut x4, mut y4)) = self.coordinate_pair () {
- if !absolute {
- x2 += self.current_x;
- y2 += self.current_y;
- x3 += self.current_x;
- y3 += self.current_y;
- x4 += self.current_x;
- y4 += self.current_y;
- }
- self.emit_curve_to (x2, y2, x3, y3, x4, y4);
+ let (mut x3, mut y3) = self.coordinate_pair()?;
- self.whitespace ();
+ self.optional_comma_whitespace()?;
- if self.lookahead_is (',') {
- assert! (self.match_char (','));
- assert! (self.optional_whitespace ());
+ let (mut x4, mut y4) = self.coordinate_pair()?;
- if !self.curveto_argument_sequence (absolute) {
- self.error ("Expected coordinate pair after comma");
- return false;
- }
- }
+ if !absolute {
+ x2 += self.current_x;
+ y2 += self.current_y;
+ x3 += self.current_x;
+ y3 += self.current_y;
+ x4 += self.current_x;
+ y4 += self.current_y;
+ }
- self.curveto_argument_sequence (absolute);
- return true;
- } else {
- return self.error ("Expected third coordinate pair for curveto");
- }
+ self.emit_curve_to (x2, y2, x3, y3, x4, y4);
+
+ self.whitespace()?;
+
+ if self.lookahead_is (',') {
+ assert! (self.match_char (','));
+ self.optional_whitespace()?;
} else {
- return self.error ("Expected second coordinate pair for curveto");
+ if !self.lookahead_is_start_of_number() {
+ break;
+ }
}
- } else {
- false
}
+
+ Ok(())
}
- fn smooth_curveto_argument_sequence (&mut self, absolute: bool) -> bool {
- if let Some ((mut x3, mut y3)) = self.coordinate_pair () {
- assert! (self.optional_comma_whitespace ());
+ fn smooth_curveto_argument_sequence (&mut self, absolute: bool) -> Result<(), ParseError> {
+ loop {
+ let (mut x3, mut y3) = self.coordinate_pair()?;
- if let Some ((mut x4, mut y4)) = self.coordinate_pair () {
- if !absolute {
- x3 += self.current_x;
- y3 += self.current_y;
- x4 += self.current_x;
- y4 += self.current_y;
- }
+ self.optional_comma_whitespace()?;
- let (x2, y2) = (self.current_x + self.current_x - self.cubic_reflection_x,
- self.current_y + self.current_y - self.cubic_reflection_y);
+ let (mut x4, mut y4) = self.coordinate_pair()?;
- self.emit_curve_to (x2, y2, x3, y3, x4, y4);
+ if !absolute {
+ x3 += self.current_x;
+ y3 += self.current_y;
+ x4 += self.current_x;
+ y4 += self.current_y;
+ }
- self.whitespace ();
+ let (x2, y2) = (self.current_x + self.current_x - self.cubic_reflection_x,
+ self.current_y + self.current_y - self.cubic_reflection_y);
- if self.lookahead_is (',') {
- assert! (self.match_char (','));
- assert! (self.optional_whitespace ());
+ self.emit_curve_to (x2, y2, x3, y3, x4, y4);
- if !self.smooth_curveto_argument_sequence (absolute) {
- self.error ("Expected coordinate pair after comma");
- return false;
- }
- }
+ self.whitespace()?;
- self.smooth_curveto_argument_sequence (absolute);
- return true;
+ if self.lookahead_is (',') {
+ assert! (self.match_char (','));
+ self.optional_whitespace()?;
} else {
- return self.error ("Expected second coordinate pair for smooth curveto");
+ if !self.lookahead_is_start_of_number() {
+ break;
+ }
}
- } else {
- false
}
+
+ Ok(())
}
- fn curve_to (&mut self) -> bool {
+ fn curve_to (&mut self) -> Result<bool, ParseError> {
if self.lookahead_is ('C') || self.lookahead_is ('c') {
let absolute = if self.match_char ('C') {
true
@@ -730,19 +679,16 @@ impl<'b> PathParser<'b> {
false
};
- self.optional_whitespace ();
+ self.optional_whitespace()?;
- if self.curveto_argument_sequence (absolute) {
- return true;
- } else {
- return self.error ("Expected coordinate pair after curveto");
- }
+ self.curveto_argument_sequence(absolute)?;
+ Ok(true)
+ } else {
+ Ok(false)
}
-
- false
}
- fn smooth_curve_to (&mut self) -> bool {
+ fn smooth_curve_to (&mut self) -> Result<bool, ParseError> {
if self.lookahead_is ('S') || self.lookahead_is ('s') {
let absolute = if self.match_char ('S') {
true
@@ -751,55 +697,48 @@ impl<'b> PathParser<'b> {
false
};
- self.optional_whitespace ();
+ self.optional_whitespace()?;
- if self.smooth_curveto_argument_sequence (absolute) {
- return true;
- } else {
- return self.error ("Expected coordinate pair after smooth curveto");
- }
+ self.smooth_curveto_argument_sequence(absolute)?;
+ Ok(true)
+ } else {
+ Ok(false)
}
-
- false
}
- fn quadratic_curveto_argument_sequence (&mut self, absolute: bool) -> bool {
- if let Some ((mut a, mut b)) = self.coordinate_pair () {
- assert! (self.optional_comma_whitespace ());
+ fn quadratic_curveto_argument_sequence (&mut self, absolute: bool) -> Result<(), ParseError> {
+ loop {
+ let (mut a, mut b) = self.coordinate_pair()?;
- if let Some ((mut c, mut d)) = self.coordinate_pair () {
- if !absolute {
- a += self.current_x;
- b += self.current_y;
- c += self.current_x;
- d += self.current_y;
- }
+ self.optional_comma_whitespace()?;
- self.emit_quadratic_curve_to (a, b, c, d);
+ let (mut c, mut d) = self.coordinate_pair()?;
- self.whitespace ();
+ if !absolute {
+ a += self.current_x;
+ b += self.current_y;
+ c += self.current_x;
+ d += self.current_y;
+ }
- if self.lookahead_is (',') {
- assert! (self.match_char (','));
- assert! (self.optional_whitespace ());
+ self.emit_quadratic_curve_to (a, b, c, d);
- if !self.quadratic_curveto_argument_sequence (absolute) {
- self.error ("Expected coordinate pair after comma");
- return false;
- }
- }
+ self.whitespace()?;
- self.quadratic_curveto_argument_sequence (absolute);
- return true;
+ if self.lookahead_is (',') {
+ assert! (self.match_char (','));
+ self.optional_whitespace()?;
} else {
- return self.error ("Expected second coordinate pair for quadratic curveto");
+ if !self.lookahead_is_start_of_number() {
+ break;
+ }
}
- } else {
- false
}
+
+ Ok(())
}
- fn quadratic_bezier_curve_to (&mut self) -> bool {
+ fn quadratic_bezier_curve_to (&mut self) -> Result<bool, ParseError> {
if self.lookahead_is ('Q') || self.lookahead_is ('q') {
let absolute = if self.match_char ('Q') {
true
@@ -808,20 +747,19 @@ impl<'b> PathParser<'b> {
false
};
- self.optional_whitespace ();
+ self.optional_whitespace()?;
- if self.quadratic_curveto_argument_sequence (absolute) {
- return true;
- } else {
- return self.error ("Expected coordinate pair after quadratic curveto");
- }
+ self.quadratic_curveto_argument_sequence (absolute)?;
+ Ok(true)
+ } else {
+ Ok(false)
}
-
- false
}
- fn smooth_quadratic_curveto_argument_sequence (&mut self, absolute: bool) -> bool {
- if let Some ((mut c, mut d)) = self.coordinate_pair () {
+ fn smooth_quadratic_curveto_argument_sequence (&mut self, absolute: bool) -> Result<(), ParseError> {
+ loop {
+ let (mut c, mut d) = self.coordinate_pair()?;
+
if !absolute {
c += self.current_x;
d += self.current_y;
@@ -832,26 +770,22 @@ impl<'b> PathParser<'b> {
self.emit_quadratic_curve_to (a, b, c, d);
- self.whitespace ();
+ self.whitespace()?;
if self.lookahead_is (',') {
assert! (self.match_char (','));
- assert! (self.optional_whitespace ());
-
- if !self.smooth_quadratic_curveto_argument_sequence (absolute) {
- self.error ("Expected coordinate pair after comma");
- return false;
+ self.optional_whitespace()?;
+ } else {
+ if !self.lookahead_is_start_of_number() {
+ break;
}
}
-
- self.smooth_quadratic_curveto_argument_sequence (absolute);
- true
- } else {
- false
}
+
+ Ok(())
}
- fn smooth_quadratic_bezier_curve_to (&mut self) -> bool {
+ fn smooth_quadratic_bezier_curve_to (&mut self) -> Result<bool, ParseError> {
if self.lookahead_is ('T') || self.lookahead_is ('t') {
let absolute = if self.match_char ('T') {
true
@@ -860,87 +794,66 @@ impl<'b> PathParser<'b> {
false
};
- self.optional_whitespace ();
+ self.optional_whitespace()?;
- if self.smooth_quadratic_curveto_argument_sequence (absolute) {
- return true;
+ self.smooth_quadratic_curveto_argument_sequence(absolute)?;
+ Ok(true)
+ } else {
+ Ok(false)
+ }
+ }
+
+ fn elliptical_arc_argument_sequence (&mut self, absolute: bool) -> Result<(), ParseError> {
+ loop {
+ let rx = self.nonnegative_number()?;
+
+ self.optional_comma_whitespace()?;
+
+ let ry = self.nonnegative_number()?;
+
+ self.optional_comma_whitespace()?;
+
+ let x_axis_rotation = self.number()?;
+
+ self.optional_comma_whitespace()?;
+
+ let large_arc = LargeArc (self.flag()?);
+
+ self.optional_comma_whitespace()?;
+
+ let sweep = if self.flag()? {
+ Sweep::Positive
} else {
- return self.error ("Expected coordinate pair after smooth quadratic curveto");
+ Sweep::Negative
+ };
+
+ self.optional_comma_whitespace()?;
+
+ let (mut x, mut y) = self.coordinate_pair()?;
+
+ if !absolute {
+ x += self.current_x;
+ y += self.current_y;
}
- }
- false
- }
+ self.emit_arc (rx, ry, x_axis_rotation, large_arc, sweep, x, y);
- fn elliptical_arc_argument_sequence (&mut self, absolute: bool) -> bool {
- if let Some (rx) = self.nonnegative_number () {
- assert! (self.optional_comma_whitespace ());
-
- if let Some (ry) = self.nonnegative_number () {
- assert! (self.optional_comma_whitespace ());
-
- if let Some (x_axis_rotation) = self.number () {
- if self.match_char (',') || self.optional_whitespace () {
- if let Some (large_arc_flag) = self.flag () {
- assert! (self.optional_comma_whitespace ());
-
- let large_arc = LargeArc (large_arc_flag);
-
- if let Some (sweep_flag) = self.flag () {
- assert! (self.optional_comma_whitespace ());
-
- let sweep = if sweep_flag {
- Sweep::Positive
- } else {
- Sweep::Negative
- };
-
- if let Some ((mut x, mut y)) = self.coordinate_pair () {
- if !absolute {
- x += self.current_x;
- y += self.current_y;
- }
-
- self.emit_arc (rx, ry, x_axis_rotation, large_arc, sweep, x, y);
-
- self.whitespace ();
-
- if self.lookahead_is (',') {
- assert! (self.match_char (','));
- assert! (self.optional_whitespace ());
-
- if !self.elliptical_arc_argument_sequence (absolute) {
- self.error ("Expected x-radius after comma");
- return false;
- }
- }
-
- self.elliptical_arc_argument_sequence (absolute);
- return true;
- } else {
- return self.error ("Expected destination coordinate pair for elliptical
arc");
- }
- } else {
- return self.error ("Expected sweep-flag for elliptical arc");
- }
- } else {
- return self.error ("Expected large-arc-flag for elliptical arc");
- }
- } else {
- unreachable! ();
- }
- } else {
- return self.error ("Expected x-axis-rotation for elliptical arc");
- }
+ self.whitespace()?;
+
+ if self.lookahead_is (',') {
+ assert! (self.match_char (','));
+ self.optional_whitespace()?;
} else {
- return self.error ("Expected nonnegative y-radius for elliptical arc");
+ if !self.lookahead_is_start_of_number() {
+ break;
+ }
}
- } else {
- false
}
+
+ Ok(())
}
- fn elliptical_arc (&mut self) -> bool {
+ fn elliptical_arc (&mut self) -> Result<bool, ParseError> {
if self.lookahead_is ('A') || self.lookahead_is ('a') {
let absolute = if self.match_char ('A') {
true
@@ -949,16 +862,13 @@ impl<'b> PathParser<'b> {
false
};
- self.optional_whitespace ();
+ self.optional_whitespace()?;
- if self.elliptical_arc_argument_sequence (absolute) {
- return true;
- } else {
- return self.error ("Expected nonnegative x-radius for elliptical arc");
- }
+ self.elliptical_arc_argument_sequence(absolute)?;
+ Ok(true)
+ } else {
+ Ok(false)
}
-
- false
}
}
@@ -974,12 +884,7 @@ pub struct ParseError {
pub fn parse_path_into_builder (path_str: &str, builder: &mut RsvgPathBuilder) -> Result <(), ParseError> {
let mut parser = PathParser::new (builder, path_str);
- if parser.parse () {
- Ok (())
- } else {
- Err (ParseError { position: parser.current_pos,
- message: parser.error_message })
- }
+ parser.parse()
}
#[cfg(test)]
@@ -1277,7 +1182,7 @@ mod tests {
#[test]
fn handles_relative_moveto_lineto_lineto_abs_lineto () {
- test_parser ("m10 20 30 40,l30,40,50 60L200,300",
+ test_parser ("m10 20 30 40l30,40,50 60L200,300",
&vec![
moveto (10.0, 20.0),
lineto (40.0, 60.0),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]