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