diff -r a435684a5223 -r 23f271534a7c stage1_2/iec_flex.ll --- a/stage1_2/iec_flex.ll Sun Feb 16 00:37:40 2014 +0000 +++ b/stage1_2/iec_flex.ll Sun Feb 16 14:27:06 2014 +0000 @@ -356,23 +356,36 @@ * Unfortunately, flex will join '_' and '4h' to create a legal {identifier} '_4h', * and return that identifier instead! So, we added this state! * - * There is a main state machine ( - * +------> INITIAL <-------> config - * | \ - * | V - * | header_state - * | | - * | V - * | vardecl_list_state <------> var_decl - * | | - * | V - * +----------body, - * ^ - * | - * ----------------------- - * | | | - * v v v - * st il sfc + * There is a main state machine... + * + * +---> INITIAL <-------> config + * | \ + * | V + * | header_state + * | | + * | V + * vardecl_list_state <------> var_decl + * ^ | + * | | [using push()] + * | | + * | V + * | body, + * | | + * | | + * | ------------------- + * | | | | + * | v v v + * | st il sfc + * | | | | [using pop() when leaving st/il/sfc => goes to vardecl_list_state] + * | | | | + * ----------------------- + * + * NOTE:- When inside sfc, and an action or transition in ST/IL is found, then + * we also push() to the body state. This means that sometimes, when pop()ing + * from st and il, the state machine may return to the sfc state! + * - The transitions form sfc to body will be decided by bison, which will + * tell flex to do the transition by calling cmd_goto_body_state(). + * * * Possible state changes are: * INITIAL -> goto(config_state) @@ -388,25 +401,25 @@ * vardecl_state -> pop() to (vardecl_list_state) * (when a END_VAR token is found) * - * vardecl_list_state -> goto(body_state) + * vardecl_list_state -> push current state (vardecl_list_state), and goto(body_state) * (when the last END_VAR is found!) * - * body_state -> push current state(body_state); goto(sfc_state) + * body_state -> goto(sfc_state) * (when it figures out it is parsing sfc language) - * body_state -> push current state(body_state); goto(st_state) + * body_state -> goto(st_state) * (when it figures out it is parsing st language) - * body_state -> push current state(body_state); goto(il_state) + * body_state -> goto(il_state) * (when it figures out it is parsing il language) - * st_state -> pop() to body_sate + * st_state -> pop() to vardecl_list_state * (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM, * END_ACTION or END_TRANSITION is found) - * il_state -> pop() to body_sate + * il_state -> pop() to vardecl_list_state * (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM, * END_ACTION or END_TRANSITION is found) - * sfc_state -> pop() to body_sate + * sfc_state -> pop() to vardecl_list_state * (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) * - * body_sate -> goto(INITIAL) + * vardecl_list_state -> goto(INITIAL) * (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) * config_state -> goto(INITIAL) * (when a END_CONFIGURATION is found) @@ -441,6 +454,7 @@ %s task_init_state /* we are looking for the first VAR inside a function's, program's or function block's declaration */ +/* This is not exclusive (%x) as we must be able to parse the identifier and data types of a function/FB */ %s header_state /* we are parsing a function, program or function block sequence of VAR..END_VAR delcarations */ @@ -448,7 +462,7 @@ /* a substate of the vardecl_list_state: we are inside a specific VAR .. END_VAR */ %s vardecl_state -/* we will be parsing a function body. Whether il/st/sfc remains to be determined */ +/* we will be parsing a function body/action/transition. Whether il/st/sfc remains to be determined */ %x body_state /* we are parsing il code -> flex must return the EOL tokens! */ @@ -559,9 +573,8 @@ /* Any other pragma... */ pragma "{"[^}]*"}"|"{{"([^}]|"}"[^}])*"}}" -/* -pragma "{"[^}]*"}" -*/ + + /* COMMENTS */ /* ======== */ @@ -798,7 +811,6 @@ * minutes ::= fixed_point 'm' | integer 'm' ['_'] seconds * seconds ::= fixed_point 's' | integer 's' ['_'] milliseconds * milliseconds ::= fixed_point 'ms' - */ interval_ms_X ({integer_0_999}(\.{integer})?)ms @@ -924,7 +936,7 @@ /* Any other pragma we find, we just pass it up to the syntax parser... */ /* Note that the state is exclusive, so we have to include it here too. */ {pragma} {/* return the pragmma without the enclosing '{' and '}' */ - int cut = yytext[1]=='{'?2:1; + int cut = yytext[1]=='{'?2:1; yytext[strlen(yytext)-cut] = '\0'; yylval.ID=strdup(yytext+cut); return pragma_token; @@ -1034,9 +1046,9 @@ * continue in the state, untill the end of the FUNCTION, FUNCTION_BLOCK * or PROGAM. */ -FUNCTION BEGIN(header_state); return FUNCTION; -FUNCTION_BLOCK BEGIN(header_state); return FUNCTION_BLOCK; -PROGRAM BEGIN(header_state); return PROGRAM; +FUNCTION yy_push_state(header_state); return FUNCTION; +FUNCTION_BLOCK yy_push_state(header_state); return FUNCTION_BLOCK; +PROGRAM yy_push_state(header_state); return PROGRAM; CONFIGURATION BEGIN(config_state); return CONFIGURATION; } @@ -1054,65 +1066,84 @@ } */ - /* header_state -> (vardecl_state | body_state) */ + /* header_state -> (vardecl_list_state) */ { -VAR unput_text(0); BEGIN(vardecl_list_state); -} - - +VAR | /* execute the next rule's action, i.e. fall-through! */ +VAR_INPUT | +VAR_OUTPUT | +VAR_IN_OUT | +VAR_EXTERNAL | +VAR_GLOBAL | +VAR_TEMP | +VAR_CONFIG | +VAR_ACCESS unput_text(0); BEGIN(vardecl_list_state); +} + + + /* vardecl_list_state -> (vardecl_state | body_state | INITIAL) */ { +VAR_INPUT | /* execute the next rule's action, i.e. fall-through! */ +VAR_OUTPUT | +VAR_IN_OUT | +VAR_EXTERNAL | +VAR_GLOBAL | +VAR_TEMP | +VAR_CONFIG | +VAR_ACCESS | VAR unput_text(0); yy_push_state(vardecl_state); -. unput_text(0); BEGIN(body_state); /* anything else, just change to body_state! */ -} - - + +END_FUNCTION unput_text(0); BEGIN(INITIAL); +END_FUNCTION_BLOCK unput_text(0); BEGIN(INITIAL); +END_PROGRAM unput_text(0); BEGIN(INITIAL); + +. unput_text(0); yy_push_state(body_state); /* anything else, just change to body_state! */ +} + + + /* vardecl_list_state -> pop to $previous_state (vardecl_list_state) */ { END_VAR yy_pop_state(); return END_VAR; /* pop back to header_state */ } - /* body_state -> (il_state | st_state) */ + /* body_state -> (il_state | st_state | sfc_state) */ { -END_FUNCTION BEGIN(INITIAL); return END_FUNCTION; -END_FUNCTION_BLOCK BEGIN(INITIAL); return END_FUNCTION_BLOCK; -END_PROGRAM BEGIN(INITIAL); return END_PROGRAM; - -INITIAL_STEP unput_text(0); yy_push_state(sfc_state); - -{qualified_identifier} unput_text(0); yy_push_state(st_state); /* will always be followed by '[' for an array access, or ':=' as the left hand of an assignment statement */ -{direct_variable_standard} unput_text(0); yy_push_state(st_state); /* will always be followed by ':=' as the left hand of an assignment statement */ - -RETURN unput_text(0); yy_push_state(st_state); -IF unput_text(0); yy_push_state(st_state); -CASE unput_text(0); yy_push_state(st_state); -FOR unput_text(0); yy_push_state(st_state); -WHILE unput_text(0); yy_push_state(st_state); -EXIT unput_text(0); yy_push_state(st_state); -REPEAT unput_text(0); yy_push_state(st_state); +INITIAL_STEP unput_text(0); BEGIN(sfc_state); + +{qualified_identifier} unput_text(0); BEGIN(st_state); /* will always be followed by '[' for an array access, or ':=' as the left hand of an assignment statement */ +{direct_variable_standard} unput_text(0); BEGIN(st_state); /* will always be followed by ':=' as the left hand of an assignment statement */ + +RETURN unput_text(0); BEGIN(st_state); +IF unput_text(0); BEGIN(st_state); +CASE unput_text(0); BEGIN(st_state); +FOR unput_text(0); BEGIN(st_state); +WHILE unput_text(0); BEGIN(st_state); +EXIT unput_text(0); BEGIN(st_state); +REPEAT unput_text(0); BEGIN(st_state); /* ':=' occurs only in transitions, and not Function or FB bodies! */ -:= unput_text(0); yy_push_state(st_state); +:= unput_text(0); BEGIN(st_state); {identifier} {int token = get_identifier_token(yytext); if ((token == prev_declared_fb_name_token) || (token == prev_declared_variable_name_token)) { /* the code has a call to a function block OR has an assingment with a variable as the lvalue */ - unput_text(0); yy_push_state(st_state); + unput_text(0); BEGIN(st_state); } else if (token == prev_declared_derived_function_name_token) { /* the code has a call to a function - must be IL */ - unput_text(0); yy_push_state(il_state); + unput_text(0); BEGIN(il_state); } else { /* Might be a lable in IL, or a bug in ST/IL code. We jump to IL */ - unput_text(0); yy_push_state(il_state); + unput_text(0); BEGIN(il_state); } } -. unput_text(0); yy_push_state(il_state); /* Don't know what it could be. This is most likely a bug. Let's just to a random state... */ +. unput_text(0); BEGIN(il_state); /* Don't know what it could be. This is most likely a bug. Let's just to a random state... */ } /* end of body_state lexical parser */ - /* (il_state | st_state) -> $previous_state (vardecl_state or sfc_state) */ + /* (il_state | st_state) -> pop to $previous_state (vardecl_list_state or sfc_state) */ { END_FUNCTION yy_pop_state(); unput_text(0); END_FUNCTION_BLOCK yy_pop_state(); unput_text(0); @@ -1121,7 +1152,7 @@ END_ACTION yy_pop_state(); unput_text(0); } - /* sfc_state -> INITIAL */ + /* sfc_state -> pop to $previous_state (vardecl_list_state or sfc_state) */ { END_FUNCTION yy_pop_state(); unput_text(0); END_FUNCTION_BLOCK yy_pop_state(); unput_text(0);