From 5e20a29b4fdc8a2d442d1093681b396dcb4b816b Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Tue, 7 Jan 2020 11:18:04 +0000 Subject: Add structopt dependency in version 0.3.7 This patch series replaces argparse with structopt in the argument handling code. As a first step, we need structopt as a dependency. Import subrepo structopt/:structopt at efbdda4753592e27bc430fb01f7b9650b2f3174d Import subrepo bitflags/:bitflags at 30668016aca6bd3b02c766e8347e0b4080d4c296 Import subrepo clap/:clap at 784524f7eb193e35f81082cc69454c8c21b948f7 Import subrepo heck/:heck at 093d56fbf001e1506e56dbfa38631d99b1066df1 Import subrepo proc-macro-error/:proc-macro-error at 6c4cfe79a622c5de8ae68557993542be46eacae2 Import subrepo proc-macro2/:proc-macro2 at d5d48eddca4566e5438e8a2cbed4a74e049544de Import subrepo quote/:quote at 727436c6c137b20f0f34dde5d8fda2679b9747ad Import subrepo rustversion/:rustversion at 0c5663313516263059ce9059ef81fc7a1cf655ca Import subrepo syn-mid/:syn-mid at 5d3d85414a9e6674e1857ec22a87b96e04a6851a Import subrepo syn/:syn at e87c27e87f6f4ef8919d0372bdb056d53ef0d8f3 Import subrepo textwrap/:textwrap at abcd618beae3f74841032aa5b53c1086b0a57ca2 Import subrepo unicode-segmentation/:unicode-segmentation at 637c9874c4fe0c205ff27787faf150a40295c6c3 Import subrepo unicode-width/:unicode-width at 3033826f8bf05e82724140a981d5941e48fce393 Import subrepo unicode-xid/:unicode-xid at 4baae9fffb156ba229665b972a9cd5991787ceb7 --- proc-macro2/src/strnom.rs | 391 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 391 insertions(+) create mode 100644 proc-macro2/src/strnom.rs (limited to 'proc-macro2/src/strnom.rs') diff --git a/proc-macro2/src/strnom.rs b/proc-macro2/src/strnom.rs new file mode 100644 index 0000000..eb7d0b8 --- /dev/null +++ b/proc-macro2/src/strnom.rs @@ -0,0 +1,391 @@ +//! Adapted from [`nom`](https://github.com/Geal/nom). + +use crate::fallback::LexError; +use std::str::{Bytes, CharIndices, Chars}; +use unicode_xid::UnicodeXID; + +#[derive(Copy, Clone, Eq, PartialEq)] +pub struct Cursor<'a> { + pub rest: &'a str, + #[cfg(span_locations)] + pub off: u32, +} + +impl<'a> Cursor<'a> { + #[cfg(not(span_locations))] + pub fn advance(&self, amt: usize) -> Cursor<'a> { + Cursor { + rest: &self.rest[amt..], + } + } + #[cfg(span_locations)] + pub fn advance(&self, amt: usize) -> Cursor<'a> { + Cursor { + rest: &self.rest[amt..], + off: self.off + (amt as u32), + } + } + + pub fn find(&self, p: char) -> Option { + self.rest.find(p) + } + + pub fn starts_with(&self, s: &str) -> bool { + self.rest.starts_with(s) + } + + pub fn is_empty(&self) -> bool { + self.rest.is_empty() + } + + pub fn len(&self) -> usize { + self.rest.len() + } + + pub fn as_bytes(&self) -> &'a [u8] { + self.rest.as_bytes() + } + + pub fn bytes(&self) -> Bytes<'a> { + self.rest.bytes() + } + + pub fn chars(&self) -> Chars<'a> { + self.rest.chars() + } + + pub fn char_indices(&self) -> CharIndices<'a> { + self.rest.char_indices() + } +} + +pub type PResult<'a, O> = Result<(Cursor<'a>, O), LexError>; + +pub fn whitespace(input: Cursor) -> PResult<()> { + if input.is_empty() { + return Err(LexError); + } + + let bytes = input.as_bytes(); + let mut i = 0; + while i < bytes.len() { + let s = input.advance(i); + if bytes[i] == b'/' { + if s.starts_with("//") + && (!s.starts_with("///") || s.starts_with("////")) + && !s.starts_with("//!") + { + if let Some(len) = s.find('\n') { + i += len + 1; + continue; + } + break; + } else if s.starts_with("/**/") { + i += 4; + continue; + } else if s.starts_with("/*") + && (!s.starts_with("/**") || s.starts_with("/***")) + && !s.starts_with("/*!") + { + let (_, com) = block_comment(s)?; + i += com.len(); + continue; + } + } + match bytes[i] { + b' ' | 0x09..=0x0d => { + i += 1; + continue; + } + b if b <= 0x7f => {} + _ => { + let ch = s.chars().next().unwrap(); + if is_whitespace(ch) { + i += ch.len_utf8(); + continue; + } + } + } + return if i > 0 { Ok((s, ())) } else { Err(LexError) }; + } + Ok((input.advance(input.len()), ())) +} + +pub fn block_comment(input: Cursor) -> PResult<&str> { + if !input.starts_with("/*") { + return Err(LexError); + } + + let mut depth = 0; + let bytes = input.as_bytes(); + let mut i = 0; + let upper = bytes.len() - 1; + while i < upper { + if bytes[i] == b'/' && bytes[i + 1] == b'*' { + depth += 1; + i += 1; // eat '*' + } else if bytes[i] == b'*' && bytes[i + 1] == b'/' { + depth -= 1; + if depth == 0 { + return Ok((input.advance(i + 2), &input.rest[..i + 2])); + } + i += 1; // eat '/' + } + i += 1; + } + Err(LexError) +} + +pub fn skip_whitespace(input: Cursor) -> Cursor { + match whitespace(input) { + Ok((rest, _)) => rest, + Err(LexError) => input, + } +} + +fn is_whitespace(ch: char) -> bool { + // Rust treats left-to-right mark and right-to-left mark as whitespace + ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}' +} + +pub fn word_break(input: Cursor) -> PResult<()> { + match input.chars().next() { + Some(ch) if UnicodeXID::is_xid_continue(ch) => Err(LexError), + Some(_) | None => Ok((input, ())), + } +} + +macro_rules! named { + ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => { + fn $name<'a>(i: Cursor<'a>) -> $crate::strnom::PResult<'a, $o> { + $submac!(i, $($args)*) + } + }; +} + +macro_rules! alt { + ($i:expr, $e:ident | $($rest:tt)*) => { + alt!($i, call!($e) | $($rest)*) + }; + + ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => { + match $subrule!($i, $($args)*) { + res @ Ok(_) => res, + _ => alt!($i, $($rest)*) + } + }; + + ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => { + match $subrule!($i, $($args)*) { + Ok((i, o)) => Ok((i, $gen(o))), + Err(LexError) => alt!($i, $($rest)*) + } + }; + + ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => { + alt!($i, call!($e) => { $gen } | $($rest)*) + }; + + ($i:expr, $e:ident => { $gen:expr }) => { + alt!($i, call!($e) => { $gen }) + }; + + ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => { + match $subrule!($i, $($args)*) { + Ok((i, o)) => Ok((i, $gen(o))), + Err(LexError) => Err(LexError), + } + }; + + ($i:expr, $e:ident) => { + alt!($i, call!($e)) + }; + + ($i:expr, $subrule:ident!( $($args:tt)*)) => { + $subrule!($i, $($args)*) + }; +} + +macro_rules! do_parse { + ($i:expr, ( $($rest:expr),* )) => { + Ok(($i, ( $($rest),* ))) + }; + + ($i:expr, $e:ident >> $($rest:tt)*) => { + do_parse!($i, call!($e) >> $($rest)*) + }; + + ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => { + match $submac!($i, $($args)*) { + Err(LexError) => Err(LexError), + Ok((i, _)) => do_parse!(i, $($rest)*), + } + }; + + ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => { + do_parse!($i, $field: call!($e) >> $($rest)*) + }; + + ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => { + match $submac!($i, $($args)*) { + Err(LexError) => Err(LexError), + Ok((i, o)) => { + let $field = o; + do_parse!(i, $($rest)*) + }, + } + }; +} + +macro_rules! peek { + ($i:expr, $submac:ident!( $($args:tt)* )) => { + match $submac!($i, $($args)*) { + Ok((_, o)) => Ok(($i, o)), + Err(LexError) => Err(LexError), + } + }; +} + +macro_rules! call { + ($i:expr, $fun:expr $(, $args:expr)*) => { + $fun($i $(, $args)*) + }; +} + +macro_rules! option { + ($i:expr, $f:expr) => { + match $f($i) { + Ok((i, o)) => Ok((i, Some(o))), + Err(LexError) => Ok(($i, None)), + } + }; +} + +macro_rules! take_until_newline_or_eof { + ($i:expr,) => {{ + if $i.len() == 0 { + Ok(($i, "")) + } else { + match $i.find('\n') { + Some(i) => Ok(($i.advance(i), &$i.rest[..i])), + None => Ok(($i.advance($i.len()), &$i.rest[..$i.len()])), + } + } + }}; +} + +macro_rules! tuple { + ($i:expr, $($rest:tt)*) => { + tuple_parser!($i, (), $($rest)*) + }; +} + +/// Do not use directly. Use `tuple!`. +macro_rules! tuple_parser { + ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => { + tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*) + }; + + ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => { + match $submac!($i, $($args)*) { + Err(LexError) => Err(LexError), + Ok((i, o)) => tuple_parser!(i, (o), $($rest)*), + } + }; + + ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => { + match $submac!($i, $($args)*) { + Err(LexError) => Err(LexError), + Ok((i, o)) => tuple_parser!(i, ($($parsed)* , o), $($rest)*), + } + }; + + ($i:expr, ($($parsed:tt),*), $e:ident) => { + tuple_parser!($i, ($($parsed),*), call!($e)) + }; + + ($i:expr, (), $submac:ident!( $($args:tt)* )) => { + $submac!($i, $($args)*) + }; + + ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => { + match $submac!($i, $($args)*) { + Err(LexError) => Err(LexError), + Ok((i, o)) => Ok((i, ($($parsed),*, o))) + } + }; + + ($i:expr, ($($parsed:expr),*)) => { + Ok(($i, ($($parsed),*))) + }; +} + +macro_rules! not { + ($i:expr, $submac:ident!( $($args:tt)* )) => { + match $submac!($i, $($args)*) { + Ok((_, _)) => Err(LexError), + Err(LexError) => Ok(($i, ())), + } + }; +} + +macro_rules! tag { + ($i:expr, $tag:expr) => { + if $i.starts_with($tag) { + Ok(($i.advance($tag.len()), &$i.rest[..$tag.len()])) + } else { + Err(LexError) + } + }; +} + +macro_rules! punct { + ($i:expr, $punct:expr) => { + $crate::strnom::punct($i, $punct) + }; +} + +/// Do not use directly. Use `punct!`. +pub fn punct<'a>(input: Cursor<'a>, token: &'static str) -> PResult<'a, &'a str> { + let input = skip_whitespace(input); + if input.starts_with(token) { + Ok((input.advance(token.len()), token)) + } else { + Err(LexError) + } +} + +macro_rules! preceded { + ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => { + match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) { + Ok((remaining, (_, o))) => Ok((remaining, o)), + Err(LexError) => Err(LexError), + } + }; + + ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => { + preceded!($i, $submac!($($args)*), call!($g)) + }; +} + +macro_rules! delimited { + ($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)+) => { + match tuple_parser!($i, (), $submac!($($args)*), $($rest)*) { + Err(LexError) => Err(LexError), + Ok((i1, (_, o, _))) => Ok((i1, o)) + } + }; +} + +macro_rules! map { + ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => { + match $submac!($i, $($args)*) { + Err(LexError) => Err(LexError), + Ok((i, o)) => Ok((i, call!(o, $g))) + } + }; + + ($i:expr, $f:expr, $g:expr) => { + map!($i, call!($f), $g) + }; +} -- cgit v1.2.1