Skip to content

Commit ee7a062

Browse files
authored
libSyntax: create a basic infrastructure for generating libSyntax entities by using Parser.
1 parent b1bbe48 commit ee7a062

16 files changed

+473
-39
lines changed

Diff for: include/swift/AST/Module.h

+16
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#include "swift/Basic/SourceLoc.h"
2929
#include "swift/Basic/STLExtras.h"
3030
#include "swift/Parse/Token.h"
31+
#include "swift/Syntax/SyntaxNodes.h"
32+
#include "swift/Syntax/SyntaxParsingContext.h"
3133
#include "llvm/ADT/ArrayRef.h"
3234
#include "llvm/ADT/DenseSet.h"
3335
#include "llvm/ADT/SetVector.h"
@@ -1082,9 +1084,23 @@ class SourceFile final : public FileUnit {
10821084
return (bool)AllCorrectedTokens;
10831085
}
10841086

1087+
syntax::SourceFileSyntax getSyntaxRoot() const {
1088+
assert(SyntaxRoot && "no syntax root is set.");
1089+
return *SyntaxRoot;
1090+
}
1091+
10851092
private:
1093+
friend class syntax::SyntaxParsingContext;
1094+
friend class syntax::SyntaxParsingContextRoot;
1095+
10861096
/// If not None, the underlying vector should contain tokens of this source file.
10871097
Optional<std::vector<Token>> AllCorrectedTokens;
1098+
1099+
/// All of the raw token syntax nodes in the underlying source.
1100+
std::vector<syntax::RawTokenInfo> AllRawTokenSyntax;
1101+
1102+
/// The root of the syntax tree representing the source file.
1103+
Optional<syntax::SourceFileSyntax> SyntaxRoot;
10881104
};
10891105

10901106

Diff for: include/swift/Basic/OwnedString.h

-4
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,6 @@ class OwnedString {
4949
assert(Length >= 0 && "expected length to be non-negative");
5050

5151
if (Ownership == StringOwnership::Copied && Data) {
52-
assert(
53-
Length <= strlen(Data) &&
54-
"expected length to be a valid index, within the length of the string");
55-
5652
char *substring = static_cast<char *>(malloc(Length + 1));
5753
assert(substring && "expected successful malloc of copy");
5854

Diff for: include/swift/Parse/Lexer.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/Parse/Token.h"
2424
#include "swift/Syntax/References.h"
2525
#include "swift/Syntax/Trivia.h"
26+
#include "swift/Syntax/SyntaxParsingContext.h"
2627
#include "llvm/ADT/SmallVector.h"
2728
#include "llvm/Support/SaveAndRestore.h"
2829

@@ -245,7 +246,7 @@ class Lexer {
245246
}
246247

247248
/// Lex a full token including leading and trailing trivia.
248-
RC<syntax::RawTokenSyntax> fullLex();
249+
syntax::RawTokenInfo fullLex();
249250

250251
bool isKeepingComments() const {
251252
return RetainComments == CommentRetentionMode::ReturnAsTokens;

Diff for: include/swift/Parse/Parser.h

+10
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "swift/AST/Module.h"
2626
#include "swift/AST/Pattern.h"
2727
#include "swift/AST/Stmt.h"
28+
#include "swift/Syntax/RawTokenSyntax.h"
29+
#include "swift/Syntax/SyntaxParsingContext.h"
2830
#include "swift/Basic/OptionSet.h"
2931
#include "swift/Parse/Lexer.h"
3032
#include "swift/Parse/LocalContext.h"
@@ -325,6 +327,9 @@ class Parser {
325327
/// This vector is managed by \c StructureMarkerRAII objects.
326328
llvm::SmallVector<StructureMarker, 16> StructureMarkers;
327329

330+
/// Current syntax parsing context where call backs should be directed to.
331+
syntax::SyntaxParsingContext *SyntaxContext;
332+
328333
public:
329334
Parser(unsigned BufferID, SourceFile &SF, SILParserTUStateBase *SIL,
330335
PersistentParserState *PersistentState = nullptr);
@@ -1417,6 +1422,11 @@ tokenizeWithTrivia(const LangOptions &LangOpts,
14171422
unsigned Offset = 0,
14181423
unsigned EndOffset = 0);
14191424

1425+
1426+
void populateTokenSyntaxMap(const LangOptions &LangOpts,
1427+
const SourceManager &SM,
1428+
unsigned BufferID,
1429+
std::vector<syntax::RawTokenInfo> &Result);
14201430
} // end namespace swift
14211431

14221432
#endif

Diff for: include/swift/Syntax/Syntax.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ class Syntax {
127127
/// if it has one, otherwise 0.
128128
CursorIndex getIndexInParent() const;
129129

130+
/// Returns true if this syntax node represents a token.
131+
bool isToken() const;
132+
130133
/// Returns true if this syntax node represents a statement.
131134
bool isStmt() const;
132135

@@ -152,9 +155,6 @@ class Syntax {
152155
/// Returns true if the node is "present" in the source.
153156
bool isPresent() const;
154157

155-
156-
bool isToken() const;
157-
158158
/// Print the syntax node with full fidelity to the given output stream.
159159
void print(llvm::raw_ostream &OS) const;
160160

Diff for: include/swift/Syntax/SyntaxFactory.h.gyb

+4-2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ struct SyntaxFactory {
5454
static Optional<Syntax>
5555
createSyntax(SyntaxKind Kind, llvm::ArrayRef<Syntax> Elements);
5656

57+
static SyntaxKind getUnknownKind(SyntaxKind Kind);
58+
5759
% for node in SYNTAX_NODES:
5860
% if node.children:
5961
% child_params = []
@@ -105,7 +107,7 @@ struct SyntaxFactory {
105107
llvm::Optional<TokenSyntax> TrailingComma = llvm::None);
106108

107109
/// Creates a TypeIdentifierSyntax with the provided name and leading/trailing
108-
/// trivia.
110+
/// trivia.
109111
static TypeIdentifierSyntax makeTypeIdentifier(OwnedString TypeName,
110112
const Trivia &LeadingTrivia = {}, const Trivia &TrailingTrivia = {});
111113

@@ -117,7 +119,7 @@ struct SyntaxFactory {
117119
/// Creates a TypeIdentifierSyntax for the `Any` type.
118120
static TypeIdentifierSyntax makeAnyTypeIdentifier(
119121
const Trivia &LeadingTrivia = {}, const Trivia &TrailingTrivia = {});
120-
122+
121123
/// Creates a TypeIdentifierSyntax for the `Self` type.
122124
static TypeIdentifierSyntax makeSelfTypeIdentifier(
123125
const Trivia &LeadingTrivia = {}, const Trivia &TrailingTrivia = {});

Diff for: include/swift/Syntax/SyntaxParsingContext.h

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
//===----------- SyntaxParsingContext.h -==============----------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 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_SYNTAX_PARSING_CONTEXT_H
14+
#define SWIFT_SYNTAX_PARSING_CONTEXT_H
15+
16+
#include "swift/Syntax/RawTokenSyntax.h"
17+
#include "swift/Syntax/TokenSyntax.h"
18+
#include "swift/Syntax/References.h"
19+
#include "swift/Syntax/RawSyntax.h"
20+
#include "swift/Syntax/Syntax.h"
21+
#include "swift/Syntax/TokenKinds.h"
22+
#include "swift/Syntax/Trivia.h"
23+
24+
namespace swift {
25+
class SourceFile;
26+
27+
namespace syntax {
28+
29+
struct RawTokenInfo {
30+
SourceLoc Loc;
31+
RC<RawTokenSyntax> Token;
32+
};
33+
34+
enum class SyntaxParsingContextKind: uint8_t {
35+
Root,
36+
Child,
37+
};
38+
39+
/// The base class of different kinds of Syntax context that Parser should use to
40+
/// create syntax nodes.
41+
class SyntaxParsingContext {
42+
protected:
43+
SyntaxParsingContext(bool Enabled);
44+
SyntaxParsingContext(SyntaxParsingContext &Another);
45+
public:
46+
struct ContextInfo;
47+
ContextInfo &ContextData;
48+
49+
// Add a token syntax at the given source location to the context; this
50+
// token node can be used to build more complex syntax nodes in later call
51+
// back.
52+
virtual void addTokenSyntax(SourceLoc Loc) = 0;
53+
54+
// Get the context kind.
55+
virtual SyntaxParsingContextKind getKind() = 0;
56+
57+
// Create a syntax node of the given kind.
58+
virtual void makeNode(SyntaxKind Kind) = 0;
59+
virtual ~SyntaxParsingContext();
60+
61+
// Disable the building of syntax tree in the current context.
62+
void disable();
63+
};
64+
65+
// The start point of syntax tree parsing. This context is the root
66+
// of all other entity-specific contexts. This is the context Parser
67+
// has when the parser instance is firstly created.
68+
class SyntaxParsingContextRoot: public SyntaxParsingContext {
69+
public:
70+
struct GlobalInfo;
71+
72+
// Contains global information of the source file under parsing.
73+
GlobalInfo &GlobalData;
74+
SyntaxParsingContextRoot(SourceFile &SF, unsigned BufferID);
75+
~SyntaxParsingContextRoot();
76+
void addTokenSyntax(SourceLoc Loc) override {};
77+
void makeNode(SyntaxKind Kind) override {};
78+
SyntaxParsingContextKind getKind() override {
79+
return SyntaxParsingContextKind::Root;
80+
};
81+
};
82+
83+
// The base class for contexts that are created from a parent context.
84+
// The stack instance will set the context holder when the context
85+
// is firstly created and reset the context holder to the parent when
86+
// it's destructed.
87+
class SyntaxParsingContextChild: public SyntaxParsingContext {
88+
SyntaxParsingContext *Parent;
89+
SyntaxParsingContext *&ContextHolder;
90+
const SyntaxKind FinalKind;
91+
public:
92+
SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
93+
SyntaxKind FinalKind):
94+
SyntaxParsingContext(*ContextHolder), Parent(ContextHolder),
95+
ContextHolder(ContextHolder), FinalKind(FinalKind) {
96+
ContextHolder = this;
97+
}
98+
~SyntaxParsingContextChild();
99+
void makeNode(SyntaxKind Kind) override;
100+
void addTokenSyntax(SourceLoc Loc) override;
101+
SyntaxParsingContext* getParent() { return Parent; }
102+
SyntaxParsingContextRoot &getRoot();
103+
SyntaxParsingContextKind getKind() override {
104+
return SyntaxParsingContextKind::Child;
105+
};
106+
};
107+
}
108+
}
109+
#endif // SWIFT_SYNTAX_PARSING_CONTEXT_H
110+

Diff for: lib/Parse/Lexer.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include "swift/AST/Identifier.h"
2121
#include "swift/Basic/LangOptions.h"
2222
#include "swift/Basic/SourceManager.h"
23-
#include "swift/Syntax/TokenSyntax.h"
23+
#include "swift/Syntax/SyntaxParsingContext.h"
2424
#include "llvm/Support/Compiler.h"
2525
#include "llvm/Support/MathExtras.h"
2626
#include "llvm/Support/MemoryBuffer.h"
@@ -737,11 +737,12 @@ static bool rangeContainsPlaceholderEnd(const char *CurPtr,
737737
return false;
738738
}
739739

740-
RC<syntax::RawTokenSyntax> Lexer::fullLex() {
740+
syntax::RawTokenInfo Lexer::fullLex() {
741741
if (NextToken.isEscapedIdentifier()) {
742742
LeadingTrivia.push_back(syntax::TriviaPiece::backtick());
743743
TrailingTrivia.push_front(syntax::TriviaPiece::backtick());
744744
}
745+
auto Loc = NextToken.getLoc();
745746
auto Result = syntax::RawTokenSyntax::make(NextToken.getKind(),
746747
OwnedString(NextToken.getText()).copy(),
747748
syntax::SourcePresence::Present,
@@ -751,7 +752,7 @@ RC<syntax::RawTokenSyntax> Lexer::fullLex() {
751752
if (NextToken.isNot(tok::eof)) {
752753
lexImpl();
753754
}
754-
return Result;
755+
return {Loc, Result};
755756
}
756757

757758
/// lexOperatorIdentifier - Match identifiers formed out of punctuation.

Diff for: lib/Parse/ParseExpr.cpp

+19-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
#include "swift/AST/DiagnosticsParse.h"
1919
#include "swift/Basic/EditorPlaceholder.h"
2020
#include "swift/Parse/CodeCompletionCallbacks.h"
21+
#include "swift/Syntax/SyntaxFactory.h"
22+
#include "swift/Syntax/TokenSyntax.h"
23+
#include "swift/Syntax/SyntaxParsingContext.h"
2124
#include "llvm/ADT/SmallString.h"
2225
#include "llvm/ADT/StringSwitch.h"
2326
#include "llvm/ADT/Twine.h"
@@ -27,6 +30,7 @@
2730
#include "llvm/Support/raw_ostream.h"
2831

2932
using namespace swift;
33+
using namespace swift::syntax;
3034

3135
/// parseExpr
3236
///
@@ -35,6 +39,9 @@ using namespace swift;
3539
///
3640
/// \param isExprBasic Whether we're only parsing an expr-basic.
3741
ParserResult<Expr> Parser::parseExprImpl(Diag<> Message, bool isExprBasic) {
42+
// Start a context for creating expression syntax.
43+
SyntaxParsingContextChild ExprParsingContext(SyntaxContext, SyntaxKind::Expr);
44+
3845
// If we are parsing a refutable pattern, check to see if this is the start
3946
// of a let/var/is pattern. If so, parse it to an UnresolvedPatternExpr and
4047
// name binding will perform final validation.
@@ -465,6 +472,7 @@ ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) {
465472
Tok.setKind(tok::oper_prefix);
466473
LLVM_FALLTHROUGH;
467474
case tok::oper_prefix:
475+
SyntaxContext->addTokenSyntax(Tok.getLoc());
468476
Operator = parseExprOperator();
469477
break;
470478
case tok::oper_binary_spaced:
@@ -757,7 +765,6 @@ UnresolvedDeclRefExpr *Parser::parseExprOperator() {
757765
SourceLoc loc = Tok.getLoc();
758766
Identifier name = Context.getIdentifier(Tok.getText());
759767
consumeToken();
760-
761768
// Bypass local lookup.
762769
return new (Context) UnresolvedDeclRefExpr(name, refKind, DeclNameLoc(loc));
763770
}
@@ -1381,6 +1388,8 @@ ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
13811388
case tok::integer_literal: {
13821389
StringRef Text = copyAndStripUnderscores(Context, Tok.getText());
13831390
SourceLoc Loc = consumeToken(tok::integer_literal);
1391+
SyntaxContext->addTokenSyntax(Loc);
1392+
SyntaxContext->makeNode(SyntaxKind::IntegerLiteralExpr);
13841393
Result = makeParserResult(new (Context) IntegerLiteralExpr(Text, Loc,
13851394
/*Implicit=*/false));
13861395
break;
@@ -1786,11 +1795,20 @@ createStringLiteralExprFromSegment(ASTContext &Ctx,
17861795
/// expr-literal:
17871796
/// string_literal
17881797
ParserResult<Expr> Parser::parseExprStringLiteral() {
1798+
17891799
SmallVector<Lexer::StringSegment, 1> Segments;
17901800
L->getStringLiteralSegments(Tok, Segments);
17911801

17921802
Token EntireTok = Tok;
17931803

1804+
// Create a syntax node for string literal.
1805+
SyntaxContext->addTokenSyntax(Tok.getLoc());
1806+
SyntaxContext->makeNode(SyntaxKind::StringLiteralExpr);
1807+
SyntaxParsingContextChild LocalContext(SyntaxContext, SyntaxKind::Expr);
1808+
1809+
// FIXME: Avoid creating syntax nodes for string interpolation.
1810+
LocalContext.disable();
1811+
17941812
// The start location of the entire string literal.
17951813
SourceLoc Loc = Tok.getLoc();
17961814

0 commit comments

Comments
 (0)