use self::Error::*;
use lexer::{self, Lexer, Token};
use range::{Op, Predicate, Range, WildcardVersion};
use std::error;
use std::fmt;
use std::mem;
use version::{Identifier, Version};
macro_rules! has_ws_separator {
($slf:expr, $pat:pat) => {{
$slf.skip_whitespace()?;
match $slf.peek() {
$pat => {
$slf.pop()?;
$slf.skip_whitespace()?;
true
},
_ => false,
}
}}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Error<'input> {
UnexpectedEnd,
UnexpectedToken(Token<'input>),
Lexer(lexer::Error),
MoreInput(Vec<Token<'input>>),
EmptyPredicate,
EmptyRange,
}
impl<'input> fmt::Display for Error<'input> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
UnexpectedEnd => write!(fmt, "unexpected end"),
UnexpectedToken(ref t) => write!(fmt, "unexpected token: {:?}", t),
Lexer(ref l) => write!(fmt, "lexer error: {}", l),
MoreInput(..) => write!(fmt, "more input"),
EmptyPredicate => write!(fmt, "empty predicate"),
EmptyRange => write!(fmt, "empty range"),
}
}
}
impl<'input> error::Error for Error<'input> {
fn description(&self) -> &str {
match *self {
UnexpectedEnd => "unexpected end",
UnexpectedToken(..) => "unexpected token",
Lexer(ref l) => l.description(),
MoreInput(..) => "more input",
EmptyPredicate => "empty predicate",
EmptyRange => "empty range",
}
}
}
impl<'input> From<lexer::Error> for Error<'input> {
fn from(value: lexer::Error) -> Self {
Error::Lexer(value)
}
}
impl<'input> From<Error<'input>> for String {
fn from(value: Error<'input>) -> Self {
value.to_string()
}
}
pub struct Parser<'input> {
lexer: Lexer<'input>,
c1: Option<Token<'input>>,
}
impl<'input> Parser<'input> {
pub fn new(input: &'input str) -> Result<Parser<'input>, Error<'input>> {
let mut lexer = Lexer::new(input);
let c1 = if let Some(c1) = lexer.next() {
Some(c1?)
} else {
None
};
Ok(Parser {
lexer: lexer,
c1: c1,
})
}
#[inline(always)]
fn pop(&mut self) -> Result<Token<'input>, Error<'input>> {
let c1 = if let Some(c1) = self.lexer.next() {
Some(c1?)
} else {
None
};
mem::replace(&mut self.c1, c1).ok_or_else(|| UnexpectedEnd)
}
#[inline(always)]
fn peek(&mut self) -> Option<&Token<'input>> {
self.c1.as_ref()
}
fn skip_whitespace(&mut self) -> Result<(), Error<'input>> {
match self.peek() {
Some(&Token::Whitespace(_, _)) => self.pop().map(|_| ()),
_ => Ok(()),
}
}
pub fn comma_predicate(&mut self) -> Result<Option<Predicate>, Error<'input>> {
if !has_ws_separator!(self, Some(&Token::Comma)) {
return Ok(None);
}
if let Some(predicate) = self.predicate()? {
Ok(Some(predicate))
} else {
Err(EmptyPredicate)
}
}
pub fn component(&mut self) -> Result<Option<u64>, Error<'input>> {
match self.pop()? {
Token::Numeric(number) => Ok(Some(number)),
ref t if t.is_wildcard() => Ok(None),
tok => Err(UnexpectedToken(tok)),
}
}
pub fn numeric(&mut self) -> Result<u64, Error<'input>> {
match self.pop()? {
Token::Numeric(number) => Ok(number),
tok => Err(UnexpectedToken(tok)),
}
}
pub fn dot_component(&mut self) -> Result<(Option<u64>, bool), Error<'input>> {
match self.peek() {
Some(&Token::Dot) => {}
_ => return Ok((None, false)),
}
self.pop()?;
self.component().map(|n| (n, n.is_none()))
}
pub fn dot_numeric(&mut self) -> Result<u64, Error<'input>> {
match self.pop()? {
Token::Dot => {}
tok => return Err(UnexpectedToken(tok)),
}
self.numeric()
}
pub fn identifier(&mut self) -> Result<Identifier, Error<'input>> {
let identifier = match self.pop()? {
Token::AlphaNumeric(identifier) => {
Identifier::AlphaNumeric(identifier.to_string())
}
Token::Numeric(n) => Identifier::Numeric(n),
tok => return Err(UnexpectedToken(tok)),
};
Ok(identifier)
}
fn pre(&mut self) -> Result<Vec<Identifier>, Error<'input>> {
match self.peek() {
Some(&Token::Hyphen) => {}
_ => return Ok(vec![]),
}
self.pop()?;
self.parts()
}
fn parts(&mut self) -> Result<Vec<Identifier>, Error<'input>> {
let mut parts = Vec::new();
parts.push(self.identifier()?);
loop {
match self.peek() {
Some(&Token::Dot) | Some(&Token::Hyphen) => {}
_ => break,
}
self.pop()?;
parts.push(self.identifier()?);
}
Ok(parts)
}
fn plus_build_metadata(&mut self) -> Result<Vec<Identifier>, Error<'input>> {
match self.peek() {
Some(&Token::Plus) => {}
_ => return Ok(vec![]),
}
self.pop()?;
self.parts()
}
pub fn op(&mut self) -> Result<Op, Error<'input>> {
use self::Token::*;
let op = match self.peek() {
Some(&Eq) => Op::Ex,
Some(&Gt) => Op::Gt,
Some(&GtEq) => Op::GtEq,
Some(&Lt) => Op::Lt,
Some(&LtEq) => Op::LtEq,
Some(&Tilde) => Op::Tilde,
Some(&Caret) => Op::Compatible,
_ => return Ok(Op::Compatible),
};
self.pop()?;
self.skip_whitespace()?;
Ok(op)
}
pub fn predicate(&mut self) -> Result<Option<Predicate>, Error<'input>> {
if self.peek().is_none() {
return Ok(None);
}
let mut op = self.op()?;
let major = match self.component()? {
Some(major) => major,
None => return Ok(None),
};
let (minor, minor_wildcard) = self.dot_component()?;
let (patch, patch_wildcard) = self.dot_component()?;
let pre = self.pre()?;
if minor_wildcard {
op = Op::Wildcard(WildcardVersion::Minor);
}
if patch_wildcard {
op = Op::Wildcard(WildcardVersion::Patch);
}
self.plus_build_metadata()?;
Ok(Some(Predicate {
op: op,
major: major,
minor: minor,
patch: patch,
pre: pre,
}))
}
pub fn range(&mut self) -> Result<Range, Error<'input>> {
let mut predicates = Vec::new();
if let Some(predicate) = self.predicate()? {
predicates.push(predicate);
while let Some(next) = self.comma_predicate()? {
predicates.push(next);
}
}
Ok(Range {
predicates: predicates,
})
}
pub fn version(&mut self) -> Result<Version, Error<'input>> {
self.skip_whitespace()?;
let major = self.numeric()?;
let minor = self.dot_numeric()?;
let patch = self.dot_numeric()?;
let pre = self.pre()?;
let build = self.plus_build_metadata()?;
self.skip_whitespace()?;
Ok(Version {
major: major,
minor: minor,
patch: patch,
pre: pre,
build: build,
})
}
pub fn is_eof(&mut self) -> bool {
self.c1.is_none()
}
#[allow(unused)]
pub fn tail(&mut self) -> Result<Vec<Token<'input>>, Error<'input>> {
let mut out = Vec::new();
if let Some(t) = self.c1.take() {
out.push(t);
}
while let Some(t) = self.lexer.next() {
out.push(t?);
}
Ok(out)
}
}