Skip to content
This repository was archived by the owner on Apr 4, 2023. It is now read-only.

Commit

Permalink
Store the parsed LHS template in an object
Browse files Browse the repository at this point in the history
  • Loading branch information
ROpdebee committed May 9, 2017
1 parent 298d175 commit f7b504f
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 27 deletions.
34 changes: 34 additions & 0 deletions Framework X/LHS/LHSTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,37 @@
//

#include "LHSTemplate.hpp"

void LHSTemplate::addTemplateSubtree(StmtOrDecl subtree) {
_templateSubtrees.push_back(subtree);
}

void LHSTemplate::addMetavariable(string metavarId, StmtOrDecl subtree) {
_metavariables.insert({ subtree, metavarId });
}

bool LHSTemplate::isMetavariable(StmtOrDecl subtree) {
return _metavariables.find(subtree) != _metavariables.end();
}

string LHSTemplate::getMetavariableId(StmtOrDecl subtree) {
auto it = _metavariables.find(subtree);
assert(it != _metavariables.end() && "Not a subtree");
return it->second;
}

void LHSTemplate::dump() {
llvm::outs() << "Template subtrees:\n~~~~~~~~~~~~~~~~~~\n\n";
for (auto &subtree : _templateSubtrees) {
subtree.dump();
llvm::outs() << "\n\n";
}

llvm::outs() << "Metavariables:\n~~~~~~~~~~~~~~\n\n";
for (auto &metaPair : _metavariables) {
llvm::outs() << metaPair.second << ": " << metaPair.first.getRawPtr() << "\n";
metaPair.first.dump();
llvm::outs() << "\n\n";
}

}
41 changes: 40 additions & 1 deletion Framework X/LHS/LHSTemplate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,49 @@
#ifndef LHSTemplate_hpp
#define LHSTemplate_hpp

namespace X {
#include "LHSTemplateParser.hpp"

using namespace std;
using namespace X;

namespace X {

class StmtOrDecl;
using SubtreeList = vector<StmtOrDecl>;

/// \class LHSTemplate
/// \brief Represents a LHS template
class LHSTemplate {
SubtreeList _templateSubtrees;

/// Keep a mapping from subtrees (Stmts and Decls) of the main template to the metavariables
/// We cannot create new AST nodes easily, nor can we alter them, so there is no way for us
/// to embed metavariable information directly in the template AST. Hence, when comparing
/// ASTs to the template, we must check if the AST node in the template is in this map to
/// determine whether or not it is a metavariable.
/// Note that a metavariable may be mapped to multiple times if it represents multiple subtrees,
/// this is fine because the template doesn't need to know what is underneath the metavariable.
map<StmtOrDecl, string> _metavariables;

public:
LHSTemplate() {}

/// Append an AST subtree to the end of the template subtree list
void addTemplateSubtree(StmtOrDecl subtree);

/// Add a metavariable to the template
/// \param metavarId The identifier of the metavariable
/// \param subtree The subtree this metavariable corresponds to in the main template
void addMetavariable(string metavarId, StmtOrDecl subtree);

/// Determine whether or not a subtree is represented by a metavariable in the template
bool isMetavariable(StmtOrDecl subtree);

/// Retrieve the identifier of the metavariable representing this subtree
string getMetavariableId(StmtOrDecl subtree);

/// Dump the template. Used for debugging purposes
void dump();
};

} // namespace X
Expand Down
8 changes: 3 additions & 5 deletions Framework X/LHS/LHSTemplateParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ bool LHSParserVisitor::parseSubtreeToTemplate(StmtOrDecl subtree) {
}

// We're now definitely part of the template, so we add ourselves to the node queue
// and to the subtree list of the LHS template
templateSubtrees.push(subtree);
_tmpl->addTemplateSubtree(subtree);

// If our end is also the end of the template, we'll end the template here
// Also end the traversal, so we'll continue on to parse metavariables
Expand Down Expand Up @@ -189,9 +191,6 @@ bool LHSParserVisitor::parseMetavariables(StmtOrDecl subtree) {
SourceLocation semiSLoc(Lexer::getSemiAfterLocation(literalSLoc, _sm, _lops));
TemplateLocation locEndWithSemi(semiSLoc.isValid() ? TemplateLocation::fromSourceLocation(semiSLoc, _sm) : locEndWithLiteral);

llvm::outs() << "[" << locStart.line << ", " << locStart.column << "] -> [" << locEndWithSemi.line << ", " << locEndWithSemi.column << "]\n";


// Check all remaining metavariables' ranges to check if this subtree is of importance
// Keep in mind that metavariable ranges can never overlap, simplifying our task
bool searchSubtrees(false);
Expand All @@ -202,7 +201,6 @@ bool LHSParserVisitor::parseMetavariables(StmtOrDecl subtree) {
// Make sure we don't start on metavariables we can't finish, see the template matching above
if (metavar.range.begin == locStart && locEnd <= metavar.range.end) {
parsingMetavariable = &metavar;
parsedMetavariables.insert({ metavar.identifier, SubtreeList() });
// Do not insert the subtree just yet, it will be done further down
break; // No need to check the rest of the metavariables, they cannot overlap
}
Expand Down Expand Up @@ -231,7 +229,7 @@ bool LHSParserVisitor::parseMetavariables(StmtOrDecl subtree) {
}

// We're definitely part of the metavariable's subtree sequence, so we add ourselves to it
parsedMetavariables[parsingMetavariable->identifier].push_back(subtree);
_tmpl->addMetavariable(parsingMetavariable->identifier, subtree);

// If we're the end of the metavariable's subtree sequence, mark this metavariable as done
if (locEndWithSemi == metaEnd || locEndWithLiteral == metaEnd || locEnd == metaEnd) {
Expand Down
56 changes: 36 additions & 20 deletions Framework X/LHS/LHSTemplateParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@
#include <clang/AST/ASTTypeTraits.h>

#include "LHSConfiguration.hpp"
#include "LHSTemplate.hpp"
#include "../common/Lexer.hpp"

using namespace clang;
using namespace clang::ast_type_traits;
using namespace std;

namespace X {

class LHSTemplate;

/// \class StmtOrDecl
/// \brief A small encapsulation class that can contain both Stmts and Decls
Expand Down Expand Up @@ -60,9 +63,25 @@ class StmtOrDecl {
if (_kind == DECL) return getAsDecl()->getLocStart();
else return getAsStmt()->getLocStart();
}

inline SourceLocation getLocEnd() {
if (_kind == DECL) return getAsDecl()->getLocEnd();
else return getAsStmt()->getLocEnd(); }
else return getAsStmt()->getLocEnd();
}

inline bool operator<(StmtOrDecl const &other) const {
return _node < other._node;
}

inline void dump() const {
if (_kind == DECL) getAsDecl()->dump();
else getAsStmt()->dump();
}

/// Use with extreme caution
inline void *getRawPtr() const {
return _node;
}

private:
void *_node; ///< The Stmt or Decl node
Expand All @@ -77,7 +96,8 @@ using SubtreeQueue = queue<StmtOrDecl>;
/// \brief An LHS template parser implementing the RecursiveASTVisitor class in order to visit all AST nodes of the template source
class LHSParserVisitor : public RecursiveASTVisitor<LHSParserVisitor> {
public:
LHSParserVisitor(ASTContext &ctx, LHSConfiguration &cfg) : _sm(ctx.getSourceManager()), _lops(ctx.getLangOpts()), _templateSourceRange(cfg.getTemplateRange()) {
LHSParserVisitor(ASTContext &ctx, LHSConfiguration &cfg)
: _sm(ctx.getSourceManager()), _lops(ctx.getLangOpts()), _templateSourceRange(cfg.getTemplateRange()), _tmpl(llvm::make_unique<LHSTemplate>()) {
auto metavars(cfg.getMetavariableRanges());
remainingMetavariables = set<MetavarLoc>(metavars.begin(), metavars.end());
}
Expand All @@ -95,6 +115,7 @@ class LHSParserVisitor : public RecursiveASTVisitor<LHSParserVisitor> {
const SourceManager &_sm;
const LangOptions &_lops;
const TemplateRange &_templateSourceRange;
unique_ptr<LHSTemplate> _tmpl;

//
// State variables to indicate the progress of parsing the template
Expand All @@ -115,11 +136,6 @@ class LHSParserVisitor : public RecursiveASTVisitor<LHSParserVisitor> {
/// The set of metavariables that still need to be parsed
set<MetavarLoc> remainingMetavariables;

/// A mapping containing the metavariables that have been parsed
/// It maps from a metavariable identifier to a sequence of subtrees
/// that the metavariable represents
map<string, SubtreeList> parsedMetavariables;

/// \brief Method to generally parse a subtree (being either a Stmt or a Decl) to a template.
/// \return Boolean indicating if the the template was parsed
bool parseSubtreeToTemplate(StmtOrDecl subtree);
Expand All @@ -137,6 +153,11 @@ class LHSParserVisitor : public RecursiveASTVisitor<LHSParserVisitor> {
/// \return The result of the traversal
bool continueTraversal(StmtOrDecl subtree);


unique_ptr<LHSTemplate> retrieveLHSTemplate() {
return move(_tmpl);
}

~LHSParserVisitor() {} // Suppress warnings about non-virtual destructor

friend class LHSParserConsumer;
Expand All @@ -146,6 +167,7 @@ class LHSParserVisitor : public RecursiveASTVisitor<LHSParserVisitor> {
/// \brief An AST consumer that forwards translation units to the LHS template parser
class LHSParserConsumer : public ASTConsumer {
LHSConfiguration &_cfg;
unique_ptr<LHSTemplate> _tmpl;

public:
LHSParserConsumer(LHSConfiguration &cfg) : _cfg(cfg) {}
Expand Down Expand Up @@ -178,11 +200,9 @@ class LHSParserConsumer : public ASTConsumer {
subtree = visitor.templateSubtrees.front();

if (subtree.getKind() == StmtOrDecl::Kind::DECL) {
subtree.getAsDecl()->dump();
visitor.TraverseDecl(subtree.getAsDecl());
} else {
visitor.TraverseStmt(subtree.getAsStmt());
subtree.getAsStmt()->dump();
}

visitor.templateSubtrees.pop();
Expand All @@ -196,17 +216,13 @@ class LHSParserConsumer : public ASTConsumer {
throw MalformedConfigException("Some metavariables could not be parsed");
}

for (auto &meta : visitor.parsedMetavariables) {
llvm::outs() << "Metavariable " << meta.first << "\n";
for (auto &subtree : meta.second) {
if (subtree.getKind() == StmtOrDecl::Kind::DECL) {
subtree.getAsDecl()->dump();
} else {
subtree.getAsStmt()->dump();
}
}
llvm::outs() << "\n";
}
_tmpl = visitor.retrieveLHSTemplate();
}

/// Retrieve the constructed LHS template
unique_ptr<LHSTemplate> retrieveLHSTemplate() {
assert(_tmpl && "Not in possession of template");
return move(_tmpl);
}
};

Expand Down
3 changes: 3 additions & 0 deletions Framework X/common/X.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ void X::transform(SourceList sourceFiles, const CompilationDatabase &compilation
LHSParserConsumer consumer(lhsConfig);
consumer.HandleTranslationUnit(templateSourceAST->getASTContext());

unique_ptr<LHSTemplate> lhs(consumer.retrieveLHSTemplate());
lhs->dump();

/*RHSTemplate rhs(lhsConfig.getRHSTemplate());
InternalCallback cb(rhs, false);
consumeASTs(ASTs, llvm::make_unique<LHSParserConsumer>(lhsConfig), cb);*/
Expand Down
1 change: 1 addition & 0 deletions Framework X/common/X.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "../RHS/RHSTemplate.hpp"
#include "../LHS/LHSConfiguration.hpp"
#include "../LHS/LHSTemplateParser.hpp"
#include "../LHS/LHSTemplate.hpp"

using namespace clang;
using namespace clang::ast_matchers;
Expand Down
2 changes: 1 addition & 1 deletion Framework X/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"templateRange": [[22, 1], [28, 2]],
"metaVariables": [{
"identifier": "private_member",
"range": [[24, 5], [24, 10]]
"range": [[24, 5], [25, 10]]
},
{
"identifier": "ctor",
Expand Down

0 comments on commit f7b504f

Please sign in to comment.