summaryrefslogtreecommitdiff
path: root/src/parser.y
diff options
context:
space:
mode:
authorMarius Kintel <marius@kintel.net>2013-05-24 14:16:20 (GMT)
committerMarius Kintel <marius@kintel.net>2013-05-24 14:16:20 (GMT)
commit26046f6f0c4a774cbbb2af8ae7dc0e687963440c (patch)
tree38ff04fc460e8aa55134fb1ee6167fafb90a3423 /src/parser.y
parenteefcd6d0b271642d470cd55bc47d1579d943938e (diff)
parent95e399e06c6522f3fa67679808a1d52815368efa (diff)
Merge branch 'master' into epec-kernel
Diffstat (limited to 'src/parser.y')
-rw-r--r--src/parser.y746
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;
}
contact: Jan Huwald // Impressum