diff --git a/CMakeLists.txt b/CMakeLists.txt
index caf4f63d0b12dec4fbd1882f70cddd441a7e5d91..621f88fbedbae5ef1a3f728cb4a8fcd87b51e38c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,6 +37,7 @@ ADD_REQUIRED_DEPENDENCY("eigen3 >= 3.0.5")
 ADD_OPTIONAL_DEPENDENCY("eigenpy >= 1.2.0")
 ADD_OPTIONAL_DEPENDENCY("metapod >= 1.0.7")
 ADD_OPTIONAL_DEPENDENCY("urdfdom >= 0.2.10")
+ADD_OPTIONAL_DEPENDENCY("lua5.1")
 
 SET(BOOST_COMPONENTS filesystem unit_test_framework)
 SEARCH_FOR_BOOST()
@@ -142,6 +143,18 @@ IF(URDFDOM_FOUND)
     )
 ENDIF(URDFDOM_FOUND)
 
+IF(LUA5_1_FOUND)
+  LIST(APPEND HEADERS 
+    multibody/parser/lua.hpp
+    multibody/parser/lua/lua_tables.hpp
+    )
+
+  SET(${PROJECT_NAME}_MULTIBODY_PARSER_LUA_HEADERS
+    multibody/parser/lua.hpp
+    multibody/parser/lua/lua_tables.hpp
+    )
+ENDIF(LUA5_1_FOUND)
+
 PKG_CONFIG_APPEND_LIBS (${PROJECT_NAME})
 
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio")
@@ -150,6 +163,7 @@ MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/spatial")
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/multibody")
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/multibody/joint")
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/multibody/parser")
+MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/multibody/parser/lua")
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/tools")
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/algorithm")
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/simulation")
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5d4854d8eed4b97d893f6382abdce1771c65c355..ae99dfab1c8d11d269e133a2f47127cd15c56040 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -18,6 +18,36 @@ MACRO(ADD_SOURCE_GROUP FILENAMES)
   ADD_GROUP("Source Files" ${FILENAMES})
 ENDMACRO(ADD_SOURCE_GROUP FILENAMES)
 
+# ----------------------------------------------------
+# --- C++ --------------------------------------------
+# ----------------------------------------------------
+
+IF(LUA5_1_FOUND)
+  SET(${PROJECT_NAME}_MULTIBODY_PARSER_LUA_SOURCES 
+      multibody/parser/lua/lua_tables.cpp
+      multibody/parser/lua.cpp
+    )
+ENDIF(LUA5_1_FOUND)
+
+SET(${PROJECT_NAME}_SOURCES ${${PROJECT_NAME}_MULTIBODY_PARSER_LUA_SOURCES}) 
+
+IF (UNIX )  
+    # Create target libpinocchio.so
+    ADD_LIBRARY ( ${PROJECT_NAME} SHARED ${HEADERS} ${${PROJECT_NAME}_SOURCES} )
+		SET_TARGET_PROPERTIES( ${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX)
+
+    IF(LUA5_1_FOUND)
+      PKG_CONFIG_USE_DEPENDENCY(${PROJECT_NAME} lua5.1)
+    ENDIF(LUA5_1_FOUND)
+    
+    ADD_HEADER_GROUP(HEADERS)  
+    ADD_SOURCE_GROUP(${PROJECT_NAME}_SOURCES)  
+
+    # Install target libpinocchio.so
+    INSTALL(FILES
+      "${CMAKE_BINARY_DIR}/src/lib${PROJECT_NAME}.so"
+      DESTINATION ${CMAKE_INSTALL_LIBDIR})
+ENDIF ( )
 
 # ----------------------------------------------------
 # --- PYTHON -----------------------------------------
@@ -33,9 +63,11 @@ IF(EIGENPY_FOUND)
   PKG_CONFIG_USE_DEPENDENCY(${PYWRAP} eigenpy)
   IF(URDFDOM_FOUND)
     PKG_CONFIG_USE_DEPENDENCY(${PYWRAP} urdfdom)
-      
   ENDIF(URDFDOM_FOUND)
-  TARGET_LINK_LIBRARIES(${PYWRAP} ${Boost_LIBRARIES} eigenpy)
+  IF(LUA5_1_FOUND)
+    PKG_CONFIG_USE_DEPENDENCY(${PYWRAP} lua5.1)
+  ENDIF(LUA5_1_FOUND)
+  TARGET_LINK_LIBRARIES(${PYWRAP} ${Boost_LIBRARIES} ${PROJECT_NAME})
   SET_TARGET_PROPERTIES(${PYWRAP} PROPERTIES
     LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/python/${PROJECT_NAME}")
   INSTALL(FILES
@@ -81,17 +113,3 @@ IF(EIGENPY_FOUND)
 
 ENDIF(EIGENPY_FOUND)
 
-IF (UNIX )  
-    # Create target libpinocchio.so
-    ADD_LIBRARY ( ${PROJECT_NAME} SHARED ${HEADERS} ${${PROJECT_NAME}_SOURCES} )
-		SET_TARGET_PROPERTIES( ${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX)
-    
-		ADD_HEADER_GROUP(HEADERS)  
-		ADD_SOURCE_GROUP(${PROJECT_NAME}_SOURCES)  
-
-    # Install target libpinocchio.so
-    INSTALL(FILES
-      "${CMAKE_BINARY_DIR}/src/lib${PROJECT_NAME}.so"
-      DESTINATION ${CMAKE_INSTALL_LIBDIR})
-
-ENDIF ( )
diff --git a/src/multibody/parser/lua.cpp b/src/multibody/parser/lua.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2f3a880c231e97d33de509bdf14e0a3c6f4e9fde
--- /dev/null
+++ b/src/multibody/parser/lua.cpp
@@ -0,0 +1,313 @@
+
+#include "pinocchio/multibody/parser/lua/lua_tables.hpp"
+#include "pinocchio/multibody/parser/lua.hpp"
+
+#include <lua.hpp>
+#include <iostream>
+#include <map>
+#include <sstream>
+
+#include "pinocchio/spatial/se3.hpp"
+#include "pinocchio/spatial/motion.hpp"
+#include "pinocchio/spatial/inertia.hpp"
+#include "pinocchio/multibody/model.hpp"
+
+typedef se3::SE3::Vector3 Vector3;
+typedef se3::SE3::Matrix3 Matrix3;
+
+template<> Vector3 LuaTableNode::getDefault<Vector3> (const Vector3 & default_value)
+{
+  Vector3 result (default_value);
+
+  if (stackQueryValue()) {
+    LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
+
+    if (vector_table.length() != 3) {
+      std::cerr << "LuaModel Error: invalid 3d vector!" << std::endl;
+      abort();
+    }
+
+    result[0] = vector_table[1];
+    result[1] = vector_table[2];
+    result[2] = vector_table[3];
+  }
+
+  stackRestore();
+
+  return result;
+}
+
+template<> Matrix3 LuaTableNode::getDefault<Matrix3> (const Matrix3 & default_value)
+{
+  Matrix3 result (default_value);
+
+  if (stackQueryValue()) {
+    LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
+
+    if (vector_table.length() != 3) {
+      std::cerr << "LuaModel Error: invalid 3d matrix!" << std::endl;
+      abort();
+    }
+
+    if (vector_table[1].length() != 3
+        || vector_table[2].length() != 3
+        || vector_table[3].length() != 3) {
+      std::cerr << "LuaModel Error: invalid 3d matrix!" << std::endl;
+      abort();
+    }
+
+    result(0,0) = vector_table[1][1];
+    result(0,1) = vector_table[1][2];
+    result(0,2) = vector_table[1][3];
+
+    result(1,0) = vector_table[2][1];
+    result(1,1) = vector_table[2][2];
+    result(1,2) = vector_table[2][3];
+
+    result(2,0) = vector_table[3][1];
+    result(2,1) = vector_table[3][2];
+    result(2,2) = vector_table[3][3];
+  }
+
+  stackRestore();
+
+  return result;
+}
+
+template<> se3::SE3 LuaTableNode::getDefault<se3::SE3> (const se3::SE3 & default_value)
+{
+  se3::SE3 result (default_value);
+
+  if (stackQueryValue()) {
+    LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
+
+    result.translation() = vector_table["r"].getDefault<Vector3> (Vector3::Zero (3));
+    result.rotation().transpose() = vector_table["E"].getDefault<Matrix3> (Matrix3::Identity (3,3));
+  }
+
+  stackRestore();
+
+  return result;
+}
+
+template<> se3::Inertia LuaTableNode::getDefault<se3::Inertia> (const se3::Inertia & default_value)
+{
+  se3::Inertia result (default_value);
+
+  if (stackQueryValue()) {
+    LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
+
+    double mass = 0.;
+    Vector3 com;
+    Matrix3 inertia_matrix;
+
+    mass = vector_table["mass"];
+    com = vector_table["com"].getDefault<Vector3> (Vector3::Zero ());
+    inertia_matrix = vector_table["inertia"].getDefault<Matrix3> (Matrix3::Identity ());
+
+    result = se3::Inertia (mass, com, inertia_matrix);
+  }
+
+  stackRestore();
+
+  return result;
+}
+
+namespace se3
+{
+  namespace lua
+  {
+    bool LuaModelReadFromTable (LuaTable & model_table, Model & model, bool freeFlyer, bool verbose)
+    {
+      typedef std::map<std::string, Model::Index> mapStringIndex_t;
+      mapStringIndex_t body_table_id_map;
+      mapStringIndex_t fixed_body_table_id_map;
+
+      typedef std::map<std::string, SE3> mapStringSE3_t;
+      mapStringSE3_t fixed_placement_map;
+
+      if (model_table["gravity"].exists())
+      {
+        model.gravity.linear() = model_table["gravity"].get<Vector3> ();
+
+        if (verbose)
+          std::cout << "gravity = " << model.gravity.linear().transpose() << std::endl;
+      }
+
+      if (! model_table["frames"].exists())
+      {
+        std::cerr << "Frames table missing from model table - Abort" << std::endl;
+        abort();
+      }
+
+      size_t frame_count = model_table["frames"].length();
+
+      body_table_id_map["ROOT"] = 0;
+
+      for (int i = 1; i <= (int) frame_count; i++) {
+
+        std::stringstream body_name_default;
+        body_name_default << "body " << i;
+        std::string body_name = model_table["frames"][i]["name"].getDefault<std::string> (body_name_default.str());
+
+        std::string parent_name;
+        if (model_table["frames"][i]["parent"].exists ())
+        {
+          parent_name = model_table["frames"][i]["parent"].get<std::string> ();
+        }
+        else if (i == 1) // first body of the tree
+        {
+          parent_name = "ROOT";
+        }
+        else // no parent defined
+        {
+          std::cerr << "Parent not defined for frame " << i << "." << std::endl;
+          abort();
+        }
+
+        Model::Index parent_id;
+        SE3 fixed_placement_offset (SE3::Identity());;
+
+        if (body_table_id_map.find (parent_name) != body_table_id_map.end ())
+        {
+          parent_id = body_table_id_map[parent_name];
+        }
+        else if (fixed_body_table_id_map.find(parent_name) != fixed_body_table_id_map.end ()) // the parent is fixed in the kinematic tree
+        {
+          parent_id = fixed_body_table_id_map[parent_name];
+          fixed_placement_offset = fixed_placement_map[parent_name];
+        }
+        else
+        {
+          std::cerr << parent_name << " is not in the tree." << std::endl;
+          abort ();
+        }
+
+
+        std::stringstream joint_name_default;
+        joint_name_default << "joint " << i;
+        std::string joint_name = model_table["frames"][i]["joint_name"].getDefault<std::string> (joint_name_default.str());
+
+        
+        SE3 joint_placement = model_table["frames"][i]["joint_frame"].getDefault<SE3> (SE3::Identity ());
+        SE3 global_placement (fixed_placement_offset * joint_placement); // placement due to the existence of fixed bodies
+
+        if (! model_table["frames"][i]["body"].exists()) {
+          std::cerr << "body field not defined for frame " << i << "." << std::endl;
+          abort();
+        }
+
+        Inertia Y = model_table["frames"][i]["body"].getDefault<Inertia> (Inertia::Identity ());
+
+        std::string joint_type;
+        if (model_table["frames"][i]["joint"].exists())
+        {
+          if (model_table["frames"][i]["joint"].length() == 1)
+            joint_type = model_table["frames"][i]["joint"][1].getDefault<std::string> ("");
+          else
+            std::cerr << "Joint compouned not implemented yet. Take only the first joint." << std::endl;
+        }
+        else if (i == 1) // first body of the tree
+        {
+          if (freeFlyer)
+            joint_type = "jointFreeFlyer";
+          else
+          {
+            std::cerr << "The first segment is defined without any definition of joint type relatily to the environment." << std::endl;
+            abort ();
+          }
+        }
+        else
+        {
+          std::cerr << "joint field not defined for frame " << i << "." << std::endl;
+          abort();
+        }
+
+
+        Model::Index body_id;
+        bool is_body_fixed = false;
+        if (joint_type == "jointRX")
+        {
+          body_id = model.addBody (parent_id, JointModelRX (), global_placement, Y, joint_name, body_name, false);
+        }
+        else if (joint_type == "jointRY")
+        {
+          body_id = model.addBody (parent_id, JointModelRY (), global_placement, Y, joint_name, body_name, false);
+        }
+        else if (joint_type == "jointRZ")
+        {
+          body_id = model.addBody (parent_id, JointModelRZ (), global_placement, Y, joint_name, body_name, false);
+        }
+        else if (joint_type == "jointPX")
+        {
+          body_id = model.addBody (parent_id, JointModelPX (), global_placement, Y, joint_name, body_name, false);
+        }
+        else if (joint_type == "jointPY")
+        {
+          body_id = model.addBody (parent_id, JointModelPY (), global_placement, Y, joint_name, body_name, false);
+        }
+        else if (joint_type == "jointPZ")
+        {
+          body_id = model.addBody (parent_id, JointModelPZ (), global_placement, Y, joint_name, body_name, false);
+        }
+        else if (joint_type == "jointFreeFlyer")
+        {
+          body_id = model.addBody (parent_id, JointModelFreeFlyer (), global_placement, Y, joint_name, body_name, false);
+        }
+        else if (joint_type == "jointSpherical")
+        {
+          body_id = model.addBody (parent_id, JointModelSpherical (), global_placement, Y, joint_name, body_name, false);
+        }
+        else if (joint_type == "jointSphericalZYX")
+        {
+          body_id = model.addBody (parent_id, JointModelSphericalZYX (), global_placement, Y, joint_name, body_name, false);
+        }
+        else if (joint_type == "jointFixed")
+        {
+          model.mergeFixedBody(parent_id, global_placement, Y);
+
+          fixed_body_table_id_map[body_name] = parent_id;
+          fixed_placement_map[body_name] = global_placement;
+
+          body_id = model.addFixedBody(parent_id, global_placement, body_name, false);
+          is_body_fixed = true;
+        }
+        else
+        {
+          std::cerr << joint_type << " is not supported.." << std::endl;
+          abort ();
+        }
+
+        body_table_id_map[body_name] = body_id;
+
+        if (verbose) {
+          std::cout << "==== Added Body ====" << std::endl;
+          std::cout << "  body name  : " << body_name << std::endl;
+          if (! is_body_fixed)
+            std::cout << "  body id    : " << body_id << std::endl;
+          else
+            std::cout << "  fixed body id    : " << body_id << std::endl;
+          std::cout << "  closest parent id  : " << parent_id << std::endl;
+          std::cout << "  joint frame:\n" << joint_placement << std::endl;
+          std::cout << "  joint type : " << joint_type << std::endl;
+          std::cout << "  joint name : " << joint_name << std::endl;
+          std::cout << "  body inertia:\n" << Y << std::endl;
+        }
+      }
+      
+      return true;
+    }
+
+    Model buildModel (const std::string & filename, bool freeFlyer, bool verbose)
+    {
+      Model model;
+
+      LuaTable model_table = LuaTable::fromFile (filename.c_str ());
+      LuaModelReadFromTable (model_table, model, freeFlyer, verbose);
+
+      return model;
+    }
+
+  } // namespace lua
+
+} // namespace se3
diff --git a/src/multibody/parser/lua.hpp b/src/multibody/parser/lua.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..259598442a351827d62bb3109258230eb8dfc613
--- /dev/null
+++ b/src/multibody/parser/lua.hpp
@@ -0,0 +1,15 @@
+#ifndef __se3_lua_hpp__
+#define __se3_lua_hpp__
+
+#include <iostream>
+#include "pinocchio/multibody/model.hpp"
+
+namespace se3
+{
+  namespace lua
+  {
+    Model buildModel (const std::string & filename, bool freeFlyer = false, bool verbose = false);
+  } // namespace lua
+} // namespace se3
+
+#endif // ifndef __se3_lua_hpp__
diff --git a/src/multibody/parser/lua/lua_tables.cpp b/src/multibody/parser/lua/lua_tables.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..11f4b6235e982f312a030e05ca019a593db38ee6
--- /dev/null
+++ b/src/multibody/parser/lua/lua_tables.cpp
@@ -0,0 +1,850 @@
+/*
+ * LuaTables++
+ * Code comming from https://bitbucket.org/rbdl/rbdl
+ * Copyright (c) 2013-2014 Martin Felis <martin@fyxs.org>.
+ * Copyright (c) 2015 Justin Carpentier <jcarpent@laas.fr>
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "pinocchio/multibody/parser/lua/lua_tables.hpp"
+
+#include <assert.h>
+#include <iostream>
+#include <cstdlib>
+#include <vector>
+#include <sstream>
+#include <cmath>
+
+#include <lua.hpp>
+
+#include <stdio.h>  /* defines FILENAME_MAX */
+#ifdef WINDOWS
+#include <direct.h>
+#define get_current_dir _getcwd
+#else
+#include <unistd.h>
+#define get_current_dir getcwd
+#endif
+
+#if defined(WIN32) || defined (_WIN32)
+#define DIRECTORY_SEPARATOR "\\"
+#elif defined(linux) || defined (__linux) || defined(__linux__) || defined(__APPLE__)
+#define DIRECTORY_SEPARATOR "/"
+#else
+#error Platform not supported!
+#endif
+
+using namespace std;
+
+std::string get_file_directory (const char* filename)
+{
+  string name (filename);
+  string result = name.substr(0, name.find_last_of (DIRECTORY_SEPARATOR) + 1);
+
+  if (result == "")
+    result = "./";
+#if defined (WIN32) || defined (_WIN32)
+#warning get_file_directory() not yet tested under Windows!
+  else if (result.substr(1,2) != ":\\")
+    result = string(".\\") + result;
+#else
+  else if (result.substr(0,string(DIRECTORY_SEPARATOR).size()) != DIRECTORY_SEPARATOR  && result[0] != '.')
+    result = string("./") + result;
+#endif
+
+  return result;
+}
+
+// char encoded serialize function that is available in plaintext in
+// utils/serialize.lua. Converted using lua auto.lua serialize.lua
+const char serialize_std[] = {
+
+  0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x6c,
+  0x69, 0x73, 0x74, 0x20, 0x28, 0x74, 0x29, 0x0a,
+  0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x74, 0x65, 0x6d, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x3d,
+  0x20, 0x30, 0x0a,
+  0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d,
+  0x20, 0x6e, 0x69, 0x6c, 0x0a,
+  0x09, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x2c, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x28,
+  0x74, 0x29, 0x20, 0x64, 0x6f, 0x0a,
+  0x09, 0x09, 0x69, 0x74, 0x65, 0x6d, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x69, 0x74, 0x65, 0x6d,
+  0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x2b, 0x20, 0x31, 0x0a,
+  0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x3d, 0x20,
+  0x6e, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x09, 0x09, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x74, 0x79, 0x70,
+  0x65, 0x28, 0x76, 0x29, 0x0a,
+  0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
+  0x09, 0x09, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x76, 0x29, 0x20, 0x7e, 0x3d, 0x20, 0x6c, 0x61,
+  0x73, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x28, 0x74, 0x79, 0x70, 0x65, 0x28, 0x76,
+  0x29, 0x20, 0x7e, 0x3d, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x20, 0x61, 0x6e, 0x64, 0x20,
+  0x74, 0x79, 0x70, 0x65, 0x28, 0x76, 0x29, 0x20, 0x7e, 0x3d, 0x20, 0x22, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
+  0x22, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x76, 0x29, 0x20, 0x7e, 0x3d, 0x20, 0x22,
+  0x62, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x22, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28,
+  0x76, 0x29, 0x20, 0x7e, 0x3d, 0x20, 0x22, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65,
+  0x6e, 0x0a,
+  0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x0a,
+  0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
+  0x09, 0x0a,
+  0x09, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x74, 0x79, 0x70, 0x65,
+  0x28, 0x76, 0x29, 0x0a,
+  0x09, 0x65, 0x6e, 0x64, 0x0a,
+  0x09, 0x69, 0x66, 0x20, 0x69, 0x74, 0x65, 0x6d, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x7e, 0x3d, 0x20, 0x23,
+  0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x0a,
+  0x09, 0x65, 0x6e, 0x64, 0x0a,
+  0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a,
+  0x65, 0x6e, 0x64, 0x0a,
+  0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6d, 0x70,
+  0x5f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x28, 0x61, 0x2c, 0x20,
+  0x62, 0x29, 0x0a,
+  0x09, 0x69, 0x66, 0x20, 0x28, 0x74, 0x79, 0x70, 0x65, 0x28, 0x61, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x73,
+  0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x62, 0x29,
+  0x20, 0x3d, 0x3d, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x79,
+  0x70, 0x65, 0x28, 0x61, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x20,
+  0x61, 0x6e, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x62, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x6e, 0x75,
+  0x6d, 0x62, 0x65, 0x72, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x3c, 0x20, 0x62, 0x0a,
+  0x09, 0x65, 0x6c, 0x73, 0x65, 0x0a,
+  0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x61, 0x29, 0x20, 0x3c,
+  0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x62, 0x29, 0x0a,
+  0x09, 0x65, 0x6e, 0x64, 0x0a,
+  0x65, 0x6e, 0x64, 0x0a,
+  0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x65, 0x6e,
+  0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x20, 0x28,
+  0x74, 0x29, 0x0a,
+  0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x64,
+  0x69, 0x63, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a,
+  0x09, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x20, 0x28, 0x74,
+  0x29, 0x20, 0x64, 0x6f, 0x0a,
+  0x09, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x20, 0x28, 0x6f, 0x72,
+  0x64, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x2c, 0x20, 0x6b, 0x29, 0x0a,
+  0x09, 0x65, 0x6e, 0x64, 0x0a,
+  0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x73, 0x6f, 0x72, 0x74, 0x20, 0x28, 0x6f, 0x72, 0x64, 0x65, 0x72,
+  0x65, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x2c, 0x20, 0x63, 0x6d, 0x70, 0x5f, 0x61, 0x6c,
+  0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x29, 0x0a,
+  0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x69, 0x6e,
+  0x64, 0x69, 0x63, 0x65, 0x73, 0x0a,
+  0x65, 0x6e, 0x64, 0x0a,
+  0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x64,
+  0x65, 0x72, 0x65, 0x64, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x20, 0x28, 0x74, 0x2c, 0x20, 0x73, 0x74, 0x61, 0x74,
+  0x65, 0x29, 0x0a,
+  0x09, 0x69, 0x66, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74,
+  0x68, 0x65, 0x6e, 0x0a,
+  0x09, 0x09, 0x74, 0x2e, 0x5f, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63,
+  0x65, 0x73, 0x20, 0x3d, 0x20, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x69,
+  0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x20, 0x28, 0x74, 0x29, 0x0a,
+  0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x3d, 0x20, 0x74, 0x2e, 0x5f, 0x5f,
+  0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x5b, 0x31, 0x5d, 0x0a,
+  0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6b, 0x65, 0x79, 0x2c, 0x20, 0x74, 0x5b, 0x6b, 0x65,
+  0x79, 0x5d, 0x0a,
+  0x09, 0x65, 0x6e, 0x64, 0x0a,
+  0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a,
+  0x09, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x31, 0x2c, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e,
+  0x67, 0x65, 0x74, 0x6e, 0x28, 0x74, 0x2e, 0x5f, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x49, 0x6e,
+  0x64, 0x69, 0x63, 0x65, 0x73, 0x29, 0x20, 0x64, 0x6f, 0x0a,
+  0x09, 0x09, 0x69, 0x66, 0x20, 0x74, 0x2e, 0x5f, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x49, 0x6e,
+  0x64, 0x69, 0x63, 0x65, 0x73, 0x5b, 0x69, 0x5d, 0x20, 0x3d, 0x3d, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20,
+  0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x09, 0x09, 0x09, 0x6b, 0x65, 0x79, 0x20, 0x3d, 0x20, 0x74, 0x2e, 0x5f, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72,
+  0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x5b, 0x69, 0x20, 0x2b, 0x20, 0x31, 0x5d, 0x0a,
+  0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
+  0x09, 0x65, 0x6e, 0x64, 0x0a,
+  0x09, 0x69, 0x66, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6b, 0x65, 0x79, 0x2c, 0x20, 0x74, 0x5b, 0x6b, 0x65,
+  0x79, 0x5d, 0x0a,
+  0x09, 0x65, 0x6e, 0x64, 0x0a,
+  0x09, 0x74, 0x2e, 0x5f, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65,
+  0x73, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a,
+  0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a,
+  0x65, 0x6e, 0x64, 0x0a,
+  0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x64,
+  0x65, 0x72, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x69, 0x72, 0x73, 0x20, 0x28, 0x74, 0x29, 0x0a,
+  0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x6e, 0x65,
+  0x78, 0x74, 0x2c, 0x20, 0x74, 0x2c, 0x20, 0x6e, 0x69, 0x6c, 0x0a,
+  0x65, 0x6e, 0x64, 0x0a,
+  0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65,
+  0x20, 0x28, 0x6f, 0x2c, 0x20, 0x74, 0x61, 0x62, 0x73, 0x2c, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x29, 0x0a,
+  0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x22,
+  0x22, 0x0a,
+  0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x20,
+  0x3d, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x0a,
+  0x09, 0x69, 0x66, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x09, 0x09, 0x70, 0x61, 0x69, 0x72, 0x73, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x20, 0x3d, 0x20, 0x6f, 0x72, 0x64,
+  0x65, 0x72, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x69, 0x72, 0x73, 0x0a,
+  0x09, 0x65, 0x6e, 0x64, 0x0a,
+  0x20, 0x20, 0x0a,
+  0x20, 0x20, 0x69, 0x66, 0x20, 0x74, 0x61, 0x62, 0x73, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74,
+  0x68, 0x65, 0x6e, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x74, 0x61, 0x62, 0x73, 0x20, 0x3d, 0x20, 0x22, 0x22, 0x0a,
+  0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
+  0x20, 0x20, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x6f, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x6e,
+  0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c,
+  0x74, 0x20, 0x2e, 0x2e, 0x20, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x6f, 0x29, 0x0a,
+  0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x6f, 0x29, 0x20, 0x3d,
+  0x3d, 0x20, 0x22, 0x62, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c,
+  0x74, 0x20, 0x2e, 0x2e, 0x20, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x6f, 0x29, 0x0a,
+  0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x6f, 0x29, 0x20, 0x3d,
+  0x3d, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c,
+  0x74, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74,
+  0x28, 0x22, 0x25, 0x71, 0x22, 0x2c, 0x20, 0x6f, 0x29, 0x0a,
+  0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x6f, 0x29, 0x20, 0x3d, 0x3d,
+  0x20, 0x22, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x6c, 0x69, 0x73,
+  0x74, 0x28, 0x6f, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x09, 0x09, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20,
+  0x2e, 0x2e, 0x20, 0x22, 0x7b, 0x22, 0x0a,
+  0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x77, 0x61, 0x73, 0x5f, 0x73,
+  0x75, 0x62, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x0a,
+  0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x2c, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72,
+  0x73, 0x28, 0x6f, 0x29, 0x20, 0x64, 0x6f, 0x0a,
+  0x09, 0x09, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x77, 0x61, 0x73, 0x5f, 0x73, 0x75, 0x62, 0x74, 0x61, 0x62,
+  0x6c, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x0a,
+  0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x76, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x22,
+  0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x09, 0x09, 0x09, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x77, 0x61, 0x73, 0x5f, 0x73, 0x75, 0x62, 0x74, 0x61,
+  0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x72,
+  0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x5c, 0x6e, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x74,
+  0x61, 0x62, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x72,
+  0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x28, 0x76, 0x2c, 0x20, 0x74, 0x61, 0x62, 0x73, 0x20, 0x2e, 0x2e, 0x20,
+  0x22, 0x20, 0x20, 0x22, 0x2c, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x22,
+  0x2c, 0x22, 0x0a,
+  0x09, 0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0a,
+  0x09, 0x09, 0x09, 0x09, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c,
+  0x74, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69,
+  0x6e, 0x67, 0x28, 0x76, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x2c, 0x22, 0x0a,
+  0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
+  0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
+  0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x77, 0x61, 0x73, 0x5f, 0x73, 0x75, 0x62, 0x74,
+  0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x09, 0x09, 0x09, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74,
+  0x20, 0x2e, 0x2e, 0x20, 0x22, 0x5c, 0x6e, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x74, 0x61, 0x62, 0x73, 0x0a,
+  0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
+  0x09, 0x09, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20,
+  0x2e, 0x2e, 0x20, 0x22, 0x7d, 0x22, 0x0a,
+  0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x6f, 0x29, 0x20, 0x3d,
+  0x3d, 0x20, 0x22, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6f, 0x2e, 0x64, 0x6f, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x69,
+  0x61, 0x6c, 0x69, 0x7a, 0x65, 0x5f, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x22, 0x7b, 0x7d, 0x22, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c,
+  0x74, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x7b, 0x5c, 0x6e, 0x22, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x2c, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x69,
+  0x72, 0x73, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6f, 0x29, 0x20, 0x64, 0x6f, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x76, 0x29, 0x20, 0x7e,
+  0x3d, 0x20, 0x22, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x73, 0x75,
+  0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x64, 0x20, 0x6b,
+  0x65, 0x79, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x6c, 0x79, 0x20, 0x61,
+  0x72, 0x65, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x69, 0x66, 0x69, 0x65, 0x64, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x6b, 0x29,
+  0x20, 0x3d, 0x3d, 0x20, 0x22, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x09, 0x09, 0x09, 0x09, 0x20, 0x20, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x76, 0x29, 0x20, 0x3d,
+  0x3d, 0x20, 0x22, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+  0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20,
+  0x3d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x2e, 0x2e, 0x20, 0x74, 0x61, 0x62, 0x73, 0x20, 0x2e,
+  0x2e, 0x20, 0x22, 0x20, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x5b, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x74,
+  0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x6b, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x5d, 0x20, 0x3d,
+  0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x76, 0x29, 0x20,
+  0x2e, 0x2e, 0x20, 0x22, 0x2c, 0x5c, 0x6e, 0x22, 0x0a,
+  0x09, 0x09, 0x09, 0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0a,
+  0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20,
+  0x3d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x2e, 0x2e, 0x20, 0x74, 0x61, 0x62, 0x73, 0x20, 0x2e,
+  0x2e, 0x20, 0x22, 0x20, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x5b, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x74,
+  0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x6b, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x5d, 0x20, 0x3d,
+  0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x28, 0x76, 0x2c,
+  0x20, 0x74, 0x61, 0x62, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x20, 0x22, 0x2c, 0x20, 0x73, 0x6f, 0x72,
+  0x74, 0x65, 0x64, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x2c, 0x5c, 0x6e, 0x22, 0x0a,
+  0x09, 0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d,
+  0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x2e, 0x2e, 0x20, 0x74, 0x61, 0x62, 0x73, 0x20, 0x2e, 0x2e,
+  0x20, 0x22, 0x20, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x6b, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x3d, 0x20,
+  0x22, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x28, 0x76, 0x2c, 0x20,
+  0x74, 0x61, 0x62, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x20, 0x22, 0x2c, 0x20, 0x73, 0x6f, 0x72, 0x74,
+  0x65, 0x64, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x2c, 0x5c, 0x6e, 0x22, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c,
+  0x74, 0x20, 0x2e, 0x2e, 0x20, 0x74, 0x61, 0x62, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x7d, 0x22, 0x0a,
+  0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x20, 0x28, 0x22, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x65,
+  0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x6f, 0x66,
+  0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x6f, 0x29,
+  0x20, 0x29, 0x0a,
+  0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
+  0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x0a,
+  0x65, 0x6e, 0x64, 0x0a,
+  0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x0a,
+};
+
+//
+// Lua Helper Functions
+//
+void bail(lua_State * L, const char *msg)
+{
+  std::cerr << msg << lua_tostring(L, -1) << endl;
+  abort();
+}
+
+void stack_print (const char *file, int line, lua_State * L)
+{
+  cout << file << ":" << line << ": stack size: " << lua_gettop(L) << endl;;
+  for (int i = 1; i < lua_gettop(L) + 1; i++) {
+    cout << file << ":" << line << ": ";
+    cout << i << ": ";
+    if (lua_istable (L, i))
+      cout << " table" << endl;
+    else if (lua_isnumber (L, i))
+      cout << " number: " << lua_tonumber (L, i) << endl;
+    else if (lua_isuserdata (L, i)) {
+      void* userdata = (void*) lua_touserdata (L, i);
+      cout << " userdata (" << userdata << ")" << endl;
+    } else if (lua_isstring (L, i))
+      cout << " string: " << lua_tostring(L, i) << endl;
+    else if (lua_isfunction (L, i))
+      cout << " function" << endl;
+    else if (lua_isnil (L, i))
+      cout << " nil" << endl;
+    else
+      cout << " unknown: " << lua_typename (L, lua_type (L, i)) << endl;
+  }
+}
+
+void l_push_LuaKey (lua_State * L, const LuaKey & key)
+{
+  if (key.type == LuaKey::Integer)
+    lua_pushnumber (L, key.int_value);
+  else
+    lua_pushstring(L, key.string_value.c_str());
+}
+
+bool query_key_stack (lua_State * L, std::vector<LuaKey> key_stack)
+{
+  for (int i = (int)key_stack.size() - 1; i >= 0; i--) {
+    // get the global value when the result of a lua expression was not
+    // pushed onto the stack via the return statement.
+    if (lua_gettop(L) == 0) {
+      lua_getglobal (L, key_stack[key_stack.size() - 1].string_value.c_str());
+
+      if (lua_isnil(L, -1)) {
+        return false;
+      }
+
+      continue;
+    }
+
+    l_push_LuaKey (L, key_stack[(size_t) i]);
+
+    lua_gettable (L, -2);
+
+    // return if key is not found
+    if (lua_isnil(L, -1)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void create_key_stack (lua_State * L, std::vector<LuaKey> key_stack)
+{
+  for (size_t i = key_stack.size() - 1; i > 0; i--) {
+    // get the global value when the result of a lua expression was not
+    // pushed onto the stack via the return statement.
+    if (lua_gettop(L) == 0) {
+      lua_getglobal (L, key_stack[key_stack.size() - 1].string_value.c_str());
+
+      if (lua_isnil(L, -1)) {
+        lua_pop(L, 1);
+        lua_newtable(L);
+        lua_pushvalue(L, -1);
+        lua_setglobal(L, key_stack[key_stack.size() - 1].string_value.c_str());
+      }
+
+      continue;
+    }
+
+    l_push_LuaKey (L, key_stack[i]);
+
+    lua_pushvalue (L, -1);
+    lua_gettable (L, -3);
+
+    if (lua_isnil(L, -1)) {
+      // parent, key, nil
+      lua_pop(L, 1);  // parent, key
+      lua_newtable(L); // parent, key, table
+      lua_insert(L, -2); // parent, table, key
+      lua_pushvalue(L, -2); // parent, table, key, table
+      lua_settable (L, -4); // parent, table
+    }
+  }
+}
+
+//
+// LuaTableNode
+//
+std::vector<LuaKey> LuaTableNode::getKeyStack()
+{
+  std::vector<LuaKey> result;
+
+  const LuaTableNode *node_ptr = this;
+
+  do {
+    result.push_back (node_ptr->key);
+    node_ptr = node_ptr->parent;
+  } while (node_ptr != NULL);
+
+  return result;
+}
+
+std::string LuaTableNode::keyStackToString()
+{
+  std::vector<LuaKey> key_stack = getKeyStack();
+
+  ostringstream result_stream ("");
+  for (int i = (int)key_stack.size() - 1; i >= 0; i--) {
+    if (key_stack[(size_t) i].type == LuaKey::String)
+      result_stream << "[\"" << key_stack[(size_t) i].string_value << "\"]";
+    else
+      result_stream << "[" << key_stack[(size_t) i].int_value << "]";
+  }
+
+  return result_stream.str();
+}
+
+bool LuaTableNode::stackQueryValue()
+{
+  lua_State * L = luaTable->L;
+  stackTop = lua_gettop(L);
+
+  std::vector<LuaKey> key_stack = getKeyStack();
+
+  return query_key_stack (L, key_stack);
+}
+
+void LuaTableNode::stackCreateValue()
+{
+  lua_State * L = luaTable->L;
+  stackTop = lua_gettop(L);
+
+  std::vector<LuaKey> key_stack = getKeyStack();
+
+  create_key_stack (L, key_stack);
+}
+
+LuaTable LuaTableNode::stackQueryTable()
+{
+  lua_State * L = luaTable->L;
+  stackTop = lua_gettop(L);
+
+  std::vector<LuaKey> key_stack = getKeyStack();
+
+  if (!query_key_stack (L, key_stack)) {
+    std::cerr << "Error: could not query table " << key << "." << std::endl;
+    abort();
+  }
+
+  return LuaTable::fromLuaState (L);
+}
+
+LuaTable LuaTableNode::stackCreateLuaTable()
+{
+  lua_State * L = luaTable->L;
+  stackTop = lua_gettop(L);
+
+  std::vector<LuaKey> key_stack = getKeyStack();
+
+  create_key_stack (L, key_stack);
+
+  // create new table for the CustomType
+  lua_newtable(luaTable->L);	// parent, CustomTable
+  // add table of CustomType to the parent
+  stackPushKey(); // parent, CustomTable, key
+  lua_pushvalue(luaTable->L, -2); // parent, CustomTable, key, CustomTable
+  lua_settable(luaTable->L, -4);
+
+  return LuaTable::fromLuaState (L);
+}
+
+void LuaTableNode::stackPushKey()
+{
+  l_push_LuaKey (luaTable->L, key);
+}
+
+void LuaTableNode::stackRestore()
+{
+  lua_pop (luaTable->L, lua_gettop(luaTable->L) - stackTop);
+}
+
+bool LuaTableNode::exists()
+{
+  bool result = true;
+
+  if (!stackQueryValue())
+    result = false;
+
+  stackRestore();
+
+  return result;
+}
+
+void LuaTableNode::remove()
+{
+  if (stackQueryValue()) {
+    lua_pop(luaTable->L, 1);
+
+    if (lua_gettop(luaTable->L) != 0) {
+      l_push_LuaKey (luaTable->L, key);
+      lua_pushnil (luaTable->L);
+      lua_settable (luaTable->L, -3);
+    } else {
+      lua_pushnil (luaTable->L);
+      lua_setglobal (luaTable->L, key.string_value.c_str());
+    }
+  }
+
+  stackRestore();
+}
+
+size_t LuaTableNode::length()
+{
+  size_t result = 0;
+
+  if (stackQueryValue()) {
+    result = lua_objlen(luaTable->L, -1);
+  }
+
+  stackRestore();
+
+  return result;
+}
+
+std::vector<LuaKey> LuaTableNode::keys()
+{
+  std::vector<LuaKey> result;
+
+  if (stackQueryValue()) {
+    // loop over all keys
+    lua_pushnil(luaTable->L);
+    while (lua_next(luaTable->L, -2) != 0) {
+      if (lua_isnumber(luaTable->L, -2)) {
+        double number = lua_tonumber (luaTable->L, -2);
+        double frac;
+        if (modf (number, &frac) == 0) {
+          LuaKey key (static_cast<int>(number));
+          result.push_back (key);
+        }
+      } else if (lua_isstring (luaTable->L, -2)) {
+        LuaKey key (lua_tostring(luaTable->L, -2));
+        result.push_back (key);
+      } else {
+        cerr << "Warning: invalid LuaKey type for key " << lua_typename(luaTable->L, lua_type(luaTable->L, -2)) << "!" << endl;
+      }
+
+      lua_pop(luaTable->L, 1);
+    }
+  }
+
+  stackRestore();
+
+  return result;
+}
+
+
+template<> bool LuaTableNode::getDefault<bool>(const bool & default_value)
+{
+  bool result = default_value;
+
+  if (stackQueryValue()) {
+    result = lua_toboolean (luaTable->L, -1);
+  }
+
+  stackRestore();
+
+  return result;
+}
+
+template<> float LuaTableNode::getDefault<float>(const float & default_value)
+{
+  float result = default_value;
+
+  if (stackQueryValue()) {
+    result = static_cast<float>(lua_tonumber (luaTable->L, -1));
+  }
+
+  stackRestore();
+
+  return result;
+}
+
+template<> double LuaTableNode::getDefault<double>(const double & default_value)
+{
+  double result = default_value;
+
+  if (stackQueryValue()) {
+    result = lua_tonumber (luaTable->L, -1);
+  }
+
+  stackRestore();
+
+  return result;
+}
+
+template<> std::string LuaTableNode::getDefault<std::string>(const std::string & default_value)
+{
+  std::string result = default_value;
+
+  if (stackQueryValue() && lua_isstring(luaTable->L, -1)) {
+    result = lua_tostring (luaTable->L, -1);
+  }
+
+  stackRestore();
+
+  return result;
+}
+
+template<> void LuaTableNode::set<bool>(const bool & value)
+{
+  stackCreateValue();
+
+  l_push_LuaKey (luaTable->L, key);
+  lua_pushboolean(luaTable->L, value);
+  // stack: parent, key, value
+  lua_settable (luaTable->L, -3);
+
+  stackRestore();
+}
+
+template<> void LuaTableNode::set<float>(const float & value)
+{
+  stackCreateValue();
+
+  l_push_LuaKey (luaTable->L, key);
+  lua_pushnumber(luaTable->L, static_cast<double>(value));
+  // stack: parent, key, value
+  lua_settable (luaTable->L, -3);
+
+  stackRestore();
+}
+
+template<> void LuaTableNode::set<double>(const double & value)
+{
+  stackCreateValue();
+
+  l_push_LuaKey (luaTable->L, key);
+  lua_pushnumber(luaTable->L, value);
+  // stack: parent, key, value
+  lua_settable (luaTable->L, -3);
+
+  stackRestore();
+}
+
+template<> void LuaTableNode::set<std::string>(const std::string & value)
+{
+  stackCreateValue();
+
+  l_push_LuaKey (luaTable->L, key);
+  lua_pushstring(luaTable->L, value.c_str());
+  // stack: parent, key, value
+  lua_settable (luaTable->L, -3);
+
+  stackRestore();
+}
+
+//
+// LuaTable
+//
+LuaTable::~LuaTable()
+{
+  if (deleteLuaState) {
+    lua_close(L);
+    L = NULL;
+  }
+}
+
+int LuaTable::length()
+{
+  if ((lua_gettop(L) == 0) || (lua_type (L, -1) != LUA_TTABLE)) {
+    cerr << "Error: cannot query table length. No table on stack!" << endl;
+    abort();
+  }
+  size_t result = 0;
+
+  result = lua_objlen(L, -1);
+
+  return (int)result;
+}
+
+LuaTable & LuaTable::operator= (const LuaTable & luatable)
+{
+  if (this != &luatable) {
+    if (deleteLuaState && L != luatable.L) {
+      lua_close (luatable.L);
+    }
+    filename = luatable.filename;
+    L = luatable.L;
+    deleteLuaState = luatable.deleteLuaState;
+  }
+
+  return *this;
+}
+
+LuaTable LuaTable::fromFile (const char* _filename)
+{
+  LuaTable result;
+
+  result.filename = _filename;
+  result.L = luaL_newstate();
+  result.deleteLuaState = true;
+  luaL_openlibs(result.L);
+
+  // Add the directory of _filename to package.path
+  result.addSearchPath(get_file_directory (_filename).c_str());
+
+  // run the file we
+  if (luaL_dofile (result.L, _filename)) {
+    bail (result.L, "Error running file: ");
+  }
+  
+  return result;
+}
+
+LuaTable LuaTable::fromLuaExpression (const char* lua_expr)
+{
+  LuaTable result;
+  
+  result.L = luaL_newstate();
+  result.deleteLuaState = true;
+  luaL_openlibs(result.L);
+  
+  if (luaL_loadstring (result.L, lua_expr)) {
+    bail (result.L, "Error compiling expression!");
+  }
+  
+  if (lua_pcall (result.L, 0, LUA_MULTRET, 0)) {
+    bail (result.L, "Error running expression!");
+  }
+  
+  return result;
+}
+
+LuaTable LuaTable::fromLuaState (lua_State* L)
+{
+  LuaTable result;
+  
+  result.L = L;
+  result.deleteLuaState = false;
+  
+  return result;
+}
+
+void LuaTable::addSearchPath(const char* path)
+{
+  if (L == NULL) {
+    cerr << "Error: Cannot add search path: Lua state is not initialized!" << endl;
+    abort();
+  }
+  
+  lua_getglobal(L, "package");
+  lua_getfield (L, -1, "path");
+  if (lua_type(L, -1) != LUA_TSTRING) {
+    cerr << "Error: could not get package.path!" << endl;
+    abort();
+  }
+  
+  string package_path = lua_tostring (L, -1);
+  package_path = package_path + string(path) + "?.lua;";
+  
+  lua_pushstring(L, package_path.c_str());
+  lua_setfield (L, -3, "path");
+  
+  lua_pop(L, 2);
+}
+
+std::string LuaTable::serialize()
+{
+  std::string result;
+  
+  int current_top = lua_gettop(L);
+  if (lua_gettop(L) != 0) {
+    if (luaL_loadstring(L, serialize_std)) {
+      bail (L, "Error loading serialization function: ");
+    }
+    
+    if (lua_pcall(L, 0, 0, 0)) {
+      bail (L, "Error compiling serialization function: " );
+    }
+    
+    lua_getglobal (L, "serialize");
+    assert (lua_isfunction (L, -1));
+    lua_pushvalue (L, -2);
+    if (lua_pcall (L, 1, 1, 0)) {
+      bail (L, "Error while serializing: ");
+    }
+    result = string("return ") + lua_tostring (L, -1);
+  } else {
+    cerr << "Cannot serialize global Lua state!" << endl;
+    abort();
+  }
+  
+  lua_pop (L, lua_gettop(L) - current_top);
+  
+  return result;
+}
+
+std::string LuaTable::orderedSerialize()
+{
+  std::string result;
+  
+  int current_top = lua_gettop(L);
+  if (lua_gettop(L) != 0) {
+    if (luaL_loadstring(L, serialize_std)) {
+      bail (L, "Error loading serialization function: ");
+    }
+    
+    if (lua_pcall(L, 0, 0, 0)) {
+      bail (L, "Error compiling serialization function: " );
+    }
+    
+    lua_getglobal (L, "serialize");
+    assert (lua_isfunction (L, -1));
+    lua_pushvalue (L, -2);
+    lua_pushstring (L, "");
+    lua_pushboolean (L, true);
+    if (lua_pcall (L, 3, 1, 0)) {
+      bail (L, "Error while serializing: ");
+    }
+    result = string("return ") + lua_tostring (L, -1);
+  } else {
+    cerr << "Cannot serialize global Lua state!" << endl;
+    abort();
+  }
+  
+  lua_pop (L, lua_gettop(L) - current_top);
+  
+  return result;
+}
diff --git a/src/multibody/parser/lua/lua_tables.hpp b/src/multibody/parser/lua/lua_tables.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..cc814a4b3275b2ee55051161ca3db290e35f644b
--- /dev/null
+++ b/src/multibody/parser/lua/lua_tables.hpp
@@ -0,0 +1,223 @@
+/*
+ * LuaTables++
+ * Code comming from https://bitbucket.org/rbdl/rbdl
+ * Copyright (c) 2013-2014 Martin Felis <martin@fyxs.org>
+ * Copyright (c) 2015 Justin Carpentier <jcarpent@laas.fr>
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __se3_parser_lua_tables_hpp____
+#define __se3_parser_lua_tables_hpp____
+
+#include <iostream>
+#include <assert.h>
+#include <cstdlib>
+#include <string>
+#include <vector>
+
+
+// Forward declaration for Lua
+extern "C" {
+  struct lua_State;
+}
+
+struct LuaKey {
+  enum Type {
+    String,
+    Integer
+  };
+
+  Type type;
+  int int_value;
+  std::string string_value;
+
+  bool operator<( const LuaKey & rhs ) const {
+    if (type == String && rhs.type == Integer) {
+      return false;
+    } else if (type == Integer && rhs.type == String) {
+      return true;
+    } else if (type == Integer && rhs.type == Integer) {
+      return int_value < rhs.int_value;
+    }
+
+    return string_value < rhs.string_value;
+  }
+
+  LuaKey (const char* key_value) :
+  type (String),
+  int_value (0),
+  string_value (key_value) { }
+  LuaKey (int key_value) :
+  type (Integer),
+  int_value (key_value),
+  string_value ("") {}
+};
+
+inline std::ostream & operator<<(std::ostream & output, const LuaKey & key) {
+  if (key.type == LuaKey::Integer)
+    output << key.int_value << "(int)";
+  else
+    output << key.string_value << "(string)";
+  return output;
+}
+struct LuaTable;
+struct LuaTableNode;
+
+struct LuaTableNode {
+  LuaTableNode() :
+  parent (NULL),
+  luaTable (NULL),
+  key("")
+  { }
+  LuaTableNode operator[](const char* child_str) {
+    LuaTableNode child_node;
+
+    child_node.luaTable = luaTable;
+    child_node.parent = this;
+    child_node.key = LuaKey (child_str);
+
+    return child_node;
+  }
+  LuaTableNode operator[](int child_index) {
+    LuaTableNode child_node;
+
+    child_node.luaTable = luaTable;
+    child_node.parent = this;
+    child_node.key = LuaKey (child_index);
+
+    return child_node;
+  }
+  bool stackQueryValue();
+  void stackPushKey();
+  void stackCreateValue();
+  void stackRestore();
+  LuaTable stackQueryTable();
+  LuaTable stackCreateLuaTable();
+
+  std::vector<LuaKey> getKeyStack();
+  std::string keyStackToString();
+
+  bool exists();
+  void remove();
+  size_t length();
+  std::vector<LuaKey> keys();
+
+  // Templates for setters and getters. Can be specialized for custom
+  // types.
+  template <typename T>
+  void set (const T & value);
+  template <typename T>
+  T getDefault (const T & default_value);
+
+  template <typename T>
+  T get() {
+    if (!exists()) {
+      std::cerr << "Error: could not find value " << keyStackToString() << "." << std::endl;
+      abort();
+    }
+    return getDefault (T());
+  }
+
+  // convenience operators (assignment, conversion, comparison)
+  template <typename T>
+  void operator=(const T & value) {
+    set<T>(value);
+  }
+  template <typename T>
+  operator T() {
+    return get<T>();
+  }
+  template <typename T>
+  bool operator==(T value) {
+    return value == get<T>();
+  }
+  template <typename T>
+  bool operator!=(T value) {
+    return value != get<T>();
+  }
+
+  LuaTableNode *parent;
+  LuaTable *luaTable;
+  LuaKey key;
+  int stackTop;
+};
+
+template<typename T>
+bool operator==(T value, LuaTableNode node) {
+  return value == (T) node;
+}
+template<typename T>
+bool operator!=(T value, LuaTableNode node) {
+  return value != (T) node;
+}
+
+template<> bool LuaTableNode::getDefault<bool>(const bool & default_value);
+template<> double LuaTableNode::getDefault<double>(const double & default_value);
+template<> float LuaTableNode::getDefault<float>(const float & default_value);
+template<> std::string LuaTableNode::getDefault<std::string>(const std::string & default_value);
+
+template<> void LuaTableNode::set<bool>(const bool & value);
+template<> void LuaTableNode::set<float>(const float & value);
+template<> void LuaTableNode::set<double>(const double & value);
+template<> void LuaTableNode::set<std::string>(const std::string & value);
+
+struct LuaTable {
+  LuaTable() :
+  filename (""),
+  L (NULL),
+  deleteLuaState (false)
+  {}
+  LuaTable & operator= (const LuaTable & luatable);
+  ~LuaTable();
+
+  LuaTableNode operator[] (const char* key) {
+    LuaTableNode root_node;
+    root_node.key = LuaKey (key);
+    root_node.parent = NULL;
+    root_node.luaTable = this;
+    
+    return root_node;
+  }
+  LuaTableNode operator[] (int key) {
+    LuaTableNode root_node;
+    root_node.key = LuaKey (key);
+    root_node.parent = NULL;
+    root_node.luaTable = this;
+    
+    return root_node;
+  }
+  int length();
+  void addSearchPath (const char* path);
+  std::string serialize ();
+  std::string orderedSerialize ();
+  
+  static LuaTable fromFile (const char *_filename);
+  static LuaTable fromLuaExpression (const char* lua_expr);
+  static LuaTable fromLuaState (lua_State *L);
+  
+  std::string filename;
+  lua_State *L;
+  bool deleteLuaState;
+};
+
+
+#endif // ifndef __se3_parser_lua_tables_hpp____