24
24
#include " swift/Parse/Token.h"
25
25
#include " swift/Config.h"
26
26
#include " swift/Subsystems.h"
27
+ #include " clang/Basic/CharInfo.h"
27
28
#include " llvm/ADT/StringSwitch.h"
28
29
#include " llvm/Support/MemoryBuffer.h"
29
30
#include < vector>
@@ -274,17 +275,6 @@ static const char *const RegexStrURL =
274
275
" tn3270|urn|vemmi|wais|xcdoc|z39\\ .50r|z39\\ .50s)://"
275
276
" ([a-zA-Z0-9\\ -_.]+/)?[a-zA-Z0-9;/?:@\\ &=+$,\\ -_.!~*'()%#]+" ;
276
277
277
- #define MARKUP_SIMPLE_FIELD (Id, Keyword, XMLKind ) \
278
- #Keyword " |"
279
- static const char *const RegexStrDocCommentField =
280
- " ^[ ]*- ("
281
- #include " swift/Markup/SimpleFields.def"
282
- " returns):" ;
283
-
284
- static const char *const RegexStrParameter = " ^[ ]?- (parameter) [^:]*:" ;
285
-
286
- static const char *const RegexStrDocCommentParametersHeading = " ^[ ]?- (Parameters):" ;
287
-
288
278
static const char *const RegexStrMailURL =
289
279
" (mailto|im):[a-zA-Z0-9\\ -_]+@[a-zA-Z0-9\\ -_\\ .!%]+" ;
290
280
@@ -298,7 +288,6 @@ class ModelASTWalker : public ASTWalker {
298
288
std::vector<StructureElement> SubStructureStack;
299
289
SourceLoc LastLoc;
300
290
static const std::regex &getURLRegex (StringRef Protocol);
301
- static const std::regex &getDocCommentRegex (unsigned Index);
302
291
303
292
Optional<SyntaxNode> parseFieldNode (StringRef Text, StringRef OrigText,
304
293
SourceLoc OrigLoc);
@@ -389,24 +378,6 @@ const std::regex &ModelASTWalker::getURLRegex(StringRef Pro) {
389
378
return Regexes[2 ];
390
379
}
391
380
392
- const std::regex &ModelASTWalker::getDocCommentRegex (unsigned Index) {
393
- static const std::regex Regexes[3 ] = {
394
- std::regex {
395
- RegexStrParameter,
396
- std::regex::egrep | std::regex::icase | std::regex::optimize
397
- },
398
- std::regex {
399
- RegexStrDocCommentParametersHeading,
400
- std::regex::egrep | std::regex::icase | std::regex::optimize
401
- },
402
- std::regex {
403
- RegexStrDocCommentField,
404
- std::regex::egrep | std::regex::icase | std::regex::optimize
405
- }
406
- };
407
- return Regexes[Index];
408
- }
409
-
410
381
SyntaxStructureKind syntaxStructureKindFromNominalTypeDecl (NominalTypeDecl *N) {
411
382
if (isa<ClassDecl>(N))
412
383
return SyntaxStructureKind::Class;
@@ -1469,27 +1440,86 @@ bool ModelASTWalker::searchForURL(CharSourceRange Range) {
1469
1440
return true ;
1470
1441
}
1471
1442
1443
+ namespace {
1444
+ class DocFieldParser {
1445
+ const char *ptr;
1446
+ const char *end;
1447
+
1448
+ bool advanceIf (char c) {
1449
+ if (ptr == end || c != *ptr)
1450
+ return false ;
1451
+ ++ptr;
1452
+ return true ;
1453
+ }
1454
+ bool advanceIf (llvm::function_ref<bool (char )> predicate) {
1455
+ if (ptr == end || !predicate (*ptr))
1456
+ return false ;
1457
+ ++ptr;
1458
+ return true ;
1459
+ }
1460
+
1461
+ public:
1462
+ DocFieldParser (StringRef text) : ptr(text.begin()), end(text.end()) {
1463
+ assert (text.rtrim ().find (' \n ' ) == StringRef::npos &&
1464
+ " expected single line" );
1465
+ }
1466
+
1467
+ // Case-insensitively match one of the following patterns:
1468
+ // ^[ ]?- (parameter) [^:]*:
1469
+ // ^[ ]?- (Parameters):
1470
+ // ^[ ]*- (...MarkupSimpleFields.def...|returns):
1471
+ Optional<StringRef> parseFieldName () {
1472
+ unsigned numSpaces = 0 ;
1473
+ while (advanceIf (' ' ))
1474
+ ++numSpaces;
1475
+ if (!advanceIf (' -' ) || !advanceIf (' ' ))
1476
+ return None;
1477
+
1478
+ if (ptr == end || !clang::isIdentifierBody (*ptr))
1479
+ return None;
1480
+ const char *identStart = ptr++;
1481
+ while (advanceIf ([](char c) { return clang::isIdentifierBody (c); }))
1482
+ ;
1483
+ StringRef ident (identStart, ptr - identStart);
1484
+
1485
+ if (ident.equals_lower (" parameter" )) {
1486
+ if (numSpaces > 1 || !advanceIf (' ' ))
1487
+ return None;
1488
+ while (advanceIf ([](char c) { return c != ' :' ; }))
1489
+ ;
1490
+ if (!advanceIf (' :' ))
1491
+ return None;
1492
+ return ident;
1493
+
1494
+ } else if (advanceIf (' :' )) {
1495
+ if (ident.equals_lower (" parameters" ) && numSpaces > 1 )
1496
+ return None;
1497
+ auto lowerIdent = ident.lower ();
1498
+ bool isField = llvm::StringSwitch<bool >(lowerIdent)
1499
+ #define MARKUP_SIMPLE_FIELD (Id, Keyword, XMLKind ) .Case(#Keyword, true )
1500
+ #include " swift/Markup/SimpleFields.def"
1501
+ .Case (" parameters" , true )
1502
+ .Case (" returns" , true )
1503
+ .Default (false );
1504
+ if (isField)
1505
+ return ident;
1506
+ }
1507
+
1508
+ return None;
1509
+ }
1510
+ };
1511
+ } // end anonymous namespace
1512
+
1472
1513
Optional<SyntaxNode> ModelASTWalker::parseFieldNode (StringRef Text,
1473
1514
StringRef OrigText,
1474
1515
SourceLoc OrigLoc) {
1475
1516
Optional<SyntaxNode> Node;
1476
- #ifdef SWIFT_HAVE_WORKING_STD_REGEX
1477
- std::match_results<StringRef::iterator> Matches;
1478
- for (unsigned i = 0 ; i != 3 ; ++i) {
1479
- auto &Rx = getDocCommentRegex (i);
1480
- bool HadMatch = std::regex_search (Text.begin (), Text.end (), Matches, Rx);
1481
- if (HadMatch)
1482
- break ;
1517
+ DocFieldParser parser (Text);
1518
+ if (auto ident = parser.parseFieldName ()) {
1519
+ auto loc = OrigLoc.getAdvancedLoc (ident->data () - OrigText.data ());
1520
+ CharSourceRange range (loc, ident->size ());
1521
+ Node = Optional<SyntaxNode>({SyntaxNodeKind::DocCommentField, range});
1483
1522
}
1484
- if (Matches.empty ())
1485
- return None;
1486
-
1487
- auto &Match = Matches[1 ];
1488
- StringRef MatchStr (Match.first , Match.second - Match.first );
1489
- auto Loc = OrigLoc.getAdvancedLoc (MatchStr.data () - OrigText.data ());
1490
- CharSourceRange Range (Loc, MatchStr.size ());
1491
- Node = Optional<SyntaxNode>({ SyntaxNodeKind::DocCommentField, Range });
1492
- #endif
1493
1523
return Node;
1494
1524
}
1495
1525
0 commit comments