Modified parse to allow overloading of variables in local blocks. Also did some minor cleanups while at it. Test cases missing

felipesanches-svg
Marius Kintel 2013-04-26 18:32:19 -04:00
parent 81266c34a1
commit ba20c0e800
11 changed files with 109 additions and 180 deletions

View File

@ -1,4 +1,4 @@
win32 { {
bison.name = Bison ${QMAKE_FILE_IN} bison.name = Bison ${QMAKE_FILE_IN}
bison.input = BISONSOURCES bison.input = BISONSOURCES
bison.output = ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}_yacc.cpp bison.output = ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}_yacc.cpp

View File

@ -1,4 +1,4 @@
win32 { {
flex.name = Flex ${QMAKE_FILE_IN} flex.name = Flex ${QMAKE_FILE_IN}
flex.input = FLEXSOURCES flex.input = FLEXSOURCES
flex.output = ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.lexer.cpp flex.output = ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.lexer.cpp

View File

@ -171,13 +171,8 @@ CONFIG(mingw-cross-env) {
include(mingw-cross-env.pri) include(mingw-cross-env.pri)
} }
win32 { FLEXSOURCES = src/lexer.l
FLEXSOURCES = src/lexer.l BISONSOURCES = src/parser.y
BISONSOURCES = src/parser.y
} else {
LEXSOURCES += src/lexer.l
YACCSOURCES += src/parser.y
}
RESOURCES = openscad.qrc RESOURCES = openscad.qrc

View File

@ -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") Expression::Expression(const Value &val) : const_value(val), type("C")
{ {
} }

View File

@ -34,6 +34,8 @@ public:
Expression(); Expression();
Expression(const Value &val); Expression(const Value &val);
Expression(const std::string &type, Expression *left, Expression *right);
Expression(const std::string &type, Expression *expr);
~Expression(); ~Expression();
Value evaluate(const class Context *context) const; Value evaluate(const class Context *context) const;

View File

@ -19,6 +19,12 @@ LocalScope::~LocalScope()
BOOST_FOREACH (AbstractModuleContainer::value_type &m, modules) delete m.second; 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::string LocalScope::dump(const std::string &indent) const
{ {
std::stringstream dump; std::stringstream dump;

View File

@ -13,6 +13,7 @@ public:
size_t numElements() const { return assignments.size() + children.size(); } size_t numElements() const { return assignments.size() + children.size(); }
std::string dump(const std::string &indent) const; std::string dump(const std::string &indent) const;
std::vector<class AbstractNode*> instantiateChildren(const class Context *evalctx, class FileContext *filectx = NULL) const; std::vector<class AbstractNode*> instantiateChildren(const class Context *evalctx, class FileContext *filectx = NULL) const;
void addChild(ModuleInstantiation *ch);
AssignmentList assignments; AssignmentList assignments;
ModuleInstantiationList children; ModuleInstantiationList children;

View File

@ -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 AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{ {
ModuleContext c(ctx, evalctx); ModuleContext c(ctx, evalctx);

View File

@ -68,8 +68,6 @@ public:
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx = NULL) const; 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; virtual std::string dump(const std::string &indent, const std::string &name) const;
void addChild(ModuleInstantiation *ch);
AssignmentList definition_arguments; AssignmentList definition_arguments;
LocalScope scope; LocalScope scope;

View File

@ -56,8 +56,7 @@
int lexerlex_destroy(void); int lexerlex_destroy(void);
int lexerlex(void); int lexerlex(void);
std::vector<Module*> module_stack; std::stack<LocalScope *> scope_stack;
Module *currmodule;
FileModule *rootmodule; FileModule *rootmodule;
extern void lexerdestroy(); extern void lexerdestroy();
@ -74,7 +73,6 @@
class Value *value; class Value *value;
class Expression *expr; class Expression *expr;
class ModuleInstantiation *inst; class ModuleInstantiation *inst;
std::vector<ModuleInstantiation*> *instvec;
class IfElseModuleInstantiation *ifelse; class IfElseModuleInstantiation *ifelse;
Assignment *arg; Assignment *arg;
AssignmentList *args; AssignmentList *args;
@ -115,8 +113,6 @@
%type <inst> module_instantiation %type <inst> module_instantiation
%type <ifelse> if_statement %type <ifelse> if_statement
%type <ifelse> ifelse_statement %type <ifelse> ifelse_statement
%type <instvec> children_instantiation
%type <instvec> module_instantiation_list
%type <inst> single_module_instantiation %type <inst> single_module_instantiation
%type <args> arguments_call %type <args> arguments_call
@ -138,89 +134,66 @@ inner_input:
/* empty */ | /* empty */ |
statement inner_input ; statement inner_input ;
assignment:
TOK_ID '=' expr ';' {
for (AssignmentList::iterator iter = scope_stack.top()->assignments.begin();
iter != scope_stack.top()->assignments.end();
iter++) {
if (iter->first == $1) {
scope_stack.top()->assignments.erase(iter);
break;
}
}
scope_stack.top()->assignments.push_back(Assignment($1, $3));
} ;
statement: statement:
';' | ';' |
'{' inner_input '}' | '{' inner_input '}' |
module_instantiation { module_instantiation {
if ($1) { if ($1) scope_stack.top()->addChild($1);
currmodule->addChild($1);
} else {
delete $1;
}
} |
TOK_ID '=' expr ';' {
for (AssignmentList::iterator iter = currmodule->scope.assignments.begin();
iter != currmodule->scope.assignments.end();
iter++) {
if (iter->first == $1) {
currmodule->scope.assignments.erase(iter);
break;
}
}
currmodule->scope.assignments.push_back(Assignment($1, $3));
} | } |
assignment |
TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' { TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' {
Module *p = currmodule; Module *newmodule = new Module();
module_stack.push_back(currmodule); newmodule->definition_arguments = *$4;
currmodule = new Module(); scope_stack.top()->modules[$2] = newmodule;
p->scope.modules[$2] = currmodule; scope_stack.push(&newmodule->scope);
currmodule->definition_arguments = *$4;
free($2); free($2);
delete $4; delete $4;
} statement { } statement {
currmodule = module_stack.back(); scope_stack.pop();
module_stack.pop_back();
} | } |
TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr { TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr {
Function *func = new Function(); Function *func = new Function();
func->definition_arguments = *$4; func->definition_arguments = *$4;
func->expr = $8; func->expr = $8;
currmodule->scope.functions[$2] = func; scope_stack.top()->functions[$2] = func;
free($2); free($2);
delete $4; delete $4;
} ';' ; } ';' ;
/* Will return a dummy parent node with zero or more children */
children_instantiation:
module_instantiation {
$$ = new std::vector<ModuleInstantiation*>;
if ($1) {
$$->push_back($1);
}
} |
'{' module_instantiation_list '}' {
$$ = $2;
} ;
if_statement: if_statement:
TOK_IF '(' expr ')' children_instantiation { TOK_IF '(' expr ')' {
$$ = new IfElseModuleInstantiation(); $<ifelse>if = new IfElseModuleInstantiation();
$$->arguments.push_back(Assignment("", $3)); $<ifelse>if->arguments.push_back(Assignment("", $3));
$$->setPath(parser_source_path); $<ifelse>if->setPath(parser_source_path);
scope_stack.push(&$<ifelse>if->scope);
if ($$) { }[if] child_statement {
$$->scope.children = *$5; scope_stack.pop();
} else { $$ = $<ifelse>if;
for (size_t i = 0; i < $5->size(); i++) } ;
delete (*$5)[i];
}
delete $5;
} ;
ifelse_statement: ifelse_statement:
if_statement { if_statement {
$$ = $1; $$ = $1;
} | } |
if_statement TOK_ELSE children_instantiation { if_statement TOK_ELSE {
scope_stack.push(&$1->else_scope);
}[else] child_statement {
scope_stack.pop();
$$ = $1; $$ = $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:
'!' module_instantiation { '!' module_instantiation {
@ -239,35 +212,28 @@ module_instantiation:
delete $2; delete $2;
$$ = NULL; $$ = NULL;
} | } |
single_module_instantiation ';' { single_module_instantiation {
$$ = $1; $<inst>inst = $1;
} | scope_stack.push(&$<inst>inst->scope);
single_module_instantiation children_instantiation { }[inst] child_statement {
$$ = $1; scope_stack.pop();
if ($$) { $$ = $<inst>inst;
$$->scope.children = *$2; } |
} else { ifelse_statement {
for (size_t i = 0; i < $2->size(); i++) $$ = $1;
delete (*$2)[i]; } ;
}
delete $2;
} |
ifelse_statement {
$$ = $1;
} ;
module_instantiation_list: child_statement:
/* empty */ { ';' |
$$ = new std::vector<ModuleInstantiation*>; '{' child_statements '}' |
module_instantiation {
if ($1) scope_stack.top()->addChild($1);
} | } |
module_instantiation_list module_instantiation { assignment ;
$$ = $1;
if ($$) { child_statements:
if ($2) $$->push_back($2); /* empty */ |
} else { child_statements child_statement ;
delete $2;
}
} ;
single_module_instantiation: single_module_instantiation:
TOK_ID '(' arguments_call ')' { TOK_ID '(' arguments_call ')' {
@ -295,9 +261,7 @@ TOK_ID {
free($1); free($1);
} | } |
expr '.' TOK_ID { expr '.' TOK_ID {
$$ = new Expression(); $$ = new Expression("N", $1);
$$->type = "N";
$$->children.push_back($1);
$$->var_name = $3; $$->var_name = $3;
free($3); free($3);
} | } |
@ -330,95 +294,52 @@ TOK_NUMBER {
$$ = $2; $$ = $2;
} | } |
expr '*' expr { expr '*' expr {
$$ = new Expression(); $$ = new Expression("*", $1, $3);
$$->type = "*";
$$->children.push_back($1);
$$->children.push_back($3);
} | } |
expr '/' expr { expr '/' expr {
$$ = new Expression(); $$ = new Expression("/", $1, $3);
$$->type = "/";
$$->children.push_back($1);
$$->children.push_back($3);
} | } |
expr '%' expr { expr '%' expr {
$$ = new Expression(); $$ = new Expression("%", $1, $3);
$$->type = "%";
$$->children.push_back($1);
$$->children.push_back($3);
} | } |
expr '+' expr { expr '+' expr {
$$ = new Expression(); $$ = new Expression("+", $1, $3);
$$->type = "+";
$$->children.push_back($1);
$$->children.push_back($3);
} | } |
expr '-' expr { expr '-' expr {
$$ = new Expression(); $$ = new Expression("-", $1, $3);
$$->type = "-";
$$->children.push_back($1);
$$->children.push_back($3);
} | } |
expr '<' expr { expr '<' expr {
$$ = new Expression(); $$ = new Expression("<", $1, $3);
$$->type = "<";
$$->children.push_back($1);
$$->children.push_back($3);
} | } |
expr LE expr { expr LE expr {
$$ = new Expression(); $$ = new Expression("<=", $1, $3);
$$->type = "<=";
$$->children.push_back($1);
$$->children.push_back($3);
} | } |
expr EQ expr { expr EQ expr {
$$ = new Expression(); $$ = new Expression("==", $1, $3);
$$->type = "==";
$$->children.push_back($1);
$$->children.push_back($3);
} | } |
expr NE expr { expr NE expr {
$$ = new Expression(); $$ = new Expression("!=", $1, $3);
$$->type = "!=";
$$->children.push_back($1);
$$->children.push_back($3);
} | } |
expr GE expr { expr GE expr {
$$ = new Expression(); $$ = new Expression(">=", $1, $3);
$$->type = ">=";
$$->children.push_back($1);
$$->children.push_back($3);
} | } |
expr '>' expr { expr '>' expr {
$$ = new Expression(); $$ = new Expression(">", $1, $3);
$$->type = ">";
$$->children.push_back($1);
$$->children.push_back($3);
} | } |
expr AND expr { expr AND expr {
$$ = new Expression(); $$ = new Expression("&&", $1, $3);
$$->type = "&&";
$$->children.push_back($1);
$$->children.push_back($3);
} | } |
expr OR expr { expr OR expr {
$$ = new Expression(); $$ = new Expression("||", $1, $3);
$$->type = "||";
$$->children.push_back($1);
$$->children.push_back($3);
} | } |
'+' expr { '+' expr {
$$ = $2; $$ = $2;
} | } |
'-' expr { '-' expr {
$$ = new Expression(); $$ = new Expression("I", $2);
$$->type = "I";
$$->children.push_back($2);
} | } |
'!' expr { '!' expr {
$$ = new Expression(); $$ = new Expression("!", $2);
$$->type = "!";
$$->children.push_back($2);
} | } |
'(' expr ')' { '(' expr ')' {
$$ = $2; $$ = $2;
@ -431,10 +352,7 @@ expr '?' expr ':' expr {
$$->children.push_back($5); $$->children.push_back($5);
} | } |
expr '[' expr ']' { expr '[' expr ']' {
$$ = new Expression(); $$ = new Expression("[]", $1, $3);
$$->type = "[]";
$$->children.push_back($1);
$$->children.push_back($3);
} | } |
TOK_ID '(' arguments_call ')' { TOK_ID '(' arguments_call ')' {
$$ = new Expression(); $$ = new Expression();
@ -450,9 +368,7 @@ optional_commas:
vector_expr: vector_expr:
expr { expr {
$$ = new Expression(); $$ = new Expression("V", $1);
$$->type = 'V';
$$->children.push_back($1);
} | } |
vector_expr ',' optional_commas expr { vector_expr ',' optional_commas expr {
$$ = $1; $$ = $1;
@ -519,7 +435,6 @@ void yyerror (char const *s)
{ {
// FIXME: We leak memory on parser errors... // FIXME: We leak memory on parser errors...
PRINTB("Parser error in line %d: %s\n", lexerget_lineno() % s); PRINTB("Parser error in line %d: %s\n", lexerget_lineno() % s);
currmodule = NULL;
} }
FileModule *parse(const char *text, const char *path, int debug) 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_input_buffer = text;
parser_source_path = boosty::absolute(std::string(path)).string(); parser_source_path = boosty::absolute(std::string(path)).string();
module_stack.clear();
rootmodule = new FileModule(); rootmodule = new FileModule();
currmodule = rootmodule;
rootmodule->setModulePath(path); rootmodule->setModulePath(path);
scope_stack.push(&rootmodule->scope);
// PRINTB_NOCACHE("New module: %s %p", "root" % rootmodule); // PRINTB_NOCACHE("New module: %s %p", "root" % rootmodule);
parserdebug = debug; parserdebug = debug;
@ -543,5 +457,6 @@ FileModule *parse(const char *text, const char *path, int debug)
if (parserretval != 0) return NULL; if (parserretval != 0) return NULL;
parser_error_pos = -1; parser_error_pos = -1;
scope_stack.pop();
return rootmodule; return rootmodule;
} }

View File

@ -13,7 +13,11 @@ include(CMakeParseArguments.cmake)
# Detect Lion and force gcc # Detect Lion and force gcc
IF (APPLE) IF (APPLE)
EXECUTE_PROCESS(COMMAND sw_vers -productVersion OUTPUT_VARIABLE MACOSX_VERSION) 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") message("Detected Lion or later")
set(CMAKE_C_COMPILER "gcc") set(CMAKE_C_COMPILER "gcc")
set(CMAKE_CXX_COMPILER "g++") set(CMAKE_CXX_COMPILER "g++")
@ -325,9 +329,8 @@ if (WIN32)
set(FLEX_UNISTD_FLAG "-DYY_NO_UNISTD_H") set(FLEX_UNISTD_FLAG "-DYY_NO_UNISTD_H")
endif() endif()
FLEX_TARGET(OpenSCADlexer ../src/lexer.l ${CMAKE_CURRENT_BINARY_DIR}/lexer.cpp COMPILE_FLAGS "-Plexer ${FLEX_UNISTD_FLAG}") 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) ADD_FLEX_BISON_DEPENDENCY(OpenSCADlexer OpenSCADparser)
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/parser_yacc.c PROPERTIES LANGUAGE "CXX")
# CGAL # CGAL