Guard against trailing tokens in Rust exprs
Currently, the following parses: $for x in y.iter() #$%!INVALID~SYNTAX!^&* { } This is because the Rust parser only consumes enough to parse a single expression (in this case `y.iter()`), ignoring all the nonsense after it. With this patch, we check that the parser has consumed *all* tokens before yielding a result, ensuring that invalid syntax (like the snippet above) is not ignored.
This commit is contained in:
parent
a8928988d0
commit
c7ab906ad9
1 changed files with 17 additions and 6 deletions
|
@ -73,8 +73,19 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a Rust AST parser from the given token tree.
|
/// Construct a Rust AST parser from the given token tree.
|
||||||
fn new_rust_parser(&self, tts: Vec<TokenTree>) -> RustParser<'s> {
|
fn with_rust_parser<F, T>(&self, tts: Vec<TokenTree>, callback: F) -> T where
|
||||||
parse::tts_to_parser(self.render.cx.parse_sess, tts, self.render.cx.cfg.clone())
|
F: FnOnce(&mut RustParser<'s>) -> T
|
||||||
|
{
|
||||||
|
let mut parser = parse::tts_to_parser(self.render.cx.parse_sess, tts,
|
||||||
|
self.render.cx.cfg.clone());
|
||||||
|
let result = callback(&mut parser);
|
||||||
|
// Make sure all tokens were consumed
|
||||||
|
if parser.token != token::Eof {
|
||||||
|
let token = parser.this_token_to_string();
|
||||||
|
self.render.cx.span_err(parser.span,
|
||||||
|
&format!("unexpected token: `{}`", token));
|
||||||
|
}
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn markups(&mut self) {
|
fn markups(&mut self) {
|
||||||
|
@ -144,7 +155,7 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn literal(&mut self, tt: &TokenTree, minus: bool) {
|
fn literal(&mut self, tt: &TokenTree, minus: bool) {
|
||||||
let lit = self.new_rust_parser(vec![tt.clone()]).parse_lit();
|
let lit = self.with_rust_parser(vec![tt.clone()], RustParser::parse_lit);
|
||||||
match lit_to_string(self.render.cx, lit, minus) {
|
match lit_to_string(self.render.cx, lit, minus) {
|
||||||
Some(s) => self.render.string(&s, Escape::Escape),
|
Some(s) => self.render.string(&s, Escape::Escape),
|
||||||
None => {},
|
None => {},
|
||||||
|
@ -210,7 +221,7 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> {
|
||||||
},
|
},
|
||||||
_ => self.render.cx.span_fatal(sp, "invalid $for"),
|
_ => self.render.cx.span_fatal(sp, "invalid $for"),
|
||||||
}}
|
}}
|
||||||
let pattern = self.new_rust_parser(pattern).parse_pat();
|
let pattern = self.with_rust_parser(pattern, RustParser::parse_pat);
|
||||||
let mut iterable = vec![];
|
let mut iterable = vec![];
|
||||||
let body;
|
let body;
|
||||||
loop { match self.input {
|
loop { match self.input {
|
||||||
|
@ -225,7 +236,7 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> {
|
||||||
},
|
},
|
||||||
_ => self.render.cx.span_fatal(sp, "invalid $for"),
|
_ => self.render.cx.span_fatal(sp, "invalid $for"),
|
||||||
}}
|
}}
|
||||||
let iterable = self.new_rust_parser(iterable).parse_expr();
|
let iterable = self.with_rust_parser(iterable, RustParser::parse_expr);
|
||||||
self.render.emit_for(pattern, iterable, body);
|
self.render.emit_for(pattern, iterable, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +264,7 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> {
|
||||||
if tts.is_empty() {
|
if tts.is_empty() {
|
||||||
self.render.cx.span_fatal(sp, "expected expression for this splice");
|
self.render.cx.span_fatal(sp, "expected expression for this splice");
|
||||||
} else {
|
} else {
|
||||||
self.new_rust_parser(tts).parse_expr()
|
self.with_rust_parser(tts, RustParser::parse_expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue