@ -26,12 +26,16 @@
*/
# include "DSMChartReader.h"
# include "log.h"
# include "AmUtils.h"
# include <dlfcn.h> // dlopen & friends
# include <vector>
using std : : vector ;
# include <string>
using std : : string ;
DSMChartReader : : DSMChartReader ( ) {
}
@ -43,7 +47,7 @@ bool DSMChartReader::is_wsp(const char c) {
}
bool DSMChartReader : : is_snt ( const char c ) {
return c = = ' ; ' | | c = = ' { ' | | c = = ' } ' ;
return c = = ' ; ' | | c = = ' { ' | | c = = ' } ' | | c = = ' [ ' | | c = = ' ] ' ;
}
string DSMChartReader : : getToken ( string str , size_t & pos ) {
@ -128,6 +132,74 @@ DSMAction* DSMChartReader::actionFromToken(const string& str) {
return NULL ;
}
DSMFunction * DSMChartReader : : functionFromToken ( const string & str ) {
string cmd ;
size_t b_pos = str . find ( ' ( ' ) ;
if ( b_pos ! = string : : npos ) {
cmd = str . substr ( 0 , b_pos ) ;
} else {
return NULL ;
}
for ( vector < DSMFunction * > : : iterator it = funcs . begin ( ) ; it ! = funcs . end ( ) ; it + + ) {
if ( ( * it ) - > name = = cmd ) {
DBG ( " found function '%s' in fuction list \n " , cmd . c_str ( ) ) ;
return * it ;
}
}
return NULL ;
}
bool DSMChartReader : : forFromToken ( DSMArrayFor & af , const string & token ) {
string forhdr = token ;
if ( forhdr . length ( ) < 2 | | forhdr [ 0 ] ! = ' ( ' | | forhdr [ forhdr . length ( ) - 1 ] ! = ' ) ' ) {
ERROR ( " syntax error in 'for %s': expected 'for (x in array)' \n " ,
forhdr . c_str ( ) ) ;
return false ;
}
forhdr = forhdr . substr ( 1 , forhdr . length ( ) - 2 ) ;
// q&d
vector < string > forh_v = explode ( forhdr , " in " ) ;
if ( forh_v . size ( ) ! = 2 ) {
ERROR ( " syntax error in 'for %s': expected 'for (x in array)' "
" or 'for (k,v in struct)' \n " ,
forhdr . c_str ( ) ) ;
return false ;
}
vector < string > kv = explode ( forh_v [ 0 ] , " , " ) ;
if ( kv . size ( ) = = 2 ) {
af . for_type = DSMArrayFor : : Struct ;
af . k = kv [ 0 ] ;
af . v = kv [ 1 ] ;
af . array_struct = forh_v [ 1 ] ;
DBG ( " for (%s,%s in %s) { \n " , af . k . c_str ( ) , af . v . c_str ( ) , af . array_struct . c_str ( ) ) ;
} else if ( forh_v [ 1 ] . length ( ) > 7 & &
forh_v [ 1 ] . substr ( 0 , 6 ) = = " range( " & &
forh_v [ 1 ] [ forh_v [ 1 ] . length ( ) - 1 ] = = ' ) ' ) {
af . for_type = DSMArrayFor : : Range ;
string range_s = forh_v [ 1 ] . substr ( 6 , forh_v [ 1 ] . length ( ) - 7 ) ;
vector < string > range_v = explode ( range_s , " , " ) ;
if ( range_v . size ( ) = = 2 ) {
af . v = trim ( range_v [ 0 ] , " " ) ;
af . array_struct = trim ( range_v [ 1 ] , " " ) ;
} else {
af . v = " 0 " ;
af . array_struct = trim ( range_s , " " ) ;
}
af . k = forh_v [ 0 ] ;
DBG ( " for (%s in range(%s, %s) { \n " ,
af . k . c_str ( ) , af . v . c_str ( ) , af . array_struct . c_str ( ) ) ;
} else {
af . for_type = DSMArrayFor : : Array ;
af . array_struct = forh_v [ 1 ] ;
af . k = forh_v [ 0 ] ;
DBG ( " for (%s in %s) { \n " , af . k . c_str ( ) , af . array_struct . c_str ( ) ) ;
}
return true ;
}
DSMCondition * DSMChartReader : : conditionFromToken ( const string & str , bool invert ) {
for ( vector < DSMModule * > : : iterator it =
mods . begin ( ) ; it ! = mods . end ( ) ; it + + ) {
@ -205,6 +277,11 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart,
continue ;
}
if ( token = = " function " ) {
stack . push_back ( new DSMFunction ( ) ) ;
continue ;
}
if ( token = = " initial " ) {
stack . push_back ( new AttribInitial ( ) ) ;
continue ;
@ -219,16 +296,77 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart,
stack . push_back ( new DSMTransition ( ) ) ;
continue ;
}
if ( stack . empty ( ) ) {
if ( token = = " ; " )
continue ;
continue ;
ERROR ( " Without context I do not understand '%s' \n " , token . c_str ( ) ) ;
return false ;
}
DSMElement * stack_top = & ( * stack . back ( ) ) ;
DSMFunction * f = dynamic_cast < DSMFunction * > ( stack_top ) ;
if ( f ) {
if ( f - > name . length ( ) = = 0 ) {
size_t b_pos = token . find ( ' ( ' ) ;
if ( b_pos ! = string : : npos ) {
f - > name = token . substr ( 0 , b_pos ) ;
continue ;
} else {
ERROR ( " Parse error -- function declarations must have a name followed "
" by parentheses, e.g., 'function foo()' \n " ) ;
return false ;
}
}
if ( token = = " { " ) {
stack . push_back ( new ActionList ( ActionList : : AL_func ) ) ;
continue ;
}
if ( token = = " ; " ) {
owner - > transferElem ( f ) ;
funcs . push_back ( f ) ;
DBG ( " Adding DSMFunction '%s' to funcs \n " , f - > name . c_str ( ) ) ;
continue ;
}
DBG ( " Unknown token: %s \n " , token . c_str ( ) ) ;
return false ;
}
DSMConditionTree * ct = dynamic_cast < DSMConditionTree * > ( stack_top ) ;
if ( ct ) {
if ( token = = " [ " ) {
DSMConditionList * cl = new DSMConditionList ( ) ;
cl - > is_if = true ;
stack . push_back ( cl ) ;
continue ;
}
if ( token = = " { " ) {
stack . push_back ( new ActionList ( ActionList : : AL_if ) ) ;
continue ;
}
if ( token = = " ; " | | token = = " } " ) {
stack . pop_back ( ) ;
ActionList * al = dynamic_cast < ActionList * > ( & ( * stack . back ( ) ) ) ;
if ( al ) {
owner - > transferElem ( ct ) ;
al - > actions . push_back ( ct ) ;
} else {
ERROR ( " no ActionList for DSMConditionTree \n " ) ;
delete al ;
return false ;
}
continue ;
}
ERROR ( " syntax error: got '%s' without context \n " , token . c_str ( ) ) ;
return false ;
}
State * state = dynamic_cast < State * > ( stack_top ) ;
if ( state ) {
if ( ! state - > name . length ( ) ) {
@ -237,6 +375,7 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart,
continue ;
}
if ( token = = " enter " ) {
DBG ( " adding 'enter' actions for state '%s' \n " , state - > name . c_str ( ) ) ;
stack . push_back ( new ActionList ( ActionList : : AL_enter ) ) ;
continue ;
}
@ -268,16 +407,64 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart,
}
if ( token = = " { " ) {
continue ;
}
}
if ( ( token = = " } " ) | | ( token = = " -> " ) ) {
stack . pop_back ( ) ;
if ( stack . empty ( ) ) {
stack . pop_back ( ) ;
if ( stack . empty ( ) ) {
ERROR ( " no item for action list \n " ) ;
delete al ;
return false ;
}
if ( al - > al_type = = ActionList : : AL_func ) {
DSMFunction * f = dynamic_cast < DSMFunction * > ( & ( * stack . back ( ) ) ) ;
if ( ! f ) {
ERROR ( " no DSMFunction for action list \n " ) ;
delete al ;
return false ;
}
f - > actions = al - > actions ;
delete al ;
continue ;
}
if ( al - > al_type = = ActionList : : AL_enter | |
if ( al - > al_type = = ActionList : : AL_if | |
al - > al_type = = ActionList : : AL_else ) {
DSMConditionTree * ct = dynamic_cast < DSMConditionTree * > ( & ( * stack . back ( ) ) ) ;
if ( ! ct ) {
ERROR ( " no DSMConditionTree for action list \n " ) ;
delete al ;
return false ;
}
if ( al - > al_type = = ActionList : : AL_if )
ct - > run_if_true = al - > actions ;
else
ct - > run_if_false = al - > actions ;
stack . pop_back ( ) ;
ActionList * al_parent = dynamic_cast < ActionList * > ( & ( * stack . back ( ) ) ) ;
if ( al_parent ) {
owner - > transferElem ( ct ) ;
al_parent - > actions . push_back ( ct ) ;
} else {
ERROR ( " no ActionList for DSMConditionTree \n " ) ;
delete al ;
return false ;
}
if ( al - > al_type = = ActionList : : AL_if )
DBG ( " } // end if \n " ) ;
else
DBG ( " } // end else \n " ) ;
delete al ;
continue ;
}
if ( al - > al_type = = ActionList : : AL_enter | |
al - > al_type = = ActionList : : AL_exit ) {
State * s = dynamic_cast < State * > ( & ( * stack . back ( ) ) ) ;
if ( ! s ) {
@ -285,11 +472,17 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart,
delete al ;
return false ;
}
if ( al - > al_type = = ActionList : : AL_enter )
if ( al - > al_type = = ActionList : : AL_enter ) {
s - > pre_actions = al - > actions ;
else if ( al - > al_type = = ActionList : : AL_exit )
} else if ( al - > al_type = = ActionList : : AL_exit ) {
s - > post_actions = al - > actions ;
} else if ( al - > al_type = = ActionList : : AL_trans ) {
}
delete al ;
continue ;
}
if ( al - > al_type = = ActionList : : AL_trans ) {
DSMTransition * t = dynamic_cast < DSMTransition * > ( & ( * stack . back ( ) ) ) ;
if ( ! t ) {
ERROR ( " no DSMTransition for action list \n " ) ;
@ -297,80 +490,177 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart,
return false ;
}
t - > actions = al - > actions ;
} else {
ERROR ( " internal: unknown transition list type \n " ) ;
delete al ;
continue ;
}
if ( al - > al_type = = ActionList : : AL_for ) {
DSMArrayFor * af = dynamic_cast < DSMArrayFor * > ( & ( * stack . back ( ) ) ) ;
if ( ! af ) {
ERROR ( " no DSMArrayFor for action list \n " ) ;
delete al ;
return false ;
}
af - > actions = al - > actions ;
stack . pop_back ( ) ;
ActionList * b_al = dynamic_cast < ActionList * > ( & ( * stack . back ( ) ) ) ;
if ( ! b_al ) {
ERROR ( " internal error: no ActionList for 'for' \n " ) ;
return false ;
}
b_al - > actions . push_back ( af ) ;
DBG ( " } // end for (%s%s in %s) { \n " ,
af - > k . c_str ( ) , af - > v . empty ( ) ? " " : ( " , " + af - > v ) . c_str ( ) ,
af - > array_struct . c_str ( ) ) ;
delete al ;
continue ;
}
ERROR ( " internal: unknown transition list type \n " ) ;
return false ;
}
if ( token = = " if " ) {
DBG ( " if ... \n " ) ;
// start condition tree
stack . push_back ( new DSMConditionTree ( ) ) ;
DSMConditionList * cl = new DSMConditionList ( ) ;
cl - > is_if = true ;
stack . push_back ( cl ) ;
continue ;
}
if ( token = = " else " ) {
DBG ( " ... else ... \n " ) ;
DSMConditionTree * ct = dynamic_cast < DSMConditionTree * > ( al - > actions . back ( ) ) ;
if ( NULL = = ct ) {
ERROR ( " syntax error: else without if block \n " ) ;
return false ;
}
stack . push_back ( ct ) ;
stack . push_back ( new ActionList ( ActionList : : AL_else ) ) ;
al - > actions . pop_back ( ) ;
continue ;
}
if ( token . substr ( 0 , 3 ) = = " for " ) {
// token is for loop
DSMArrayFor * af = new DSMArrayFor ( ) ;
if ( token . length ( ) > 3 ) {
if ( ! forFromToken ( * af , token . substr ( 3 ) ) )
return false ;
}
stack . push_back ( af ) ;
continue ;
}
DSMFunction * f = functionFromToken ( token ) ;
if ( f ) {
DBG ( " adding actions from function '%s' \n " , f - > name . c_str ( ) ) ;
DBG ( " al.size is %zd before " , al - > actions . size ( ) ) ;
for ( vector < DSMElement * > : : iterator it = f - > actions . begin ( ) ;
it ! = f - > actions . end ( ) ; it + + ) {
DSMElement * a = * it ;
owner - > transferElem ( a ) ;
al - > actions . push_back ( a ) ;
}
delete al ;
DBG ( " al.size is %zd after " , al - > actions . size ( ) ) ;
continue ;
}
// token is action
// DBG("adding action '%s'\n", token.c_str());
DBG ( " adding action '%s' \n " , token . c_str ( ) ) ;
DSMAction * a = actionFromToken ( token ) ;
if ( ! a )
return false ;
owner - > transferElem ( a ) ;
al - > actions . push_back ( a ) ;
continue ;
}
} // actionlist
DSMConditionList * cl = dynamic_cast < DSMConditionList * > ( stack_top ) ;
if ( cl ) {
if ( token = = " ; " )
continue ;
if ( token = = " ; " | | token = = " [ " )
continue ;
if ( ( token = = " { " ) | | ( token = = " } " ) ) {
// readability
continue ;
}
if ( ( token = = " / " ) | | ( token = = " -> " ) ) {
// end of condition list
if ( cl - > is_if & & token = = " { " ) {
// end of condition list for if
stack . pop_back ( ) ;
if ( stack . empty ( ) ) {
ERROR ( " no transition to apply conditions to \n " ) ;
delete cl ;
return false ;
}
DSMTransition * tr = dynamic_cast < DSMTransition * > ( & ( * stack . back ( ) ) ) ;
if ( ! tr ) {
ERROR ( " no transition to apply conditions to \n " ) ;
delete cl ;
DSMConditionTree * ct = dynamic_cast < DSMConditionTree * > ( & ( * stack . back ( ) ) ) ;
if ( ! ct ) {
ERROR ( " internal error: condition list without condition tree \n " ) ;
return false ;
}
DBG ( " { \n " ) ;
ct - > conditions = cl - > conditions ;
ct - > is_exception = cl - > is_exception ;
stack . push_back ( new ActionList ( ActionList : : AL_if ) ) ;
continue ;
}
tr - > precond = cl - > conditions ;
tr - > is_exception = cl - > is_exception ;
delete cl ;
if ( ( token = = " { " ) | | ( token = = " } " ) ) {
// readability
continue ;
}
// start AL_trans action list
if ( token = = " / " ) {
stack . push_back ( new ActionList ( ActionList : : AL_trans ) ) ;
}
continue ;
if ( ( token = = " / " ) | | ( token = = " -> " ) | | ( token = = " ] " ) ) {
// end of condition list
stack . pop_back ( ) ;
if ( stack . empty ( ) ) {
ERROR ( " nothing to apply conditions to \n " ) ;
delete cl ;
return false ;
}
DSMElement * el = & ( * stack . back ( ) ) ;
DSMTransition * tr = dynamic_cast < DSMTransition * > ( el ) ;
DSMConditionTree * ct = dynamic_cast < DSMConditionTree * > ( el ) ;
if ( tr ) {
tr - > precond = cl - > conditions ;
tr - > is_exception = cl - > is_exception ;
} else if ( ct ) {
ct - > conditions = cl - > conditions ;
ct - > is_exception = cl - > is_exception ;
} else {
ERROR ( " no transition or condition list to apply conditions to \n " ) ;
delete cl ;
return false ;
}
delete cl ;
// start AL_trans action list
if ( token = = " / " ) {
stack . push_back ( new ActionList ( ActionList : : AL_trans ) ) ;
}
continue ;
}
if ( token = = " not " ) {
cl - > invert_next = ! cl - > invert_next ;
continue ;
cl - > invert_next = ! cl - > invert_next ;
continue ;
}
if ( token = = " exception " ) {
cl - > is_exception = true ;
continue ;
cl - > is_exception = true ;
continue ;
}
// DBG("new condition: '%s'\n", token.c_str());
DBG ( " new condition: '%s' \n " , token . c_str ( ) ) ;
DSMCondition * c = conditionFromToken ( token , cl - > invert_next ) ;
cl - > invert_next = false ;
if ( ! c )
return false ;
return false ;
owner - > transferElem ( c ) ;
cl - > conditions . push_back ( c ) ;
continue ;
}
DSMTransition * tr = dynamic_cast < DSMTransition * > ( stack_top ) ;
if ( tr ) {
if ( ! tr - > name . length ( ) ) {
@ -418,6 +708,31 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart,
}
continue ;
}
DSMArrayFor * af = dynamic_cast < DSMArrayFor * > ( stack_top ) ;
if ( af ) {
if ( af - > array_struct . length ( ) | | af - > k . length ( ) ) {
// expecting body
if ( token = = " } " ) {
DBG ( " close for \n " ) ;
ERROR ( " sounds wrong!!! \n " ) ;
stack . pop_back ( ) ;
continue ;
}
if ( token = = " { " ) {
// start action list for 'for'
stack . push_back ( new ActionList ( ActionList : : AL_for ) ) ;
continue ;
}
} else {
if ( ! forFromToken ( * af , token ) )
return false ;
}
continue ;
}
}
for ( vector < DSMModule * > : : iterator it =