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#ifndef BASE_TEST_EXPECTATIONS_PARSER_H_
6#define BASE_TEST_EXPECTATIONS_PARSER_H_
7
8#include <string>
9
10#include "base/basictypes.h"
11#include "base/strings/string_piece.h"
12#include "base/test/expectations/expectation.h"
13
14namespace test_expectations {
15
16// This is the internal parser for test expectations. It parses an input
17// string and reports information to its Delegate as it's processing the
18// input.
19//
20// The input format is documented here:
21// https://docs.google.com/a/chromium.org/document/d/1edhMJ5doY_dzfbKNCzeJJ-8XxPrexTbNL2Y_jVvLB8Q/view
22//
23// Basic format:
24// "http://bug/1234 [ OS-Version ] Test.Name = Result"
25//
26// The parser is implemented as a state machine, with each state returning a
27// function pointer to the next state.
28class Parser {
29 public:
30  // The parser will call these methods on its delegate during a Parse()
31  // operation.
32  class Delegate {
33   public:
34    // When a well-formed and valid Expectation has been parsed from the input,
35    // it is reported to the delegate via this method.
36    virtual void EmitExpectation(const Expectation& expectation) = 0;
37
38    // Called when the input string is not well-formed. Parsing will stop after
39    // this method is called.
40    virtual void OnSyntaxError(const std::string& message) = 0;
41
42    // Called when an Expectation has been parsed because it is well-formed but
43    // contains invalid data (i.e. the modifiers or result are not valid
44    // keywords). This Expectation will not be reported via EmitExpectation.
45    virtual void OnDataError(const std::string& message) = 0;
46  };
47
48  // Creates a new parser for |input| that will send data to |delegate|.
49  Parser(Delegate* delegate, const std::string& input);
50  ~Parser();
51
52  // Runs the parser of the input string.
53  void Parse();
54
55 private:
56  // This bit of hackery is used to implement a function pointer type that
57  // returns a pointer to a function of the same signature. Since a definition
58  // like that is inherently recursive, it's impossible to do:
59  //     type StateFunc(*StateFunc)(StateData*);
60  // However, this approach works without the need to use void*. Inspired by
61  // <http://www.gotw.ca/gotw/057.htm>.
62  struct StateFunc;
63  typedef StateFunc(Parser::*StateFuncPtr)();
64  struct StateFunc {
65    StateFunc(StateFuncPtr pf) : pf_(pf) {}
66    operator StateFuncPtr() {
67      return pf_;
68    }
69    StateFuncPtr pf_;
70  };
71
72  // Tests whether there is at least one more character at pos_ before end_.
73  bool HasNext();
74
75  // The parser state functions. On entry, the parser state is at the beginning
76  // of the token. Each returns a function pointer to the next state function,
77  // or NULL to end parsing. On return, the parser is at the beginning of the
78  // next token.
79  StateFunc Start();
80  StateFunc ParseComment();
81  StateFunc ParseBugURL();
82  StateFunc BeginModifiers();
83  StateFunc InModifiers();
84  StateFunc SaveModifier();
85  StateFunc EndModifiers();
86  StateFunc ParseTestName();
87  StateFunc SaveTestName();
88  StateFunc ParseExpectation();
89  StateFunc ParseExpectationType();
90  StateFunc SaveExpectationType();
91  StateFunc End();
92
93  // A state function that collects character data from the current position
94  // to the next whitespace character. Returns the |success| function when at
95  // the end of the string, with the data stored in |extracted_string_|.
96  StateFunc ExtractString(StateFunc success);
97
98  // Function that skips over horizontal whitespace characters and then returns
99  // the |next| state.
100  StateFunc SkipWhitespace(StateFunc next);
101
102  // Does the same as SkipWhitespace but includes newlines.
103  StateFunc SkipWhitespaceAndNewLines(StateFunc next);
104
105  // State function that reports the given syntax error |message| to the
106  // delegate and then returns NULL, ending the parse loop.
107  StateFunc SyntaxError(const std::string& message);
108
109  // Function that reports the data |error| to the delegate without stopping
110  // parsing.
111  void DataError(const std::string& error);
112
113  // Parser delegate.
114  Delegate* delegate_;
115
116  // The input string.
117  std::string input_;
118
119  // Current location in the |input_|.
120  const char* pos_;
121
122  // Pointer to the end of the |input_|.
123  const char* end_;
124
125  // Current line number, as updated by SkipWhitespace().
126  int line_number_;
127
128  // The character data extracted from |input_| as a result of the
129  // ExtractString() state.
130  base::StringPiece extracted_string_;
131
132  // The Expectation object that is currently being processed by the parser.
133  // Reset in Start().
134  Expectation current_;
135
136  // If DataError() has been called during the course of parsing |current_|.
137  // If true, then |current_| will not be emitted to the Delegate.
138  bool data_error_;
139};
140
141}  // namespace test_expectations
142
143#endif  // BASE_TEST_EXPECTATIONS_PARSER_H_
144