[C++] Parse include directives
diff --git a/parser.cc b/parser.cc
index 8d872de..9ddd8cc 100644
--- a/parser.cc
+++ b/parser.cc
@@ -1,5 +1,7 @@
#include "parser.h"
+#include <unordered_map>
+
#include "ast.h"
#include "file.h"
#include "loc.h"
@@ -43,6 +45,24 @@
}
}
+ static void Init() {
+ make_directives_ = new unordered_map<StringPiece, DirectiveHandler>;
+ (*make_directives_)["include"] = &Parser::ParseIncludeAST;
+ (*make_directives_)["-include"] = &Parser::ParseIncludeAST;
+
+ shortest_directive_len_ = 9999;
+ longest_directive_len_ = 0;
+ for (auto p : *make_directives_) {
+ size_t len = p.first.size();
+ shortest_directive_len_ = min(len, shortest_directive_len_);
+ longest_directive_len_ = max(len, longest_directive_len_);
+ }
+ }
+
+ static void Quit() {
+ delete make_directives_;
+ }
+
private:
void Error(const string& msg) {
ERROR("%s:%d: %s", LOCF(loc_), msg.c_str());
@@ -78,7 +98,10 @@
return;
}
- // TODO: directive.
+ line = line.StripLeftSpaces();
+ if (HandleDirective(line)) {
+ return;
+ }
size_t sep = line.find_first_of(STRING_PIECE("=:"));
if (sep == string::npos) {
@@ -145,6 +168,29 @@
state_ = ParserState::NOT_AFTER_RULE;
}
+ void ParseIncludeAST(StringPiece line, StringPiece directive) {
+ IncludeAST* ast = new IncludeAST();
+ ast->expr = ParseExpr(line, false);
+ ast->op = directive[0] == '-' ? '-' : 0;
+ out_asts_->push_back(ast);
+ }
+
+ bool HandleDirective(StringPiece line) {
+ if (line.size() < shortest_directive_len_)
+ return false;
+ StringPiece prefix = line.substr(0, longest_directive_len_ + 1);
+ size_t space_index = prefix.find(' ');
+ if (space_index == string::npos)
+ return false;
+ StringPiece directive = prefix.substr(0, space_index);
+ auto found = make_directives_->find(directive);
+ if (found == make_directives_->end())
+ return false;
+
+ (this->*found->second)(line.substr(directive.size() + 1), directive);
+ return true;
+ }
+
StringPiece buf_;
size_t l_;
ParserState state_;
@@ -153,6 +199,12 @@
Loc loc_;
bool fixed_lineno_;
+
+ typedef void (Parser::*DirectiveHandler)(
+ StringPiece line, StringPiece directive);
+ static unordered_map<StringPiece, DirectiveHandler>* make_directives_;
+ static size_t shortest_directive_len_;
+ static size_t longest_directive_len_;
};
void Parse(Makefile* mk) {
@@ -161,3 +213,15 @@
mk->mutable_asts());
parser.Parse();
}
+
+void InitParser() {
+ Parser::Init();
+}
+
+void QuitParser() {
+ Parser::Quit();
+}
+
+unordered_map<StringPiece, Parser::DirectiveHandler>* Parser::make_directives_;
+size_t Parser::shortest_directive_len_;
+size_t Parser::longest_directive_len_;