diff options
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/lexer/mod.rs | 43 | ||||
| -rw-r--r-- | src/libsyntax/parse/mod.rs | 26 | ||||
| -rw-r--r-- | src/libsyntax/parse/obsolete.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 4 |
4 files changed, 50 insertions, 25 deletions
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 532b632fac8..78470f00207 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -20,7 +20,6 @@ use std::borrow::{IntoCow, Cow}; use std::char; use std::fmt; use std::mem::replace; -use std::num; use std::rc::Rc; pub use ext::tt::transcribe::{TtReader, new_tt_reader, new_tt_reader_with_doc_flag}; @@ -621,9 +620,9 @@ impl<'a> StringReader<'a> { let base = 10; // find the integer representing the name - self.scan_digits(base); + self.scan_digits(base, base); let encoded_name : u32 = self.with_str_from(start_bpos, |s| { - num::from_str_radix(s, 10).unwrap_or_else(|_| { + u32::from_str_radix(s, 10).unwrap_or_else(|_| { panic!("expected digits representing a name, got {:?}, {}, range [{:?},{:?}]", s, whence, start_bpos, self.last_pos); }) @@ -639,9 +638,9 @@ impl<'a> StringReader<'a> { // find the integer representing the ctxt let start_bpos = self.last_pos; - self.scan_digits(base); + self.scan_digits(base, base); let encoded_ctxt : ast::SyntaxContext = self.with_str_from(start_bpos, |s| { - num::from_str_radix(s, 10).unwrap_or_else(|_| { + u32::from_str_radix(s, 10).unwrap_or_else(|_| { panic!("expected digits representing a ctxt, got {:?}, {}", s, whence); }) }); @@ -653,16 +652,28 @@ impl<'a> StringReader<'a> { ctxt: encoded_ctxt, } } - /// Scan through any digits (base `radix`) or underscores, and return how - /// many digits there were. - fn scan_digits(&mut self, radix: u32) -> usize { + /// Scan through any digits (base `scan_radix`) or underscores, + /// and return how many digits there were. + /// + /// `real_radix` represents the true radix of the number we're + /// interested in, and errors will be emitted for any digits + /// between `real_radix` and `scan_radix`. + fn scan_digits(&mut self, real_radix: u32, scan_radix: u32) -> usize { + assert!(real_radix <= scan_radix); let mut len = 0; loop { let c = self.curr; if c == Some('_') { debug!("skipping a _"); self.bump(); continue; } - match c.and_then(|cc| cc.to_digit(radix)) { + match c.and_then(|cc| cc.to_digit(scan_radix)) { Some(_) => { debug!("{:?} in scan_digits", c); + // check that the hypothetical digit is actually + // in range for the true radix + if c.unwrap().to_digit(real_radix).is_none() { + self.err_span_(self.last_pos, self.pos, + &format!("invalid digit for a base {} literal", + real_radix)); + } len += 1; self.bump(); } @@ -681,11 +692,11 @@ impl<'a> StringReader<'a> { if c == '0' { match self.curr.unwrap_or('\0') { - 'b' => { self.bump(); base = 2; num_digits = self.scan_digits(2); } - 'o' => { self.bump(); base = 8; num_digits = self.scan_digits(8); } - 'x' => { self.bump(); base = 16; num_digits = self.scan_digits(16); } + 'b' => { self.bump(); base = 2; num_digits = self.scan_digits(2, 10); } + 'o' => { self.bump(); base = 8; num_digits = self.scan_digits(8, 10); } + 'x' => { self.bump(); base = 16; num_digits = self.scan_digits(16, 16); } '0'...'9' | '_' | '.' => { - num_digits = self.scan_digits(10) + 1; + num_digits = self.scan_digits(10, 10) + 1; } _ => { // just a 0 @@ -693,7 +704,7 @@ impl<'a> StringReader<'a> { } } } else if c.is_digit(10) { - num_digits = self.scan_digits(10) + 1; + num_digits = self.scan_digits(10, 10) + 1; } else { num_digits = 0; } @@ -712,7 +723,7 @@ impl<'a> StringReader<'a> { // with a number self.bump(); if self.curr.unwrap_or('\0').is_digit(10) { - self.scan_digits(10); + self.scan_digits(10, 10); self.scan_float_exponent(); } let last_pos = self.last_pos; @@ -935,7 +946,7 @@ impl<'a> StringReader<'a> { if self.curr_is('-') || self.curr_is('+') { self.bump(); } - if self.scan_digits(10) == 0 { + if self.scan_digits(10, 10) == 0 { self.err_span_(self.last_pos, self.pos, "expected at least one digit in exponent") } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index bea42a88bf5..f59e1d8214a 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -21,6 +21,7 @@ use std::cell::{Cell, RefCell}; use std::fs::File; use std::io::Read; use std::iter; +#[allow(deprecated)] // Int use std::num::Int; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -372,7 +373,7 @@ pub fn maybe_aborted<T>(result: T, p: Parser) -> T { /// well. Can take any slice prefixed by a character escape. Returns the /// character and the number of characters consumed. pub fn char_lit(lit: &str) -> (char, isize) { - use std::{num, char}; + use std::char; let mut chars = lit.chars(); let c = match (chars.next(), chars.next()) { @@ -399,7 +400,7 @@ pub fn char_lit(lit: &str) -> (char, isize) { let msg2 = &msg[..]; fn esc(len: usize, lit: &str) -> Option<(char, isize)> { - num::from_str_radix(&lit[2..len], 16).ok() + u32::from_str_radix(&lit[2..len], 16).ok() .and_then(char::from_u32) .map(|x| (x, len as isize)) } @@ -408,7 +409,7 @@ pub fn char_lit(lit: &str) -> (char, isize) { if lit.as_bytes()[2] == b'{' { let idx = lit.find('}').expect(msg2); let subslice = &lit[3..idx]; - num::from_str_radix(subslice, 16).ok() + u32::from_str_radix(subslice, 16).ok() .and_then(char::from_u32) .map(|x| (x, subslice.chars().count() as isize + 4)) } else { @@ -582,7 +583,7 @@ pub fn byte_lit(lit: &str) -> (u8, usize) { b'\'' => b'\'', b'0' => b'\0', _ => { - match ::std::num::from_str_radix::<u64>(&lit[2..4], 16).ok() { + match u64::from_str_radix(&lit[2..4], 16).ok() { Some(c) => if c > 0xFF { panic!(err(2)) @@ -733,9 +734,22 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> debug!("integer_lit: the type is {:?}, base {:?}, the new string is {:?}, the original \ string was {:?}, the original suffix was {:?}", ty, base, s, orig, suffix); - let res: u64 = match ::std::num::from_str_radix(s, base).ok() { + let res = match u64::from_str_radix(s, base).ok() { Some(r) => r, - None => { sd.span_err(sp, "int literal is too large"); 0 } + None => { + // small bases are lexed as if they were base 10, e.g, the string + // might be `0b10201`. This will cause the conversion above to fail, + // but these cases have errors in the lexer: we don't want to emit + // two errors, and we especially don't want to emit this error since + // it isn't necessarily true. + let already_errored = base < 10 && + s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base)); + + if !already_errored { + sd.span_err(sp, "int literal is too large"); + } + 0 + } }; // adjust the sign diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index bb9b586bb3f..f120dde8e1c 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -20,7 +20,7 @@ use parse::token; use ptr::P; /// The specific types of unsupported syntax -#[derive(Copy, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] pub enum ObsoleteSyntax { ClosureKind, ExternCrateString, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6f1f73aa2a9..c7216243239 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -96,7 +96,7 @@ type ItemInfo = (Ident, Item_, Option<Vec<Attribute> >); /// How to parse a path. There are four different kinds of paths, all of which /// are parsed somewhat differently. -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum PathParsingMode { /// A path with no type parameters; e.g. `foo::bar::Baz` NoTypesAllowed, @@ -109,7 +109,7 @@ pub enum PathParsingMode { } /// How to parse a bound, whether to allow bound modifiers such as `?`. -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum BoundParsingMode { Bare, Modified, |
