Skip to content

Commit

Permalink
Don't require mutable StringReader to emit lexer errors
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
lilyball committed Jun 18, 2014
1 parent 0f481db commit d41058e
Showing 1 changed file with 52 additions and 42 deletions.
94 changes: 52 additions & 42 deletions src/libsyntax/parse/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
}
Expand All @@ -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"),
_ => ()
}
}
Expand Down Expand Up @@ -509,15 +519,15 @@ 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(),
base as uint) {
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
}
};
Expand Down Expand Up @@ -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;
Expand All @@ -583,15 +593,15 @@ 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(),
base as uint) {
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
}
};
Expand All @@ -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');
Expand All @@ -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");
'?'
}
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand All @@ -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();
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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();
Expand All @@ -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;
Expand Down

0 comments on commit d41058e

Please sign in to comment.