From ba20c0e800566c649a8e48937a71c849e5aba96a Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 26 Apr 2013 18:32:19 -0400 Subject: [PATCH] Modified parse to allow overloading of variables in local blocks. Also did some minor cleanups while at it. Test cases missing --- bison.pri | 2 +- flex.pri | 2 +- openscad.pro | 9 +- src/expr.cc | 14 +++ src/expression.h | 2 + src/localscope.cc | 6 ++ src/localscope.h | 1 + src/module.cc | 5 - src/module.h | 2 - src/parser.y | 233 ++++++++++++++----------------------------- tests/CMakeLists.txt | 9 +- 11 files changed, 107 insertions(+), 178 deletions(-) diff --git a/bison.pri b/bison.pri index 7a63f0ec8d..d2972d6e57 100644 --- a/bison.pri +++ b/bison.pri @@ -1,4 +1,4 @@ -win32 { +{ bison.name = Bison ${QMAKE_FILE_IN} bison.input = BISONSOURCES bison.output = ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}_yacc.cpp diff --git a/flex.pri b/flex.pri index 203d90d23e..0813300ac0 100644 --- a/flex.pri +++ b/flex.pri @@ -1,4 +1,4 @@ -win32 { +{ flex.name = Flex ${QMAKE_FILE_IN} flex.input = FLEXSOURCES flex.output = ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.lexer.cpp diff --git a/openscad.pro b/openscad.pro index bd69dfe93d..81f5e6f0f8 100644 --- a/openscad.pro +++ b/openscad.pro @@ -171,13 +171,8 @@ CONFIG(mingw-cross-env) { include(mingw-cross-env.pri) } -win32 { - FLEXSOURCES = src/lexer.l - BISONSOURCES = src/parser.y -} else { - LEXSOURCES += src/lexer.l - YACCSOURCES += src/parser.y -} +FLEXSOURCES = src/lexer.l +BISONSOURCES = src/parser.y RESOURCES = openscad.qrc diff --git a/src/expr.cc b/src/expr.cc index 6629bf5bad..985a53a642 100644 --- a/src/expr.cc +++ b/src/expr.cc @@ -38,6 +38,20 @@ Expression::Expression() { } +Expression::Expression(const std::string &type, + Expression *left, Expression *right) + : type(type) +{ + this->children.push_back(left); + this->children.push_back(right); +} + +Expression::Expression(const std::string &type, Expression *expr) + : type(type) +{ + this->children.push_back(expr); +} + Expression::Expression(const Value &val) : const_value(val), type("C") { } diff --git a/src/expression.h b/src/expression.h index 06becc09e3..6c03f529ed 100644 --- a/src/expression.h +++ b/src/expression.h @@ -34,6 +34,8 @@ class Expression Expression(); Expression(const Value &val); + Expression(const std::string &type, Expression *left, Expression *right); + Expression(const std::string &type, Expression *expr); ~Expression(); Value evaluate(const class Context *context) const; diff --git a/src/localscope.cc b/src/localscope.cc index c4001f56b2..eecff91e35 100644 --- a/src/localscope.cc +++ b/src/localscope.cc @@ -19,6 +19,12 @@ LocalScope::~LocalScope() BOOST_FOREACH (AbstractModuleContainer::value_type &m, modules) delete m.second; } +void LocalScope::addChild(ModuleInstantiation *ch) +{ + assert(ch != NULL); + this->children.push_back(ch); +} + std::string LocalScope::dump(const std::string &indent) const { std::stringstream dump; diff --git a/src/localscope.h b/src/localscope.h index 87f8430312..d81a27c7ed 100644 --- a/src/localscope.h +++ b/src/localscope.h @@ -13,6 +13,7 @@ class LocalScope size_t numElements() const { return assignments.size() + children.size(); } std::string dump(const std::string &indent) const; std::vector instantiateChildren(const class Context *evalctx, class FileContext *filectx = NULL) const; + void addChild(ModuleInstantiation *ch); AssignmentList assignments; ModuleInstantiationList children; diff --git a/src/module.cc b/src/module.cc index e9a5169a6b..9503f05d6a 100644 --- a/src/module.cc +++ b/src/module.cc @@ -132,11 +132,6 @@ Module::~Module() { } -void Module::addChild(ModuleInstantiation *ch) -{ - this->scope.children.push_back(ch); -} - AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { ModuleContext c(ctx, evalctx); diff --git a/src/module.h b/src/module.h index b7ee23d4df..8f1ccb7fe0 100644 --- a/src/module.h +++ b/src/module.h @@ -68,8 +68,6 @@ class Module : public AbstractModule virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx = NULL) const; virtual std::string dump(const std::string &indent, const std::string &name) const; - void addChild(ModuleInstantiation *ch); - AssignmentList definition_arguments; LocalScope scope; diff --git a/src/parser.y b/src/parser.y index 0cd1fbdb44..272f801077 100644 --- a/src/parser.y +++ b/src/parser.y @@ -56,8 +56,7 @@ int lexerlex_destroy(void); int lexerlex(void); - std::vector module_stack; - Module *currmodule; + std::stack scope_stack; FileModule *rootmodule; extern void lexerdestroy(); @@ -74,7 +73,6 @@ class Value *value; class Expression *expr; class ModuleInstantiation *inst; - std::vector *instvec; class IfElseModuleInstantiation *ifelse; Assignment *arg; AssignmentList *args; @@ -115,8 +113,6 @@ %type module_instantiation %type if_statement %type ifelse_statement -%type children_instantiation -%type module_instantiation_list %type single_module_instantiation %type arguments_call @@ -138,89 +134,66 @@ inner_input: /* empty */ | statement inner_input ; -statement: -';' | -'{' inner_input '}' | -module_instantiation { - if ($1) { - currmodule->addChild($1); - } else { - delete $1; - } -} | +assignment: TOK_ID '=' expr ';' { - for (AssignmentList::iterator iter = currmodule->scope.assignments.begin(); - iter != currmodule->scope.assignments.end(); + for (AssignmentList::iterator iter = scope_stack.top()->assignments.begin(); + iter != scope_stack.top()->assignments.end(); iter++) { if (iter->first == $1) { - currmodule->scope.assignments.erase(iter); + scope_stack.top()->assignments.erase(iter); break; } } - currmodule->scope.assignments.push_back(Assignment($1, $3)); + scope_stack.top()->assignments.push_back(Assignment($1, $3)); +} ; + +statement: +';' | +'{' inner_input '}' | +module_instantiation { + if ($1) scope_stack.top()->addChild($1); } | +assignment | TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' { - Module *p = currmodule; - module_stack.push_back(currmodule); - currmodule = new Module(); - p->scope.modules[$2] = currmodule; - currmodule->definition_arguments = *$4; + Module *newmodule = new Module(); + newmodule->definition_arguments = *$4; + scope_stack.top()->modules[$2] = newmodule; + scope_stack.push(&newmodule->scope); free($2); delete $4; } statement { - currmodule = module_stack.back(); - module_stack.pop_back(); + scope_stack.pop(); } | TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr { Function *func = new Function(); func->definition_arguments = *$4; func->expr = $8; - currmodule->scope.functions[$2] = func; + scope_stack.top()->functions[$2] = func; free($2); delete $4; } ';' ; - -/* Will return a dummy parent node with zero or more children */ -children_instantiation: -module_instantiation { - $$ = new std::vector; - if ($1) { - $$->push_back($1); - } -} | -'{' module_instantiation_list '}' { - $$ = $2; -} ; if_statement: -TOK_IF '(' expr ')' children_instantiation { - $$ = new IfElseModuleInstantiation(); - $$->arguments.push_back(Assignment("", $3)); - $$->setPath(parser_source_path); - - if ($$) { - $$->scope.children = *$5; - } else { - for (size_t i = 0; i < $5->size(); i++) - delete (*$5)[i]; - } - delete $5; -} ; +TOK_IF '(' expr ')' { + $if = new IfElseModuleInstantiation(); + $if->arguments.push_back(Assignment("", $3)); + $if->setPath(parser_source_path); + scope_stack.push(&$if->scope); +}[if] child_statement { + scope_stack.pop(); + $$ = $if; + } ; ifelse_statement: if_statement { $$ = $1; } | -if_statement TOK_ELSE children_instantiation { +if_statement TOK_ELSE { + scope_stack.push(&$1->else_scope); +}[else] child_statement { + scope_stack.pop(); $$ = $1; - if ($$) { - $$->else_scope.children = *$3; - } else { - for (size_t i = 0; i < $3->size(); i++) - delete (*$3)[i]; - } - delete $3; -} ; + } ; module_instantiation: '!' module_instantiation { @@ -239,35 +212,28 @@ module_instantiation: delete $2; $$ = NULL; } | -single_module_instantiation ';' { - $$ = $1; -} | -single_module_instantiation children_instantiation { - $$ = $1; - if ($$) { - $$->scope.children = *$2; - } else { - for (size_t i = 0; i < $2->size(); i++) - delete (*$2)[i]; - } - delete $2; +single_module_instantiation { + $inst = $1; + scope_stack.push(&$inst->scope); +}[inst] child_statement { + scope_stack.pop(); + $$ = $inst; + } | + ifelse_statement { + $$ = $1; + } ; + +child_statement: +';' | +'{' child_statements '}' | +module_instantiation { + if ($1) scope_stack.top()->addChild($1); } | -ifelse_statement { - $$ = $1; -} ; +assignment ; -module_instantiation_list: -/* empty */ { - $$ = new std::vector; -} | -module_instantiation_list module_instantiation { - $$ = $1; - if ($$) { - if ($2) $$->push_back($2); - } else { - delete $2; - } -} ; +child_statements: +/* empty */ | +child_statements child_statement ; single_module_instantiation: TOK_ID '(' arguments_call ')' { @@ -295,9 +261,7 @@ TOK_ID { free($1); } | expr '.' TOK_ID { - $$ = new Expression(); - $$->type = "N"; - $$->children.push_back($1); + $$ = new Expression("N", $1); $$->var_name = $3; free($3); } | @@ -330,95 +294,52 @@ TOK_NUMBER { $$ = $2; } | expr '*' expr { - $$ = new Expression(); - $$->type = "*"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("*", $1, $3); } | expr '/' expr { - $$ = new Expression(); - $$->type = "/"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("/", $1, $3); } | expr '%' expr { - $$ = new Expression(); - $$->type = "%"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("%", $1, $3); } | expr '+' expr { - $$ = new Expression(); - $$->type = "+"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("+", $1, $3); } | expr '-' expr { - $$ = new Expression(); - $$->type = "-"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("-", $1, $3); } | expr '<' expr { - $$ = new Expression(); - $$->type = "<"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("<", $1, $3); } | expr LE expr { - $$ = new Expression(); - $$->type = "<="; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("<=", $1, $3); } | expr EQ expr { - $$ = new Expression(); - $$->type = "=="; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("==", $1, $3); } | expr NE expr { - $$ = new Expression(); - $$->type = "!="; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("!=", $1, $3); } | expr GE expr { - $$ = new Expression(); - $$->type = ">="; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression(">=", $1, $3); } | expr '>' expr { - $$ = new Expression(); - $$->type = ">"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression(">", $1, $3); } | expr AND expr { - $$ = new Expression(); - $$->type = "&&"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("&&", $1, $3); } | expr OR expr { - $$ = new Expression(); - $$->type = "||"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("||", $1, $3); } | '+' expr { $$ = $2; } | '-' expr { - $$ = new Expression(); - $$->type = "I"; - $$->children.push_back($2); + $$ = new Expression("I", $2); } | '!' expr { - $$ = new Expression(); - $$->type = "!"; - $$->children.push_back($2); + $$ = new Expression("!", $2); } | '(' expr ')' { $$ = $2; @@ -431,10 +352,7 @@ expr '?' expr ':' expr { $$->children.push_back($5); } | expr '[' expr ']' { - $$ = new Expression(); - $$->type = "[]"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("[]", $1, $3); } | TOK_ID '(' arguments_call ')' { $$ = new Expression(); @@ -450,9 +368,7 @@ optional_commas: vector_expr: expr { - $$ = new Expression(); - $$->type = 'V'; - $$->children.push_back($1); + $$ = new Expression("V", $1); } | vector_expr ',' optional_commas expr { $$ = $1; @@ -519,7 +435,6 @@ void yyerror (char const *s) { // FIXME: We leak memory on parser errors... PRINTB("Parser error in line %d: %s\n", lexerget_lineno() % s); - currmodule = NULL; } FileModule *parse(const char *text, const char *path, int debug) @@ -529,10 +444,9 @@ FileModule *parse(const char *text, const char *path, int debug) parser_input_buffer = text; parser_source_path = boosty::absolute(std::string(path)).string(); - module_stack.clear(); rootmodule = new FileModule(); - currmodule = rootmodule; rootmodule->setModulePath(path); + scope_stack.push(&rootmodule->scope); // PRINTB_NOCACHE("New module: %s %p", "root" % rootmodule); parserdebug = debug; @@ -543,5 +457,6 @@ FileModule *parse(const char *text, const char *path, int debug) if (parserretval != 0) return NULL; parser_error_pos = -1; + scope_stack.pop(); return rootmodule; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 909c8ed5c2..51abd064e9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -13,7 +13,11 @@ include(CMakeParseArguments.cmake) # Detect Lion and force gcc IF (APPLE) EXECUTE_PROCESS(COMMAND sw_vers -productVersion OUTPUT_VARIABLE MACOSX_VERSION) - IF (NOT ${MACOSX_VERSION} VERSION_LESS "10.7.0") + IF (NOT ${MACOSX_VERSION} VERSION_LESS "10.8.0") + message("Detected Mountain Lion or later") + set(CMAKE_C_COMPILER "gcc") + set(CMAKE_CXX_COMPILER "g++") + ELSEIF (NOT ${MACOSX_VERSION} VERSION_LESS "10.7.0") message("Detected Lion or later") set(CMAKE_C_COMPILER "gcc") set(CMAKE_CXX_COMPILER "g++") @@ -325,9 +329,8 @@ if (WIN32) set(FLEX_UNISTD_FLAG "-DYY_NO_UNISTD_H") endif() FLEX_TARGET(OpenSCADlexer ../src/lexer.l ${CMAKE_CURRENT_BINARY_DIR}/lexer.cpp COMPILE_FLAGS "-Plexer ${FLEX_UNISTD_FLAG}") -BISON_TARGET(OpenSCADparser ../src/parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser_yacc.c COMPILE_FLAGS "-p parser") +BISON_TARGET(OpenSCADparser ../src/parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp COMPILE_FLAGS "-p parser") ADD_FLEX_BISON_DEPENDENCY(OpenSCADlexer OpenSCADparser) -set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/parser_yacc.c PROPERTIES LANGUAGE "CXX") # CGAL