• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- UnwrappedLineParser.h - Format C++ code ----------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief This file contains the declaration of the UnwrappedLineParser,
12 /// which turns a stream of tokens into UnwrappedLines.
13 ///
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef LLVM_CLANG_FORMAT_UNWRAPPED_LINE_PARSER_H
17 #define LLVM_CLANG_FORMAT_UNWRAPPED_LINE_PARSER_H
18 
19 #include "clang/Basic/IdentifierTable.h"
20 #include "clang/Format/Format.h"
21 #include "FormatToken.h"
22 #include <list>
23 
24 namespace clang {
25 namespace format {
26 
27 /// \brief An unwrapped line is a sequence of \c Token, that we would like to
28 /// put on a single line if there was no column limit.
29 ///
30 /// This is used as a main interface between the \c UnwrappedLineParser and the
31 /// \c UnwrappedLineFormatter. The key property is that changing the formatting
32 /// within an unwrapped line does not affect any other unwrapped lines.
33 struct UnwrappedLine {
UnwrappedLineUnwrappedLine34   UnwrappedLine() : Level(0), InPPDirective(false), MustBeDeclaration(false) {}
35 
36   // FIXME: Don't use std::list here.
37   /// \brief The \c Tokens comprising this \c UnwrappedLine.
38   std::list<FormatToken *> Tokens;
39 
40   /// \brief The indent level of the \c UnwrappedLine.
41   unsigned Level;
42 
43   /// \brief Whether this \c UnwrappedLine is part of a preprocessor directive.
44   bool InPPDirective;
45 
46   bool MustBeDeclaration;
47 };
48 
49 class UnwrappedLineConsumer {
50 public:
~UnwrappedLineConsumer()51   virtual ~UnwrappedLineConsumer() {}
52   virtual void consumeUnwrappedLine(const UnwrappedLine &Line) = 0;
53 };
54 
55 class FormatTokenSource;
56 
57 class UnwrappedLineParser {
58 public:
59   UnwrappedLineParser(const FormatStyle &Style, ArrayRef<FormatToken *> Tokens,
60                       UnwrappedLineConsumer &Callback);
61 
62   /// Returns true in case of a structural error.
63   bool parse();
64 
65 private:
66   void parseFile();
67   void parseLevel(bool HasOpeningBrace);
68   void parseBlock(bool MustBeDeclaration, bool AddLevel = true);
69   void parsePPDirective();
70   void parsePPDefine();
71   void parsePPIf();
72   void parsePPIfdef();
73   void parsePPElIf();
74   void parsePPElse();
75   void parsePPEndIf();
76   void parsePPUnknown();
77   void parseStructuralElement();
78   bool tryToParseBracedList();
79   void parseBracedList();
80   void parseReturn();
81   void parseParens();
82   void parseIfThenElse();
83   void parseForOrWhileLoop();
84   void parseDoWhile();
85   void parseLabel();
86   void parseCaseLabel();
87   void parseSwitch();
88   void parseNamespace();
89   void parseAccessSpecifier();
90   void parseEnum();
91   void parseRecord();
92   void parseObjCProtocolList();
93   void parseObjCUntilAtEnd();
94   void parseObjCInterfaceOrImplementation();
95   void parseObjCProtocol();
96   void addUnwrappedLine();
97   bool eof() const;
98   void nextToken();
99   void readToken();
100   void flushComments(bool NewlineBeforeNext);
101   void pushToken(FormatToken *Tok);
102   void calculateBraceTypes();
103   void pushPPConditional();
104 
105   // FIXME: We are constantly running into bugs where Line.Level is incorrectly
106   // subtracted from beyond 0. Introduce a method to subtract from Line.Level
107   // and use that everywhere in the Parser.
108   OwningPtr<UnwrappedLine> Line;
109 
110   // Comments are sorted into unwrapped lines by whether they are in the same
111   // line as the previous token, or not. If not, they belong to the next token.
112   // Since the next token might already be in a new unwrapped line, we need to
113   // store the comments belonging to that token.
114   SmallVector<FormatToken *, 1> CommentsBeforeNextToken;
115   FormatToken *FormatTok;
116   bool MustBreakBeforeNextToken;
117 
118   // The parsed lines. Only added to through \c CurrentLines.
119   std::vector<UnwrappedLine> Lines;
120 
121   // Preprocessor directives are parsed out-of-order from other unwrapped lines.
122   // Thus, we need to keep a list of preprocessor directives to be reported
123   // after an unwarpped line that has been started was finished.
124   std::vector<UnwrappedLine> PreprocessorDirectives;
125 
126   // New unwrapped lines are added via CurrentLines.
127   // Usually points to \c &Lines. While parsing a preprocessor directive when
128   // there is an unfinished previous unwrapped line, will point to
129   // \c &PreprocessorDirectives.
130   std::vector<UnwrappedLine> *CurrentLines;
131 
132   // We store for each line whether it must be a declaration depending on
133   // whether we are in a compound statement or not.
134   std::vector<bool> DeclarationScopeStack;
135 
136   // Will be true if we encounter an error that leads to possibily incorrect
137   // indentation levels.
138   bool StructuralError;
139 
140   const FormatStyle &Style;
141   FormatTokenSource *Tokens;
142   UnwrappedLineConsumer &Callback;
143 
144   // FIXME: This is a temporary measure until we have reworked the ownership
145   // of the format tokens. The goal is to have the actual tokens created and
146   // owned outside of and handed into the UnwrappedLineParser.
147   ArrayRef<FormatToken *> AllTokens;
148 
149   // Represents preprocessor branch type, so we can find matching
150   // #if/#else/#endif directives.
151   enum PPBranchKind {
152     PP_Conditional, // Any #if, #ifdef, #ifndef, #elif, block outside #if 0
153     PP_Unreachable  // #if 0 or a conditional preprocessor block inside #if 0
154   };
155 
156   // Keeps a stack of currently active preprocessor branching directives.
157   SmallVector<PPBranchKind, 16> PPStack;
158 
159   friend class ScopedLineState;
160 };
161 
162 } // end namespace format
163 } // end namespace clang
164 
165 #endif // LLVM_CLANG_FORMAT_UNWRAPPED_LINE_PARSER_H
166