From 0b585f0dc8e185bcf1a7e281108281f5b2b96706 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Tue, 3 May 2005 18:32:14 +0000 Subject: [PATCH] Checking in miniswig: It's a flex/bison based parser that is able to parse simple c++ header files and create squirrel wrappers for them. SVN-Revision: 2391 --- Jamfile | 1 + configure.ac | 6 + mk/jam/bisonflex.jam | 8 +- tools/miniswig/Jamfile | 9 ++ tools/miniswig/create_wrapper.cpp | 270 ++++++++++++++++++++++++++++++++++++++ tools/miniswig/create_wrapper.h | 31 +++++ tools/miniswig/globals.h | 13 ++ tools/miniswig/lexer.ll | 78 +++++++++++ tools/miniswig/main.cpp | 100 ++++++++++++++ tools/miniswig/parser.yy | 267 +++++++++++++++++++++++++++++++++++++ tools/miniswig/tree.cpp | 12 ++ tools/miniswig/tree.h | 169 ++++++++++++++++++++++++ 12 files changed, 960 insertions(+), 4 deletions(-) create mode 100644 tools/miniswig/Jamfile create mode 100644 tools/miniswig/create_wrapper.cpp create mode 100644 tools/miniswig/create_wrapper.h create mode 100644 tools/miniswig/globals.h create mode 100644 tools/miniswig/lexer.ll create mode 100644 tools/miniswig/main.cpp create mode 100644 tools/miniswig/parser.yy create mode 100644 tools/miniswig/tree.cpp create mode 100644 tools/miniswig/tree.h diff --git a/Jamfile b/Jamfile index 3c3fab3f6..bcb3208d1 100644 --- a/Jamfile +++ b/Jamfile @@ -1,6 +1,7 @@ SubDir TOP ; # Decend into subdirs +SubInclude TOP tools miniswig ; SubInclude TOP lib ; SubInclude TOP src ; SubInclude TOP data ; diff --git a/configure.ac b/configure.ac index a2c8befc1..f54ef0142 100644 --- a/configure.ac +++ b/configure.ac @@ -39,6 +39,12 @@ if test -n "$XGETTEXT" ; then fi fi +AC_PROG_LEX +LEX_LIBS=$LEXLIB +AC_SUBST([LEX_LIBS]) +AC_CHECK_PROGS([BISON], bison) +AC_SUBST([BISON]) + dnl Checks for header files. AC_HEADER_DIRENT AC_HEADER_STDC diff --git a/mk/jam/bisonflex.jam b/mk/jam/bisonflex.jam index 83912b5be..141f839e7 100644 --- a/mk/jam/bisonflex.jam +++ b/mk/jam/bisonflex.jam @@ -24,7 +24,7 @@ if $(LEX) return $(object) ; } - RegisterFileType Flex++Rule : .ll ; + RegisterFileType Lex++Rule : .ll ; if $(COMPILER_TYPE) != "GCC" { @@ -57,7 +57,7 @@ if $(BISON) Includes $(headerfile:G=) : $(headerfile) ; - Bison $(cfile) $(headerfile) : $(<) ; + Bison $(cfile) : $(<) ; # work around jam warning about independent target Includes $(cfile) : $(headerfile) ; @@ -76,8 +76,8 @@ if $(BISON) # here Includes $(headerfile:G=) : $(headerfile) ; - Bison $(cppfile) $(headerfile) : $(<) ; - Includes $(cppfile) : $(headerfile) ; + Bison $(cppfile) : $(<) ; +#Includes $(cppfile) : $(headerfile) ; return $(object) ; } diff --git a/tools/miniswig/Jamfile b/tools/miniswig/Jamfile new file mode 100644 index 000000000..bc621c914 --- /dev/null +++ b/tools/miniswig/Jamfile @@ -0,0 +1,9 @@ +SubDir TOP tools miniswig ; + +if $(LEX) && $(BISON) { + MINISWIG = [ Application miniswig : [ Wildcard *.yy *.ll *.cpp ] ] ; + C++Flags miniswig : -Wno-unused ; + IncludeDir miniswig : . ; + ExternalLibs miniswig : LEX ; +} + diff --git a/tools/miniswig/create_wrapper.cpp b/tools/miniswig/create_wrapper.cpp new file mode 100644 index 000000000..a806de411 --- /dev/null +++ b/tools/miniswig/create_wrapper.cpp @@ -0,0 +1,270 @@ +#include "tree.h" +#include +#include +#include +#include "create_wrapper.h" +#include "globals.h" + +void +WrapperCreator::create_wrapper(CompilationUnit* unit) +{ + // hpp file + hppout + << "/**\n" + << " * WARNING: This file is automatically generated from '" + << inputfile << "' - do not change\n" + << " */\n" + << "#ifndef __" << modulename << "_WRAPPER_HPP__\n" + << "#define __" << modulename << "_WRAPPER_HPP__\n" + << "\n" + << "#include \"WrapperUtil.hpp\"\n" + << "\n" + << "extern WrappedFunction " << modulename << "_global_functions[];\n" + << "extern WrappedClass " << modulename << "_classes[];\n" + << "\n" + << "#endif\n" + << "\n"; + + // cpp header + out << "/**\n" + << " * WARNING: This file is automatically generated from '" + << inputfile << "' - do not change\n" + << " */\n" + << "\n" + << "#include \n" + << "#include \n" + << "#include \n" + << "#include \"WrapperUtil.hpp\"\n" + << "#include \"" << inputfile << "\"\n" + << "\n"; + + for(std::vector::iterator i = unit->types.begin(); + i != unit->types.end(); ++i) { + AtomicType* type = *i; + Class* _class = dynamic_cast (type); + if(_class != 0) + create_class_wrapper(_class); + } + for(std::vector::iterator i = unit->functions.begin(); + i != unit->functions.end(); ++i) { + create_function_wrapper(0, *i); + } + + // create function list... + out << "WrappedFunction " << modulename << "_global_functions[] = {\n"; + for(std::vector::iterator i = unit->functions.begin(); + i != unit->functions.end(); ++i) { + Function* function = *i; + out << ind << "{ \"" << function->name << "\", &" + << function->name << "_wrapper },\n"; + } + out << ind << "{ 0, 0 }\n" + << "};\n" + << "\n"; + + // create class list... + std::ostringstream classlist; + classlist << "WrappedClass " << modulename << "_classes[] = {\n"; + + for(std::vector::iterator i = unit->types.begin(); + i != unit->types.end(); ++i) { + AtomicType* type = *i; + Class* _class = dynamic_cast (type); + if(_class == 0) + continue; + + classlist << ind << "{ \"" << _class->name << "\", " + << modulename << "_" << _class->name + << "_methods },\n"; + + out << "static WrappedFunction " << modulename << "_" + << _class->name << "_methods[] = {\n"; + out << ind << "{ \"constructor\", &" + << _class->name << "_" << "construct_wrapper },\n"; + for(std::vector::iterator i = _class->members.begin(); + i != _class->members.end(); ++i) { + ClassMember* member = *i; + if(member->visibility != ClassMember::PUBLIC) + continue; + Function* function = dynamic_cast (member); + if(!function || function->type != Function::FUNCTION) + continue; + + out << ind << "{ \"" << function->name << "\", &" + << _class->name << "_" << function->name << "_wrapper },\n"; + } + classlist << ind << "{ 0, 0 }\n"; + out << "};\n" + << "\n"; + } + classlist << "};\n"; + out << classlist.str(); + out << "\n"; +} + +void +WrapperCreator::create_function_wrapper(Class* _class, Function* function) +{ + if(function->type == Function::CONSTRUCTOR) + throw std::runtime_error("Constructors not supported yet"); + if(function->type == Function::DESTRUCTOR) + throw std::runtime_error("Destructors not supported yet"); + + out << "static int "; + if(_class != 0) { + out << _class->name << "_"; + } + out << function->name << "_wrapper(HSQUIRRELVM v)\n" + << "{\n"; + // avoid warning... + if(_class == 0 && function->parameters.empty() + && function->return_type.is_void()) { + out << ind << "(void) v;\n"; + } + + // eventually retrieve pointer to class + if(_class != 0) { + out << ind << _class->name << "* _this;\n"; + out << ind << "sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);\n"; + out << ind << "assert(_this != 0);\n"; + } + + // declare and retrieve arguments + size_t i = 0; + for(std::vector::iterator p = function->parameters.begin(); + p != function->parameters.end(); ++p) { + char argname[64]; + snprintf(argname, sizeof(argname), "arg%u", i); + prepare_argument(p->type, i + 2, argname); + + ++i; + } + // call function + out << ind << "\n"; + out << ind; + if(!function->return_type.is_void()) { + function->return_type.write_c_type(out); + out << " return_value = "; + } + if(_class != 0) { + out << "_this->"; + } + out << function->name << "("; + for(size_t i = 0; i < function->parameters.size(); ++i) { + if(i != 0) + out << ", "; + out << "arg" << i; + } + out << ");\n"; + out << ind << "\n"; + // push return value back on stack and return + if(function->return_type.is_void()) { + out << ind << "return 0;\n"; + } else { + push_to_stack(function->return_type, "return_value"); + out << ind << "return 1;\n"; + } + out << "}\n"; + out << "\n"; +} + +void +WrapperCreator::prepare_argument(const Type& type, size_t index, + const std::string& var) +{ + if(type.ref > 0 && type.atomic_type != StringType::instance()) + throw std::runtime_error("References not handled yet"); + if(type.pointer > 0) + throw std::runtime_error("Pointers not handled yet"); + if(type.atomic_type == &BasicType::INT) { + out << ind << "int " << var << ";\n"; + out << ind << "sq_getinteger(v, " << index << ", &" << var << ");\n"; + } else if(type.atomic_type == &BasicType::FLOAT) { + out << ind << "float " << var << ";\n"; + out << ind << "sq_getfloat(v, " << index << ", &" << var << ");\n"; + } else if(type.atomic_type == &BasicType::BOOL) { + out << ind << "SQBool " << var << ";\n"; + out << ind << "sq_getbool(v, " << index << ", &" << var << ");\n"; + } else if(type.atomic_type == StringType::instance()) { + out << ind << "const char* " << var << ";\n"; + out << ind << "sq_getstring(v, " << index << ", &" << var << ");\n"; + } else { + std::ostringstream msg; + msg << "Type '" << type.atomic_type->name << "' not supported yet."; + throw std::runtime_error(msg.str()); + } +} + +void +WrapperCreator::push_to_stack(const Type& type, const std::string& var) +{ + if(type.ref > 0 && type.atomic_type != StringType::instance()) + throw std::runtime_error("References not handled yet"); + if(type.pointer > 0) + throw std::runtime_error("Pointers not handled yet"); + out << ind; + if(type.atomic_type == &BasicType::INT) { + out << "sq_pushinteger(v, " << var << ");\n"; + } else if(type.atomic_type == &BasicType::FLOAT) { + out << "sq_pushfloat(v, " << var << ");\n"; + } else if(type.atomic_type == &BasicType::BOOL) { + out << "sq_pushbool(v, " << var << ");\n"; + } else if(type.atomic_type == StringType::instance()) { + out << "sq_pushstring(v, " << var << ".c_str(), " + << var << ".size());\n"; + } else { + std::ostringstream msg; + msg << "Type '" << type.atomic_type->name << "' not supported yet."; + throw std::runtime_error(msg.str()); + } +} + +void +WrapperCreator::create_class_wrapper(Class* _class) +{ + create_class_destruct_function(_class); + create_class_construct_function(_class); + for(std::vector::iterator i = _class->members.begin(); + i != _class->members.end(); ++i) { + ClassMember* member = *i; + if(member->visibility != ClassMember::PUBLIC) + continue; + Function* function = dynamic_cast (member); + if(!function) + continue; + // don't wrap constructors and destructors (for now...) + if(function->type != Function::FUNCTION) + continue; + create_function_wrapper(_class, function); + } +} + +void +WrapperCreator::create_class_construct_function(Class* _class) +{ + out << "static int " << _class->name << "_construct_wrapper(HSQUIRRELVM v)\n"; + out << "{\n"; + out << ind << _class->name << "* _this = new " + << _class->name << "();\n"; + out << ind << "sq_setinstanceup(v, 1, _this);\n"; + out << ind << "sq_setreleasehook(v, 1, " + << _class->name << "_release_wrapper);\n"; + out << "\n"; + out << ind << "return 0;\n"; + out << "}\n"; + out << "\n"; +} + +void +WrapperCreator::create_class_destruct_function(Class* _class) +{ + out << "static int " << _class->name << "_release_wrapper(SQUserPointer ptr, int )\n" + << "{\n" + << ind << _class->name + << "* _this = reinterpret_cast<" << _class->name << "*> (ptr);\n" + << ind << "_this->~" << _class->name << "();\n" + << ind << "return 0;\n" + << "}\n" + << "\n"; +} + diff --git a/tools/miniswig/create_wrapper.h b/tools/miniswig/create_wrapper.h new file mode 100644 index 000000000..7b51a18ec --- /dev/null +++ b/tools/miniswig/create_wrapper.h @@ -0,0 +1,31 @@ +#ifndef __CREATE_WRAPPER_H__ +#define __CREATE_WRAPPER_H__ + +#include "tree.h" + +class WrapperCreator +{ +public: + /// this is used for indentation + const char* ind; + // output stream + std::ostream& out; + std::ostream& hppout; + + WrapperCreator(std::ostream& _out = std::cout, std::ostream& _hppout = std::cout) + : out(_out), hppout(_hppout) + { + ind = " "; + } + + void create_wrapper(CompilationUnit* unit); + void create_class_wrapper(Class* _class); + void create_class_construct_function(Class* _class); + void create_class_destruct_function(Class* _class); + void create_function_wrapper(Class* _class, Function* function); + void prepare_argument(const Type& type, size_t idx, const std::string& var); + void push_to_stack(const Type& type, const std::string& var); +}; + +#endif + diff --git a/tools/miniswig/globals.h b/tools/miniswig/globals.h new file mode 100644 index 000000000..652f68892 --- /dev/null +++ b/tools/miniswig/globals.h @@ -0,0 +1,13 @@ +#ifndef __GLOBALS_H__ +#define __GLOBALS_H__ + +#include "tree.h" +#include + +extern CompilationUnit* unit; +extern std::istream* input; +extern std::string inputfile; +extern std::string modulename; + +#endif + diff --git a/tools/miniswig/lexer.ll b/tools/miniswig/lexer.ll new file mode 100644 index 000000000..dc019e813 --- /dev/null +++ b/tools/miniswig/lexer.ll @@ -0,0 +1,78 @@ +%{ +#include +#include +#include "tree.h" +#include "parser.hpp" +#include "globals.h" + +#define YY_DECL int yylex YY_PROTO(( YYSTYPE* yylval )) + +#define YY_INPUT(buf, result, max_size) \ +{ \ + input->read(buf, max_size); \ + result = input->gcount(); \ +} + +%} + +%option noyywrap +%option yylineno +/* %option never-interactive */ + +%% + +[[:space:]]+ /* eat spaces */ +\/\*.*\*\/ /* eat comment */ +\/\/[^\n]*\n /* eat comment */ +class { return T_CLASS; } +struct { return T_STRUCT; } +static { return T_STATIC; } +const { return T_CONST; } +unsigned { return T_UNSIGNED; } +signed { return T_SIGNED; } +void { return T_VOID; } +bool { return T_BOOL; } +char { return T_CHAR; } +short { return T_SHORT; } +int { return T_INT; } +long { return T_LONG; } +float { return T_FLOAT; } +double { return T_DOUBLE; } +public { return T_PUBLIC; } +protected { return T_PROTECTED; } +private { return T_PRIVATE; } +[a-zA-Z_][a-zA-Z_0-9]* { + // is it a type? + for(std::vector::iterator i = unit->types.begin(); + i != unit->types.end(); ++i) { + AtomicType* type = *i; + if(type->name == yytext) { + yylval->atomic_type = type; + return T_ATOMIC_TYPE; + } + } + // or a namespace? (hack for now...) + if(strcmp(yytext, "std") == 0) { + yylval->_namespace = unit->namespaces[0]; + return T_NAMESPACE; + } + yylval->str = strdup(yytext); + return T_ID; +} +\:\: { return T_DDCOL; } +[0-9]+ { + yylval->ival = atoi(yytext); + return T_INT; + } +[0-9]*\.[0-9]+(e[0-9]+)? { + yylval->fval = atof(yytext); + return T_FLOAT; + } +\".*\" { + yylval->str = strdup(yytext); + return T_STRING; + } +. { return yytext[0]; } + +%% + diff --git a/tools/miniswig/main.cpp b/tools/miniswig/main.cpp new file mode 100644 index 000000000..94393df1f --- /dev/null +++ b/tools/miniswig/main.cpp @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include "tree.h" +#include "globals.h" +#include "create_wrapper.h" + +extern int yyparse(); +extern int yylex(); + +CompilationUnit* unit = 0; +std::istream* input = 0; +std::string inputfile; +std::string modulename = "wrapper"; + +void usage() +{ + std::cout << "Usage: miniswig --input FILE --output-cpp FILE --output-hpp FILE [--module NAME]\n"; + std::cout << "\n"; +} + +int main(int argc, char** argv) +{ + std::string outputcpp; + std::string outputhpp; + for(int i = 0; i < argc; ++i) { + if(strcmp(argv[i], "--module") == 0) { + if(i+1 >= argc) { + std::cerr << "Need to specify a module name.\n"; + usage(); + return 1; + } + modulename = argv[++i]; + } else if(strcmp(argv[i], "--input") == 0) { + if(i+1 >= argc) { + std::cerr << "Need to specify input file name.\n"; + usage(); + return 1; + } + inputfile = argv[++i]; + } else if(strcmp(argv[i], "--output-cpp") == 0) { + if(i+1 >= argc) { + std::cerr << "Need to specifiy output cpp name.\n"; + usage(); + return 1; + } + outputcpp = argv[++i]; + } else if(strcmp(argv[i], "--output-hpp") == 0) { + if(i+1 >= argc) { + std::cerr << "Need to specify output hpp name.\n"; + usage(); + return 1; + } + outputhpp = argv[++i]; + } else if(argv[i][0] == '-') { + std::cerr << "Unknown option '" << argv[i] << "'.\n"; + usage(); + return 1; + } else { + } + } + if(inputfile == "" || outputcpp == "" || outputhpp == "") { + std::cerr << "Not all options specified.\n"; + usage(); + return 1; + } + + try { + input = new std::ifstream(inputfile.c_str()); + if(!input->good()) { + std::cerr << "Couldn't open file '" << input << "' for reading.\n"; + return 1; + } + unit = new CompilationUnit(); + unit->types.push_back(new StringType()); + Namespace* std_namespace = new Namespace(); + std_namespace->name = "std"; + unit->namespaces.push_back(std_namespace); + yyparse(); + std::ofstream cppout(outputcpp.c_str()); + if(!cppout.good()) { + std::cerr << "Couldn't open file '" << outputcpp << "' for writing.\n"; + return 1; + } + std::ofstream hppout(outputhpp.c_str()); + if(!hppout.good()) { + std::cerr << "Couldn't open file '" << outputhpp << "' for writing.\n"; + return 1; + } + WrapperCreator creator(cppout, hppout); + creator.create_wrapper(unit); + } catch(std::exception& e) { + std::cerr << e.what() << "\n"; + return 1; + } + + return 0; +} + diff --git a/tools/miniswig/parser.yy b/tools/miniswig/parser.yy new file mode 100644 index 000000000..f7865cc2c --- /dev/null +++ b/tools/miniswig/parser.yy @@ -0,0 +1,267 @@ +%{ + +#include +#include +#include +#include "tree.h" +#include "globals.h" + +%} + +%pure_parser +%union { + char* str; + int ival; + float fval; + Class* _class; + Function* function; + Type* type; + AtomicType* atomic_type; + Namespace* _namespace; +} + +%{ + +extern int yylex(YYSTYPE* yylval); +void yyerror(const char* s); +extern int yylineno; + +static Class* currentClass = 0; +static Function* currentFunction = 0; +static Type* currentType = 0; +static ClassMember::Visbility currentVisibility; + +class ParseError : public std::exception +{ +public: + ParseError(const std::string& message) throw() + { + std::ostringstream msg; + msg << "Parse error in line " << yylineno << ": " + << message; + this->message = msg.str(); + } + virtual ~ParseError() throw() + {} + const char* what() const throw() + { + return message.c_str(); + } + +private: + std::string message; +}; + +%} + +%token T_INT +%token T_FLOAT +%token T_STRING +%token T_ID +%token T_ATOMIC_TYPE +%token <_namespace> T_NAMESPACE; +%token T_CLASS +%token T_STRUCT +%token T_STATIC +%token T_CONST +%token T_UNSIGNED +%token T_SIGNED +%token T_VOID +%token T_BOOL +%token T_CHAR +%token T_SHORT +%token T_INT +%token T_LONG +%token T_FLOAT +%token T_DOUBLE +%token T_PUBLIC +%token T_PROTECTED +%token T_PRIVATE +%token T_DDCOL "::" + +%type <_class> class_declaration +%type function_declaration +%type constructor_declaration; +%type destructor_declaration; +%type type +%type type_identifier + +%% + +input: /* empty */ + | compilation_unit +; + +compilation_unit: compilation_unit_part + | compilation_unit compilation_unit_part +; + +compilation_unit_part: class_declaration + { unit->types.push_back($1); } + | function_declaration + { unit->functions.push_back($1); } +; + +class_declaration: T_CLASS T_ID '{' + { + currentClass = new Class(); + currentClass->name = $2; + free($2); + currentVisibility = ClassMember::PROTECTED; + } + class_body '}' ';' + { + $$ = currentClass; + } +; + +class_body: /* empty */ + | visibility_change class_body + | constructor_declaration + { + $1->visibility = currentVisibility; + currentClass->members.push_back($1); + } + class_body + | destructor_declaration + { + $1->visibility = currentVisibility; + currentClass->members.push_back($1); + } + class_body + | function_declaration + { + $1->visibility = currentVisibility; + currentClass->members.push_back($1); + } + class_body + | variable_declaration class_body +; + +visibility_change: T_PUBLIC ':' + { currentVisibility = ClassMember::PUBLIC; } + | T_PROTECTED ':' + { currentVisibility = ClassMember::PROTECTED; } + | T_PRIVATE ':' + { currentVisibility = ClassMember::PRIVATE; } +; + +constructor_declaration: T_ID '(' + { + currentFunction = new Function(); + currentFunction->type = Function::CONSTRUCTOR; + free($1); + } + param_list ')' ';' + { + $$ = currentFunction; + } +; + +destructor_declaration: '~' T_ID '(' ')' ';' + { + currentFunction = new Function(); + currentFunction->type = Function::DESTRUCTOR; + free($2); + $$ = currentFunction; + } +; + +variable_declaration: type T_ID ';' + +function_declaration: type T_ID '(' + { + currentFunction = new Function(); + currentFunction->type = Function::FUNCTION; + currentFunction->return_type = *($1); + delete $1; + currentFunction->name = $2; + free($2); + } + param_list ')' ';' + { + $$ = currentFunction; + } +; + +param_list: /* empty */ + | param_list2 +; + +param_list2: parameter + | parameter ',' param_list2 +; + +parameter: type + { + Parameter parameter; + parameter.type = *($1); + delete $1; + currentFunction->parameters.push_back(parameter); + } + | type T_ID + { + Parameter parameter; + parameter.type = *($1); + delete $1; + parameter.name = *($2); + free($2); + currentFunction->parameters.push_back(parameter); + } +; + +type: { + currentType = new Type(); + } + prefix_type_modifiers atomic_type postfix_type_modifiers + { + $$ = currentType; + } +; + +prefix_type_modifiers: /* empty */ + | T_UNSIGNED prefix_type_modifiers + | T_SIGNED prefix_type_modifiers + | T_STATIC prefix_type_modifiers + | T_CONST prefix_type_modifiers +; + +postfix_type_modifiers: /* empty */ + | T_CONST postfix_type_modifiers + { currentType->_const = true; } + | '*' postfix_type_modifiers + { currentType->pointer++; } + | '&' postfix_type_modifiers + { currentType->ref++; } +; + +atomic_type: T_VOID { currentType->atomic_type = &BasicType::VOID; } + | T_BOOL { currentType->atomic_type = &BasicType::BOOL; } + | T_CHAR { currentType->atomic_type = &BasicType::CHAR; } + | T_SHORT { currentType->atomic_type = &BasicType::SHORT; } + | T_INT { currentType->atomic_type = &BasicType::INT; } + | T_LONG { currentType->atomic_type = &BasicType::LONG; } + | T_FLOAT { currentType->atomic_type = &BasicType::FLOAT; } + | T_DOUBLE { currentType->atomic_type = &BasicType::DOUBLE; } + | type_identifier { currentType->atomic_type = $1; } +; + +type_identifier: T_ATOMIC_TYPE + { + // search for type in current compilation unit... + $$ = $1; + } + | T_NAMESPACE "::" type_identifier + { + // hack... + $$ = $3; + } +; + +%% + +void yyerror(const char* error) +{ + throw ParseError(error); +} + diff --git a/tools/miniswig/tree.cpp b/tools/miniswig/tree.cpp new file mode 100644 index 000000000..d05a38af6 --- /dev/null +++ b/tools/miniswig/tree.cpp @@ -0,0 +1,12 @@ +#include "tree.h" + +BasicType BasicType::VOID("void"); +BasicType BasicType::BOOL("bool"); +BasicType BasicType::CHAR("char"); +BasicType BasicType::SHORT("short"); +BasicType BasicType::INT("int"); +BasicType BasicType::LONG("long"); +BasicType BasicType::FLOAT("float"); +BasicType BasicType::DOUBLE("double"); + +StringType* StringType::_instance = 0; diff --git a/tools/miniswig/tree.h b/tools/miniswig/tree.h new file mode 100644 index 000000000..4b9485c1a --- /dev/null +++ b/tools/miniswig/tree.h @@ -0,0 +1,169 @@ +#ifndef __TREE_H__ +#define __TREE_H__ + +#include +#include +#include + +class AtomicType { +public: + std::string name; + virtual ~AtomicType() + { } + + virtual void write_c(std::ostream& out) + { + out << name; + } +}; + +class BasicType : public AtomicType { +public: + static BasicType VOID; + static BasicType BOOL; + static BasicType CHAR; + static BasicType SHORT; + static BasicType INT; + static BasicType LONG; + static BasicType FLOAT; + static BasicType DOUBLE; + +private: + BasicType(const std::string& name) + { + this->name = name; + } +}; + +class Type { +public: + Type() + : atomic_type(0), _const(false), _static(false), pointer(0), ref(0) + { } + + void write_c_type(std::ostream& out) + { + if(_static) + out << "static "; + if(_const) + out << "const "; + atomic_type->write_c(out); + for(int i = 0; i < pointer; ++i) + out << "*"; + for(int i = 0; i < ref; ++i) + out << "&"; + } + + bool is_void() const + { + if(atomic_type == &BasicType::VOID && pointer == 0) + return true; + return false; + } + + AtomicType* atomic_type; + bool _const; + bool _static; + // number of '*' in the type declaration... + int pointer; + // number of '&' in the type declaration... + int ref; +}; + +class StringType : public AtomicType { +public: + StringType() + { + this->name = "string"; + assert(_instance == 0); + _instance = this; + } + virtual ~StringType() + { + assert(_instance == this); + _instance = 0; + } + + static StringType* instance() + { + return _instance; + } + + virtual void write_c(std::ostream& out) + { + out << "std::string"; + } + +private: + static StringType* _instance; +}; + +class Parameter { +public: + std::string name; + Type type; +}; + +class ClassMember { +public: + virtual ~ClassMember() + { } + + enum Visbility { + PUBLIC, + PROTECTED, + PRIVATE + }; + Visbility visibility; +}; + +class Function : public ClassMember { +public: + enum FuncType { + FUNCTION, + CONSTRUCTOR, + DESTRUCTOR + }; + FuncType type; + std::string name; + Type return_type; + std::vector parameters; +}; + +class Class : public AtomicType { +public: + ~Class() { + for(std::vector::iterator i = members.begin(); + i != members.end(); ++i) + delete *i; + } + + std::vector members; +}; + +class Namespace { +public: + std::string name; +}; + +class CompilationUnit { +public: + ~CompilationUnit() { + for(std::vector::iterator i = functions.begin(); + i != functions.end(); ++i) + delete *i; + for(std::vector::iterator i = types.begin(); + i != types.end(); ++i) + delete *i; + for(std::vector::iterator i = namespaces.begin(); + i != namespaces.end(); ++i) + delete *i; + } + + std::vector functions; + std::vector types; + std::vector namespaces; +}; + +#endif + -- 2.11.0