From 54cbe2b7bd4971c175b938ea0e79a1c1eb6a167a Mon Sep 17 00:00:00 2001 From: Evan Martin Date: Sat, 16 Oct 2010 11:05:58 -0700 Subject: [PATCH] split parser into separate file --- Makefile | 4 +- manifest_parser.h | 194 +++++++++++++++++++++++++++++++++++++++++++++++++++++ ninja.h | 195 +----------------------------------------------------- 3 files changed, 197 insertions(+), 196 deletions(-) create mode 100644 manifest_parser.h diff --git a/Makefile b/Makefile index c97465b..44877bf 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ all_i_currently_care_about: ninja_test ninja_test: LDFLAGS = -lgtest -lgtest_main ninja_test: ninja_test.o -ninja_test.o: ninja_test.cc ninja.h +ninja_test.o: ninja_test.cc ninja.h manifest_parser.h ninja: ninja.o -ninja.o: ninja.cc ninja.h +ninja.o: ninja.cc ninja.h manifest_parser.h diff --git a/manifest_parser.h b/manifest_parser.h new file mode 100644 index 0000000..e2addcc --- /dev/null +++ b/manifest_parser.h @@ -0,0 +1,194 @@ +#include +#include +#include + +struct ManifestParser { + ManifestParser(State* state) : state_(state), line_(0), col_(0) {} + bool Load(const string& filename, string* err); + bool Parse(const string& input, string* err); + + bool Error(const string& message, string* err); + + bool ParseRule(string* err); + bool ParseEdge(string* err); + + bool SkipWhitespace(bool newline=false); + bool Newline(string* err); + bool NextToken(); + bool ReadToNewline(string* text, string* err); + + State* state_; + const char* cur_; + const char* end_; + int line_, col_; + string token_; +}; + +bool ManifestParser::Load(const string& filename, string* err) { + FILE* f = fopen(filename.c_str(), "r"); + if (!f) { + err->assign(strerror(errno)); + return false; + } + + string text; + char buf[64 << 10]; + size_t len; + while ((len = fread(buf, 1, sizeof(buf), f)) > 0) { + text.append(buf, len); + } + if (ferror(f)) { + err->assign(strerror(errno)); + fclose(f); + return false; + } + fclose(f); + + return Parse(text, err); +} + +bool ManifestParser::Parse(const string& input, string* err) { + cur_ = input.data(); end_ = cur_ + input.size(); + line_ = col_ = 0; + + while (NextToken()) { + if (token_ == "rule") { + if (!ParseRule(err)) + return false; + } else if (token_ == "build") { + if (!ParseEdge(err)) + return false; + } else { + return Error("unknown token: " + token_, err); + } + SkipWhitespace(true); + } + + if (cur_ < end_) + return Error("expected eof", err); + + return true; +} + +bool ManifestParser::Error(const string& message, string* err) { + char buf[1024]; + sprintf(buf, "line %d, col %d: %s", line_ + 1, col_, message.c_str()); + err->assign(buf); + return false; +} + +bool ManifestParser::ParseRule(string* err) { + SkipWhitespace(); + if (!NextToken()) + return Error("expected rule name", err); + if (!Newline(err)) + return false; + string name = token_; + + if (!NextToken() || token_ != "command") + return Error("expected command", err); + string command; + SkipWhitespace(); + if (!ReadToNewline(&command, err)) + return false; + + state_->AddRule(name, command); + + return true; +} + +bool ManifestParser::ParseEdge(string* err) { + vector ins, outs; + string rule; + SkipWhitespace(); + for (;;) { + if (!NextToken()) + return Error("expected output file list", err); + if (token_ == ":") + break; + ins.push_back(token_); + } + if (!NextToken()) + return Error("expected build command name", err); + rule = token_; + for (;;) { + if (!NextToken()) + break; + outs.push_back(token_); + } + if (!Newline(err)) + return false; + + Edge* edge = state_->AddEdge(rule); + if (!edge) + return Error("unknown build rule name name", err); + for (vector::iterator i = ins.begin(); i != ins.end(); ++i) + state_->AddInOut(edge, Edge::IN, *i); + for (vector::iterator i = outs.begin(); i != outs.end(); ++i) + state_->AddInOut(edge, Edge::OUT, *i); + + return true; +} + +bool ManifestParser::SkipWhitespace(bool newline) { + bool skipped = false; + while (cur_ < end_) { + if (*cur_ == ' ') { + ++col_; + } else if (newline && *cur_ == '\n') { + col_ = 0; ++line_; + } else { + break; + } + skipped = true; + ++cur_; + } + return skipped; +} + +bool ManifestParser::Newline(string* err) { + if (cur_ < end_ && *cur_ == '\n') { + ++cur_; ++line_; col_ = 0; + return true; + } else { + if (cur_ >= end_) + return Error("expected newline, got eof", err); + else + return Error(string("expected newline, got '") + *cur_ + string("'"), err); + } +} + +static bool IsIdentChar(char c) { + return + ('a' <= c && c <= 'z') || + ('+' <= c && c <= '9') || // +,-./ and numbers + ('A' <= c && c <= 'Z') || + (c == '_'); +} + +bool ManifestParser::NextToken() { + SkipWhitespace(); + token_.clear(); + if (cur_ >= end_) + return false; + + if (IsIdentChar(*cur_)) { + while (cur_ < end_ && IsIdentChar(*cur_)) { + token_.push_back(*cur_); + ++col_; ++cur_; + } + } else if (*cur_ == ':') { + token_ = ":"; + ++col_; ++cur_; + } + + return !token_.empty(); +} + +bool ManifestParser::ReadToNewline(string* text, string* err) { + while (cur_ < end_ && *cur_ != '\n') { + text->push_back(*cur_); + ++cur_; ++col_; + } + return Newline(err); +} diff --git a/ninja.h b/ninja.h index d10a5b3..5bcb854 100644 --- a/ninja.h +++ b/ninja.h @@ -266,197 +266,4 @@ Edge* Plan::FindWork() { return edge; } -#include -#include -#include - -struct ManifestParser { - ManifestParser(State* state) : state_(state), line_(0), col_(0) {} - bool Load(const string& filename, string* err); - bool Parse(const string& input, string* err); - - bool Error(const string& message, string* err); - - bool ParseRule(string* err); - bool ParseEdge(string* err); - - bool SkipWhitespace(bool newline=false); - bool Newline(string* err); - bool NextToken(); - bool ReadToNewline(string* text, string* err); - - State* state_; - const char* cur_; - const char* end_; - int line_, col_; - string token_; -}; - -bool ManifestParser::Load(const string& filename, string* err) { - FILE* f = fopen(filename.c_str(), "r"); - if (!f) { - err->assign(strerror(errno)); - return false; - } - - string text; - char buf[64 << 10]; - size_t len; - while ((len = fread(buf, 1, sizeof(buf), f)) > 0) { - text.append(buf, len); - } - if (ferror(f)) { - err->assign(strerror(errno)); - fclose(f); - return false; - } - fclose(f); - - return Parse(text, err); -} - -bool ManifestParser::Parse(const string& input, string* err) { - cur_ = input.data(); end_ = cur_ + input.size(); - line_ = col_ = 0; - - while (NextToken()) { - if (token_ == "rule") { - if (!ParseRule(err)) - return false; - } else if (token_ == "build") { - if (!ParseEdge(err)) - return false; - } else { - return Error("unknown token: " + token_, err); - } - SkipWhitespace(true); - } - - if (cur_ < end_) - return Error("expected eof", err); - - return true; -} - -bool ManifestParser::Error(const string& message, string* err) { - char buf[1024]; - sprintf(buf, "line %d, col %d: %s", line_ + 1, col_, message.c_str()); - err->assign(buf); - return false; -} - -bool ManifestParser::ParseRule(string* err) { - SkipWhitespace(); - if (!NextToken()) - return Error("expected rule name", err); - if (!Newline(err)) - return false; - string name = token_; - - if (!NextToken() || token_ != "command") - return Error("expected command", err); - string command; - SkipWhitespace(); - if (!ReadToNewline(&command, err)) - return false; - - state_->AddRule(name, command); - - return true; -} - -bool ManifestParser::ParseEdge(string* err) { - vector ins, outs; - string rule; - SkipWhitespace(); - for (;;) { - if (!NextToken()) - return Error("expected output file list", err); - if (token_ == ":") - break; - ins.push_back(token_); - } - if (!NextToken()) - return Error("expected build command name", err); - rule = token_; - for (;;) { - if (!NextToken()) - break; - outs.push_back(token_); - } - if (!Newline(err)) - return false; - - Edge* edge = state_->AddEdge(rule); - if (!edge) - return Error("unknown build rule name name", err); - for (vector::iterator i = ins.begin(); i != ins.end(); ++i) - state_->AddInOut(edge, Edge::IN, *i); - for (vector::iterator i = outs.begin(); i != outs.end(); ++i) - state_->AddInOut(edge, Edge::OUT, *i); - - return true; -} - -bool ManifestParser::SkipWhitespace(bool newline) { - bool skipped = false; - while (cur_ < end_) { - if (*cur_ == ' ') { - ++col_; - } else if (newline && *cur_ == '\n') { - col_ = 0; ++line_; - } else { - break; - } - skipped = true; - ++cur_; - } - return skipped; -} - -bool ManifestParser::Newline(string* err) { - if (cur_ < end_ && *cur_ == '\n') { - ++cur_; ++line_; col_ = 0; - return true; - } else { - if (cur_ >= end_) - return Error("expected newline, got eof", err); - else - return Error(string("expected newline, got '") + *cur_ + string("'"), err); - } -} - -static bool IsIdentChar(char c) { - return - ('a' <= c && c <= 'z') || - ('+' <= c && c <= '9') || // +,-./ and numbers - ('A' <= c && c <= 'Z') || - (c == '_'); -} - -bool ManifestParser::NextToken() { - SkipWhitespace(); - token_.clear(); - if (cur_ >= end_) - return false; - - if (IsIdentChar(*cur_)) { - while (cur_ < end_ && IsIdentChar(*cur_)) { - token_.push_back(*cur_); - ++col_; ++cur_; - } - } else if (*cur_ == ':') { - token_ = ":"; - ++col_; ++cur_; - } - - return !token_.empty(); -} - -bool ManifestParser::ReadToNewline(string* text, string* err) { - while (cur_ < end_ && *cur_ != '\n') { - text->push_back(*cur_); - ++cur_; ++col_; - } - return Newline(err); -} +#include "manifest_parser.h" -- 2.7.4