354 * e.g.: TIME#55d_4h_56m |
354 * e.g.: TIME#55d_4h_56m |
355 * We would like to return to bison the tokens 'TIME' '#' '55d' '_' '4h' '_' '56m' |
355 * We would like to return to bison the tokens 'TIME' '#' '55d' '_' '4h' '_' '56m' |
356 * Unfortunately, flex will join '_' and '4h' to create a legal {identifier} '_4h', |
356 * Unfortunately, flex will join '_' and '4h' to create a legal {identifier} '_4h', |
357 * and return that identifier instead! So, we added this state! |
357 * and return that identifier instead! So, we added this state! |
358 * |
358 * |
359 * The state machine has 7 possible states (INITIAL, config, decl, body, st, il, sfc) |
359 * There is a main state machine... |
|
360 * |
|
361 * +---> INITIAL <-------> config |
|
362 * | \ |
|
363 * | V |
|
364 * | header_state |
|
365 * | | |
|
366 * | V |
|
367 * vardecl_list_state <------> var_decl |
|
368 * ^ | |
|
369 * | | [using push()] |
|
370 * | | |
|
371 * | V |
|
372 * | body, |
|
373 * | | |
|
374 * | | |
|
375 * | ------------------- |
|
376 * | | | | |
|
377 * | v v v |
|
378 * | st il sfc |
|
379 * | | | | [using pop() when leaving st/il/sfc => goes to vardecl_list_state] |
|
380 * | | | | |
|
381 * ----------------------- |
|
382 * |
|
383 * NOTE:- When inside sfc, and an action or transition in ST/IL is found, then |
|
384 * we also push() to the body state. This means that sometimes, when pop()ing |
|
385 * from st and il, the state machine may return to the sfc state! |
|
386 * - The transitions form sfc to body will be decided by bison, which will |
|
387 * tell flex to do the transition by calling cmd_goto_body_state(). |
|
388 * |
|
389 * |
360 * Possible state changes are: |
390 * Possible state changes are: |
361 * INITIAL -> goto(decl_state) |
|
362 * (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found, |
|
363 * and followed by a VAR declaration) |
|
364 * INITIAL -> goto(body_state) |
|
365 * (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found, |
|
366 * and _not_ followed by a VAR declaration) |
|
367 * (This transition is actually commented out, since the syntax |
|
368 * does not allow the declaration of functions, FBs, or programs |
|
369 * without any VAR declaration!) |
|
370 * INITIAL -> goto(config_state) |
391 * INITIAL -> goto(config_state) |
371 * (when a CONFIGURATION is found) |
392 * (when a CONFIGURATION is found) |
372 * decl_state -> push(decl_state); goto(body_state) |
393 * |
373 * (when the last END_VAR is found, i.e. the function body starts) |
394 * INITIAL -> goto(header_state) |
374 * decl_state -> push(decl_state); goto(sfc_state) |
395 * (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found) |
|
396 * header_state -> goto(vardecl_list_state) |
|
397 * (When the first VAR token is found, i.e. at begining of first VAR .. END_VAR declaration) |
|
398 * |
|
399 * vardecl_list_state -> push current state (vardecl_list_state), and goto(vardecl_state) |
|
400 * (when a VAR token is found) |
|
401 * vardecl_state -> pop() to (vardecl_list_state) |
|
402 * (when a END_VAR token is found) |
|
403 * |
|
404 * vardecl_list_state -> push current state (vardecl_list_state), and goto(body_state) |
|
405 * (when the last END_VAR is found!) |
|
406 * |
|
407 * body_state -> goto(sfc_state) |
375 * (when it figures out it is parsing sfc language) |
408 * (when it figures out it is parsing sfc language) |
376 * body_state -> goto(st_state) |
409 * body_state -> goto(st_state) |
377 * (when it figures out it is parsing st language) |
410 * (when it figures out it is parsing st language) |
378 * body_state -> goto(il_state) |
411 * body_state -> goto(il_state) |
379 * (when it figures out it is parsing il language) |
412 * (when it figures out it is parsing il language) |
380 * st_state -> pop() |
413 * st_state -> pop() to vardecl_list_state |
381 * (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM, |
414 * (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM, |
382 * END_ACTION or END_TRANSITION is found) |
415 * END_ACTION or END_TRANSITION is found) |
383 * il_state -> pop() |
416 * il_state -> pop() to vardecl_list_state |
384 * (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM, |
417 * (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM, |
385 * END_ACTION or END_TRANSITION is found) |
418 * END_ACTION or END_TRANSITION is found) |
386 * decl_state -> goto(INITIAL) |
419 * sfc_state -> pop() to vardecl_list_state |
387 * (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
420 * (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
388 * sfc_state -> goto(INITIAL) |
421 * |
|
422 * vardecl_list_state -> goto(INITIAL) |
389 * (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
423 * (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
390 * config_state -> goto(INITIAL) |
424 * config_state -> goto(INITIAL) |
391 * (when a END_CONFIGURATION is found) |
425 * (when a END_CONFIGURATION is found) |
392 * sfc_state -> push(sfc_state); goto(body_state) |
426 * |
|
427 * |
|
428 * sfc_state -> push current state(sfc_state); goto(body_state) |
393 * (when parsing an action. This transition is requested by bison) |
429 * (when parsing an action. This transition is requested by bison) |
394 * sfc_state -> push(sfc_state); goto(sfc_qualifier_state) |
430 * sfc_state -> push current state(sfc_state); goto(sfc_qualifier_state) |
395 * (when expecting an action qualifier. This transition is requested by bison) |
431 * (when expecting an action qualifier. This transition is requested by bison) |
396 * sfc_qualifier_state -> pop() |
432 * sfc_qualifier_state -> pop() to sfc_state |
397 * (when no longer expecting an action qualifier. This transition is requested by bison) |
433 * (when no longer expecting an action qualifier. This transition is requested by bison) |
|
434 * |
398 * config_state -> push(config_state); goto(task_init_state) |
435 * config_state -> push(config_state); goto(task_init_state) |
399 * (when parsing a task initialisation. This transition is requested by bison) |
436 * (when parsing a task initialisation. This transition is requested by bison) |
400 * task_init_state -> pop() |
437 * task_init_state -> pop() |
401 * (when no longer parsing task initialisation parameters. This transition is requested by bison) |
438 * (when no longer parsing task initialisation parameters. This transition is requested by bison) |
402 * |
439 * |
|
440 * |
|
441 * There is another secondary state machine for parsing comments, another for file_includes, |
|
442 * and yet another for time literals. |
403 */ |
443 */ |
404 |
444 |
405 |
445 |
406 /* we are parsing a configuration. */ |
446 /* we are parsing a configuration. */ |
407 %s config_state |
447 %s config_state |
519 disable_code_generation_pragma "{disable code generation}" |
570 disable_code_generation_pragma "{disable code generation}" |
520 enable_code_generation_pragma "{enable code generation}" |
571 enable_code_generation_pragma "{enable code generation}" |
521 |
572 |
522 |
573 |
523 /* Any other pragma... */ |
574 /* Any other pragma... */ |
524 |
575 pragma ("{"[^}]*"}")|("{{"([^}]|"}"[^}])*"}}") |
525 pragma "{"[^}]*"}"|"{{"([^}]|"}"[^}])*"}}" |
576 |
526 |
577 |
|
578 |
|
579 /* COMMENTS */ |
|
580 /* ======== */ |
|
581 |
|
582 /* In order to allow nested comments, comments are handled by a specific comment_state state */ |
|
583 /* Whenever a "(*" is found, we push the current state onto the stack, and enter a new instance of the comment_state state. |
|
584 * Whenever a "*)" is found, we pop a state off the stack |
|
585 */ |
|
586 |
|
587 /* comments... */ |
|
588 comment_beg "(*" |
|
589 comment_end "*)" |
|
590 |
|
591 /* However, bison has a shift/reduce conflict in bison, when parsing formal function/FB |
|
592 * invocations with the 'NOT <variable_name> =>' syntax (which needs two look ahead |
|
593 * tokens to be parsed correctly - and bison being LALR(1) only supports one). |
|
594 * The current work around requires flex to completely parse the '<variable_name> =>' |
|
595 * sequence. This sequence includes whitespace and/or comments between the |
|
596 * <variable_name> and the "=>" token. |
|
597 * |
|
598 * This flex rule (sendto_identifier_token) uses the whitespace/comment as trailing context, |
|
599 * which means we can not use the comment_state method of specifying/finding and ignoring |
|
600 * comments. |
|
601 * |
|
602 * For this reason only, we must also define what a complete comment looks like, so |
|
603 * it may be used in this rule. Since the rule uses the whitespace_or_comment |
|
604 * construct as trailing context, this definition of comment must not use any |
|
605 * trailing context either. |
|
606 * |
|
607 * Aditionally, it is not possible to define nested comments in flex without the use of |
|
608 * states, so for this particular location, we do NOT support nested comments. |
|
609 */ |
527 /* NOTE: this seemingly unnecessary complex definition is required |
610 /* NOTE: this seemingly unnecessary complex definition is required |
528 * to be able to eat up comments such as: |
611 * to be able to eat up comments such as: |
529 * '(* Testing... ! ***** ******)' |
612 * '(* Testing... ! ***** ******)' |
530 * without using the trailing context command in flex (/{context}) |
613 * without using the trailing context command in flex (/{context}) |
531 * since {comment} itself will later be used with |
614 * since {comment} itself will later be used with |
532 * trailing context ({comment}/{context}) |
615 * trailing context ({comment}/{context}) |
533 */ |
616 */ |
534 not_asterisk [^*] |
617 not_asterisk [^*] |
535 not_close_parenthesis_nor_asterisk [^*)] |
618 not_close_parenthesis_nor_asterisk [^*)] |
536 asterisk "*" |
619 asterisk "*" |
537 comment_text {not_asterisk}|(({asterisk}+){not_close_parenthesis_nor_asterisk}) |
620 comment_text ({not_asterisk})|(({asterisk}+){not_close_parenthesis_nor_asterisk}) |
538 |
|
539 comment "(*"({comment_text}*)({asterisk}+)")" |
621 comment "(*"({comment_text}*)({asterisk}+)")" |
540 |
622 |
541 |
623 |
|
624 |
|
625 /* 3.1 Whitespace */ |
|
626 /* ============== */ |
542 /* |
627 /* |
543 3.1 Whitespace |
628 * Whitespace is clearly defined (see IEC 61131-3 v2, section 2.1.4) |
544 (NOTE: Whitespace IS clearly defined, to include newline!!! See section 2.1.4!!!) |
629 * |
545 No definition of whitespace is given, in other words, the characters that may be used to seperate language tokens are not pecisely defined. One may nevertheless make an inteligent guess of using the space (' '), and other characters also commonly considered whitespace in other programming languages (horizontal tab, vertical tab, form feed, etc.). |
630 * Whitespace definition includes the newline character. |
546 The main question is whether the newline character should be considered whitespace. IL language statements use an EOL token (End Of Line) to distinguish between some language constructs. The EOL token itself is openly defined as "normally consist[ing] of the 'paragraph separator' ", leaving the final choice open to each implemention. If we choose the newline character to represent the EOL token, it may then not be considered whitespace. |
631 * |
547 On the other hand, some examples that come in a non-normative annex of the specification allow function declarations to span multiple3.1 Whitespace |
632 * However, the standard is inconsistent in that in IL the newline character |
548 (NOTE: Whitespace IS clearly defined, to include newline!!! See section 2.1.4!!!) |
633 * is considered a token (EOL - end of line). |
549 No definition of whitespace is given, in other words, the characters that may be used to seperate language tokens are not pecisely defined. One may nevertheless make an inteligent guess of using the space (' '), and other characters also commonly considered whitespace in other programming languages (horizontal tab, vertical tab, form feed, etc.). |
634 * In our implementation we therefore have two definitions of whitespace |
550 The main question is whether the newline character should be considered whitespace. IL language statements use an EOL token (End Of Line) to distinguish between some language constructs. The EOL token itself is openly defined as "normally consist[ing] of the 'paragraph separator' ", leaving the final choice open to each implemention. If we choose the newline character to represent the EOL token, it may then not be considered whitespace. |
635 * - one for ST, that includes the newline character |
551 On the other hand, some examples that come in a non-normative annex of the specification allow function declarations to span multiple lines, which means that the newline character is being considered as whitespace. |
636 * - one for IL without the newline character. |
552 Our implementation works around this issue by including the new line character in the whitespace while parsing function declarations and the ST language, and parsing it as the EOL token only while parsing IL language statements. This requires the use of a state machine in the lexical parser that needs at least some knowledge of the syntax itself. |
637 * Additionally, when parsing IL, the newline character is treated as the EOL token. |
553 */ |
638 * This requires the use of a state machine in the lexical parser that needs at least |
554 /* NOTE: Our definition of whitespace will only work in ASCII! |
639 * some knowledge of the syntax itself. |
555 * |
640 * |
556 * Since the IL language needs to know the location of newline |
641 * NOTE: Our definition of whitespace will only work in ASCII! |
557 * (token EOL -> '\n' ), we need one definition of whitespace |
642 * |
558 * for each language... |
|
559 */ |
|
560 /* |
|
561 * NOTE: we cannot use |
643 * NOTE: we cannot use |
562 * st_whitespace [:space:]* |
644 * st_whitespace [:space:]* |
563 * since we use {st_whitespace} as trailing context. In our case |
645 * since we use {st_whitespace} as trailing context. In our case |
564 * this would not constitute "dangerous trailing context", but the |
646 * this would not constitute "dangerous trailing context", but the |
565 * lexical generator (i.e. flex) does not know this (since it does |
647 * lexical generator (i.e. flex) does not know this (since it does |
851 <INITIAL>{file_include_pragma} unput_text(0); yy_push_state(include_beg); |
928 <INITIAL>{file_include_pragma} unput_text(0); yy_push_state(include_beg); |
852 |
929 |
853 /* Pragmas sent to syntax analyser (bison) */ |
930 /* Pragmas sent to syntax analyser (bison) */ |
854 {disable_code_generation_pragma} return disable_code_generation_pragma_token; |
931 {disable_code_generation_pragma} return disable_code_generation_pragma_token; |
855 {enable_code_generation_pragma} return enable_code_generation_pragma_token; |
932 {enable_code_generation_pragma} return enable_code_generation_pragma_token; |
856 <body_state>{disable_code_generation_pragma} return disable_code_generation_pragma_token; |
933 <body_state,vardecl_list_state>{disable_code_generation_pragma} return disable_code_generation_pragma_token; |
857 <body_state>{enable_code_generation_pragma} return enable_code_generation_pragma_token; |
934 <body_state,vardecl_list_state>{enable_code_generation_pragma} return enable_code_generation_pragma_token; |
858 |
935 |
859 /* Any other pragma we find, we just pass it up to the syntax parser... */ |
936 /* Any other pragma we find, we just pass it up to the syntax parser... */ |
860 /* Note that the <body_state> state is exclusive, so we have to include it here too. */ |
937 /* Note that the <body_state> state is exclusive, so we have to include it here too. */ |
861 {pragma} {/* return the pragmma without the enclosing '{' and '}' */ |
938 {pragma} {/* return the pragmma without the enclosing '{' and '}' */ |
862 int cut = yytext[1]=='{'?2:1; |
939 int cut = yytext[1]=='{'?2:1; |
863 yytext[strlen(yytext)-cut] = '\0'; |
940 yytext[strlen(yytext)-cut] = '\0'; |
864 yylval.ID=strdup(yytext+cut); |
941 yylval.ID=strdup(yytext+cut); |
865 return pragma_token; |
942 return pragma_token; |
866 } |
943 } |
867 <body_state>{pragma} {/* return the pragmma without the enclosing '{' and '}' */ |
944 <body_state,vardecl_list_state>{pragma} {/* return the pragmma without the enclosing '{' and '}' */ |
868 int cut = yytext[1]=='{'?2:1; |
945 int cut = yytext[1]=='{'?2:1; |
869 yytext[strlen(yytext)-cut] = '\0'; |
946 yytext[strlen(yytext)-cut] = '\0'; |
870 yylval.ID=strdup(yytext+cut); |
947 yylval.ID=strdup(yytext+cut); |
871 return pragma_token; |
948 return pragma_token; |
872 } |
949 } |
873 |
950 |
874 |
951 |
987 FUNCTION_BLOCK BEGIN(body_state); return FUNCTION_BLOCK; |
1064 FUNCTION_BLOCK BEGIN(body_state); return FUNCTION_BLOCK; |
988 PROGRAM BEGIN(body_state); return PROGRAM; |
1065 PROGRAM BEGIN(body_state); return PROGRAM; |
989 } |
1066 } |
990 */ |
1067 */ |
991 |
1068 |
992 /* decl_state -> (body_state | sfc_state) */ |
1069 /* header_state -> (vardecl_list_state) */ |
993 <decl_state>{ |
1070 <header_state>{ |
994 END_VAR{st_whitespace}VAR {unput_text(strlen("END_VAR")); |
1071 VAR | /* execute the next rule's action, i.e. fall-through! */ |
995 return END_VAR; |
1072 VAR_INPUT | |
996 } |
1073 VAR_OUTPUT | |
997 END_VAR{st_whitespace}INITIAL_STEP {unput_text(strlen("END_VAR")); |
1074 VAR_IN_OUT | |
998 yy_push_state(sfc_state); |
1075 VAR_EXTERNAL | |
999 return END_VAR; |
1076 VAR_GLOBAL | |
1000 } |
1077 VAR_TEMP | |
1001 END_VAR{st_whitespace} {unput_text(strlen("END_VAR")); |
1078 VAR_CONFIG | |
1002 cmd_goto_body_state(); |
1079 VAR_ACCESS unput_text(0); BEGIN(vardecl_list_state); |
1003 return END_VAR; |
1080 } |
1004 } |
1081 |
1005 } |
1082 |
1006 |
1083 /* vardecl_list_state -> (vardecl_state | body_state | INITIAL) */ |
1007 /* body_state -> (il_state | st_state) */ |
1084 <vardecl_list_state>{ |
|
1085 VAR_INPUT | /* execute the next rule's action, i.e. fall-through! */ |
|
1086 VAR_OUTPUT | |
|
1087 VAR_IN_OUT | |
|
1088 VAR_EXTERNAL | |
|
1089 VAR_GLOBAL | |
|
1090 VAR_TEMP | |
|
1091 VAR_CONFIG | |
|
1092 VAR_ACCESS | |
|
1093 VAR unput_text(0); yy_push_state(vardecl_state); |
|
1094 |
|
1095 END_FUNCTION unput_text(0); BEGIN(INITIAL); |
|
1096 END_FUNCTION_BLOCK unput_text(0); BEGIN(INITIAL); |
|
1097 END_PROGRAM unput_text(0); BEGIN(INITIAL); |
|
1098 |
|
1099 . unput_text(0); yy_push_state(body_state); /* anything else, just change to body_state! */ |
|
1100 } |
|
1101 |
|
1102 |
|
1103 /* vardecl_list_state -> pop to $previous_state (vardecl_list_state) */ |
|
1104 <vardecl_state>{ |
|
1105 END_VAR yy_pop_state(); return END_VAR; /* pop back to header_state */ |
|
1106 } |
|
1107 |
|
1108 |
|
1109 /* body_state -> (il_state | st_state | sfc_state) */ |
1008 <body_state>{ |
1110 <body_state>{ |
1009 {st_whitespace_no_pragma} /* Eat any whitespace */ |
1111 INITIAL_STEP unput_text(0); BEGIN(sfc_state); |
1010 {qualified_identifier}{st_whitespace}":=" unput_text(0); BEGIN(st_state); |
1112 |
1011 {direct_variable_standard}{st_whitespace}":=" unput_text(0); BEGIN(st_state); |
1113 {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 */ |
1012 {qualified_identifier}"[" unput_text(0); BEGIN(st_state); |
1114 {direct_variable_standard} unput_text(0); BEGIN(st_state); /* will always be followed by ':=' as the left hand of an assignment statement */ |
1013 |
1115 |
1014 RETURN unput_text(0); BEGIN(st_state); |
1116 RETURN unput_text(0); BEGIN(st_state); |
1015 IF unput_text(0); BEGIN(st_state); |
1117 IF unput_text(0); BEGIN(st_state); |
1016 CASE unput_text(0); BEGIN(st_state); |
1118 CASE unput_text(0); BEGIN(st_state); |
1017 FOR unput_text(0); BEGIN(st_state); |
1119 FOR unput_text(0); BEGIN(st_state); |
1018 WHILE unput_text(0); BEGIN(st_state); |
1120 WHILE unput_text(0); BEGIN(st_state); |
1019 REPEAT unput_text(0); BEGIN(st_state); |
1121 EXIT unput_text(0); BEGIN(st_state); |
1020 EXIT unput_text(0); BEGIN(st_state); |
1122 REPEAT unput_text(0); BEGIN(st_state); |
1021 |
1123 |
1022 /* ':=' occurs only in transitions, and not Function or FB bodies! */ |
1124 /* ':=' occurs only in transitions, and not Function or FB bodies! */ |
1023 := unput_text(0); BEGIN(st_state); |
1125 := unput_text(0); BEGIN(st_state); |
1024 |
|
1025 /* Hopefully, the above rules (along with the last one), |
|
1026 * used to distinguish ST from IL, are |
|
1027 * enough to handle all ocurrences. However, if |
|
1028 * there is some situation where the compiler is getting confused, |
|
1029 * we add the following rule to detect 'label:' in IL code. This will |
|
1030 * allow the user to insert a label right at the beginning (which |
|
1031 * will probably not be used further by his code) simply as a way |
|
1032 * to force the compiler to interpret his code as IL code. |
|
1033 */ |
|
1034 {identifier}{st_whitespace}":"{st_whitespace} unput_text(0); BEGIN(il_state); |
|
1035 |
1126 |
1036 {identifier} {int token = get_identifier_token(yytext); |
1127 {identifier} {int token = get_identifier_token(yytext); |
1037 if (token == prev_declared_fb_name_token) { |
1128 if ((token == prev_declared_fb_name_token) || (token == prev_declared_variable_name_token)) { |
1038 /* the code has a call to a function block */ |
1129 /* the code has a call to a function block OR has an assingment with a variable as the lvalue */ |
1039 /* NOTE: if we ever decide to allow the user to use IL operator tokens |
1130 unput_text(0); BEGIN(st_state); |
1040 * (LD, ST, ...) as identifiers for variable names (including |
1131 } else |
1041 * function block instances), then the above inference/conclusion |
1132 if (token == prev_declared_derived_function_name_token) { |
1042 * may be incorrect, and this condition may have to be changed! |
1133 /* the code has a call to a function - must be IL */ |
1043 */ |
1134 unput_text(0); BEGIN(il_state); |
1044 BEGIN(st_state); |
|
1045 } else { |
1135 } else { |
1046 BEGIN(il_state); |
1136 /* Might be a lable in IL, or a bug in ST/IL code. We jump to IL */ |
|
1137 unput_text(0); BEGIN(il_state); |
1047 } |
1138 } |
1048 unput_text(0); |
|
1049 } |
1139 } |
1050 |
1140 |
1051 . unput_text(0); BEGIN(il_state); |
1141 . 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... */ |
1052 } /* end of body_state lexical parser */ |
1142 } /* end of body_state lexical parser */ |
1053 |
1143 |
1054 /* (il_state | st_state) -> $previous_state (decl_state or sfc_state) */ |
1144 |
|
1145 |
|
1146 /* (il_state | st_state) -> pop to $previous_state (vardecl_list_state or sfc_state) */ |
1055 <il_state,st_state>{ |
1147 <il_state,st_state>{ |
1056 END_FUNCTION yy_pop_state(); unput_text(0); |
1148 END_FUNCTION yy_pop_state(); unput_text(0); |
1057 END_FUNCTION_BLOCK yy_pop_state(); unput_text(0); |
1149 END_FUNCTION_BLOCK yy_pop_state(); unput_text(0); |
1058 END_PROGRAM yy_pop_state(); unput_text(0); |
1150 END_PROGRAM yy_pop_state(); unput_text(0); |
1059 END_TRANSITION yy_pop_state(); unput_text(0); |
1151 END_TRANSITION yy_pop_state(); unput_text(0); |
1060 END_ACTION yy_pop_state(); unput_text(0); |
1152 END_ACTION yy_pop_state(); unput_text(0); |
1061 } |
1153 } |
1062 |
1154 |
1063 /* sfc_state -> INITIAL */ |
1155 /* sfc_state -> pop to $previous_state (vardecl_list_state or sfc_state) */ |
1064 <sfc_state>{ |
1156 <sfc_state>{ |
1065 END_FUNCTION yy_pop_state(); unput_text(0); |
1157 END_FUNCTION yy_pop_state(); unput_text(0); |
1066 END_FUNCTION_BLOCK yy_pop_state(); unput_text(0); |
1158 END_FUNCTION_BLOCK yy_pop_state(); unput_text(0); |
1067 END_PROGRAM yy_pop_state(); unput_text(0); |
1159 END_PROGRAM yy_pop_state(); unput_text(0); |
1068 } |
1160 } |
1069 |
1161 |
1070 /* decl_state -> INITIAL */ |
|
1071 <decl_state>{ |
|
1072 END_FUNCTION BEGIN(INITIAL); return END_FUNCTION; |
|
1073 END_FUNCTION_BLOCK BEGIN(INITIAL); return END_FUNCTION_BLOCK; |
|
1074 END_PROGRAM BEGIN(INITIAL); return END_PROGRAM; |
|
1075 } |
|
1076 /* config -> INITIAL */ |
1162 /* config -> INITIAL */ |
1077 END_CONFIGURATION BEGIN(INITIAL); return END_CONFIGURATION; |
1163 END_CONFIGURATION BEGIN(INITIAL); return END_CONFIGURATION; |
1078 |
1164 |
1079 |
1165 |
1080 |
1166 |
1081 /***************************************/ |
1167 /***************************************/ |
1082 /* Next is to to remove all whitespace */ |
1168 /* Next is to to remove all whitespace */ |
1083 /***************************************/ |
1169 /***************************************/ |
1084 /* NOTE: pragmas are handled right at the beginning... */ |
1170 /* NOTE: pragmas are handled right at the beginning... */ |
1085 |
1171 |
1086 <INITIAL,config_state,decl_state,st_state,sfc_state,task_init_state,sfc_qualifier_state>{st_whitespace_no_pragma} /* Eat any whitespace */ |
1172 /* The whitespace */ |
1087 <il_state>{il_whitespace_no_pragma} /* Eat any whitespace */ |
1173 <INITIAL,header_state,config_state,body_state,vardecl_list_state,vardecl_state,st_state,sfc_state,task_init_state,sfc_qualifier_state>{st_whitespace} /* Eat any whitespace */ |
1088 |
1174 <il_state>{il_whitespace} /* Eat any whitespace */ |
1089 |
1175 |
|
1176 /* The comments */ |
|
1177 <body_state,vardecl_list_state>{comment_beg} yy_push_state(comment_state); |
|
1178 {comment_beg} yy_push_state(comment_state); |
|
1179 <comment_state>{ |
|
1180 {comment_beg} {if (get_opt_nested_comments()) yy_push_state(comment_state);} |
|
1181 {comment_end} yy_pop_state(); |
|
1182 . /* Ignore text inside comment! */ |
|
1183 \n /* Ignore text inside comment! */ |
|
1184 } |
1090 |
1185 |
1091 /*****************************************/ |
1186 /*****************************************/ |
1092 /* B.1.1 Letters, digits and identifiers */ |
1187 /* B.1.1 Letters, digits and identifiers */ |
1093 /*****************************************/ |
1188 /*****************************************/ |
1094 /* NOTE: 'R1', 'IN', etc... are IL operators, and therefore tokens |
1189 /* NOTE: 'R1', 'IN', etc... are IL operators, and therefore tokens |