forked from OSchip/llvm-project
[pseudo] Rename DirectiveMap -> DirectiveTree. NFC
Addressing comment from previous review https://reviews.llvm.org/D121165?id=413636#inline-1160757
This commit is contained in:
parent
eac3487510
commit
c03d6257c5
|
@ -1,4 +1,4 @@
|
|||
//===--- DirectiveMap.h - Find and strip preprocessor directives -*- C++-*-===//
|
||||
//===--- DirectiveTree.h - Find and strip preprocessor directives *- C++-*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
@ -25,8 +25,8 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CLANG_PSEUDO_DIRECTIVEMAP_H
|
||||
#define CLANG_PSEUDO_DIRECTIVEMAP_H
|
||||
#ifndef CLANG_PSEUDO_DIRECTIVETREE_H
|
||||
#define CLANG_PSEUDO_DIRECTIVETREE_H
|
||||
|
||||
#include "clang-pseudo/Token.h"
|
||||
#include "clang/Basic/TokenKinds.h"
|
||||
|
@ -55,7 +55,7 @@ namespace pseudo {
|
|||
///
|
||||
/// Unlike the clang preprocessor, we model the full tree explicitly.
|
||||
/// This class does not recognize macro usage, only directives.
|
||||
struct DirectiveMap {
|
||||
struct DirectiveTree {
|
||||
/// A range of code (and possibly comments) containing no directives.
|
||||
struct Code {
|
||||
Token::Range Tokens;
|
||||
|
@ -75,12 +75,12 @@ struct DirectiveMap {
|
|||
///
|
||||
/// The first branch will have an #if type directive.
|
||||
/// Subsequent branches will have #else type directives.
|
||||
std::vector<std::pair<Directive, DirectiveMap>> Branches;
|
||||
std::vector<std::pair<Directive, DirectiveTree>> Branches;
|
||||
/// The directive terminating the conditional, should be #endif.
|
||||
Directive End;
|
||||
/// The index of the conditional branch we chose as active.
|
||||
/// None indicates no branch was taken (e.g. #if 0 ... #endif).
|
||||
/// The initial map from of `parse()` has no branches marked as taken.
|
||||
/// The initial tree from `parse()` has no branches marked as taken.
|
||||
/// See `chooseConditionalBranches()`.
|
||||
llvm::Optional<unsigned> Taken;
|
||||
};
|
||||
|
@ -90,17 +90,17 @@ struct DirectiveMap {
|
|||
std::vector<Chunk> Chunks;
|
||||
|
||||
/// Extract preprocessor structure by examining the raw tokens.
|
||||
static DirectiveMap parse(const TokenStream &);
|
||||
static DirectiveTree parse(const TokenStream &);
|
||||
|
||||
// FIXME: allow deriving a preprocessed stream
|
||||
};
|
||||
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const DirectiveMap &);
|
||||
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const DirectiveMap::Chunk &);
|
||||
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const DirectiveMap::Code &);
|
||||
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const DirectiveTree &);
|
||||
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const DirectiveTree::Chunk &);
|
||||
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const DirectiveTree::Code &);
|
||||
llvm::raw_ostream &operator<<(llvm::raw_ostream &,
|
||||
const DirectiveMap::Directive &);
|
||||
const DirectiveTree::Directive &);
|
||||
llvm::raw_ostream &operator<<(llvm::raw_ostream &,
|
||||
const DirectiveMap::Conditional &);
|
||||
const DirectiveTree::Conditional &);
|
||||
|
||||
/// Selects a "taken" branch for each conditional directive in the file.
|
||||
///
|
||||
|
@ -118,11 +118,11 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &,
|
|||
/// #endif
|
||||
///
|
||||
/// The choices are stored in Conditional::Taken nodes.
|
||||
void chooseConditionalBranches(DirectiveMap &, const TokenStream &Code);
|
||||
void chooseConditionalBranches(DirectiveTree &, const TokenStream &Code);
|
||||
|
||||
// FIXME: This approximates std::variant<Code, Directive, Conditional>.
|
||||
// Switch once we can use C++17.
|
||||
class DirectiveMap::Chunk {
|
||||
class DirectiveTree::Chunk {
|
||||
public:
|
||||
enum Kind { K_Empty, K_Code, K_Directive, K_Conditional };
|
||||
Kind kind() const {
|
||||
|
@ -165,4 +165,4 @@ private:
|
|||
} // namespace pseudo
|
||||
} // namespace clang
|
||||
|
||||
#endif // CLANG_PSEUDO_DIRECTIVEMAP_H
|
||||
#endif // CLANG_PSEUDO_DIRECTIVETREE_H
|
|
@ -1,7 +1,7 @@
|
|||
set(LLVM_LINK_COMPONENTS Support)
|
||||
|
||||
add_clang_library(clangPseudo
|
||||
DirectiveMap.cpp
|
||||
DirectiveTree.cpp
|
||||
Forest.cpp
|
||||
Grammar.cpp
|
||||
GrammarBNF.cpp
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//===--- DirectiveMap.cpp - Find and strip preprocessor directives --------===//
|
||||
//===--- DirectiveTree.cpp - Find and strip preprocessor directives -------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
@ -6,7 +6,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang-pseudo/DirectiveMap.h"
|
||||
#include "clang-pseudo/DirectiveTree.h"
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/Basic/TokenKinds.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
|
@ -19,7 +19,7 @@ class DirectiveParser {
|
|||
public:
|
||||
explicit DirectiveParser(const TokenStream &Code)
|
||||
: Code(Code), Tok(&Code.front()) {}
|
||||
void parse(DirectiveMap *Result) { parse(Result, /*TopLevel=*/true); }
|
||||
void parse(DirectiveTree *Result) { parse(Result, /*TopLevel=*/true); }
|
||||
|
||||
private:
|
||||
// Roles that a directive might take within a conditional block.
|
||||
|
@ -42,10 +42,10 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
// Parses tokens starting at Tok into Map.
|
||||
// If we reach an End or Else directive that ends Map, returns it.
|
||||
// Parses tokens starting at Tok into Tree.
|
||||
// If we reach an End or Else directive that ends Tree, returns it.
|
||||
// If TopLevel is true, then we do not expect End and always return None.
|
||||
llvm::Optional<DirectiveMap::Directive> parse(DirectiveMap *Map,
|
||||
llvm::Optional<DirectiveTree::Directive> parse(DirectiveTree *Tree,
|
||||
bool TopLevel) {
|
||||
auto StartsDirective =
|
||||
[&, AllowDirectiveAt((const Token *)nullptr)]() mutable {
|
||||
|
@ -66,29 +66,29 @@ private:
|
|||
do
|
||||
++Tok;
|
||||
while (Tok->Kind != tok::eof && !StartsDirective());
|
||||
Map->Chunks.push_back(DirectiveMap::Code{
|
||||
Tree->Chunks.push_back(DirectiveTree::Code{
|
||||
Token::Range{Code.index(*Start), Code.index(*Tok)}});
|
||||
continue;
|
||||
}
|
||||
|
||||
// We have some kind of directive.
|
||||
DirectiveMap::Directive Directive;
|
||||
DirectiveTree::Directive Directive;
|
||||
parseDirective(&Directive);
|
||||
Cond Kind = classifyDirective(Directive.Kind);
|
||||
if (Kind == Cond::If) {
|
||||
// #if or similar, starting a nested conditional block.
|
||||
DirectiveMap::Conditional Conditional;
|
||||
DirectiveTree::Conditional Conditional;
|
||||
Conditional.Branches.emplace_back();
|
||||
Conditional.Branches.back().first = std::move(Directive);
|
||||
parseConditional(&Conditional);
|
||||
Map->Chunks.push_back(std::move(Conditional));
|
||||
Tree->Chunks.push_back(std::move(Conditional));
|
||||
} else if ((Kind == Cond::Else || Kind == Cond::End) && !TopLevel) {
|
||||
// #endif or similar, ending this PStructure scope.
|
||||
// (#endif is unexpected at the top level, treat as simple directive).
|
||||
return std::move(Directive);
|
||||
} else {
|
||||
// #define or similar, a simple directive at the current scope.
|
||||
Map->Chunks.push_back(std::move(Directive));
|
||||
Tree->Chunks.push_back(std::move(Directive));
|
||||
}
|
||||
}
|
||||
return None;
|
||||
|
@ -96,7 +96,7 @@ private:
|
|||
|
||||
// Parse the rest of a conditional section, after seeing the If directive.
|
||||
// Returns after consuming the End directive.
|
||||
void parseConditional(DirectiveMap::Conditional *C) {
|
||||
void parseConditional(DirectiveTree::Conditional *C) {
|
||||
assert(C->Branches.size() == 1 &&
|
||||
C->Branches.front().second.Chunks.empty() &&
|
||||
"Should be ready to parse first branch body");
|
||||
|
@ -119,7 +119,7 @@ private:
|
|||
}
|
||||
|
||||
// Parse a directive. Tok is the hash.
|
||||
void parseDirective(DirectiveMap::Directive *D) {
|
||||
void parseDirective(DirectiveTree::Directive *D) {
|
||||
assert(Tok->Kind == tok::hash);
|
||||
|
||||
// Directive spans from the hash until the end of line or file.
|
||||
|
@ -143,26 +143,26 @@ private:
|
|||
|
||||
} // namespace
|
||||
|
||||
DirectiveMap DirectiveMap::parse(const TokenStream &Code) {
|
||||
DirectiveMap Result;
|
||||
DirectiveTree DirectiveTree::parse(const TokenStream &Code) {
|
||||
DirectiveTree Result;
|
||||
DirectiveParser(Code).parse(&Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
static void dump(llvm::raw_ostream &OS, const DirectiveMap &, unsigned Indent);
|
||||
static void dump(llvm::raw_ostream &OS, const DirectiveTree &, unsigned Indent);
|
||||
static void dump(llvm::raw_ostream &OS,
|
||||
const DirectiveMap::Directive &Directive, unsigned Indent,
|
||||
const DirectiveTree::Directive &Directive, unsigned Indent,
|
||||
bool Taken = false) {
|
||||
OS.indent(Indent) << llvm::formatv(
|
||||
"#{0} ({1} tokens){2}\n", tok::getPPKeywordSpelling(Directive.Kind),
|
||||
Directive.Tokens.size(), Taken ? " TAKEN" : "");
|
||||
}
|
||||
static void dump(llvm::raw_ostream &OS, const DirectiveMap::Code &Code,
|
||||
static void dump(llvm::raw_ostream &OS, const DirectiveTree::Code &Code,
|
||||
unsigned Indent) {
|
||||
OS.indent(Indent) << llvm::formatv("code ({0} tokens)\n", Code.Tokens.size());
|
||||
}
|
||||
static void dump(llvm::raw_ostream &OS,
|
||||
const DirectiveMap::Conditional &Conditional,
|
||||
const DirectiveTree::Conditional &Conditional,
|
||||
unsigned Indent) {
|
||||
for (unsigned I = 0; I < Conditional.Branches.size(); ++I) {
|
||||
const auto &Branch = Conditional.Branches[I];
|
||||
|
@ -172,23 +172,23 @@ static void dump(llvm::raw_ostream &OS,
|
|||
dump(OS, Conditional.End, Indent);
|
||||
}
|
||||
|
||||
static void dump(llvm::raw_ostream &OS, const DirectiveMap::Chunk &Chunk,
|
||||
static void dump(llvm::raw_ostream &OS, const DirectiveTree::Chunk &Chunk,
|
||||
unsigned Indent) {
|
||||
switch (Chunk.kind()) {
|
||||
case DirectiveMap::Chunk::K_Empty:
|
||||
case DirectiveTree::Chunk::K_Empty:
|
||||
llvm_unreachable("invalid chunk");
|
||||
case DirectiveMap::Chunk::K_Code:
|
||||
return dump(OS, (const DirectiveMap::Code &)Chunk, Indent);
|
||||
case DirectiveMap::Chunk::K_Directive:
|
||||
return dump(OS, (const DirectiveMap::Directive &)Chunk, Indent);
|
||||
case DirectiveMap::Chunk::K_Conditional:
|
||||
return dump(OS, (const DirectiveMap::Conditional &)Chunk, Indent);
|
||||
case DirectiveTree::Chunk::K_Code:
|
||||
return dump(OS, (const DirectiveTree::Code &)Chunk, Indent);
|
||||
case DirectiveTree::Chunk::K_Directive:
|
||||
return dump(OS, (const DirectiveTree::Directive &)Chunk, Indent);
|
||||
case DirectiveTree::Chunk::K_Conditional:
|
||||
return dump(OS, (const DirectiveTree::Conditional &)Chunk, Indent);
|
||||
}
|
||||
}
|
||||
|
||||
static void dump(llvm::raw_ostream &OS, const DirectiveMap &Map,
|
||||
static void dump(llvm::raw_ostream &OS, const DirectiveTree &Tree,
|
||||
unsigned Indent) {
|
||||
for (const auto &Chunk : Map.Chunks)
|
||||
for (const auto &Chunk : Tree.Chunks)
|
||||
dump(OS, Chunk, Indent);
|
||||
}
|
||||
|
||||
|
@ -198,11 +198,11 @@ static void dump(llvm::raw_ostream &OS, const DirectiveMap &Map,
|
|||
dump(OS, T, 0); \
|
||||
return OS; \
|
||||
}
|
||||
OSTREAM_DUMP(DirectiveMap)
|
||||
OSTREAM_DUMP(DirectiveMap::Chunk)
|
||||
OSTREAM_DUMP(DirectiveMap::Directive)
|
||||
OSTREAM_DUMP(DirectiveMap::Conditional)
|
||||
OSTREAM_DUMP(DirectiveMap::Code)
|
||||
OSTREAM_DUMP(DirectiveTree)
|
||||
OSTREAM_DUMP(DirectiveTree::Chunk)
|
||||
OSTREAM_DUMP(DirectiveTree::Directive)
|
||||
OSTREAM_DUMP(DirectiveTree::Conditional)
|
||||
OSTREAM_DUMP(DirectiveTree::Code)
|
||||
#undef OSTREAM_DUMP
|
||||
|
||||
namespace {
|
||||
|
@ -223,7 +223,7 @@ class BranchChooser {
|
|||
public:
|
||||
BranchChooser(const TokenStream &Code) : Code(Code) {}
|
||||
|
||||
void choose(DirectiveMap &M) { walk(M); }
|
||||
void choose(DirectiveTree &M) { walk(M); }
|
||||
|
||||
private:
|
||||
// Describes code seen by making particular branch choices. Higher is better.
|
||||
|
@ -246,7 +246,7 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
Score walk(DirectiveMap::Code &C) {
|
||||
Score walk(DirectiveTree::Code &C) {
|
||||
Score S;
|
||||
for (const Token &T : Code.tokens(C.Tokens))
|
||||
if (T.Kind != tok::comment)
|
||||
|
@ -254,35 +254,35 @@ private:
|
|||
return S;
|
||||
}
|
||||
|
||||
Score walk(DirectiveMap::Directive &D) {
|
||||
Score walk(DirectiveTree::Directive &D) {
|
||||
Score S;
|
||||
S.Directives = 1;
|
||||
S.Errors = D.Kind == tok::pp_error;
|
||||
return S;
|
||||
}
|
||||
|
||||
Score walk(DirectiveMap::Chunk &C) {
|
||||
Score walk(DirectiveTree::Chunk &C) {
|
||||
switch (C.kind()) {
|
||||
case DirectiveMap::Chunk::K_Code:
|
||||
return walk((DirectiveMap::Code &)C);
|
||||
case DirectiveMap::Chunk::K_Directive:
|
||||
return walk((DirectiveMap::Directive &)C);
|
||||
case DirectiveMap::Chunk::K_Conditional:
|
||||
return walk((DirectiveMap::Conditional &)C);
|
||||
case DirectiveMap::Chunk::K_Empty:
|
||||
case DirectiveTree::Chunk::K_Code:
|
||||
return walk((DirectiveTree::Code &)C);
|
||||
case DirectiveTree::Chunk::K_Directive:
|
||||
return walk((DirectiveTree::Directive &)C);
|
||||
case DirectiveTree::Chunk::K_Conditional:
|
||||
return walk((DirectiveTree::Conditional &)C);
|
||||
case DirectiveTree::Chunk::K_Empty:
|
||||
break;
|
||||
}
|
||||
llvm_unreachable("bad chunk kind");
|
||||
}
|
||||
|
||||
Score walk(DirectiveMap &M) {
|
||||
Score walk(DirectiveTree &M) {
|
||||
Score S;
|
||||
for (DirectiveMap::Chunk &C : M.Chunks)
|
||||
for (DirectiveTree::Chunk &C : M.Chunks)
|
||||
S += walk(C);
|
||||
return S;
|
||||
}
|
||||
|
||||
Score walk(DirectiveMap::Conditional &C) {
|
||||
Score walk(DirectiveTree::Conditional &C) {
|
||||
Score Best;
|
||||
bool MayTakeTrivial = true;
|
||||
bool TookTrivial = false;
|
||||
|
@ -314,7 +314,7 @@ private:
|
|||
|
||||
// Return true if the directive starts an always-taken conditional branch,
|
||||
// false if the branch is never taken, and None otherwise.
|
||||
llvm::Optional<bool> isTakenWhenReached(const DirectiveMap::Directive &Dir) {
|
||||
llvm::Optional<bool> isTakenWhenReached(const DirectiveTree::Directive &Dir) {
|
||||
switch (Dir.Kind) {
|
||||
case clang::tok::pp_if:
|
||||
case clang::tok::pp_elif:
|
||||
|
@ -343,8 +343,8 @@ private:
|
|||
|
||||
} // namespace
|
||||
|
||||
void chooseConditionalBranches(DirectiveMap &Map, const TokenStream &Code) {
|
||||
BranchChooser{Code}.choose(Map);
|
||||
void chooseConditionalBranches(DirectiveTree &Tree, const TokenStream &Code) {
|
||||
BranchChooser{Code}.choose(Tree);
|
||||
}
|
||||
|
||||
} // namespace pseudo
|
|
@ -39,14 +39,14 @@ TOKEN-NEXT: hash 5:0 "#" flags=1
|
|||
TOKEN-NEXT: raw_identifier 5:0 "endif"
|
||||
TOKEN-NEXT: r_brace 6:0 "}" flags=1
|
||||
|
||||
RUN: clang-pseudo -source %s -print-directive-map | FileCheck %s -check-prefix=PPS --strict-whitespace
|
||||
PPS: code (5 tokens)
|
||||
PPS-NEXT: #ifndef (3 tokens) TAKEN
|
||||
PPS-NEXT: code (4 tokens)
|
||||
PPS-NEXT: #else (2 tokens)
|
||||
PPS-NEXT: code (3 tokens)
|
||||
PPS-NEXT: #endif (2 tokens)
|
||||
PPS-NEXT: code (2 tokens)
|
||||
RUN: clang-pseudo -source %s -print-directive-tree | FileCheck %s -check-prefix=PPT --strict-whitespace
|
||||
PPT: code (5 tokens)
|
||||
PPT-NEXT: #ifndef (3 tokens) TAKEN
|
||||
PPT-NEXT: code (4 tokens)
|
||||
PPT-NEXT: #else (2 tokens)
|
||||
PPT-NEXT: code (3 tokens)
|
||||
PPT-NEXT: #endif (2 tokens)
|
||||
PPT-NEXT: code (2 tokens)
|
||||
^ including this block comment
|
||||
|
||||
*******************************************************************************/
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang-pseudo/DirectiveMap.h"
|
||||
#include "clang-pseudo/DirectiveTree.h"
|
||||
#include "clang-pseudo/Grammar.h"
|
||||
#include "clang-pseudo/LRGraph.h"
|
||||
#include "clang-pseudo/LRTable.h"
|
||||
|
@ -33,7 +33,7 @@ static opt<std::string> Source("source", desc("Source file"));
|
|||
static opt<bool> PrintSource("print-source", desc("Print token stream"));
|
||||
static opt<bool> PrintTokens("print-tokens", desc("Print detailed token info"));
|
||||
static opt<bool>
|
||||
PrintDirectiveMap("print-directive-map",
|
||||
PrintDirectiveTree("print-directive-tree",
|
||||
desc("Print directive structure of source code"));
|
||||
|
||||
static std::string readOrDie(llvm::StringRef Path) {
|
||||
|
@ -74,10 +74,10 @@ int main(int argc, char *argv[]) {
|
|||
std::string Text = readOrDie(Source);
|
||||
clang::LangOptions LangOpts; // FIXME: use real options.
|
||||
auto Stream = clang::pseudo::lex(Text, LangOpts);
|
||||
auto Structure = clang::pseudo::DirectiveMap::parse(Stream);
|
||||
auto Structure = clang::pseudo::DirectiveTree::parse(Stream);
|
||||
clang::pseudo::chooseConditionalBranches(Structure, Stream);
|
||||
|
||||
if (PrintDirectiveMap)
|
||||
if (PrintDirectiveTree)
|
||||
llvm::outs() << Structure;
|
||||
if (PrintSource)
|
||||
Stream.print(llvm::outs());
|
||||
|
|
|
@ -4,7 +4,7 @@ set(LLVM_LINK_COMPONENTS
|
|||
|
||||
add_custom_target(ClangPseudoUnitTests)
|
||||
add_unittest(ClangPseudoUnitTests ClangPseudoTests
|
||||
DirectiveMapTest.cpp
|
||||
DirectiveTreeTest.cpp
|
||||
ForestTest.cpp
|
||||
GrammarTest.cpp
|
||||
LRTableTest.cpp
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//===--- DirectiveMapTest.cpp ---------------------------------------------===//
|
||||
//===--- DirectiveTreeTest.cpp --------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
@ -6,7 +6,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang-pseudo/DirectiveMap.h"
|
||||
#include "clang-pseudo/DirectiveTree.h"
|
||||
|
||||
#include "clang-pseudo/Token.h"
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
|
@ -25,7 +25,7 @@ using testing::ElementsAre;
|
|||
using testing::Matcher;
|
||||
using testing::Pair;
|
||||
using testing::StrEq;
|
||||
using Chunk = DirectiveMap::Chunk;
|
||||
using Chunk = DirectiveTree::Chunk;
|
||||
|
||||
MATCHER_P2(tokensAre, TS, Tokens, "tokens are " + std::string(Tokens)) {
|
||||
std::vector<llvm::StringRef> Texts;
|
||||
|
@ -37,7 +37,7 @@ MATCHER_P2(tokensAre, TS, Tokens, "tokens are " + std::string(Tokens)) {
|
|||
|
||||
MATCHER_P(chunkKind, K, "") { return arg.kind() == K; }
|
||||
|
||||
TEST(DirectiveMap, Parse) {
|
||||
TEST(DirectiveTree, Parse) {
|
||||
LangOptions Opts;
|
||||
std::string Code = R"cpp(
|
||||
#include <foo.h>
|
||||
|
@ -56,30 +56,30 @@ TEST(DirectiveMap, Parse) {
|
|||
)cpp";
|
||||
|
||||
TokenStream S = cook(lex(Code, Opts), Opts);
|
||||
DirectiveMap PP = DirectiveMap::parse(S);
|
||||
DirectiveTree PP = DirectiveTree::parse(S);
|
||||
|
||||
ASSERT_THAT(PP.Chunks, ElementsAre(chunkKind(Chunk::K_Directive),
|
||||
chunkKind(Chunk::K_Code),
|
||||
chunkKind(Chunk::K_Conditional),
|
||||
chunkKind(Chunk::K_Code)));
|
||||
|
||||
EXPECT_THAT((const DirectiveMap::Directive &)PP.Chunks[0],
|
||||
EXPECT_THAT((const DirectiveTree::Directive &)PP.Chunks[0],
|
||||
tokensAre(S, "# include < foo . h >"));
|
||||
EXPECT_THAT((const DirectiveMap::Code &)PP.Chunks[1],
|
||||
EXPECT_THAT((const DirectiveTree::Code &)PP.Chunks[1],
|
||||
tokensAre(S, "int main ( ) {"));
|
||||
EXPECT_THAT((const DirectiveMap::Code &)PP.Chunks[3], tokensAre(S, "}"));
|
||||
EXPECT_THAT((const DirectiveTree::Code &)PP.Chunks[3], tokensAre(S, "}"));
|
||||
|
||||
const DirectiveMap::Conditional &Ifdef(PP.Chunks[2]);
|
||||
const DirectiveTree::Conditional &Ifdef(PP.Chunks[2]);
|
||||
EXPECT_THAT(Ifdef.Branches,
|
||||
ElementsAre(Pair(tokensAre(S, "# ifdef HAS_FOO"), _),
|
||||
Pair(tokensAre(S, "# elif NEEDS_FOO"), _)));
|
||||
EXPECT_THAT(Ifdef.End, tokensAre(S, "# endif"));
|
||||
|
||||
const DirectiveMap &HasFoo(Ifdef.Branches[0].second);
|
||||
const DirectiveMap &NeedsFoo(Ifdef.Branches[1].second);
|
||||
const DirectiveTree &HasFoo(Ifdef.Branches[0].second);
|
||||
const DirectiveTree &NeedsFoo(Ifdef.Branches[1].second);
|
||||
|
||||
EXPECT_THAT(HasFoo.Chunks, ElementsAre(chunkKind(Chunk::K_Conditional)));
|
||||
const DirectiveMap::Conditional &If(HasFoo.Chunks[0]);
|
||||
const DirectiveTree::Conditional &If(HasFoo.Chunks[0]);
|
||||
EXPECT_THAT(If.Branches, ElementsAre(Pair(tokensAre(S, "# if HAS_BAR"), _),
|
||||
Pair(tokensAre(S, "# else"), _)));
|
||||
EXPECT_THAT(If.Branches[0].second.Chunks,
|
||||
|
@ -88,12 +88,12 @@ TEST(DirectiveMap, Parse) {
|
|||
ElementsAre(chunkKind(Chunk::K_Code)));
|
||||
|
||||
EXPECT_THAT(NeedsFoo.Chunks, ElementsAre(chunkKind(Chunk::K_Directive)));
|
||||
const DirectiveMap::Directive &Error(NeedsFoo.Chunks[0]);
|
||||
const DirectiveTree::Directive &Error(NeedsFoo.Chunks[0]);
|
||||
EXPECT_THAT(Error, tokensAre(S, "# error missing_foo"));
|
||||
EXPECT_EQ(Error.Kind, tok::pp_error);
|
||||
}
|
||||
|
||||
TEST(DirectiveMap, ParseUgly) {
|
||||
TEST(DirectiveTree, ParseUgly) {
|
||||
LangOptions Opts;
|
||||
std::string Code = R"cpp(
|
||||
/*A*/ # /*B*/ \
|
||||
|
@ -103,19 +103,19 @@ BAR /*D*/
|
|||
/*E*/
|
||||
)cpp";
|
||||
TokenStream S = cook(lex(Code, Opts), Opts);
|
||||
DirectiveMap PP = DirectiveMap::parse(S);
|
||||
DirectiveTree PP = DirectiveTree::parse(S);
|
||||
|
||||
ASSERT_THAT(PP.Chunks, ElementsAre(chunkKind(Chunk::K_Code),
|
||||
chunkKind(Chunk::K_Directive),
|
||||
chunkKind(Chunk::K_Code)));
|
||||
EXPECT_THAT((const DirectiveMap::Code &)PP.Chunks[0], tokensAre(S, "/*A*/"));
|
||||
const DirectiveMap::Directive &Define(PP.Chunks[1]);
|
||||
EXPECT_THAT((const DirectiveTree::Code &)PP.Chunks[0], tokensAre(S, "/*A*/"));
|
||||
const DirectiveTree::Directive &Define(PP.Chunks[1]);
|
||||
EXPECT_EQ(Define.Kind, tok::pp_define);
|
||||
EXPECT_THAT(Define, tokensAre(S, "# /*B*/ /*C*/ define BAR /*D*/"));
|
||||
EXPECT_THAT((const DirectiveMap::Code &)PP.Chunks[2], tokensAre(S, "/*E*/"));
|
||||
EXPECT_THAT((const DirectiveTree::Code &)PP.Chunks[2], tokensAre(S, "/*E*/"));
|
||||
}
|
||||
|
||||
TEST(DirectiveMap, ParseBroken) {
|
||||
TEST(DirectiveTree, ParseBroken) {
|
||||
LangOptions Opts;
|
||||
std::string Code = R"cpp(
|
||||
a
|
||||
|
@ -124,17 +124,17 @@ TEST(DirectiveMap, ParseBroken) {
|
|||
b
|
||||
)cpp";
|
||||
TokenStream S = cook(lex(Code, Opts), Opts);
|
||||
DirectiveMap PP = DirectiveMap::parse(S);
|
||||
DirectiveTree PP = DirectiveTree::parse(S);
|
||||
|
||||
ASSERT_THAT(PP.Chunks, ElementsAre(chunkKind(Chunk::K_Code),
|
||||
chunkKind(Chunk::K_Directive),
|
||||
chunkKind(Chunk::K_Conditional)));
|
||||
EXPECT_THAT((const DirectiveMap::Code &)PP.Chunks[0], tokensAre(S, "a"));
|
||||
const DirectiveMap::Directive &Endif(PP.Chunks[1]);
|
||||
EXPECT_THAT((const DirectiveTree::Code &)PP.Chunks[0], tokensAre(S, "a"));
|
||||
const DirectiveTree::Directive &Endif(PP.Chunks[1]);
|
||||
EXPECT_EQ(Endif.Kind, tok::pp_endif);
|
||||
EXPECT_THAT(Endif, tokensAre(S, "# endif // mismatched"));
|
||||
|
||||
const DirectiveMap::Conditional &X(PP.Chunks[2]);
|
||||
const DirectiveTree::Conditional &X(PP.Chunks[2]);
|
||||
EXPECT_EQ(1u, X.Branches.size());
|
||||
// The (only) branch of the broken conditional section runs until eof.
|
||||
EXPECT_EQ(tok::pp_if, X.Branches.front().first.Kind);
|
||||
|
@ -145,7 +145,7 @@ TEST(DirectiveMap, ParseBroken) {
|
|||
EXPECT_EQ(0u, X.End.Tokens.size());
|
||||
}
|
||||
|
||||
TEST(DirectiveMap, ChooseBranches) {
|
||||
TEST(DirectiveTree, ChooseBranches) {
|
||||
LangOptions Opts;
|
||||
const std::string Cases[] = {
|
||||
R"cpp(
|
||||
|
@ -280,12 +280,12 @@ TEST(DirectiveMap, ChooseBranches) {
|
|||
for (const auto &Code : Cases) {
|
||||
TokenStream S = cook(lex(Code, Opts), Opts);
|
||||
|
||||
std::function<void(const DirectiveMap &)> Verify =
|
||||
[&](const DirectiveMap &M) {
|
||||
std::function<void(const DirectiveTree &)> Verify =
|
||||
[&](const DirectiveTree &M) {
|
||||
for (const auto &C : M.Chunks) {
|
||||
if (C.kind() != DirectiveMap::Chunk::K_Conditional)
|
||||
if (C.kind() != DirectiveTree::Chunk::K_Conditional)
|
||||
continue;
|
||||
const DirectiveMap::Conditional &Cond(C);
|
||||
const DirectiveTree::Conditional &Cond(C);
|
||||
for (unsigned I = 0; I < Cond.Branches.size(); ++I) {
|
||||
auto Directive = S.tokens(Cond.Branches[I].first.Tokens);
|
||||
EXPECT_EQ(I == Cond.Taken, Directive.back().text() == "// TAKEN")
|
||||
|
@ -295,9 +295,9 @@ TEST(DirectiveMap, ChooseBranches) {
|
|||
}
|
||||
};
|
||||
|
||||
DirectiveMap Map = DirectiveMap::parse(S);
|
||||
chooseConditionalBranches(Map, S);
|
||||
Verify(Map);
|
||||
DirectiveTree Tree = DirectiveTree::parse(S);
|
||||
chooseConditionalBranches(Tree, S);
|
||||
Verify(Tree);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue