Add parsing of in-memory strings

Some times, specifically in unit tests, we might want to parse a string
instead of an actual file. And now we can!

Change-Id: Iafdb0f0c1c4002c281de8e819da07a32b10694bf
Test: unit tests
Bug: 24385461
Signed-off-by: Casey Dahlin <sadmac@google.com>
diff --git a/aidl_language.cpp b/aidl_language.cpp
index c84e436..e791f7a 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -28,6 +28,8 @@
 void yylex_destroy(void *);
 void yyset_in(FILE *f, void *);
 int yyparse(Parser*);
+YY_BUFFER_STATE yy_scan_string(const char *, void *);
+void yy_delete_buffer(YY_BUFFER_STATE, void *);
 
 Parser::Parser(const string& filename)
     : filename_(filename) {
@@ -35,6 +37,8 @@
 }
 
 Parser::~Parser() {
+  if (buffer_is_valid_)
+    yy_delete_buffer(buffer_, scanner_);
   yylex_destroy(scanner_);
 }
 
@@ -73,6 +77,14 @@
   return true;
 }
 
+void Parser::SetFileContents(const std::string& contents) {
+  if (buffer_is_valid_)
+    yy_delete_buffer(buffer_, scanner_);
+
+  buffer_ = yy_scan_string(contents.c_str(), scanner_);
+  buffer_is_valid_ = true;
+}
+
 bool Parser::RunParser() {
   int ret = yy::parser(this).parse();
 
diff --git a/aidl_language.h b/aidl_language.h
index eea2988..274515a 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -5,6 +5,9 @@
 
 #include <base/macros.h>
 
+struct yy_buffer_state;
+typedef yy_buffer_state* YY_BUFFER_STATE;
+
 typedef enum {
     NO_EXTRA_TEXT = 0,
     SHORT_COMMENT,
@@ -153,6 +156,11 @@
   ~Parser();
 
   bool OpenFileFromDisk();
+
+  // Call this instead of OpenFileFromDisk to provide the text of the file
+  // directly.
+  void SetFileContents(const std::string& contents);
+
   bool RunParser();
   void ReportError(const std::string& err);
 
@@ -174,6 +182,8 @@
   void *scanner_ = nullptr;
   document_item_type* document_ = nullptr;
   import_info* imports_ = nullptr;
+  bool buffer_is_valid_ = false;
+  YY_BUFFER_STATE buffer_;
 
   DISALLOW_COPY_AND_ASSIGN(Parser);
 };