Skip to content

Commit dad9557

Browse files
committed
Add unit tests for Parser::look_ahead.
It's currently buggy, so some of the test results are surprising, as described in the `FIXME` comments. The bugs will be fixed in subsequent commits.
1 parent 0ca92de commit dad9557

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

compiler/rustc_parse/src/parser/tests.rs

+116
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,122 @@ fn ttdelim_span() {
13761376
});
13771377
}
13781378

1379+
// Uses a macro rather than a function so that failure messages mention the
1380+
// correct line in the test function.
1381+
macro_rules! look {
1382+
($p:ident, $dist:literal, $kind:expr) => {
1383+
$p.look_ahead($dist, |tok| assert_eq!($kind, tok.kind));
1384+
};
1385+
}
1386+
1387+
#[test]
1388+
fn look_ahead() {
1389+
create_default_session_globals_then(|| {
1390+
let sym_f = Symbol::intern("f");
1391+
let sym_x = Symbol::intern("x");
1392+
#[allow(non_snake_case)]
1393+
let sym_S = Symbol::intern("S");
1394+
let raw_no = IdentIsRaw::No;
1395+
1396+
let psess = psess();
1397+
let mut p = string_to_parser(&psess, "fn f(x: u32) { x } struct S;".to_string());
1398+
1399+
// Current position is the `fn`.
1400+
look!(p, 0, token::Ident(kw::Fn, raw_no));
1401+
look!(p, 1, token::Ident(sym_f, raw_no));
1402+
look!(p, 2, token::OpenDelim(Delimiter::Parenthesis));
1403+
look!(p, 3, token::Ident(sym_x, raw_no));
1404+
look!(p, 4, token::Colon);
1405+
look!(p, 5, token::Ident(sym::u32, raw_no));
1406+
look!(p, 6, token::CloseDelim(Delimiter::Parenthesis));
1407+
look!(p, 7, token::OpenDelim(Delimiter::Brace));
1408+
look!(p, 8, token::Ident(sym_x, raw_no));
1409+
look!(p, 9, token::CloseDelim(Delimiter::Brace));
1410+
look!(p, 10, token::Ident(kw::Struct, raw_no));
1411+
look!(p, 11, token::Ident(sym_S, raw_no));
1412+
look!(p, 12, token::Semi);
1413+
// Any lookahead past the end of the token stream returns `Eof`.
1414+
look!(p, 13, token::Eof);
1415+
look!(p, 14, token::Eof);
1416+
look!(p, 15, token::Eof);
1417+
look!(p, 100, token::Eof);
1418+
1419+
// Move forward to the first `x`.
1420+
for _ in 0..3 {
1421+
p.bump();
1422+
}
1423+
look!(p, 0, token::Ident(sym_x, raw_no));
1424+
look!(p, 1, token::Colon);
1425+
look!(p, 2, token::Ident(sym::u32, raw_no));
1426+
look!(p, 3, token::CloseDelim(Delimiter::Parenthesis));
1427+
// FIXME(nnethercote) If we lookahead any distance past a close delim
1428+
// we currently return that close delim.
1429+
look!(p, 4, token::CloseDelim(Delimiter::Parenthesis));
1430+
look!(p, 5, token::CloseDelim(Delimiter::Parenthesis));
1431+
look!(p, 6, token::CloseDelim(Delimiter::Parenthesis));
1432+
look!(p, 100, token::CloseDelim(Delimiter::Parenthesis));
1433+
1434+
// Move forward to the `;`.
1435+
for _ in 0..9 {
1436+
p.bump();
1437+
}
1438+
look!(p, 0, token::Semi);
1439+
// Any lookahead past the end of the token stream returns `Eof`.
1440+
look!(p, 1, token::Eof);
1441+
look!(p, 100, token::Eof);
1442+
1443+
// Move one past the `;`, i.e. past the end of the token stream.
1444+
p.bump();
1445+
look!(p, 0, token::Eof);
1446+
look!(p, 1, token::Eof);
1447+
look!(p, 100, token::Eof);
1448+
1449+
// Bumping after Eof is idempotent.
1450+
p.bump();
1451+
look!(p, 0, token::Eof);
1452+
look!(p, 1, token::Eof);
1453+
look!(p, 100, token::Eof);
1454+
});
1455+
}
1456+
1457+
/// FIXME(nnethercote) Currently there is some buggy behaviour when using
1458+
/// `look_ahead` not within the outermost token stream, as this test shows.
1459+
#[test]
1460+
fn look_ahead_non_outermost_stream() {
1461+
create_default_session_globals_then(|| {
1462+
let sym_f = Symbol::intern("f");
1463+
#[allow(non_snake_case)]
1464+
let sym_S = Symbol::intern("S");
1465+
let raw_no = IdentIsRaw::No;
1466+
1467+
let psess = psess();
1468+
let mut p = string_to_parser(&psess, "mod m { fn f(x: u32) { x } struct S; }".to_string());
1469+
1470+
// Move forward to the `fn`, which is not within the outermost token
1471+
// stream (because it's inside the `mod { ... }`).
1472+
for _ in 0..3 {
1473+
p.bump();
1474+
}
1475+
look!(p, 0, token::Ident(kw::Fn, raw_no));
1476+
look!(p, 1, token::Ident(sym_f, raw_no));
1477+
look!(p, 2, token::OpenDelim(Delimiter::Parenthesis));
1478+
// FIXME(nnethercote) The current code incorrectly skips the `x: u32)`
1479+
// to the next token tree.
1480+
look!(p, 3, token::OpenDelim(Delimiter::Brace));
1481+
// FIXME(nnethercote) The current code incorrectly skips the `x }`
1482+
// to the next token tree.
1483+
look!(p, 4, token::Ident(kw::Struct, raw_no));
1484+
look!(p, 5, token::Ident(sym_S, raw_no));
1485+
look!(p, 6, token::Semi);
1486+
// FIXME(nnethercote) If we lookahead any distance past a close delim
1487+
// we currently return that close delim.
1488+
look!(p, 7, token::CloseDelim(Delimiter::Brace));
1489+
look!(p, 8, token::CloseDelim(Delimiter::Brace));
1490+
look!(p, 9, token::CloseDelim(Delimiter::Brace));
1491+
look!(p, 100, token::CloseDelim(Delimiter::Brace));
1492+
});
1493+
}
1494+
13791495
// This tests that when parsing a string (rather than a file) we don't try
13801496
// and read in a file for a module declaration and just parse a stub.
13811497
// See `recurse_into_file_modules` in the parser.

0 commit comments

Comments
 (0)