Moving hidl-gen parser stack outside of AST

Move compiler stack outside of AST members,
adding a parent member to NamedType to make AST
a real tree.

Add a check that interface must be declared in global scope,
that was not checked in hidl-gen.

Also move scanner outside of AST.

Test: compiles, links, boots, hidl_test
Change-Id: Ida0c192b258e40c8cfe033f00a842444df0130ad
diff --git a/AST.cpp b/AST.cpp
index 2dfd7fa..ef17b71 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -25,27 +25,23 @@
 #include "Scope.h"
 #include "TypeDef.h"
 
-#include <hidl-util/Formatter.h>
-#include <hidl-util/FQName.h>
 #include <android-base/logging.h>
-#include <iostream>
+#include <hidl-util/FQName.h>
+#include <hidl-util/Formatter.h>
+#include <hidl-util/StringHelper.h>
 #include <stdlib.h>
+#include <algorithm>
+#include <iostream>
 
 namespace android {
 
-AST::AST(const Coordinator *coordinator, const std::string &path)
+AST::AST(const Coordinator* coordinator, const std::string& path)
     : mCoordinator(coordinator),
       mPath(path),
-      mScanner(NULL),
-      mRootScope(new Scope("" /* localName */, Location::startOf(path))) {
-    enterScope(mRootScope);
-}
+      mRootScope("" /* localName */, Location::startOf(path), nullptr /* parent */) {}
 
-AST::~AST() {
-    delete mRootScope;
-    mRootScope = nullptr;
-
-    CHECK(mScanner == NULL);
+Scope* AST::getRootScope() {
+    return &mRootScope;
 }
 
 // used by the parser.
@@ -57,14 +53,6 @@
     return mSyntaxErrors;
 }
 
-void *AST::scanner() {
-    return mScanner;
-}
-
-void AST::setScanner(void *scanner) {
-    mScanner = scanner;
-}
-
 const std::string &AST::getFilename() const {
     return mPath;
 }
@@ -87,11 +75,11 @@
 }
 
 bool AST::isInterface() const {
-    return mRootScope->getInterface() != nullptr;
+    return mRootScope.getInterface() != nullptr;
 }
 
 bool AST::containsInterfaces() const {
-    return mRootScope->containsInterfaces();
+    return mRootScope.containsInterfaces();
 }
 
 bool AST::addImport(const char *import) {
@@ -187,51 +175,33 @@
     mImportedASTs.insert(ast);
 }
 
-void AST::enterScope(Scope *container) {
-    mScopePath.push_back(container);
-}
-
-void AST::leaveScope() {
-    mScopePath.pop_back();
-}
-
-Scope *AST::scope() {
-    CHECK(!mScopePath.empty());
-    return mScopePath.back();
-}
-
-bool AST::addTypeDef(const char *localName, Type *type, const Location &location,
-        std::string *errorMsg) {
+bool AST::addTypeDef(const char* localName, Type* type, const Location& location,
+                     std::string* errorMsg, Scope* scope) {
     // The reason we wrap the given type in a TypeDef is simply to suppress
     // emitting any type definitions later on, since this is just an alias
     // to a type defined elsewhere.
-    return addScopedTypeInternal(
-            new TypeDef(localName, location, type), errorMsg);
+    return addScopedTypeInternal(new TypeDef(localName, location, scope, type), errorMsg, scope);
 }
 
-bool AST::addScopedType(NamedType *type, std::string *errorMsg) {
-    return addScopedTypeInternal(
-            type, errorMsg);
+bool AST::addScopedType(NamedType* type, std::string* errorMsg, Scope* scope) {
+    return addScopedTypeInternal(type, errorMsg, scope);
 }
 
-bool AST::addScopedTypeInternal(
-        NamedType *type,
-        std::string *errorMsg) {
-
-    bool success = scope()->addType(type, errorMsg);
+bool AST::addScopedTypeInternal(NamedType* type, std::string* errorMsg, Scope* scope) {
+    bool success = scope->addType(type, errorMsg);
     if (!success) {
         return false;
     }
 
-    std::string path;
-    for (size_t i = 1; i < mScopePath.size(); ++i) {
-        path.append(mScopePath[i]->localName());
-        path.append(".");
+    std::vector<std::string> pathComponents{{type->localName()}};
+    for (; scope != &mRootScope; scope = scope->parent()) {
+        pathComponents.push_back(scope->localName());
     }
-    path.append(type->localName());
+
+    std::reverse(pathComponents.begin(), pathComponents.end());
+    std::string path = StringHelper::JoinStrings(pathComponents, ".");
 
     FQName fqName(mPackage.package(), mPackage.version(), path);
-
     type->setFullName(fqName);
 
     mDefinedTypesByFullName[fqName] = type;
@@ -239,15 +209,14 @@
     return true;
 }
 
-EnumValue *AST::lookupEnumValue(const FQName &fqName, std::string *errorMsg) {
-
+EnumValue* AST::lookupEnumValue(const FQName& fqName, std::string* errorMsg, Scope* scope) {
     FQName enumTypeName = fqName.typeName();
     std::string enumValueName = fqName.valueName();
 
     CHECK(enumTypeName.isValid());
     CHECK(!enumValueName.empty());
 
-    Type *type = lookupType(enumTypeName);
+    Type* type = lookupType(enumTypeName, scope);
     if(type == nullptr) {
         *errorMsg = "Cannot find type " + enumTypeName.string();
         return nullptr;
@@ -266,7 +235,7 @@
     return v;
 }
 
-Type *AST::lookupType(const FQName &fqName) {
+Type* AST::lookupType(const FQName& fqName, Scope* scope) {
     CHECK(fqName.isValid());
 
     if (fqName.name().empty()) {
@@ -278,7 +247,7 @@
 
     if (fqName.package().empty() && fqName.version().empty()) {
         // resolve locally first if possible.
-        returnedType = lookupTypeLocally(fqName);
+        returnedType = lookupTypeLocally(fqName, scope);
         if (returnedType != nullptr) {
             return returnedType;
         }
@@ -298,12 +267,12 @@
 }
 
 // Rule 0: try resolve locally
-Type *AST::lookupTypeLocally(const FQName &fqName) {
+Type* AST::lookupTypeLocally(const FQName& fqName, Scope* scope) {
     CHECK(fqName.package().empty() && fqName.version().empty()
         && !fqName.name().empty() && fqName.valueName().empty());
 
-    for (size_t i = mScopePath.size(); i-- > 0;) {
-        Type *type = mScopePath[i]->lookupType(fqName);
+    for (; scope != nullptr; scope = scope->parent()) {
+        Type* type = scope->lookupType(fqName);
 
         if (type != nullptr) {
             // Resolve typeDefs to the target type.
@@ -329,7 +298,7 @@
     // in import.
     Type *local = findDefinedType(autofilled, &matchingName);
     CHECK(local == nullptr || autofilled == matchingName);
-    Type *fromImport = lookupType(autofilled);
+    Type* fromImport = lookupType(autofilled, nullptr /* scope */);
 
     if (local != nullptr && fromImport != nullptr && local != fromImport) {
         // Something bad happen; two types have the same FQName.
@@ -531,7 +500,7 @@
 
 bool AST::isJavaCompatible() const {
     if (!AST::isInterface()) {
-        for (const auto *type : mRootScope->getSubTypes()) {
+        for (const auto* type : mRootScope.getSubTypes()) {
             if (!type->isJavaCompatible()) {
                 return false;
             }
@@ -540,26 +509,26 @@
         return true;
     }
 
-    const Interface *iface = mRootScope->getInterface();
+    const Interface* iface = mRootScope.getInterface();
     return iface->isJavaCompatible();
 }
 
 void AST::appendToExportedTypesVector(
         std::vector<const Type *> *exportedTypes) const {
-    mRootScope->appendToExportedTypesVector(exportedTypes);
+    mRootScope.appendToExportedTypesVector(exportedTypes);
 }
 
 bool AST::isIBase() const {
-    Interface *iface = mRootScope->getInterface();
+    Interface* iface = mRootScope.getInterface();
     return iface != nullptr && iface->isIBase();
 }
 
 const Interface *AST::getInterface() const {
-    return mRootScope->getInterface();
+    return mRootScope.getInterface();
 }
 
 std::string AST::getBaseName() const {
-    const Interface *iface = mRootScope->getInterface();
+    const Interface* iface = mRootScope.getInterface();
 
     return iface ? iface->getBaseName() : "types";
 }
diff --git a/AST.h b/AST.h
index 437e2be..bb6e677 100644
--- a/AST.h
+++ b/AST.h
@@ -25,6 +25,7 @@
 #include <string>
 #include <vector>
 
+#include "Scope.h"
 #include "Type.h"
 
 namespace android {
@@ -36,12 +37,10 @@
 struct Method;
 struct NamedType;
 struct TypedVar;
-struct Scope;
 struct EnumValue;
 
 struct AST {
     AST(const Coordinator *coordinator, const std::string &path);
-    ~AST();
 
     bool setPackage(const char *package);
     bool addImport(const char *import);
@@ -51,29 +50,22 @@
     bool isInterface() const;
     bool containsInterfaces() const;
 
-    void enterScope(Scope *container);
-    void leaveScope();
-    Scope *scope();
+    // Returns true iff successful.
+    bool addTypeDef(const char* localName, Type* type, const Location& location,
+                    std::string* errorMsg, Scope* scope);
 
     // Returns true iff successful.
-    bool addTypeDef(const char *localName, Type *type, const Location &location,
-            std::string *errorMsg);
-
-    // Returns true iff successful.
-    bool addScopedType(NamedType *type, std::string *errorMsg);
-
-    void *scanner();
-    void setScanner(void *scanner);
+    bool addScopedType(NamedType* type, std::string* errorMsg, Scope* scope);
 
     const std::string &getFilename() const;
 
     // Look up an enum value by "FQName:valueName".
-    EnumValue *lookupEnumValue(const FQName &fqName, std::string *errorMsg);
+    EnumValue* lookupEnumValue(const FQName& fqName, std::string* errorMsg, Scope* scope);
 
     // Look up a type by FQName, "pure" names, i.e. those without package
     // or version are first looked up in the current scope chain.
     // After that lookup proceeds to imports.
-    Type *lookupType(const FQName &fqName);
+    Type* lookupType(const FQName& fqName, Scope* scope);
 
     void addImportedAST(AST *ast);
 
@@ -126,13 +118,13 @@
     // types or Interface base name (e.x. Foo)
     std::string getBaseName() const;
 
-private:
+    Scope* getRootScope();
+
+   private:
     const Coordinator *mCoordinator;
     std::string mPath;
-    std::vector<Scope *> mScopePath;
 
-    void *mScanner;
-    Scope *mRootScope;
+    Scope mRootScope;
 
     FQName mPackage;
 
@@ -155,12 +147,10 @@
     // used by the parser.
     size_t mSyntaxErrors = 0;
 
-    bool addScopedTypeInternal(
-            NamedType *type,
-            std::string *errorMsg);
+    bool addScopedTypeInternal(NamedType* type, std::string* errorMsg, Scope* scope);
 
     // Helper functions for lookupType.
-    Type *lookupTypeLocally(const FQName &fqName);
+    Type* lookupTypeLocally(const FQName& fqName, Scope* scope);
     status_t lookupAutofilledType(const FQName &fqName, Type **returnedType);
     Type *lookupTypeFromImports(const FQName &fqName);
 
diff --git a/CompoundType.cpp b/CompoundType.cpp
index 154bc67..597e51f 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -23,11 +23,9 @@
 
 namespace android {
 
-CompoundType::CompoundType(Style style, const char *localName, const Location &location)
-    : Scope(localName, location),
-      mStyle(style),
-      mFields(NULL) {
-}
+CompoundType::CompoundType(Style style, const char* localName, const Location& location,
+                           Scope* parent)
+    : Scope(localName, location, parent), mStyle(style), mFields(NULL) {}
 
 CompoundType::Style CompoundType::style() const {
     return mStyle;
diff --git a/CompoundType.h b/CompoundType.h
index aa395ba..3aea816 100644
--- a/CompoundType.h
+++ b/CompoundType.h
@@ -32,7 +32,7 @@
         STYLE_UNION,
     };
 
-    CompoundType(Style style, const char *localName, const Location &location);
+    CompoundType(Style style, const char* localName, const Location& location, Scope* parent);
 
     Style style() const;
 
diff --git a/EnumType.cpp b/EnumType.cpp
index 6dfabfd..fb8545f 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -25,13 +25,9 @@
 
 namespace android {
 
-EnumType::EnumType(
-        const char *localName,
-        const Location &location,
-        Type *storageType)
-    : Scope(localName, location),
-      mValues(),
-      mStorageType(storageType) {
+EnumType::EnumType(const char* localName, const Location& location, Type* storageType,
+                   Scope* parent)
+    : Scope(localName, location, parent), mValues(), mStorageType(storageType) {
     mBitfieldType = new BitFieldType();
     mBitfieldType->setElementType(this);
 }
diff --git a/EnumType.h b/EnumType.h
index ab9c4a7..d829292 100644
--- a/EnumType.h
+++ b/EnumType.h
@@ -29,9 +29,7 @@
 struct BitFieldType;
 
 struct EnumType : public Scope {
-    EnumType(const char *localName,
-             const Location &location,
-             Type *storageType);
+    EnumType(const char* localName, const Location& location, Type* storageType, Scope* parent);
 
     const Type *storageType() const;
     const std::vector<EnumValue *> &values() const;
diff --git a/Interface.cpp b/Interface.cpp
index 5974288..26bdf3c 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -67,11 +67,9 @@
     LAST_HIDL_TRANSACTION   = 0x0fffffff,
 };
 
-Interface::Interface(const char *localName, const Location &location, Interface *super)
-    : Scope(localName, location),
-      mSuperType(super),
-      mIsJavaCompatibleInProgress(false) {
-}
+Interface::Interface(const char* localName, const Location& location, Scope* parent,
+                     Interface* super)
+    : Scope(localName, location, parent), mSuperType(super), mIsJavaCompatibleInProgress(false) {}
 
 std::string Interface::typeName() const {
     return "interface " + localName();
diff --git a/Interface.h b/Interface.h
index 793226a..b37dc60 100644
--- a/Interface.h
+++ b/Interface.h
@@ -27,7 +27,7 @@
 struct InterfaceAndMethod;
 
 struct Interface : public Scope {
-    Interface(const char *localName, const Location &location, Interface *super);
+    Interface(const char* localName, const Location& location, Scope* parent, Interface* super);
 
     bool addMethod(Method *method);
     bool addAllReservedMethods();
diff --git a/NamedType.cpp b/NamedType.cpp
index 027245a..f6d876f 100644
--- a/NamedType.cpp
+++ b/NamedType.cpp
@@ -18,9 +18,8 @@
 
 namespace android {
 
-NamedType::NamedType(const char *localName, const Location &loc)
-    : mLocalName(localName), mLocation(loc) {
-}
+NamedType::NamedType(const char* localName, const Location& loc, Scope* parent)
+    : mLocalName(localName), mLocation(loc), mParent(parent) {}
 
 bool NamedType::isNamedType() const {
     return true;
@@ -54,6 +53,10 @@
     return mLocation;
 }
 
+Scope* NamedType::parent() const {
+    return mParent;
+}
+
 void NamedType::emitDump(
         Formatter &out,
         const std::string &streamName,
diff --git a/NamedType.h b/NamedType.h
index 8a1a79e..1e5a614 100644
--- a/NamedType.h
+++ b/NamedType.h
@@ -27,8 +27,10 @@
 
 namespace android {
 
+struct Scope;
+
 struct NamedType : public Type {
-    NamedType(const char *localName, const Location &loc);
+    NamedType(const char* localName, const Location& loc, Scope* mParent);
 
     bool isNamedType() const override;
 
@@ -53,10 +55,13 @@
             const std::string &streamName,
             const std::string &name) const override;
 
-private:
+    Scope* parent() const;
+
+   private:
     std::string mLocalName;
     FQName mFullName;
     Location mLocation;
+    Scope* const mParent;
 
     DISALLOW_COPY_AND_ASSIGN(NamedType);
 };
diff --git a/Scope.cpp b/Scope.cpp
index b2414b3..b12cec8 100644
--- a/Scope.cpp
+++ b/Scope.cpp
@@ -24,10 +24,8 @@
 
 namespace android {
 
-Scope::Scope(const char *localName,
-        const Location &location)
-    : NamedType(localName, location) {
-}
+Scope::Scope(const char* localName, const Location& location, Scope* parent)
+    : NamedType(localName, location, parent) {}
 Scope::~Scope(){}
 
 bool Scope::addType(NamedType *type, std::string *errorMsg) {
diff --git a/Scope.h b/Scope.h
index 122520b..0f58444 100644
--- a/Scope.h
+++ b/Scope.h
@@ -30,8 +30,7 @@
 struct LocalIdentifier;
 
 struct Scope : public NamedType {
-    Scope(const char *localName,
-          const Location &location);
+    Scope(const char* localName, const Location& location, Scope* parent);
     virtual ~Scope();
 
     bool addType(NamedType *type, std::string *errorMsg);
diff --git a/TypeDef.cpp b/TypeDef.cpp
index cf7c0ab..5ca050e 100644
--- a/TypeDef.cpp
+++ b/TypeDef.cpp
@@ -21,10 +21,8 @@
 
 namespace android {
 
-TypeDef::TypeDef(const char* localName, const Location &location, Type *type)
-    : NamedType(localName, location),
-      mReferencedType(type) {
-}
+TypeDef::TypeDef(const char* localName, const Location& location, Scope* parent, Type* type)
+    : NamedType(localName, location, parent), mReferencedType(type) {}
 
 const ScalarType *TypeDef::resolveToScalarType() const {
     CHECK(!"Should not be here");
diff --git a/TypeDef.h b/TypeDef.h
index 5ccbf01..58e3d5c 100644
--- a/TypeDef.h
+++ b/TypeDef.h
@@ -23,7 +23,7 @@
 namespace android {
 
 struct TypeDef : public NamedType {
-    TypeDef(const char* localName, const Location &location, Type *type);
+    TypeDef(const char* localName, const Location& location, Scope* parent, Type* type);
 
     const ScalarType *resolveToScalarType() const override;
 
diff --git a/generateCpp.cpp b/generateCpp.cpp
index fa2bf25..5dde1e6 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -555,7 +555,7 @@
         out << "};\n\n";
     }
 
-    err = mRootScope->emitGlobalTypeDeclarations(out);
+    err = mRootScope.emitGlobalTypeDeclarations(out);
 
     if (err != OK) {
         return err;
@@ -614,7 +614,7 @@
 
     enterLeaveNamespace(out, true /* enter */);
 
-    status_t err = mRootScope->emitGlobalHwDeclarations(out);
+    status_t err = mRootScope.emitGlobalHwDeclarations(out);
     if (err != OK) {
         return err;
     }
@@ -627,7 +627,7 @@
 }
 
 status_t AST::emitTypeDeclarations(Formatter &out) const {
-    return mRootScope->emitTypeDeclarations(out);
+    return mRootScope.emitTypeDeclarations(out);
 }
 
 static void wrapPassthroughArg(Formatter &out,
@@ -797,7 +797,7 @@
 }
 
 status_t AST::generateMethods(Formatter &out, MethodGenerator gen) const {
-    const Interface *iface = mRootScope->getInterface();
+    const Interface* iface = mRootScope.getInterface();
 
     const Interface *prevIterface = nullptr;
     for (const auto &tuple : iface->allMethodsFromRoot()) {
@@ -826,7 +826,7 @@
 }
 
 void AST::generateTemplatizationLink(Formatter& out) const {
-    out << "typedef " << mRootScope->getInterface()->localName() << " Pure;\n\n";
+    out << "typedef " << mRootScope.getInterface()->localName() << " Pure;\n\n";
 }
 
 status_t AST::generateStubHeader(const std::string &outputPath) const {
@@ -835,7 +835,7 @@
         return OK;
     }
 
-    const Interface *iface = mRootScope->getInterface();
+    const Interface* iface = mRootScope.getInterface();
     const std::string klassName = iface->getStubName();
 
     std::string path = outputPath;
@@ -942,7 +942,7 @@
         return OK;
     }
 
-    const Interface *iface = mRootScope->getInterface();
+    const Interface* iface = mRootScope.getInterface();
     const std::string proxyName = iface->getProxyName();
 
     std::string path = outputPath;
@@ -1079,7 +1079,7 @@
     status_t err = generateTypeSource(out, iface ? iface->localName() : "");
 
     if (err == OK && iface) {
-        const Interface *iface = mRootScope->getInterface();
+        const Interface* iface = mRootScope.getInterface();
 
         // need to be put here, generateStubSource is using this.
         out << "const char* "
@@ -1150,7 +1150,7 @@
     }
 
     if (err == OK && iface) {
-        const Interface *iface = mRootScope->getInterface();
+        const Interface* iface = mRootScope.getInterface();
 
         if (isIBase()) {
             out << "// skipped getService, registerAsService, registerForNotifications\n";
@@ -1182,7 +1182,7 @@
 
 status_t AST::generateTypeSource(
         Formatter &out, const std::string &ifaceName) const {
-    return mRootScope->emitTypeDefinitions(out, ifaceName);
+    return mRootScope.emitTypeDefinitions(out, ifaceName);
 }
 
 void AST::declareCppReaderLocals(
@@ -1824,7 +1824,7 @@
         return OK;
     }
 
-    const Interface *iface = mRootScope->getInterface();
+    const Interface* iface = mRootScope.getInterface();
     CHECK(iface != nullptr);
 
     const std::string klassName = iface->getPassthroughName();
@@ -1919,7 +1919,7 @@
 }
 
 status_t AST::generateInterfaceSource(Formatter &out) const {
-    const Interface *iface = mRootScope->getInterface();
+    const Interface* iface = mRootScope.getInterface();
 
     // generate castFrom functions
     std::string childTypeResult = iface->getCppResultType();
@@ -1981,7 +1981,7 @@
 }
 
 status_t AST::generatePassthroughSource(Formatter &out) const {
-    const Interface *iface = mRootScope->getInterface();
+    const Interface* iface = mRootScope.getInterface();
 
     const std::string klassName = iface->getPassthroughName();
 
@@ -2034,7 +2034,7 @@
 status_t AST::generateCppAtraceCall(Formatter &out,
                                     InstrumentationEvent event,
                                     const Method *method) const {
-    const Interface *iface = mRootScope->getInterface();
+    const Interface* iface = mRootScope.getInterface();
     std::string baseString = "HIDL::" + iface->localName() + "::" + method->name();
     switch (event) {
         case SERVER_API_ENTRY:
@@ -2157,7 +2157,7 @@
         }
     }
 
-    const Interface *iface = mRootScope->getInterface();
+    const Interface* iface = mRootScope.getInterface();
 
     out << "for (const auto &callback: mInstrumentationCallbacks) {\n";
     out.indent();
diff --git a/generateCppImpl.cpp b/generateCppImpl.cpp
index 7025a87..ae95590 100644
--- a/generateCppImpl.cpp
+++ b/generateCppImpl.cpp
@@ -85,7 +85,7 @@
         return OK;
     }
 
-    const Interface *iface = mRootScope->getInterface();
+    const Interface* iface = mRootScope.getInterface();
     const std::string baseName = iface->getBaseName();
 
     std::string path = outputPath;
@@ -172,7 +172,7 @@
         return OK;
     }
 
-    const Interface *iface = mRootScope->getInterface();
+    const Interface* iface = mRootScope.getInterface();
     const std::string baseName = iface->getBaseName();
 
     std::string path = outputPath;
diff --git a/generateJava.cpp b/generateJava.cpp
index 0a589ae..f463b7f 100644
--- a/generateJava.cpp
+++ b/generateJava.cpp
@@ -49,7 +49,7 @@
         const std::string &outputPath, const std::string &limitToType) const {
     // Splits types.hal up into one java file per declared type.
 
-    for (const auto &type : mRootScope->getSubTypes()) {
+    for (const auto& type : mRootScope.getSubTypes()) {
         std::string typeName = type->localName();
 
         if (type->isTypeDef()) {
@@ -112,7 +112,7 @@
         return generateJavaTypes(outputPath, limitToType);
     }
 
-    const Interface *iface = mRootScope->getInterface();
+    const Interface* iface = mRootScope.getInterface();
     std::string ifaceName = iface->localName();
 
     const std::string baseName = iface->getBaseName();
@@ -697,7 +697,7 @@
 }
 
 status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
-    return mRootScope->emitJavaTypeDeclarations(out, false /* atTopLevel */);
+    return mRootScope.emitJavaTypeDeclarations(out, false /* atTopLevel */);
 }
 
 }  // namespace android
diff --git a/generateVts.cpp b/generateVts.cpp
index f695bec..5fd8670 100644
--- a/generateVts.cpp
+++ b/generateVts.cpp
@@ -31,11 +31,11 @@
 
 status_t AST::emitVtsTypeDeclarations(Formatter &out) const {
     if (AST::isInterface()) {
-      const Interface *iface = mRootScope->getInterface();
-      return iface->emitVtsAttributeDeclaration(out);
+        const Interface* iface = mRootScope.getInterface();
+        return iface->emitVtsAttributeDeclaration(out);
     }
 
-    for (const auto &type : mRootScope->getSubTypes()) {
+    for (const auto& type : mRootScope.getSubTypes()) {
         // Skip for TypeDef as it is just an alias of a defined type.
         if (type->isTypeDef()) {
             continue;
@@ -94,7 +94,7 @@
     out << "\n";
 
     if (isInterface()) {
-        const Interface *iface = mRootScope->getInterface();
+        const Interface* iface = mRootScope.getInterface();
         out << "interface: {\n";
         out.indent();
 
diff --git a/hidl-gen_l.ll b/hidl-gen_l.ll
index 5945df9..13b69bf 100644
--- a/hidl-gen_l.ll
+++ b/hidl-gen_l.ll
@@ -53,8 +53,6 @@
 using namespace android;
 using token = yy::parser::token;
 
-int check_type(yyscan_t yyscanner, struct yyguts_t *yyg);
-
 #define SCALAR_TYPE(kind)                                       \
     do {                                                        \
         yylval->type = new ScalarType(ScalarType::kind);        \
@@ -179,22 +177,22 @@
 status_t parseFile(AST *ast) {
     FILE *file = fopen(ast->getFilename().c_str(), "rb");
 
-    if (file == NULL) {
+    if (file == nullptr) {
         return -errno;
     }
 
     yyscan_t scanner;
-    yylex_init_extra(ast, &scanner);
-    ast->setScanner(scanner);
+    yylex_init(&scanner);
 
     yyset_in(file, scanner);
-    int res = yy::parser(ast).parse();
+
+    Scope* scopeStack = ast->getRootScope();
+    int res = yy::parser(scanner, ast, &scopeStack).parse();
 
     yylex_destroy(scanner);
-    ast->setScanner(NULL);
 
     fclose(file);
-    file = NULL;
+    file = nullptr;
 
     if (res != 0 || ast->syntaxErrors() != 0) {
         return UNKNOWN_ERROR;
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 35f7405..a244579 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -25,6 +25,7 @@
 #include "Interface.h"
 #include "Location.h"
 #include "Method.h"
+#include "Scope.h"
 #include "VectorType.h"
 #include "RefType.h"
 
@@ -37,9 +38,17 @@
 
 using namespace android;
 
-extern int yylex(yy::parser::semantic_type *, yy::parser::location_type *, void *);
+extern int yylex(yy::parser::semantic_type*, yy::parser::location_type*, void*);
 
-#define scanner ast->scanner()
+void enterScope(AST* /* ast */, Scope** scope, Scope* container) {
+    CHECK(container->parent() == (*scope));
+    *scope = container;
+}
+
+void leaveScope(AST* ast, Scope** scope) {
+    CHECK((*scope) != ast->getRootScope());
+    *scope = (*scope)->parent();
+}
 
 ::android::Location convertYYLoc(const yy::parser::location_type &loc) {
     return ::android::Location(
@@ -192,8 +201,10 @@
         const_cast<std::string *>(&ast->getFilename());
 }
 
-%parse-param { android::AST *ast }
-%lex-param { void *scanner }
+%parse-param { void* scanner }
+%parse-param { android::AST* const ast }
+%parse-param { android::Scope** const scope }
+%lex-param { void* scanner }
 %pure-parser
 %glr-parser
 %skeleton "glr.cc"
@@ -472,7 +483,7 @@
 fqtype
     : fqname
       {
-          $$ = ast->lookupType(*($1));
+          $$ = ast->lookupType(*($1), *scope);
           if ($$ == NULL) {
               std::cerr << "ERROR: Failed to lookup type '" << $1->string() << "' at "
                         << @1
@@ -560,13 +571,13 @@
           }
 
           if ($2 != nullptr) {
-            if (!ast->scope()->isInterface()) {
+            if (!(*scope)->isInterface()) {
                 std::cerr << "ERROR: unknown error in interface declaration at "
                     << @2 << "\n";
                 YYERROR;
             }
 
-            Interface *iface = static_cast<Interface *>(ast->scope());
+            Interface *iface = static_cast<Interface *>(*scope);
             if (!iface->addMethod($2)) {
                 std::cerr << "ERROR: Unable to add method '" << $2->name()
                           << "' at " << @2 << "\n";
@@ -623,7 +634,7 @@
                   YYERROR;
               }
               if (parent == nullptr) {
-                parent = ast->lookupType(gIBaseFqName);
+                parent = ast->lookupType(gIBaseFqName, *scope);
               }
           }
 
@@ -641,34 +652,43 @@
               YYERROR;
           }
 
-          Interface *iface = new Interface($2, convertYYLoc(@2), static_cast<Interface *>(parent));
+          if (*scope != ast->getRootScope()) {
+              std::cerr << "ERROR: All interface must declared in "
+                        << "global scope. at " << @2 << "\n";
+
+              YYERROR;
+          }
+
+          Interface* iface = new Interface(
+              $2, convertYYLoc(@2), *scope,
+              static_cast<Interface *>(parent));
 
           // Register interface immediately so it can be referenced inside
           // definition.
           std::string errorMsg;
-          if (!ast->addScopedType(iface, &errorMsg)) {
+          if (!ast->addScopedType(iface, &errorMsg, *scope)) {
               std::cerr << "ERROR: " << errorMsg << " at " << @2 << "\n";
               YYERROR;
           }
 
-          ast->enterScope(iface);
+          enterScope(ast, scope, iface);
       }
       '{' interface_declarations '}'
       {
-          if (!ast->scope()->isInterface()) {
+          if (!(*scope)->isInterface()) {
               std::cerr << "ERROR: unknown error in interface declaration at "
                   << @5 << "\n";
               YYERROR;
           }
 
-          Interface *iface = static_cast<Interface *>(ast->scope());
+          Interface *iface = static_cast<Interface *>(*scope);
           if (!iface->addAllReservedMethods()) {
               std::cerr << "ERROR: unknown error in adding reserved methods at "
                   << @5 << "\n";
               YYERROR;
           }
 
-          ast->leaveScope();
+          leaveScope(ast, scope);
 
           $$ = iface;
       }
@@ -678,7 +698,7 @@
     : TYPEDEF type valid_type_name
       {
           std::string errorMsg;
-          if (!ast->addTypeDef($3, $2, convertYYLoc(@3), &errorMsg)) {
+          if (!ast->addTypeDef($3, $2, convertYYLoc(@3), &errorMsg, *scope)) {
               std::cerr << "ERROR: " << errorMsg << " at " << @3 << "\n";
               YYERROR;
           }
@@ -699,7 +719,7 @@
           }
           if($1->isIdentifier()) {
               std::string identifier = $1->name();
-              LocalIdentifier *iden = ast->scope()->lookupIdentifier(identifier);
+              LocalIdentifier *iden = (*scope)->lookupIdentifier(identifier);
               if(!iden) {
                   std::cerr << "ERROR: identifier " << $1->string()
                             << " could not be found at " << @1 << ".\n";
@@ -714,7 +734,7 @@
                       *(static_cast<EnumValue *>(iden)->constExpr()), $1->string());
           } else {
               std::string errorMsg;
-              EnumValue *v = ast->lookupEnumValue(*($1), &errorMsg);
+              EnumValue *v = ast->lookupEnumValue(*($1), &errorMsg, *scope);
               if(v == nullptr) {
                   std::cerr << "ERROR: " << errorMsg << " at " << @1 << ".\n";
                   YYERROR;
@@ -810,17 +830,17 @@
 named_struct_or_union_declaration
     : struct_or_union_keyword valid_type_name
       {
-          CompoundType *container = new CompoundType($1, $2, convertYYLoc(@2));
-          ast->enterScope(container);
+          CompoundType *container = new CompoundType($1, $2, convertYYLoc(@2), *scope);
+          enterScope(ast, scope, container);
       }
       struct_or_union_body
       {
-          if (!ast->scope()->isCompoundType()) {
+          if (!(*scope)->isCompoundType()) {
               std::cerr << "ERROR: unknown error in struct or union declaration at "
                   << @4 << "\n";
               YYERROR;
           }
-          CompoundType *container = static_cast<CompoundType *>(ast->scope());
+          CompoundType *container = static_cast<CompoundType *>(*scope);
 
           std::string errorMsg;
           if (!container->setFields($4, &errorMsg)) {
@@ -828,9 +848,9 @@
               YYERROR;
           }
 
-          ast->leaveScope();
+          leaveScope(ast, scope);
 
-          if (!ast->addScopedType(container, &errorMsg)) {
+          if (!ast->addScopedType(container, &errorMsg, *scope)) {
               std::cerr << "ERROR: " << errorMsg << " at " << @2 << "\n";
               YYERROR;
           }
@@ -860,8 +880,8 @@
     | type valid_identifier require_semicolon
       {
         std::string errorMsg;
-        if (ast->scope()->isCompoundType() &&
-            static_cast<CompoundType *>(ast->scope())->style() == CompoundType::STYLE_STRUCT &&
+        if ((*scope)->isCompoundType() &&
+            static_cast<CompoundType *>(*scope)->style() == CompoundType::STYLE_STRUCT &&
             !isValidStructField($2, &errorMsg)) {
             std::cerr << "ERROR: " << errorMsg << " at "
                       << @2 << "\n";
@@ -872,8 +892,8 @@
     | annotated_compound_declaration ';'
       {
         std::string errorMsg;
-        if (ast->scope()->isCompoundType() &&
-            static_cast<CompoundType *>(ast->scope())->style() == CompoundType::STYLE_STRUCT &&
+        if ((*scope)->isCompoundType() &&
+            static_cast<CompoundType *>(*scope)->style() == CompoundType::STYLE_STRUCT &&
             $1 != nullptr &&
             $1->isNamedType() &&
             !isValidStructField(static_cast<NamedType *>($1)->localName().c_str(), &errorMsg)) {
@@ -922,21 +942,21 @@
 named_enum_declaration
     : ENUM valid_type_name enum_storage_type
       {
-          ast->enterScope(new EnumType($2, convertYYLoc(@2), $3));
+          enterScope(ast, scope, new EnumType($2, convertYYLoc(@2), $3, *scope));
       }
       enum_declaration_body
       {
-          if (!ast->scope()->isEnum()) {
+          if (!(*scope)->isEnum()) {
               std::cerr << "ERROR: unknown error in enum declaration at "
                   << @5 << "\n";
               YYERROR;
           }
 
-          EnumType *enumType = static_cast<EnumType *>(ast->scope());
-          ast->leaveScope();
+          EnumType *enumType = static_cast<EnumType *>(*scope);
+          leaveScope(ast, scope);
 
           std::string errorMsg;
-          if (!ast->addScopedType(enumType, &errorMsg)) {
+          if (!ast->addScopedType(enumType, &errorMsg, *scope)) {
               std::cerr << "ERROR: " << errorMsg << " at " << @2 << "\n";
               YYERROR;
           }
@@ -959,23 +979,23 @@
       { /* do nothing */ }
     | enum_value
       {
-          if (!ast->scope()->isEnum()) {
+          if (!(*scope)->isEnum()) {
               std::cerr << "ERROR: unknown error in enum declaration at "
                   << @1 << "\n";
               YYERROR;
           }
 
-          static_cast<EnumType *>(ast->scope())->addValue($1);
+          static_cast<EnumType *>(*scope)->addValue($1);
       }
     | enum_values ',' enum_value
       {
-          if (!ast->scope()->isEnum()) {
+          if (!(*scope)->isEnum()) {
               std::cerr << "ERROR: unknown error in enum declaration at "
                   << @3 << "\n";
               YYERROR;
           }
 
-          static_cast<EnumType *>(ast->scope())->addValue($3);
+          static_cast<EnumType *>(*scope)->addValue($3);
       }
     ;
 
@@ -1041,7 +1061,7 @@
     | INTERFACE
       {
           // "interface" is a synonym of android.hidl.base@1.0::IBase
-          $$ = ast->lookupType(gIBaseFqName);
+          $$ = ast->lookupType(gIBaseFqName, *scope);
           if ($$ == nullptr) {
               std::cerr << "ERROR: Cannot find "
                         << gIBaseFqName.string()
diff --git a/main.cpp b/main.cpp
index b2c4dd9..08af509 100644
--- a/main.cpp
+++ b/main.cpp
@@ -293,7 +293,7 @@
         if (fqName.name() == "types") {
             CHECK(typesAST != nullptr);
 
-            Scope *rootScope = typesAST->scope();
+            Scope* rootScope = typesAST->getRootScope();
 
             std::vector<NamedType *> subTypes = rootScope->getSubTypes();
             std::sort(
@@ -405,7 +405,7 @@
     // We'll have to generate Java code if types.hal contains any non-typedef
     // type declarations.
 
-    Scope *rootScope = typesAST->scope();
+    Scope* rootScope = typesAST->getRootScope();
     std::vector<NamedType *> subTypes = rootScope->getSubTypes();
 
     for (const auto &subType : subTypes) {