summaryrefslogtreecommitdiff
path: root/base/test/expectations/parser.h
blob: 69a741a852d34e0e0bdf7d309d3f448768c45f90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_TEST_EXPECTATIONS_PARSER_H_
#define BASE_TEST_EXPECTATIONS_PARSER_H_

#include <string>

#include "base/basictypes.h"
#include "base/strings/string_piece.h"
#include "base/test/expectations/expectation.h"

namespace test_expectations {

// This is the internal parser for test expectations. It parses an input
// string and reports information to its Delegate as it's processing the
// input.
//
// The input format is documented here:
// https://docs.google.com/a/chromium.org/document/d/1edhMJ5doY_dzfbKNCzeJJ-8XxPrexTbNL2Y_jVvLB8Q/view
//
// Basic format:
// "http://bug/1234 [ OS-Version ] Test.Name = Result"
//
// The parser is implemented as a state machine, with each state returning a
// function pointer to the next state.
class Parser {
 public:
  // The parser will call these methods on its delegate during a Parse()
  // operation.
  class Delegate {
   public:
    // When a well-formed and valid Expectation has been parsed from the input,
    // it is reported to the delegate via this method.
    virtual void EmitExpectation(const Expectation& expectation) = 0;

    // Called when the input string is not well-formed. Parsing will stop after
    // this method is called.
    virtual void OnSyntaxError(const std::string& message) = 0;

    // Called when an Expectation has been parsed because it is well-formed but
    // contains invalid data (i.e. the modifiers or result are not valid
    // keywords). This Expectation will not be reported via EmitExpectation.
    virtual void OnDataError(const std::string& message) = 0;
  };

  // Creates a new parser for |input| that will send data to |delegate|.
  Parser(Delegate* delegate, const std::string& input);
  ~Parser();

  // Runs the parser of the input string.
  void Parse();

 private:
  // This bit of hackery is used to implement a function pointer type that
  // returns a pointer to a function of the same signature. Since a definition
  // like that is inherently recursive, it's impossible to do:
  //     type StateFunc(*StateFunc)(StateData*);
  // However, this approach works without the need to use void*. Inspired by
  // <http://www.gotw.ca/gotw/057.htm>.
  struct StateFunc;
  typedef StateFunc(Parser::*StateFuncPtr)();
  struct StateFunc {
    StateFunc(StateFuncPtr pf) : pf_(pf) {}
    operator StateFuncPtr() {
      return pf_;
    }
    StateFuncPtr pf_;
  };

  // Tests whether there is at least one more character at pos_ before end_.
  bool HasNext();

  // The parser state functions. On entry, the parser state is at the beginning
  // of the token. Each returns a function pointer to the next state function,
  // or NULL to end parsing. On return, the parser is at the beginning of the
  // next token.
  StateFunc Start();
  StateFunc ParseComment();
  StateFunc ParseBugURL();
  StateFunc BeginModifiers();
  StateFunc InModifiers();
  StateFunc SaveModifier();
  StateFunc EndModifiers();
  StateFunc ParseTestName();
  StateFunc SaveTestName();
  StateFunc ParseExpectation();
  StateFunc ParseExpectationType();
  StateFunc SaveExpectationType();
  StateFunc End();

  // A state function that collects character data from the current position
  // to the next whitespace character. Returns the |success| function when at
  // the end of the string, with the data stored in |extracted_string_|.
  StateFunc ExtractString(StateFunc success);

  // Function that skips over horizontal whitespace characters and then returns
  // the |next| state.
  StateFunc SkipWhitespace(StateFunc next);

  // Does the same as SkipWhitespace but includes newlines.
  StateFunc SkipWhitespaceAndNewLines(StateFunc next);

  // State function that reports the given syntax error |message| to the
  // delegate and then returns NULL, ending the parse loop.
  StateFunc SyntaxError(const std::string& message);

  // Function that reports the data |error| to the delegate without stopping
  // parsing.
  void DataError(const std::string& error);

  // Parser delegate.
  Delegate* delegate_;

  // The input string.
  std::string input_;

  // Current location in the |input_|.
  const char* pos_;

  // Pointer to the end of the |input_|.
  const char* end_;

  // Current line number, as updated by SkipWhitespace().
  int line_number_;

  // The character data extracted from |input_| as a result of the
  // ExtractString() state.
  base::StringPiece extracted_string_;

  // The Expectation object that is currently being processed by the parser.
  // Reset in Start().
  Expectation current_;

  // If DataError() has been called during the course of parsing |current_|.
  // If true, then |current_| will not be emitted to the Delegate.
  bool data_error_;
};

}  // namespace test_expectations

#endif  // BASE_TEST_EXPECTATIONS_PARSER_H_