refactor: parser returns parsed document
Parser::Parse returns AidlDocument. After parsing a document,
AidlDocument is added to AidlTypenames and managed by it. So we don't
need to keep a parser instance.
This enables caching so that when loading a document which is already
parsed then Parse() can simply return the AidlDocument.
Bug: 188878102
Test: aidl_unittests
Change-Id: Ifc50bc20b48e3a2c7a8a614ed8c8a179cd6dd9c9
diff --git a/parser.cpp b/parser.cpp
index 732de59..c7fd61a 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -25,9 +25,15 @@
YY_BUFFER_STATE yy_scan_buffer(char*, size_t, void*);
void yy_delete_buffer(YY_BUFFER_STATE, void*);
-std::unique_ptr<Parser> Parser::Parse(const std::string& filename,
- const android::aidl::IoDelegate& io_delegate,
- AidlTypenames& typenames) {
+const AidlDocument* Parser::Parse(const std::string& filename,
+ const android::aidl::IoDelegate& io_delegate,
+ AidlTypenames& typenames) {
+ // reuse pre-parsed document from typenames
+ for (auto& doc : typenames.AllDocuments()) {
+ if (doc->GetLocation().GetFile() == filename) {
+ return doc.get();
+ }
+ }
// Make sure we can read the file first, before trashing previous state.
unique_ptr<string> raw_buffer = io_delegate.GetFileContents(filename);
if (raw_buffer == nullptr) {
@@ -39,13 +45,13 @@
// nulls at the end.
raw_buffer->append(2u, '\0');
- std::unique_ptr<Parser> parser(new Parser(filename, *raw_buffer, typenames));
+ Parser parser(filename, *raw_buffer, typenames);
- if (yy::parser(parser.get()).parse() != 0 || parser->HasError()) {
+ if (yy::parser(&parser).parse() != 0 || parser.HasError()) {
return nullptr;
}
- return parser;
+ return parser.ParsedDocument();
}
void Parser::SetTypeParameters(AidlTypeSpecifier* type,
@@ -63,9 +69,8 @@
class ReferenceResolver : public AidlVisitor {
public:
- ReferenceResolver(const AidlDefinedType* scope, const AidlTypenames& typenames,
- TypeResolver& resolver, bool* success)
- : scope_(scope), typenames_(typenames), resolver_(resolver), success_(success) {}
+ ReferenceResolver(const AidlDefinedType* scope, TypeResolver& resolver, bool* success)
+ : scope_(scope), resolver_(resolver), success_(success) {}
void Visit(const AidlTypeSpecifier& t) override {
// We're visiting the same node again. This can happen when two constant references
@@ -75,7 +80,7 @@
}
AidlTypeSpecifier& type = const_cast<AidlTypeSpecifier&>(t);
- if (!resolver_(typenames_.GetDocumentFor(scope_), &type)) {
+ if (!resolver_(scope_, &type)) {
AIDL_ERROR(type) << "Failed to resolve '" << type.GetUnresolvedName() << "'";
*success_ = false;
}
@@ -139,18 +144,17 @@
}
const AidlDefinedType* scope_;
- const AidlTypenames& typenames_;
TypeResolver& resolver_;
bool* success_;
std::vector<StackElem> stack_ = {};
};
// Resolve "unresolved" types in the "main" document.
-bool Parser::Resolve(TypeResolver& type_resolver) {
+bool ResolveReferences(const AidlDocument& document, TypeResolver& type_resolver) {
bool success = true;
- for (const auto& type : document_->DefinedTypes()) {
- ReferenceResolver ref_resolver{type.get(), typenames_, type_resolver, &success};
+ for (const auto& type : document.DefinedTypes()) {
+ ReferenceResolver ref_resolver{type.get(), type_resolver, &success};
VisitBottomUp(ref_resolver, *type);
}