Skip to content

Commit d0ddece

Browse files
authored
Merge pull request #25193 from jansvoboda11/gsoc-2019-parser
[Parser] Decouple the parser from AST creation (part 1)
2 parents 483fc05 + 5aee188 commit d0ddece

23 files changed

+892
-307
lines changed

include/swift/Parse/ASTGen.h

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//===--- ASTGen.h ---------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_PARSE_ASTGEN_H
14+
#define SWIFT_PARSE_ASTGEN_H
15+
16+
#include "swift/AST/ASTContext.h"
17+
#include "swift/AST/Expr.h"
18+
#include "swift/Syntax/SyntaxNodes.h"
19+
#include "llvm/ADT/DenseMap.h"
20+
21+
namespace swift {
22+
/// Generates AST nodes from Syntax nodes.
23+
class ASTGen {
24+
ASTContext &Context;
25+
// A stack of source locations of syntax constructs. Allows us to get the
26+
// SourceLoc necessary to create AST nodes for nodes in not-yet-complete
27+
// Syntax tree. The topmost item should always correspond to the token/node
28+
// that has been parsed/transformed most recently.
29+
// todo [gsoc]: remove when possible
30+
llvm::SmallVector<SourceLoc, 16> LocStack;
31+
32+
public:
33+
explicit ASTGen(ASTContext &Context) : Context(Context) {}
34+
35+
IntegerLiteralExpr *generate(syntax::IntegerLiteralExprSyntax &Expr);
36+
FloatLiteralExpr *generate(syntax::FloatLiteralExprSyntax &Expr);
37+
NilLiteralExpr *generate(syntax::NilLiteralExprSyntax &Expr);
38+
BooleanLiteralExpr *generate(syntax::BooleanLiteralExprSyntax &Expr);
39+
MagicIdentifierLiteralExpr *generate(syntax::PoundFileExprSyntax &Expr);
40+
MagicIdentifierLiteralExpr *generate(syntax::PoundLineExprSyntax &Expr);
41+
MagicIdentifierLiteralExpr *generate(syntax::PoundColumnExprSyntax &Expr);
42+
MagicIdentifierLiteralExpr *generate(syntax::PoundFunctionExprSyntax &Expr);
43+
MagicIdentifierLiteralExpr *generate(syntax::PoundDsohandleExprSyntax &Expr);
44+
Expr *generate(syntax::UnknownExprSyntax &Expr);
45+
46+
/// Stores source location necessary for AST creation.
47+
void pushLoc(SourceLoc Loc);
48+
49+
/// Copy a numeric literal value into AST-owned memory, stripping underscores
50+
/// so the semantic part of the value can be parsed by APInt/APFloat parsers.
51+
static StringRef copyAndStripUnderscores(StringRef Orig, ASTContext &Context);
52+
53+
private:
54+
StringRef copyAndStripUnderscores(StringRef Orig);
55+
56+
SourceLoc topLoc();
57+
58+
MagicIdentifierLiteralExpr *
59+
generateMagicIdentifierLiteralExpr(const syntax::TokenSyntax &PoundToken);
60+
61+
/// Map magic literal tokens such as #file to their MagicIdentifierLiteralExpr
62+
/// kind.
63+
static MagicIdentifierLiteralExpr::Kind
64+
getMagicIdentifierLiteralKind(tok Kind);
65+
};
66+
} // namespace swift
67+
68+
#endif // SWIFT_PARSE_ASTGEN_H
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//===--- HiddenLibSyntaxAction.h ------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_PARSE_HIDDENLIBSYNTAXACTION_H
14+
#define SWIFT_PARSE_HIDDENLIBSYNTAXACTION_H
15+
16+
#include "swift/Parse/SyntaxParseActions.h"
17+
#include "swift/SyntaxParse/SyntaxTreeCreator.h"
18+
#include "llvm/ADT/DenseMap.h"
19+
20+
namespace swift {
21+
/// Holds an explicitly provided action and uses it to handle all function
22+
/// calls. Also hides an implicit SyntaxTreeCreator and ensures libSyntax nodes
23+
/// are always created. Provides an interface to map results of the explicitly
24+
/// provided action to the hidden libSyntax action.
25+
// todo [gsoc]: remove when possible
26+
class HiddenLibSyntaxAction : public SyntaxParseActions {
27+
std::shared_ptr<SyntaxParseActions> ExplicitAction;
28+
std::shared_ptr<SyntaxTreeCreator> LibSyntaxAction;
29+
llvm::DenseMap<OpaqueSyntaxNode, OpaqueSyntaxNode> OpaqueNodeMap;
30+
31+
bool areBothLibSyntax() {
32+
return ExplicitAction->getOpaqueKind() == OpaqueSyntaxNodeKind::LibSyntax;
33+
}
34+
35+
public:
36+
HiddenLibSyntaxAction(
37+
const std::shared_ptr<SyntaxParseActions> &SPActions,
38+
const std::shared_ptr<SyntaxTreeCreator> &LibSyntaxAction)
39+
: ExplicitAction(SPActions != nullptr ? SPActions : LibSyntaxAction),
40+
LibSyntaxAction(LibSyntaxAction){};
41+
42+
OpaqueSyntaxNode recordToken(tok tokenKind,
43+
ArrayRef<ParsedTriviaPiece> leadingTrivia,
44+
ArrayRef<ParsedTriviaPiece> trailingTrivia,
45+
CharSourceRange range) override;
46+
47+
OpaqueSyntaxNode recordMissingToken(tok tokenKind, SourceLoc loc) override;
48+
49+
OpaqueSyntaxNode recordRawSyntax(syntax::SyntaxKind kind,
50+
ArrayRef<OpaqueSyntaxNode> elements,
51+
CharSourceRange range) override;
52+
53+
std::pair<size_t, OpaqueSyntaxNode>
54+
lookupNode(size_t lexerOffset, syntax::SyntaxKind kind) override;
55+
56+
OpaqueSyntaxNodeKind getOpaqueKind() override {
57+
return ExplicitAction->getOpaqueKind();
58+
}
59+
60+
/// Returns the libSyntax node corresponding to the provided node that has
61+
/// been created by the explicit action.
62+
OpaqueSyntaxNode getLibSyntaxNodeFor(OpaqueSyntaxNode explicitNode);
63+
64+
/// Returns the underlying libSyntax SyntaxTreeCreator.
65+
std::shared_ptr<SyntaxTreeCreator> getLibSyntaxAction() {
66+
return LibSyntaxAction;
67+
}
68+
};
69+
} // namespace swift
70+
71+
#endif // SWIFT_PARSE_HIDDENLIBSYNTAXACTION_H
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//===----------- LibSyntaxGenerator.h -------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_PARSE_LIBSYNTAXGENERATOR_H
14+
#define SWIFT_PARSE_LIBSYNTAXGENERATOR_H
15+
16+
#include "swift/Parse/HiddenLibSyntaxAction.h"
17+
#include "swift/Parse/ParsedRawSyntaxNode.h"
18+
#include "swift/Parse/ParsedRawSyntaxRecorder.h"
19+
#include "swift/Parse/SyntaxParsingCache.h"
20+
#include "swift/Syntax/RawSyntax.h"
21+
#include "swift/SyntaxParse/SyntaxTreeCreator.h"
22+
23+
namespace swift {
24+
/// Generates libSyntax nodes either by looking them up using
25+
/// HiddenLibSyntaxAction (based on provided OpaqueSyntaxNode) or by recording
26+
/// them with ParsedRawSyntaxRecorder.
27+
// todo [gsoc]: remove when possible
28+
class LibSyntaxGenerator {
29+
std::shared_ptr<HiddenLibSyntaxAction> Actions;
30+
ParsedRawSyntaxRecorder Recorder;
31+
32+
public:
33+
explicit LibSyntaxGenerator(std::shared_ptr<HiddenLibSyntaxAction> TwoActions)
34+
: Actions(std::move(TwoActions)),
35+
Recorder(Actions->getLibSyntaxAction()) {}
36+
37+
TokenSyntax createToken(ParsedRawSyntaxNode Node) {
38+
assert(Node.isDeferredToken());
39+
40+
auto Kind = Node.getTokenKind();
41+
auto Range = Node.getDeferredTokenRangeWithTrivia();
42+
auto LeadingTriviaPieces = Node.getDeferredLeadingTriviaPieces();
43+
auto TrailingTriviaPieces = Node.getDeferredTrailingTriviaPieces();
44+
45+
auto Recorded = Recorder.recordToken(Kind, Range, LeadingTriviaPieces,
46+
TrailingTriviaPieces);
47+
auto Raw = static_cast<RawSyntax *>(Recorded.getOpaqueNode());
48+
return make<TokenSyntax>(Raw);
49+
}
50+
51+
template <typename SyntaxNode>
52+
SyntaxNode createNode(ParsedRawSyntaxNode Node) {
53+
assert(Node.isDeferredLayout());
54+
auto Kind = Node.getKind();
55+
auto Children = Node.getDeferredChildren();
56+
57+
auto Recorded = Recorder.recordRawSyntax(Kind, Children);
58+
auto Raw = static_cast<RawSyntax *>(Recorded.getOpaqueNode());
59+
return make<SyntaxNode>(Raw);
60+
}
61+
62+
TokenSyntax getLibSyntaxTokenFor(OpaqueSyntaxNode Node) {
63+
return getLibSyntaxNodeFor<TokenSyntax>(Node);
64+
}
65+
66+
template <typename SyntaxNode>
67+
SyntaxNode getLibSyntaxNodeFor(OpaqueSyntaxNode Node) {
68+
auto Raw = static_cast<RawSyntax *>(Actions->getLibSyntaxNodeFor(Node));
69+
return make<SyntaxNode>(Raw);
70+
}
71+
};
72+
} // namespace swift
73+
74+
#endif // SWIFT_PARSE_LIBSYNTAXGENERATOR_H

include/swift/Parse/ParsedRawSyntaxNode.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,19 @@ class ParsedRawSyntaxNode {
156156

157157
// Deferred Token Data =====================================================//
158158

159+
CharSourceRange getDeferredTokenRangeWithTrivia() const {
160+
assert(DK == DataKind::DeferredToken);
161+
auto leadTriviaPieces = getDeferredLeadingTriviaPieces();
162+
auto trailTriviaPieces = getDeferredTrailingTriviaPieces();
163+
164+
auto leadTriviaLen = ParsedTriviaPiece::getTotalLength(leadTriviaPieces);
165+
auto trailTriviaLen = ParsedTriviaPiece::getTotalLength(trailTriviaPieces);
166+
167+
SourceLoc begin = DeferredToken.TokLoc.getAdvancedLoc(-leadTriviaLen);
168+
unsigned len = leadTriviaLen + DeferredToken.TokLength + trailTriviaLen;
169+
170+
return CharSourceRange{begin, len};
171+
}
159172
CharSourceRange getDeferredTokenRangeWithoutBackticks() const {
160173
assert(DK == DataKind::DeferredToken);
161174
return CharSourceRange{DeferredToken.TokLoc, DeferredToken.TokLength};

include/swift/Parse/ParsedSyntaxRecorder.h.gyb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,31 @@ public:
6666

6767
static Parsed${node.name} makeBlank${node.syntax_kind}(SourceLoc loc,
6868
SyntaxParsingContext &SPCtx);
69+
% elif node.is_unknown():
70+
private:
71+
static Parsed${node.name} record${node.syntax_kind}(
72+
ArrayRef<ParsedSyntax> elts,
73+
ParsedRawSyntaxRecorder &rec);
74+
75+
public:
76+
static Parsed${node.name} defer${node.syntax_kind}(
77+
ArrayRef<ParsedSyntax> elts,
78+
SyntaxParsingContext &SPCtx);
79+
80+
static Parsed${node.name} make${node.syntax_kind}(
81+
ArrayRef<ParsedSyntax> elts,
82+
SyntaxParsingContext &SPCtx);
6983
% end
7084
% end
7185

7286
#pragma mark - Convenience APIs
7387

88+
public:
89+
static ParsedTokenSyntax makeToken(const Token &Tok,
90+
const ParsedTrivia &LeadingTrivia,
91+
const ParsedTrivia &TrailingTrivia,
92+
SyntaxParsingContext &SPCtx);
93+
7494
/// Records an unlabelled TupleTypeElementSyntax with the provided type and
7595
/// optional trailing comma.
7696
static ParsedTupleTypeElementSyntax

include/swift/Parse/Parser.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@
2525
#include "swift/AST/Pattern.h"
2626
#include "swift/AST/Stmt.h"
2727
#include "swift/Basic/OptionSet.h"
28+
#include "swift/Parse/ASTGen.h"
2829
#include "swift/Parse/Lexer.h"
2930
#include "swift/Parse/LocalContext.h"
3031
#include "swift/Parse/PersistentParserState.h"
3132
#include "swift/Parse/Token.h"
33+
#include "swift/Parse/ParsedSyntaxNodes.h"
3234
#include "swift/Parse/ParserPosition.h"
3335
#include "swift/Parse/ParserResult.h"
3436
#include "swift/Parse/SyntaxParserResult.h"
@@ -376,6 +378,9 @@ class Parser {
376378
/// Current syntax parsing context where call backs should be directed to.
377379
SyntaxParsingContext *SyntaxContext;
378380

381+
/// The AST generator.
382+
ASTGen Generator;
383+
379384
public:
380385
Parser(unsigned BufferID, SourceFile &SF, DiagnosticEngine* LexerDiags,
381386
SILParserTUStateBase *SIL,
@@ -518,6 +523,12 @@ class Parser {
518523
assert(Tok.is(K) && "Consuming wrong token kind");
519524
return consumeToken();
520525
}
526+
/// Consume a token without providing it to the SyntaxParsingContext.
527+
ParsedTokenSyntax consumeTokenSyntax();
528+
ParsedTokenSyntax consumeTokenSyntax(tok K) {
529+
assert(Tok.is(K) && "Consuming wrong token kind");
530+
return consumeTokenSyntax();
531+
}
521532

522533
SourceLoc consumeIdentifier(Identifier *Result = nullptr,
523534
bool allowDollarIdentifier = false) {
@@ -1324,6 +1335,15 @@ class Parser {
13241335
ParserResult<Expr> parseExprSuper();
13251336
ParserResult<Expr> parseExprStringLiteral();
13261337

1338+
// todo [gsoc]: create new result type for ParsedSyntax
1339+
// todo [gsoc]: turn into proper non-templated methods later
1340+
template <typename SyntaxNode>
1341+
ParsedExprSyntax parseExprSyntax();
1342+
1343+
// todo [gsoc]: remove when possible
1344+
template <typename SyntaxNode>
1345+
ParserResult<Expr> parseExprAST();
1346+
13271347
StringRef copyAndStripUnderscores(StringRef text);
13281348

13291349
ParserStatus parseStringSegments(SmallVectorImpl<Lexer::StringSegment> &Segments,

include/swift/Parse/SyntaxParseActions.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ namespace syntax {
3333

3434
typedef void *OpaqueSyntaxNode;
3535

36+
// todo [gsoc]: remove when possible
37+
enum class OpaqueSyntaxNodeKind {
38+
SwiftSyntax,
39+
LibSyntax,
40+
};
41+
3642
class SyntaxParseActions {
3743
virtual void _anchor();
3844

@@ -60,6 +66,9 @@ class SyntaxParseActions {
6066
lookupNode(size_t lexerOffset, syntax::SyntaxKind kind) {
6167
return std::make_pair(0, nullptr);
6268
}
69+
70+
/// Returns what kind of OpaqueSyntaxNode is created by `recordXXX` methods.
71+
virtual OpaqueSyntaxNodeKind getOpaqueKind() = 0;
6372
};
6473

6574
} // end namespace swift

0 commit comments

Comments
 (0)