-
Notifications
You must be signed in to change notification settings - Fork 10.7k
Expand file tree
/
Copy pathParser.h
More file actions
1447 lines (1195 loc) · 53.8 KB
/
Parser.h
File metadata and controls
1447 lines (1195 loc) · 53.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//===--- Parser.h - Swift Language Parser -----------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the Parser interface.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_PARSER_H
#define SWIFT_PARSER_H
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTNode.h"
#include "swift/AST/DiagnosticsParse.h"
#include "swift/AST/Expr.h"
#include "swift/AST/LayoutConstraint.h"
#include "swift/AST/Module.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/Stmt.h"
#include "swift/Basic/OptionSet.h"
#include "swift/Parse/Lexer.h"
#include "swift/Parse/LocalContext.h"
#include "swift/Parse/PersistentParserState.h"
#include "swift/Parse/Token.h"
#include "swift/Parse/ParserPosition.h"
#include "swift/Parse/ParserResult.h"
#include "swift/Parse/SyntaxParserResult.h"
#include "swift/Syntax/SyntaxParsingContext.h"
#include "swift/Config.h"
#include "llvm/ADT/SetVector.h"
namespace llvm {
template <typename PT1, typename PT2, typename PT3> class PointerUnion3;
}
namespace swift {
class DefaultArgumentInitializer;
class DiagnosticEngine;
class Lexer;
class ScopeInfo;
struct TypeLoc;
class TupleType;
class SILParserTUStateBase;
class SourceManager;
class PersistentParserState;
class CodeCompletionCallbacks;
class DelayedParsingCallbacks;
struct EnumElementInfo;
namespace syntax {
class AbsolutePosition;
class RawSyntax;
enum class SyntaxKind;
class TypeSyntax;
}// end of syntax namespace
/// Different contexts in which BraceItemList are parsed.
enum class BraceItemListKind {
/// A statement list terminated by a closing brace. The default.
Brace,
/// A statement list in a case block. The list is terminated
/// by a closing brace or a 'case' or 'default' label.
Case,
/// The top-level of a file, when not in parse-as-library mode (i.e. the
/// repl or a script).
TopLevelCode,
/// The top-level of a file, when in parse-as-library mode.
TopLevelLibrary,
/// The body of the inactive clause of an #if/#else/#endif block
InactiveConditionalBlock,
/// The body of the active clause of an #if/#else/#endif block
ActiveConditionalBlock,
};
/// The receiver will be fed with consumed tokens while parsing. The main purpose
/// is to generate a corrected token stream for tooling support like syntax
/// coloring.
class ConsumeTokenReceiver {
public:
/// This is called when a token is consumed.
virtual void receive(Token Tok) {}
/// This is called to update the kind of a token whose start location is Loc.
virtual void registerTokenKindChange(SourceLoc Loc, tok NewKind) {};
/// This is called when a source file is fully parsed.
virtual void finalize() {};
virtual ~ConsumeTokenReceiver() = default;
};
/// The main class used for parsing a source file (.swift or .sil).
///
/// Rather than instantiating a Parser yourself, use one of the parsing APIs
/// provided in Subsystems.h.
class Parser {
Parser(const Parser&) = delete;
void operator=(const Parser&) = delete;
bool IsInputIncomplete = false;
SourceLoc DelayedDeclEnd;
std::vector<Token> SplitTokens;
public:
SourceManager &SourceMgr;
DiagnosticEngine &Diags;
SourceFile &SF;
Lexer *L;
SILParserTUStateBase *SIL; // Non-null when parsing a .sil file.
PersistentParserState *State;
std::unique_ptr<PersistentParserState> OwnedState;
DeclContext *CurDeclContext;
ASTContext &Context;
CodeCompletionCallbacks *CodeCompletion = nullptr;
std::vector<std::pair<SourceLoc, std::vector<ParamDecl*>>> AnonClosureVars;
bool IsParsingInterfaceTokens = false;
/// DisabledVars is a list of variables for whom local name lookup is
/// disabled. This is used when parsing a PatternBindingDecl to reject self
/// uses and to disable uses of the bound variables in a let/else block. The
/// diagnostic to emit is stored in DisabledVarReason.
ArrayRef<VarDecl *> DisabledVars;
Diag<> DisabledVarReason;
llvm::SmallPtrSet<Decl *, 2> AlreadyHandledDecls;
enum {
/// InVarOrLetPattern has this value when not parsing a pattern.
IVOLP_NotInVarOrLet,
/// InVarOrLetPattern has this value when we're in a matching pattern, but
/// not within a var/let pattern. In this phase, identifiers are references
/// to the enclosing scopes, not a variable binding.
IVOLP_InMatchingPattern,
/// InVarOrLetPattern has this value when parsing a pattern in which bound
/// variables are implicitly immutable, but allowed to be marked mutable by
/// using a 'var' pattern. This happens in for-each loop patterns.
IVOLP_ImplicitlyImmutable,
/// When InVarOrLetPattern has this value, bound variables are mutable, and
/// nested let/var patterns are not permitted. This happens when parsing a
/// 'var' decl or when parsing inside a 'var' pattern.
IVOLP_InVar,
/// When InVarOrLetPattern has this value, bound variables are immutable,and
/// nested let/var patterns are not permitted. This happens when parsing a
/// 'let' decl or when parsing inside a 'let' pattern.
IVOLP_InLet
} InVarOrLetPattern = IVOLP_NotInVarOrLet;
bool InPoundLineEnvironment = false;
bool InPoundIfEnvironment = false;
bool InSwiftKeyPath = false;
Expr* SwiftKeyPathRoot = nullptr;
SourceLoc SwiftKeyPathSlashLoc = SourceLoc();
LocalContext *CurLocalContext = nullptr;
DelayedParsingCallbacks *DelayedParseCB = nullptr;
bool isDelayedParsingEnabled() const { return DelayedParseCB != nullptr; }
void setDelayedParsingCallbacks(DelayedParsingCallbacks *DelayedParseCB) {
this->DelayedParseCB = DelayedParseCB;
}
void setCodeCompletionCallbacks(CodeCompletionCallbacks *Callbacks) {
CodeCompletion = Callbacks;
}
bool isCodeCompletionFirstPass() {
return L->isCodeCompletion() && !CodeCompletion;
}
bool allowTopLevelCode() const {
return SF.isScriptMode();
}
const std::vector<Token> &getSplitTokens() { return SplitTokens; }
void markSplitToken(tok Kind, StringRef Txt);
/// Returns true if the parser reached EOF with incomplete source input, due
/// for example, a missing right brace.
bool isInputIncomplete() const { return IsInputIncomplete; }
void checkForInputIncomplete() {
IsInputIncomplete = IsInputIncomplete || Tok.is(tok::eof);
}
/// \brief This is the current token being considered by the parser.
Token Tok;
/// \brief leading trivias for \c Tok.
/// Always empty if !SF.shouldKeepSyntaxInfo().
syntax::Trivia LeadingTrivia;
/// \brief trailing trivias for \c Tok.
/// Always empty if !SF.shouldKeepSyntaxInfo().
syntax::Trivia TrailingTrivia;
/// \brief The receiver to collect all consumed tokens.
ConsumeTokenReceiver *TokReceiver;
/// \brief The location of the previous token.
SourceLoc PreviousLoc;
/// Stop parsing immediately.
void cutOffParsing() {
// Cut off parsing by acting as if we reached the end-of-file.
Tok.setKind(tok::eof);
}
/// A RAII object for temporarily changing CurDeclContext.
class ContextChange {
protected:
Parser &P;
DeclContext *OldContext; // null signals that this has been popped
LocalContext *OldLocal;
ContextChange(const ContextChange &) = delete;
ContextChange &operator=(const ContextChange &) = delete;
public:
ContextChange(Parser &P, DeclContext *DC,
LocalContext *newLocal = nullptr)
: P(P), OldContext(P.CurDeclContext), OldLocal(P.CurLocalContext) {
assert(DC && "pushing null context?");
P.CurDeclContext = DC;
P.CurLocalContext = newLocal;
}
/// Prematurely pop the DeclContext installed by the constructor.
/// Makes the destructor a no-op.
void pop() {
assert(OldContext && "already popped context!");
popImpl();
OldContext = nullptr;
}
~ContextChange() {
if (OldContext) popImpl();
}
private:
void popImpl() {
P.CurDeclContext = OldContext;
P.CurLocalContext = OldLocal;
}
};
/// A RAII object for parsing a new local context.
class ParseFunctionBody : public LocalContext {
private:
ContextChange CC;
public:
ParseFunctionBody(Parser &P, DeclContext *DC) : CC(P, DC, this) {
assert(!isa<TopLevelCodeDecl>(DC) &&
"top-level code should be parsed using TopLevelCodeContext!");
}
void pop() {
CC.pop();
}
};
/// Describes the kind of a lexical structure marker, indicating
/// what kind of structural element we started parsing at a
/// particular location.
enum class StructureMarkerKind : unsigned char {
/// The start of a declaration.
Declaration,
/// The start of a statement.
Statement,
/// An open parentheses.
OpenParen,
/// An open brace.
OpenBrace,
/// An open square bracket.
OpenSquare,
/// An #if conditional clause.
IfConfig,
};
/// A structure marker, which identifies the location at which the
/// parser saw an entity it is parsing.
struct StructureMarker {
/// The location at which the marker occurred.
SourceLoc Loc;
/// The kind of marker.
StructureMarkerKind Kind;
/// The leading whitespace for this marker, if it has already been
/// computed.
Optional<StringRef> LeadingWhitespace;
};
/// An RAII object that notes when we have seen a structure marker.
class StructureMarkerRAII {
Parser &P;
/// Max nesting level
// TODO: customizable.
enum { MaxDepth = 256 };
void diagnoseOverflow();
public:
StructureMarkerRAII(Parser &parser, SourceLoc loc,
StructureMarkerKind kind)
: P(parser) {
P.StructureMarkers.push_back({loc, kind, None});
if (P.StructureMarkers.size() >= MaxDepth) {
diagnoseOverflow();
P.cutOffParsing();
}
}
StructureMarkerRAII(Parser &parser, const Token &tok);
~StructureMarkerRAII() {
P.StructureMarkers.pop_back();
}
};
friend class StructureMarkerRAII;
/// The stack of structure markers indicating the locations of
/// structural elements actively being parsed, including the start
/// of declarations, statements, and opening operators of various
/// kinds.
///
/// This vector is managed by \c StructureMarkerRAII objects.
llvm::SmallVector<StructureMarker, 16> StructureMarkers;
/// Current syntax parsing context where call backs should be directed to.
syntax::SyntaxParsingContext *SyntaxContext;
public:
Parser(unsigned BufferID, SourceFile &SF, SILParserTUStateBase *SIL,
PersistentParserState *PersistentState = nullptr);
Parser(std::unique_ptr<Lexer> Lex, SourceFile &SF,
SILParserTUStateBase *SIL = nullptr,
PersistentParserState *PersistentState = nullptr);
~Parser();
bool isInSILMode() const { return SIL != nullptr; }
/// Calling this function to finalize libSyntax tree creation without destroying
/// the parser instance.
void finalizeSyntaxTree() {
assert(Tok.is(tok::eof) && "not done parsing yet");
SyntaxContext->finalizeRoot();
}
//===--------------------------------------------------------------------===//
// Routines to save and restore parser state.
ParserPosition getParserPosition() {
return ParserPosition(L->getStateForBeginningOfToken(Tok, LeadingTrivia),
PreviousLoc);
}
ParserPosition getParserPosition(const PersistentParserState::ParserPos &Pos){
return ParserPosition(L->getStateForBeginningOfTokenLoc(Pos.Loc),
Pos.PrevLoc);
}
void restoreParserPosition(ParserPosition PP, bool enableDiagnostics = false) {
L->restoreState(PP.LS, enableDiagnostics);
// We might be at tok::eof now, so ensure that consumeToken() does not
// assert about lexing past eof.
Tok.setKind(tok::unknown);
consumeTokenWithoutFeedingReceiver();
PreviousLoc = PP.PreviousLoc;
}
void backtrackToPosition(ParserPosition PP) {
assert(PP.isValid());
L->backtrackToState(PP.LS);
// We might be at tok::eof now, so ensure that consumeToken() does not
// assert about lexing past eof.
Tok.setKind(tok::unknown);
consumeTokenWithoutFeedingReceiver();
PreviousLoc = PP.PreviousLoc;
}
/// RAII object that, when it is destructed, restores the parser and lexer to
/// their positions at the time the object was constructed. Will not jump
/// forward in the token stream.
class BacktrackingScope {
Parser &P;
ParserPosition PP;
DiagnosticTransaction DT;
/// This context immediately deconstructed with transparent accumulation
/// on cancelBacktrack().
llvm::Optional<syntax::SyntaxParsingContext> SynContext;
bool Backtrack = true;
public:
BacktrackingScope(Parser &P)
: P(P), PP(P.getParserPosition()), DT(P.Diags) {
SynContext.emplace(P.SyntaxContext);
SynContext->setDiscard();
}
~BacktrackingScope();
void cancelBacktrack() {
Backtrack = false;
SynContext->setTransparent();
SynContext.reset();
DT.commit();
}
};
/// RAII object that, when it is destructed, restores the parser and lexer to
/// their positions at the time the object was constructed.
struct ParserPositionRAII {
private:
Parser &P;
ParserPosition PP;
public:
ParserPositionRAII(Parser &P) : P(P), PP(P.getParserPosition()) {}
~ParserPositionRAII() {
P.restoreParserPosition(PP);
}
};
//===--------------------------------------------------------------------===//
// Utilities
/// \brief Return the next token that will be installed by \c consumeToken.
const Token &peekToken();
/// Consume a token that we created on the fly to correct the original token
/// stream from lexer.
void consumeExtraToken(Token K);
SourceLoc consumeTokenWithoutFeedingReceiver();
SourceLoc consumeToken();
SourceLoc consumeToken(tok K) {
assert(Tok.is(K) && "Consuming wrong token kind");
return consumeToken();
}
SourceLoc consumeIdentifier(Identifier *Result = nullptr) {
assert(Tok.isAny(tok::identifier, tok::kw_self, tok::kw_Self,
/* for Swift3 */tok::kw_throws, tok::kw_rethrows));
if (Result)
*Result = Context.getIdentifier(Tok.getText());
return consumeToken();
}
/// \brief Retrieve the location just past the end of the previous
/// source location.
SourceLoc getEndOfPreviousLoc();
/// \brief If the current token is the specified kind, consume it and
/// return true. Otherwise, return false without consuming it.
bool consumeIf(tok K) {
if (Tok.isNot(K)) return false;
consumeToken(K);
return true;
}
/// \brief If the current token is the specified kind, consume it and
/// return true. Otherwise, return false without consuming it.
bool consumeIf(tok K, SourceLoc &consumedLoc) {
if (Tok.isNot(K)) return false;
consumedLoc = consumeToken(K);
return true;
}
bool consumeIfNotAtStartOfLine(tok K) {
if (Tok.isAtStartOfLine()) return false;
return consumeIf(K);
}
/// \brief Read tokens until we get to one of the specified tokens, then
/// return without consuming it. Because we cannot guarantee that the token
/// will ever occur, this skips to some likely good stopping point.
void skipUntil(tok T1, tok T2 = tok::NUM_TOKENS);
void skipUntilAnyOperator();
/// \brief Skip until a token that starts with '>', and consume it if found.
/// Applies heuristics that are suitable when trying to find the end of a list
/// of generic parameters, generic arguments, or list of types in a protocol
/// composition.
SourceLoc skipUntilGreaterInTypeList(bool protocolComposition = false);
/// skipUntilDeclStmtRBrace - Skip to the next decl or '}'.
void skipUntilDeclRBrace();
void skipUntilDeclStmtRBrace(tok T1);
void skipUntilDeclStmtRBrace(tok T1, tok T2);
void skipUntilDeclRBrace(tok T1, tok T2);
/// Skip a single token, but match parentheses, braces, and square brackets.
///
/// Note: this does \em not match angle brackets ("<" and ">")! These are
/// matched in the source when they refer to a generic type,
/// but not when used as comparison operators.
void skipSingle();
/// \brief Skip until the next '#else', '#endif' or until eof.
void skipUntilConditionalBlockClose();
/// Parse an #endif.
bool parseEndIfDirective(SourceLoc &Loc);
public:
InFlightDiagnostic diagnose(SourceLoc Loc, Diagnostic Diag) {
if (Diags.isDiagnosticPointsToFirstBadToken(Diag.getID()) &&
Loc == Tok.getLoc() && Tok.isAtStartOfLine())
Loc = getEndOfPreviousLoc();
return Diags.diagnose(Loc, Diag);
}
InFlightDiagnostic diagnose(Token Tok, Diagnostic Diag) {
return diagnose(Tok.getLoc(), Diag);
}
template<typename ...DiagArgTypes, typename ...ArgTypes>
InFlightDiagnostic diagnose(SourceLoc Loc, Diag<DiagArgTypes...> DiagID,
ArgTypes &&...Args) {
return diagnose(Loc, Diagnostic(DiagID, std::forward<ArgTypes>(Args)...));
}
template<typename ...DiagArgTypes, typename ...ArgTypes>
InFlightDiagnostic diagnose(Token Tok, Diag<DiagArgTypes...> DiagID,
ArgTypes &&...Args) {
return diagnose(Tok.getLoc(),
Diagnostic(DiagID, std::forward<ArgTypes>(Args)...));
}
void diagnoseRedefinition(ValueDecl *Prev, ValueDecl *New);
/// Add a fix-it to remove the space in consecutive identifiers.
/// Add a camel-cased option if it is different than the first option.
void diagnoseConsecutiveIDs(StringRef First, SourceLoc FirstLoc,
StringRef DeclKindName);
bool startsWithSymbol(Token Tok, char symbol) {
return (Tok.isAnyOperator() || Tok.isPunctuation()) &&
Tok.getText()[0] == symbol;
}
/// \brief Check whether the current token starts with '<'.
bool startsWithLess(Token Tok) { return startsWithSymbol(Tok, '<'); }
/// \brief Check whether the current token starts with '>'.
bool startsWithGreater(Token Tok) { return startsWithSymbol(Tok, '>'); }
/// \brief Consume the starting '<' of the current token, which may either
/// be a complete '<' token or some kind of operator token starting with '<',
/// e.g., '<>'.
SourceLoc consumeStartingLess();
/// \brief Consume the starting '>' of the current token, which may either
/// be a complete '>' token or some kind of operator token starting with '>',
/// e.g., '>>'.
SourceLoc consumeStartingGreater();
/// \brief Consume the starting character of the current token, and split the
/// remainder of the token into a new token (or tokens).
SourceLoc
consumeStartingCharacterOfCurrentToken(tok Kind = tok::oper_binary_unspaced,
size_t Len = 1);
swift::ScopeInfo &getScopeInfo() { return State->getScopeInfo(); }
/// \brief Add the given Decl to the current scope.
void addToScope(ValueDecl *D) {
getScopeInfo().addToScope(D, *this);
}
ValueDecl *lookupInScope(DeclName Name) {
if (Context.LangOpts.EnableASTScopeLookup)
return nullptr;
return getScopeInfo().lookupValueName(Name);
}
//===--------------------------------------------------------------------===//
// Primitive Parsing
/// \brief Consume an identifier (but not an operator) if present and return
/// its name in \p Result. Otherwise, emit an error.
///
/// \returns false on success, true on error.
bool parseIdentifier(Identifier &Result, SourceLoc &Loc, const Diagnostic &D);
/// Consume an identifier with a specific expected name. This is useful for
/// contextually sensitive keywords that must always be present.
bool parseSpecificIdentifier(StringRef expected, SourceLoc &Loc,
const Diagnostic &D);
template<typename ...DiagArgTypes, typename ...ArgTypes>
bool parseIdentifier(Identifier &Result, Diag<DiagArgTypes...> ID,
ArgTypes... Args) {
SourceLoc L;
return parseIdentifier(Result, L, Diagnostic(ID, Args...));
}
template<typename ...DiagArgTypes, typename ...ArgTypes>
bool parseIdentifier(Identifier &Result, SourceLoc &L,
Diag<DiagArgTypes...> ID, ArgTypes... Args) {
return parseIdentifier(Result, L, Diagnostic(ID, Args...));
}
template<typename ...DiagArgTypes, typename ...ArgTypes>
bool parseSpecificIdentifier(StringRef expected,
Diag<DiagArgTypes...> ID, ArgTypes... Args) {
SourceLoc L;
return parseSpecificIdentifier(expected, L, Diagnostic(ID, Args...));
}
/// \brief Consume an identifier or operator if present and return its name
/// in \p Result. Otherwise, emit an error and return true.
bool parseAnyIdentifier(Identifier &Result, SourceLoc &Loc,
const Diagnostic &D);
template<typename ...DiagArgTypes, typename ...ArgTypes>
bool parseAnyIdentifier(Identifier &Result, Diag<DiagArgTypes...> ID,
ArgTypes... Args) {
SourceLoc L;
return parseAnyIdentifier(Result, L, Diagnostic(ID, Args...));
}
template<typename ...DiagArgTypes, typename ...ArgTypes>
bool parseAnyIdentifier(Identifier &Result, SourceLoc &L,
Diag<DiagArgTypes...> ID, ArgTypes... Args) {
return parseAnyIdentifier(Result, L, Diagnostic(ID, Args...));
}
/// \brief The parser expects that \p K is next token in the input. If so,
/// it is consumed and false is returned.
///
/// If the input is malformed, this emits the specified error diagnostic.
bool parseToken(tok K, SourceLoc &TokLoc, const Diagnostic &D);
template<typename ...DiagArgTypes, typename ...ArgTypes>
bool parseToken(tok K, Diag<DiagArgTypes...> ID, ArgTypes... Args) {
SourceLoc L;
return parseToken(K, L, Diagnostic(ID, Args...));
}
template<typename ...DiagArgTypes, typename ...ArgTypes>
bool parseToken(tok K, SourceLoc &L,
Diag<DiagArgTypes...> ID, ArgTypes... Args) {
return parseToken(K, L, Diagnostic(ID, Args...));
}
/// \brief Parse the specified expected token and return its location
/// on success. On failure, emit the specified error diagnostic, and
/// a note at the specified note location.
bool parseMatchingToken(tok K, SourceLoc &TokLoc, Diag<> ErrorDiag,
SourceLoc OtherLoc);
/// \brief Parse a comma separated list of some elements.
ParserStatus parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
bool AllowSepAfterLast, Diag<> ErrorDiag,
syntax::SyntaxKind Kind,
std::function<ParserStatus()> callback);
void consumeTopLevelDecl(ParserPosition BeginParserPosition,
TopLevelCodeDecl *TLCD);
ParserStatus parseBraceItems(SmallVectorImpl<ASTNode> &Decls,
BraceItemListKind Kind =
BraceItemListKind::Brace,
BraceItemListKind ConditionalBlockKind =
BraceItemListKind::Brace);
ParserResult<BraceStmt> parseBraceItemList(Diag<> ID);
void parseTopLevelCodeDeclDelayed();
//===--------------------------------------------------------------------===//
// Decl Parsing
/// Return true if parser is at the start of a decl or decl-import.
bool isStartOfDecl();
bool parseTopLevel();
/// Flags that control the parsing of declarations.
enum ParseDeclFlags {
PD_Default = 0,
PD_AllowTopLevel = 1 << 1,
PD_HasContainerType = 1 << 2,
PD_DisallowInit = 1 << 3,
PD_AllowDestructor = 1 << 4,
PD_AllowEnumElement = 1 << 5,
PD_InProtocol = 1 << 6,
PD_InClass = 1 << 7,
PD_InExtension = 1 << 8,
PD_InStruct = 1 << 9,
PD_InEnum = 1 << 10,
};
/// Options that control the parsing of declarations.
typedef OptionSet<ParseDeclFlags> ParseDeclOptions;
void delayParseFromBeginningToHere(ParserPosition BeginParserPosition,
ParseDeclOptions Flags);
void consumeDecl(ParserPosition BeginParserPosition, ParseDeclOptions Flags,
bool IsTopLevel);
// When compiling for the Debugger, some Decl's need to be moved from the
// current scope. In which case although the Decl will be returned in the
// ParserResult, it should not be inserted into the Decl list for the current
// context. markWasHandled asserts that the Decl is already where it
// belongs, and declWasHandledAlready is used to check this assertion.
// To keep the handled decl array small, we remove the Decl when it is
// checked, so you can only call declWasAlreadyHandled once for a given
// decl.
void markWasHandled(Decl *D) {
AlreadyHandledDecls.insert(D);
}
bool declWasHandledAlready(Decl *D) {
return AlreadyHandledDecls.erase(D);
}
ParserResult<Decl> parseDecl(ParseDeclOptions Flags,
llvm::function_ref<void(Decl*)> Handler);
void parseDeclDelayed();
ParserResult<TypeDecl> parseDeclTypeAlias(ParseDeclOptions Flags,
DeclAttributes &Attributes);
ParserResult<TypeDecl> parseDeclAssociatedType(ParseDeclOptions Flags,
DeclAttributes &Attributes);
/// Parse a #if ... #endif directive.
/// Delegate callback function to parse elements in the blocks.
ParserResult<IfConfigDecl> parseIfConfig(
llvm::function_ref<void(SmallVectorImpl<ASTNode> &, bool)> parseElements);
/// Parse a #line/#sourceLocation directive.
/// 'isLine = true' indicates parsing #line instead of #sourcelocation
ParserStatus parseLineDirective(bool isLine = false);
void setLocalDiscriminator(ValueDecl *D);
/// Parse the optional attributes before a declaration.
bool parseDeclAttributeList(DeclAttributes &Attributes,
bool &FoundCodeCompletionToken);
/// Parse the @_specialize attribute.
/// \p closingBrace is the expected closing brace, which can be either ) or ]
/// \p Attr is where to store the parsed attribute
bool parseSpecializeAttribute(swift::tok ClosingBrace, SourceLoc AtLoc,
SourceLoc Loc, SpecializeAttr *&Attr);
/// Parse the @_implements attribute.
/// \p Attr is where to store the parsed attribute
ParserResult<ImplementsAttr> parseImplementsAttribute(SourceLoc AtLoc,
SourceLoc Loc);
/// Parse a specific attribute.
bool parseDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc);
bool parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
DeclAttrKind DK);
/// Parse a version tuple of the form x[.y[.z]]. Returns true if there was
/// an error parsing.
bool parseVersionTuple(clang::VersionTuple &Version, SourceRange &Range,
const Diagnostic &D);
bool parseTypeAttributeList(VarDecl::Specifier &Specifier,
SourceLoc &SpecifierLoc,
TypeAttributes &Attributes) {
if (Tok.isAny(tok::at_sign, tok::kw_inout) ||
(Tok.is(tok::identifier) &&
(Tok.getRawText().equals("__shared") ||
Tok.getRawText().equals("__owned"))))
return parseTypeAttributeListPresent(Specifier, SpecifierLoc, Attributes);
return false;
}
bool parseTypeAttributeListPresent(VarDecl::Specifier &Specifier,
SourceLoc &SpecifierLoc,
TypeAttributes &Attributes);
bool parseTypeAttribute(TypeAttributes &Attributes,
bool justChecking = false);
ParserResult<ImportDecl> parseDeclImport(ParseDeclOptions Flags,
DeclAttributes &Attributes);
ParserStatus parseInheritance(SmallVectorImpl<TypeLoc> &Inherited,
bool allowClassRequirement,
bool allowAnyObject);
ParserStatus parseDeclItem(bool &PreviousHadSemi,
Parser::ParseDeclOptions Options,
llvm::function_ref<void(Decl*)> handler);
bool parseDeclList(SourceLoc LBLoc, SourceLoc &RBLoc,
Diag<> ErrorDiag, ParseDeclOptions Options,
llvm::function_ref<void(Decl*)> handler);
ParserResult<ExtensionDecl> parseDeclExtension(ParseDeclOptions Flags,
DeclAttributes &Attributes);
ParserResult<EnumDecl> parseDeclEnum(ParseDeclOptions Flags,
DeclAttributes &Attributes);
ParserResult<EnumCaseDecl>
parseDeclEnumCase(ParseDeclOptions Flags, DeclAttributes &Attributes,
SmallVectorImpl<Decl *> &decls);
ParserResult<StructDecl>
parseDeclStruct(ParseDeclOptions Flags, DeclAttributes &Attributes);
ParserResult<ClassDecl>
parseDeclClass(SourceLoc ClassLoc,
ParseDeclOptions Flags, DeclAttributes &Attributes);
ParserResult<PatternBindingDecl>
parseDeclVar(ParseDeclOptions Flags, DeclAttributes &Attributes,
SmallVectorImpl<Decl *> &Decls,
SourceLoc StaticLoc,
StaticSpellingKind StaticSpelling,
SourceLoc TryLoc);
void consumeGetSetBody(AbstractFunctionDecl *AFD, SourceLoc LBLoc);
struct ParsedAccessors {
SourceLoc LBLoc, RBLoc;
AccessorDecl *Get = nullptr;
AccessorDecl *Set = nullptr;
AccessorDecl *Addressor = nullptr;
AccessorDecl *MutableAddressor = nullptr;
AccessorDecl *WillSet = nullptr;
AccessorDecl *DidSet = nullptr;
void record(Parser &P, AbstractStorageDecl *storage, bool invalid,
ParseDeclOptions flags, SourceLoc staticLoc,
const DeclAttributes &attrs,
TypeLoc elementTy, ParameterList *indices,
SmallVectorImpl<Decl *> &decls);
};
void parseAccessorAttributes(DeclAttributes &Attributes);
bool parseGetSetImpl(ParseDeclOptions Flags,
GenericParamList *GenericParams,
ParameterList *Indices,
TypeLoc ElementTy,
ParsedAccessors &accessors,
AbstractStorageDecl *storage,
SourceLoc &LastValidLoc,
SourceLoc StaticLoc, SourceLoc VarLBLoc,
SmallVectorImpl<Decl *> &Decls);
bool parseGetSet(ParseDeclOptions Flags,
GenericParamList *GenericParams,
ParameterList *Indices,
TypeLoc ElementTy,
ParsedAccessors &accessors,
AbstractStorageDecl *storage,
SourceLoc StaticLoc, SmallVectorImpl<Decl *> &Decls);
void recordAccessors(AbstractStorageDecl *storage, ParseDeclOptions flags,
TypeLoc elementTy, const DeclAttributes &attrs,
SourceLoc staticLoc, ParsedAccessors &accessors);
void parseAccessorBodyDelayed(AbstractFunctionDecl *AFD);
VarDecl *parseDeclVarGetSet(Pattern *pattern, ParseDeclOptions Flags,
SourceLoc StaticLoc, SourceLoc VarLoc,
bool hasInitializer,
const DeclAttributes &Attributes,
SmallVectorImpl<Decl *> &Decls);
void consumeAbstractFunctionBody(AbstractFunctionDecl *AFD,
const DeclAttributes &Attrs);
ParserResult<FuncDecl> parseDeclFunc(SourceLoc StaticLoc,
StaticSpellingKind StaticSpelling,
ParseDeclOptions Flags,
DeclAttributes &Attributes);
bool parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD);
ParserResult<ProtocolDecl> parseDeclProtocol(ParseDeclOptions Flags,
DeclAttributes &Attributes);
ParserResult<SubscriptDecl>
parseDeclSubscript(ParseDeclOptions Flags, DeclAttributes &Attributes,
SmallVectorImpl<Decl *> &Decls);
ParserResult<ConstructorDecl>
parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes);
ParserResult<DestructorDecl>
parseDeclDeinit(ParseDeclOptions Flags, DeclAttributes &Attributes);
void addPatternVariablesToScope(ArrayRef<Pattern *> Patterns);
void addParametersToScope(ParameterList *PL);
ParserResult<OperatorDecl> parseDeclOperator(ParseDeclOptions Flags,
DeclAttributes &Attributes);
ParserResult<OperatorDecl> parseDeclOperatorImpl(SourceLoc OperatorLoc,
Identifier Name,
SourceLoc NameLoc,
DeclAttributes &Attrs);
ParserResult<PrecedenceGroupDecl>
parseDeclPrecedenceGroup(ParseDeclOptions flags, DeclAttributes &attributes);
//===--------------------------------------------------------------------===//
// Type Parsing
ParserResult<TypeRepr> parseType();
ParserResult<TypeRepr> parseType(Diag<> MessageID,
bool HandleCodeCompletion = true,
bool IsSILFuncDecl = false);
ParserResult<TypeRepr>
parseTypeSimpleOrComposition(Diag<> MessageID,
bool HandleCodeCompletion = true);
ParserResult<TypeRepr> parseTypeSimple(Diag<> MessageID,
bool HandleCodeCompletion = true);
/// \brief Parse layout constraint.
LayoutConstraint parseLayoutConstraint(Identifier LayoutConstraintID);
bool parseGenericArguments(SmallVectorImpl<TypeRepr*> &Args,
SourceLoc &LAngleLoc,
SourceLoc &RAngleLoc);
ParserResult<TypeRepr> parseTypeIdentifier();
ParserResult<TypeRepr> parseOldStyleProtocolComposition();
ParserResult<CompositionTypeRepr> parseAnyType();
ParserResult<TypeRepr> parseSILBoxType(GenericParamList *generics,
const TypeAttributes &attrs,
Optional<Scope> &GenericsScope);
ParserResult<TupleTypeRepr> parseTypeTupleBody();
ParserResult<TypeRepr> parseTypeArray(TypeRepr *Base);
/// Parse a collection type.
/// type-simple:
/// '[' type ']'
/// '[' type ':' type ']'
SyntaxParserResult<syntax::TypeSyntax, TypeRepr> parseTypeCollection();
SyntaxParserResult<syntax::TypeSyntax, OptionalTypeRepr>
parseTypeOptional(TypeRepr *Base);
SyntaxParserResult<syntax::TypeSyntax, ImplicitlyUnwrappedOptionalTypeRepr>
parseTypeImplicitlyUnwrappedOptional(TypeRepr *Base);
bool isOptionalToken(const Token &T) const;
SourceLoc consumeOptionalToken();
bool isImplicitlyUnwrappedOptionalToken(const Token &T) const;
SourceLoc consumeImplicitlyUnwrappedOptionalToken();
TypeRepr *applyAttributeToType(TypeRepr *Ty, const TypeAttributes &Attr,
VarDecl::Specifier Specifier,
SourceLoc SpecifierLoc);
//===--------------------------------------------------------------------===//
// Pattern Parsing
/// A structure for collecting information about the default
/// arguments of a context.
struct DefaultArgumentInfo {
llvm::SmallVector<DefaultArgumentInitializer *, 4> ParsedContexts;
unsigned NextIndex : 31;
/// Track whether or not one of the parameters in a signature's argument
/// list accepts a default argument.
unsigned HasDefaultArgument : 1;
/// Claim the next argument index. It's important to do this for
/// all the arguments, not just those that have default arguments.
unsigned claimNextIndex() { return NextIndex++; }
/// Set the parsed context for all the initializers to the given
/// function.
void setFunctionContext(AbstractFunctionDecl *AFD);
DefaultArgumentInfo(bool inTypeContext) {
NextIndex = inTypeContext ? 1 : 0;
HasDefaultArgument = false;
}
};
/// Describes a parsed parameter.
struct ParsedParameter {
/// Any declaration attributes attached to the parameter.
DeclAttributes Attrs;