summaryrefslogtreecommitdiffstats
path: root/vendor/proc-macro2/src/parse.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/proc-macro2/src/parse.rs
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/proc-macro2/src/parse.rs')
-rw-r--r--vendor/proc-macro2/src/parse.rs276
1 files changed, 194 insertions, 82 deletions
diff --git a/vendor/proc-macro2/src/parse.rs b/vendor/proc-macro2/src/parse.rs
index 82291da1b..21e324136 100644
--- a/vendor/proc-macro2/src/parse.rs
+++ b/vendor/proc-macro2/src/parse.rs
@@ -27,7 +27,18 @@ impl<'a> Cursor<'a> {
self.rest.starts_with(s)
}
- fn is_empty(&self) -> bool {
+ pub fn starts_with_char(&self, ch: char) -> bool {
+ self.rest.starts_with(ch)
+ }
+
+ pub fn starts_with_fn<Pattern>(&self, f: Pattern) -> bool
+ where
+ Pattern: FnMut(char) -> bool,
+ {
+ self.rest.starts_with(f)
+ }
+
+ pub fn is_empty(&self) -> bool {
self.rest.is_empty()
}
@@ -97,7 +108,7 @@ fn skip_whitespace(input: Cursor) -> Cursor {
s = s.advance(1);
continue;
}
- b if b <= 0x7f => {}
+ b if b.is_ascii() => {}
_ => {
let ch = s.chars().next().unwrap();
if is_whitespace(ch) {
@@ -262,9 +273,11 @@ fn leaf_token(input: Cursor) -> PResult<TokenTree> {
}
fn ident(input: Cursor) -> PResult<crate::Ident> {
- if ["r\"", "r#\"", "r##", "b\"", "b\'", "br\"", "br#"]
- .iter()
- .any(|prefix| input.starts_with(prefix))
+ if [
+ "r\"", "r#\"", "r##", "b\"", "b\'", "br\"", "br#", "c\"", "cr\"", "cr#",
+ ]
+ .iter()
+ .any(|prefix| input.starts_with(prefix))
{
Err(Reject)
} else {
@@ -322,6 +335,8 @@ fn literal_nocapture(input: Cursor) -> Result<Cursor, Reject> {
Ok(ok)
} else if let Ok(ok) = byte_string(input) {
Ok(ok)
+ } else if let Ok(ok) = c_string(input) {
+ Ok(ok)
} else if let Ok(ok) = byte(input) {
Ok(ok)
} else if let Ok(ok) = character(input) {
@@ -352,8 +367,8 @@ fn string(input: Cursor) -> Result<Cursor, Reject> {
}
}
-fn cooked_string(input: Cursor) -> Result<Cursor, Reject> {
- let mut chars = input.char_indices().peekable();
+fn cooked_string(mut input: Cursor) -> Result<Cursor, Reject> {
+ let mut chars = input.char_indices();
while let Some((i, ch)) = chars.next() {
match ch {
@@ -367,31 +382,17 @@ fn cooked_string(input: Cursor) -> Result<Cursor, Reject> {
},
'\\' => match chars.next() {
Some((_, 'x')) => {
- if !backslash_x_char(&mut chars) {
- break;
- }
+ backslash_x_char(&mut chars)?;
}
Some((_, 'n')) | Some((_, 'r')) | Some((_, 't')) | Some((_, '\\'))
| Some((_, '\'')) | Some((_, '"')) | Some((_, '0')) => {}
Some((_, 'u')) => {
- if !backslash_u(&mut chars) {
- break;
- }
+ backslash_u(&mut chars)?;
}
- Some((_, ch @ '\n')) | Some((_, ch @ '\r')) => {
- let mut last = ch;
- loop {
- if last == '\r' && chars.next().map_or(true, |(_, ch)| ch != '\n') {
- return Err(Reject);
- }
- match chars.peek() {
- Some((_, ch)) if ch.is_whitespace() => {
- last = *ch;
- chars.next();
- }
- _ => break,
- }
- }
+ Some((newline, ch @ '\n')) | Some((newline, ch @ '\r')) => {
+ input = input.advance(newline + 1);
+ trailing_backslash(&mut input, ch as u8)?;
+ chars = input.char_indices();
}
_ => break,
},
@@ -401,11 +402,30 @@ fn cooked_string(input: Cursor) -> Result<Cursor, Reject> {
Err(Reject)
}
+fn raw_string(input: Cursor) -> Result<Cursor, Reject> {
+ let (input, delimiter) = delimiter_of_raw_string(input)?;
+ let mut bytes = input.bytes().enumerate();
+ while let Some((i, byte)) = bytes.next() {
+ match byte {
+ b'"' if input.rest[i + 1..].starts_with(delimiter) => {
+ let rest = input.advance(i + 1 + delimiter.len());
+ return Ok(literal_suffix(rest));
+ }
+ b'\r' => match bytes.next() {
+ Some((_, b'\n')) => {}
+ _ => break,
+ },
+ _ => {}
+ }
+ }
+ Err(Reject)
+}
+
fn byte_string(input: Cursor) -> Result<Cursor, Reject> {
if let Ok(input) = input.parse("b\"") {
cooked_byte_string(input)
} else if let Ok(input) = input.parse("br") {
- raw_string(input)
+ raw_byte_string(input)
} else {
Err(Reject)
}
@@ -425,68 +445,127 @@ fn cooked_byte_string(mut input: Cursor) -> Result<Cursor, Reject> {
},
b'\\' => match bytes.next() {
Some((_, b'x')) => {
- if !backslash_x_byte(&mut bytes) {
- break;
- }
+ backslash_x_byte(&mut bytes)?;
}
Some((_, b'n')) | Some((_, b'r')) | Some((_, b't')) | Some((_, b'\\'))
| Some((_, b'0')) | Some((_, b'\'')) | Some((_, b'"')) => {}
Some((newline, b @ b'\n')) | Some((newline, b @ b'\r')) => {
- let mut last = b as char;
- let rest = input.advance(newline + 1);
- let mut chars = rest.char_indices();
- loop {
- if last == '\r' && chars.next().map_or(true, |(_, ch)| ch != '\n') {
- return Err(Reject);
- }
- match chars.next() {
- Some((_, ch)) if ch.is_whitespace() => last = ch,
- Some((offset, _)) => {
- input = rest.advance(offset);
- bytes = input.bytes().enumerate();
- break;
- }
- None => return Err(Reject),
- }
- }
+ input = input.advance(newline + 1);
+ trailing_backslash(&mut input, b)?;
+ bytes = input.bytes().enumerate();
}
_ => break,
},
- b if b < 0x80 => {}
+ b if b.is_ascii() => {}
_ => break,
}
}
Err(Reject)
}
-fn raw_string(input: Cursor) -> Result<Cursor, Reject> {
- let mut chars = input.char_indices();
- let mut n = 0;
- for (i, ch) in &mut chars {
- match ch {
- '"' => {
- n = i;
- break;
+fn delimiter_of_raw_string(input: Cursor) -> PResult<&str> {
+ for (i, byte) in input.bytes().enumerate() {
+ match byte {
+ b'"' => {
+ if i > 255 {
+ // https://github.com/rust-lang/rust/pull/95251
+ return Err(Reject);
+ }
+ return Ok((input.advance(i + 1), &input.rest[..i]));
}
- '#' => {}
- _ => return Err(Reject),
+ b'#' => {}
+ _ => break,
}
}
- if n > 255 {
- // https://github.com/rust-lang/rust/pull/95251
- return Err(Reject);
+ Err(Reject)
+}
+
+fn raw_byte_string(input: Cursor) -> Result<Cursor, Reject> {
+ let (input, delimiter) = delimiter_of_raw_string(input)?;
+ let mut bytes = input.bytes().enumerate();
+ while let Some((i, byte)) = bytes.next() {
+ match byte {
+ b'"' if input.rest[i + 1..].starts_with(delimiter) => {
+ let rest = input.advance(i + 1 + delimiter.len());
+ return Ok(literal_suffix(rest));
+ }
+ b'\r' => match bytes.next() {
+ Some((_, b'\n')) => {}
+ _ => break,
+ },
+ other => {
+ if !other.is_ascii() {
+ break;
+ }
+ }
+ }
+ }
+ Err(Reject)
+}
+
+fn c_string(input: Cursor) -> Result<Cursor, Reject> {
+ if let Ok(input) = input.parse("c\"") {
+ cooked_c_string(input)
+ } else if let Ok(input) = input.parse("cr") {
+ raw_c_string(input)
+ } else {
+ Err(Reject)
+ }
+}
+
+fn raw_c_string(input: Cursor) -> Result<Cursor, Reject> {
+ let (input, delimiter) = delimiter_of_raw_string(input)?;
+ let mut bytes = input.bytes().enumerate();
+ while let Some((i, byte)) = bytes.next() {
+ match byte {
+ b'"' if input.rest[i + 1..].starts_with(delimiter) => {
+ let rest = input.advance(i + 1 + delimiter.len());
+ return Ok(literal_suffix(rest));
+ }
+ b'\r' => match bytes.next() {
+ Some((_, b'\n')) => {}
+ _ => break,
+ },
+ b'\0' => break,
+ _ => {}
+ }
}
+ Err(Reject)
+}
+
+fn cooked_c_string(mut input: Cursor) -> Result<Cursor, Reject> {
+ let mut chars = input.char_indices();
+
while let Some((i, ch)) = chars.next() {
match ch {
- '"' if input.rest[i + 1..].starts_with(&input.rest[..n]) => {
- let rest = input.advance(i + 1 + n);
- return Ok(literal_suffix(rest));
+ '"' => {
+ let input = input.advance(i + 1);
+ return Ok(literal_suffix(input));
}
'\r' => match chars.next() {
Some((_, '\n')) => {}
_ => break,
},
- _ => {}
+ '\\' => match chars.next() {
+ Some((_, 'x')) => {
+ backslash_x_nonzero(&mut chars)?;
+ }
+ Some((_, 'n')) | Some((_, 'r')) | Some((_, 't')) | Some((_, '\\'))
+ | Some((_, '\'')) | Some((_, '"')) => {}
+ Some((_, 'u')) => {
+ if backslash_u(&mut chars)? == '\0' {
+ break;
+ }
+ }
+ Some((newline, ch @ '\n')) | Some((newline, ch @ '\r')) => {
+ input = input.advance(newline + 1);
+ trailing_backslash(&mut input, ch as u8)?;
+ chars = input.char_indices();
+ }
+ _ => break,
+ },
+ '\0' => break,
+ _ch => {}
}
}
Err(Reject)
@@ -497,7 +576,7 @@ fn byte(input: Cursor) -> Result<Cursor, Reject> {
let mut bytes = input.bytes().enumerate();
let ok = match bytes.next().map(|(_, b)| b) {
Some(b'\\') => match bytes.next().map(|(_, b)| b) {
- Some(b'x') => backslash_x_byte(&mut bytes),
+ Some(b'x') => backslash_x_byte(&mut bytes).is_ok(),
Some(b'n') | Some(b'r') | Some(b't') | Some(b'\\') | Some(b'0') | Some(b'\'')
| Some(b'"') => true,
_ => false,
@@ -520,8 +599,8 @@ fn character(input: Cursor) -> Result<Cursor, Reject> {
let mut chars = input.char_indices();
let ok = match chars.next().map(|(_, ch)| ch) {
Some('\\') => match chars.next().map(|(_, ch)| ch) {
- Some('x') => backslash_x_char(&mut chars),
- Some('u') => backslash_u(&mut chars),
+ Some('x') => backslash_x_char(&mut chars).is_ok(),
+ Some('u') => backslash_u(&mut chars).is_ok(),
Some('n') | Some('r') | Some('t') | Some('\\') | Some('0') | Some('\'') | Some('"') => {
true
}
@@ -542,32 +621,45 @@ macro_rules! next_ch {
match $chars.next() {
Some((_, ch)) => match ch {
$pat $(| $rest)* => ch,
- _ => return false,
+ _ => return Err(Reject),
},
- None => return false,
+ None => return Err(Reject),
}
};
}
-fn backslash_x_char<I>(chars: &mut I) -> bool
+fn backslash_x_char<I>(chars: &mut I) -> Result<(), Reject>
where
I: Iterator<Item = (usize, char)>,
{
next_ch!(chars @ '0'..='7');
next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
- true
+ Ok(())
}
-fn backslash_x_byte<I>(chars: &mut I) -> bool
+fn backslash_x_byte<I>(chars: &mut I) -> Result<(), Reject>
where
I: Iterator<Item = (usize, u8)>,
{
next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F');
next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F');
- true
+ Ok(())
}
-fn backslash_u<I>(chars: &mut I) -> bool
+fn backslash_x_nonzero<I>(chars: &mut I) -> Result<(), Reject>
+where
+ I: Iterator<Item = (usize, char)>,
+{
+ let first = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
+ let second = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
+ if first == '0' && second == '0' {
+ Err(Reject)
+ } else {
+ Ok(())
+ }
+}
+
+fn backslash_u<I>(chars: &mut I) -> Result<char, Reject>
where
I: Iterator<Item = (usize, char)>,
{
@@ -580,17 +672,37 @@ where
'a'..='f' => 10 + ch as u8 - b'a',
'A'..='F' => 10 + ch as u8 - b'A',
'_' if len > 0 => continue,
- '}' if len > 0 => return char::from_u32(value).is_some(),
- _ => return false,
+ '}' if len > 0 => return char::from_u32(value).ok_or(Reject),
+ _ => break,
};
if len == 6 {
- return false;
+ break;
}
value *= 0x10;
value += u32::from(digit);
len += 1;
}
- false
+ Err(Reject)
+}
+
+fn trailing_backslash(input: &mut Cursor, mut last: u8) -> Result<(), Reject> {
+ let mut whitespace = input.bytes().enumerate();
+ loop {
+ if last == b'\r' && whitespace.next().map_or(true, |(_, b)| b != b'\n') {
+ return Err(Reject);
+ }
+ match whitespace.next() {
+ Some((_, b @ b' ')) | Some((_, b @ b'\t')) | Some((_, b @ b'\n'))
+ | Some((_, b @ b'\r')) => {
+ last = b;
+ }
+ Some((offset, _)) => {
+ *input = input.advance(offset);
+ return Ok(());
+ }
+ None => return Err(Reject),
+ }
+ }
}
fn float(input: Cursor) -> Result<Cursor, Reject> {
@@ -756,7 +868,7 @@ fn digits(mut input: Cursor) -> Result<Cursor, Reject> {
fn punct(input: Cursor) -> PResult<Punct> {
let (rest, ch) = punct_char(input)?;
if ch == '\'' {
- if ident_any(rest)?.0.starts_with("'") {
+ if ident_any(rest)?.0.starts_with_char('\'') {
Err(Reject)
} else {
Ok((rest, Punct::new('\'', Spacing::Joint)))
@@ -848,7 +960,7 @@ fn doc_comment_contents(input: Cursor) -> PResult<(&str, bool)> {
Ok((input, (&s[3..s.len() - 2], true)))
} else if input.starts_with("///") {
let input = input.advance(3);
- if input.starts_with("/") {
+ if input.starts_with_char('/') {
return Err(Reject);
}
let (input, s) = take_until_newline_or_eof(input);