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:
@@ -70,10 +70,10 @@ impl<'a> Reader for StringReader<'a> {
|
|||||||
ret_val
|
ret_val
|
||||||
}
|
}
|
||||||
fn fatal(&self, m: &str) -> ! {
|
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) {
|
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 {
|
fn peek(&self) -> TokenAndSpan {
|
||||||
// FIXME(pcwalton): Bad copy!
|
// FIXME(pcwalton): Bad copy!
|
||||||
@@ -137,43 +137,52 @@ impl<'a> StringReader<'a> {
|
|||||||
self.curr == Some(c)
|
self.curr == Some(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Report a lexical error spanning [`from_pos`, `to_pos`)
|
/// Report a fatal lexical error with a given span.
|
||||||
fn fatal_span(&mut self, from_pos: BytePos, to_pos: BytePos, m: &str) -> ! {
|
pub fn fatal_span(&self, sp: Span, m: &str) -> ! {
|
||||||
self.peek_span = codemap::mk_sp(from_pos, to_pos);
|
self.span_diagnostic.span_fatal(sp, m)
|
||||||
self.fatal(m);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn err_span(&mut self, from_pos: BytePos, to_pos: BytePos, m: &str) {
|
/// Report a lexical error with a given span.
|
||||||
self.peek_span = codemap::mk_sp(from_pos, to_pos);
|
pub fn err_span(&self, sp: Span, m: &str) {
|
||||||
self.err(m);
|
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
|
/// Report a lexical error spanning [`from_pos`, `to_pos`), appending an
|
||||||
/// escaped character to the error message
|
/// 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();
|
let mut m = m.to_string();
|
||||||
m.push_str(": ");
|
m.push_str(": ");
|
||||||
char::escape_default(c, |c| m.push_char(c));
|
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
|
/// Report a lexical error spanning [`from_pos`, `to_pos`), appending an
|
||||||
/// escaped character to the error message
|
/// 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();
|
let mut m = m.to_string();
|
||||||
m.push_str(": ");
|
m.push_str(": ");
|
||||||
char::escape_default(c, |c| m.push_char(c));
|
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
|
/// Report a lexical error spanning [`from_pos`, `to_pos`), appending the
|
||||||
/// offending string to the error message
|
/// 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(": ");
|
m.push_str(": ");
|
||||||
let from = self.byte_offset(from_pos).to_uint();
|
let from = self.byte_offset(from_pos).to_uint();
|
||||||
let to = self.byte_offset(to_pos).to_uint();
|
let to = self.byte_offset(to_pos).to_uint();
|
||||||
m.push_str(self.filemap.src.as_slice().slice(from, to));
|
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
|
/// Advance peek_tok and peek_span to refer to the next token, and
|
||||||
@@ -369,7 +378,7 @@ impl<'a> StringReader<'a> {
|
|||||||
"unterminated block comment"
|
"unterminated block comment"
|
||||||
};
|
};
|
||||||
let last_bpos = self.last_pos;
|
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('*') {
|
} else if self.curr_is('/') && self.nextch_is('*') {
|
||||||
level += 1;
|
level += 1;
|
||||||
self.bump();
|
self.bump();
|
||||||
@@ -421,7 +430,7 @@ impl<'a> StringReader<'a> {
|
|||||||
return Some(rslt);
|
return Some(rslt);
|
||||||
} else {
|
} else {
|
||||||
let last_bpos = self.last_pos;
|
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
|
rslt.push_str("1"); // arbitrary placeholder exponent
|
||||||
return Some(rslt);
|
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) {
|
fn check_float_base(&mut self, start_bpos: BytePos, last_bpos: BytePos, base: uint) {
|
||||||
match base {
|
match base {
|
||||||
16u => self.err_span(start_bpos, last_bpos, "hexadecimal float literal is not supported"),
|
16u => self.err_span_(start_bpos, last_bpos,
|
||||||
8u => self.err_span(start_bpos, last_bpos, "octal float literal is not supported"),
|
"hexadecimal float literal is not supported"),
|
||||||
2u => self.err_span(start_bpos, last_bpos, "binary 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 {
|
if num_str.len() == 0u {
|
||||||
let last_bpos = self.last_pos;
|
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();
|
num_str = "1".to_string();
|
||||||
}
|
}
|
||||||
let parsed = match from_str_radix::<u64>(num_str.as_slice(),
|
let parsed = match from_str_radix::<u64>(num_str.as_slice(),
|
||||||
@@ -517,7 +527,7 @@ impl<'a> StringReader<'a> {
|
|||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
None => {
|
None => {
|
||||||
let last_bpos = self.last_pos;
|
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
|
1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -573,7 +583,7 @@ impl<'a> StringReader<'a> {
|
|||||||
return token::LIT_FLOAT(str_to_ident(num_str.as_slice()), ast::TyF128);
|
return token::LIT_FLOAT(str_to_ident(num_str.as_slice()), ast::TyF128);
|
||||||
}
|
}
|
||||||
let last_bpos = self.last_pos;
|
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 {
|
if is_float {
|
||||||
let last_bpos = self.last_pos;
|
let last_bpos = self.last_pos;
|
||||||
@@ -583,7 +593,7 @@ impl<'a> StringReader<'a> {
|
|||||||
} else {
|
} else {
|
||||||
if num_str.len() == 0u {
|
if num_str.len() == 0u {
|
||||||
let last_bpos = self.last_pos;
|
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();
|
num_str = "1".to_string();
|
||||||
}
|
}
|
||||||
let parsed = match from_str_radix::<u64>(num_str.as_slice(),
|
let parsed = match from_str_radix::<u64>(num_str.as_slice(),
|
||||||
@@ -591,7 +601,7 @@ impl<'a> StringReader<'a> {
|
|||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
None => {
|
None => {
|
||||||
let last_bpos = self.last_pos;
|
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
|
1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -609,11 +619,11 @@ impl<'a> StringReader<'a> {
|
|||||||
for _ in range(0, n_hex_digits) {
|
for _ in range(0, n_hex_digits) {
|
||||||
if self.is_eof() {
|
if self.is_eof() {
|
||||||
let last_bpos = self.last_pos;
|
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) {
|
if self.curr_is(delim) {
|
||||||
let last_bpos = self.last_pos;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
let c = self.curr.unwrap_or('\x00');
|
let c = self.curr.unwrap_or('\x00');
|
||||||
@@ -630,7 +640,7 @@ impl<'a> StringReader<'a> {
|
|||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
None => {
|
None => {
|
||||||
let last_bpos = self.last_pos;
|
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;
|
let last_bpos = self.last_pos;
|
||||||
if token::is_keyword(token::keywords::Self,
|
if token::is_keyword(token::keywords::Self,
|
||||||
keyword_checking_token) {
|
keyword_checking_token) {
|
||||||
self.err_span(start,
|
self.err_span_(start,
|
||||||
last_bpos,
|
last_bpos,
|
||||||
"invalid lifetime name: 'self \
|
"invalid lifetime name: 'self \
|
||||||
is no longer a special lifetime");
|
is no longer a special lifetime");
|
||||||
} else if token::is_any_keyword(keyword_checking_token) &&
|
} else if token::is_any_keyword(keyword_checking_token) &&
|
||||||
!token::is_keyword(token::keywords::Static,
|
!token::is_keyword(token::keywords::Static,
|
||||||
keyword_checking_token) {
|
keyword_checking_token) {
|
||||||
self.err_span(start,
|
self.err_span_(start,
|
||||||
last_bpos,
|
last_bpos,
|
||||||
"invalid lifetime name");
|
"invalid lifetime name");
|
||||||
}
|
}
|
||||||
@@ -922,7 +932,7 @@ impl<'a> StringReader<'a> {
|
|||||||
while !self_.curr_is('"') {
|
while !self_.curr_is('"') {
|
||||||
if self_.is_eof() {
|
if self_.is_eof() {
|
||||||
let last_pos = self_.last_pos;
|
let last_pos = self_.last_pos;
|
||||||
self_.fatal_span(start, last_pos,
|
self_.fatal_span_(start, last_pos,
|
||||||
"unterminated double quote byte string");
|
"unterminated double quote byte string");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -947,7 +957,7 @@ impl<'a> StringReader<'a> {
|
|||||||
|
|
||||||
if self_.is_eof() {
|
if self_.is_eof() {
|
||||||
let last_pos = self_.last_pos;
|
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('"') {
|
} else if !self_.curr_is('"') {
|
||||||
let last_pos = self_.last_pos;
|
let last_pos = self_.last_pos;
|
||||||
let ch = self_.curr.unwrap();
|
let ch = self_.curr.unwrap();
|
||||||
@@ -963,7 +973,7 @@ impl<'a> StringReader<'a> {
|
|||||||
match self_.curr {
|
match self_.curr {
|
||||||
None => {
|
None => {
|
||||||
let last_pos = self_.last_pos;
|
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('"') => {
|
Some('"') => {
|
||||||
content_end_bpos = self_.last_pos;
|
content_end_bpos = self_.last_pos;
|
||||||
@@ -997,7 +1007,7 @@ impl<'a> StringReader<'a> {
|
|||||||
while !self.curr_is('"') {
|
while !self.curr_is('"') {
|
||||||
if self.is_eof() {
|
if self.is_eof() {
|
||||||
let last_bpos = self.last_pos;
|
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;
|
let ch_start = self.last_pos;
|
||||||
@@ -1020,7 +1030,7 @@ impl<'a> StringReader<'a> {
|
|||||||
|
|
||||||
if self.is_eof() {
|
if self.is_eof() {
|
||||||
let last_bpos = self.last_pos;
|
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('"') {
|
} else if !self.curr_is('"') {
|
||||||
let last_bpos = self.last_pos;
|
let last_bpos = self.last_pos;
|
||||||
let curr_char = self.curr.unwrap();
|
let curr_char = self.curr.unwrap();
|
||||||
@@ -1035,7 +1045,7 @@ impl<'a> StringReader<'a> {
|
|||||||
'outer: loop {
|
'outer: loop {
|
||||||
if self.is_eof() {
|
if self.is_eof() {
|
||||||
let last_bpos = self.last_pos;
|
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('"') {
|
if self.curr_is('"') {
|
||||||
content_end_bpos = self.last_pos;
|
content_end_bpos = self.last_pos;
|
||||||
|
|||||||
Reference in New Issue
Block a user