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:
parent
0f481db211
commit
d41058ed39
1 changed files with 52 additions and 42 deletions
|
@ -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,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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue