| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "base/test/expectations/parser.h" | |
| 6 | |
| 7 #include "base/strings/string_util.h" | |
| 8 | |
| 9 namespace test_expectations { | |
| 10 | |
| 11 Parser::Parser(Delegate* delegate, const std::string& input) | |
| 12 : delegate_(delegate), | |
| 13 input_(input), | |
| 14 pos_(NULL), | |
| 15 end_(NULL), | |
| 16 line_number_(0), | |
| 17 data_error_(false) { | |
| 18 } | |
| 19 | |
| 20 Parser::~Parser() { | |
| 21 } | |
| 22 | |
| 23 void Parser::Parse() { | |
| 24 pos_ = &input_[0]; | |
| 25 end_ = pos_ + input_.length(); | |
| 26 | |
| 27 line_number_ = 1; | |
| 28 | |
| 29 StateFuncPtr state = &Parser::Start; | |
| 30 while (state) { | |
| 31 state = (this->*state)(); | |
| 32 } | |
| 33 } | |
| 34 | |
| 35 inline bool Parser::HasNext() { | |
| 36 return pos_ < end_; | |
| 37 } | |
| 38 | |
| 39 Parser::StateFunc Parser::Start() { | |
| 40 // If at the start of a line is whitespace, skip it and arrange to come back | |
| 41 // here. | |
| 42 if (base::IsAsciiWhitespace(*pos_)) | |
| 43 return SkipWhitespaceAndNewLines(&Parser::Start); | |
| 44 | |
| 45 // Handle comments at the start of lines. | |
| 46 if (*pos_ == '#') | |
| 47 return &Parser::ParseComment; | |
| 48 | |
| 49 // After arranging to come back here from skipping whitespace and comments, | |
| 50 // the parser may be at the end of the input. | |
| 51 if (pos_ >= end_) | |
| 52 return NULL; | |
| 53 | |
| 54 current_ = Expectation(); | |
| 55 data_error_ = false; | |
| 56 | |
| 57 return &Parser::ParseBugURL; | |
| 58 } | |
| 59 | |
| 60 Parser::StateFunc Parser::ParseComment() { | |
| 61 if (*pos_ != '#') | |
| 62 return SyntaxError("Invalid start of comment"); | |
| 63 | |
| 64 do { | |
| 65 ++pos_; | |
| 66 } while (HasNext() && *pos_ != '\n'); | |
| 67 | |
| 68 return &Parser::Start; | |
| 69 } | |
| 70 | |
| 71 Parser::StateFunc Parser::ParseBugURL() { | |
| 72 return SkipWhitespace(ExtractString( | |
| 73 &Parser::BeginModifiers)); | |
| 74 } | |
| 75 | |
| 76 Parser::StateFunc Parser::BeginModifiers() { | |
| 77 if (*pos_ != '[' || !HasNext()) | |
| 78 return SyntaxError("Expected '[' for start of modifiers"); | |
| 79 | |
| 80 ++pos_; | |
| 81 return SkipWhitespace(&Parser::InModifiers); | |
| 82 } | |
| 83 | |
| 84 Parser::StateFunc Parser::InModifiers() { | |
| 85 if (*pos_ == ']') | |
| 86 return &Parser::EndModifiers; | |
| 87 | |
| 88 return ExtractString(SkipWhitespace( | |
| 89 &Parser::SaveModifier)); | |
| 90 } | |
| 91 | |
| 92 Parser::StateFunc Parser::SaveModifier() { | |
| 93 if (extracted_string_.empty()) | |
| 94 return SyntaxError("Invalid modifier list"); | |
| 95 | |
| 96 Configuration config; | |
| 97 if (ConfigurationFromString(extracted_string_, &config)) { | |
| 98 if (current_.configuration != CONFIGURATION_UNSPECIFIED) | |
| 99 DataError("Cannot use more than one configuration modifier"); | |
| 100 else | |
| 101 current_.configuration = config; | |
| 102 } else { | |
| 103 Platform platform; | |
| 104 if (PlatformFromString(extracted_string_, &platform)) | |
| 105 current_.platforms.push_back(platform); | |
| 106 else | |
| 107 DataError("Invalid modifier string"); | |
| 108 } | |
| 109 | |
| 110 return SkipWhitespace(&Parser::InModifiers); | |
| 111 } | |
| 112 | |
| 113 Parser::StateFunc Parser::EndModifiers() { | |
| 114 if (*pos_ != ']' || !HasNext()) | |
| 115 return SyntaxError("Expected ']' for end of modifiers list"); | |
| 116 | |
| 117 ++pos_; | |
| 118 return SkipWhitespace(&Parser::ParseTestName); | |
| 119 } | |
| 120 | |
| 121 Parser::StateFunc Parser::ParseTestName() { | |
| 122 return ExtractString(&Parser::SaveTestName); | |
| 123 } | |
| 124 | |
| 125 Parser::StateFunc Parser::SaveTestName() { | |
| 126 if (extracted_string_.empty()) | |
| 127 return SyntaxError("Invalid test name"); | |
| 128 | |
| 129 current_.test_name = extracted_string_.as_string(); | |
| 130 return SkipWhitespace(&Parser::ParseExpectation); | |
| 131 } | |
| 132 | |
| 133 Parser::StateFunc Parser::ParseExpectation() { | |
| 134 if (*pos_ != '=' || !HasNext()) | |
| 135 return SyntaxError("Expected '=' for expectation result"); | |
| 136 | |
| 137 ++pos_; | |
| 138 return SkipWhitespace(&Parser::ParseExpectationType); | |
| 139 } | |
| 140 | |
| 141 Parser::StateFunc Parser::ParseExpectationType() { | |
| 142 return ExtractString(&Parser::SaveExpectationType); | |
| 143 } | |
| 144 | |
| 145 Parser::StateFunc Parser::SaveExpectationType() { | |
| 146 if (!ResultFromString(extracted_string_, ¤t_.result)) | |
| 147 DataError("Unknown expectation type"); | |
| 148 | |
| 149 return SkipWhitespace(&Parser::End); | |
| 150 } | |
| 151 | |
| 152 Parser::StateFunc Parser::End() { | |
| 153 if (!data_error_) | |
| 154 delegate_->EmitExpectation(current_); | |
| 155 | |
| 156 if (HasNext()) | |
| 157 return SkipWhitespaceAndNewLines(&Parser::Start); | |
| 158 | |
| 159 return NULL; | |
| 160 } | |
| 161 | |
| 162 Parser::StateFunc Parser::ExtractString(StateFunc success) { | |
| 163 const char* start = pos_; | |
| 164 while (!base::IsAsciiWhitespace(*pos_) && *pos_ != ']' && HasNext()) { | |
| 165 ++pos_; | |
| 166 if (*pos_ == '#') { | |
| 167 return SyntaxError("Unexpected start of comment"); | |
| 168 } | |
| 169 } | |
| 170 extracted_string_ = base::StringPiece(start, pos_ - start); | |
| 171 return success; | |
| 172 } | |
| 173 | |
| 174 Parser::StateFunc Parser::SkipWhitespace(Parser::StateFunc next) { | |
| 175 while ((*pos_ == ' ' || *pos_ == '\t') && HasNext()) { | |
| 176 ++pos_; | |
| 177 } | |
| 178 return next; | |
| 179 } | |
| 180 | |
| 181 Parser::StateFunc Parser::SkipWhitespaceAndNewLines(Parser::StateFunc next) { | |
| 182 while (base::IsAsciiWhitespace(*pos_) && HasNext()) { | |
| 183 if (*pos_ == '\n') { | |
| 184 ++line_number_; | |
| 185 } | |
| 186 ++pos_; | |
| 187 } | |
| 188 return next; | |
| 189 } | |
| 190 | |
| 191 Parser::StateFunc Parser::SyntaxError(const std::string& message) { | |
| 192 delegate_->OnSyntaxError(message); | |
| 193 return NULL; | |
| 194 } | |
| 195 | |
| 196 void Parser::DataError(const std::string& error) { | |
| 197 data_error_ = true; | |
| 198 delegate_->OnDataError(error); | |
| 199 } | |
| 200 | |
| 201 } // namespace test_expectations | |
| OLD | NEW |