From d41058ed39fcd7e15ce9d0e7705643da85c94271 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Sat, 24 May 2014 01:12:22 -0700 Subject: [PATCH] Don't require mutable StringReader to emit lexer errors Teach StringReader how to emit errors for arbitrary spans, so we don't need to modify peek_span. This allows for emitting errors without having a &mut borrow of the StringReader. --- src/libsyntax/parse/lexer/mod.rs | 94 ++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 42 deletions(-) diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 4ea47eb0a3d..348445149a4 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -70,10 +70,10 @@ impl<'a> Reader for StringReader<'a> { ret_val } fn fatal(&self, m: &str) -> ! { - self.span_diagnostic.span_fatal(self.peek_span, m) + self.fatal_span(self.peek_span, m) } fn err(&self, m: &str) { - self.span_diagnostic.span_err(self.peek_span, m) + self.err_span(self.peek_span, m) } fn peek(&self) -> TokenAndSpan { // FIXME(pcwalton): Bad copy! @@ -137,43 +137,52 @@ impl<'a> StringReader<'a> { self.curr == Some(c) } - /// Report a lexical error spanning [`from_pos`, `to_pos`) - fn fatal_span(&mut self, from_pos: BytePos, to_pos: BytePos, m: &str) -> ! { - self.peek_span = codemap::mk_sp(from_pos, to_pos); - self.fatal(m); + /// Report a fatal lexical error with a given span. + pub fn fatal_span(&self, sp: Span, m: &str) -> ! { + self.span_diagnostic.span_fatal(sp, m) } - fn err_span(&mut self, from_pos: BytePos, to_pos: BytePos, m: &str) { - self.peek_span = codemap::mk_sp(from_pos, to_pos); - self.err(m); + /// Report a lexical error with a given span. + pub fn err_span(&self, sp: Span, m: &str) { + self.span_diagnostic.span_err(sp, m) + } + + /// Report a fatal error spanning [`from_pos`, `to_pos`). + fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> ! { + self.fatal_span(codemap::mk_sp(from_pos, to_pos), m) + } + + /// Report a lexical error spanning [`from_pos`, `to_pos`). + fn err_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) { + self.err_span(codemap::mk_sp(from_pos, to_pos), m) } /// Report a lexical error spanning [`from_pos`, `to_pos`), appending an /// escaped character to the error message - fn fatal_span_char(&mut self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) -> ! { + fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) -> ! { let mut m = m.to_string(); m.push_str(": "); char::escape_default(c, |c| m.push_char(c)); - self.fatal_span(from_pos, to_pos, m.as_slice()); + self.fatal_span_(from_pos, to_pos, m.as_slice()); } /// Report a lexical error spanning [`from_pos`, `to_pos`), appending an /// escaped character to the error message - fn err_span_char(&mut self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) { + fn err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) { let mut m = m.to_string(); m.push_str(": "); char::escape_default(c, |c| m.push_char(c)); - self.err_span(from_pos, to_pos, m.as_slice()); + self.err_span_(from_pos, to_pos, m.as_slice()); } /// Report a lexical error spanning [`from_pos`, `to_pos`), appending the /// offending string to the error message - fn fatal_span_verbose(&mut self, from_pos: BytePos, to_pos: BytePos, mut m: String) -> ! { + fn fatal_span_verbose(&self, from_pos: BytePos, to_pos: BytePos, mut m: String) -> ! { m.push_str(": "); let from = self.byte_offset(from_pos).to_uint(); let to = self.byte_offset(to_pos).to_uint(); m.push_str(self.filemap.src.as_slice().slice(from, to)); - self.fatal_span(from_pos, to_pos, m.as_slice()); + self.fatal_span_(from_pos, to_pos, m.as_slice()); } /// Advance peek_tok and peek_span to refer to the next token, and @@ -369,7 +378,7 @@ impl<'a> StringReader<'a> { "unterminated block comment" }; let last_bpos = self.last_pos; - self.fatal_span(start_bpos, last_bpos, msg); + self.fatal_span_(start_bpos, last_bpos, msg); } else if self.curr_is('/') && self.nextch_is('*') { level += 1; self.bump(); @@ -421,7 +430,7 @@ impl<'a> StringReader<'a> { return Some(rslt); } else { let last_bpos = self.last_pos; - self.err_span(start_bpos, last_bpos, "scan_exponent: bad fp literal"); + self.err_span_(start_bpos, last_bpos, "scan_exponent: bad fp literal"); rslt.push_str("1"); // arbitrary placeholder exponent return Some(rslt); } @@ -447,9 +456,10 @@ impl<'a> StringReader<'a> { fn check_float_base(&mut self, start_bpos: BytePos, last_bpos: BytePos, base: uint) { match base { - 16u => self.err_span(start_bpos, last_bpos, "hexadecimal float literal is not supported"), - 8u => self.err_span(start_bpos, last_bpos, "octal float literal is not supported"), - 2u => self.err_span(start_bpos, last_bpos, "binary float literal is not supported"), + 16u => self.err_span_(start_bpos, last_bpos, + "hexadecimal float literal is not supported"), + 8u => self.err_span_(start_bpos, last_bpos, "octal float literal is not supported"), + 2u => self.err_span_(start_bpos, last_bpos, "binary float literal is not supported"), _ => () } } @@ -509,7 +519,7 @@ impl<'a> StringReader<'a> { } if num_str.len() == 0u { let last_bpos = self.last_pos; - self.err_span(start_bpos, last_bpos, "no valid digits found for number"); + self.err_span_(start_bpos, last_bpos, "no valid digits found for number"); num_str = "1".to_string(); } let parsed = match from_str_radix::(num_str.as_slice(), @@ -517,7 +527,7 @@ impl<'a> StringReader<'a> { Some(p) => p, None => { let last_bpos = self.last_pos; - self.err_span(start_bpos, last_bpos, "int literal is too large"); + self.err_span_(start_bpos, last_bpos, "int literal is too large"); 1 } }; @@ -573,7 +583,7 @@ impl<'a> StringReader<'a> { return token::LIT_FLOAT(str_to_ident(num_str.as_slice()), ast::TyF128); } let last_bpos = self.last_pos; - self.err_span(start_bpos, last_bpos, "expected `f32`, `f64` or `f128` suffix"); + self.err_span_(start_bpos, last_bpos, "expected `f32`, `f64` or `f128` suffix"); } if is_float { let last_bpos = self.last_pos; @@ -583,7 +593,7 @@ impl<'a> StringReader<'a> { } else { if num_str.len() == 0u { let last_bpos = self.last_pos; - self.err_span(start_bpos, last_bpos, "no valid digits found for number"); + self.err_span_(start_bpos, last_bpos, "no valid digits found for number"); num_str = "1".to_string(); } let parsed = match from_str_radix::(num_str.as_slice(), @@ -591,7 +601,7 @@ impl<'a> StringReader<'a> { Some(p) => p, None => { let last_bpos = self.last_pos; - self.err_span(start_bpos, last_bpos, "int literal is too large"); + self.err_span_(start_bpos, last_bpos, "int literal is too large"); 1 } }; @@ -609,11 +619,11 @@ impl<'a> StringReader<'a> { for _ in range(0, n_hex_digits) { if self.is_eof() { let last_bpos = self.last_pos; - self.fatal_span(start_bpos, last_bpos, "unterminated numeric character escape"); + self.fatal_span_(start_bpos, last_bpos, "unterminated numeric character escape"); } if self.curr_is(delim) { let last_bpos = self.last_pos; - self.err_span(start_bpos, last_bpos, "numeric character escape is too short"); + self.err_span_(start_bpos, last_bpos, "numeric character escape is too short"); break; } let c = self.curr.unwrap_or('\x00'); @@ -630,7 +640,7 @@ impl<'a> StringReader<'a> { Some(x) => x, None => { let last_bpos = self.last_pos; - self.err_span(start_bpos, last_bpos, "illegal numeric character escape"); + self.err_span_(start_bpos, last_bpos, "illegal numeric character escape"); '?' } } @@ -856,16 +866,16 @@ impl<'a> StringReader<'a> { let last_bpos = self.last_pos; if token::is_keyword(token::keywords::Self, keyword_checking_token) { - self.err_span(start, - last_bpos, - "invalid lifetime name: 'self \ - is no longer a special lifetime"); + self.err_span_(start, + last_bpos, + "invalid lifetime name: 'self \ + is no longer a special lifetime"); } else if token::is_any_keyword(keyword_checking_token) && !token::is_keyword(token::keywords::Static, keyword_checking_token) { - self.err_span(start, - last_bpos, - "invalid lifetime name"); + self.err_span_(start, + last_bpos, + "invalid lifetime name"); } return token::LIFETIME(ident); } @@ -922,8 +932,8 @@ impl<'a> StringReader<'a> { while !self_.curr_is('"') { if self_.is_eof() { let last_pos = self_.last_pos; - self_.fatal_span(start, last_pos, - "unterminated double quote byte string"); + self_.fatal_span_(start, last_pos, + "unterminated double quote byte string"); } let ch_start = self_.last_pos; @@ -947,7 +957,7 @@ impl<'a> StringReader<'a> { if self_.is_eof() { let last_pos = self_.last_pos; - self_.fatal_span(start_bpos, last_pos, "unterminated raw string"); + self_.fatal_span_(start_bpos, last_pos, "unterminated raw string"); } else if !self_.curr_is('"') { let last_pos = self_.last_pos; let ch = self_.curr.unwrap(); @@ -963,7 +973,7 @@ impl<'a> StringReader<'a> { match self_.curr { None => { let last_pos = self_.last_pos; - self_.fatal_span(start_bpos, last_pos, "unterminated raw string") + self_.fatal_span_(start_bpos, last_pos, "unterminated raw string") }, Some('"') => { content_end_bpos = self_.last_pos; @@ -997,7 +1007,7 @@ impl<'a> StringReader<'a> { while !self.curr_is('"') { if self.is_eof() { let last_bpos = self.last_pos; - self.fatal_span(start_bpos, last_bpos, "unterminated double quote string"); + self.fatal_span_(start_bpos, last_bpos, "unterminated double quote string"); } let ch_start = self.last_pos; @@ -1020,7 +1030,7 @@ impl<'a> StringReader<'a> { if self.is_eof() { let last_bpos = self.last_pos; - self.fatal_span(start_bpos, last_bpos, "unterminated raw string"); + self.fatal_span_(start_bpos, last_bpos, "unterminated raw string"); } else if !self.curr_is('"') { let last_bpos = self.last_pos; let curr_char = self.curr.unwrap(); @@ -1035,7 +1045,7 @@ impl<'a> StringReader<'a> { 'outer: loop { if self.is_eof() { let last_bpos = self.last_pos; - self.fatal_span(start_bpos, last_bpos, "unterminated raw string"); + self.fatal_span_(start_bpos, last_bpos, "unterminated raw string"); } if self.curr_is('"') { content_end_bpos = self.last_pos;