1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
/// Like the try! macro, but only works on Result<Option<_>, _> and returns /// Some(Err(err)) instead of Err(err). /// ```rust,ignore /// assert_eq!(try_some!(Ok(Some(1))), Some(1)); /// assert_eq!(try_some!(Ok(None)), None); /// try_some!(Err("some error")) // returns Some(Err("some error")) /// ``` #[macro_export] macro_rules! try_some { ($expr:expr) => { match $expr { Ok(Some(v)) => Some(v), Ok(None) => None, Err(e) => return Some(Err(From::from(e))), } }; } /// Like the try! macro only that this returns Some(Err(err)) instead of Err(err). /// ```rust,ignore /// assert_eq!(try_err!(Ok(1)), try!(Ok(1))); /// assert!(try_err!(Err("some error"))) // returns Some(Err("some error")) /// ``` #[macro_export] macro_rules! try_err { ($expr:expr) => { match $expr { Ok(v) => v, Err(e) => return Some(Err(From::from(e))), } }; } /// Accept only the given `TokenKind`. /// /// The first arg has to have an accessible field `lexer: iter::Peekable<_>`. /// The second arg is the name of a `TokenKind` variant, e.g. `StringLiteral`. /// If the variant contains data, a third arg is needed and can be any ident. /// /// `Ok(Some(TokenKind))` is returned if it is the correct token without data. /// `Ok(Some(data))` is returned if it is the correct token with data. /// `Ok(None)` is returned if another token is found. /// If an error is found, it will be returned. /// /// ```rust,ignore /// // In a method of GgaParser. The next bytes to parse are b",doc*". /// assert_eq!(accept!(self, CommaSeparator), Ok(Some(TokenKind::CommaSeparator))); /// assert_eq!(accept!(self, CommaSeparator), Ok(None)); /// match accept!(self, StringLiteral, s) { /// Ok(Some(s)) => assert_eq!(s.len(), 3), /// _ => unreachable!(), /// } /// assert!(accept!(self, Checksum, c).is_err()); /// ``` #[macro_export] macro_rules! accept { ($parser:expr, $toktype:ident) => { match $parser.lexer.peek() { Some(Ok(::lexer::Token { kind: ::lexer::TokenKind::$toktype, .. })) => { $parser.lexer.next(); Ok(Some(::lexer::TokenKind::$toktype)) } Some(&Err(_)) => match $parser.lexer.next() { Some(Err(e)) => Err(e), _ => unreachable!(), }, _ => Ok(None), } }; ($parser:expr, $toktype:ident, $tokdata:ident) => { match $parser.lexer.peek() { Some(Ok(::lexer::Token { kind: ::lexer::TokenKind::$toktype(_), .. })) => match $parser.lexer.next() { Some(Ok(::lexer::Token { kind: ::lexer::TokenKind::$toktype($tokdata), .. })) => Ok(Some($tokdata)), _ => unreachable!(), }, Some(&Err(_)) => match $parser.lexer.next() { Some(Err(e)) => Err(e), _ => unreachable!(), }, _ => Ok(None), } }; } /// Expect the given `TokenKind`. /// /// The first arg has to be a parser with an accessible field `lexer`. /// The second arg is the name of a `TokenKind` variant, e.g. `StringLiteral`. /// If the variant contains data, a third arg is needed and can be any ident. /// /// `Ok(TokenKind)` is returned if it is the correct token without data. /// `Ok(data)` is returned if it is the correct token with data. /// `Err(ParseError::UnexpectedToken)` is returned if another token is found. /// If an error is found, it will be returned. /// /// ```rust,ignore /// // In a method of GgaParser wrapping ",doc*" /// assert_eq!(expect!(self, CommaSeparator), Ok(TokenKind::CommaSeparator)); /// assert_eq!(expect!(self, CommaSeparator), Err(ParseError::UnexpectedToken)); /// match expect!(self, StringLiteral, s) { /// Ok(s) => assert_eq!(s.len(), 3), /// _ => unreachable!(), /// } /// assert!(expect!(self, Checksum, c).is_err()); /// ``` #[macro_export] macro_rules! expect { ($parser:expr, $toktype:ident) => { match accept!($parser, $toktype) { Ok(Some(t)) => Ok(t), Ok(None) => Err(::err::ParseError::UnexpectedToken), Err(e) => Err(e.into()), } }; ($parser:expr, $toktype:ident, $tokdata:ident) => { match accept!($parser, $toktype, $tokdata) { Ok(Some(t)) => Ok(t), Ok(None) => Err(::err::ParseError::UnexpectedToken), Err(e) => Err(e.into()), } }; }