diff options
author | Marius Kintel <marius@kintel.net> | 2013-04-27 05:01:45 (GMT) |
---|---|---|
committer | Marius Kintel <marius@kintel.net> | 2013-04-27 05:01:45 (GMT) |
commit | 17df3f6275fce73119c311cc73a6ad057d3b47ee (patch) | |
tree | 6c907e241b53c40c10743bbf08754b86a13f6457 /src/parser.y | |
parent | 6b3daa748543f13cc7cf8eff1c9efeebd6dc3a14 (diff) | |
parent | 7858b0443e7fb09134f2b69a535417688353c0bb (diff) |
Merge pull request #328 from openscad/issue116
Issue116
Diffstat (limited to 'src/parser.y')
-rw-r--r-- | src/parser.y | 795 |
1 files changed, 385 insertions, 410 deletions
diff --git a/src/parser.y b/src/parser.y index 70aebba..fd6b164 100644 --- a/src/parser.y +++ b/src/parser.y @@ -34,6 +34,7 @@ #include <unistd.h> #endif +#include "typedefs.h" #include "module.h" #include "expression.h" #include "value.h" @@ -43,50 +44,39 @@ #include <boost/foreach.hpp> #include <boost/filesystem.hpp> -namespace fs = boost::filesystem; + namespace fs = boost::filesystem; #include "boosty.h" -int parser_error_pos = -1; + int parser_error_pos = -1; -int parserlex(void); -void yyerror(char const *s); + int parserlex(void); + void yyerror(char const *s); -int lexerget_lineno(void); -int lexerlex_destroy(void); -int lexerlex(void); + int lexerget_lineno(void); + int lexerlex_destroy(void); + int lexerlex(void); -std::vector<Module*> module_stack; -Module *currmodule; + std::vector<Module*> module_stack; + Module *currmodule; -extern void lexerdestroy(); -extern FILE *lexerin; -extern const char *parser_input_buffer; -const char *parser_input_buffer; -std::string parser_source_path; + extern void lexerdestroy(); + extern FILE *lexerin; + extern const char *parser_input_buffer; + const char *parser_input_buffer; + std::string parser_source_path; -class ArgContainer { -public: - std::string argname; - Expression *argexpr; -}; -class ArgsContainer { -public: - std::vector<std::string> argnames; - std::vector<Expression*> argexpr; -}; - -%} + %} %union { - char *text; - double number; - class Value *value; - class Expression *expr; - class ModuleInstantiation *inst; - std::vector<ModuleInstantiation*> *instvec; - class IfElseModuleInstantiation *ifelse; - class ArgContainer *arg; - class ArgsContainer *args; + char *text; + double number; + class Value *value; + class Expression *expr; + class ModuleInstantiation *inst; + std::vector<ModuleInstantiation*> *instvec; + class IfElseModuleInstantiation *ifelse; + Assignment *arg; + AssignmentList *args; } %token TOK_MODULE @@ -139,427 +129,412 @@ public: %% input: - /* empty */ | - TOK_USE { currmodule->usedlibs[$1] = NULL; } input | - statement input ; +/* empty */ | +TOK_USE { currmodule->usedlibs[$1] = NULL; } input | +statement input ; inner_input: - /* empty */ | - statement inner_input ; +/* empty */ | +statement inner_input ; statement: - ';' | - '{' inner_input '}' | - module_instantiation { - if ($1) { - currmodule->addChild($1); - } else { - delete $1; - } - } | - TOK_ID '=' expr ';' { - std::list<std::string>::iterator found = std::find(currmodule->assignments_var.begin(), currmodule->assignments_var.end(),$1); - if (found != currmodule->assignments_var.end()) currmodule->assignments_var.erase(found); - currmodule->assignments_var.push_back($1); - currmodule->assignments[$1] = $3; - } | - TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' { - Module *p = currmodule; - module_stack.push_back(currmodule); - currmodule = new Module(); - p->modules[$2] = currmodule; - currmodule->argnames = $4->argnames; - currmodule->argexpr = $4->argexpr; - free($2); - delete $4; - } statement { - currmodule = module_stack.back(); - module_stack.pop_back(); - } | - TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr { - Function *func = new Function(); - func->argnames = $4->argnames; - func->argexpr = $4->argexpr; - func->expr = $8; - currmodule->functions[$2] = func; - free($2); - delete $4; - } ';' ; +';' | +'{' inner_input '}' | +module_instantiation { + if ($1) { + currmodule->addChild($1); + } else { + delete $1; + } +} | +TOK_ID '=' expr ';' { + std::list<std::string>::iterator found = std::find(currmodule->assignments_var.begin(), currmodule->assignments_var.end(),$1); + if (found != currmodule->assignments_var.end()) currmodule->assignments_var.erase(found); + currmodule->assignments_var.push_back($1); + currmodule->assignments[$1] = $3; +} | +TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' { + Module *p = currmodule; + module_stack.push_back(currmodule); + currmodule = new Module(); + p->modules[$2] = currmodule; + currmodule->definition_arguments = *$4; + free($2); + delete $4; +} statement { + currmodule = module_stack.back(); + module_stack.pop_back(); + } | + TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr { + Function *func = new Function(); + func->definition_arguments = *$4; + func->expr = $8; + currmodule->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<ModuleInstantiation*>; - if ($1) { - $$->push_back($1); - } - } | - '{' module_instantiation_list '}' { - $$ = $2; - } ; +module_instantiation { + $$ = new std::vector<ModuleInstantiation*>; + if ($1) { + $$->push_back($1); + } +} | +'{' module_instantiation_list '}' { + $$ = $2; +} ; if_statement: - TOK_IF '(' expr ')' children_instantiation { - $$ = new IfElseModuleInstantiation(); - $$->argnames.push_back(""); - $$->argexpr.push_back($3); - $$->setPath(parser_source_path); - - if ($$) { - $$->children = *$5; - } else { - for (size_t i = 0; i < $5->size(); i++) - delete (*$5)[i]; - } - delete $5; - } ; +TOK_IF '(' expr ')' children_instantiation { + $$ = new IfElseModuleInstantiation(); + $$->arguments.push_back(Assignment("", $3)); + $$->setPath(parser_source_path); + + if ($$) { + $$->children = *$5; + } else { + for (size_t i = 0; i < $5->size(); i++) + delete (*$5)[i]; + } + delete $5; +} ; ifelse_statement: - if_statement { - $$ = $1; - } | - if_statement TOK_ELSE children_instantiation { - $$ = $1; - if ($$) { - $$->else_children = *$3; - } else { - for (size_t i = 0; i < $3->size(); i++) - delete (*$3)[i]; - } - delete $3; - } ; +if_statement { + $$ = $1; +} | +if_statement TOK_ELSE children_instantiation { + $$ = $1; + if ($$) { + $$->else_children = *$3; + } else { + for (size_t i = 0; i < $3->size(); i++) + delete (*$3)[i]; + } + delete $3; +} ; module_instantiation: - '!' module_instantiation { - $$ = $2; - if ($$) $$->tag_root = true; - } | - '#' module_instantiation { - $$ = $2; - if ($$) $$->tag_highlight = true; - } | - '%' module_instantiation { - $$ = $2; - if ($$) $$->tag_background = true; - } | - '*' module_instantiation { - delete $2; - $$ = NULL; - } | - single_module_instantiation ';' { - $$ = $1; - } | - single_module_instantiation children_instantiation { - $$ = $1; - if ($$) { - $$->children = *$2; - } else { - for (size_t i = 0; i < $2->size(); i++) - delete (*$2)[i]; - } - delete $2; - } | - ifelse_statement { - $$ = $1; - } ; +'!' module_instantiation { + $$ = $2; + if ($$) $$->tag_root = true; +} | +'#' module_instantiation { + $$ = $2; + if ($$) $$->tag_highlight = true; +} | +'%' module_instantiation { + $$ = $2; + if ($$) $$->tag_background = true; +} | +'*' module_instantiation { + delete $2; + $$ = NULL; +} | +single_module_instantiation ';' { + $$ = $1; +} | +single_module_instantiation children_instantiation { + $$ = $1; + if ($$) { + $$->children = *$2; + } else { + for (size_t i = 0; i < $2->size(); i++) + delete (*$2)[i]; + } + delete $2; +} | +ifelse_statement { + $$ = $1; +} ; module_instantiation_list: - /* empty */ { - $$ = new std::vector<ModuleInstantiation*>; - } | - module_instantiation_list module_instantiation { - $$ = $1; - if ($$) { - if ($2) $$->push_back($2); - } else { - delete $2; - } - } ; +/* empty */ { + $$ = new std::vector<ModuleInstantiation*>; +} | +module_instantiation_list module_instantiation { + $$ = $1; + if ($$) { + if ($2) $$->push_back($2); + } else { + delete $2; + } +} ; single_module_instantiation: - TOK_ID '(' arguments_call ')' { - $$ = new ModuleInstantiation($1); - $$->argnames = $3->argnames; - $$->argexpr = $3->argexpr; - $$->setPath(parser_source_path); - free($1); - delete $3; - } +TOK_ID '(' arguments_call ')' { + $$ = new ModuleInstantiation($1); + $$->arguments = *$3; + $$->setPath(parser_source_path); + free($1); + delete $3; +} expr: - TOK_TRUE { - $$ = new Expression(Value(true)); - } | - TOK_FALSE { - $$ = new Expression(Value(false)); - } | - TOK_UNDEF { - $$ = new Expression(Value::undefined); - } | - TOK_ID { - $$ = new Expression(); - $$->type = "L"; - $$->var_name = $1; - free($1); - } | - expr '.' TOK_ID { - $$ = new Expression(); - $$->type = "N"; - $$->children.push_back($1); - $$->var_name = $3; - free($3); - } | - TOK_STRING { - $$ = new Expression(Value(std::string($1))); - free($1); - } | - TOK_NUMBER { - $$ = new Expression(Value($1)); - } | - '[' expr ':' expr ']' { - Expression *e_one = new Expression(Value(1.0)); - $$ = new Expression(); - $$->type = "R"; - $$->children.push_back($2); - $$->children.push_back(e_one); - $$->children.push_back($4); - } | - '[' expr ':' expr ':' expr ']' { - $$ = new Expression(); - $$->type = "R"; - $$->children.push_back($2); - $$->children.push_back($4); - $$->children.push_back($6); - } | - '[' optional_commas ']' { - $$ = new Expression(Value(Value::VectorType())); - } | - '[' vector_expr optional_commas ']' { - $$ = $2; - } | - expr '*' expr { - $$ = new Expression(); - $$->type = "*"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr '/' expr { - $$ = new Expression(); - $$->type = "/"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr '%' expr { - $$ = new Expression(); - $$->type = "%"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr '+' expr { - $$ = new Expression(); - $$->type = "+"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr '-' expr { - $$ = new Expression(); - $$->type = "-"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr '<' expr { - $$ = new Expression(); - $$->type = "<"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr LE expr { - $$ = new Expression(); - $$->type = "<="; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr EQ expr { - $$ = new Expression(); - $$->type = "=="; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr NE expr { - $$ = new Expression(); - $$->type = "!="; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr GE expr { - $$ = new Expression(); - $$->type = ">="; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr '>' expr { - $$ = new Expression(); - $$->type = ">"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr AND expr { - $$ = new Expression(); - $$->type = "&&"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr OR expr { - $$ = new Expression(); - $$->type = "||"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - '+' expr { - $$ = $2; - } | - '-' expr { - $$ = new Expression(); - $$->type = "I"; - $$->children.push_back($2); - } | - '!' expr { - $$ = new Expression(); - $$->type = "!"; - $$->children.push_back($2); - } | - '(' expr ')' { - $$ = $2; - } | - expr '?' expr ':' expr { - $$ = new Expression(); - $$->type = "?:"; - $$->children.push_back($1); - $$->children.push_back($3); - $$->children.push_back($5); - } | - expr '[' expr ']' { - $$ = new Expression(); - $$->type = "[]"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - TOK_ID '(' arguments_call ')' { - $$ = new Expression(); - $$->type = "F"; - $$->call_funcname = $1; - $$->call_argnames = $3->argnames; - $$->children = $3->argexpr; - free($1); - delete $3; - } ; +TOK_TRUE { + $$ = new Expression(Value(true)); +} | +TOK_FALSE { + $$ = new Expression(Value(false)); +} | +TOK_UNDEF { + $$ = new Expression(Value::undefined); +} | +TOK_ID { + $$ = new Expression(); + $$->type = "L"; + $$->var_name = $1; + free($1); +} | +expr '.' TOK_ID { + $$ = new Expression(); + $$->type = "N"; + $$->children.push_back($1); + $$->var_name = $3; + free($3); +} | +TOK_STRING { + $$ = new Expression(Value(std::string($1))); + free($1); +} | +TOK_NUMBER { + $$ = new Expression(Value($1)); +} | +'[' expr ':' expr ']' { + Expression *e_one = new Expression(Value(1.0)); + $$ = new Expression(); + $$->type = "R"; + $$->children.push_back($2); + $$->children.push_back(e_one); + $$->children.push_back($4); +} | +'[' expr ':' expr ':' expr ']' { + $$ = new Expression(); + $$->type = "R"; + $$->children.push_back($2); + $$->children.push_back($4); + $$->children.push_back($6); +} | +'[' optional_commas ']' { + $$ = new Expression(Value(Value::VectorType())); +} | +'[' vector_expr optional_commas ']' { + $$ = $2; +} | +expr '*' expr { + $$ = new Expression(); + $$->type = "*"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr '/' expr { + $$ = new Expression(); + $$->type = "/"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr '%' expr { + $$ = new Expression(); + $$->type = "%"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr '+' expr { + $$ = new Expression(); + $$->type = "+"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr '-' expr { + $$ = new Expression(); + $$->type = "-"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr '<' expr { + $$ = new Expression(); + $$->type = "<"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr LE expr { + $$ = new Expression(); + $$->type = "<="; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr EQ expr { + $$ = new Expression(); + $$->type = "=="; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr NE expr { + $$ = new Expression(); + $$->type = "!="; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr GE expr { + $$ = new Expression(); + $$->type = ">="; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr '>' expr { + $$ = new Expression(); + $$->type = ">"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr AND expr { + $$ = new Expression(); + $$->type = "&&"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr OR expr { + $$ = new Expression(); + $$->type = "||"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +'+' expr { + $$ = $2; +} | +'-' expr { + $$ = new Expression(); + $$->type = "I"; + $$->children.push_back($2); +} | +'!' expr { + $$ = new Expression(); + $$->type = "!"; + $$->children.push_back($2); +} | +'(' expr ')' { + $$ = $2; +} | +expr '?' expr ':' expr { + $$ = new Expression(); + $$->type = "?:"; + $$->children.push_back($1); + $$->children.push_back($3); + $$->children.push_back($5); +} | +expr '[' expr ']' { + $$ = new Expression(); + $$->type = "[]"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +TOK_ID '(' arguments_call ')' { + $$ = new Expression(); + $$->type = "F"; + $$->call_funcname = $1; + $$->call_arguments = *$3; + free($1); + delete $3; +} ; optional_commas: - ',' optional_commas | ; +',' optional_commas | ; vector_expr: - expr { - $$ = new Expression(); - $$->type = 'V'; - $$->children.push_back($1); - } | - vector_expr ',' optional_commas expr { - $$ = $1; - $$->children.push_back($4); - } ; +expr { + $$ = new Expression(); + $$->type = 'V'; + $$->children.push_back($1); +} | +vector_expr ',' optional_commas expr { + $$ = $1; + $$->children.push_back($4); +} ; arguments_decl: - /* empty */ { - $$ = new ArgsContainer(); - } | - argument_decl { - $$ = new ArgsContainer(); - $$->argnames.push_back($1->argname); - $$->argexpr.push_back($1->argexpr); - delete $1; - } | - arguments_decl ',' optional_commas argument_decl { - $$ = $1; - $$->argnames.push_back($4->argname); - $$->argexpr.push_back($4->argexpr); - delete $4; - } ; +/* empty */ { + $$ = new AssignmentList(); +} | +argument_decl { + $$ = new AssignmentList(); + $$->push_back(*$1); + delete $1; +} | +arguments_decl ',' optional_commas argument_decl { + $$ = $1; + $$->push_back(*$4); + delete $4; +} ; argument_decl: - TOK_ID { - $$ = new ArgContainer(); - $$->argname = $1; - $$->argexpr = NULL; - free($1); - } | - TOK_ID '=' expr { - $$ = new ArgContainer(); - $$->argname = $1; - $$->argexpr = $3; - free($1); - } ; +TOK_ID { + $$ = new Assignment($1, NULL); + free($1); +} | +TOK_ID '=' expr { + $$ = new Assignment($1, $3); + free($1); +} ; arguments_call: - /* empty */ { - $$ = new ArgsContainer(); - } | - argument_call { - $$ = new ArgsContainer(); - $$->argnames.push_back($1->argname); - $$->argexpr.push_back($1->argexpr); - delete $1; - } | - arguments_call ',' optional_commas argument_call { - $$ = $1; - $$->argnames.push_back($4->argname); - $$->argexpr.push_back($4->argexpr); - delete $4; - } ; +/* empty */ { + $$ = new AssignmentList(); +} | +argument_call { + $$ = new AssignmentList(); + $$->push_back(*$1); + delete $1; +} | +arguments_call ',' optional_commas argument_call { + $$ = $1; + $$->push_back(*$4); + delete $4; +} ; argument_call: - expr { - $$ = new ArgContainer(); - $$->argexpr = $1; - } | - TOK_ID '=' expr { - $$ = new ArgContainer(); - $$->argname = $1; - $$->argexpr = $3; - free($1); - } ; +expr { + $$ = new Assignment("", $1); +} | +TOK_ID '=' expr { + $$ = new Assignment($1, $3); + free($1); +} ; %% int parserlex(void) { - return lexerlex(); + return lexerlex(); } 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; + // FIXME: We leak memory on parser errors... + PRINTB("Parser error in line %d: %s\n", lexerget_lineno() % s); + currmodule = NULL; } Module *parse(const char *text, const char *path, int debug) { - lexerin = NULL; - parser_error_pos = -1; - parser_input_buffer = text; - parser_source_path = boosty::absolute(std::string(path)).string(); + lexerin = NULL; + parser_error_pos = -1; + parser_input_buffer = text; + parser_source_path = boosty::absolute(std::string(path)).string(); - module_stack.clear(); - Module *rootmodule = currmodule = new Module(); - // PRINTB_NOCACHE("New module: %s %p", "root" % rootmodule); + module_stack.clear(); + Module *rootmodule = currmodule = new Module(); + rootmodule->setModulePath(path); + // PRINTB_NOCACHE("New module: %s %p", "root" % rootmodule); - parserdebug = debug; - int parserretval = parserparse(); - lexerdestroy(); - lexerlex_destroy(); + parserdebug = debug; + int parserretval = parserparse(); + lexerdestroy(); + lexerlex_destroy(); - if (parserretval != 0) return NULL; + if (parserretval != 0) return NULL; - parser_error_pos = -1; - return rootmodule; + parser_error_pos = -1; + return rootmodule; } |