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;
+}