initial commit of reimplementation of hidl-gen

    commit 56da787631c17276bc987f19649c6c1ea92200c3
    Author: Andreas Huber <andih@google.com>
    Date:   Thu Jul 28 12:18:57 2016 -0700

    ast.cpp => AST.cpp

    commit 095552aba072152d9c87475895cd2e97c43b7b03
    Author: Andreas Huber <andih@google.com>
    Date:   Thu Jul 28 10:43:04 2016 -0700

    TypeContainer => Scope, since it now also holds constants.

    commit 89ec1c511e7806037a53e43333c37fdf1b7aa39e
    Author: Andreas Huber <andih@google.com>
    Date:   Thu Jul 28 10:41:05 2016 -0700

    initial support for constants

    commit b60b7ae588654b634bfdc5c283a25dd6378e1df7
    Author: Andreas Huber <andih@google.com>
    Date:   Thu Jul 28 10:01:46 2016 -0700

    Support for typedef, maintain ordering inside TypeContainer

    commit 8e83034a077ce2309deeb0e2094079cf6f11d8b4
    Author: Andreas Huber <andih@google.com>
    Date:   Thu Jul 28 09:36:29 2016 -0700

    support for optional super interface

    commit 9d44b022adb4a68dfca67ba2a6d845b7c8f27b88
    Author: Andreas Huber <andih@google.com>
    Date:   Thu Jul 28 09:28:18 2016 -0700

    ast => AST

    commit 48fd7f8a4e8ecf230cfc416aec6c8f6115e410af
    Author: Andreas Huber <andih@google.com>
    Date:   Thu Jul 28 09:26:44 2016 -0700

    Each type in its own source/header file pair.

    commit ca1285ecbcbbb1340eec476e3fd4d1334908d8c1
    Author: Andreas Huber <andih@google.com>
    Date:   Thu Jul 28 08:52:24 2016 -0700

    added scalar types "char", "bool" and "opaque"

    commit fbb351e5f4392fcbbce77402dfe059a1c8d79fb2
    Author: Andreas Huber <andih@google.com>
    Date:   Wed Jul 27 13:47:32 2016 -0700

    some fixes to the parser and ast.

    commit 78288216b101349e9364c2d4470ecb5b9a942f5c
    Author: Andreas Huber <andih@google.com>
    Date:   Wed Jul 27 12:34:21 2016 -0700

    Formatter, AST::dump(), NamedType

    commit 4b8cc5d0a8ff5f70cb53e21b56138124259b8bcb
    Author: Andreas Huber <andih@google.com>
    Date:   Wed Jul 27 11:45:10 2016 -0700

    revamp of the parser, scoped type containers

    commit 0193fbfa5c7ac3ac1ce306dfb9c55d879f8c02b5
    Author: Andreas Huber <andih@google.com>
    Date:   Wed Jul 27 10:13:35 2016 -0700

    store output in AST.

    commit 7f53022123978cc7c2a05b0c4aba7a4c5deea93b
    Author: Andreas Huber <andih@google.com>
    Date:   Wed Jul 27 10:06:54 2016 -0700

    reentrant lexer/parser

    commit 3d3e343d6cea2fb127b203071e8aff08a5715011
    Author: Andreas Huber <andih@google.com>
    Date:   Tue Jul 26 15:27:02 2016 -0700

    better typename lookup, comments.

    commit 39f13ae860dbd9ffd163a5c99f150170525457ef
    Author: Andreas Huber <andih@google.com>
    Date:   Tue Jul 26 14:29:33 2016 -0700

    an actual AST.

    commit b1f3f1d94a8d1257426da35ace5bc2af04c433b6
    Author: Andreas Huber <andih@google.com>
    Date:   Tue Jul 26 12:51:34 2016 -0700

    initial commit

Change-Id: I44d1d928a5f3dcb908e264d53af09bbe25d8c464
diff --git a/AST.cpp b/AST.cpp
new file mode 100644
index 0000000..c4e1f18
--- /dev/null
+++ b/AST.cpp
@@ -0,0 +1,74 @@
+#include "AST.h"
+
+#include "Formatter.h"
+#include "Scope.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+extern void parseFile(android::AST *ast, const char *path);
+
+namespace android {
+
+AST::AST()
+    : mScanner(NULL),
+      mRootScope(new Scope("root")) {
+    enterScope(mRootScope);
+}
+
+AST::~AST() {
+    assert(scope() == mRootScope);
+    leaveScope();
+
+    delete mRootScope;
+    mRootScope = NULL;
+
+    assert(mScanner == NULL);
+}
+
+// static
+AST *AST::Parse(const char *path) {
+    AST *ast = new AST;
+    parseFile(ast, path);
+
+    return ast;
+}
+
+void *AST::scanner() {
+    return mScanner;
+}
+
+void AST::setScanner(void *scanner) {
+    mScanner = scanner;
+}
+
+void AST::enterScope(Scope *container) {
+    mScopePath.push_back(container);
+}
+
+void AST::leaveScope() {
+    mScopePath.pop();
+}
+
+Scope *AST::scope() {
+    assert(!mScopePath.empty());
+    return mScopePath.top();
+}
+
+Type *AST::lookupType(const char *name) {
+    for (size_t i = mScopePath.size(); i-- > 0;) {
+        Type *type = mScopePath[i]->lookupType(name);
+
+        if (type != NULL) {
+            return type;
+        }
+    }
+
+    return NULL;
+}
+
+void AST::dump(Formatter &out) const {
+    mRootScope->dump(out);
+}
+
+}  // namespace android;
diff --git a/AST.h b/AST.h
new file mode 100644
index 0000000..1e29227
--- /dev/null
+++ b/AST.h
@@ -0,0 +1,42 @@
+#ifndef AST_H_
+
+#define AST_H_
+
+#include <android-base/macros.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct Formatter;
+struct Type;
+struct Scope;
+
+struct AST {
+    AST();
+    ~AST();
+
+    static AST *Parse(const char *path);
+
+    void enterScope(Scope *container);
+    void leaveScope();
+    Scope *scope();
+
+    void *scanner();
+    void setScanner(void *scanner);
+
+    Type *lookupType(const char *name);
+
+    void dump(Formatter &out) const;
+
+private:
+    Vector<Scope *> mScopePath;
+
+    void *mScanner;
+    Scope *mRootScope;
+
+    DISALLOW_COPY_AND_ASSIGN(AST);
+};
+
+}  // namespace android
+
+#endif  // AST_H_
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..932b308
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,37 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := nuhidl-gen
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_IS_HOST_MODULE := true
+
+LOCAL_SRC_FILES :=              \
+    ArrayType.cpp               \
+    CompoundType.cpp            \
+    Constant.cpp                \
+    EnumType.cpp                \
+    Formatter.cpp               \
+    HandleType.cpp              \
+    hidl-gen_y.yy               \
+    hidl-gen_l.ll               \
+    Interface.cpp               \
+    Method.cpp                  \
+    NamedType.cpp               \
+    RefType.cpp                 \
+    ScalarType.cpp              \
+    Scope.cpp                   \
+    StringType.cpp              \
+    Type.cpp                    \
+    TypeDef.cpp                 \
+    VectorType.cpp              \
+    AST.cpp                     \
+    main.cpp                    \
+
+LOCAL_SHARED_LIBRARIES :=       \
+    libbase                     \
+    liblog                      \
+
+LOCAL_STATIC_LIBRARIES :=       \
+    libutils                    \
+
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/ArrayType.cpp b/ArrayType.cpp
new file mode 100644
index 0000000..9137de1
--- /dev/null
+++ b/ArrayType.cpp
@@ -0,0 +1,18 @@
+#include "ArrayType.h"
+
+#include "Formatter.h"
+
+namespace android {
+
+ArrayType::ArrayType(Type *elementType, const char *dimension)
+    : mElementType(elementType),
+      mDimension(dimension) {
+}
+
+void ArrayType::dump(Formatter &out) const {
+    mElementType->dump(out);
+    out << "[" << mDimension << "]";
+}
+
+}  // namespace android
+
diff --git a/ArrayType.h b/ArrayType.h
new file mode 100644
index 0000000..25320f4
--- /dev/null
+++ b/ArrayType.h
@@ -0,0 +1,26 @@
+#ifndef ARRAY_TYPE_H_
+
+#define ARRAY_TYPE_H_
+
+#include "Type.h"
+
+#include <string>
+
+namespace android {
+
+struct ArrayType : public Type {
+    ArrayType(Type *elementType, const char *dimension);
+
+    void dump(Formatter &out) const override;
+
+private:
+    Type *mElementType;
+    std::string mDimension;
+
+    DISALLOW_COPY_AND_ASSIGN(ArrayType);
+};
+
+}  // namespace android
+
+#endif  // ARRAY_TYPE_H_
+
diff --git a/CompoundType.cpp b/CompoundType.cpp
new file mode 100644
index 0000000..ce8dc86
--- /dev/null
+++ b/CompoundType.cpp
@@ -0,0 +1,49 @@
+#include "CompoundType.h"
+
+#include "Formatter.h"
+
+namespace android {
+
+CompoundField::CompoundField(const char *name, Type *type)
+    : mName(name),
+      mType(type) {
+}
+
+void CompoundField::dump(Formatter &out) const {
+    mType->dump(out);
+
+    out << " " << mName << ";";
+}
+
+CompoundType::CompoundType(Style style, const char *name)
+    : Scope(name),
+      mStyle(style),
+      mFields(NULL) {
+}
+
+void CompoundType::setFields(Vector<CompoundField *> *fields) {
+    mFields = fields;
+}
+
+void CompoundType::dump(Formatter &out) const {
+    out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
+        << " "
+        << name()
+        << " {\n";
+
+    out.indent();
+
+    Scope::dump(out);
+
+    for (size_t i = 0; i < mFields->size(); ++i) {
+        mFields->itemAt(i)->dump(out);
+        out << "\n";
+    }
+
+    out.unindent();
+
+    out << "};\n\n";
+}
+
+}  // namespace android
+
diff --git a/CompoundType.h b/CompoundType.h
new file mode 100644
index 0000000..8d4b837
--- /dev/null
+++ b/CompoundType.h
@@ -0,0 +1,45 @@
+#ifndef COMPOUND_TYPE_H_
+
+#define COMPOUND_TYPE_H_
+
+#include "Scope.h"
+
+#include <utils/Vector.h>
+
+namespace android {
+
+struct CompoundField {
+    CompoundField(const char *name, Type *type);
+
+    void dump(Formatter &out) const;
+
+private:
+    std::string mName;
+    Type *mType;
+
+    DISALLOW_COPY_AND_ASSIGN(CompoundField);
+};
+
+struct CompoundType : public Scope {
+    enum Style {
+        STYLE_STRUCT,
+        STYLE_UNION,
+    };
+
+    CompoundType(Style style, const char *name);
+
+    void setFields(Vector<CompoundField *> *fields);
+
+    void dump(Formatter &out) const override;
+
+private:
+    Style mStyle;
+    Vector<CompoundField *> *mFields;
+
+    DISALLOW_COPY_AND_ASSIGN(CompoundType);
+};
+
+}  // namespace android
+
+#endif  // COMPOUND_TYPE_H_
+
diff --git a/Constant.cpp b/Constant.cpp
new file mode 100644
index 0000000..19ac685
--- /dev/null
+++ b/Constant.cpp
@@ -0,0 +1,33 @@
+#include "Constant.h"
+
+#include "Formatter.h"
+#include "Type.h"
+
+namespace android {
+
+Constant::Constant(const char *name, Type *type, const char *value)
+    : mName(name),
+      mType(type),
+      mValue(value) {
+}
+
+std::string Constant::name() const {
+    return mName;
+}
+
+const Type *Constant::type() const {
+    return mType;
+}
+
+std::string Constant::value() const {
+    return mValue;
+}
+
+void Constant::dump(Formatter &out) const {
+    out << "const ";
+    mType->dump(out);
+    out << " " << mName << " = " << mValue << ";\n";
+}
+
+}  // namespace android
+
diff --git a/Constant.h b/Constant.h
new file mode 100644
index 0000000..4f96ef6
--- /dev/null
+++ b/Constant.h
@@ -0,0 +1,32 @@
+#ifndef CONSTANT_H_
+
+#define CONSTANT_H_
+
+#include <android-base/macros.h>
+#include <string>
+
+namespace android {
+
+struct Formatter;
+struct Type;
+
+struct Constant {
+    Constant(const char *name, Type *type, const char *value);
+
+    std::string name() const;
+    const Type *type() const;
+    std::string value() const;
+
+    void dump(Formatter &out) const;
+
+private:
+    std::string mName;
+    Type *mType;
+    std::string mValue;
+
+    DISALLOW_COPY_AND_ASSIGN(Constant);
+};
+
+}  // namespace android
+
+#endif  // CONSTANT_H_
diff --git a/EnumType.cpp b/EnumType.cpp
new file mode 100644
index 0000000..c4d27c1
--- /dev/null
+++ b/EnumType.cpp
@@ -0,0 +1,52 @@
+#include "EnumType.h"
+
+#include "Formatter.h"
+
+namespace android {
+
+EnumValue::EnumValue(const char *name, const char *value)
+    : mName(name),
+      mValue(value) {
+}
+
+void EnumValue::dump(Formatter &out) const {
+    out << mName;
+
+    if (mValue) {
+        out << " = " << mValue;
+    }
+
+    out << ",";
+}
+
+EnumType::EnumType(
+        const char *name, Vector<EnumValue *> *values, Type *storageType)
+    : NamedType(name),
+      mValues(values),
+      mStorageType(storageType) {
+}
+
+void EnumType::dump(Formatter &out) const {
+    out << "enum " << name() << " ";
+
+    if (mStorageType) {
+        out << ": ";
+        mStorageType->dump(out);
+        out << " ";
+    }
+
+    out << "{\n";
+    out.indent();
+
+    for (size_t i = 0; i < mValues->size(); ++i) {
+        mValues->itemAt(i)->dump(out);
+        out << "\n";
+    }
+
+    out.unindent();
+
+    out << "};\n\n";
+}
+
+}  // namespace android
+
diff --git a/EnumType.h b/EnumType.h
new file mode 100644
index 0000000..7f44d59
--- /dev/null
+++ b/EnumType.h
@@ -0,0 +1,40 @@
+#ifndef ENUM_TYPE_H_
+
+#define ENUM_TYPE_H_
+
+#include "NamedType.h"
+
+#include <utils/Vector.h>
+
+namespace android {
+
+struct EnumValue {
+    EnumValue(const char *name, const char *value = NULL);
+
+    void dump(Formatter &out) const;
+
+private:
+    std::string mName;
+    const char *mValue;
+
+    DISALLOW_COPY_AND_ASSIGN(EnumValue);
+};
+
+struct EnumType : public NamedType {
+    EnumType(const char *name,
+             Vector<EnumValue *> *values,
+             Type *storageType = NULL);
+
+    void dump(Formatter &out) const override;
+
+private:
+    Vector<EnumValue *> *mValues;
+    Type *mStorageType;
+
+    DISALLOW_COPY_AND_ASSIGN(EnumType);
+};
+
+}  // namespace android
+
+#endif  // ENUM_TYPE_H_
+
diff --git a/Formatter.cpp b/Formatter.cpp
new file mode 100644
index 0000000..50b5368
--- /dev/null
+++ b/Formatter.cpp
@@ -0,0 +1,62 @@
+#include "Formatter.h"
+
+#include <assert.h>
+
+using std::string;
+
+namespace android {
+
+Formatter::Formatter()
+    : mIndentDepth(0),
+      mAtStartOfLine(true) {
+}
+
+void Formatter::indent() {
+    ++mIndentDepth;
+}
+
+void Formatter::unindent() {
+    assert(mIndentDepth > 0);
+    --mIndentDepth;
+}
+
+Formatter &Formatter::operator<<(const string &out) {
+    const size_t len = out.length();
+    size_t start = 0;
+    while (start < len) {
+        size_t pos = out.find("\n", start);
+
+        if (pos == string::npos) {
+            if (mAtStartOfLine) {
+                printf("%*s", (int)(2 * mIndentDepth), "");
+                mAtStartOfLine = false;
+            }
+
+            printf("%s", out.substr(start).c_str());
+            break;
+        }
+
+        if (pos == start) {
+            printf("\n");
+            mAtStartOfLine = true;
+        } else if (pos > start) {
+            if (mAtStartOfLine) {
+                printf("%*s", (int)(2 * mIndentDepth), "");
+            }
+
+            printf("%s", out.substr(start, pos - start + 1).c_str());
+
+            mAtStartOfLine = true;
+        }
+
+        start = pos + 1;
+    }
+
+    return *this;
+}
+
+Formatter &Formatter::operator<<(size_t n) {
+    return (*this) << std::to_string(n);
+}
+
+}  // namespace android
diff --git a/Formatter.h b/Formatter.h
new file mode 100644
index 0000000..38e5419
--- /dev/null
+++ b/Formatter.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FORMATTER_H_
+
+#define FORMATTER_H_
+
+#include <android-base/macros.h>
+#include <string>
+
+namespace android {
+
+struct Formatter {
+    Formatter();
+
+    void indent();
+    void unindent();
+
+    Formatter &operator<<(const std::string &out);
+    Formatter &operator<<(size_t n);
+
+private:
+    size_t mIndentDepth;
+    bool mAtStartOfLine;
+
+    DISALLOW_COPY_AND_ASSIGN(Formatter);
+};
+
+}  // namespace android
+
+#endif  // FORMATTER_H_
+
diff --git a/HandleType.cpp b/HandleType.cpp
new file mode 100644
index 0000000..70ffa5f
--- /dev/null
+++ b/HandleType.cpp
@@ -0,0 +1,14 @@
+#include "HandleType.h"
+
+#include "Formatter.h"
+
+namespace android {
+
+HandleType::HandleType() {}
+
+void HandleType::dump(Formatter &out) const {
+    out << "handle";
+}
+
+}  // namespace android
+
diff --git a/HandleType.h b/HandleType.h
new file mode 100644
index 0000000..fa9eb8e
--- /dev/null
+++ b/HandleType.h
@@ -0,0 +1,18 @@
+#ifndef HANDLE_TYPE_H_
+
+#define HANDLE_TYPE_H_
+
+#include "Type.h"
+
+namespace android {
+
+struct HandleType : public Type {
+    HandleType();
+
+    void dump(Formatter &out) const override;
+};
+
+}  // namespace android
+
+#endif  // HANDLE_TYPE_H_
+
diff --git a/Interface.cpp b/Interface.cpp
new file mode 100644
index 0000000..054a869
--- /dev/null
+++ b/Interface.cpp
@@ -0,0 +1,46 @@
+#include "Interface.h"
+
+#include "Formatter.h"
+#include "Method.h"
+
+namespace android {
+
+Interface::Interface(const char *name, Type *super)
+    : Scope(name),
+      mSuperType(super) {
+}
+
+void Interface::addMethod(Method *method) {
+    mMethods.push_back(method);
+}
+
+const Type *Interface::superType() const {
+    return mSuperType;
+}
+
+void Interface::dump(Formatter &out) const {
+    out << "interface " << name();
+
+    if (mSuperType != NULL) {
+        out << " extends ";
+        mSuperType->dump(out);
+    }
+
+    out << " {\n";
+
+    out.indent();
+    Scope::dump(out);
+
+    for (size_t i = 0; i < mMethods.size(); ++i) {
+        mMethods[i]->dump(out);
+
+        out << "\n";
+    }
+
+    out.unindent();
+
+    out << "};\n\n";
+}
+
+}  // namespace android
+
diff --git a/Interface.h b/Interface.h
new file mode 100644
index 0000000..14981ee
--- /dev/null
+++ b/Interface.h
@@ -0,0 +1,33 @@
+#ifndef INTERFACE_H_
+
+#define INTERFACE_H_
+
+#include "Scope.h"
+
+#include <utils/Vector.h>
+
+namespace android {
+
+struct Method;
+
+struct Interface : public Scope {
+    Interface(const char *name, Type *super);
+
+    void addMethod(Method *method);
+
+    void dump(Formatter &out) const override;
+
+    const Type *superType() const;
+
+private:
+    std::string mName;
+    Type *mSuperType;
+    Vector<Method *> mMethods;
+
+    DISALLOW_COPY_AND_ASSIGN(Interface);
+};
+
+}  // namespace android
+
+#endif  // INTERFACE_H_
+
diff --git a/Method.cpp b/Method.cpp
new file mode 100644
index 0000000..b9eb885
--- /dev/null
+++ b/Method.cpp
@@ -0,0 +1,59 @@
+#include "Method.h"
+
+#include "Formatter.h"
+#include "Type.h"
+
+namespace android {
+
+TypedVar::TypedVar(const char *name, Type *type)
+    : mName(name),
+      mType(type) {
+}
+
+void TypedVar::dump(Formatter &out) const {
+    mType->dump(out);
+    out << " ";
+    out << mName;
+}
+
+Method::Method(
+        const char *name,
+        Vector<TypedVar *> *args,
+        Vector<TypedVar *> *results)
+    : mName(name),
+      mArgs(args),
+      mResults(results) {
+}
+
+void Method::dump(Formatter &out) const {
+    out << mName << "(";
+
+    for (size_t i = 0; i < mArgs->size(); ++i) {
+        if (i > 0) {
+            out << ", ";
+        }
+
+        mArgs->itemAt(i)->dump(out);
+    }
+
+    out << ")";
+
+    if (mResults != NULL) {
+        out << " generates (";
+
+        for (size_t i = 0; i < mResults->size(); ++i) {
+            if (i > 0) {
+                out << ", ";
+            }
+
+            mResults->itemAt(i)->dump(out);
+        }
+
+        out << ")";
+    }
+
+    out << ";";
+}
+
+}  // namespace android
+
diff --git a/Method.h b/Method.h
new file mode 100644
index 0000000..3f80402
--- /dev/null
+++ b/Method.h
@@ -0,0 +1,44 @@
+#ifndef METHOD_H_
+
+#define METHOD_H_
+
+#include <android-base/macros.h>
+#include <string>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct Formatter;
+struct Type;
+
+struct TypedVar {
+    TypedVar(const char *name, Type *type);
+
+    void dump(Formatter &out) const;
+
+private:
+    std::string mName;
+    Type *mType;
+
+    DISALLOW_COPY_AND_ASSIGN(TypedVar);
+};
+
+struct Method {
+    Method(const char *name,
+           Vector<TypedVar *> *args,
+           Vector<TypedVar *> *results = NULL);
+
+    void dump(Formatter &out) const;
+
+private:
+    std::string mName;
+    Vector<TypedVar *> *mArgs;
+    Vector<TypedVar *> *mResults;
+
+    DISALLOW_COPY_AND_ASSIGN(Method);
+};
+
+}  // namespace android
+
+#endif  // METHOD_H_
+
diff --git a/NamedType.cpp b/NamedType.cpp
new file mode 100644
index 0000000..53c8c86
--- /dev/null
+++ b/NamedType.cpp
@@ -0,0 +1,14 @@
+#include "NamedType.h"
+
+namespace android {
+
+NamedType::NamedType(const char *name)
+    : mName(name) {
+}
+
+std::string NamedType::name() const {
+    return mName;
+}
+
+}  // namespace android
+
diff --git a/NamedType.h b/NamedType.h
new file mode 100644
index 0000000..8992609
--- /dev/null
+++ b/NamedType.h
@@ -0,0 +1,25 @@
+#ifndef NAMED_TYPE_H_
+
+#define NAMED_TYPE_H_
+
+#include "Type.h"
+
+#include <string>
+
+namespace android {
+
+struct NamedType : public Type {
+    NamedType(const char *name);
+
+    std::string name() const;
+
+private:
+    std::string mName;
+
+    DISALLOW_COPY_AND_ASSIGN(NamedType);
+};
+
+}  // namespace android
+
+#endif  // NAMED_TYPE_H_
+
diff --git a/RefType.cpp b/RefType.cpp
new file mode 100644
index 0000000..fe1fb51
--- /dev/null
+++ b/RefType.cpp
@@ -0,0 +1,21 @@
+#include "RefType.h"
+
+#include "Formatter.h"
+
+namespace android {
+
+RefType::RefType(const char *name, Type *type)
+    : NamedType(name),
+      mReferencedType(type) {
+}
+
+const Type *RefType::referencedType() const {
+    return mReferencedType;
+}
+
+void RefType::dump(Formatter &out) const {
+    out << name();
+}
+
+}  // namespace android
+
diff --git a/RefType.h b/RefType.h
new file mode 100644
index 0000000..74093fc
--- /dev/null
+++ b/RefType.h
@@ -0,0 +1,25 @@
+#ifndef REF_TYPE_H_
+
+#define REF_TYPE_H_
+
+#include "NamedType.h"
+
+namespace android {
+
+struct RefType : public NamedType {
+    RefType(const char *name, Type *type);
+
+    void dump(Formatter &out) const override;
+
+    const Type *referencedType() const;
+
+private:
+    Type *mReferencedType;
+
+    DISALLOW_COPY_AND_ASSIGN(RefType);
+};
+
+}  // namespace android
+
+#endif  // REF_TYPE_H_
+
diff --git a/ScalarType.cpp b/ScalarType.cpp
new file mode 100644
index 0000000..ef816a9
--- /dev/null
+++ b/ScalarType.cpp
@@ -0,0 +1,20 @@
+#include "ScalarType.h"
+
+#include "Formatter.h"
+
+namespace android {
+
+ScalarType::ScalarType(Kind kind)
+    : mKind(kind) {
+}
+
+void ScalarType::dump(Formatter &out) const {
+    static const char *const kName[] = {
+        "char", "bool", "opaque", "int8_t", "uint8_t", "int16_t", "uint16_t",
+        "int32_t", "uint32_t", "int64_t", "uint64_t", "float", "double"
+    };
+    out << kName[mKind];
+}
+
+}  // namespace android
+
diff --git a/ScalarType.h b/ScalarType.h
new file mode 100644
index 0000000..e574b80
--- /dev/null
+++ b/ScalarType.h
@@ -0,0 +1,38 @@
+#ifndef SCALAR_TYPE_H_
+
+#define SCALAR_TYPE_H_
+
+#include "Type.h"
+
+namespace android {
+
+struct ScalarType : public Type {
+    enum Kind {
+        KIND_CHAR,
+        KIND_BOOL,
+        KIND_OPAQUE,
+        KIND_INT8,
+        KIND_UINT8,
+        KIND_INT16,
+        KIND_UINT16,
+        KIND_INT32,
+        KIND_UINT32,
+        KIND_INT64,
+        KIND_UINT64,
+        KIND_FLOAT,
+        KIND_DOUBLE,
+    };
+
+    ScalarType(Kind kind);
+
+    void dump(Formatter &out) const override;
+
+private:
+    Kind mKind;
+
+    DISALLOW_COPY_AND_ASSIGN(ScalarType);
+};
+
+}  // namespace android
+
+#endif  // SCALAR_TYPE_H_
diff --git a/Scope.cpp b/Scope.cpp
new file mode 100644
index 0000000..73c6c83
--- /dev/null
+++ b/Scope.cpp
@@ -0,0 +1,63 @@
+#include "Scope.h"
+
+#include "Constant.h"
+#include "Formatter.h"
+
+namespace android {
+
+Scope::Scope(const char *name)
+    : NamedType(name) {
+}
+
+bool Scope::addType(NamedType *type) {
+    std::string name = type->name();
+
+    if (mTypeIndexByName.indexOfKey(name) >= 0) {
+        return false;
+    }
+
+    size_t index = mTypes.size();
+    mTypes.push_back(type);
+    mTypeIndexByName.add(name, index);
+
+    return true;
+}
+
+bool Scope::addConstant(Constant *constant) {
+    ssize_t index = mConstants.indexOfKey(constant->name());
+
+    if (index >= 0) {
+        return false;
+    }
+
+    mConstants.add(constant->name(), constant);
+
+    return true;
+}
+
+Type *Scope::lookupType(const char *name) const {
+    ssize_t index = mTypeIndexByName.indexOfKey(name);
+
+    if (index >= 0) {
+        return mTypes[mTypeIndexByName.valueAt(index)];
+    }
+
+    return NULL;
+}
+
+void Scope::dump(Formatter &out) const {
+    for (size_t i = 0; i < mConstants.size(); ++i) {
+        mConstants.valueAt(i)->dump(out);
+    }
+
+    if (mConstants.size() > 0) {
+        out << "\n";
+    }
+
+    for (size_t i = 0; i < mTypes.size(); ++i) {
+        mTypes[i]->dump(out);
+    }
+}
+
+}  // namespace android
+
diff --git a/Scope.h b/Scope.h
new file mode 100644
index 0000000..a7cf5ec
--- /dev/null
+++ b/Scope.h
@@ -0,0 +1,36 @@
+#ifndef SCOPE_H_
+
+#define SCOPE_H_
+
+#include "NamedType.h"
+
+#include <utils/KeyedVector.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct Constant;
+
+struct Scope : public NamedType {
+    Scope(const char *name);
+
+    bool addType(NamedType *type);
+    Type *lookupType(const char *name) const;
+
+    bool addConstant(Constant *constant);
+
+    void dump(Formatter &out) const override;
+
+private:
+    Vector<Type *> mTypes;
+    KeyedVector<std::string, size_t> mTypeIndexByName;
+
+    KeyedVector<std::string, Constant *> mConstants;
+
+    DISALLOW_COPY_AND_ASSIGN(Scope);
+};
+
+}  // namespace android
+
+#endif  // SCOPE_H_
+
diff --git a/StringType.cpp b/StringType.cpp
new file mode 100644
index 0000000..2356e3a
--- /dev/null
+++ b/StringType.cpp
@@ -0,0 +1,14 @@
+#include "StringType.h"
+
+#include "Formatter.h"
+
+namespace android {
+
+StringType::StringType() {}
+
+void StringType::dump(Formatter &out) const {
+    out << "string";
+}
+
+}  // namespace android
+
diff --git a/StringType.h b/StringType.h
new file mode 100644
index 0000000..8016f4e
--- /dev/null
+++ b/StringType.h
@@ -0,0 +1,18 @@
+#ifndef STRING_TYPE_H_
+
+#define STRING_TYPE_H_
+
+#include "Type.h"
+
+namespace android {
+
+struct StringType : public Type {
+    StringType();
+
+    void dump(Formatter &out) const override;
+};
+
+}  // namespace android
+
+#endif  // STRING_TYPE_H_
+
diff --git a/Type.cpp b/Type.cpp
new file mode 100644
index 0000000..fd64343
--- /dev/null
+++ b/Type.cpp
@@ -0,0 +1,9 @@
+#include "Type.h"
+
+namespace android {
+
+Type::Type() {}
+Type::~Type() {}
+
+}  // namespace android
+
diff --git a/Type.h b/Type.h
new file mode 100644
index 0000000..0fef750
--- /dev/null
+++ b/Type.h
@@ -0,0 +1,24 @@
+#ifndef TYPE_H_
+
+#define TYPE_H_
+
+#include <android-base/macros.h>
+
+namespace android {
+
+struct Formatter;
+
+struct Type {
+    Type();
+    virtual ~Type();
+
+    virtual void dump(Formatter &out) const = 0;
+
+private:
+    DISALLOW_COPY_AND_ASSIGN(Type);
+};
+
+}  // namespace android
+
+#endif  // TYPE_H_
+
diff --git a/TypeDef.cpp b/TypeDef.cpp
new file mode 100644
index 0000000..c365e5d
--- /dev/null
+++ b/TypeDef.cpp
@@ -0,0 +1,23 @@
+#include "TypeDef.h"
+
+#include "Formatter.h"
+
+namespace android {
+
+TypeDef::TypeDef(const char *name, Type *type)
+    : NamedType(name),
+      mReferencedType(type) {
+}
+
+const Type *TypeDef::referencedType() const {
+    return mReferencedType;
+}
+
+void TypeDef::dump(Formatter &out) const {
+    out << "typedef ";
+    mReferencedType->dump(out);
+    out << " " << name() << ";\n\n";
+}
+
+}  // namespace android
+
diff --git a/TypeDef.h b/TypeDef.h
new file mode 100644
index 0000000..716c853
--- /dev/null
+++ b/TypeDef.h
@@ -0,0 +1,25 @@
+#ifndef TYPE_DEF_H_
+
+#define TYPE_DEF_H_
+
+#include "NamedType.h"
+
+namespace android {
+
+struct TypeDef : public NamedType {
+    TypeDef(const char *name, Type *type);
+
+    void dump(Formatter &out) const override;
+
+    const Type *referencedType() const;
+
+private:
+    Type *mReferencedType;
+
+    DISALLOW_COPY_AND_ASSIGN(TypeDef);
+};
+
+}  // namespace android
+
+#endif  // TYPE_DEF_H_
+
diff --git a/VectorType.cpp b/VectorType.cpp
new file mode 100644
index 0000000..2343868
--- /dev/null
+++ b/VectorType.cpp
@@ -0,0 +1,18 @@
+#include "VectorType.h"
+
+#include "Formatter.h"
+
+namespace android {
+
+VectorType::VectorType(Type *elementType)
+    : mElementType(elementType) {
+}
+
+void VectorType::dump(Formatter &out) const {
+    out<< "vec<";
+    mElementType->dump(out);
+    out << ">";
+}
+
+}  // namespace android
+
diff --git a/VectorType.h b/VectorType.h
new file mode 100644
index 0000000..0cde849
--- /dev/null
+++ b/VectorType.h
@@ -0,0 +1,23 @@
+#ifndef VECTOR_TYPE_H_
+
+#define VECTOR_TYPE_H_
+
+#include "Type.h"
+
+namespace android {
+
+struct VectorType : public Type {
+    VectorType(Type *elementType);
+
+    void dump(Formatter &out) const override;
+
+private:
+    Type *mElementType;
+
+    DISALLOW_COPY_AND_ASSIGN(VectorType);
+};
+
+}  // namespace android
+
+#endif  // VECTOR_TYPE_H_
+
diff --git a/hidl-gen_l.ll b/hidl-gen_l.ll
new file mode 100644
index 0000000..cea965a
--- /dev/null
+++ b/hidl-gen_l.ll
@@ -0,0 +1,173 @@
+D			[0-9]
+L			[a-zA-Z_]
+H			[a-fA-F0-9]
+E			[Ee][+-]?{D}+
+FS			(f|F|l|L)
+IS			(u|U|l|L)*
+
+%{
+
+#include "AST.h"
+#include "CompoundType.h"
+#include "EnumType.h"
+#include "HandleType.h"
+#include "Method.h"
+#include "RefType.h"
+#include "ScalarType.h"
+#include "StringType.h"
+
+#include "hidl-gen_y.h"
+
+#include <assert.h>
+
+using namespace android;
+
+void count(struct yyguts_t *yyg);
+void comment(yyscan_t yyscanner, struct yyguts_t *yyg);
+int check_type(yyscan_t yyscanner, struct yyguts_t *yyg);
+
+#define SCALAR_TYPE(kind)                                       \
+    do {                                                        \
+        count(yyg);                                             \
+        yylval->type = new ScalarType(ScalarType::kind);        \
+        return TYPENAME;                                        \
+    } while (0)
+
+%}
+
+%option reentrant
+%option bison-bridge
+%option extra-type="android::AST *"
+
+%%
+
+"/*"			{ comment(yyscanner, yyg); }
+"//"[^\r\n]*            { /* skip C++ style comment */ }
+
+"const"			{ count(yyg); return(CONST); }
+"enum"			{ count(yyg); return(ENUM); }
+"extends"		{ count(yyg); return(EXTENDS); }
+"generates"		{ count(yyg); return(GENERATES); }
+"import"		{ count(yyg); return(IMPORT); }
+"interface"		{ count(yyg); return(INTERFACE); }
+"package"		{ count(yyg); return(PACKAGE); }
+"struct"		{ count(yyg); return(STRUCT); }
+"typedef"		{ count(yyg); return(TYPEDEF); }
+"union"			{ count(yyg); return(UNION); }
+"vec"			{ count(yyg); return(VEC); }
+"version"		{ count(yyg); return(VERSION); }
+
+"char"			{ SCALAR_TYPE(KIND_CHAR); }
+"bool"			{ SCALAR_TYPE(KIND_BOOL); }
+"opaque"		{ SCALAR_TYPE(KIND_OPAQUE); }
+"int8_t"		{ SCALAR_TYPE(KIND_INT8); }
+"uint8_t"		{ SCALAR_TYPE(KIND_UINT8); }
+"int16_t"		{ SCALAR_TYPE(KIND_INT16); }
+"uint16_t"		{ SCALAR_TYPE(KIND_UINT16); }
+"int32_t"		{ SCALAR_TYPE(KIND_INT32); }
+"uint32_t"		{ SCALAR_TYPE(KIND_UINT32); }
+"int64_t"		{ SCALAR_TYPE(KIND_INT64); }
+"uint64_t"		{ SCALAR_TYPE(KIND_UINT64); }
+"float"			{ SCALAR_TYPE(KIND_FLOAT); }
+"double"		{ SCALAR_TYPE(KIND_DOUBLE); }
+
+"handle"		{ count(yyg); yylval->type = new HandleType; return TYPENAME; }
+"string"		{ count(yyg); yylval->type = new StringType; return TYPENAME; }
+
+"("			{ count(yyg); return('('); }
+")"			{ count(yyg); return(')'); }
+"<"			{ count(yyg); return('<'); }
+">"			{ count(yyg); return('>'); }
+"{"			{ count(yyg); return('{'); }
+"}"			{ count(yyg); return('}'); }
+"["			{ count(yyg); return('['); }
+"]"			{ count(yyg); return(']'); }
+":"			{ count(yyg); return(':'); }
+";"			{ count(yyg); return(';'); }
+","			{ count(yyg); return(','); }
+"."			{ count(yyg); return('.'); }
+"="			{ count(yyg); return('='); }
+
+{L}({L}|{D})*		{ count(yyg); return check_type(yyscanner, yyg); }
+
+0[xX]{H}+{IS}?		{ count(yyg); yylval->str = strdup(yytext); return(INTEGER); }
+0{D}+{IS}?		{ count(yyg); yylval->str = strdup(yytext); return(INTEGER); }
+{D}+{IS}?		{ count(yyg); yylval->str = strdup(yytext); return(INTEGER); }
+L?\"(\\.|[^\\"])*\"	{ count(yyg); yylval->str = strdup(yytext); return(STRING_LITERAL); }
+
+[ \t\v\n\f]		{ count(yyg); }
+.			{ /* ignore bad characters */ }
+
+%%
+
+int yywrap(yyscan_t scanner) {
+    return 1;
+}
+
+void comment(yyscan_t yyscanner, yyguts_t *yyg) {
+    char c, c1;
+
+loop:
+    while ((c = yyinput(yyscanner)) != '*' && c != 0)
+        putchar(c);
+
+    if ((c1 = yyinput(yyscanner)) != '/' && c != 0)
+    {
+        unput(c1);
+        goto loop;
+    }
+
+    if (c != 0) {
+        putchar(c1);
+    }
+}
+
+
+int column = 0;
+
+void count(yyguts_t *yyg) {
+    int i;
+
+    for (i = 0; yytext[i] != '\0'; i++)
+        if (yytext[i] == '\n')
+            column = 0;
+        else if (yytext[i] == '\t')
+            column += 8 - (column % 8);
+        else
+            column++;
+
+    ECHO;
+}
+
+int check_type(yyscan_t yyscanner, yyguts_t *yyg) {
+    AST *ast = yyextra;
+
+    Type *type = ast->lookupType(yytext);
+    if (type != NULL) {
+        yylval->type = new RefType(yytext, type);
+
+        return TYPENAME;
+    }
+
+    yylval->str = strdup(yytext);
+
+    return IDENTIFIER;
+}
+
+void parseFile(AST *ast, const char *path) {
+    FILE *file = fopen(path, "rb");
+
+    yyscan_t scanner;
+    yylex_init_extra(ast, &scanner);
+    ast->setScanner(scanner);
+
+    yyset_in(file, scanner);
+    int res = yyparse(ast);
+    assert(res == 0);
+
+    yylex_destroy(scanner);
+    ast->setScanner(NULL);
+
+    fclose(file);
+    file = NULL;
+}
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
new file mode 100644
index 0000000..ae17f92
--- /dev/null
+++ b/hidl-gen_y.yy
@@ -0,0 +1,337 @@
+%{
+
+#include "AST.h"
+#include "ArrayType.h"
+#include "CompoundType.h"
+#include "Constant.h"
+#include "EnumType.h"
+#include "Interface.h"
+#include "Method.h"
+#include "RefType.h"
+#include "TypeDef.h"
+#include "VectorType.h"
+
+#include "hidl-gen_y.h"
+
+#include <stdio.h>
+
+using namespace android;
+
+extern int yylex(YYSTYPE *yylval_param, void *yyscanner);
+extern int column;
+
+int yyerror(AST *ast, const char *s) {
+    fflush(stdout);
+    printf("\n%*s\n%*s\n", column, "^", column, s);
+
+    return 0;
+}
+
+#define scanner ast->scanner()
+
+%}
+
+%parse-param { android::AST *ast }
+%lex-param { void *scanner }
+%pure-parser
+
+%token<str> CONST
+%token<str> ENUM
+%token<str> EXTENDS
+%token<str> GENERATES
+%token<str> IDENTIFIER
+%token<str> IMPORT
+%token<str> INTEGER
+%token<str> INTERFACE
+%token<str> PACKAGE
+%token<str> STRUCT
+%token<str> STRING_LITERAL
+%token<str> TYPEDEF
+%token<str> UNION
+%token<str> VEC
+%token<str> VERSION
+
+%token<type> TYPENAME
+
+%type<str> optIdentifier package
+%type<str> const_value
+
+%type<type> type opt_storage_type
+%type<type> enum_declaration
+%type<type> struct_or_union_declaration
+%type<type> opt_extends
+
+%type<field> field_declaration
+%type<fields> field_declarations struct_or_union_body
+%type<enumValue> enum_value
+%type<enumValues> enum_values
+%type<typedVars> typed_vars
+%type<typedVar> typed_var
+%type<method> method_declaration
+%type<compoundStyle> struct_or_union_keyword
+
+%start program
+
+%union {
+    const char *str;
+    android::Type *type;
+    android::CompoundType *compoundType;
+    android::CompoundField *field;
+    android::Vector<android::CompoundField *> *fields;
+    android::EnumValue *enumValue;
+    android::Vector<android::EnumValue *> *enumValues;
+    android::TypedVar *typedVar;
+    android::Vector<android::TypedVar *> *typedVars;
+    android::Method *method;
+    android::CompoundType::Style compoundStyle;
+}
+
+%%
+
+program
+    : version package imports body
+    ;
+
+version
+    : VERSION INTEGER '.' INTEGER ';'
+
+package
+    : PACKAGE package_path ';'
+
+package_path
+    : IDENTIFIER
+    | package_path '.' IDENTIFIER
+    ;
+
+imports
+    : /* empty */
+    | imports IMPORT package_path ';'
+    ;
+
+opt_extends
+    : /* empty */ { $$ = NULL; }
+    | EXTENDS TYPENAME { $$ = $2; }
+
+body
+    : INTERFACE IDENTIFIER opt_extends
+      {
+          Interface *iface = new Interface($2, $3);
+          ast->enterScope(iface);
+      }
+      '{' interface_declarations '}' ';'
+      {
+          Interface *iface = static_cast<Interface *>(ast->scope());
+
+          ast->leaveScope();
+          ast->scope()->addType(iface);
+      }
+    | type_declarations
+    ;
+
+interface_declarations
+    : /* empty */
+    | interface_declarations type_declaration
+    | interface_declarations method_declaration
+      {
+          Interface *iface = static_cast<Interface *>(ast->scope());
+          iface->addMethod($2);
+      }
+    ;
+
+type_declarations
+    : type_declaration
+    | type_declarations type_declaration
+    ;
+
+type_declaration
+    : named_struct_or_union_declaration ';'
+    | named_enum_declaration ';'
+    | typedef_declaration ';'
+    | const_declaration ';'
+    ;
+
+typedef_declaration
+    : TYPEDEF type IDENTIFIER
+      {
+          TypeDef *def = new TypeDef($3, $2);
+          ast->scope()->addType(def);
+      }
+    ;
+
+const_value
+    : INTEGER
+    | STRING_LITERAL ;
+
+const_declaration
+    : CONST TYPENAME IDENTIFIER '=' const_value
+      {
+          Constant *constant = new Constant($3, $2, $5);
+          ast->scope()->addConstant(constant);
+      }
+    ;
+
+method_declaration
+    : IDENTIFIER '(' typed_vars ')' ';'
+      {
+          $$ = new Method($1, $3);
+      }
+    | IDENTIFIER '(' typed_vars ')' GENERATES '(' typed_vars ')' ';'
+      {
+          $$ = new Method($1, $3, $7);
+      }
+    ;
+
+typed_vars
+    : /* empty */
+      {
+          $$ = new Vector<TypedVar *>;
+      }
+    | typed_var
+      {
+          $$ = new Vector<TypedVar *>;
+          $$->push_back($1);
+      }
+    | typed_vars ',' typed_var
+      {
+          $$ = $1;
+          $$->push_back($3);
+      }
+    ;
+
+typed_var : type IDENTIFIER { $$ = new TypedVar($2, $1); }
+    ;
+
+
+struct_or_union_keyword
+    : STRUCT { $$ = CompoundType::STYLE_STRUCT; }
+    | UNION { $$ = CompoundType::STYLE_UNION; }
+    ;
+
+named_struct_or_union_declaration
+    : struct_or_union_keyword IDENTIFIER
+      {
+          CompoundType *container = new CompoundType($1, $2);
+          ast->enterScope(container);
+      }
+      struct_or_union_body
+      {
+          CompoundType *container = static_cast<CompoundType *>(ast->scope());
+
+          container->setFields($4);
+          ast->leaveScope();
+          ast->scope()->addType(container);
+      }
+    ;
+
+struct_or_union_declaration
+    : struct_or_union_keyword optIdentifier
+      {
+          CompoundType *container = new CompoundType($1, $2);
+          ast->enterScope(container);
+      }
+      struct_or_union_body
+      {
+          CompoundType *container = static_cast<CompoundType *>(ast->scope());
+
+          container->setFields($4);
+          ast->leaveScope();
+          ast->scope()->addType(container);
+
+          $$ = new RefType(container->name().c_str(), container);
+      }
+    ;
+
+struct_or_union_body
+    : '{' field_declarations '}' { $$ = $2; }
+    ;
+
+field_declarations
+    : /* empty */ { $$ = new Vector<CompoundField *>; }
+    | field_declarations field_declaration
+      {
+          $$ = $1;
+
+          if ($2 != NULL) {
+              $$->push_back($2);
+          }
+      }
+    ;
+
+field_declaration
+    : type IDENTIFIER ';' { $$ = new CompoundField($2, $1); }
+    | struct_or_union_declaration ';' { $$ = NULL; }
+    | enum_declaration ';' { $$ = NULL; }
+    ;
+
+opt_storage_type
+    : /* empty */ { $$ = NULL; }
+    | ':' TYPENAME { $$ = $2; }
+    ;
+
+opt_comma
+    : /* empty */
+    | ','
+    ;
+
+named_enum_declaration
+    : ENUM IDENTIFIER opt_storage_type '{' enum_values opt_comma '}'
+      {
+          EnumType *enumType = new EnumType($2, $5, $3);
+          ast->scope()->addType(enumType);
+      }
+    ;
+
+enum_declaration
+    : ENUM '{' enum_values opt_comma '}'
+      {
+          EnumType *enumType = new EnumType(NULL /* name */, $3);
+          ast->scope()->addType(enumType);
+
+          $$ = new RefType(enumType->name().c_str(), enumType);
+      }
+    | ENUM IDENTIFIER opt_storage_type '{' enum_values opt_comma '}'
+      {
+          EnumType *enumType = new EnumType($2, $5, $3);
+          ast->scope()->addType(enumType);
+
+          $$ = new RefType(enumType->name().c_str(), enumType);
+      }
+    ;
+
+enum_value
+    : IDENTIFIER { $$ = new EnumValue($1); }
+    | IDENTIFIER '=' INTEGER { $$ = new EnumValue($1, $3); }
+    | IDENTIFIER '=' IDENTIFIER { $$ = new EnumValue($1, $3); }
+    ;
+
+enum_values
+    : /* empty */
+      {
+          $$ = new Vector<EnumValue *>;
+      }
+    | enum_value
+      {
+          $$ = new Vector<EnumValue *>;
+          $$->push_back($1);
+      }
+    | enum_values ',' enum_value
+      {
+          $$ = $1;
+          $$->push_back($3);
+      }
+    ;
+
+type
+    : TYPENAME { $$ = $1; }
+    | TYPENAME '[' INTEGER ']' { $$ = new ArrayType($1, $3); }
+    | VEC '<' TYPENAME '>' { $$ = new VectorType($3); }
+    | struct_or_union_declaration { $$ = $1; }
+    | enum_declaration { $$ = $1; }
+    ;
+
+optIdentifier
+    : /* empty */ { $$ = NULL; }
+    | IDENTIFIER { $$ = $1; }
+    ;
+
+%%
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..9e29706
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,22 @@
+#include "AST.h"
+
+#include "Formatter.h"
+
+#include <stdio.h>
+
+using namespace android;
+
+int main(int argc, const char *const argv[]) {
+    AST *ast = AST::Parse(argv[1]);
+
+    Formatter out;
+
+    printf("========================================\n");
+
+    ast->dump(out);
+
+    delete ast;
+    ast = NULL;
+
+    return 0;
+}