remove panic in Parser::next

This commit is contained in:
Mrmaxmeier 2017-04-27 20:59:34 +02:00
parent 20df66f8f0
commit 545a70771d
4 changed files with 27 additions and 25 deletions

View file

@ -31,7 +31,7 @@ fn parse_definition<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Def
Ok(Definition::Operation(try!(parse_operation_definition(parser)))), Ok(Definition::Operation(try!(parse_operation_definition(parser)))),
Token::Name("fragment") => Token::Name("fragment") =>
Ok(Definition::Fragment(try!(parse_fragment_definition(parser)))), Ok(Definition::Fragment(try!(parse_fragment_definition(parser)))),
_ => Err(parser.next().map(ParseError::UnexpectedToken)), _ => Err(parser.next()?.map(ParseError::UnexpectedToken)),
} }
} }
@ -130,7 +130,7 @@ fn parse_fragment<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Selec
match parser.peek().item { match parser.peek().item {
Token::Name("on") => { Token::Name("on") => {
parser.next(); parser.next()?;
let name = try!(parser.expect_name()); let name = try!(parser.expect_name());
let directives = try!(parse_directives(parser)); let directives = try!(parse_directives(parser));
let selection_set = try!(parse_selection_set(parser)); let selection_set = try!(parse_selection_set(parser));
@ -185,7 +185,7 @@ fn parse_fragment<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Selec
selection_set: selection_set.item, selection_set: selection_set.item,
}))) })))
}, },
_ => Err(parser.next().map(ParseError::UnexpectedToken)), _ => Err(parser.next()?.map(ParseError::UnexpectedToken)),
} }
} }
@ -244,9 +244,9 @@ fn parse_argument<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, (Spanning<&'a
fn parse_operation_type<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, OperationType> { fn parse_operation_type<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, OperationType> {
match parser.peek().item { match parser.peek().item {
Token::Name("query") => Ok(parser.next().map(|_| OperationType::Query)), Token::Name("query") => Ok(parser.next()?.map(|_| OperationType::Query)),
Token::Name("mutation") => Ok(parser.next().map(|_| OperationType::Mutation)), Token::Name("mutation") => Ok(parser.next()?.map(|_| OperationType::Mutation)),
_ => Err(parser.next().map(ParseError::UnexpectedToken)) _ => Err(parser.next()?.map(ParseError::UnexpectedToken))
} }
} }

View file

@ -54,28 +54,31 @@ impl<'a> Parser<'a> {
} }
#[doc(hidden)] #[doc(hidden)]
pub fn next(&mut self) -> Spanning<Token<'a>> { pub fn next(&mut self) -> ParseResult<'a, Token<'a>> {
if self.tokens.len() == 1 { if self.tokens.len() == 1 {
panic!("Can not parse over EOF marker"); Err(Spanning::start_end(
&self.peek().start.clone(),
&self.peek().end.clone(),
ParseError::UnexpectedEndOfFile))
} else {
Ok(self.tokens.remove(0))
} }
self.tokens.remove(0)
} }
#[doc(hidden)] #[doc(hidden)]
pub fn expect(&mut self, expected: &Token) -> ParseResult<'a, Token<'a>> { pub fn expect(&mut self, expected: &Token) -> ParseResult<'a, Token<'a>> {
if &self.peek().item != expected { if &self.peek().item != expected {
Err(self.next().map(ParseError::UnexpectedToken)) Err(self.next()?.map(ParseError::UnexpectedToken))
} }
else { else {
Ok(self.next()) self.next()
} }
} }
#[doc(hidden)] #[doc(hidden)]
pub fn skip(&mut self, expected: &Token) -> Result<Option<Spanning<Token<'a>>>, Spanning<ParseError<'a>>> { pub fn skip(&mut self, expected: &Token) -> Result<Option<Spanning<Token<'a>>>, Spanning<ParseError<'a>>> {
if &self.peek().item == expected { if &self.peek().item == expected {
Ok(Some(self.next())) Ok(Some(self.next()?))
} }
else if self.peek().item == Token::EndOfFile { else if self.peek().item == Token::EndOfFile {
Err(Spanning::zero_width( Err(Spanning::zero_width(
@ -151,7 +154,7 @@ impl<'a> Parser<'a> {
pub fn expect_name(&mut self) -> ParseResult<'a, &'a str> { pub fn expect_name(&mut self) -> ParseResult<'a, &'a str> {
match *self.peek() { match *self.peek() {
Spanning { item: Token::Name(_), .. } => Spanning { item: Token::Name(_), .. } =>
Ok(self.next().map(|token| Ok(self.next()?.map(|token|
if let Token::Name(name) = token { if let Token::Name(name) = token {
name name
} }
@ -163,7 +166,7 @@ impl<'a> Parser<'a> {
&self.peek().start.clone(), &self.peek().start.clone(),
&self.peek().end.clone(), &self.peek().end.clone(),
ParseError::UnexpectedEndOfFile)), ParseError::UnexpectedEndOfFile)),
_ => Err(self.next().map(ParseError::UnexpectedToken)), _ => Err(self.next()?.map(ParseError::UnexpectedToken)),
} }
} }
} }

View file

@ -108,8 +108,7 @@ impl<T> PartialEq for Spanning<T> where T: PartialEq + fmt::Debug {
} }
} }
impl<T> Eq for Spanning<T> where T: Eq + fmt::Debug { impl<T> Eq for Spanning<T> where T: Eq + fmt::Debug {}
}
impl<T> Hash for Spanning<T> where T: Hash + fmt::Debug { impl<T> Hash for Spanning<T> where T: Hash + fmt::Debug {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {

View file

@ -8,11 +8,11 @@ pub fn parse_value_literal<'a>(parser: &mut Parser<'a>, is_const: bool) -> Parse
Spanning { item: Token::CurlyOpen, .. } => parse_object_literal(parser, is_const), Spanning { item: Token::CurlyOpen, .. } => parse_object_literal(parser, is_const),
Spanning { item: Token::Dollar, .. } if !is_const => parse_variable_literal(parser), Spanning { item: Token::Dollar, .. } if !is_const => parse_variable_literal(parser),
Spanning { item: Token::Int(i), .. } => Spanning { item: Token::Int(i), .. } =>
Ok(parser.next().map(|_| InputValue::int(i))), Ok(parser.next()?.map(|_| InputValue::int(i))),
Spanning { item: Token::Float(f), .. } => Spanning { item: Token::Float(f), .. } =>
Ok(parser.next().map(|_| InputValue::float(f))), Ok(parser.next()?.map(|_| InputValue::float(f))),
Spanning { item: Token::String(_), .. } => Spanning { item: Token::String(_), .. } =>
Ok(parser.next().map(|t| Ok(parser.next()?.map(|t|
if let Token::String(s) = t { if let Token::String(s) = t {
InputValue::string(s) InputValue::string(s)
} }
@ -20,14 +20,14 @@ pub fn parse_value_literal<'a>(parser: &mut Parser<'a>, is_const: bool) -> Parse
panic!("Internal parser error"); panic!("Internal parser error");
})), })),
Spanning { item: Token::Name("true"), .. } => Spanning { item: Token::Name("true"), .. } =>
Ok(parser.next().map(|_| InputValue::boolean(true))), Ok(parser.next()?.map(|_| InputValue::boolean(true))),
Spanning { item: Token::Name("false"), .. } => Spanning { item: Token::Name("false"), .. } =>
Ok(parser.next().map(|_| InputValue::boolean(false))), Ok(parser.next()?.map(|_| InputValue::boolean(false))),
Spanning { item: Token::Name("null"), .. } => Spanning { item: Token::Name("null"), .. } =>
Ok(parser.next().map(|_| InputValue::null())), Ok(parser.next()?.map(|_| InputValue::null())),
Spanning { item: Token::Name(name), .. } => Spanning { item: Token::Name(name), .. } =>
Ok(parser.next().map(|_| InputValue::enum_value(name.to_owned()))), Ok(parser.next()?.map(|_| InputValue::enum_value(name.to_owned()))),
_ => Err(parser.next().map(ParseError::UnexpectedToken)), _ => Err(parser.next()?.map(ParseError::UnexpectedToken)),
} }
} }