1f4a2713aSLionel Sambuc //===--- UnwrappedLineParser.h - Format C++ code ----------------*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc ///
10f4a2713aSLionel Sambuc /// \file
11f4a2713aSLionel Sambuc /// \brief This file contains the declaration of the UnwrappedLineParser,
12f4a2713aSLionel Sambuc /// which turns a stream of tokens into UnwrappedLines.
13f4a2713aSLionel Sambuc ///
14f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
15f4a2713aSLionel Sambuc
16*0a6a1f1dSLionel Sambuc #ifndef LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEPARSER_H
17*0a6a1f1dSLionel Sambuc #define LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEPARSER_H
18f4a2713aSLionel Sambuc
19*0a6a1f1dSLionel Sambuc #include "FormatToken.h"
20f4a2713aSLionel Sambuc #include "clang/Basic/IdentifierTable.h"
21f4a2713aSLionel Sambuc #include "clang/Format/Format.h"
22f4a2713aSLionel Sambuc #include <list>
23*0a6a1f1dSLionel Sambuc #include <stack>
24f4a2713aSLionel Sambuc
25f4a2713aSLionel Sambuc namespace clang {
26f4a2713aSLionel Sambuc namespace format {
27f4a2713aSLionel Sambuc
28f4a2713aSLionel Sambuc struct UnwrappedLineNode;
29f4a2713aSLionel Sambuc
30f4a2713aSLionel Sambuc /// \brief An unwrapped line is a sequence of \c Token, that we would like to
31f4a2713aSLionel Sambuc /// put on a single line if there was no column limit.
32f4a2713aSLionel Sambuc ///
33f4a2713aSLionel Sambuc /// This is used as a main interface between the \c UnwrappedLineParser and the
34f4a2713aSLionel Sambuc /// \c UnwrappedLineFormatter. The key property is that changing the formatting
35f4a2713aSLionel Sambuc /// within an unwrapped line does not affect any other unwrapped lines.
36f4a2713aSLionel Sambuc struct UnwrappedLine {
37f4a2713aSLionel Sambuc UnwrappedLine();
38f4a2713aSLionel Sambuc
39f4a2713aSLionel Sambuc // FIXME: Don't use std::list here.
40f4a2713aSLionel Sambuc /// \brief The \c Tokens comprising this \c UnwrappedLine.
41f4a2713aSLionel Sambuc std::list<UnwrappedLineNode> Tokens;
42f4a2713aSLionel Sambuc
43f4a2713aSLionel Sambuc /// \brief The indent level of the \c UnwrappedLine.
44f4a2713aSLionel Sambuc unsigned Level;
45f4a2713aSLionel Sambuc
46f4a2713aSLionel Sambuc /// \brief Whether this \c UnwrappedLine is part of a preprocessor directive.
47f4a2713aSLionel Sambuc bool InPPDirective;
48f4a2713aSLionel Sambuc
49f4a2713aSLionel Sambuc bool MustBeDeclaration;
50f4a2713aSLionel Sambuc };
51f4a2713aSLionel Sambuc
52f4a2713aSLionel Sambuc class UnwrappedLineConsumer {
53f4a2713aSLionel Sambuc public:
~UnwrappedLineConsumer()54f4a2713aSLionel Sambuc virtual ~UnwrappedLineConsumer() {}
55f4a2713aSLionel Sambuc virtual void consumeUnwrappedLine(const UnwrappedLine &Line) = 0;
56f4a2713aSLionel Sambuc virtual void finishRun() = 0;
57f4a2713aSLionel Sambuc };
58f4a2713aSLionel Sambuc
59f4a2713aSLionel Sambuc class FormatTokenSource;
60f4a2713aSLionel Sambuc
61f4a2713aSLionel Sambuc class UnwrappedLineParser {
62f4a2713aSLionel Sambuc public:
63*0a6a1f1dSLionel Sambuc UnwrappedLineParser(const FormatStyle &Style,
64*0a6a1f1dSLionel Sambuc const AdditionalKeywords &Keywords,
65*0a6a1f1dSLionel Sambuc ArrayRef<FormatToken *> Tokens,
66f4a2713aSLionel Sambuc UnwrappedLineConsumer &Callback);
67f4a2713aSLionel Sambuc
68f4a2713aSLionel Sambuc /// Returns true in case of a structural error.
69f4a2713aSLionel Sambuc bool parse();
70f4a2713aSLionel Sambuc
71f4a2713aSLionel Sambuc private:
72f4a2713aSLionel Sambuc void reset();
73f4a2713aSLionel Sambuc void parseFile();
74f4a2713aSLionel Sambuc void parseLevel(bool HasOpeningBrace);
75f4a2713aSLionel Sambuc void parseBlock(bool MustBeDeclaration, bool AddLevel = true,
76f4a2713aSLionel Sambuc bool MunchSemi = true);
77f4a2713aSLionel Sambuc void parseChildBlock();
78f4a2713aSLionel Sambuc void parsePPDirective();
79f4a2713aSLionel Sambuc void parsePPDefine();
80f4a2713aSLionel Sambuc void parsePPIf(bool IfDef);
81f4a2713aSLionel Sambuc void parsePPElIf();
82f4a2713aSLionel Sambuc void parsePPElse();
83f4a2713aSLionel Sambuc void parsePPEndIf();
84f4a2713aSLionel Sambuc void parsePPUnknown();
85f4a2713aSLionel Sambuc void parseStructuralElement();
86f4a2713aSLionel Sambuc bool tryToParseBracedList();
87f4a2713aSLionel Sambuc bool parseBracedList(bool ContinueOnSemicolons = false);
88f4a2713aSLionel Sambuc void parseParens();
89*0a6a1f1dSLionel Sambuc void parseSquare();
90f4a2713aSLionel Sambuc void parseIfThenElse();
91*0a6a1f1dSLionel Sambuc void parseTryCatch();
92f4a2713aSLionel Sambuc void parseForOrWhileLoop();
93f4a2713aSLionel Sambuc void parseDoWhile();
94f4a2713aSLionel Sambuc void parseLabel();
95f4a2713aSLionel Sambuc void parseCaseLabel();
96f4a2713aSLionel Sambuc void parseSwitch();
97f4a2713aSLionel Sambuc void parseNamespace();
98f4a2713aSLionel Sambuc void parseAccessSpecifier();
99f4a2713aSLionel Sambuc void parseEnum();
100*0a6a1f1dSLionel Sambuc void parseJavaEnumBody();
101f4a2713aSLionel Sambuc void parseRecord();
102f4a2713aSLionel Sambuc void parseObjCProtocolList();
103f4a2713aSLionel Sambuc void parseObjCUntilAtEnd();
104f4a2713aSLionel Sambuc void parseObjCInterfaceOrImplementation();
105f4a2713aSLionel Sambuc void parseObjCProtocol();
106*0a6a1f1dSLionel Sambuc bool tryToParseLambda();
107f4a2713aSLionel Sambuc bool tryToParseLambdaIntroducer();
108*0a6a1f1dSLionel Sambuc void tryToParseJSFunction();
109f4a2713aSLionel Sambuc void addUnwrappedLine();
110f4a2713aSLionel Sambuc bool eof() const;
111f4a2713aSLionel Sambuc void nextToken();
112f4a2713aSLionel Sambuc void readToken();
113f4a2713aSLionel Sambuc void flushComments(bool NewlineBeforeNext);
114f4a2713aSLionel Sambuc void pushToken(FormatToken *Tok);
115f4a2713aSLionel Sambuc void calculateBraceTypes();
116*0a6a1f1dSLionel Sambuc
117*0a6a1f1dSLionel Sambuc // Marks a conditional compilation edge (for example, an '#if', '#ifdef',
118*0a6a1f1dSLionel Sambuc // '#else' or merge conflict marker). If 'Unreachable' is true, assumes
119*0a6a1f1dSLionel Sambuc // this branch either cannot be taken (for example '#if false'), or should
120*0a6a1f1dSLionel Sambuc // not be taken in this round.
121*0a6a1f1dSLionel Sambuc void conditionalCompilationCondition(bool Unreachable);
122*0a6a1f1dSLionel Sambuc void conditionalCompilationStart(bool Unreachable);
123*0a6a1f1dSLionel Sambuc void conditionalCompilationAlternative();
124*0a6a1f1dSLionel Sambuc void conditionalCompilationEnd();
125*0a6a1f1dSLionel Sambuc
126*0a6a1f1dSLionel Sambuc bool isOnNewLine(const FormatToken &FormatTok);
127f4a2713aSLionel Sambuc
128f4a2713aSLionel Sambuc // FIXME: We are constantly running into bugs where Line.Level is incorrectly
129f4a2713aSLionel Sambuc // subtracted from beyond 0. Introduce a method to subtract from Line.Level
130f4a2713aSLionel Sambuc // and use that everywhere in the Parser.
131*0a6a1f1dSLionel Sambuc std::unique_ptr<UnwrappedLine> Line;
132f4a2713aSLionel Sambuc
133f4a2713aSLionel Sambuc // Comments are sorted into unwrapped lines by whether they are in the same
134f4a2713aSLionel Sambuc // line as the previous token, or not. If not, they belong to the next token.
135f4a2713aSLionel Sambuc // Since the next token might already be in a new unwrapped line, we need to
136f4a2713aSLionel Sambuc // store the comments belonging to that token.
137f4a2713aSLionel Sambuc SmallVector<FormatToken *, 1> CommentsBeforeNextToken;
138f4a2713aSLionel Sambuc FormatToken *FormatTok;
139f4a2713aSLionel Sambuc bool MustBreakBeforeNextToken;
140f4a2713aSLionel Sambuc
141f4a2713aSLionel Sambuc // The parsed lines. Only added to through \c CurrentLines.
142f4a2713aSLionel Sambuc SmallVector<UnwrappedLine, 8> Lines;
143f4a2713aSLionel Sambuc
144f4a2713aSLionel Sambuc // Preprocessor directives are parsed out-of-order from other unwrapped lines.
145f4a2713aSLionel Sambuc // Thus, we need to keep a list of preprocessor directives to be reported
146f4a2713aSLionel Sambuc // after an unwarpped line that has been started was finished.
147f4a2713aSLionel Sambuc SmallVector<UnwrappedLine, 4> PreprocessorDirectives;
148f4a2713aSLionel Sambuc
149f4a2713aSLionel Sambuc // New unwrapped lines are added via CurrentLines.
150f4a2713aSLionel Sambuc // Usually points to \c &Lines. While parsing a preprocessor directive when
151f4a2713aSLionel Sambuc // there is an unfinished previous unwrapped line, will point to
152f4a2713aSLionel Sambuc // \c &PreprocessorDirectives.
153f4a2713aSLionel Sambuc SmallVectorImpl<UnwrappedLine> *CurrentLines;
154f4a2713aSLionel Sambuc
155f4a2713aSLionel Sambuc // We store for each line whether it must be a declaration depending on
156f4a2713aSLionel Sambuc // whether we are in a compound statement or not.
157f4a2713aSLionel Sambuc std::vector<bool> DeclarationScopeStack;
158f4a2713aSLionel Sambuc
159f4a2713aSLionel Sambuc // Will be true if we encounter an error that leads to possibily incorrect
160f4a2713aSLionel Sambuc // indentation levels.
161f4a2713aSLionel Sambuc bool StructuralError;
162f4a2713aSLionel Sambuc
163f4a2713aSLionel Sambuc const FormatStyle &Style;
164*0a6a1f1dSLionel Sambuc const AdditionalKeywords &Keywords;
165*0a6a1f1dSLionel Sambuc
166f4a2713aSLionel Sambuc FormatTokenSource *Tokens;
167f4a2713aSLionel Sambuc UnwrappedLineConsumer &Callback;
168f4a2713aSLionel Sambuc
169f4a2713aSLionel Sambuc // FIXME: This is a temporary measure until we have reworked the ownership
170f4a2713aSLionel Sambuc // of the format tokens. The goal is to have the actual tokens created and
171f4a2713aSLionel Sambuc // owned outside of and handed into the UnwrappedLineParser.
172f4a2713aSLionel Sambuc ArrayRef<FormatToken *> AllTokens;
173f4a2713aSLionel Sambuc
174f4a2713aSLionel Sambuc // Represents preprocessor branch type, so we can find matching
175f4a2713aSLionel Sambuc // #if/#else/#endif directives.
176f4a2713aSLionel Sambuc enum PPBranchKind {
177f4a2713aSLionel Sambuc PP_Conditional, // Any #if, #ifdef, #ifndef, #elif, block outside #if 0
178f4a2713aSLionel Sambuc PP_Unreachable // #if 0 or a conditional preprocessor block inside #if 0
179f4a2713aSLionel Sambuc };
180f4a2713aSLionel Sambuc
181f4a2713aSLionel Sambuc // Keeps a stack of currently active preprocessor branching directives.
182f4a2713aSLionel Sambuc SmallVector<PPBranchKind, 16> PPStack;
183f4a2713aSLionel Sambuc
184f4a2713aSLionel Sambuc // The \c UnwrappedLineParser re-parses the code for each combination
185f4a2713aSLionel Sambuc // of preprocessor branches that can be taken.
186f4a2713aSLionel Sambuc // To that end, we take the same branch (#if, #else, or one of the #elif
187f4a2713aSLionel Sambuc // branches) for each nesting level of preprocessor branches.
188f4a2713aSLionel Sambuc // \c PPBranchLevel stores the current nesting level of preprocessor
189f4a2713aSLionel Sambuc // branches during one pass over the code.
190f4a2713aSLionel Sambuc int PPBranchLevel;
191f4a2713aSLionel Sambuc
192f4a2713aSLionel Sambuc // Contains the current branch (#if, #else or one of the #elif branches)
193f4a2713aSLionel Sambuc // for each nesting level.
194f4a2713aSLionel Sambuc SmallVector<int, 8> PPLevelBranchIndex;
195f4a2713aSLionel Sambuc
196f4a2713aSLionel Sambuc // Contains the maximum number of branches at each nesting level.
197f4a2713aSLionel Sambuc SmallVector<int, 8> PPLevelBranchCount;
198f4a2713aSLionel Sambuc
199f4a2713aSLionel Sambuc // Contains the number of branches per nesting level we are currently
200f4a2713aSLionel Sambuc // in while parsing a preprocessor branch sequence.
201f4a2713aSLionel Sambuc // This is used to update PPLevelBranchCount at the end of a branch
202f4a2713aSLionel Sambuc // sequence.
203f4a2713aSLionel Sambuc std::stack<int> PPChainBranchIndex;
204f4a2713aSLionel Sambuc
205f4a2713aSLionel Sambuc friend class ScopedLineState;
206*0a6a1f1dSLionel Sambuc friend class CompoundStatementIndenter;
207f4a2713aSLionel Sambuc };
208f4a2713aSLionel Sambuc
209f4a2713aSLionel Sambuc struct UnwrappedLineNode {
UnwrappedLineNodeUnwrappedLineNode210*0a6a1f1dSLionel Sambuc UnwrappedLineNode() : Tok(nullptr) {}
UnwrappedLineNodeUnwrappedLineNode211f4a2713aSLionel Sambuc UnwrappedLineNode(FormatToken *Tok) : Tok(Tok) {}
212f4a2713aSLionel Sambuc
213f4a2713aSLionel Sambuc FormatToken *Tok;
214f4a2713aSLionel Sambuc SmallVector<UnwrappedLine, 0> Children;
215f4a2713aSLionel Sambuc };
216f4a2713aSLionel Sambuc
UnwrappedLine()217f4a2713aSLionel Sambuc inline UnwrappedLine::UnwrappedLine()
218f4a2713aSLionel Sambuc : Level(0), InPPDirective(false), MustBeDeclaration(false) {}
219f4a2713aSLionel Sambuc
220f4a2713aSLionel Sambuc } // end namespace format
221f4a2713aSLionel Sambuc } // end namespace clang
222f4a2713aSLionel Sambuc
223*0a6a1f1dSLionel Sambuc #endif
224