• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
14 namespace 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.
28 class 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 {
StateFuncStateFunc65     StateFunc(StateFuncPtr pf) : pf_(pf) {}
StateFuncPtrStateFunc66     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