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),
23 void Parser::Parse() {
25 end_ = pos_ + input_.length();
29 StateFuncPtr state = &Parser::Start;
31 state = (this->*state)();
35 inline bool Parser::HasNext() {
39 Parser::StateFunc Parser::Start() {
40 // If at the start of a line is whitespace, skip it and arrange to come back
42 if (IsAsciiWhitespace(*pos_))
43 return SkipWhitespaceAndNewLines(&Parser::Start);
45 // Handle comments at the start of lines.
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.
54 current_ = Expectation();
57 return &Parser::ParseBugURL;
60 Parser::StateFunc Parser::ParseComment() {
62 return SyntaxError("Invalid start of comment");
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");
81 return SkipWhitespace(&Parser::InModifiers);
84 Parser::StateFunc Parser::InModifiers() {
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");
97 if (ConfigurationFromString(extracted_string_, &config)) {
98 if (current_.configuration != CONFIGURATION_UNSPECIFIED)
99 DataError("Cannot use more than one configuration modifier");
101 current_.configuration = config;
104 if (PlatformFromString(extracted_string_, &platform))
105 current_.platforms.push_back(platform);
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");
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");
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_, ¤t_.result))
147 DataError("Unknown expectation type");
149 return SkipWhitespace(&Parser::End);
152 Parser::StateFunc Parser::End() {
154 delegate_->EmitExpectation(current_);
157 return SkipWhitespaceAndNewLines(&Parser::Start);
162 Parser::StateFunc Parser::ExtractString(StateFunc success) {
163 const char* start = pos_;
164 while (!IsAsciiWhitespace(*pos_) && *pos_ != ']' && HasNext()) {
167 return SyntaxError("Unexpected start of comment");
170 extracted_string_ = base::StringPiece(start, pos_ - start);
174 Parser::StateFunc Parser::SkipWhitespace(Parser::StateFunc next) {
175 while ((*pos_ == ' ' || *pos_ == '\t') && HasNext()) {
181 Parser::StateFunc Parser::SkipWhitespaceAndNewLines(Parser::StateFunc next) {
182 while (IsAsciiWhitespace(*pos_) && HasNext()) {
191 Parser::StateFunc Parser::SyntaxError(const std::string& message) {
192 delegate_->OnSyntaxError(message);
196 void Parser::DataError(const std::string& error) {
198 delegate_->OnDataError(error);
201 } // namespace test_expectations