1
Fork 0

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.
This commit is contained in:
Kevin Ballard 2014-05-24 01:12:22 -07:00
parent 0f481db211
commit d41058ed39

View file

@ -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::<u64>(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::<u64>(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,14 +866,14 @@ impl<'a> StringReader<'a> {
let last_bpos = self.last_pos;
if token::is_keyword(token::keywords::Self,
keyword_checking_token) {
self.err_span(start,
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,
self.err_span_(start,
last_bpos,
"invalid lifetime name");
}
@ -922,7 +932,7 @@ impl<'a> StringReader<'a> {
while !self_.curr_is('"') {
if self_.is_eof() {
let last_pos = self_.last_pos;
self_.fatal_span(start, last_pos,
self_.fatal_span_(start, last_pos,
"unterminated double quote byte string");
}
@ -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;