summaryrefslogtreecommitdiff
path: root/src/exports.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/exports.cc')
-rw-r--r--src/exports.cc316
1 files changed, 316 insertions, 0 deletions
diff --git a/src/exports.cc b/src/exports.cc
new file mode 100644
index 0000000..62e0d2a
--- /dev/null
+++ b/src/exports.cc
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2006-2012 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Colm.
+ *
+ * Colm is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Colm is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Colm; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "parsedata.h"
+#include "fsmcodegen.h"
+#include "redfsm.h"
+#include "bstmap.h"
+#include "debug.h"
+#include <sstream>
+#include <string>
+
+using std::ostream;
+using std::ostringstream;
+using std::string;
+using std::cerr;
+using std::endl;
+
+void Compiler::openNameSpace( ostream &out, Namespace *nspace )
+{
+ if ( nspace == rootNamespace )
+ return;
+
+ openNameSpace( out, nspace->parentNamespace );
+ out << "namespace " << nspace->name << " { ";
+}
+
+void Compiler::closeNameSpace( ostream &out, Namespace *nspace )
+{
+ if ( nspace == rootNamespace )
+ return;
+
+ openNameSpace( out, nspace->parentNamespace );
+ out << " }";
+}
+
+void Compiler::generateExports()
+{
+ ostream &out = *outStream;
+
+ out <<
+ "#ifndef _EXPORTS_H\n"
+ "#define _EXPORTS_H\n"
+ "\n"
+ "#include <colm/colm.h>\n"
+ "#include <string>\n"
+ "\n";
+
+ out <<
+ "inline void appendString( colm_print_args *args, const char *data, int length )\n"
+ "{\n"
+ " std::string *str = (std::string*)args->arg;\n"
+ " *str += std::string( data, length );\n"
+ "}\n"
+ "\n";
+
+ out <<
+ "inline std::string printTreeStr( colm_program *prg, colm_tree *tree, bool trim )\n"
+ "{\n"
+ " std::string str;\n"
+ " colm_print_args printArgs = { &str, 1, 0, trim, &appendString, \n"
+ " &colm_print_null, &colm_print_term_tree, &colm_print_null };\n"
+ " colm_print_tree_args( prg, colm_vm_root(prg), &printArgs, tree );\n"
+ " return str;\n"
+ "}\n"
+ "\n";
+
+ /* Declare. */
+ for ( LelList::Iter lel = langEls; lel.lte(); lel++ ) {
+ if ( lel->isEOF )
+ continue;
+
+ openNameSpace( out, lel->nspace );
+ out << "struct " << lel->fullName << ";";
+ closeNameSpace( out, lel->nspace );
+ out << "\n";
+ }
+
+ /* Class definitions. */
+ for ( LelList::Iter lel = langEls; lel.lte(); lel++ ) {
+ if ( lel->isEOF )
+ continue;
+
+ openNameSpace( out, lel->nspace );
+ out << "struct " << lel->fullName << "\n";
+ out << "{\n";
+ out << " std::string text() { return printTreeStr( __prg, __tree, true ); }\n";
+ out << " colm_location *loc() { return colm_find_location( __prg, __tree ); }\n";
+ out << " std::string text_notrim() { return printTreeStr( __prg, __tree, false ); }\n";
+ out << " std::string text_ws() { return printTreeStr( __prg, __tree, false ); }\n";
+ out << " colm_data *data() { return __tree->tokdata; }\n";
+ out << " operator colm_tree *() { return __tree; }\n";
+ out << " colm_program *__prg;\n";
+ out << " colm_tree *__tree;\n";
+
+ if ( mainReturnUT != 0 && mainReturnUT->langEl == lel ) {
+ out << " " << lel->fullName <<
+ "( colm_program *prg ) : __prg(prg), __tree(returnVal(prg)) {}\n";
+ }
+
+ out << " " << lel->fullName <<
+ "( colm_program *prg, colm_tree *tree ) : __prg(prg), __tree(tree) {}\n";
+
+ if ( lel->objectDef != 0 && lel->objectDef->objFieldList != 0 ) {
+ ObjFieldList *objFieldList = lel->objectDef->objFieldList;
+ for ( ObjFieldList::Iter ofi = *objFieldList; ofi.lte(); ofi++ ) {
+ ObjectField *field = ofi->value;
+ if ( field->useOffset && field->typeRef != 0 ) {
+ UniqueType *ut = field->typeRef->resolveType( this );
+
+ if ( ut != 0 && ut->typeId == TYPE_TREE ) {
+ out << " " << ut->langEl->refName << " " << field->name << "();\n";
+ }
+ }
+
+ if ( field->isRhsGet ) {
+ UniqueType *ut = field->typeRef->resolveType( this );
+
+ if ( ut != 0 && ut->typeId == TYPE_TREE ) {
+ out << " " << ut->langEl->refName << " " << field->name << "();\n";
+ }
+ }
+ }
+ }
+
+ bool prodNames = false;
+ for ( LelDefList::Iter prod = lel->defList; prod.lte(); prod++ ) {
+ if ( prod->name.length() > 0 )
+ prodNames = true;
+ }
+
+ if ( prodNames ) {
+ out << " enum prod_name {\n";
+ for ( LelDefList::Iter prod = lel->defList; prod.lte(); prod++ ) {
+ if ( prod->name.length() > 0 )
+ out << "\t\t_" << prod->name << " = " << prod->prodNum << ",\n";
+ }
+ out << " };\n";
+ out << " enum prod_name prodName() " <<
+ "{ return (enum prod_name)__tree->prodNum; }\n";
+ }
+
+
+ if ( lel->isRepeat ) {
+ out << " " << "int end() { return colm_repeat_end( __tree ); }\n";
+ out << " " << lel->refName << " next();\n";
+ out << " " << lel->repeatOf->refName << " value();\n";
+ }
+
+ if ( lel->isList ) {
+ out << " " << "int last() { return colm_list_last( __tree ); }\n";
+ out << " " << lel->refName << " next();\n";
+ out << " " << lel->repeatOf->refName << " value();\n";
+ }
+
+
+ out << "};";
+ closeNameSpace( out, lel->nspace );
+ out << "\n";
+ }
+
+ for ( ObjFieldList::Iter of = *globalObjectDef->objFieldList; of.lte(); of++ ) {
+ ObjectField *field = of->value;
+ if ( field->isExport ) {
+ UniqueType *ut = field->typeRef->resolveType(this);
+ if ( ut != 0 && ut->typeId == TYPE_TREE ) {
+ out << ut->langEl->refName << " " << field->name << "( colm_program *prg );\n";
+ }
+ }
+ }
+
+ out << "\n";
+
+ for ( FunctionList::Iter func = functionList; func.lte(); func++ ) {
+ if ( func->exprt ) {
+ char *refName = func->typeRef->uniqueType->langEl->refName;
+ int paramCount = func->paramList->length();
+ out <<
+ refName << " " << func->name << "( colm_program *prg";
+
+ for ( int p = 0; p < paramCount; p++ )
+ out << ", const char *p" << p;
+
+ out << " );\n";
+ }
+ }
+
+ out << "#endif\n";
+}
+
+void Compiler::generateExportsImpl()
+{
+ ostream &out = *outStream;
+
+ if ( exportHeaderFn != 0 ) {
+ out << "#include \"" << exportHeaderFn << "\"\n";
+ }
+
+ /* Function implementations. */
+ for ( LelList::Iter lel = langEls; lel.lte(); lel++ ) {
+ if ( lel->objectDef != 0 && lel->objectDef->objFieldList != 0 ) {
+ ObjFieldList *objFieldList = lel->objectDef->objFieldList;
+ for ( ObjFieldList::Iter ofi = *objFieldList; ofi.lte(); ofi++ ) {
+ ObjectField *field = ofi->value;
+ if ( field->useOffset && field->typeRef != 0 ) {
+ UniqueType *ut = field->typeRef->resolveType( this );
+
+ if ( ut != 0 && ut->typeId == TYPE_TREE ) {
+ out << ut->langEl->refName << " " << lel->declName << "::" << field->name <<
+ "() { return " << ut->langEl->refName <<
+ "( __prg, colm_get_attr( __tree, " << field->offset << ") ); }\n";
+ }
+ }
+
+ if ( field->isRhsGet ) {
+ UniqueType *ut = field->typeRef->resolveType( this );
+
+ if ( ut != 0 && ut->typeId == TYPE_TREE ) {
+ out << ut->langEl->refName << " " << lel->declName << "::" << field->name <<
+ "() { static int a[] = {";
+
+ /* Need to place the array computing the val. */
+ out << field->rhsVal.length();
+ for ( Vector<RhsVal>::Iter rg = field->rhsVal; rg.lte(); rg++ ) {
+ out << ", " << rg->prodEl->production->prodNum;
+ out << ", " << rg->prodEl->pos;
+ }
+
+ out << "}; return " << ut->langEl->refName <<
+ "( __prg, colm_get_rhs_val( __prg, __tree, a ) ); }\n";
+ }
+ }
+ }
+ }
+
+ if ( lel->isRepeat ) {
+ out << lel->refName << " " << lel->declName << "::" << " next"
+ "() { return " << lel->refName <<
+ "( __prg, colm_get_repeat_next( __tree ) ); }\n";
+
+ out << lel->repeatOf->refName << " " << lel->declName << "::" << " value"
+ "() { return " << lel->repeatOf->refName <<
+ "( __prg, colm_get_repeat_val( __tree ) ); }\n";
+
+ }
+
+ if ( lel->isList ) {
+ out << lel->refName << " " << lel->declName << "::" << " next"
+ "() { return " << lel->refName <<
+ "( __prg, colm_get_repeat_next( __tree ) ); }\n";
+
+ out << lel->repeatOf->refName << " " << lel->declName << "::" << " value"
+ "() { return " << lel->repeatOf->refName <<
+ "( __prg, colm_get_repeat_val( __tree ) ); }\n";
+ }
+ }
+
+ out << "\n";
+
+ for ( ObjFieldList::Iter of = *globalObjectDef->objFieldList; of.lte(); of++ ) {
+ ObjectField *field = of->value;
+ if ( field->isExport ) {
+ UniqueType *ut = field->typeRef->resolveType(this);
+ if ( ut != 0 && ut->typeId == TYPE_TREE ) {
+ out <<
+ ut->langEl->refName << " " << field->name << "( colm_program *prg )\n"
+ "{ return " << ut->langEl->refName << "( prg, colm_get_global( prg, " <<
+ field->offset << ") ); }\n";
+ }
+ }
+ }
+
+ out << "\n";
+
+ for ( FunctionList::Iter func = functionList; func.lte(); func++ ) {
+ if ( func->exprt ) {
+ char *refName = func->typeRef->uniqueType->langEl->refName;
+ int paramCount = func->paramList->length();
+ out <<
+ refName << " " << func->name << "( colm_program *prg";
+
+ for ( int p = 0; p < paramCount; p++ )
+ out << ", const char *p" << p;
+
+ out << " )\n"
+ "{\n"
+ " int funcId = " << func->funcId << ";\n"
+ " const char *params[" << paramCount << "];\n";
+
+ for ( int p = 0; p < paramCount; p++ )
+ out << " params[" << p << "] = p" << p << ";\n";
+
+ out <<
+ " return " << refName <<
+ "( prg, colm_run_func( prg, funcId, params, " << paramCount << " ));\n"
+ "}\n";
+ }
+ }
+}