Add unit tests for Parser::look_ahead. · rust-lang/rust@dad9557 (original) (raw)

`@@ -1376,6 +1376,122 @@ fn ttdelim_span() {

`

1376

1376

`});

`

1377

1377

`}

`

1378

1378

``

``

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,dist:literal, dist:literal,kind:expr) => {

`

``

1383

`+

p.lookahead(p.look_ahead(p.lookahead(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

+

1379

1495

`// This tests that when parsing a string (rather than a file) we don't try

`

1380

1496

`// and read in a file for a module declaration and just parse a stub.

`

1381

1497

`` // See recurse_into_file_modules in the parser.

``