Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / base / test / expectations / parser.cc
blobc7132e5d4844ae4315de494d1b52c3bca1fc4729
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.
5 #include "base/test/expectations/parser.h"
7 #include "base/strings/string_util.h"
9 namespace test_expectations {
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) {
20 Parser::~Parser() {
23 void Parser::Parse() {
24 pos_ = &input_[0];
25 end_ = pos_ + input_.length();
27 line_number_ = 1;
29 StateFuncPtr state = &Parser::Start;
30 while (state) {
31 state = (this->*state)();
35 inline bool Parser::HasNext() {
36 return pos_ < end_;
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 (IsAsciiWhitespace(*pos_))
43 return SkipWhitespaceAndNewLines(&Parser::Start);
45 // Handle comments at the start of lines.
46 if (*pos_ == '#')
47 return &Parser::ParseComment;
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;
54 current_ = Expectation();
55 data_error_ = false;
57 return &Parser::ParseBugURL;
60 Parser::StateFunc Parser::ParseComment() {
61 if (*pos_ != '#')
62 return SyntaxError("Invalid start of comment");
64 do {
65 ++pos_;
66 } while (HasNext() && *pos_ != '\n');
68 return &Parser::Start;
71 Parser::StateFunc Parser::ParseBugURL() {
72 return SkipWhitespace(ExtractString(
73 &Parser::BeginModifiers));
76 Parser::StateFunc Parser::BeginModifiers() {
77 if (*pos_ != '[' || !HasNext())
78 return SyntaxError("Expected '[' for start of modifiers");
80 ++pos_;
81 return SkipWhitespace(&Parser::InModifiers);
84 Parser::StateFunc Parser::InModifiers() {
85 if (*pos_ == ']')
86 return &Parser::EndModifiers;
88 return ExtractString(SkipWhitespace(
89 &Parser::SaveModifier));
92 Parser::StateFunc Parser::SaveModifier() {
93 if (extracted_string_.empty())
94 return SyntaxError("Invalid modifier list");
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");
110 return SkipWhitespace(&Parser::InModifiers);
113 Parser::StateFunc Parser::EndModifiers() {
114 if (*pos_ != ']' || !HasNext())
115 return SyntaxError("Expected ']' for end of modifiers list");
117 ++pos_;
118 return SkipWhitespace(&Parser::ParseTestName);
121 Parser::StateFunc Parser::ParseTestName() {
122 return ExtractString(&Parser::SaveTestName);
125 Parser::StateFunc Parser::SaveTestName() {
126 if (extracted_string_.empty())
127 return SyntaxError("Invalid test name");
129 current_.test_name = extracted_string_.as_string();
130 return SkipWhitespace(&Parser::ParseExpectation);
133 Parser::StateFunc Parser::ParseExpectation() {
134 if (*pos_ != '=' || !HasNext())
135 return SyntaxError("Expected '=' for expectation result");
137 ++pos_;
138 return SkipWhitespace(&Parser::ParseExpectationType);
141 Parser::StateFunc Parser::ParseExpectationType() {
142 return ExtractString(&Parser::SaveExpectationType);
145 Parser::StateFunc Parser::SaveExpectationType() {
146 if (!ResultFromString(extracted_string_, &current_.result))
147 DataError("Unknown expectation type");
149 return SkipWhitespace(&Parser::End);
152 Parser::StateFunc Parser::End() {
153 if (!data_error_)
154 delegate_->EmitExpectation(current_);
156 if (HasNext())
157 return SkipWhitespaceAndNewLines(&Parser::Start);
159 return NULL;
162 Parser::StateFunc Parser::ExtractString(StateFunc success) {
163 const char* start = pos_;
164 while (!IsAsciiWhitespace(*pos_) && *pos_ != ']' && HasNext()) {
165 ++pos_;
166 if (*pos_ == '#') {
167 return SyntaxError("Unexpected start of comment");
170 extracted_string_ = base::StringPiece(start, pos_ - start);
171 return success;
174 Parser::StateFunc Parser::SkipWhitespace(Parser::StateFunc next) {
175 while ((*pos_ == ' ' || *pos_ == '\t') && HasNext()) {
176 ++pos_;
178 return next;
181 Parser::StateFunc Parser::SkipWhitespaceAndNewLines(Parser::StateFunc next) {
182 while (IsAsciiWhitespace(*pos_) && HasNext()) {
183 if (*pos_ == '\n') {
184 ++line_number_;
186 ++pos_;
188 return next;
191 Parser::StateFunc Parser::SyntaxError(const std::string& message) {
192 delegate_->OnSyntaxError(message);
193 return NULL;
196 void Parser::DataError(const std::string& error) {
197 data_error_ = true;
198 delegate_->OnDataError(error);
201 } // namespace test_expectations