diff options
author | Marius Kintel <marius@kintel.net> | 2013-05-24 14:16:20 (GMT) |
---|---|---|
committer | Marius Kintel <marius@kintel.net> | 2013-05-24 14:16:20 (GMT) |
commit | 26046f6f0c4a774cbbb2af8ae7dc0e687963440c (patch) | |
tree | 38ff04fc460e8aa55134fb1ee6167fafb90a3423 /src/parser.y | |
parent | eefcd6d0b271642d470cd55bc47d1579d943938e (diff) | |
parent | 95e399e06c6522f3fa67679808a1d52815368efa (diff) |
Merge branch 'master' into epec-kernel
Diffstat (limited to 'src/parser.y')
-rw-r--r-- | src/parser.y | 746 |
1 files changed, 324 insertions, 422 deletions
diff --git a/src/parser.y b/src/parser.y index 536f4ef..2b07f14 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,43 +44,38 @@ #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::stack<LocalScope *> scope_stack; + FileModule *rootmodule; -class ArgContainer { -public: - std::string argname; - Expression *argexpr; -}; -class ArgsContainer { -public: - std::vector<std::string> argnames; - std::vector<Expression*> argexpr; -}; + extern void lexerdestroy(); + extern FILE *lexerin; + extern const char *parser_input_buffer; + const char *parser_input_buffer; + std::string parser_source_path; -%} + %} %union { - char *text; - double number; - class Value *value; - class Expression *expr; - class ModuleInstantiation *inst; - class IfElseModuleInstantiation *ifelse; - class ArgContainer *arg; - class ArgsContainer *args; + char *text; + double number; + class Value *value; + class Expression *expr; + class ModuleInstantiation *inst; + class IfElseModuleInstantiation *ifelse; + Assignment *arg; + AssignmentList *args; } %token TOK_MODULE @@ -117,8 +113,6 @@ public: %type <inst> module_instantiation %type <ifelse> if_statement %type <ifelse> ifelse_statement -%type <inst> children_instantiation -%type <inst> module_instantiation_list %type <inst> single_module_instantiation %type <args> arguments_call @@ -132,434 +126,342 @@ public: %% input: - /* empty */ | - TOK_USE { currmodule->usedlibs[$1] = NULL; } input | - statement input ; +/* empty */ | +TOK_USE { rootmodule->usedlibs[$1] = NULL; } input | +statement input ; inner_input: - /* empty */ | - statement inner_input ; +/* empty */ | +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: - ';' | - '{' 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; - } ';' ; - -/* Will return a dummy parent node with zero or more children */ -children_instantiation: - module_instantiation { - $$ = new ModuleInstantiation(); - if ($1) { - $$->children.push_back($1); - } - } | - '{' module_instantiation_list '}' { - $$ = $2; - } ; +';' | +'{' inner_input '}' | +module_instantiation { + if ($1) scope_stack.top()->addChild($1); +} | +assignment | +TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' { + Module *newmodule = new Module(); + newmodule->definition_arguments = *$4; + scope_stack.top()->modules[$2] = newmodule; + scope_stack.push(&newmodule->scope); + free($2); + delete $4; +} statement { + scope_stack.pop(); + } | + TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr { + Function *func = new Function(); + func->definition_arguments = *$4; + func->expr = $8; + scope_stack.top()->functions[$2] = func; + free($2); + delete $4; + } ';' ; if_statement: - TOK_IF '(' expr ')' children_instantiation { - $$ = new IfElseModuleInstantiation(); - $$->argnames.push_back(""); - $$->argexpr.push_back($3); - - if ($$) { - $$->children = $5->children; - } else { - for (size_t i = 0; i < $5->children.size(); i++) - delete $5->children[i]; - } - $5->children.clear(); - delete $5; - } ; +TOK_IF '(' expr ')' { + $<ifelse>$ = new IfElseModuleInstantiation(); + $<ifelse>$->arguments.push_back(Assignment("", $3)); + $<ifelse>$->setPath(parser_source_path); + scope_stack.push(&$<ifelse>$->scope); +} child_statement { + scope_stack.pop(); + $$ = $<ifelse>5; + } ; ifelse_statement: - if_statement { - $$ = $1; - } | - if_statement TOK_ELSE children_instantiation { - $$ = $1; - if ($$) { - $$->else_children = $3->children; - } else { - for (size_t i = 0; i < $3->children.size(); i++) - delete $3->children[i]; - } - $3->children.clear(); - delete $3; - } ; +if_statement { + $$ = $1; +} | +if_statement TOK_ELSE { + scope_stack.push(&$1->else_scope); +} child_statement { + scope_stack.pop(); + $$ = $1; + } ; 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->children; - } else { - for (size_t i = 0; i < $2->children.size(); i++) - delete $2->children[i]; - } - $2->children.clear(); - delete $2; - } | - ifelse_statement { - $$ = $1; - } ; - -module_instantiation_list: - /* empty */ { - $$ = new ModuleInstantiation(); - } | - module_instantiation_list module_instantiation { - $$ = $1; - if ($$) { - if ($2) $$->children.push_back($2); - } else { - delete $2; - } - } ; +'!' 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 { + $<inst>$ = $1; + scope_stack.push(&$1->scope); +} child_statement { + scope_stack.pop(); + $$ = $<inst>2; + } | + ifelse_statement { + $$ = $1; + } ; + +child_statement: +';' | +'{' child_statements '}' | +module_instantiation { + if ($1) scope_stack.top()->addChild($1); +} ; + +/* + FIXME: This allows for variable declaration in child blocks, not activated yet + | +assignment ; +*/ + +child_statements: +/* empty */ | +child_statements child_statement ; single_module_instantiation: - TOK_ID '(' arguments_call ')' { - $$ = new ModuleInstantiation($1); - $$->argnames = $3->argnames; - $$->argexpr = $3->argexpr; - 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("N", $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("*", $1, $3); +} | +expr '/' expr { + $$ = new Expression("/", $1, $3); +} | +expr '%' expr { + $$ = new Expression("%", $1, $3); +} | +expr '+' expr { + $$ = new Expression("+", $1, $3); +} | +expr '-' expr { + $$ = new Expression("-", $1, $3); +} | +expr '<' expr { + $$ = new Expression("<", $1, $3); +} | +expr LE expr { + $$ = new Expression("<=", $1, $3); +} | +expr EQ expr { + $$ = new Expression("==", $1, $3); +} | +expr NE expr { + $$ = new Expression("!=", $1, $3); +} | +expr GE expr { + $$ = new Expression(">=", $1, $3); +} | +expr '>' expr { + $$ = new Expression(">", $1, $3); +} | +expr AND expr { + $$ = new Expression("&&", $1, $3); +} | +expr OR expr { + $$ = new Expression("||", $1, $3); +} | +'+' expr { + $$ = $2; +} | +'-' expr { + $$ = new Expression("I", $2); +} | +'!' expr { + $$ = new Expression("!", $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("[]", $1, $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("V", $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); } -extern void lexerdestroy(); -extern FILE *lexerin; -extern const char *parser_input_buffer; -const char *parser_input_buffer; -std::string parser_source_path; - -Module *parse(const char *text, const char *path, int debug) +FileModule *parse(const char *text, const char *path, int debug) { - lexerin = NULL; - parser_error_pos = -1; - parser_input_buffer = text; - parser_source_path = std::string(path); - - module_stack.clear(); - Module *rootmodule = currmodule = new Module(); - // PRINTB_NOCACHE("New module: %s %p", "root" % rootmodule); - - parserdebug = debug; - int parserretval = parserparse(); - lexerdestroy(); - lexerlex_destroy(); - - if (parserretval != 0) return NULL; - - parser_error_pos = -1; - return rootmodule; + lexerin = NULL; + parser_error_pos = -1; + parser_input_buffer = text; + parser_source_path = boosty::absolute(std::string(path)).string(); + + rootmodule = new FileModule(); + rootmodule->setModulePath(path); + scope_stack.push(&rootmodule->scope); + // PRINTB_NOCACHE("New module: %s %p", "root" % rootmodule); + + parserdebug = debug; + int parserretval = parserparse(); + lexerdestroy(); + lexerlex_destroy(); + + if (parserretval != 0) return NULL; + + parser_error_pos = -1; + scope_stack.pop(); + return rootmodule; } |