Skip to content

Commit

Permalink
Optionally skip CloneTypeIdentifier
Browse files Browse the repository at this point in the history
  • Loading branch information
jan-auer committed Apr 16, 2020
1 parent 9059eac commit fbd5741
Showing 1 changed file with 36 additions and 6 deletions.
42 changes: 36 additions & 6 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1512,7 +1512,7 @@ where
/// <clone-suffix> ::= [ . <clone-type-identifier> ] [ . <nonnegative number> ]*

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CloneSuffix(CloneTypeIdentifier, Vec<isize>);
pub struct CloneSuffix(Option<CloneTypeIdentifier>, Vec<isize>);

impl Parse for CloneSuffix {
fn parse<'a, 'b>(
Expand All @@ -1522,8 +1522,11 @@ impl Parse for CloneSuffix {
) -> Result<(CloneSuffix, IndexStr<'b>)> {
try_begin_parse!("CloneSuffix", ctx, input);

let tail = consume(b".", input)?;
let (identifier, mut tail) = CloneTypeIdentifier::parse(ctx, subs, tail)?;
if input.peek() != Some(b'.') {
return Err(error::Error::UnexpectedText);
}

let (identifier, mut tail) = zero_or_one(ctx, subs, input);

let mut numbers = Vec::with_capacity(1);
while let Ok((n, t)) = consume(b".", tail).and_then(|t| parse_number(10, false, t)) {
Expand All @@ -1532,6 +1535,10 @@ impl Parse for CloneSuffix {
}

let clone_suffix = CloneSuffix(identifier, numbers);
if clone_suffix.0.is_none() && clone_suffix.1.is_empty() {
return Err(error::Error::UnexpectedText);
}

Ok((clone_suffix, tail))
}
}
Expand All @@ -1546,8 +1553,10 @@ where
scope: Option<ArgScopeStack<'prev, 'subs>>,
) -> fmt::Result {
let ctx = try_begin_demangle!(self, ctx, scope);
write!(ctx, " [clone")?;
self.0.demangle(ctx, scope)?;
write!(ctx, " [clone ")?;
if let Some(ref identifier) = self.0 {
identifier.demangle(ctx, scope)?;
}
for nonnegative in &self.1 {
write!(ctx, ".{}", nonnegative)?;
}
Expand Down Expand Up @@ -2758,6 +2767,7 @@ impl Parse for CloneTypeIdentifier {
) -> Result<(CloneTypeIdentifier, IndexStr<'b>)> {
try_begin_parse!("CloneTypeIdentifier", ctx, input);

let input = consume(b".", input)?;
if input.is_empty() {
return Err(error::Error::UnexpectedEnd);
}
Expand All @@ -2773,6 +2783,11 @@ impl Parse for CloneTypeIdentifier {
return Err(error::Error::UnexpectedText);
}

// Detect nonnegative numbers in place of clone identifiers.
if input.range(0..end).as_ref().iter().all(|&c| char::from(c).is_ascii_digit()) {
return Err(error::Error::UnexpectedText);
}

let tail = input.range_from(end..);

let identifier = CloneTypeIdentifier {
Expand Down Expand Up @@ -2800,7 +2815,7 @@ where

let source_name = String::from_utf8_lossy(ident);
ctx.set_source_name(self.start, self.end);
write!(ctx, " .{}", source_name)?;
write!(ctx, ".{}", source_name)?;
Ok(())
}
}
Expand Down Expand Up @@ -7498,6 +7513,21 @@ where
}
}

fn zero_or_one<'a, 'b, P>(
ctx: &'a ParseContext,
subs: &'a mut SubstitutionTable,
input: IndexStr<'b>,
) -> (Option<P>, IndexStr<'b>)
where
P: Parse,
{
if let Ok((parsed, tail)) = P::parse(ctx, subs, input) {
(Some(parsed), tail)
} else {
(None, input)
}
}

/// Parse a number with the given `base`. Do not allow negative numbers
/// (prefixed with an 'n' instead of a '-') if `allow_signed` is false.
#[allow(unsafe_code)]
Expand Down

0 comments on commit fbd5741

Please sign in to comment.