1 // this is only for parsing versions now 2 3 use std::fmt; 4 use std::mem; 5 6 use self::Error::*; 7 use crate::lexer::{self, Lexer, Token}; 8 use crate::version::{Identifier, Version}; 9 10 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] 11 pub enum Error<'input> { 12 /// Needed more tokens for parsing, but none are available. 13 UnexpectedEnd, 14 /// Unexpected token. 15 UnexpectedToken(Token<'input>), 16 /// An error occurred in the lexer. 17 Lexer(lexer::Error), 18 /// More input available. 19 MoreInput(Vec<Token<'input>>), 20 /// Encountered empty predicate in a set of predicates. 21 EmptyPredicate, 22 /// Encountered an empty range. 23 EmptyRange, 24 } 25 26 impl<'input> From<lexer::Error> for Error<'input> { from(value: lexer::Error) -> Self27 fn from(value: lexer::Error) -> Self { 28 Error::Lexer(value) 29 } 30 } 31 32 impl<'input> fmt::Display for Error<'input> { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result33 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 34 use self::Error::*; 35 36 match *self { 37 UnexpectedEnd => write!(fmt, "expected more input"), 38 UnexpectedToken(ref token) => write!(fmt, "encountered unexpected token: {:?}", token), 39 Lexer(ref error) => write!(fmt, "lexer error: {:?}", error), 40 MoreInput(ref tokens) => write!(fmt, "expected end of input, but got: {:?}", tokens), 41 EmptyPredicate => write!(fmt, "encountered empty predicate"), 42 EmptyRange => write!(fmt, "encountered empty range"), 43 } 44 } 45 } 46 47 /// impl for backwards compatibility. 48 impl<'input> From<Error<'input>> for String { from(value: Error<'input>) -> Self49 fn from(value: Error<'input>) -> Self { 50 value.to_string() 51 } 52 } 53 54 /// A recursive-descent parser for parsing version requirements. 55 pub struct Parser<'input> { 56 /// Source of token. 57 lexer: Lexer<'input>, 58 /// Lookaehead. 59 c1: Option<Token<'input>>, 60 } 61 62 impl<'input> Parser<'input> { 63 /// Construct a new parser for the given input. new(input: &'input str) -> Result<Parser<'input>, Error<'input>>64 pub fn new(input: &'input str) -> Result<Parser<'input>, Error<'input>> { 65 let mut lexer = Lexer::new(input); 66 67 let c1 = if let Some(c1) = lexer.next() { 68 Some(c1?) 69 } else { 70 None 71 }; 72 73 Ok(Parser { lexer, c1 }) 74 } 75 76 /// Pop one token. 77 #[inline(always)] pop(&mut self) -> Result<Token<'input>, Error<'input>>78 fn pop(&mut self) -> Result<Token<'input>, Error<'input>> { 79 let c1 = if let Some(c1) = self.lexer.next() { 80 Some(c1?) 81 } else { 82 None 83 }; 84 85 mem::replace(&mut self.c1, c1).ok_or_else(|| UnexpectedEnd) 86 } 87 88 /// Peek one token. 89 #[inline(always)] peek(&mut self) -> Option<&Token<'input>>90 fn peek(&mut self) -> Option<&Token<'input>> { 91 self.c1.as_ref() 92 } 93 94 /// Skip whitespace if present. skip_whitespace(&mut self) -> Result<(), Error<'input>>95 fn skip_whitespace(&mut self) -> Result<(), Error<'input>> { 96 match self.peek() { 97 Some(&Token::Whitespace(_, _)) => self.pop().map(|_| ()), 98 _ => Ok(()), 99 } 100 } 101 102 /// Parse a single component. 103 /// 104 /// Returns `None` if the component is a wildcard. component(&mut self) -> Result<Option<u64>, Error<'input>>105 pub fn component(&mut self) -> Result<Option<u64>, Error<'input>> { 106 match self.pop()? { 107 Token::Numeric(number) => Ok(Some(number)), 108 ref t if t.is_wildcard() => Ok(None), 109 tok => Err(UnexpectedToken(tok)), 110 } 111 } 112 113 /// Parse a single numeric. numeric(&mut self) -> Result<u64, Error<'input>>114 pub fn numeric(&mut self) -> Result<u64, Error<'input>> { 115 match self.pop()? { 116 Token::Numeric(number) => Ok(number), 117 tok => Err(UnexpectedToken(tok)), 118 } 119 } 120 121 /// Optionally parse a dot, then a component. 122 /// 123 /// The second component of the tuple indicates if a wildcard has been encountered, and is 124 /// always `false` if the first component is `Some`. 125 /// 126 /// If a dot is not encountered, `(None, false)` is returned. 127 /// 128 /// If a wildcard is encountered, `(None, true)` is returned. dot_component(&mut self) -> Result<(Option<u64>, bool), Error<'input>>129 pub fn dot_component(&mut self) -> Result<(Option<u64>, bool), Error<'input>> { 130 match self.peek() { 131 Some(&Token::Dot) => {} 132 _ => return Ok((None, false)), 133 } 134 135 // pop the peeked dot. 136 self.pop()?; 137 self.component().map(|n| (n, n.is_none())) 138 } 139 140 /// Parse a dot, then a numeric. dot_numeric(&mut self) -> Result<u64, Error<'input>>141 pub fn dot_numeric(&mut self) -> Result<u64, Error<'input>> { 142 match self.pop()? { 143 Token::Dot => {} 144 tok => return Err(UnexpectedToken(tok)), 145 } 146 147 self.numeric() 148 } 149 150 /// Parse an string identifier. 151 /// 152 /// Like, `foo`, or `bar`, or `beta-1`. identifier(&mut self) -> Result<Identifier, Error<'input>>153 pub fn identifier(&mut self) -> Result<Identifier, Error<'input>> { 154 let identifier = match self.pop()? { 155 Token::AlphaNumeric(identifier) => { 156 // TODO: Borrow? 157 Identifier::AlphaNumeric(identifier.to_string()) 158 } 159 Token::Numeric(n) => Identifier::Numeric(n), 160 tok => return Err(UnexpectedToken(tok)), 161 }; 162 163 if let Some(&Token::Hyphen) = self.peek() { 164 // pop the peeked hyphen 165 self.pop()?; 166 // concat with any following identifiers 167 Ok(identifier 168 .concat("-") 169 .concat(&self.identifier()?.to_string())) 170 } else { 171 Ok(identifier) 172 } 173 } 174 175 /// Parse all pre-release identifiers, separated by dots. 176 /// 177 /// Like, `abcdef.1234`. pre(&mut self) -> Result<Vec<Identifier>, Error<'input>>178 fn pre(&mut self) -> Result<Vec<Identifier>, Error<'input>> { 179 match self.peek() { 180 Some(&Token::Hyphen) => {} 181 _ => return Ok(vec![]), 182 } 183 184 // pop the peeked hyphen. 185 self.pop()?; 186 self.parts() 187 } 188 189 /// Parse a dot-separated set of identifiers. parts(&mut self) -> Result<Vec<Identifier>, Error<'input>>190 fn parts(&mut self) -> Result<Vec<Identifier>, Error<'input>> { 191 let mut parts = Vec::new(); 192 193 parts.push(self.identifier()?); 194 195 while let Some(&Token::Dot) = self.peek() { 196 self.pop()?; 197 198 parts.push(self.identifier()?); 199 } 200 201 Ok(parts) 202 } 203 204 /// Parse optional build metadata. 205 /// 206 /// Like, `` (empty), or `+abcdef`. plus_build_metadata(&mut self) -> Result<Vec<Identifier>, Error<'input>>207 fn plus_build_metadata(&mut self) -> Result<Vec<Identifier>, Error<'input>> { 208 match self.peek() { 209 Some(&Token::Plus) => {} 210 _ => return Ok(vec![]), 211 } 212 213 // pop the plus. 214 self.pop()?; 215 self.parts() 216 } 217 218 /// Parse a version. 219 /// 220 /// Like, `1.0.0` or `3.0.0-beta.1`. version(&mut self) -> Result<Version, Error<'input>>221 pub fn version(&mut self) -> Result<Version, Error<'input>> { 222 self.skip_whitespace()?; 223 224 let major = self.numeric()?; 225 let minor = self.dot_numeric()?; 226 let patch = self.dot_numeric()?; 227 let pre = self.pre()?; 228 let build = self.plus_build_metadata()?; 229 230 self.skip_whitespace()?; 231 232 Ok(Version { 233 major, 234 minor, 235 patch, 236 pre, 237 build, 238 }) 239 } 240 241 /// Check if we have reached the end of input. is_eof(&mut self) -> bool242 pub fn is_eof(&mut self) -> bool { 243 self.c1.is_none() 244 } 245 246 /// Get the rest of the tokens in the parser. 247 /// 248 /// Useful for debugging. tail(&mut self) -> Result<Vec<Token<'input>>, Error<'input>>249 pub fn tail(&mut self) -> Result<Vec<Token<'input>>, Error<'input>> { 250 let mut out = Vec::new(); 251 252 if let Some(t) = self.c1.take() { 253 out.push(t); 254 } 255 256 while let Some(t) = self.lexer.next() { 257 out.push(t?); 258 } 259 260 Ok(out) 261 } 262 } 263