diff options
-rw-r--r-- | ast.cc | 13 | ||||
-rw-r--r-- | ast.h | 44 | ||||
-rw-r--r-- | eval.cc | 12 | ||||
-rw-r--r-- | eval.h | 6 | ||||
-rw-r--r-- | main.cc | 3 | ||||
-rw-r--r-- | parser.cc | 66 | ||||
-rw-r--r-- | parser.h | 3 |
7 files changed, 146 insertions, 1 deletions
@@ -41,6 +41,11 @@ string CommandAST::DebugString() const { expr->DebugString().c_str(), LOCF(loc())); } +string IncludeAST::DebugString() const { + return StringPrintf("IncludeAST(%s, loc=%s:%d)", + expr->DebugString().c_str(), LOCF(loc())); +} + RuleAST::~RuleAST() { delete expr; delete after_term; @@ -66,3 +71,11 @@ CommandAST::~CommandAST() { void CommandAST::Eval(Evaluator* ev) const { ev->EvalCommand(this); } + +IncludeAST::~IncludeAST() { + delete expr; +} + +void IncludeAST::Eval(Evaluator* ev) const { + ev->EvalInclude(this); +} @@ -2,6 +2,7 @@ #define AST_H_ #include <string> +#include <vector> #include "loc.h" #include "string_piece.h" @@ -24,6 +25,13 @@ enum struct AssignDirective { EXPORT, }; +enum struct CondOp { + IFEQ, + IFNEQ, + IFDEF, + IFNDEF, +}; + struct AST { public: virtual ~AST(); @@ -79,4 +87,40 @@ struct CommandAST : public AST { virtual string DebugString() const; }; +struct IfAST : public AST { + CondOp op; + Value* lhs; + Value* rhs; + vector<AST*> true_stmts; + vector<AST*> false_stmts; + + virtual ~IfAST(); + + virtual void Eval(Evaluator* ev) const; + + virtual string DebugString() const; +}; + +struct IncludeAST : public AST { + Value* expr; + char op; // '-' or 0. + + virtual ~IncludeAST(); + + virtual void Eval(Evaluator* ev) const; + + virtual string DebugString() const; +}; + +struct ExportAST : public AST { + Value* expr; + bool is_export; + + virtual ~ExportAST(); + + virtual void Eval(Evaluator* ev) const; + + virtual string DebugString() const; +}; + #endif // AST_H_ @@ -105,6 +105,18 @@ void Evaluator::EvalCommand(const CommandAST* ast) { LOG("Command: %s", ast->expr->DebugString().c_str()); } +void Evaluator::EvalIf(const IfAST* ast) { + ERROR("TODO"); +} + +void Evaluator::EvalInclude(const IncludeAST* ast) { + ERROR("TODO"); +} + +void Evaluator::EvalExport(const ExportAST* ast) { + ERROR("TODO"); +} + Var* Evaluator::LookupVar(StringPiece name) { // TODO: TSV. Var* v = vars_->Lookup(name); @@ -11,6 +11,9 @@ using namespace std; class AssignAST; class CommandAST; +class ExportAST; +class IfAST; +class IncludeAST; class Makefile; class Rule; class RuleAST; @@ -34,6 +37,9 @@ class Evaluator { void EvalAssign(const AssignAST* ast); void EvalRule(const RuleAST* ast); void EvalCommand(const CommandAST* ast); + void EvalIf(const IfAST* ast); + void EvalInclude(const IncludeAST* ast); + void EvalExport(const ExportAST* ast); Var* LookupVar(StringPiece name); // For target specific variables. @@ -10,6 +10,7 @@ #include "fileutil.h" #include "func.h" #include "log.h" +#include "parser.h" #include "string_piece.h" #include "strutil.h" #include "var.h" @@ -34,6 +35,7 @@ static void Init() { InitSymtab(); InitFuncTable(); InitDepNodePool(); + InitParser(); if (g_makefile == NULL) { if (Exists("GNUmakefile")) { @@ -49,6 +51,7 @@ static void Init() { } static void Quit() { + QuitParser(); QuitDepNodePool(); QuitFuncTable(); QuitSymtab(); @@ -1,5 +1,7 @@ #include "parser.h" +#include <unordered_map> + #include "ast.h" #include "file.h" #include "loc.h" @@ -43,6 +45,24 @@ class Parser { } } + 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 @@ class Parser { 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 @@ class Parser { 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 @@ class Parser { 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 @@ void Parse(Makefile* mk) { 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_; @@ -5,4 +5,7 @@ class Makefile; void Parse(Makefile* mk); +void InitParser(); +void QuitParser(); + #endif // PARSER_H_ |