From 744a6b848693f7f346317f5df7db646c71085627 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 1 Jun 2017 11:34:29 -0700 Subject: [PATCH] Check for word boundary after numeric suffixes --- src/stable.rs | 89 ++++++++++++++++++++++++++------------------------- src/strnom.rs | 8 +---- 2 files changed, 46 insertions(+), 51 deletions(-) diff --git a/src/stable.rs b/src/stable.rs index 02cd626..297177a 100644 --- a/src/stable.rs +++ b/src/stable.rs @@ -11,7 +11,7 @@ use std::vec; use proc_macro; use unicode_xid::UnicodeXID; -use strnom::{PResult, skip_whitespace, block_comment, whitespace}; +use strnom::{PResult, skip_whitespace, block_comment, whitespace, word_break}; use {TokenTree, TokenKind, Delimiter, OpKind}; @@ -721,19 +721,17 @@ fn backslash_u(chars: &mut I) -> bool true } -named!(float -> (), do_parse!( - float_string >> - alt!( - tag!("f32") => { |_| () } - | - tag!("f64") => { |_| () } - | - epsilon!() - ) >> - (()) -)); +fn float(input: &str) -> PResult<()> { + let (rest, ()) = float_digits(input)?; + for suffix in &["f32", "f64"] { + if rest.starts_with(suffix) { + return word_break(&rest[suffix.len()..]); + } + } + word_break(rest) +} -fn float_string(input: &str) -> PResult<()> { +fn float_digits(input: &str) -> PResult<()> { let mut chars = input.chars().peekable(); match chars.next() { Some(ch) if ch >= '0' && ch <= '9' => {} @@ -808,37 +806,28 @@ fn float_string(input: &str) -> PResult<()> { Ok((&input[len..], ())) } -named!(int -> (), do_parse!( - digits >> - alt!( - tag!("isize") => { |_| () } - | - tag!("i8") => { |_| () } - | - tag!("i16") => { |_| () } - | - tag!("i32") => { |_| () } - | - tag!("i64") => { |_| () } - | - tag!("i128") => { |_| () } - | - tag!("usize") => { |_| () } - | - tag!("u8") => { |_| () } - | - tag!("u16") => { |_| () } - | - tag!("u32") => { |_| () } - | - tag!("u64") => { |_| () } - | - tag!("u128") => { |_| () } - | - epsilon!() - ) >> - (()) -)); +fn int(input: &str) -> PResult<()> { + let (rest, ()) = digits(input)?; + for suffix in &[ + "isize", + "i8", + "i16", + "i32", + "i64", + "i128", + "usize", + "u8", + "u16", + "u32", + "u64", + "u128", + ] { + if rest.starts_with(suffix) { + return word_break(&rest[suffix.len()..]); + } + } + word_break(rest) +} fn digits(mut input: &str) -> PResult<()> { let base = if input.starts_with("0x") { @@ -996,4 +985,16 @@ mod tests { 0xffffffffffffffffffffffffffffffff "); } + + #[test] + fn fail() { + fn fail(p: &str) { + if p.parse::().is_ok() { + panic!("should have failed to parse: {}", p); + } + } + fail("1x"); + fail("1u80"); + fail("1f320"); + } } diff --git a/src/strnom.rs b/src/strnom.rs index 875c4bf..22b39e8 100644 --- a/src/strnom.rs +++ b/src/strnom.rs @@ -90,7 +90,7 @@ fn is_whitespace(ch: char) -> bool { ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}' } -fn word_break(input: &str) -> PResult<()> { +pub fn word_break(input: &str) -> PResult<()> { match input.chars().next() { Some(ch) if UnicodeXID::is_xid_continue(ch) => Err(LexError), Some(_) | None => Ok((input, ())), @@ -336,12 +336,6 @@ pub fn keyword<'a>(input: &'a str, token: &'static str) -> PResult<'a, &'a str> } } -macro_rules! epsilon { - ($i:expr,) => { - Ok(($i, ())) - }; -} - macro_rules! preceded { ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => { match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) {