%{ #include #include #include #include #include #include #include "config.h" extern "C" { int yyparse(); void yyerror(const char *); int yylook(); int yywrap(); } int yylex(void); NTPM::Configurator *configurator; NTPM::Configurator::Class *curcl; NTPM::Configurator::Subroutine *cursub; string *currentrhs = NULL; int nlist_entries = 0; bool in_class = false; int ncalls = 0; string numtostr(int n) { char ns[100]; sprintf(ns, "%d", n); return string(ns); } %} %union { int val; string *name; } %token CLASSKEYWORD %token SUBROUTINEKEYWORD %token CALLKEYWORD %token USINGKEYWORD %token NAME %token QUALIFIED_NAME %% class_body : start_of_class statement_list object_definition_list ; start_of_class : { if(curcl == NULL) { curcl = &configurator->root_class; } else { NTPM::Configurator::Class next_guy(configurator, curcl); curcl->children.push_front(next_guy); curcl = &(*curcl->children.begin()); } in_class = true; } ; object_definition_list : object_definition_list definition | /* empty */ ; definition : class_definition | subroutine_definition ; subroutine_definition : start_of_subroutine SUBROUTINEKEYWORD NAME '{' statement_list '}' { cursub->name = *$3; in_class = true; delete $3; } ; start_of_subroutine : { NTPM::Configurator::Subroutine thissub(configurator, curcl); curcl->subroutines.push_front(thissub); cursub = &(*curcl->subroutines.begin()); in_class = false; } ; class_definition : CLASSKEYWORD NAME '{' class_body '}' { curcl->name = *$2; curcl = curcl->parent; delete $2; } ; statement_list : statement_list statement | /*emtpy*/ ; statement : assignment | subroutine_call | using_statement ; using_statement : USINGKEYWORD NAME { if(!in_class) yyerror("'using' only works in section defintion."); curcl->parents.push_back(*$2); delete $2; } ; assignment : NAME '=' assignment_rhs { if(in_class) curcl->bindings[ *$1 ] = *currentrhs; else cursub->bindings[ *$1 ] = *currentrhs; delete $1; delete currentrhs; currentrhs = NULL; } ; assignment_rhs : simple_value | start_of_namelist '{' namelist '}' end_of_namelist ; simple_value : NAME { assert(currentrhs==NULL); currentrhs = new string(*$1); delete $1; } ; start_of_namelist : /* empty */ { assert(currentrhs==NULL); nlist_entries = 0; currentrhs = new string("{"); } ; end_of_namelist : /* empty */ { (*currentrhs) += "}"; *currentrhs = numtostr(nlist_entries)+(*currentrhs); nlist_entries = 0; } ; namelist : namelist namelist_component | /* empty */ ; namelist_component : NAME { (*currentrhs) += *$1 + " "; nlist_entries++; delete $1; } ; subroutine_call : CALLKEYWORD NAME { char callid[50]; sprintf(callid, "call%d", ncalls++); if(in_class) curcl->bindings[ callid ] = *$2; else cursub->bindings[ callid ] = *$2; delete $2; } ; %% namespace NTPM { extern "C" { extern FILE *yyin; } void parse_configuration_file(NTPM::Configurator *_configurator) { configurator = _configurator; yyin = fopen(configurator->GetFilename().c_str(), "r"); if(yyin == NULL) throw std::runtime_error(strerror(errno)); curcl = NULL; yyparse(); fclose(yyin); } } extern "C" void yyerror(const char *str) { extern int line_number; ostrstream osr; osr << "error in config file (line " << line_number << "): " << str << "." << endl; throw runtime_error(string(osr.str())); } int yywrap() { return 1; }