clang: lib/AST/CommentParser.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

15#include "llvm/Support/ErrorHandling.h"

16

18

20 for (StringRef::const_iterator I = S.begin(), E = S.end(); I != E; ++I) {

22 return false;

23 }

24 return true;

25}

26

27namespace comments {

28

29

31 llvm::BumpPtrAllocator &Allocator;

33

34

35 bool NoMoreInterestingTokens;

36

37

39

40

41 struct Position {

42 const char *BufferStart;

43 const char *BufferEnd;

44 const char *BufferPtr;

46 unsigned CurToken;

47 };

48

49

50 Position Pos;

51

52 bool isEnd() const {

53 return Pos.CurToken >= Toks.size();

54 }

55

56

57 void setupBuffer() {

58 assert(!isEnd());

59 const Token &Tok = Toks[Pos.CurToken];

60

61 Pos.BufferStart = Tok.getText().begin();

62 Pos.BufferEnd = Tok.getText().end();

63 Pos.BufferPtr = Pos.BufferStart;

65 }

66

68 const unsigned CharNo = Pos.BufferPtr - Pos.BufferStart;

69 return Pos.BufferStartLoc.getLocWithOffset(CharNo);

70 }

71

72 char peek() const {

73 assert(!isEnd());

74 assert(Pos.BufferPtr != Pos.BufferEnd);

75 return *Pos.BufferPtr;

76 }

77

78 void consumeChar() {

79 assert(!isEnd());

80 assert(Pos.BufferPtr != Pos.BufferEnd);

81 Pos.BufferPtr++;

82 if (Pos.BufferPtr == Pos.BufferEnd) {

83 Pos.CurToken++;

84 if (isEnd() && !addToken())

85 return;

86

87 assert(!isEnd());

88 setupBuffer();

89 }

90 }

91

92

94 unsigned BracketCount = 0;

95 while (!isEnd()) {

96 const char C = peek();

97 WordText.push_back(C);

98 consumeChar();

99 switch (C) {

100 case '<': {

101 BracketCount++;

102 break;

103 }

104 case '>': {

105 BracketCount--;

106 if (!BracketCount)

107 return true;

108 break;

109 }

110 default:

111 break;

112 }

113 }

114 return false;

115 }

116

117

118

119

120 bool addToken() {

121 if (NoMoreInterestingTokens)

122 return false;

123

125

126 Token Newline = P.Tok;

127 P.consumeToken();

129 P.putBack(Newline);

130 NoMoreInterestingTokens = true;

131 return false;

132 }

133 }

135 NoMoreInterestingTokens = true;

136 return false;

137 }

138

139 Toks.push_back(P.Tok);

140 P.consumeToken();

141 if (Toks.size() == 1)

142 setupBuffer();

143 return true;

144 }

145

146 void consumeWhitespace() {

147 while (!isEnd()) {

149 consumeChar();

150 else

151 break;

152 }

153 }

154

157 const char *TokBegin,

158 unsigned TokLength,

159 StringRef Text) {

162 Result.setLength(TokLength);

163#ifndef NDEBUG

164 Result.TextPtr = "";

166#endif

168 }

169

170public:

172 Allocator(Allocator), P(P), NoMoreInterestingTokens(false) {

173 Pos.CurToken = 0;

174 addToken();

175 }

176

177

179 if (isEnd())

180 return false;

181

182

183

184 Position SavedPos = Pos;

185

186

187 consumeWhitespace();

189 const char *WordBegin = Pos.BufferPtr;

191

192 while (!isEnd()) {

193 const char C = peek();

194

195

197 if (C == '<') {

198 if (!lexTemplate(WordText))

199 return false;

200 } else {

201 WordText.push_back(C);

202 consumeChar();

203 }

204 } else {

205 consumeChar();

206 break;

207 }

208 }

209

210 const unsigned Length = WordText.size();

211 if (Length == 0) {

212 Pos = SavedPos;

213 return false;

214 }

215

216 char *TextPtr = Allocator.Allocate<char>(Length + 1);

217

218 memcpy(TextPtr, WordText.c_str(), Length + 1);

219 StringRef Text = StringRef(TextPtr, Length);

220

221 formTokenWithChars(Tok, Loc, WordBegin, Length, Text);

222 return true;

223 }

224

225

227 unsigned Offset = 1;

228

229

230

231

232 while (isWhitespace(*(Pos.BufferPtr - Offset)))

233 Offset++;

234

235

236

237 llvm::StringRef LineStart(Pos.BufferPtr - Offset - 3, 4);

238 return LineStart.starts_with("\\par") || LineStart.starts_with("@par");

239 }

240

241

243 if (isEnd())

244 return false;

245

246 Position SavedPos = Pos;

247

248 consumeWhitespace();

250 const char *WordBegin = Pos.BufferPtr;

252

254 return false;

255

256

257

258 while (!isEnd()) {

259 WordText.push_back(peek());

260 if (Pos.BufferPtr + 1 == Pos.BufferEnd) {

261 consumeChar();

262 break;

263 }

264 consumeChar();

265 }

266

267 unsigned Length = WordText.size();

268 if (Length == 0) {

269 Pos = SavedPos;

270 return false;

271 }

272

273 char *TextPtr = Allocator.Allocate<char>(Length + 1);

274

275 memcpy(TextPtr, WordText.c_str(), Length + 1);

276 StringRef Text = StringRef(TextPtr, Length);

277

278 formTokenWithChars(Tok, Loc, WordBegin, Length, Text);

279 return true;

280 }

281

282

284 if (isEnd())

285 return false;

286

287 Position SavedPos = Pos;

288

289 consumeWhitespace();

291 const char *WordBegin = Pos.BufferPtr;

293 while (!isEnd()) {

294 const char C = peek();

296 WordText.push_back(C);

297 consumeChar();

298 } else

299 break;

300 }

301 const unsigned Length = WordText.size();

302 if (Length == 0) {

303 Pos = SavedPos;

304 return false;

305 }

306

307 char *TextPtr = Allocator.Allocate<char>(Length + 1);

308

309 memcpy(TextPtr, WordText.c_str(), Length + 1);

310 StringRef Text = StringRef(TextPtr, Length);

311

312 formTokenWithChars(Tok, Loc, WordBegin, Length, Text);

313 return true;

314 }

315

317 if (isEnd())

318 return false;

319

320 Position SavedPos = Pos;

321

322 consumeWhitespace();

324 const char *WordBegin = Pos.BufferPtr;

326 bool Error = false;

327 if (!isEnd()) {

328 const char C = peek();

329 if (C == OpenDelim) {

330 WordText.push_back(C);

331 consumeChar();

332 } else

333 Error = true;

334 }

335 char C = '\0';

336 while (!Error && !isEnd()) {

337 C = peek();

338 WordText.push_back(C);

339 consumeChar();

340 if (C == CloseDelim)

341 break;

342 }

343 if (!Error && C != CloseDelim)

344 Error = true;

345

346 if (Error) {

347 Pos = SavedPos;

348 return false;

349 }

350

351 const unsigned Length = WordText.size();

352 char *TextPtr = Allocator.Allocate<char>(Length + 1);

353

354 memcpy(TextPtr, WordText.c_str(), Length + 1);

355 StringRef Text = StringRef(TextPtr, Length);

356

357 formTokenWithChars(Tok, Loc, WordBegin,

358 Pos.BufferPtr - WordBegin, Text);

359 return true;

360 }

361

362

364 if (isEnd())

365 return;

366

367 bool HavePartialTok = false;

368 Token PartialTok;

369 if (Pos.BufferPtr != Pos.BufferStart) {

370 formTokenWithChars(PartialTok, getSourceLocation(),

371 Pos.BufferPtr, Pos.BufferEnd - Pos.BufferPtr,

372 StringRef(Pos.BufferPtr,

373 Pos.BufferEnd - Pos.BufferPtr));

374 HavePartialTok = true;

375 Pos.CurToken++;

376 }

377

378 P.putBack(llvm::ArrayRef(Toks.begin() + Pos.CurToken, Toks.end()));

379 Pos.CurToken = Toks.size();

380

381 if (HavePartialTok)

382 P.putBack(PartialTok);

383 }

384};

385

386Parser::Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator,

389 L(L), S(S), Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags),

390 Traits(Traits) {

391 consumeToken();

392}

393

397

398

404

405 if (Retokenizer.lexWord(Arg))

410}

411

415 if (Retokenizer.lexWord(Arg))

420}

421

424 auto *Args = new (Allocator.Allocate<Comment::Argument>(NumArgs))

426 unsigned ParsedArgs = 0;

428 while (ParsedArgs < NumArgs && Retokenizer.lexWord(Arg)) {

431 ParsedArgs++;

432 }

433

435}

436

439 unsigned NumArgs) {

440 auto *Args = new (Allocator.Allocate<Comment::Argument>(NumArgs))

442 unsigned ParsedArgs = 0;

444

445 while (ParsedArgs < NumArgs && Retokenizer.lexType(Arg)) {

448 ParsedArgs++;

449 }

450

452}

453

456 unsigned NumArgs) {

457 assert(NumArgs > 0);

458 auto *Args = new (Allocator.Allocate<Comment::Argument>(NumArgs))

460 unsigned ParsedArgs = 0;

462

463 while (ParsedArgs < NumArgs && Retokenizer.lexParHeading(Arg)) {

466 ParsedArgs++;

467 }

468

470}

471

474

485 CommandMarker);

490 CommandMarker);

491 } else {

495 CommandMarker);

496 }

497 consumeToken();

498

499 if (isTokBlockCommand()) {

500

501

503 if (PC) {

505 return PC;

506 } else if (TPC) {

508 return TPC;

509 } else {

511 return BC;

512 }

513 }

514

515 if (PC || TPC || Info->NumArgs > 0) {

516

517

519

520 if (PC)

522 else if (TPC)

530 else

532

534 }

535

536

537

538 bool EmptyParagraph = false;

539 if (isTokBlockCommand())

540 EmptyParagraph = true;

542 Token PrevTok = Tok;

543 consumeToken();

544 EmptyParagraph = isTokBlockCommand();

545 putBack(PrevTok);

546 }

547

549 if (EmptyParagraph)

551 else {

553

554

555 Paragraph = cast(Block);

556 }

557

558 if (PC) {

560 return PC;

561 } else if (TPC) {

563 return TPC;

564 } else {

566 return BC;

567 }

568}

569

573

574 const Token CommandTok = Tok;

575 consumeToken();

576

580

584

585 if (Args.size() < Info->NumArgs) {

587 diag::warn_doc_inline_command_not_enough_arguments)

591 }

592

594

595 return IC;

596}

597

603 consumeToken();

604

606 while (true) {

609 Token Ident = Tok;

610 consumeToken();

614 continue;

615 }

616 Token Equals = Tok;

617 consumeToken();

620 diag::warn_doc_html_start_tag_expected_quoted_string)

626 consumeToken();

627 continue;

628 }

632 Equals.getLocation(),

636 consumeToken();

637 continue;

638 }

639

643 false);

644 consumeToken();

645 return HST;

646

650 true);

651 consumeToken();

652 return HST;

653

657 diag::warn_doc_html_start_tag_expected_ident_or_greater);

660 consumeToken();

664 continue;

665

668 false);

669 return HST;

670

671 default:

672

675 false);

676 bool StartLineInvalid;

679 &StartLineInvalid);

680 bool EndLineInvalid;

683 &EndLineInvalid);

684 if (StartLineInvalid || EndLineInvalid || StartLine == EndLine)

686 diag::warn_doc_html_start_tag_expected_ident_or_greater)

688 else {

690 diag::warn_doc_html_start_tag_expected_ident_or_greater);

691 Diag(HST->getLocation(), diag::note_doc_html_tag_started_here)

693 }

694 return HST;

695 }

696 }

697}

698

701 Token TokEndTag = Tok;

702 consumeToken();

706 consumeToken();

707 }

708

712}

713

716

717 while (true) {

722 break;

723

728 consumeToken();

729 continue;

730

735 if (Content.size() == 0)

737 break;

738 }

741 diag::warn_verbatim_block_end_without_start)

743 << Info->Name

745 consumeToken();

746 continue;

747 }

752 consumeToken();

753 continue;

754 }

757 continue;

758 }

759

761 consumeToken();

763 consumeToken();

764 break;

765 }

766

767

769 Token WhitespaceTok = Tok;

770 consumeToken();

772 consumeToken();

773 break;

774 }

775

776 putBack(WhitespaceTok);

777 }

778 if (Content.size() > 0)

779 Content.back()->addTrailingNewline();

780 continue;

781 }

782

783

786 continue;

787

790 continue;

791

796 consumeToken();

797 continue;

798

807 llvm_unreachable("should not see this token");

808 }

809 break;

810 }

811

813}

814

817

821 consumeToken();

822

823

824

826 consumeToken();

827

835 consumeToken();

837 consumeToken();

838 }

839 } else {

840

842 consumeToken();

843 }

844 Lines.push_back(Line);

845 }

846

851 consumeToken();

852 } else {

853

856 }

857

858 return VB;

859}

860

863

864 Token NameTok = Tok;

865 consumeToken();

866

868 StringRef Text;

869

870

874 } else {

877 }

878

881 TextBegin,

883 consumeToken();

884 return VL;

885}

886

896

899

902

913 llvm_unreachable("should not see this token");

914 }

915 llvm_unreachable("bogus token kind");

916}

917

919

921 consumeToken();

922

926

927

929 consumeToken();

930 }

932}

933

934}

935}

Defines the SourceManager interface.

__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)

Concrete class used by the front-end to report problems and issues.

Encodes a location in the source.

SourceLocation getLocWithOffset(IntTy Offset) const

Return a source location with the specified offset from this SourceLocation.

This class handles loading and caching of source files into memory.

unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const

A trivial tuple used to represent a source range.

Block content (contains inline content).

The JSON file list parser is used to communicate input to InstallAPI.

@ Result

The result type of a method or function.

LLVM_READONLY bool isWhitespace(unsigned char c)

Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t',...