|
1 /* |
|
2 * (c) 2003 Mario de Sousa |
|
3 * |
|
4 * Offered to the public under the terms of the GNU General Public License |
|
5 * as published by the Free Software Foundation; either version 2 of the |
|
6 * License, or (at your option) any later version. |
|
7 * |
|
8 * This program is distributed in the hope that it will be useful, but |
|
9 * WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
|
11 * Public License for more details. |
|
12 * |
|
13 * This code is made available on the understanding that it will not be |
|
14 * used in safety-critical situations without a full and competent review. |
|
15 */ |
|
16 |
|
17 /* |
|
18 * An IEC 61131-3 IL and ST compiler. |
|
19 * |
|
20 * Based on the |
|
21 * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) |
|
22 * |
|
23 */ |
|
24 |
|
25 /* |
|
26 * Stage 2 |
|
27 * ======= |
|
28 * |
|
29 * This file contains the syntax definition of the textual |
|
30 * languages IL and ST. The syntax parser, comprising the |
|
31 * 2nd stage of the overall compiler, is generated by runing |
|
32 * bison on this file. |
|
33 */ |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 /**********************************************************************/ |
|
39 /**********************************************************************/ |
|
40 /**********************************************************************/ |
|
41 /**********************************************************************/ |
|
42 /******* *******/ |
|
43 /******* The following syntax does not have any conflicts. *******/ |
|
44 /******* *******/ |
|
45 /******* P L E A S E K E E P I T T H A T W A Y ! *******/ |
|
46 /******* =================================================== *******/ |
|
47 /******* *******/ |
|
48 /**********************************************************************/ |
|
49 /**********************************************************************/ |
|
50 /**********************************************************************/ |
|
51 /**********************************************************************/ |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 %{ |
|
57 #include <string.h> /* required for strdup() */ |
|
58 |
|
59 |
|
60 /* declare the token parser generated by flex... */ |
|
61 int yylex(void); |
|
62 |
|
63 /* declare the error handler defined at the end of this file */ |
|
64 void yyerror (const char *error_msg); |
|
65 |
|
66 /* produce a more verbose parsing error message */ |
|
67 #define YYERROR_VERBOSE |
|
68 |
|
69 /* Include debuging code. |
|
70 * Printing of debug info must then be activated by setting |
|
71 * the variable yydebug to 1. |
|
72 */ |
|
73 #define YYDEBUG 0 |
|
74 |
|
75 |
|
76 /* file with declaration of absyntax classes... */ |
|
77 #include "../absyntax/absyntax.hh" |
|
78 |
|
79 /* file with declaration of token constants. Generated by bison! */ |
|
80 #include "iec.y.hh" |
|
81 |
|
82 /* file with the declarations of symbol tables... */ |
|
83 #include "../util/symtable.hh" |
|
84 |
|
85 |
|
86 /* an ugly hack!! |
|
87 * We will probably not need it when we decide |
|
88 * to cut down the abstract syntax down to size. |
|
89 * We keep it as it is until we get to write |
|
90 * stages 3 and 4 of the compiler. Who knows, |
|
91 * we might just find out that we really do need |
|
92 * the abstract syntax tree to stay as it is |
|
93 * afterall! |
|
94 */ |
|
95 /* for each element <elem> in list_c * <list> |
|
96 * execute the code <code> |
|
97 */ |
|
98 #define FOR_EACH_ELEMENT(elem, list, code) { \ |
|
99 symbol_c *elem; \ |
|
100 for(int i = 0; i < list->n; i++) { \ |
|
101 elem = list->elements[i]; \ |
|
102 code; \ |
|
103 } \ |
|
104 } |
|
105 |
|
106 |
|
107 /* A macro for printing out internal parser errors... */ |
|
108 #define ERROR error_exit(__FILE__,__LINE__) |
|
109 /* function defined in main.cc */ |
|
110 extern void error_exit(const char *file_name, int line_no); |
|
111 |
|
112 |
|
113 /*********************************/ |
|
114 /* The global symbol tables... */ |
|
115 /*********************************/ |
|
116 /* NOTE: declared static because they are not accessed |
|
117 * directly by the lexical parser (flex), but rather |
|
118 * through the function get_identifier_token() |
|
119 */ |
|
120 /* A symbol table to store all the library elements */ |
|
121 /* e.g.: <function_name , function_decl> |
|
122 * <fb_name , fb_decl> |
|
123 * <type_name , type_decl> |
|
124 * <program_name , program_decl> |
|
125 * <configuration_name , configuration_decl> |
|
126 */ |
|
127 static symtable_c<int, BOGUS_TOKEN_ID> library_element_symtable; |
|
128 |
|
129 /* A symbol table to store the declared variables of |
|
130 * the function currently being parsed... |
|
131 */ |
|
132 static symtable_c<int, BOGUS_TOKEN_ID> variable_name_symtable; |
|
133 |
|
134 |
|
135 /*************************/ |
|
136 /* global variables... */ |
|
137 /*************************/ |
|
138 static symbol_c *tree_root = NULL; |
|
139 |
|
140 /* The name of the file currently being parsed... |
|
141 * Note that flex accesses and updates this global variable |
|
142 * apropriately whenever it comes across an (*#include <filename> *) |
|
143 * directive... |
|
144 */ |
|
145 const char *current_filename = NULL; |
|
146 |
|
147 /* A global flag used to tell the parser if overloaded funtions should be allowed. |
|
148 * The IEC 61131-3 standard allows overloaded funtions in the standard library, |
|
149 * but disallows them in user code... |
|
150 */ |
|
151 bool allow_function_overloading = false; |
|
152 |
|
153 |
|
154 /************************/ |
|
155 /* forward declarations */ |
|
156 /************************/ |
|
157 /* The functions declared here are defined at the end of this file... */ |
|
158 |
|
159 /* Convert an il_operator_c into an identifier_c */ |
|
160 symbol_c *il_operator_c_2_identifier_c(symbol_c *il_operator); |
|
161 |
|
162 /* print an error message */ |
|
163 void print_err_msg(const char *filename, int lineno, const char *additional_error_msg); |
|
164 |
|
165 |
|
166 /************************/ |
|
167 /* forward declarations */ |
|
168 /************************/ |
|
169 /* The functions declared here are defined in iec.flex... */ |
|
170 void print_include_stack(void); |
|
171 |
|
172 |
|
173 %} |
|
174 |
|
175 |
|
176 |
|
177 %union { |
|
178 symbol_c *leaf; |
|
179 list_c *list; |
|
180 char *ID; /* token value */ |
|
181 struct { |
|
182 symbol_c *first; |
|
183 symbol_c *second; |
|
184 } double_symbol; /* used by il_simple_operator_clash_il_operand */ |
|
185 } |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 |
|
192 /*****************************/ |
|
193 /* Prelimenary constructs... */ |
|
194 /*****************************/ |
|
195 %type <leaf> start |
|
196 |
|
197 %type <leaf> any_identifier |
|
198 |
|
199 %token <ID> prev_declared_variable_name_token |
|
200 %token <ID> prev_declared_fb_name_token |
|
201 %type <leaf> prev_declared_variable_name |
|
202 %type <leaf> prev_declared_fb_name |
|
203 |
|
204 %token <ID> prev_declared_simple_type_name_token |
|
205 %token <ID> prev_declared_subrange_type_name_token |
|
206 %token <ID> prev_declared_enumerated_type_name_token |
|
207 %token <ID> prev_declared_array_type_name_token |
|
208 %token <ID> prev_declared_structure_type_name_token |
|
209 %token <ID> prev_declared_string_type_name_token |
|
210 |
|
211 %type <leaf> prev_declared_simple_type_name |
|
212 %type <leaf> prev_declared_subrange_type_name |
|
213 %type <leaf> prev_declared_enumerated_type_name |
|
214 %type <leaf> prev_declared_array_type_name |
|
215 %type <leaf> prev_declared_structure_type_name |
|
216 %type <leaf> prev_declared_string_type_name |
|
217 |
|
218 %token <ID> prev_declared_derived_function_name_token |
|
219 %token <ID> prev_declared_derived_function_block_name_token |
|
220 %token <ID> prev_declared_program_type_name_token |
|
221 %type <leaf> prev_declared_derived_function_name |
|
222 %type <leaf> prev_declared_derived_function_block_name |
|
223 %type <leaf> prev_declared_program_type_name |
|
224 |
|
225 |
|
226 /* A bogus token that, in principle, flex MUST NEVER generate */ |
|
227 /* USE 1: |
|
228 * ====== |
|
229 * This token is currently also being used as the default |
|
230 * initialisation value of the token_id member in |
|
231 * the symbol_c base class. |
|
232 * |
|
233 * USE 2 |
|
234 * ===== |
|
235 * This token may also be used in the future to remove |
|
236 * mysterious reduce/reduce conflicts due to the fact |
|
237 * that our grammar may not be LALR(1) but merely LR(1). |
|
238 * This means that bison cannot handle it without some |
|
239 * caoxing from ourselves. We will then need this token |
|
240 * to do the coaxing... |
|
241 */ |
|
242 %token BOGUS_TOKEN_ID |
|
243 |
|
244 |
|
245 /* The pragmas... */ |
|
246 %token <ID> pragma_token |
|
247 %type <leaf> pragma |
|
248 |
|
249 |
|
250 /* Where do these tokens belong ?? */ |
|
251 /* TODO: get the syntax parser to handle these tokens... */ |
|
252 %token EN |
|
253 %token ENO |
|
254 |
|
255 |
|
256 |
|
257 /***************************/ |
|
258 /* B 0 - Programming Model */ |
|
259 /***************************/ |
|
260 %type <list> library |
|
261 %type <leaf> library_element_declaration |
|
262 |
|
263 |
|
264 /*******************************************/ |
|
265 /* B 1.1 - Letters, digits and identifiers */ |
|
266 /*******************************************/ |
|
267 /* Done totally within flex... |
|
268 letter |
|
269 digit |
|
270 octal_digit |
|
271 hex_digit |
|
272 */ |
|
273 %token <ID> identifier_token |
|
274 %type <leaf> identifier |
|
275 |
|
276 |
|
277 /*********************/ |
|
278 /* B 1.2 - Constants */ |
|
279 /*********************/ |
|
280 %type <leaf> constant |
|
281 /* a helper symbol for expression */ |
|
282 %type <leaf> non_negative_constant |
|
283 |
|
284 |
|
285 /******************************/ |
|
286 /* B 1.2.1 - Numeric Literals */ |
|
287 /******************************/ |
|
288 /* Done totally within flex... |
|
289 bit |
|
290 */ |
|
291 %type <leaf> numeric_literal |
|
292 /* helper symbol for non_negative_constant */ |
|
293 %type <leaf> non_negative_numeric_literal |
|
294 %type <leaf> integer_literal |
|
295 %type <leaf> signed_integer |
|
296 /* a helper symbol for non_negative_constant */ |
|
297 %type <leaf> non_negative_signed_integer |
|
298 %token <ID> integer_token |
|
299 %type <leaf> integer |
|
300 %token <ID> binary_integer_token |
|
301 %type <leaf> binary_integer |
|
302 %token <ID> octal_integer_token |
|
303 %type <leaf> octal_integer |
|
304 %token <ID> hex_integer_token |
|
305 %type <leaf> hex_integer |
|
306 %token <ID> real_token |
|
307 %type <leaf> real |
|
308 %type <leaf> signed_real |
|
309 /* helper symbol for non_negative_real_literal */ |
|
310 %type <leaf> non_negative_signed_real |
|
311 %type <leaf> real_literal |
|
312 /* helper symbol for non_negative_numeric_literal */ |
|
313 %type <leaf> non_negative_real_literal |
|
314 // %type <leaf> exponent |
|
315 %type <leaf> bit_string_literal |
|
316 %type <leaf> boolean_literal |
|
317 |
|
318 %token FALSE |
|
319 %token TRUE |
|
320 |
|
321 |
|
322 /*******************************/ |
|
323 /* B 1.2.2 - Character Strings */ |
|
324 /*******************************/ |
|
325 %token <ID> single_byte_character_string_token |
|
326 %token <ID> double_byte_character_string_token |
|
327 |
|
328 %type <leaf> character_string |
|
329 %type <leaf> single_byte_character_string |
|
330 %type <leaf> double_byte_character_string |
|
331 |
|
332 |
|
333 /***************************/ |
|
334 /* B 1.2.3 - Time Literals */ |
|
335 /***************************/ |
|
336 %type <leaf> time_literal |
|
337 |
|
338 |
|
339 /************************/ |
|
340 /* B 1.2.3.1 - Duration */ |
|
341 /************************/ |
|
342 %type <leaf> duration |
|
343 %type <leaf> interval |
|
344 %type <leaf> days |
|
345 %type <leaf> fixed_point |
|
346 %type <leaf> hours |
|
347 %type <leaf> minutes |
|
348 %type <leaf> seconds |
|
349 %type <leaf> milliseconds |
|
350 |
|
351 %type <leaf> integer_d |
|
352 %type <leaf> integer_h |
|
353 %type <leaf> integer_m |
|
354 %type <leaf> integer_s |
|
355 %type <leaf> integer_ms |
|
356 %type <leaf> fixed_point_d |
|
357 %type <leaf> fixed_point_h |
|
358 %type <leaf> fixed_point_m |
|
359 %type <leaf> fixed_point_s |
|
360 %type <leaf> fixed_point_ms |
|
361 |
|
362 %token <ID> fixed_point_token |
|
363 %token <ID> fixed_point_d_token |
|
364 %token <ID> integer_d_token |
|
365 %token <ID> fixed_point_h_token |
|
366 %token <ID> integer_h_token |
|
367 %token <ID> fixed_point_m_token |
|
368 %token <ID> integer_m_token |
|
369 %token <ID> fixed_point_s_token |
|
370 %token <ID> integer_s_token |
|
371 %token <ID> fixed_point_ms_token |
|
372 %token <ID> integer_ms_token |
|
373 |
|
374 %token TIME |
|
375 %token T_SHARP |
|
376 |
|
377 |
|
378 /************************************/ |
|
379 /* B 1.2.3.2 - Time of day and Date */ |
|
380 /************************************/ |
|
381 %type <leaf> time_of_day |
|
382 %type <leaf> daytime |
|
383 %type <leaf> day_hour |
|
384 %type <leaf> day_minute |
|
385 %type <leaf> day_second |
|
386 %type <leaf> date |
|
387 %type <leaf> date_literal |
|
388 %type <leaf> year |
|
389 %type <leaf> month |
|
390 %type <leaf> day |
|
391 %type <leaf> date_and_time |
|
392 |
|
393 %token TIME_OF_DAY |
|
394 %token DATE |
|
395 %token D_SHARP |
|
396 %token DATE_AND_TIME |
|
397 |
|
398 |
|
399 /**********************/ |
|
400 /* B 1.3 - Data Types */ |
|
401 /**********************/ |
|
402 /* Strangely, the following symbol does seem to be required! */ |
|
403 // %type <leaf> data_type_name |
|
404 %type <leaf> non_generic_type_name |
|
405 |
|
406 |
|
407 /***********************************/ |
|
408 /* B 1.3.1 - Elementary Data Types */ |
|
409 /***********************************/ |
|
410 /* NOTES: |
|
411 * |
|
412 * - To make the definition of bit_string_literal more |
|
413 * concise, it is useful to use an extra non-terminal |
|
414 * symbol (i.e. a grouping or construct) that groups the |
|
415 * following elements (BYTE, WORD, DWORD, LWORD). |
|
416 * Note that the definition of bit_string_type_name |
|
417 * (according to the spec) includes the above elements |
|
418 * and an extra BOOL. |
|
419 * We could use an extra construct with the first four |
|
420 * elements to be used solely in the definition of |
|
421 * bit_string_literal, but with the objective of not |
|
422 * having to replicate the actions (if we ever need |
|
423 * to change them, they would need to be changed in both |
|
424 * bit_string_type_name and the extra grouping), we |
|
425 * have re-defined bit_string_type_name as only including |
|
426 * the first four elements. |
|
427 * In order to have our parser implement the specification |
|
428 * correctly we have augmented every occurence of |
|
429 * bit_string_type_name in other rules with the BOOL |
|
430 * token. Since bit_string_type_name only appears in |
|
431 * the rule for elementary_type_name, this does not |
|
432 * seem to be a big concession to make! |
|
433 * |
|
434 * - We have added a helper symbol to concentrate the |
|
435 * instantiation of STRING and WSTRING into a single |
|
436 * location (elementary_string_type_name). |
|
437 * These two elements show up in several other rules, |
|
438 * but we want to create the equivalent abstract syntax |
|
439 * in a single location of this file, in order to make |
|
440 * possible future changes easier to edit... |
|
441 */ |
|
442 %type <leaf> elementary_type_name |
|
443 %type <leaf> numeric_type_name |
|
444 %type <leaf> integer_type_name |
|
445 %type <leaf> signed_integer_type_name |
|
446 %type <leaf> unsigned_integer_type_name |
|
447 %type <leaf> real_type_name |
|
448 %type <leaf> date_type_name |
|
449 %type <leaf> bit_string_type_name |
|
450 /* helper symbol to concentrate the instantiation |
|
451 * of STRING and WSTRING into a single location |
|
452 */ |
|
453 %type <leaf> elementary_string_type_name |
|
454 |
|
455 %token BYTE |
|
456 %token WORD |
|
457 %token DWORD |
|
458 %token LWORD |
|
459 |
|
460 %token LREAL |
|
461 %token REAL |
|
462 |
|
463 %token SINT |
|
464 %token INT |
|
465 %token DINT |
|
466 %token LINT |
|
467 |
|
468 %token USINT |
|
469 %token UINT |
|
470 %token UDINT |
|
471 %token ULINT |
|
472 |
|
473 %token WSTRING |
|
474 %token STRING |
|
475 %token BOOL |
|
476 |
|
477 %token TIME |
|
478 %token DATE |
|
479 %token DATE_AND_TIME |
|
480 %token DT |
|
481 %token TIME_OF_DAY |
|
482 %token TOD |
|
483 |
|
484 |
|
485 /********************************/ |
|
486 /* B 1.3.2 - Generic data types */ |
|
487 /********************************/ |
|
488 /* Strangely, the following symbol does seem to be required! */ |
|
489 // %type <leaf> generic_type_name |
|
490 |
|
491 /* The following tokens do not seem to be used either |
|
492 * but we declare them so they become reserved words... |
|
493 */ |
|
494 %token ANY |
|
495 %token ANY_DERIVED |
|
496 %token ANY_ELEMENTARY |
|
497 %token ANY_MAGNITUDE |
|
498 %token ANY_NUM |
|
499 %token ANY_REAL |
|
500 %token ANY_INT |
|
501 %token ANY_BIT |
|
502 %token ANY_STRING |
|
503 %token ANY_DATE |
|
504 |
|
505 |
|
506 /********************************/ |
|
507 /* B 1.3.3 - Derived data types */ |
|
508 /********************************/ |
|
509 %type <leaf> derived_type_name |
|
510 %type <leaf> single_element_type_name |
|
511 // %type <leaf> simple_type_name |
|
512 // %type <leaf> subrange_type_name |
|
513 // %type <leaf> enumerated_type_name |
|
514 // %type <leaf> array_type_name |
|
515 // %type <leaf> structure_type_name |
|
516 |
|
517 %type <leaf> data_type_declaration |
|
518 /* helper symbol for data_type_declaration */ |
|
519 %type <list> type_declaration_list |
|
520 %type <leaf> type_declaration |
|
521 %type <leaf> single_element_type_declaration |
|
522 |
|
523 %type <leaf> simple_type_declaration |
|
524 %type <leaf> simple_spec_init |
|
525 %type <leaf> simple_specification |
|
526 |
|
527 %type <leaf> subrange_type_declaration |
|
528 %type <leaf> subrange_spec_init |
|
529 %type <leaf> subrange_specification |
|
530 %type <leaf> subrange |
|
531 |
|
532 %type <leaf> enumerated_type_declaration |
|
533 %type <leaf> enumerated_spec_init |
|
534 %type <leaf> enumerated_specification |
|
535 /* helper symbol for enumerated_value */ |
|
536 %type <list> enumerated_value_list |
|
537 %type <leaf> enumerated_value |
|
538 |
|
539 %type <leaf> array_type_declaration |
|
540 %type <leaf> array_spec_init |
|
541 %type <leaf> array_specification |
|
542 /* helper symbol for array_specification */ |
|
543 %type <list> array_subrange_list |
|
544 %type <leaf> array_initialization |
|
545 /* helper symbol for array_initialization */ |
|
546 %type <list> array_initial_elements_list |
|
547 %type <leaf> array_initial_elements |
|
548 %type <leaf> array_initial_element |
|
549 |
|
550 %type <leaf> structure_type_declaration |
|
551 %type <leaf> structure_specification |
|
552 %type <leaf> initialized_structure |
|
553 %type <leaf> structure_declaration |
|
554 /* helper symbol for structure_declaration */ |
|
555 %type <list> structure_element_declaration_list |
|
556 %type <leaf> structure_element_declaration |
|
557 %type <leaf> structure_element_name |
|
558 %type <leaf> structure_initialization |
|
559 /* helper symbol for structure_initialization */ |
|
560 %type <list> structure_element_initialization_list |
|
561 %type <leaf> structure_element_initialization |
|
562 |
|
563 //%type <leaf> string_type_name |
|
564 %type <leaf> string_type_declaration |
|
565 /* helper symbol for string_type_declaration */ |
|
566 %type <leaf> string_type_declaration_size |
|
567 /* helper symbol for string_type_declaration */ |
|
568 %type <leaf> string_type_declaration_init |
|
569 |
|
570 %token ASSIGN |
|
571 %token DOTDOT /* ".." */ |
|
572 %token TYPE |
|
573 %token END_TYPE |
|
574 %token ARRAY |
|
575 %token OF |
|
576 %token STRUCT |
|
577 %token END_STRUCT |
|
578 |
|
579 |
|
580 |
|
581 /*********************/ |
|
582 /* B 1.4 - Variables */ |
|
583 /*********************/ |
|
584 %type <leaf> variable |
|
585 %type <leaf> symbolic_variable |
|
586 /* helper symbol for prog_cnxn */ |
|
587 %type <leaf> any_symbolic_variable |
|
588 %type <leaf> variable_name |
|
589 |
|
590 |
|
591 |
|
592 |
|
593 /********************************************/ |
|
594 /* B.1.4.1 Directly Represented Variables */ |
|
595 /********************************************/ |
|
596 /* Done totally within flex... |
|
597 location_prefix |
|
598 size_prefix |
|
599 */ |
|
600 %token <ID> direct_variable_token |
|
601 %type <leaf> direct_variable |
|
602 |
|
603 |
|
604 /*************************************/ |
|
605 /* B.1.4.2 Multi-element Variables */ |
|
606 /*************************************/ |
|
607 %type <leaf> multi_element_variable |
|
608 /* helper symbol for any_symbolic_variable */ |
|
609 %type <leaf> any_multi_element_variable |
|
610 %type <leaf> array_variable |
|
611 /* helper symbol for any_symbolic_variable */ |
|
612 %type <leaf> any_array_variable |
|
613 %type <leaf> subscripted_variable |
|
614 /* helper symbol for any_symbolic_variable */ |
|
615 %type <leaf> any_subscripted_variable |
|
616 %type <list> subscript_list |
|
617 %type <leaf> subscript |
|
618 %type <leaf> structured_variable |
|
619 /* helper symbol for any_symbolic_variable */ |
|
620 %type <leaf> any_structured_variable |
|
621 %type <leaf> record_variable |
|
622 /* helper symbol for any_symbolic_variable */ |
|
623 %type <leaf> any_record_variable |
|
624 %type <leaf> field_selector |
|
625 |
|
626 |
|
627 /******************************************/ |
|
628 /* B 1.4.3 - Declaration & Initialisation */ |
|
629 /******************************************/ |
|
630 %type <leaf> input_declarations |
|
631 /* helper symbol for input_declarations */ |
|
632 %type <list> input_declaration_list |
|
633 %type <leaf> input_declaration |
|
634 %type <leaf> edge_declaration |
|
635 %type <leaf> var_init_decl |
|
636 %type <leaf> var1_init_decl |
|
637 %type <list> var1_list |
|
638 %type <leaf> array_var_init_decl |
|
639 %type <leaf> structured_var_init_decl |
|
640 %type <leaf> fb_name_decl |
|
641 /* helper symbol for fb_name_decl */ |
|
642 %type <list> fb_name_list_with_colon |
|
643 /* helper symbol for fb_name_list_with_colon */ |
|
644 %type <list> var1_list_with_colon |
|
645 // %type <list> fb_name_list |
|
646 // %type <leaf> fb_name |
|
647 %type <leaf> output_declarations |
|
648 %type <leaf> input_output_declarations |
|
649 /* helper symbol for input_output_declarations */ |
|
650 %type <list> var_declaration_list |
|
651 %type <leaf> var_declaration |
|
652 %type <leaf> temp_var_decl |
|
653 %type <leaf> var1_declaration |
|
654 %type <leaf> array_var_declaration |
|
655 %type <leaf> structured_var_declaration |
|
656 %type <leaf> var_declarations |
|
657 %type <leaf> retentive_var_declarations |
|
658 %type <leaf> located_var_declarations |
|
659 /* helper symbol for located_var_declarations */ |
|
660 %type <list> located_var_decl_list |
|
661 %type <leaf> located_var_decl |
|
662 %type <leaf> external_var_declarations |
|
663 /* helper symbol for external_var_declarations */ |
|
664 %type <list> external_declaration_list |
|
665 %type <leaf> external_declaration |
|
666 %type <leaf> global_var_name |
|
667 %type <leaf> global_var_declarations |
|
668 /* helper symbol for global_var_declarations */ |
|
669 %type <list> global_var_decl_list |
|
670 %type <leaf> global_var_decl |
|
671 %type <leaf> global_var_spec |
|
672 %type <leaf> located_var_spec_init |
|
673 %type <leaf> location |
|
674 %type <list> global_var_list |
|
675 %type <leaf> string_var_declaration |
|
676 %type <leaf> single_byte_string_var_declaration |
|
677 %type <leaf> single_byte_string_spec |
|
678 %type <leaf> double_byte_string_var_declaration |
|
679 %type <leaf> double_byte_string_spec |
|
680 %type <leaf> incompl_located_var_declarations |
|
681 /* helper symbol for incompl_located_var_declarations */ |
|
682 %type <list> incompl_located_var_decl_list |
|
683 %type <leaf> incompl_located_var_decl |
|
684 %type <leaf> incompl_location |
|
685 %type <leaf> var_spec |
|
686 /* helper symbol for var_spec */ |
|
687 %type <leaf> string_spec |
|
688 /* intermediate helper symbol for: |
|
689 * - non_retentive_var_decls |
|
690 * - output_declarations |
|
691 */ |
|
692 %type <list> var_init_decl_list |
|
693 |
|
694 %token <ID> incompl_location_token |
|
695 |
|
696 %token VAR_INPUT |
|
697 %token VAR_OUTPUT |
|
698 %token VAR_IN_OUT |
|
699 %token VAR_EXTERNAL |
|
700 %token VAR_GLOBAL |
|
701 %token END_VAR |
|
702 %token RETAIN |
|
703 %token NON_RETAIN |
|
704 %token R_EDGE |
|
705 %token F_EDGE |
|
706 %token AT |
|
707 |
|
708 |
|
709 /***********************/ |
|
710 /* B 1.5.1 - Functions */ |
|
711 /***********************/ |
|
712 //%type <leaf> function_name |
|
713 /* helper symbol for IL language */ |
|
714 %type <leaf> function_name_no_clashes |
|
715 %type <leaf> function_name_simpleop_clashes |
|
716 //%type <leaf> function_name_expression_clashes |
|
717 /* helper symbols for ST language */ |
|
718 //%type <leaf> function_name_NOT_clashes |
|
719 %type <leaf> function_name_no_NOT_clashes |
|
720 |
|
721 //%type <leaf> standard_function_name |
|
722 /* helper symbols for IL language */ |
|
723 %type <leaf> standard_function_name_no_clashes |
|
724 %type <leaf> standard_function_name_simpleop_clashes |
|
725 %type <leaf> standard_function_name_expression_clashes |
|
726 /* helper symbols for ST language */ |
|
727 %type <leaf> standard_function_name_NOT_clashes |
|
728 %type <leaf> standard_function_name_no_NOT_clashes |
|
729 |
|
730 %type <leaf> derived_function_name |
|
731 %type <leaf> function_declaration |
|
732 /* helper symbol for function_declaration */ |
|
733 %type <leaf> function_name_declaration |
|
734 %type <leaf> io_var_declarations |
|
735 %type <leaf> function_var_decls |
|
736 %type <leaf> function_body |
|
737 %type <leaf> var2_init_decl |
|
738 /* intermediate helper symbol for function_declaration */ |
|
739 %type <list> io_OR_function_var_declarations_list |
|
740 /* intermediate helper symbol for function_var_decls */ |
|
741 %type <list> var2_init_decl_list |
|
742 |
|
743 %token <ID> standard_function_name_token |
|
744 |
|
745 %token FUNCTION |
|
746 %token END_FUNCTION |
|
747 %token CONSTANT |
|
748 |
|
749 |
|
750 /*****************************/ |
|
751 /* B 1.5.2 - Function Blocks */ |
|
752 /*****************************/ |
|
753 %type <leaf> function_block_type_name |
|
754 %type <leaf> standard_function_block_name |
|
755 %type <leaf> derived_function_block_name |
|
756 %type <leaf> function_block_declaration |
|
757 %type <leaf> other_var_declarations |
|
758 %type <leaf> temp_var_decls |
|
759 %type <leaf> non_retentive_var_decls |
|
760 %type <leaf> function_block_body |
|
761 /* intermediate helper symbol for function_declaration */ |
|
762 %type <list> io_OR_other_var_declarations_list |
|
763 /* intermediate helper symbol for temp_var_decls */ |
|
764 %type <list> temp_var_decls_list |
|
765 |
|
766 %token <ID> standard_function_block_name_token |
|
767 |
|
768 %token FUNCTION_BLOCK |
|
769 %token END_FUNCTION_BLOCK |
|
770 %token VAR_TEMP |
|
771 %token END_VAR |
|
772 %token VAR |
|
773 %token NON_RETAIN |
|
774 %token END_VAR |
|
775 |
|
776 |
|
777 /**********************/ |
|
778 /* B 1.5.3 - Programs */ |
|
779 /**********************/ |
|
780 %type <leaf> program_type_name |
|
781 %type <leaf> program_declaration |
|
782 /* helper symbol for program_declaration */ |
|
783 %type <list> program_var_declarations_list |
|
784 |
|
785 %token PROGRAM |
|
786 %token END_PROGRAM |
|
787 |
|
788 |
|
789 /********************************************/ |
|
790 /* B 1.6 Sequential Function Chart elements */ |
|
791 /********************************************/ |
|
792 /* TODO */ |
|
793 /* |
|
794 %type <list> sequential_function_chart |
|
795 %type <leaf> sfc_network |
|
796 %type <leaf> initial_step |
|
797 %type <leaf> step |
|
798 %type <leaf> action_association_list |
|
799 %type <leaf> step_name |
|
800 %type <leaf> action_association |
|
801 /* helper symbol for action_association * |
|
802 %type <list> indicator_name_list |
|
803 %type <leaf> action_name |
|
804 %type <leaf> action_qualifier |
|
805 %type <leaf> timed_qualifier |
|
806 %type <leaf> action_time |
|
807 %type <leaf> indicator_name |
|
808 %type <leaf> transition |
|
809 %type <leaf> steps |
|
810 %type <list> step_name_list |
|
811 %type <leaf> transition_condition |
|
812 %type <leaf> action |
|
813 */ |
|
814 |
|
815 %token ASSIGN |
|
816 %token ACTION |
|
817 %token END_ACTION |
|
818 |
|
819 %token TRANSITION |
|
820 %token END_TRANSITION |
|
821 %token FROM |
|
822 %token TO |
|
823 %token PRIORITY |
|
824 |
|
825 %token INITIAL_STEP |
|
826 %token STEP |
|
827 %token END_STEP |
|
828 |
|
829 %token L |
|
830 %token D |
|
831 %token SD |
|
832 %token DS |
|
833 %token SL |
|
834 |
|
835 %token N |
|
836 %token P |
|
837 /* NOTE: the following two clash with the R and S IL operators. |
|
838 * It will have to be handled when we include parsing of SFC... |
|
839 */ |
|
840 /* |
|
841 %token R |
|
842 %token S |
|
843 */ |
|
844 |
|
845 |
|
846 /********************************/ |
|
847 /* B 1.7 Configuration elements */ |
|
848 /********************************/ |
|
849 %type <leaf> configuration_name |
|
850 %type <leaf> resource_type_name |
|
851 %type <leaf> configuration_declaration |
|
852 // helper symbol for |
|
853 // - configuration_declaration |
|
854 // - resource_declaration |
|
855 // |
|
856 %type <leaf> optional_global_var_declarations |
|
857 // helper symbol for configuration_declaration |
|
858 %type <leaf> optional_access_declarations |
|
859 // helper symbol for configuration_declaration |
|
860 %type <leaf> optional_instance_specific_initializations |
|
861 // helper symbol for configuration_declaration |
|
862 %type <list> resource_declaration_list |
|
863 %type <leaf> resource_declaration |
|
864 %type <leaf> single_resource_declaration |
|
865 // helper symbol for single_resource_declaration |
|
866 %type <list> task_configuration_list |
|
867 // helper symbol for single_resource_declaration |
|
868 %type <list> program_configuration_list |
|
869 %type <leaf> resource_name |
|
870 // %type <leaf> access_declarations |
|
871 // helper symbol for access_declarations |
|
872 // %type <leaf> access_declaration_list |
|
873 // %type <leaf> access_declaration |
|
874 // %type <leaf> access_path |
|
875 // helper symbol for access_path |
|
876 %type <list> any_fb_name_list |
|
877 %type <leaf> global_var_reference |
|
878 // %type <leaf> access_name |
|
879 %type <leaf> program_output_reference |
|
880 %type <leaf> program_name |
|
881 // %type <leaf> direction |
|
882 %type <leaf> task_configuration |
|
883 %type <leaf> task_name |
|
884 %type <leaf> task_initialization |
|
885 %type <leaf> data_source |
|
886 %type <leaf> program_configuration |
|
887 // helper symbol for program_configuration |
|
888 %type <leaf> optional_task_name |
|
889 // helper symbol for program_configuration |
|
890 %type <leaf> optional_prog_conf_elements |
|
891 %type <list> prog_conf_elements |
|
892 %type <leaf> prog_conf_element |
|
893 %type <leaf> fb_task |
|
894 %type <leaf> prog_cnxn |
|
895 %type <leaf> prog_data_source |
|
896 %type <leaf> data_sink |
|
897 %type <leaf> instance_specific_initializations |
|
898 // helper symbol for instance_specific_initializations |
|
899 %type <list> instance_specific_init_list |
|
900 %type <leaf> instance_specific_init |
|
901 // helper symbol for instance_specific_init |
|
902 %type <leaf> fb_initialization |
|
903 |
|
904 %type <leaf> prev_declared_global_var_name |
|
905 %token <ID> prev_declared_global_var_name_token |
|
906 |
|
907 %type <leaf> prev_declared_program_name |
|
908 %token <ID> prev_declared_program_name_token |
|
909 |
|
910 %type <leaf> prev_declared_resource_name |
|
911 %token <ID> prev_declared_resource_name_token |
|
912 |
|
913 %token <ID> prev_declared_configuration_name_token |
|
914 |
|
915 // %type <leaf> prev_declared_task_name |
|
916 // %token <ID> prev_declared_task_name_token |
|
917 |
|
918 %token CONFIGURATION |
|
919 %token END_CONFIGURATION |
|
920 %token TASK |
|
921 %token RESOURCE |
|
922 %token ON |
|
923 %token END_RESOURCE |
|
924 %token VAR_CONFIG |
|
925 %token VAR_ACCESS |
|
926 %token END_VAR |
|
927 %token WITH |
|
928 %token PROGRAM |
|
929 %token RETAIN |
|
930 %token NON_RETAIN |
|
931 %token PRIORITY |
|
932 %token SINGLE |
|
933 %token INTERVAL |
|
934 %token READ_WRITE |
|
935 %token READ_ONLY |
|
936 |
|
937 |
|
938 /***********************************/ |
|
939 /* B 2.1 Instructions and Operands */ |
|
940 /***********************************/ |
|
941 %type <list> instruction_list |
|
942 %type <leaf> il_instruction |
|
943 %type <leaf> il_incomplete_instruction |
|
944 %type <leaf> label |
|
945 %type <leaf> il_simple_operation |
|
946 // helper symbol for il_simple_operation |
|
947 %type <double_symbol> il_simple_operator_clash_il_operand |
|
948 %type <leaf> il_expression |
|
949 %type <leaf> il_jump_operation |
|
950 %type <leaf> il_fb_call |
|
951 %type <leaf> il_formal_funct_call |
|
952 // helper symbol for il_formal_funct_call |
|
953 %type <leaf> il_expr_operator_clash_eol_list |
|
954 %type <leaf> il_operand |
|
955 %type <list> il_operand_list |
|
956 %type <list> simple_instr_list |
|
957 %type <leaf> il_simple_instruction |
|
958 %type <list> il_param_list |
|
959 %type <list> il_param_instruction_list |
|
960 %type <leaf> il_param_instruction |
|
961 %type <leaf> il_param_last_instruction |
|
962 %type <leaf> il_param_assignment |
|
963 %type <leaf> il_param_out_assignment |
|
964 |
|
965 %token EOL |
|
966 |
|
967 |
|
968 /*******************/ |
|
969 /* B 2.2 Operators */ |
|
970 /*******************/ |
|
971 %token <ID> sendto_identifier_token |
|
972 %type <leaf> sendto_identifier |
|
973 |
|
974 %type <leaf> LD_operator |
|
975 %type <leaf> LDN_operator |
|
976 %type <leaf> ST_operator |
|
977 %type <leaf> STN_operator |
|
978 %type <leaf> NOT_operator |
|
979 %type <leaf> S_operator |
|
980 %type <leaf> R_operator |
|
981 %type <leaf> S1_operator |
|
982 %type <leaf> R1_operator |
|
983 %type <leaf> CLK_operator |
|
984 %type <leaf> CU_operator |
|
985 %type <leaf> CD_operator |
|
986 %type <leaf> PV_operator |
|
987 %type <leaf> IN_operator |
|
988 %type <leaf> PT_operator |
|
989 %type <leaf> AND_operator |
|
990 %type <leaf> AND2_operator |
|
991 %type <leaf> OR_operator |
|
992 %type <leaf> XOR_operator |
|
993 %type <leaf> ANDN_operator |
|
994 %type <leaf> ANDN2_operator |
|
995 %type <leaf> ORN_operator |
|
996 %type <leaf> XORN_operator |
|
997 %type <leaf> ADD_operator |
|
998 %type <leaf> SUB_operator |
|
999 %type <leaf> MUL_operator |
|
1000 %type <leaf> DIV_operator |
|
1001 %type <leaf> MOD_operator |
|
1002 %type <leaf> GT_operator |
|
1003 %type <leaf> GE_operator |
|
1004 %type <leaf> EQ_operator |
|
1005 %type <leaf> LT_operator |
|
1006 %type <leaf> LE_operator |
|
1007 %type <leaf> NE_operator |
|
1008 %type <leaf> CAL_operator |
|
1009 %type <leaf> CALC_operator |
|
1010 %type <leaf> CALCN_operator |
|
1011 %type <leaf> RET_operator |
|
1012 %type <leaf> RETC_operator |
|
1013 %type <leaf> RETCN_operator |
|
1014 %type <leaf> JMP_operator |
|
1015 %type <leaf> JMPC_operator |
|
1016 %type <leaf> JMPCN_operator |
|
1017 |
|
1018 %type <leaf> il_simple_operator |
|
1019 %type <leaf> il_simple_operator_clash |
|
1020 %type <leaf> il_simple_operator_clash1 |
|
1021 %type <leaf> il_simple_operator_clash2 |
|
1022 %type <leaf> il_simple_operator_noclash |
|
1023 |
|
1024 //%type <leaf> il_expr_operator |
|
1025 %type <leaf> il_expr_operator_clash |
|
1026 %type <leaf> il_expr_operator_noclash |
|
1027 |
|
1028 %type <leaf> il_assign_operator |
|
1029 %type <leaf> il_assign_out_operator |
|
1030 %type <leaf> il_call_operator |
|
1031 %type <leaf> il_return_operator |
|
1032 %type <leaf> il_jump_operator |
|
1033 |
|
1034 |
|
1035 %token LD |
|
1036 %token LDN |
|
1037 %token ST |
|
1038 %token STN |
|
1039 %token NOT |
|
1040 %token S |
|
1041 %token R |
|
1042 %token S1 |
|
1043 %token R1 |
|
1044 %token CLK |
|
1045 %token CU |
|
1046 %token CD |
|
1047 %token PV |
|
1048 %token IN |
|
1049 %token PT |
|
1050 %token AND |
|
1051 %token AND2 /* character '&' in the source code*/ |
|
1052 %token OR |
|
1053 %token XOR |
|
1054 %token ANDN |
|
1055 %token ANDN2 /* characters '&N' in the source code */ |
|
1056 %token ORN |
|
1057 %token XORN |
|
1058 %token ADD |
|
1059 %token SUB |
|
1060 %token MUL |
|
1061 %token DIV |
|
1062 %token MOD |
|
1063 %token GT |
|
1064 %token GE |
|
1065 %token EQ |
|
1066 %token LT |
|
1067 %token LE |
|
1068 %token NE |
|
1069 %token CAL |
|
1070 %token CALC |
|
1071 %token CALCN |
|
1072 %token RET |
|
1073 %token RETC |
|
1074 %token RETCN |
|
1075 %token JMP |
|
1076 %token JMPC |
|
1077 %token JMPCN |
|
1078 |
|
1079 %token SENDTO /* "=>" */ |
|
1080 |
|
1081 |
|
1082 /***********************/ |
|
1083 /* B 3.1 - Expressions */ |
|
1084 /***********************/ |
|
1085 /* NOTE: |
|
1086 * |
|
1087 * - unary_operator, multiply_operator, |
|
1088 * add_operator and comparison_operator |
|
1089 * are not required. Their values are integrated |
|
1090 * directly into other rules... |
|
1091 */ |
|
1092 %type <leaf> expression |
|
1093 %type <leaf> xor_expression |
|
1094 %type <leaf> and_expression |
|
1095 %type <leaf> comparison |
|
1096 %type <leaf> equ_expression |
|
1097 // %type <leaf> comparison_operator |
|
1098 %type <leaf> add_expression |
|
1099 // %type <leaf> add_operator |
|
1100 %type <leaf> term |
|
1101 // %type <leaf> multiply_operator |
|
1102 %type <leaf> power_expression |
|
1103 %type <leaf> unary_expression |
|
1104 // %type <leaf> unary_operator |
|
1105 %type <leaf> primary_expression |
|
1106 /* intermediate helper symbol for primary_expression */ |
|
1107 %type <leaf> function_invocation |
|
1108 |
|
1109 %token AND |
|
1110 %token XOR |
|
1111 %token OR |
|
1112 %token MOD |
|
1113 %token NOT |
|
1114 %token OPER_NE |
|
1115 %token OPER_GE |
|
1116 %token OPER_LE |
|
1117 %token OPER_EXP |
|
1118 |
|
1119 |
|
1120 /********************/ |
|
1121 /* B 3.2 Statements */ |
|
1122 /********************/ |
|
1123 %type <list> statement_list |
|
1124 %type <leaf> statement |
|
1125 |
|
1126 |
|
1127 |
|
1128 /*********************************/ |
|
1129 /* B 3.2.1 Assignment Statements */ |
|
1130 /*********************************/ |
|
1131 %type <leaf> assignment_statement |
|
1132 %token ASSIGN /* ":=" */ |
|
1133 |
|
1134 |
|
1135 /*****************************************/ |
|
1136 /* B 3.2.2 Subprogram Control Statements */ |
|
1137 /*****************************************/ |
|
1138 %type <leaf> subprogram_control_statement |
|
1139 %type <leaf> return_statement |
|
1140 %type <leaf> fb_invocation |
|
1141 %type <leaf> param_assignment |
|
1142 /* helper symbol for fb_invocation */ |
|
1143 %type <list> param_assignment_list |
|
1144 |
|
1145 %token ASSIGN |
|
1146 %token SENDTO /* "=>" */ |
|
1147 %token RETURN |
|
1148 |
|
1149 |
|
1150 /********************************/ |
|
1151 /* B 3.2.3 Selection Statements */ |
|
1152 /********************************/ |
|
1153 %type <leaf> selection_statement |
|
1154 %type <leaf> if_statement |
|
1155 %type <leaf> case_statement |
|
1156 %type <leaf> case_element |
|
1157 %type <list> case_list |
|
1158 %type <leaf> case_list_element |
|
1159 /* helper symbol for if_statement */ |
|
1160 %type <list> elseif_statement_list |
|
1161 /* helper symbol for elseif_statement_list */ |
|
1162 %type <leaf> elseif_statement |
|
1163 /* helper symbol for case_statement */ |
|
1164 %type <list> case_element_list |
|
1165 |
|
1166 %token IF |
|
1167 %token THEN |
|
1168 %token ELSIF |
|
1169 %token ELSE |
|
1170 %token END_IF |
|
1171 |
|
1172 %token CASE |
|
1173 %token OF |
|
1174 %token ELSE |
|
1175 %token END_CASE |
|
1176 |
|
1177 |
|
1178 |
|
1179 /********************************/ |
|
1180 /* B 3.2.4 Iteration Statements */ |
|
1181 /********************************/ |
|
1182 %type <leaf> iteration_statement |
|
1183 %type <leaf> for_statement |
|
1184 %type <leaf> control_variable |
|
1185 %type <leaf> while_statement |
|
1186 %type <leaf> repeat_statement |
|
1187 %type <leaf> exit_statement |
|
1188 /* Integrated directly into for_statement */ |
|
1189 // %type <leaf> for_list |
|
1190 |
|
1191 %token FOR |
|
1192 %token ASSIGN |
|
1193 %token TO |
|
1194 %token BY |
|
1195 %token DO |
|
1196 %token END_FOR |
|
1197 |
|
1198 %token WHILE |
|
1199 %token DO |
|
1200 %token END_WHILE |
|
1201 |
|
1202 %token REPEAT |
|
1203 %token UNTIL |
|
1204 %token END_REPEAT |
|
1205 |
|
1206 %token EXIT |
|
1207 |
|
1208 %% |
|
1209 |
|
1210 |
|
1211 |
|
1212 |
|
1213 /********************************************************/ |
|
1214 /********************************************************/ |
|
1215 /********************************************************/ |
|
1216 /********************************************************/ |
|
1217 /********************************************************/ |
|
1218 /********************************************************/ |
|
1219 /********************************************************/ |
|
1220 /********************************************************/ |
|
1221 /********************************************************/ |
|
1222 /********************************************************/ |
|
1223 /********************************************************/ |
|
1224 /********************************************************/ |
|
1225 /********************************************************/ |
|
1226 /********************************************************/ |
|
1227 /********************************************************/ |
|
1228 /********************************************************/ |
|
1229 /********************************************************/ |
|
1230 /********************************************************/ |
|
1231 /********************************************************/ |
|
1232 /********************************************************/ |
|
1233 /********************************************************/ |
|
1234 /********************************************************/ |
|
1235 /********************************************************/ |
|
1236 /********************************************************/ |
|
1237 /********************************************************/ |
|
1238 /********************************************************/ |
|
1239 /********************************************************/ |
|
1240 /********************************************************/ |
|
1241 /********************************************************/ |
|
1242 /********************************************************/ |
|
1243 /********************************************************/ |
|
1244 /********************************************************/ |
|
1245 /********************************************************/ |
|
1246 /********************************************************/ |
|
1247 /********************************************************/ |
|
1248 /********************************************************/ |
|
1249 /********************************************************/ |
|
1250 /********************************************************/ |
|
1251 /********************************************************/ |
|
1252 /********************************************************/ |
|
1253 /********************************************************/ |
|
1254 /********************************************************/ |
|
1255 /********************************************************/ |
|
1256 /********************************************************/ |
|
1257 /********************************************************/ |
|
1258 |
|
1259 |
|
1260 |
|
1261 |
|
1262 |
|
1263 /*****************************/ |
|
1264 /* Prelimenary constructs... */ |
|
1265 /*****************************/ |
|
1266 start: |
|
1267 library {$$ = $1;} |
|
1268 ; |
|
1269 |
|
1270 /* the pragmas... */ |
|
1271 pragma: |
|
1272 pragma_token {$$ = new pragma_c($1);} |
|
1273 |
|
1274 |
|
1275 |
|
1276 /* NOTE: |
|
1277 * short version: |
|
1278 * identifier is used for previously undeclared identifiers |
|
1279 * any_identifier is used when any identifier, previously |
|
1280 * declared or not, is required in the syntax. |
|
1281 * |
|
1282 * long version: |
|
1283 * When flex comes across an identifier, it first |
|
1284 * searches through the currently declared variables, |
|
1285 * functions, types, etc... to determine if it has |
|
1286 * been previously declared. |
|
1287 * Only if the identifier has not yet been declared |
|
1288 * will it return an identifier_token (later turned into |
|
1289 * an identifier symbol by the bison generated syntax parser). |
|
1290 * |
|
1291 * Some constructs in the syntax, such as when calling |
|
1292 * a function 'F(var1 := 1; var2 := 2);', will accept _any_ |
|
1293 * identifier in 'var1', even if it has been previously |
|
1294 * declared in the current scope, since var1 belongs to |
|
1295 * another scope (the variables declared in function F). |
|
1296 * |
|
1297 * For the above reason, we need to define the symbol |
|
1298 * any_identifier. All the symbols that may become an |
|
1299 * any_identifier are expected to be stored in the |
|
1300 * abstract syntax as a identifier_c |
|
1301 */ |
|
1302 /* NOTE: |
|
1303 * Type names, function names, function block type names and |
|
1304 * program type names are considerd keywords once they are defined, |
|
1305 * so may no longer be used for variable names! |
|
1306 * BUT the spec is confusing on this issue, as it is not clear when |
|
1307 * a function name should be considered as defined. If it is to be |
|
1308 * considered defined only from the location from where it is declared |
|
1309 * and onwards, it means that before it is declared its name may be |
|
1310 * used for variable names! |
|
1311 * This means that we must allow names previously used for functions |
|
1312 * (et. al.) to also constitue an any_identifier! |
|
1313 */ |
|
1314 any_identifier: |
|
1315 identifier |
|
1316 | prev_declared_fb_name |
|
1317 | prev_declared_variable_name |
|
1318 /**/ |
|
1319 | prev_declared_enumerated_type_name |
|
1320 | prev_declared_simple_type_name |
|
1321 | prev_declared_subrange_type_name |
|
1322 | prev_declared_array_type_name |
|
1323 | prev_declared_structure_type_name |
|
1324 | prev_declared_string_type_name |
|
1325 | prev_declared_derived_function_name |
|
1326 | prev_declared_derived_function_block_name |
|
1327 | prev_declared_program_type_name |
|
1328 /**/ |
|
1329 | prev_declared_resource_name |
|
1330 | prev_declared_program_name |
|
1331 | prev_declared_global_var_name |
|
1332 ; |
|
1333 |
|
1334 |
|
1335 |
|
1336 |
|
1337 prev_declared_variable_name: prev_declared_variable_name_token {$$ = new identifier_c($1);}; |
|
1338 prev_declared_fb_name: prev_declared_fb_name_token {$$ = new identifier_c($1);}; |
|
1339 |
|
1340 prev_declared_simple_type_name: prev_declared_simple_type_name_token {$$ = new identifier_c($1);}; |
|
1341 prev_declared_subrange_type_name: prev_declared_subrange_type_name_token {$$ = new identifier_c($1);}; |
|
1342 prev_declared_enumerated_type_name: prev_declared_enumerated_type_name_token {$$ = new identifier_c($1);}; |
|
1343 prev_declared_array_type_name: prev_declared_array_type_name_token {$$ = new identifier_c($1);}; |
|
1344 prev_declared_structure_type_name: prev_declared_structure_type_name_token {$$ = new identifier_c($1);}; |
|
1345 prev_declared_string_type_name: prev_declared_string_type_name_token {$$ = new identifier_c($1);}; |
|
1346 |
|
1347 prev_declared_derived_function_name: prev_declared_derived_function_name_token {$$ = new identifier_c($1);}; |
|
1348 prev_declared_derived_function_block_name: prev_declared_derived_function_block_name_token {$$ = new identifier_c($1);}; |
|
1349 prev_declared_program_type_name: prev_declared_program_type_name_token {$$ = new identifier_c($1);}; |
|
1350 |
|
1351 |
|
1352 |
|
1353 |
|
1354 |
|
1355 /***************************/ |
|
1356 /* B 0 - Programming Model */ |
|
1357 /***************************/ |
|
1358 library: |
|
1359 /* empty */ |
|
1360 {if (tree_root == NULL) |
|
1361 tree_root = new library_c(); |
|
1362 $$ = (list_c *)tree_root; |
|
1363 } |
|
1364 | library library_element_declaration |
|
1365 {$$ = $1; $$->add_element($2);} |
|
1366 | library error |
|
1367 {$$ = NULL; |
|
1368 print_err_msg(current_filename, @2.last_line, "unknown error."); |
|
1369 /* yychar */ |
|
1370 yyerrok; |
|
1371 } |
|
1372 ; |
|
1373 |
|
1374 |
|
1375 library_element_declaration: |
|
1376 data_type_declaration |
|
1377 | function_declaration |
|
1378 | function_block_declaration |
|
1379 | program_declaration |
|
1380 | configuration_declaration |
|
1381 ; |
|
1382 |
|
1383 |
|
1384 |
|
1385 /*******************************************/ |
|
1386 /* B 1.1 - Letters, digits and identifiers */ |
|
1387 /*******************************************/ |
|
1388 /* NOTE: the spec defines identifier as: |
|
1389 * identifier ::= (letter|('_' (letter|digit))) {['_'] (letter|digit)} |
|
1390 * In essence, any sequence of letters or digits, starting with a letter |
|
1391 * or '_'. |
|
1392 * |
|
1393 * On section 2.1.3 (pg 26) , the spec states |
|
1394 * "The keywords listed in annex C shall not be used for any other purpose, |
|
1395 * e.g., variable names or extensions as defined in 1.5.1." |
|
1396 * (NOTE: the spec itself does not follow this rule, as it defines standard |
|
1397 * functions with names identidal to keywords, e.g. 'MOD', 'NOT' !!. This is |
|
1398 * another issue altogether, and is worked around somewhere else...) |
|
1399 * |
|
1400 * This means that we must re-define indentifier so as to exclude |
|
1401 * any keywords defined in annex C. |
|
1402 * |
|
1403 * Note also that the list includes |
|
1404 * - Data type names |
|
1405 * - Function names |
|
1406 * - Function Block names |
|
1407 * This means that any named used for a function name, data type name |
|
1408 * or function block name, essentially becomes a keyword, and may therefore |
|
1409 * no longer be re-used for any other use! (see NOTE 2) |
|
1410 * |
|
1411 * In our case, excluding the keywords is achieved in the lexical parser, |
|
1412 * by two mechanisms: |
|
1413 * (1) giving higher priority to the keywords (tokens) than to identifiers, |
|
1414 * so when the lexical parser finds a keyword it will be parsed as a |
|
1415 * token before being parsed as an identifier. |
|
1416 * (2) when an identifier is found that is not a keyword, the lexical parser |
|
1417 * then looks in the global symbol table, and will not return an identifier |
|
1418 * if the name has been previously used as a data type name, function name, |
|
1419 * or function block name! (In these cases it will return a |
|
1420 * prev_declared_function_name_token, etc...). |
|
1421 * |
|
1422 * Unfortunately, the language (especially IL) uses tokens that are |
|
1423 * not defined as keywords in the spec (e.g. 'IN', 'R1', 'S1', 'PT', etc...)! |
|
1424 * This means that it is valid to name a function 'IN', a variable 'PT', etc... |
|
1425 * BUT, the lexical parser will interpret these names as tokens (keywords). |
|
1426 * To allow these names to be used as function names, variable names, etc..., |
|
1427 * I (Mario) have augmented the definition of identifier to also include the tokens |
|
1428 * that are not explicitly defined as keywords in the spec!! |
|
1429 * |
|
1430 * |
|
1431 * |
|
1432 * |
|
1433 * NOTE 2: |
|
1434 * I (Mario) find it strange that the writers of the spec really want |
|
1435 * names previously used for function names, data type names or function |
|
1436 * block names, to become full fledged keywords. I understand that they |
|
1437 * do not want these names being used as variable names, but how about |
|
1438 * enumeration values? How about structure element names? |
|
1439 * If we interpret the spec literally, these would not be accepted, |
|
1440 * which would probably burden the programmer quite a bit, in making sure |
|
1441 * all these name don't clash! |
|
1442 * |
|
1443 * |
|
1444 * |
|
1445 * NOTE 3: The keywords, as specified in Annex C are... |
|
1446 * |
|
1447 * - Data type names |
|
1448 * - Function names |
|
1449 * - Function Block names |
|
1450 * - ACTION...END_ACTION |
|
1451 * - ARRAY...OF |
|
1452 * - AT |
|
1453 * - CASE...OF...ELSE...END_CASE |
|
1454 * - CONFIGURATION...END_CONFIGURATION |
|
1455 * - CONSTANT |
|
1456 * - EN, ENO |
|
1457 * - EXIT |
|
1458 * - FALSE |
|
1459 * - F_EDGE |
|
1460 * - FOR...TO...BY...DO...END_FOR |
|
1461 * - FUNCTION...END_FUNCTION |
|
1462 * - FUNCTION_BLOCK...END_FUNCTION_BLOCK |
|
1463 * - IF...THEN...ELSIF...ELSE...END_IF |
|
1464 * - INITIAL_STEP...END_STEP |
|
1465 * - NOT, MOD, AND, XOR, OR |
|
1466 * - PROGRAM...WITH... |
|
1467 * - PROGRAM...END_PROGRAM |
|
1468 * - R_EDGE |
|
1469 * - READ_ONLY, READ_WRITE |
|
1470 * - REPEAT...UNTIL...END_REPEAT |
|
1471 * - RESOURCE...ON...END_RESOURCE |
|
1472 * - RETAIN, NON_RETAIN |
|
1473 * - RETURN |
|
1474 * - STEP...END_STEP |
|
1475 * - STRUCT...END_STRUCT |
|
1476 * - TASK |
|
1477 * - TRANSITION...FROM...TO...END_TRANSITION |
|
1478 * - TRUE |
|
1479 * - TYPE...END_TYPE |
|
1480 * - VAR...END_VAR |
|
1481 * - VAR_INPUT...END_VAR |
|
1482 * - VAR_OUTPUT...END_VAR |
|
1483 * - VAR_IN_OUT...END_VAR |
|
1484 * - VAR_TEMP...END_VAR |
|
1485 * - VAR_EXTERNAL...END_VAR |
|
1486 * - VAR_ACCESS...END_VAR |
|
1487 * - VAR_CONFIG...END_VAR |
|
1488 * - VAR_GLOBAL...END_VAR |
|
1489 * - WHILE...DO...END_WHILE |
|
1490 * - WITH |
|
1491 */ |
|
1492 |
|
1493 identifier: |
|
1494 identifier_token {$$ = new identifier_c($1);} |
|
1495 /* Make sure that all tokens (names) not defined as keywords are included here... |
|
1496 * I (Mario) have already done this, but if any changes are made to this file, |
|
1497 * this list MUST be kept consistent!! |
|
1498 */ |
|
1499 /**/ |
|
1500 | PRIORITY {$$ = new identifier_c(strdup("PRIORITY"));} |
|
1501 | SINGLE {$$ = new identifier_c(strdup("SINGLE"));} |
|
1502 | INTERVAL {$$ = new identifier_c(strdup("INTERVAL"));} |
|
1503 /**/ |
|
1504 | LD_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1505 | LDN_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1506 | ST_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1507 | STN_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1508 | S_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1509 | R_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1510 | S1_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1511 | R1_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1512 | CLK_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1513 | CU_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1514 | CD_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1515 | PV_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1516 | IN_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1517 | PT_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1518 | ANDN_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1519 /* NOTE: ANDN2_operator corresponds to the string '&N' in the source code! |
|
1520 * This is __not__ a valid name, so it is omitted from this list!! |
|
1521 *| ANDN2_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1522 */ |
|
1523 /* NOTE: 'AND' is a keyword, so should not appear on this list... */ |
|
1524 | ORN_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1525 | XORN_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1526 | ADD_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1527 | SUB_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1528 | MUL_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1529 | DIV_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1530 | GT_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1531 | GE_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1532 | EQ_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1533 | LT_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1534 | LE_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1535 | NE_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1536 | CAL_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1537 | CALC_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1538 | CALCN_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1539 | RET_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1540 | RETC_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1541 | RETCN_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1542 | JMP_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1543 | JMPC_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1544 | JMPCN_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
1545 /**/ |
|
1546 | L {$$ = new identifier_c(strdup("L"));} |
|
1547 | D {$$ = new identifier_c(strdup("D"));} |
|
1548 | SD {$$ = new identifier_c(strdup("SD"));} |
|
1549 | DS {$$ = new identifier_c(strdup("DS"));} |
|
1550 | SL {$$ = new identifier_c(strdup("SL"));} |
|
1551 | N {$$ = new identifier_c(strdup("N"));} |
|
1552 /* NOTE: the following two clash with the R and S IL operators. |
|
1553 * It will have to be handled when we include parsing of SFC... |
|
1554 */ |
|
1555 /* |
|
1556 | R {$$ = new identifier_c(strdup("R"));} |
|
1557 | S {$$ = new identifier_c(strdup("S"));} |
|
1558 */ |
|
1559 | P {$$ = new identifier_c(strdup("P"));} |
|
1560 |
|
1561 ; |
|
1562 |
|
1563 /*********************/ |
|
1564 /* B 1.2 - Constants */ |
|
1565 /*********************/ |
|
1566 constant: |
|
1567 numeric_literal |
|
1568 | character_string |
|
1569 | time_literal |
|
1570 | bit_string_literal |
|
1571 | boolean_literal |
|
1572 /* NOTE: in order to remove reduce/reduce conflicts, |
|
1573 * unsigned_integer, signed_integer, binary_integer, octal_integer |
|
1574 * and hex_integer have been integrated directly into |
|
1575 * the constants construct, instead of belonging to |
|
1576 * either the bit_string_literal or integer_literal |
|
1577 * construct. |
|
1578 */ |
|
1579 /* NOTE: unsigned_integer, although used in some |
|
1580 * rules, is not defined in the spec! |
|
1581 * We therefore replaced unsigned_integer as integer |
|
1582 */ |
|
1583 /*| integer {} */ /* i.e. an unsigned_integer */ /* NOTE: already included as a signed integer! */ |
|
1584 | signed_integer |
|
1585 | binary_integer |
|
1586 | octal_integer |
|
1587 | hex_integer |
|
1588 ; |
|
1589 |
|
1590 /* a helper symbol for expression */ |
|
1591 /* A constant without any preceding '-', but may |
|
1592 * include a preceding '+' ! |
|
1593 */ |
|
1594 non_negative_constant: |
|
1595 non_negative_numeric_literal |
|
1596 | character_string |
|
1597 | time_literal |
|
1598 | bit_string_literal |
|
1599 | boolean_literal |
|
1600 | non_negative_signed_integer |
|
1601 | binary_integer |
|
1602 | octal_integer |
|
1603 | hex_integer |
|
1604 ; |
|
1605 |
|
1606 |
|
1607 |
|
1608 /******************************/ |
|
1609 /* B 1.2.1 - Numeric Literals */ |
|
1610 /******************************/ |
|
1611 /* NOTES: |
|
1612 * |
|
1613 * - integer is parsed by flex, but signed_integer |
|
1614 * is parsed by bison. Flex cannot parse a signed |
|
1615 * integer correctly! For example: '123+456' |
|
1616 * would be parsed by flex as an {integer} {signed_integer} |
|
1617 * instead of {integer} '+' {integer} |
|
1618 * |
|
1619 * - Neither flex nor bison can parse a real_literal |
|
1620 * completely (and correctly). |
|
1621 * Note that we cannot use the definition of real in bison as |
|
1622 * real: signed_integer '.' integer [exponent] |
|
1623 * exponent: {'E'|'e'} ['+'|'-'] integer |
|
1624 * because 123e45 would be parsed by flex as |
|
1625 * integer (123) identifier (e45). |
|
1626 * I.e., flex never hands over an 'e' directly to |
|
1627 * bison, but rather interprets it as an identifier. |
|
1628 * I guess we could jump through hoops and get it |
|
1629 * working in bison, but the following alternative |
|
1630 * seems more straight forward... |
|
1631 * |
|
1632 * We therefore had to break up the definition of |
|
1633 * real_literal in discrete parts: |
|
1634 * real_literal: [real_type_name '#'] singned_real |
|
1635 * signed_real: ['+'|'-'] real |
|
1636 * Flex handles real, while bison handles signed_real |
|
1637 * and real_literal. |
|
1638 * |
|
1639 * - According to the spec, intger '.' integer |
|
1640 * may be reduced to either a real or a fixed_point. |
|
1641 * It is nevertheless possible to figure out from the |
|
1642 * context which of the two rules should be used in |
|
1643 * the reduction. |
|
1644 * Unfortunately, due to the issue described above |
|
1645 * regarding the exponent of a real, the syntax |
|
1646 * integer '.' integer |
|
1647 * must be parsed by flex as a single token (i.e. |
|
1648 * fixed_point_token). This means we must add fixed_point |
|
1649 * to the definition of real! |
|
1650 * |
|
1651 * - The syntax also uses a construct |
|
1652 * fixed_point: integer ['.' integer] |
|
1653 * Notice that real is not defined based on fixed point, |
|
1654 * but rather off integer thus: |
|
1655 * real: integer '.' integer [exponent] |
|
1656 * This means that a real may not be composed of a single |
|
1657 * integer, unlike the construct fixed_point! |
|
1658 * This also means that a |
|
1659 * integer '.' integer |
|
1660 * could be reduced to either a real or a fixed_point |
|
1661 * construct. It is probably possible to decide by looking |
|
1662 * at the context, BUT: |
|
1663 * Unfortunatley, due to the reasons explained way above, |
|
1664 * a real (with an exponent) has to be handled by flex as a |
|
1665 * whole. This means that we cannot leave to bison (the syntax |
|
1666 * parser) the decision of how to reduce an |
|
1667 * integer '.' integer |
|
1668 * (either to real or to fixed_point) |
|
1669 * The decision on how to reduce it would need to be done by |
|
1670 * ther lexical analyser (i.e. flex). But flex cannot do this |
|
1671 * sort of thing. |
|
1672 * The solution I (Mario) adopted is to have flex return |
|
1673 * a real_token on (notice that exponent is no longer optional) |
|
1674 * integer '.' integer exponent |
|
1675 * and to return a fixed_point_token when it finds |
|
1676 * integer '.' integer |
|
1677 * We now redefine real and fixed_point to be |
|
1678 * fixed_point: fixed_point_token | integer |
|
1679 * real: real_token | fixed_point_token |
|
1680 */ |
|
1681 real: |
|
1682 real_token {$$ = new real_c($1);} |
|
1683 | fixed_point_token {$$ = new real_c($1);} |
|
1684 ; |
|
1685 |
|
1686 integer: integer_token {$$ = new integer_c($1);}; |
|
1687 binary_integer: binary_integer_token {$$ = new binary_integer_c($1);}; |
|
1688 octal_integer: octal_integer_token {$$ = new octal_integer_c($1);}; |
|
1689 hex_integer: hex_integer_token {$$ = new hex_integer_c($1);}; |
|
1690 |
|
1691 numeric_literal: |
|
1692 integer_literal |
|
1693 | real_literal |
|
1694 ; |
|
1695 |
|
1696 /* helper symbol for non_negative_constant */ |
|
1697 non_negative_numeric_literal: |
|
1698 integer_literal |
|
1699 | non_negative_real_literal |
|
1700 ; |
|
1701 |
|
1702 |
|
1703 integer_literal: |
|
1704 integer_type_name '#' signed_integer |
|
1705 {$$ = new integer_literal_c($1, $3);} |
|
1706 | integer_type_name '#' binary_integer |
|
1707 {$$ = new integer_literal_c($1, $3);} |
|
1708 | integer_type_name '#' octal_integer |
|
1709 {$$ = new integer_literal_c($1, $3);} |
|
1710 | integer_type_name '#' hex_integer |
|
1711 {$$ = new integer_literal_c($1, $3);} |
|
1712 /* NOTE: see note in the definition of constant for reason |
|
1713 * why signed_integer, binary_integer, octal_integer |
|
1714 * and hex_integer are missing here! |
|
1715 */ |
|
1716 ; |
|
1717 |
|
1718 signed_integer: |
|
1719 integer |
|
1720 | '+' integer {$$ = $2;} |
|
1721 | '-' integer {$$ = new neg_expression_c($2);} |
|
1722 ; |
|
1723 |
|
1724 /* a helper symbol for non_negative_constant */ |
|
1725 /* A integer without any preceding '-', but may |
|
1726 * include a preceding '+' ! |
|
1727 */ |
|
1728 non_negative_signed_integer: |
|
1729 integer |
|
1730 | '+' integer {$$ = $2;} |
|
1731 ; |
|
1732 |
|
1733 |
|
1734 real_literal: |
|
1735 signed_real |
|
1736 | real_type_name '#' signed_real |
|
1737 {$$ = new real_literal_c($1, $3);} |
|
1738 ; |
|
1739 |
|
1740 /* helper symbol for non_negative_numeric_literal */ |
|
1741 non_negative_real_literal: |
|
1742 non_negative_signed_real |
|
1743 | real_type_name '#' signed_real |
|
1744 {$$ = new real_literal_c($1, $3);} |
|
1745 ; |
|
1746 |
|
1747 signed_real: |
|
1748 real |
|
1749 | '+' real {$$ = $2;} |
|
1750 | '-' real {$$ = new neg_expression_c($2);} |
|
1751 ; |
|
1752 |
|
1753 /* helper symbol for non_negative_real_literal */ |
|
1754 non_negative_signed_real: |
|
1755 real |
|
1756 | '+' real {$$ = $2;} |
|
1757 ; |
|
1758 |
|
1759 |
|
1760 bit_string_literal: |
|
1761 bit_string_type_name '#' integer /* i.e. unsigned_integer */ |
|
1762 {$$ = new bit_string_literal_c($1, $3);} |
|
1763 | bit_string_type_name '#' binary_integer |
|
1764 {$$ = new bit_string_literal_c($1, $3);} |
|
1765 | bit_string_type_name '#' octal_integer |
|
1766 {$$ = new bit_string_literal_c($1, $3);} |
|
1767 | bit_string_type_name '#' hex_integer |
|
1768 {$$ = new bit_string_literal_c($1, $3);} |
|
1769 /* NOTE: see note in the definition of constant for reason |
|
1770 * why unsigned_integer, binary_integer, octal_integer |
|
1771 * and hex_integer are missing here! |
|
1772 */ |
|
1773 /* NOTE: see note under the B 1.2.1 section of token |
|
1774 * and grouping type definition for reason why the use of |
|
1775 * bit_string_type_name, although seemingly incorrect, is |
|
1776 * really correct here! |
|
1777 */ |
|
1778 ; |
|
1779 |
|
1780 |
|
1781 boolean_literal: |
|
1782 TRUE {$$ = new boolean_literal_c(new bool_type_name_c(), |
|
1783 new boolean_true_c());} |
|
1784 | FALSE {$$ = new boolean_literal_c(new bool_type_name_c(), |
|
1785 new boolean_false_c());} |
|
1786 /* |
|
1787 | BOOL '#' '1' {} |
|
1788 | BOOL '#' '0' {} |
|
1789 */ |
|
1790 /* NOTE: the rules |
|
1791 * BOOL '#' '1' |
|
1792 * and |
|
1793 * BOOL '#' '0' |
|
1794 * do not work as expected... |
|
1795 * Consider that we are using 'BOOL' and '#' as tokens |
|
1796 * that flex hands over to bison (yacc). Because flex would |
|
1797 * then parse the single '1' or '0' as an integer, |
|
1798 * the rule in bison would have to be |
|
1799 * BOOL '#' integer, followed by verifying of the |
|
1800 * integer has the correct value! |
|
1801 * |
|
1802 * We therefore have flex return TRUE whenever it |
|
1803 * comes across 'TRUE' or 'BOOL#1', and FALSE whenever |
|
1804 * it comes across 'FALSE' or 'BOOL#0'. |
|
1805 * Note that this means that flex will parse "BOOL#01" |
|
1806 * as FALSE followed by an integer ('1'). |
|
1807 * Bison should detect this as an error, so we should |
|
1808 * be OK. |
|
1809 * |
|
1810 * Another option would be to change the rules to accept |
|
1811 * BOOL '#' integer |
|
1812 * but then check whether the integer has a correct |
|
1813 * value! At the moment I feel that the first option |
|
1814 * is more straight forward. |
|
1815 */ |
|
1816 ; |
|
1817 |
|
1818 |
|
1819 |
|
1820 /*******************************/ |
|
1821 /* B 1.2.2 - Character Strings */ |
|
1822 /*******************************/ |
|
1823 /* Transform the tokens given us by flex into leafs */ |
|
1824 single_byte_character_string: single_byte_character_string_token |
|
1825 {$$ = new single_byte_character_string_c($1);}; |
|
1826 |
|
1827 double_byte_character_string: double_byte_character_string_token |
|
1828 {$$ = new double_byte_character_string_c($1);}; |
|
1829 |
|
1830 |
|
1831 character_string: |
|
1832 single_byte_character_string |
|
1833 | double_byte_character_string |
|
1834 ; |
|
1835 |
|
1836 |
|
1837 |
|
1838 |
|
1839 |
|
1840 /***************************/ |
|
1841 /* B 1.2.3 - Time Literals */ |
|
1842 /***************************/ |
|
1843 time_literal: |
|
1844 time_of_day |
|
1845 | date |
|
1846 | date_and_time |
|
1847 | duration |
|
1848 ; |
|
1849 |
|
1850 |
|
1851 /************************/ |
|
1852 /* B 1.2.3.1 - Duration */ |
|
1853 /************************/ |
|
1854 duration: |
|
1855 /* (T | TIME) '#' ['-'] interval */ |
|
1856 /* NOTE: since TIME is also a data type, it is a keyword |
|
1857 * and may therefore be handled by a token. |
|
1858 * |
|
1859 * Unfortunately T is not a data type, and therefore |
|
1860 * not a keyword. This means that we may have variables named T! |
|
1861 * Flex cannot return the token TIME when it comes across a single T! |
|
1862 * |
|
1863 * We therefore have flex returning the token T_SHARP |
|
1864 * when it comes across 'T#' |
|
1865 */ |
|
1866 TIME '#' interval |
|
1867 {$$ = new duration_c(NULL, $3);} |
|
1868 | TIME '#' '-' interval |
|
1869 {$$ = new duration_c(new neg_time_c(), $4);} |
|
1870 | T_SHARP interval |
|
1871 {$$ = new duration_c(NULL, $2);} |
|
1872 | T_SHARP '-' interval |
|
1873 {$$ = new duration_c(new neg_time_c(), $3);} |
|
1874 ; |
|
1875 |
|
1876 |
|
1877 interval: |
|
1878 days |
|
1879 | hours |
|
1880 | minutes |
|
1881 | seconds |
|
1882 | milliseconds |
|
1883 ; |
|
1884 |
|
1885 integer_d: integer_d_token {$$ = new integer_c($1);}; |
|
1886 integer_h: integer_h_token {$$ = new integer_c($1);}; |
|
1887 integer_m: integer_m_token {$$ = new integer_c($1);}; |
|
1888 integer_s: integer_s_token {$$ = new integer_c($1);}; |
|
1889 integer_ms: integer_ms_token {$$ = new integer_c($1);}; |
|
1890 |
|
1891 fixed_point_d: |
|
1892 fixed_point_d_token |
|
1893 {$$ = new fixed_point_c($1);} |
|
1894 | integer_d |
|
1895 ; |
|
1896 |
|
1897 fixed_point_h: |
|
1898 fixed_point_h_token |
|
1899 {$$ = new fixed_point_c($1);} |
|
1900 | integer_h |
|
1901 ; |
|
1902 |
|
1903 fixed_point_m: |
|
1904 fixed_point_m_token |
|
1905 {$$ = new fixed_point_c($1);} |
|
1906 | integer_m |
|
1907 ; |
|
1908 |
|
1909 fixed_point_s: |
|
1910 fixed_point_s_token |
|
1911 {$$ = new fixed_point_c($1);} |
|
1912 | integer_s |
|
1913 ; |
|
1914 |
|
1915 fixed_point_ms: |
|
1916 fixed_point_ms_token |
|
1917 {$$ = new fixed_point_c($1);} |
|
1918 | integer_ms |
|
1919 ; |
|
1920 |
|
1921 |
|
1922 fixed_point: |
|
1923 fixed_point_token |
|
1924 {$$ = new fixed_point_c($1);} |
|
1925 | integer |
|
1926 ; |
|
1927 |
|
1928 |
|
1929 days: |
|
1930 /* fixed_point ('d') */ |
|
1931 fixed_point_d |
|
1932 {$$ = new days_c($1, NULL);} |
|
1933 /*| integer ('d') ['_'] hours */ |
|
1934 | integer_d hours |
|
1935 {$$ = new days_c($1, $2);} |
|
1936 | integer_d '_' hours |
|
1937 {$$ = new days_c($1, $3);} |
|
1938 ; |
|
1939 |
|
1940 |
|
1941 hours: |
|
1942 /* fixed_point ('h') */ |
|
1943 fixed_point_h |
|
1944 {$$ = new hours_c($1, NULL);} |
|
1945 /*| integer ('h') ['_'] minutes */ |
|
1946 | integer_h minutes |
|
1947 {$$ = new hours_c($1, $2);} |
|
1948 | integer_h '_' minutes |
|
1949 {$$ = new hours_c($1, $3);} |
|
1950 ; |
|
1951 |
|
1952 minutes: |
|
1953 /* fixed_point ('m') */ |
|
1954 fixed_point_m |
|
1955 {$$ = new minutes_c($1, NULL);} |
|
1956 /*| integer ('m') ['_'] seconds */ |
|
1957 | integer_m seconds |
|
1958 {$$ = new minutes_c($1, $2);} |
|
1959 | integer_m '_' seconds |
|
1960 {$$ = new minutes_c($1, $3);} |
|
1961 ; |
|
1962 |
|
1963 seconds: |
|
1964 /* fixed_point ('s') */ |
|
1965 fixed_point_s |
|
1966 {$$ = new seconds_c($1, NULL);} |
|
1967 /*| integer ('s') ['_'] milliseconds */ |
|
1968 | integer_s milliseconds |
|
1969 {$$ = new seconds_c($1, $2);} |
|
1970 | integer_s '_' milliseconds |
|
1971 {$$ = new seconds_c($1, $3);} |
|
1972 ; |
|
1973 |
|
1974 milliseconds: |
|
1975 /* fixed_point ('ms') */ |
|
1976 fixed_point_ms |
|
1977 {$$ = new milliseconds_c($1);} |
|
1978 ; |
|
1979 |
|
1980 |
|
1981 |
|
1982 /************************************/ |
|
1983 /* B 1.2.3.2 - Time of day and Date */ |
|
1984 /************************************/ |
|
1985 time_of_day: |
|
1986 TIME_OF_DAY '#' daytime |
|
1987 {$$ = new time_of_day_c($3);} |
|
1988 ; |
|
1989 |
|
1990 |
|
1991 daytime: |
|
1992 day_hour ':' day_minute ':' day_second |
|
1993 {$$ = new daytime_c($1, $3, $5);} |
|
1994 ; |
|
1995 |
|
1996 |
|
1997 day_hour: integer; |
|
1998 day_minute: integer; |
|
1999 day_second: fixed_point; |
|
2000 |
|
2001 |
|
2002 date: |
|
2003 DATE '#' date_literal |
|
2004 {$$ = new date_c($3);} |
|
2005 | D_SHARP date_literal |
|
2006 {$$ = new date_c($2);} |
|
2007 ; |
|
2008 |
|
2009 |
|
2010 date_literal: |
|
2011 year '-' month '-' day |
|
2012 {$$ = new date_literal_c($1, $3, $5);} |
|
2013 ; |
|
2014 |
|
2015 |
|
2016 year: integer; |
|
2017 month: integer; |
|
2018 day: integer; |
|
2019 |
|
2020 |
|
2021 date_and_time: |
|
2022 DATE_AND_TIME '#' date_literal '-' daytime |
|
2023 {$$ = new date_and_time_c($3, $5);} |
|
2024 ; |
|
2025 |
|
2026 |
|
2027 |
|
2028 |
|
2029 |
|
2030 |
|
2031 /**********************/ |
|
2032 /* B 1.3 - Data Types */ |
|
2033 /**********************/ |
|
2034 /* Strangely, the following symbol does seem to be required! */ |
|
2035 /* |
|
2036 data_type_name: |
|
2037 non_generic_type_name |
|
2038 | generic_type_name |
|
2039 ; |
|
2040 */ |
|
2041 |
|
2042 non_generic_type_name: |
|
2043 elementary_type_name |
|
2044 | derived_type_name |
|
2045 ; |
|
2046 |
|
2047 |
|
2048 |
|
2049 /***********************************/ |
|
2050 /* B 1.3.1 - Elementary Data Types */ |
|
2051 /***********************************/ |
|
2052 elementary_type_name: |
|
2053 numeric_type_name |
|
2054 | date_type_name |
|
2055 | bit_string_type_name |
|
2056 | elementary_string_type_name |
|
2057 | TIME {$$ = new time_type_name_c();} |
|
2058 | BOOL {$$ = new bool_type_name_c();} |
|
2059 /* NOTE: see note under the B 1.2.1 section of token |
|
2060 * and grouping type definition for reason why BOOL |
|
2061 * was added to this definition. |
|
2062 */ |
|
2063 ; |
|
2064 |
|
2065 numeric_type_name: |
|
2066 integer_type_name |
|
2067 | real_type_name |
|
2068 ; |
|
2069 |
|
2070 integer_type_name: |
|
2071 signed_integer_type_name |
|
2072 | unsigned_integer_type_name |
|
2073 ; |
|
2074 |
|
2075 signed_integer_type_name: |
|
2076 SINT {$$ = new sint_type_name_c();} |
|
2077 | INT {$$ = new int_type_name_c();} |
|
2078 | DINT {$$ = new dint_type_name_c();} |
|
2079 | LINT {$$ = new lint_type_name_c();} |
|
2080 ; |
|
2081 |
|
2082 unsigned_integer_type_name: |
|
2083 USINT {$$ = new usint_type_name_c();} |
|
2084 | UINT {$$ = new uint_type_name_c();} |
|
2085 | UDINT {$$ = new udint_type_name_c();} |
|
2086 | ULINT {$$ = new ulint_type_name_c();} |
|
2087 ; |
|
2088 |
|
2089 real_type_name: |
|
2090 REAL {$$ = new real_type_name_c();} |
|
2091 | LREAL {$$ = new lreal_type_name_c();} |
|
2092 ; |
|
2093 |
|
2094 date_type_name: |
|
2095 DATE {$$ = new date_type_name_c();} |
|
2096 | TIME_OF_DAY {$$ = new tod_type_name_c();} |
|
2097 | TOD {$$ = new tod_type_name_c();} |
|
2098 | DATE_AND_TIME {$$ = new dt_type_name_c();} |
|
2099 | DT {$$ = new dt_type_name_c();} |
|
2100 ; |
|
2101 |
|
2102 |
|
2103 bit_string_type_name: |
|
2104 BYTE {$$ = new byte_type_name_c();} |
|
2105 | WORD {$$ = new word_type_name_c();} |
|
2106 | DWORD {$$ = new dword_type_name_c();} |
|
2107 | LWORD {$$ = new lword_type_name_c();} |
|
2108 /* NOTE: see note under the B 1.2.1 section of token |
|
2109 * and grouping type definition for reason why the BOOL |
|
2110 * was omitted from this definition. |
|
2111 */ |
|
2112 ; |
|
2113 |
|
2114 |
|
2115 /* Helper symbol to concentrate the instantiation |
|
2116 * of STRING and WSTRING into a single location. |
|
2117 * |
|
2118 * These two elements show up in several other rules, |
|
2119 * but we want to create the equivalent abstract syntax |
|
2120 * in a single location of this file, in order to make |
|
2121 * possible future changes easier to edit... |
|
2122 */ |
|
2123 elementary_string_type_name: |
|
2124 STRING {$$ = new string_type_name_c();} |
|
2125 | WSTRING {$$ = new wstring_type_name_c();} |
|
2126 ; |
|
2127 |
|
2128 |
|
2129 |
|
2130 /********************************/ |
|
2131 /* B 1.3.2 - Generic data types */ |
|
2132 /********************************/ |
|
2133 /* Strangely, the following symbol does seem to be required! */ |
|
2134 /* |
|
2135 generic_type_name: |
|
2136 ANY |
|
2137 | ANY_DERIVED |
|
2138 | ANY_ELEMENTARY |
|
2139 | ANY_MAGNITUDE |
|
2140 | ANY_NUM |
|
2141 | ANY_REAL |
|
2142 | ANY_INT |
|
2143 | ANY_BIT |
|
2144 | ANY_STRING |
|
2145 | ANY_DATE |
|
2146 ; |
|
2147 */ |
|
2148 |
|
2149 |
|
2150 /********************************/ |
|
2151 /* B 1.3.3 - Derived data types */ |
|
2152 /********************************/ |
|
2153 |
|
2154 derived_type_name: |
|
2155 single_element_type_name |
|
2156 | prev_declared_array_type_name {$$ = $1;} |
|
2157 | prev_declared_structure_type_name {$$ = $1;} |
|
2158 | prev_declared_string_type_name {$$ = $1;} |
|
2159 ; |
|
2160 |
|
2161 single_element_type_name: |
|
2162 prev_declared_simple_type_name {$$ = $1;} |
|
2163 /* Include the following if arrays of function blocks are to be allowed! |
|
2164 * Since the standard does not allow them, |
|
2165 * we leave it commented out for the time being... |
|
2166 */ |
|
2167 //| prev_declared_derived_function_block_name {$$ = $1;} |
|
2168 | prev_declared_subrange_type_name {$$ = $1;} |
|
2169 | prev_declared_enumerated_type_name {$$ = $1;} |
|
2170 ; |
|
2171 |
|
2172 /* NOTE: in order to remove a reduce/reduce conflict, |
|
2173 * all occurences of simple_type_name, etc... |
|
2174 * have been replaced with identifier! |
|
2175 */ |
|
2176 /* |
|
2177 simple_type_name: identifier; |
|
2178 subrange_type_name: identifier; |
|
2179 enumerated_type_name: identifier; |
|
2180 array_type_name: identifier; |
|
2181 structure_type_name: identifier; |
|
2182 */ |
|
2183 |
|
2184 data_type_declaration: |
|
2185 TYPE type_declaration_list END_TYPE |
|
2186 {$$ = new data_type_declaration_c($2);} |
|
2187 ; |
|
2188 |
|
2189 /* helper symbol for data_type_declaration */ |
|
2190 type_declaration_list: |
|
2191 type_declaration ';' |
|
2192 {$$ = new type_declaration_list_c(); $$->add_element($1);} |
|
2193 | type_declaration_list type_declaration ';' |
|
2194 {$$ = $1; $$->add_element($2);} |
|
2195 ; |
|
2196 |
|
2197 type_declaration: |
|
2198 single_element_type_declaration |
|
2199 | array_type_declaration |
|
2200 | structure_type_declaration |
|
2201 | string_type_declaration |
|
2202 ; |
|
2203 |
|
2204 single_element_type_declaration: |
|
2205 simple_type_declaration |
|
2206 | subrange_type_declaration |
|
2207 | enumerated_type_declaration |
|
2208 ; |
|
2209 |
|
2210 simple_type_declaration: |
|
2211 /* simple_type_name ':' simple_spec_init */ |
|
2212 identifier ':' simple_spec_init |
|
2213 {$$ = new simple_type_declaration_c($1, $3); |
|
2214 library_element_symtable.insert($1, prev_declared_simple_type_name_token); |
|
2215 } |
|
2216 ; |
|
2217 |
|
2218 |
|
2219 simple_spec_init: |
|
2220 simple_specification |
|
2221 /* The following line was changed so that we wouldn't |
|
2222 * have the first element of a simple_spec_init_c() |
|
2223 * pointing to another simple_spec_init_c! |
|
2224 */ |
|
2225 /* |
|
2226 | simple_specification ASSIGN constant |
|
2227 {$$ = new simple_spec_init_c($1, $3);} |
|
2228 */ |
|
2229 | elementary_type_name ASSIGN constant |
|
2230 {$$ = new simple_spec_init_c($1, $3);} |
|
2231 | prev_declared_simple_type_name ASSIGN constant |
|
2232 {$$ = new simple_spec_init_c($1, $3);} |
|
2233 ; |
|
2234 |
|
2235 /* When converting to C/C++, we need to know whether |
|
2236 * the elementary_type_name is being used in a variable |
|
2237 * declaration or elsewhere (ex. declaration of a derived |
|
2238 * type), so the abstract syntax has the elementary_type_name |
|
2239 * wrapped inside a simple_spec_init_c. |
|
2240 * The exact same thing occurs with prev_declared_simple_type_name. |
|
2241 * |
|
2242 * This is why in the definition of simple_spec_init, |
|
2243 * simple_specification was brocken up into its |
|
2244 * constituent components... |
|
2245 */ |
|
2246 simple_specification: |
|
2247 // elementary_type_name | simple_type_name |
|
2248 elementary_type_name |
|
2249 {$$ = new simple_spec_init_c($1, NULL);} |
|
2250 | prev_declared_simple_type_name |
|
2251 {$$ = new simple_spec_init_c($1, NULL);} |
|
2252 ; |
|
2253 |
|
2254 |
|
2255 subrange_type_declaration: |
|
2256 /* subrange_type_name ':' subrange_spec_init */ |
|
2257 identifier ':' subrange_spec_init |
|
2258 {$$ = new subrange_type_declaration_c($1, $3); |
|
2259 library_element_symtable.insert($1, prev_declared_subrange_type_name_token); |
|
2260 } |
|
2261 ; |
|
2262 |
|
2263 subrange_spec_init: |
|
2264 subrange_specification |
|
2265 {$$ = new subrange_spec_init_c($1, NULL);} |
|
2266 | subrange_specification ASSIGN signed_integer |
|
2267 {$$ = new subrange_spec_init_c($1, $3);} |
|
2268 ; |
|
2269 |
|
2270 subrange_specification: |
|
2271 integer_type_name '(' subrange')' |
|
2272 {$$ = new subrange_specification_c($1, $3);} |
|
2273 | prev_declared_subrange_type_name {$$ = $1;} |
|
2274 ; |
|
2275 |
|
2276 |
|
2277 subrange: |
|
2278 signed_integer DOTDOT signed_integer |
|
2279 {$$ = new subrange_c($1, $3);} |
|
2280 ; |
|
2281 |
|
2282 enumerated_type_declaration: |
|
2283 /* enumerated_type_name ':' enumerated_spec_init */ |
|
2284 identifier ':' enumerated_spec_init |
|
2285 {$$ = new enumerated_type_declaration_c($1, $3); |
|
2286 library_element_symtable.insert($1, prev_declared_enumerated_type_name_token); |
|
2287 } |
|
2288 ; |
|
2289 |
|
2290 |
|
2291 enumerated_spec_init: |
|
2292 enumerated_specification |
|
2293 {$$ = new enumerated_spec_init_c($1, NULL);} |
|
2294 | enumerated_specification ASSIGN enumerated_value |
|
2295 {$$ = new enumerated_spec_init_c($1, $3);} |
|
2296 ; |
|
2297 |
|
2298 enumerated_specification: |
|
2299 '(' enumerated_value_list ')' |
|
2300 {$$ = $2;} |
|
2301 | prev_declared_enumerated_type_name {$$ = $1;} |
|
2302 ; |
|
2303 |
|
2304 /* helper symbol for enumerated_specification */ |
|
2305 enumerated_value_list: |
|
2306 enumerated_value |
|
2307 {$$ = new enumerated_value_list_c(); $$->add_element($1);} |
|
2308 | enumerated_value_list ',' enumerated_value |
|
2309 {$$ = $1; $$->add_element($3);} |
|
2310 ; |
|
2311 |
|
2312 |
|
2313 enumerated_value: |
|
2314 identifier |
|
2315 {$$ = $1;} |
|
2316 | prev_declared_enumerated_type_name '#' any_identifier |
|
2317 {$$ = new enumerated_value_c($1, $3);} |
|
2318 ; |
|
2319 |
|
2320 |
|
2321 |
|
2322 array_type_declaration: |
|
2323 /* array_type_name ':' array_spec_init */ |
|
2324 identifier ':' array_spec_init |
|
2325 {$$ = new array_type_declaration_c($1, $3); |
|
2326 library_element_symtable.insert($1, prev_declared_array_type_name_token); |
|
2327 } |
|
2328 ; |
|
2329 |
|
2330 array_spec_init: |
|
2331 array_specification |
|
2332 {$$ = new array_spec_init_c($1, NULL);} |
|
2333 | array_specification ASSIGN array_initialization |
|
2334 {$$ = new array_spec_init_c($1, $3);} |
|
2335 ; |
|
2336 |
|
2337 |
|
2338 array_specification: |
|
2339 prev_declared_array_type_name |
|
2340 {$$ = $1;} |
|
2341 | ARRAY '[' array_subrange_list ']' OF non_generic_type_name |
|
2342 {$$ = new array_specification_c($3, $6);} |
|
2343 ; |
|
2344 |
|
2345 /* helper symbol for array_specification */ |
|
2346 array_subrange_list: |
|
2347 subrange |
|
2348 {$$ = new array_subrange_list_c(); $$->add_element($1);} |
|
2349 | array_subrange_list ',' subrange |
|
2350 {$$ = $1; $$->add_element($1);} |
|
2351 ; |
|
2352 |
|
2353 |
|
2354 array_initialization: |
|
2355 '[' array_initial_elements_list ']' |
|
2356 {$$ = $2;} |
|
2357 ; |
|
2358 |
|
2359 |
|
2360 /* helper symbol for array_initialization */ |
|
2361 array_initial_elements_list: |
|
2362 array_initial_elements |
|
2363 {$$ = new array_initial_elements_list_c(); $$->add_element($1);} |
|
2364 | array_initial_elements_list ',' array_initial_elements |
|
2365 {$$ = $1; $$->add_element($3);} |
|
2366 ; |
|
2367 |
|
2368 |
|
2369 array_initial_elements: |
|
2370 array_initial_element |
|
2371 | integer '(' ')' |
|
2372 | integer '(' array_initial_element ')' |
|
2373 {$$ = new array_initial_elements_c($1, $3);} |
|
2374 ; |
|
2375 |
|
2376 |
|
2377 array_initial_element: |
|
2378 constant |
|
2379 | enumerated_value |
|
2380 | structure_initialization |
|
2381 | array_initialization |
|
2382 ; |
|
2383 |
|
2384 |
|
2385 |
|
2386 structure_type_declaration: |
|
2387 /* structure_type_name ':' structure_specification */ |
|
2388 identifier ':' structure_specification |
|
2389 {$$ = new structure_type_declaration_c($1, $3); |
|
2390 library_element_symtable.insert($1, prev_declared_structure_type_name_token); |
|
2391 } |
|
2392 ; |
|
2393 |
|
2394 |
|
2395 structure_specification: |
|
2396 structure_declaration |
|
2397 | initialized_structure |
|
2398 ; |
|
2399 |
|
2400 |
|
2401 initialized_structure: |
|
2402 prev_declared_structure_type_name |
|
2403 {$$ = new initialized_structure_c($1, NULL);} |
|
2404 | prev_declared_structure_type_name ASSIGN structure_initialization |
|
2405 {$$ = new initialized_structure_c($1, $3);} |
|
2406 ; |
|
2407 |
|
2408 |
|
2409 structure_declaration: |
|
2410 STRUCT structure_element_declaration_list END_STRUCT |
|
2411 {$$ = $2;} |
|
2412 ; |
|
2413 |
|
2414 /* helper symbol for structure_declaration */ |
|
2415 structure_element_declaration_list: |
|
2416 structure_element_declaration ';' |
|
2417 {$$ = new structure_element_declaration_list_c(); $$->add_element($1);} |
|
2418 | structure_element_declaration_list structure_element_declaration ';' |
|
2419 {$$ = $1; $$->add_element($2);} |
|
2420 ; |
|
2421 |
|
2422 |
|
2423 structure_element_declaration: |
|
2424 structure_element_name ':' simple_spec_init |
|
2425 {$$ = new structure_element_declaration_c($1, $3);} |
|
2426 | structure_element_name ':' subrange_spec_init |
|
2427 {$$ = new structure_element_declaration_c($1, $3);} |
|
2428 | structure_element_name ':' enumerated_spec_init |
|
2429 {$$ = new structure_element_declaration_c($1, $3);} |
|
2430 | structure_element_name ':' array_spec_init |
|
2431 {$$ = new structure_element_declaration_c($1, $3);} |
|
2432 | structure_element_name ':' initialized_structure |
|
2433 {$$ = new structure_element_declaration_c($1, $3);} |
|
2434 ; |
|
2435 |
|
2436 |
|
2437 structure_element_name: any_identifier; |
|
2438 |
|
2439 |
|
2440 structure_initialization: |
|
2441 '(' structure_element_initialization_list ')' |
|
2442 {$$ = $2;} |
|
2443 ; |
|
2444 |
|
2445 /* helper symbol for structure_initialization */ |
|
2446 structure_element_initialization_list: |
|
2447 structure_element_initialization |
|
2448 {$$ = new structure_element_initialization_list_c(); $$->add_element($1);} |
|
2449 | structure_element_initialization_list ',' structure_element_initialization |
|
2450 {$$ = $1; $$->add_element($3);} |
|
2451 ; |
|
2452 |
|
2453 |
|
2454 structure_element_initialization: |
|
2455 structure_element_name ASSIGN constant |
|
2456 {$$ = new structure_element_initialization_c($1, $3);} |
|
2457 | structure_element_name ASSIGN enumerated_value |
|
2458 {$$ = new structure_element_initialization_c($1, $3);} |
|
2459 | structure_element_name ASSIGN array_initialization |
|
2460 {$$ = new structure_element_initialization_c($1, $3);} |
|
2461 | structure_element_name ASSIGN structure_initialization |
|
2462 {$$ = new structure_element_initialization_c($1, $3);} |
|
2463 ; |
|
2464 |
|
2465 /* NOTE: in order to remove a reduce/reduce conflict, |
|
2466 * all occurences of string_type_name |
|
2467 * have been replaced with identifier! |
|
2468 */ |
|
2469 /* |
|
2470 string_type_name: identifier; |
|
2471 */ |
|
2472 |
|
2473 string_type_declaration: |
|
2474 /* string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */ |
|
2475 identifier ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init |
|
2476 {$$ = new string_type_declaration_c($1, $3, $4, $5); |
|
2477 library_element_symtable.insert($1, prev_declared_string_type_name_token); |
|
2478 } |
|
2479 ; |
|
2480 |
|
2481 |
|
2482 /* helper symbol for string_type_declaration */ |
|
2483 string_type_declaration_size: |
|
2484 '[' integer ']' |
|
2485 {$$ = $2;} |
|
2486 /* REMOVED !! */ |
|
2487 //| /* empty */ |
|
2488 // {$$ = NULL;} |
|
2489 ; |
|
2490 /* The syntax contains a reduce/reduce conflict. |
|
2491 * The optional '[' <size> ']' |
|
2492 * has been changed to become mandatory to remove the conflict. |
|
2493 * |
|
2494 * The conflict arises because |
|
2495 * new_str_type : STRING := "hello!" |
|
2496 * may be reduced to a string_type_declaration OR |
|
2497 * a simple_type_declaration. |
|
2498 * |
|
2499 * Our change forces it to be reduced to a |
|
2500 * simple_type_declaration! |
|
2501 * We chose this option because changing the definition |
|
2502 * of simple_spec_init would force us to change all the other |
|
2503 * rules in which it appears. The change we made has no |
|
2504 * side-effects! |
|
2505 */ |
|
2506 |
|
2507 /* helper symbol for string_type_declaration */ |
|
2508 string_type_declaration_init: |
|
2509 /* empty */ |
|
2510 {$$ = NULL;} |
|
2511 | ASSIGN character_string |
|
2512 {$$ = $2;} |
|
2513 ; |
|
2514 |
|
2515 |
|
2516 |
|
2517 /*********************/ |
|
2518 /* B 1.4 - Variables */ |
|
2519 /*********************/ |
|
2520 variable: |
|
2521 symbolic_variable |
|
2522 | direct_variable |
|
2523 ; |
|
2524 |
|
2525 |
|
2526 symbolic_variable: |
|
2527 /* NOTE: To be entirely correct, variable_name should be replacemed by |
|
2528 * prev_declared_variable_name | prev_declared_fb_name | prev_declared_global_var_name |
|
2529 */ |
|
2530 prev_declared_variable_name |
|
2531 {$$ = new symbolic_variable_c($1);} |
|
2532 | prev_declared_fb_name |
|
2533 {$$ = new symbolic_variable_c($1);} |
|
2534 | prev_declared_global_var_name |
|
2535 {$$ = new symbolic_variable_c($1);} |
|
2536 | multi_element_variable |
|
2537 ; |
|
2538 |
|
2539 |
|
2540 /* NOTE: in section B 1.7, when configuring a program, symbolic_variable |
|
2541 * is used. Nevertheless, during the parsing of a configuration, |
|
2542 * the variables in question are out of scope, so we should |
|
2543 * be allowing any_identifier instead of prev_declared_variable_name! |
|
2544 * |
|
2545 * We therefore need a new any_symbolic_variable construct that |
|
2546 * allows the use of any_identifier instead of previously declared |
|
2547 * variables, function blocks, etc... |
|
2548 */ |
|
2549 any_symbolic_variable: |
|
2550 // variable_name -> replaced by any_identifier |
|
2551 any_identifier |
|
2552 {$$ = new symbolic_variable_c($1);} |
|
2553 | any_multi_element_variable |
|
2554 ; |
|
2555 |
|
2556 |
|
2557 /* for yet undeclared variable names ! */ |
|
2558 variable_name: identifier; |
|
2559 |
|
2560 |
|
2561 |
|
2562 |
|
2563 |
|
2564 /********************************************/ |
|
2565 /* B.1.4.1 Directly Represented Variables */ |
|
2566 /********************************************/ |
|
2567 direct_variable: direct_variable_token {$$ = new direct_variable_c($1);}; |
|
2568 |
|
2569 |
|
2570 |
|
2571 |
|
2572 /*************************************/ |
|
2573 /* B.1.4.2 Multi-element Variables */ |
|
2574 /*************************************/ |
|
2575 multi_element_variable: |
|
2576 array_variable |
|
2577 | structured_variable |
|
2578 ; |
|
2579 |
|
2580 /* please see note above any_symbolic_variable */ |
|
2581 any_multi_element_variable: |
|
2582 any_array_variable |
|
2583 | any_structured_variable |
|
2584 ; |
|
2585 |
|
2586 |
|
2587 array_variable: |
|
2588 subscripted_variable '[' subscript_list ']' |
|
2589 {$$ = new array_variable_c($1, $3);} |
|
2590 ; |
|
2591 |
|
2592 /* please see note above any_symbolic_variable */ |
|
2593 any_array_variable: |
|
2594 any_subscripted_variable '[' subscript_list ']' |
|
2595 {$$ = new array_variable_c($1, $3);} |
|
2596 ; |
|
2597 |
|
2598 |
|
2599 subscripted_variable: |
|
2600 symbolic_variable |
|
2601 ; |
|
2602 |
|
2603 |
|
2604 /* please see note above any_symbolic_variable */ |
|
2605 any_subscripted_variable: |
|
2606 any_symbolic_variable |
|
2607 ; |
|
2608 |
|
2609 |
|
2610 subscript_list: |
|
2611 subscript |
|
2612 {$$ = new subscript_list_c(); $$->add_element($1);} |
|
2613 | subscript_list ',' subscript |
|
2614 {$$ = $1; $$->add_element($3);} |
|
2615 ; |
|
2616 |
|
2617 |
|
2618 subscript: expression; |
|
2619 |
|
2620 |
|
2621 structured_variable: |
|
2622 record_variable '.' field_selector |
|
2623 {$$ = new structured_variable_c($1, $3);} |
|
2624 ; |
|
2625 |
|
2626 |
|
2627 /* please see note above any_symbolic_variable */ |
|
2628 any_structured_variable: |
|
2629 any_record_variable '.' field_selector |
|
2630 {$$ = new structured_variable_c($1, $3);} |
|
2631 ; |
|
2632 |
|
2633 |
|
2634 |
|
2635 record_variable: |
|
2636 symbolic_variable |
|
2637 ; |
|
2638 |
|
2639 |
|
2640 /* please see note above any_symbolic_variable */ |
|
2641 any_record_variable: |
|
2642 any_symbolic_variable |
|
2643 ; |
|
2644 |
|
2645 |
|
2646 field_selector: any_identifier; |
|
2647 |
|
2648 |
|
2649 |
|
2650 |
|
2651 |
|
2652 |
|
2653 /******************************************/ |
|
2654 /* B 1.4.3 - Declaration & Initialisation */ |
|
2655 /******************************************/ |
|
2656 input_declarations: |
|
2657 VAR_INPUT input_declaration_list END_VAR |
|
2658 {$$ = new input_declarations_c(NULL, $2);} |
|
2659 | VAR_INPUT RETAIN input_declaration_list END_VAR |
|
2660 {$$ = new input_declarations_c(new retain_option_c(), $3);} |
|
2661 | VAR_INPUT NON_RETAIN input_declaration_list END_VAR |
|
2662 {$$ = new input_declarations_c(new non_retain_option_c(), $3);} |
|
2663 ; |
|
2664 |
|
2665 /* helper symbol for input_declarations */ |
|
2666 input_declaration_list: |
|
2667 input_declaration ';' |
|
2668 {$$ = new input_declaration_list_c(); $$->add_element($1);} |
|
2669 | input_declaration_list input_declaration ';' |
|
2670 {$$ = $1; $$->add_element($2);} |
|
2671 ; |
|
2672 |
|
2673 |
|
2674 input_declaration: |
|
2675 var_init_decl |
|
2676 | edge_declaration |
|
2677 ; |
|
2678 |
|
2679 |
|
2680 edge_declaration: |
|
2681 var1_list ':' BOOL R_EDGE |
|
2682 {$$ = new edge_declaration_c(new raising_edge_option_c(), $1);} |
|
2683 | var1_list ':' BOOL F_EDGE |
|
2684 {$$ = new edge_declaration_c(new falling_edge_option_c(), $1);} |
|
2685 ; |
|
2686 |
|
2687 |
|
2688 var_init_decl: |
|
2689 var1_init_decl |
|
2690 | array_var_init_decl |
|
2691 | structured_var_init_decl |
|
2692 | fb_name_decl |
|
2693 | string_var_declaration |
|
2694 ; |
|
2695 |
|
2696 |
|
2697 |
|
2698 |
|
2699 var1_init_decl: |
|
2700 var1_list ':' simple_spec_init |
|
2701 {$$ = new var1_init_decl_c($1, $3);} |
|
2702 | var1_list ':' subrange_spec_init |
|
2703 {$$ = new var1_init_decl_c($1, $3);} |
|
2704 | var1_list ':' enumerated_spec_init |
|
2705 {$$ = new var1_init_decl_c($1, $3);} |
|
2706 ; |
|
2707 |
|
2708 |
|
2709 var1_list: |
|
2710 variable_name |
|
2711 {$$ = new var1_list_c(); $$->add_element($1); |
|
2712 variable_name_symtable.insert($1, prev_declared_variable_name_token); |
|
2713 } |
|
2714 | var1_list ',' variable_name |
|
2715 {$$ = $1; $$->add_element($3); |
|
2716 variable_name_symtable.insert($3, prev_declared_variable_name_token); |
|
2717 } |
|
2718 ; |
|
2719 |
|
2720 |
|
2721 |
|
2722 array_var_init_decl: |
|
2723 var1_list ':' array_spec_init |
|
2724 {$$ = new array_var_init_decl_c($1, $3);} |
|
2725 ; |
|
2726 |
|
2727 |
|
2728 structured_var_init_decl: |
|
2729 var1_list ':' initialized_structure |
|
2730 {$$ = new structured_var_init_decl_c($1, $3);} |
|
2731 ; |
|
2732 |
|
2733 |
|
2734 /* NOTE: see notes above fb_name_list and var1_list |
|
2735 * for reason why ':' was removed from this rule! |
|
2736 * In essence, to remove a shift/reduce conflict, |
|
2737 * the ':' was moved to var1_list and fb_name_list! |
|
2738 */ |
|
2739 fb_name_decl: |
|
2740 /* fb_name_list ':' function_block_type_name */ |
|
2741 fb_name_list_with_colon function_block_type_name |
|
2742 {$$ = new fb_name_decl_c($1, $2, NULL);} |
|
2743 /*| fb_name_list ':' function_block_type_name ASSIGN structure_initialization */ |
|
2744 | fb_name_list_with_colon function_block_type_name ASSIGN structure_initialization |
|
2745 {$$ = new fb_name_decl_c($1, $2, $4);} |
|
2746 ; |
|
2747 |
|
2748 |
|
2749 |
|
2750 /* NOTE: In order to remove a reduce/reduce conflict between |
|
2751 * var1_list and fb_name_list, which are identical to each |
|
2752 * other, fb_name_list has been redefined to be a var1_list. |
|
2753 * |
|
2754 * In order to remove a further shift/reduce conflict, var1_list |
|
2755 * is imediately transfomred into var1_list_with_colon |
|
2756 * (i.e. it includes the ':' following the list), which |
|
2757 * means that fb_name_list is built from a |
|
2758 * var1_list_with_colon after all! |
|
2759 */ |
|
2760 /* |
|
2761 fb_name_list: |
|
2762 (* fb_name *) |
|
2763 identifier |
|
2764 {$$ = new fb_name_list_c($1); |
|
2765 variable_name_symtable.insert($1, prev_declared_fb_name_token); |
|
2766 } |
|
2767 (* | fb_name_list ',' fb_name *) |
|
2768 | fb_name_list ',' identifier |
|
2769 {$$ = $1; $$->add_element($3); |
|
2770 variable_name_symtable.insert($3, prev_declared_fb_name_token); |
|
2771 } |
|
2772 ; |
|
2773 */ |
|
2774 |
|
2775 fb_name_list_with_colon: |
|
2776 var1_list_with_colon |
|
2777 {$$ = new fb_name_list_c(); |
|
2778 /* fill up the new fb_name_list_c object with the references |
|
2779 * contained in the var1_list_c object. |
|
2780 */ |
|
2781 FOR_EACH_ELEMENT(elem, $1, {$$->add_element(elem);}); |
|
2782 delete $1; |
|
2783 /* change the tokens associated with the symbols stored in |
|
2784 * the variable name symbol table from prev_declared_variable_name_token |
|
2785 * to prev_declared_fb_name_token |
|
2786 */ |
|
2787 FOR_EACH_ELEMENT(elem, $$, {variable_name_symtable.set(elem, prev_declared_fb_name_token);}); |
|
2788 } |
|
2789 ; |
|
2790 |
|
2791 /* helper symbol for fb_name_list_with_colon */ |
|
2792 var1_list_with_colon: |
|
2793 var1_list ':' |
|
2794 ; |
|
2795 |
|
2796 |
|
2797 // fb_name: identifier; |
|
2798 |
|
2799 |
|
2800 |
|
2801 output_declarations: |
|
2802 VAR_OUTPUT var_init_decl_list END_VAR |
|
2803 {$$ = new output_declarations_c(NULL, $2);} |
|
2804 | VAR_OUTPUT RETAIN var_init_decl_list END_VAR |
|
2805 {$$ = new output_declarations_c(new retain_option_c(), $3);} |
|
2806 | VAR_OUTPUT NON_RETAIN var_init_decl_list END_VAR |
|
2807 {$$ = new output_declarations_c(new non_retain_option_c(), $3);} |
|
2808 ; |
|
2809 |
|
2810 |
|
2811 |
|
2812 input_output_declarations: |
|
2813 VAR_IN_OUT var_declaration_list END_VAR |
|
2814 {$$ = new input_output_declarations_c($2);} |
|
2815 ; |
|
2816 |
|
2817 |
|
2818 |
|
2819 /* helper symbol for input_output_declarations */ |
|
2820 var_declaration_list: |
|
2821 var_declaration ';' |
|
2822 {$$ = new var_declaration_list_c(); $$->add_element($1);} |
|
2823 | var_declaration_list var_declaration ';' |
|
2824 {$$ = $1; $$->add_element($2);} |
|
2825 ; |
|
2826 |
|
2827 |
|
2828 var_declaration: |
|
2829 temp_var_decl |
|
2830 | fb_name_decl |
|
2831 ; |
|
2832 |
|
2833 |
|
2834 temp_var_decl: |
|
2835 var1_declaration |
|
2836 | array_var_declaration |
|
2837 | structured_var_declaration |
|
2838 | string_var_declaration |
|
2839 ; |
|
2840 |
|
2841 var1_declaration: |
|
2842 var1_list ':' simple_specification |
|
2843 {$$ = new var1_init_decl_c($1, $3);} |
|
2844 | var1_list ':' subrange_specification |
|
2845 {$$ = new var1_init_decl_c($1, $3);} |
|
2846 | var1_list ':' enumerated_specification |
|
2847 {$$ = new var1_init_decl_c($1, $3);} |
|
2848 ; |
|
2849 |
|
2850 |
|
2851 |
|
2852 array_var_declaration: |
|
2853 var1_list ':' array_specification |
|
2854 {$$ = new array_var_declaration_c($1, $3);} |
|
2855 ; |
|
2856 |
|
2857 structured_var_declaration: |
|
2858 var1_list ':' prev_declared_structure_type_name |
|
2859 {$$ = new structured_var_declaration_c($1, $3);} |
|
2860 ; |
|
2861 |
|
2862 |
|
2863 var_declarations: |
|
2864 VAR var_init_decl_list END_VAR |
|
2865 {$$ = new var_declarations_c(NULL, $2);} |
|
2866 | VAR CONSTANT var_init_decl_list END_VAR |
|
2867 {$$ = new var_declarations_c(new constant_option_c(), $3);} |
|
2868 ; |
|
2869 |
|
2870 |
|
2871 retentive_var_declarations: |
|
2872 VAR RETAIN var_init_decl_list END_VAR |
|
2873 {$$ = new retentive_var_declarations_c($3);} |
|
2874 ; |
|
2875 |
|
2876 |
|
2877 located_var_declarations: |
|
2878 VAR located_var_decl_list END_VAR |
|
2879 {$$ = new located_var_declarations_c(NULL, $2);} |
|
2880 | VAR CONSTANT located_var_decl_list END_VAR |
|
2881 {$$ = new located_var_declarations_c(new constant_option_c(), $3);} |
|
2882 | VAR RETAIN located_var_decl_list END_VAR |
|
2883 {$$ = new located_var_declarations_c(new retain_option_c(), $3);} |
|
2884 | VAR NON_RETAIN located_var_decl_list END_VAR |
|
2885 {$$ = new located_var_declarations_c(new non_retain_option_c(), $3);} |
|
2886 ; |
|
2887 |
|
2888 |
|
2889 /* helper symbol for located_var_declarations */ |
|
2890 located_var_decl_list: |
|
2891 located_var_decl ';' |
|
2892 {$$ = new located_var_decl_list_c(); $$->add_element($1);} |
|
2893 | located_var_decl_list located_var_decl ';' |
|
2894 {$$ = $1; $$->add_element($2);} |
|
2895 ; |
|
2896 |
|
2897 |
|
2898 located_var_decl: |
|
2899 variable_name location ':' located_var_spec_init |
|
2900 {$$ = new located_var_decl_c($1, $2, $4); |
|
2901 variable_name_symtable.insert($1, prev_declared_variable_name_token); |
|
2902 } |
|
2903 | location ':' located_var_spec_init |
|
2904 {$$ = new located_var_decl_c(NULL, $1, $3);} |
|
2905 ; |
|
2906 |
|
2907 |
|
2908 |
|
2909 |
|
2910 external_var_declarations: |
|
2911 VAR_EXTERNAL external_declaration_list END_VAR |
|
2912 {$$ = new external_var_declarations_c(NULL, $2);} |
|
2913 | VAR_EXTERNAL CONSTANT external_declaration_list END_VAR |
|
2914 {$$ = new external_var_declarations_c(new constant_option_c(), $3);} |
|
2915 ; |
|
2916 |
|
2917 /* helper symbol for external_var_declarations */ |
|
2918 external_declaration_list: |
|
2919 external_declaration ';' |
|
2920 {$$ = new external_declaration_list_c(); $$->add_element($1);} |
|
2921 | external_declaration_list external_declaration';' |
|
2922 {$$ = $1; $$->add_element($2);} |
|
2923 ; |
|
2924 |
|
2925 |
|
2926 external_declaration: |
|
2927 global_var_name ':' simple_specification |
|
2928 {$$ = new external_declaration_c($1, $3); |
|
2929 variable_name_symtable.insert($1, prev_declared_variable_name_token); |
|
2930 } |
|
2931 | global_var_name ':' subrange_specification |
|
2932 {$$ = new external_declaration_c($1, $3); |
|
2933 variable_name_symtable.insert($1, prev_declared_variable_name_token); |
|
2934 } |
|
2935 | global_var_name ':' enumerated_specification |
|
2936 {$$ = new external_declaration_c($1, $3); |
|
2937 variable_name_symtable.insert($1, prev_declared_variable_name_token); |
|
2938 } |
|
2939 | global_var_name ':' array_specification |
|
2940 {$$ = new external_declaration_c($1, $3); |
|
2941 variable_name_symtable.insert($1, prev_declared_variable_name_token); |
|
2942 } |
|
2943 | global_var_name ':' prev_declared_structure_type_name |
|
2944 {$$ = new external_declaration_c($1, $3); |
|
2945 variable_name_symtable.insert($1, prev_declared_variable_name_token); |
|
2946 } |
|
2947 | global_var_name ':' function_block_type_name |
|
2948 {$$ = new external_declaration_c($1, $3); |
|
2949 variable_name_symtable.insert($1, prev_declared_fb_name_token); |
|
2950 } |
|
2951 ; |
|
2952 |
|
2953 |
|
2954 global_var_name: identifier; |
|
2955 |
|
2956 |
|
2957 global_var_declarations: |
|
2958 VAR_GLOBAL global_var_decl_list END_VAR |
|
2959 {$$ = new global_var_declarations_c(NULL, $2);} |
|
2960 | VAR_GLOBAL CONSTANT global_var_decl_list END_VAR |
|
2961 {$$ = new global_var_declarations_c(new constant_option_c(), $3);} |
|
2962 | VAR_GLOBAL RETAIN global_var_decl_list END_VAR |
|
2963 {$$ = new global_var_declarations_c(new retain_option_c(), $3);} |
|
2964 ; |
|
2965 |
|
2966 |
|
2967 /* helper symbol for global_var_declarations */ |
|
2968 global_var_decl_list: |
|
2969 global_var_decl ';' |
|
2970 {$$ = new global_var_decl_list_c(); $$->add_element($1);} |
|
2971 | global_var_decl_list global_var_decl ';' |
|
2972 {$$ = $1; $$->add_element($2);} |
|
2973 ; |
|
2974 |
|
2975 |
|
2976 global_var_decl: |
|
2977 global_var_spec ':' |
|
2978 {$$ = new global_var_decl_c($1, NULL);} |
|
2979 | global_var_spec ':' located_var_spec_init |
|
2980 {$$ = new global_var_decl_c($1, $3);} |
|
2981 | global_var_spec ':' function_block_type_name |
|
2982 {$$ = new global_var_decl_c($1, $3);} |
|
2983 ; |
|
2984 |
|
2985 |
|
2986 global_var_spec: |
|
2987 global_var_list {$$ = $1;} |
|
2988 | location |
|
2989 | global_var_name location |
|
2990 {$$ = new global_var_spec_c($1, $2); |
|
2991 variable_name_symtable.insert($1, prev_declared_global_var_name_token); |
|
2992 } |
|
2993 |
|
2994 ; |
|
2995 |
|
2996 |
|
2997 located_var_spec_init: |
|
2998 simple_spec_init |
|
2999 | subrange_spec_init |
|
3000 | enumerated_spec_init |
|
3001 | array_spec_init |
|
3002 | initialized_structure |
|
3003 | single_byte_string_spec |
|
3004 | double_byte_string_spec |
|
3005 ; |
|
3006 |
|
3007 |
|
3008 location: |
|
3009 AT direct_variable |
|
3010 {$$ = new location_c($2);} |
|
3011 ; |
|
3012 |
|
3013 |
|
3014 |
|
3015 global_var_list: |
|
3016 global_var_name |
|
3017 {$$ = new global_var_list_c(); $$->add_element($1); |
|
3018 variable_name_symtable.insert($1, prev_declared_global_var_name_token); |
|
3019 } |
|
3020 | global_var_list ',' global_var_name |
|
3021 {$$ = $1; $$->add_element($3); |
|
3022 variable_name_symtable.insert($3, prev_declared_global_var_name_token); |
|
3023 } |
|
3024 ; |
|
3025 |
|
3026 |
|
3027 |
|
3028 string_var_declaration: |
|
3029 single_byte_string_var_declaration |
|
3030 | double_byte_string_var_declaration |
|
3031 ; |
|
3032 |
|
3033 single_byte_string_var_declaration: |
|
3034 var1_list ':' single_byte_string_spec |
|
3035 {$$ = new single_byte_string_var_declaration_c($1, $3);} |
|
3036 ; |
|
3037 |
|
3038 /* NOTE: The constructs |
|
3039 * |
|
3040 * [W]STRING |
|
3041 * and |
|
3042 * [W]STRING ASSIGN single_byte_character_string |
|
3043 * |
|
3044 * were removed as they are already contained |
|
3045 * within a other constructs. |
|
3046 * |
|
3047 * single_byte_string_spec is used in: |
|
3048 * - single_byte_string_var_declaration -> |
|
3049 * -> string_var_declaration ---> var_init_decl |
|
3050 * |--> temp_var_decl |
|
3051 * |--> var2_init_decl |
|
3052 * - located_var_spec_init |
|
3053 * |
|
3054 * STRING [ASSIGN string_constant] -> elementary_string_type_name -> |
|
3055 * -> simple_spec -> simple_specification -> simple_spec_init -> |
|
3056 * -> located_var_spec_init |
|
3057 * |
|
3058 * STRING [ASSIGN string_constant] -> elementary_string_type_name -> |
|
3059 * -> simple_spec -> simple_specification -> simple_spec_init -> |
|
3060 * -> var1_init_decl -> var_init_decl |
|
3061 * |
|
3062 * STRING [ASSIGN string_constant] -> elementary_string_type_name -> |
|
3063 * -> simple_spec -> simple_specification -> simple_spec_init -> |
|
3064 * -> var1_init_decl -> var2_init_decl |
|
3065 * |
|
3066 * STRING [ASSIGN string_constant] -> elementary_string_type_name -> |
|
3067 * -> simple_spec -> simple_specification -> |
|
3068 * -> var1_declaration -> temp_var_decl |
|
3069 */ |
|
3070 single_byte_string_spec: |
|
3071 /* STRING |
|
3072 {$$ = new single_byte_string_spec_c(NULL, NULL);} |
|
3073 */ |
|
3074 STRING '[' integer ']' |
|
3075 {$$ = new single_byte_string_spec_c($3, NULL);} |
|
3076 /* |
|
3077 | STRING ASSIGN single_byte_character_string |
|
3078 {$$ = new single_byte_string_spec_c(NULL, $3);} |
|
3079 */ |
|
3080 | STRING '[' integer ']' ASSIGN single_byte_character_string |
|
3081 {$$ = new single_byte_string_spec_c($3, $6);} |
|
3082 ; |
|
3083 |
|
3084 |
|
3085 double_byte_string_var_declaration: |
|
3086 var1_list ':' double_byte_string_spec |
|
3087 {$$ = new double_byte_string_var_declaration_c($1, $3);} |
|
3088 ; |
|
3089 |
|
3090 double_byte_string_spec: |
|
3091 /* WSTRING |
|
3092 {$$ = new double_byte_string_spec_c(NULL, NULL);} |
|
3093 */ |
|
3094 WSTRING '[' integer ']' |
|
3095 {$$ = new double_byte_string_spec_c($3, NULL);} |
|
3096 /* |
|
3097 | WSTRING ASSIGN double_byte_character_string |
|
3098 {$$ = new double_byte_string_spec_c(NULL, $3);} |
|
3099 */ |
|
3100 | WSTRING '[' integer ']' ASSIGN double_byte_character_string |
|
3101 {$$ = new double_byte_string_spec_c($3, $6);} |
|
3102 ; |
|
3103 |
|
3104 |
|
3105 |
|
3106 incompl_located_var_declarations: |
|
3107 VAR incompl_located_var_decl_list END_VAR |
|
3108 {$$ = new incompl_located_var_declarations_c(NULL, $2);} |
|
3109 | VAR RETAIN incompl_located_var_decl_list END_VAR |
|
3110 {$$ = new incompl_located_var_declarations_c(new retain_option_c(), $3);} |
|
3111 | VAR NON_RETAIN incompl_located_var_decl_list END_VAR |
|
3112 {$$ = new incompl_located_var_declarations_c(new non_retain_option_c(), $3);} |
|
3113 ; |
|
3114 |
|
3115 /* helper symbol for incompl_located_var_declarations */ |
|
3116 incompl_located_var_decl_list: |
|
3117 incompl_located_var_decl ';' |
|
3118 {$$ = new incompl_located_var_decl_list_c(); $$->add_element($1);} |
|
3119 | incompl_located_var_decl_list incompl_located_var_decl ';' |
|
3120 {$$ = $1; $$->add_element($2);} |
|
3121 ; |
|
3122 |
|
3123 |
|
3124 incompl_located_var_decl: |
|
3125 variable_name incompl_location ':' var_spec |
|
3126 {$$ = new incompl_located_var_decl_c($1, $2, $4);} |
|
3127 ; |
|
3128 |
|
3129 |
|
3130 incompl_location: |
|
3131 AT incompl_location_token |
|
3132 {$$ = new incompl_location_c($2);} |
|
3133 ; |
|
3134 |
|
3135 |
|
3136 var_spec: |
|
3137 simple_specification |
|
3138 | subrange_specification |
|
3139 | enumerated_specification |
|
3140 | array_specification |
|
3141 | prev_declared_structure_type_name |
|
3142 | string_spec |
|
3143 ; |
|
3144 |
|
3145 |
|
3146 /* helper symbol for var_spec */ |
|
3147 /* NOTE: The constructs |
|
3148 * |
|
3149 * STRING |
|
3150 * and |
|
3151 * WSTRING |
|
3152 * |
|
3153 * were removed as they are already contained |
|
3154 * within a simple_specification. |
|
3155 */ |
|
3156 string_spec: |
|
3157 /* STRING |
|
3158 {$$ = new single_byte_string_spec_c(NULL, NULL);} |
|
3159 */ |
|
3160 STRING '[' integer ']' |
|
3161 {$$ = new single_byte_string_spec_c($3, NULL);} |
|
3162 /* |
|
3163 | WSTRING |
|
3164 {$$ = new double_byte_string_spec_c(NULL, NULL);} |
|
3165 */ |
|
3166 | WSTRING '[' integer ']' |
|
3167 {$$ = new double_byte_string_spec_c($3, NULL);} |
|
3168 ; |
|
3169 |
|
3170 |
|
3171 |
|
3172 |
|
3173 /* intermediate helper symbol for: |
|
3174 * - non_retentive_var_decls |
|
3175 * - output_declarations |
|
3176 * - var_declarations |
|
3177 */ |
|
3178 var_init_decl_list: |
|
3179 var_init_decl ';' |
|
3180 {$$ = new var_init_decl_list_c(); $$->add_element($1);} |
|
3181 | var_init_decl_list var_init_decl ';' |
|
3182 {$$ = $1; $$->add_element($2);} |
|
3183 ; |
|
3184 |
|
3185 |
|
3186 |
|
3187 |
|
3188 /***********************/ |
|
3189 /* B 1.5.1 - Functions */ |
|
3190 /***********************/ |
|
3191 /* The following rules should be set such as: |
|
3192 * function_name: function_name_no_clashes | function_name_simpleop_clashes | function_name_expression_clashes |
|
3193 * function_name: function_name_no_NOT_clashes | function_name_NOT_clashes; |
|
3194 */ |
|
3195 |
|
3196 function_name_no_clashes: prev_declared_derived_function_name | standard_function_name_no_clashes; |
|
3197 function_name_simpleop_clashes: standard_function_name_simpleop_clashes; |
|
3198 //function_name_expression_clashes: standard_function_name_expression_clashes; |
|
3199 |
|
3200 function_name_no_NOT_clashes: prev_declared_derived_function_name | standard_function_name_no_NOT_clashes; |
|
3201 //function_name_NOT_clashes: standard_function_name_NOT_clashes; |
|
3202 |
|
3203 /* |
|
3204 function_name: |
|
3205 prev_declared_derived_function_name |
|
3206 | standard_function_name |
|
3207 ; |
|
3208 */ |
|
3209 |
|
3210 /* NOTE: The list of standard function names |
|
3211 * includes the standard functions MOD(), NOT() |
|
3212 * |
|
3213 * Strangely enough, MOD and NOT are reserved keywords, |
|
3214 * so shouldn't be used for function names. |
|
3215 * |
|
3216 * The specification contradicts itself! |
|
3217 * Our workaround is to treat MOD as a token, |
|
3218 * but to include this token as a |
|
3219 * standard_function_name. |
|
3220 * |
|
3221 * The names of all other standard functions get |
|
3222 * preloaded into the library_element_symbol_table |
|
3223 * with the token value of |
|
3224 * standard_function_name_token |
|
3225 * Actually, simply for completeness, MOD is also |
|
3226 * loaded into the library_element_symbol_table, but |
|
3227 * it is irrelevant since flex will catch MOD as a |
|
3228 * token, before it interprets it as an identifier, |
|
3229 * and looks in the library_element_symbol_table to check |
|
3230 * whether it has been previously declared. |
|
3231 * |
|
3232 * NOTE: The same as the above also occurs with the IL |
|
3233 * operators NOT AND OR XOR ADD SUB MUL DIV MOD |
|
3234 * GT GE EQ LT LE NE. |
|
3235 * Note that MOD is once again in the list! |
|
3236 * Anyway, we give these the same treatement as |
|
3237 * MOD, since we are writing a parser for ST and |
|
3238 * IL simultaneously. If this were not the case, |
|
3239 * the ST parser would not need the tokens NOT AND ... |
|
3240 * |
|
3241 * NOTE: Note that 'NOT' is special, as it conflicts |
|
3242 * with two operators: the IL 'NOT' operator, and |
|
3243 * the unary operator 'NOT' in ST!! |
|
3244 * |
|
3245 * NOTE: The IL language is ambiguous, since using NOT, AND, ... |
|
3246 * may be interpreted as either an IL operator, or |
|
3247 * as a standard function call! |
|
3248 * I (Mario) opted to interpret it as an IL operator. |
|
3249 * This requires changing the syntax for IL language |
|
3250 * function calling, to exclude all function with |
|
3251 * names that clash with IL operators. I therefore |
|
3252 * created the constructs |
|
3253 * function_name_without_clashes |
|
3254 * standard_function_name_without_clashes |
|
3255 * to include all function names, except those that clash |
|
3256 * with IL operators. These constructs are only used |
|
3257 * within the IL language! |
|
3258 */ |
|
3259 /* The following rules should be set such as: |
|
3260 * standard_function_name: standard_function_name_no_clashes | standard_function_name_simpleop_clashes | standard_function_name_expression_clashes |
|
3261 * standard_function_name: standard_function_name_no_NOT_clashes | standard_function_name_NOT_clashes; |
|
3262 */ |
|
3263 |
|
3264 /* |
|
3265 standard_function_name: |
|
3266 standard_function_name_no_clashes |
|
3267 | standard_function_name_expression_clashes |
|
3268 | standard_function_name_NOT_clashes |
|
3269 //| standard_function_name_simpleop_only_clashes |
|
3270 ; |
|
3271 */ |
|
3272 |
|
3273 standard_function_name_no_NOT_clashes: |
|
3274 standard_function_name_no_clashes |
|
3275 | standard_function_name_expression_clashes |
|
3276 //| standard_function_name_simpleop_only_clashes |
|
3277 ; |
|
3278 |
|
3279 standard_function_name_no_clashes: |
|
3280 standard_function_name_token |
|
3281 {$$ = new identifier_c($1);} |
|
3282 ; |
|
3283 |
|
3284 |
|
3285 standard_function_name_simpleop_clashes: |
|
3286 standard_function_name_NOT_clashes |
|
3287 //| standard_function_name_simpleop_only_clashes |
|
3288 ; |
|
3289 |
|
3290 standard_function_name_NOT_clashes: |
|
3291 NOT |
|
3292 {$$ = new identifier_c(strdup("NOT"));} |
|
3293 ; |
|
3294 |
|
3295 /* Add here any other IL simple operators that collide |
|
3296 * with standard function names! |
|
3297 * Don't forget to uncomment the equivalent lines in |
|
3298 * - standard_function_name_simpleop_clashes |
|
3299 * - standard_function_name |
|
3300 * - standard_function_name_no_NOT_clashes |
|
3301 */ |
|
3302 /* |
|
3303 standard_function_name_simpleop_only_clashes: |
|
3304 ; |
|
3305 */ |
|
3306 |
|
3307 standard_function_name_expression_clashes: |
|
3308 AND_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
3309 //NOTE: AND2 (corresponding to the source code string '&') does not clash |
|
3310 // with a standard function name, so should be commented out! |
|
3311 //| AND2_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
3312 | OR_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
3313 | XOR_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
3314 | ADD_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
3315 | SUB_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
3316 | MUL_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
3317 | DIV_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
3318 | MOD_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
3319 | GT_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
3320 | GE_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
3321 | EQ_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
3322 | LT_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
3323 | LE_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
3324 | NE_operator {$$ = il_operator_c_2_identifier_c($1);} |
|
3325 ; |
|
3326 |
|
3327 |
|
3328 derived_function_name: |
|
3329 identifier |
|
3330 | prev_declared_derived_function_name |
|
3331 {$$ = $1; |
|
3332 if (not(allow_function_overloading)) |
|
3333 ERROR; |
|
3334 } |
|
3335 ; |
|
3336 |
|
3337 |
|
3338 function_declaration: |
|
3339 /* FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */ |
|
3340 function_name_declaration ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION |
|
3341 {$$ = new function_declaration_c($1, $3, $4, $5); |
|
3342 variable_name_symtable.pop(); |
|
3343 if (allow_function_overloading) { |
|
3344 switch (library_element_symtable.find_value($1)) { |
|
3345 case prev_declared_derived_function_name_token: |
|
3346 /* do nothing, already in map. */ |
|
3347 break; |
|
3348 case BOGUS_TOKEN_ID: |
|
3349 /* Not yet in map. Must insert...*/ |
|
3350 library_element_symtable.insert($1, prev_declared_derived_function_name_token); |
|
3351 break; |
|
3352 default: |
|
3353 /* Already in map but associated with something else other than a funtion name! */ |
|
3354 ERROR; |
|
3355 } |
|
3356 } else { |
|
3357 library_element_symtable.insert($1, prev_declared_derived_function_name_token); |
|
3358 } |
|
3359 } |
|
3360 /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */ |
|
3361 | function_name_declaration ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION |
|
3362 {$$ = new function_declaration_c($1, $3, $4, $5); |
|
3363 variable_name_symtable.pop(); |
|
3364 if (allow_function_overloading) { |
|
3365 switch (library_element_symtable.find_value($1)) { |
|
3366 case prev_declared_derived_function_name_token: /* do nothing, already in map. */ break; |
|
3367 case BOGUS_TOKEN_ID: library_element_symtable.insert($1, prev_declared_derived_function_name_token); break; |
|
3368 default: ERROR; |
|
3369 } |
|
3370 } else { |
|
3371 library_element_symtable.insert($1, prev_declared_derived_function_name_token); |
|
3372 } |
|
3373 } |
|
3374 ; |
|
3375 |
|
3376 /* helper symbol for function_declaration */ |
|
3377 /* NOTE: due to reduce/reduce conflicts between identifiers |
|
3378 * being reduced to either a variable or an enumerator value, |
|
3379 * we were forced to keep a symbol table of the names |
|
3380 * of all declared variables. Variables are no longer |
|
3381 * created from simple identifier_token, but from |
|
3382 * prev_declared_variable_name_token. |
|
3383 * |
|
3384 * BUT, in functions the function name itself may be used as |
|
3385 * a variable! In order to be able to parse this correctly, |
|
3386 * the token parser (flex) must return a prev_declared_variable_name_token |
|
3387 * when it comes across the function name, while parsing |
|
3388 * the function itself. |
|
3389 * We do this by inserting the function name into the variable |
|
3390 * symbol table, and having flex return a prev_declared_variable_name_token |
|
3391 * whenever it comes across it. |
|
3392 * When we finish parsing the function the variable name |
|
3393 * symbol table is cleared of all entries, and the function |
|
3394 * name is inserted into the library element symbol table. This |
|
3395 * means that from then onwards flex will return a |
|
3396 * derived_function_name_token whenever it comes across the |
|
3397 * function name. |
|
3398 * |
|
3399 * In order to insert the function name into the variable_name |
|
3400 * symbol table BEFORE the function body gets parsed, we |
|
3401 * need the parser to reduce a construct that contains the |
|
3402 * the function name. That is why we created this extra |
|
3403 * construct (function_name_declaration), i.e. to force |
|
3404 * the parser to reduce it, before parsing the function body! |
|
3405 */ |
|
3406 function_name_declaration: |
|
3407 FUNCTION derived_function_name |
|
3408 {$$ = $2; |
|
3409 /* the function name functions as a |
|
3410 * variable within the function itself! |
|
3411 * |
|
3412 * Remember that the variable_name_symtable |
|
3413 * is cleared once the end of the function |
|
3414 * is parsed. |
|
3415 */ |
|
3416 variable_name_symtable.insert($2, prev_declared_variable_name_token); |
|
3417 } |
|
3418 ; |
|
3419 |
|
3420 |
|
3421 |
|
3422 /* intermediate helper symbol for function_declaration */ |
|
3423 io_OR_function_var_declarations_list: |
|
3424 /* empty */ |
|
3425 {$$ = new var_declarations_list_c();} |
|
3426 | io_OR_function_var_declarations_list io_var_declarations |
|
3427 {$$ = $1; $$->add_element($2);} |
|
3428 | io_OR_function_var_declarations_list function_var_decls |
|
3429 {$$ = $1; $$->add_element($2);} |
|
3430 ; |
|
3431 |
|
3432 |
|
3433 io_var_declarations: |
|
3434 input_declarations |
|
3435 | output_declarations |
|
3436 | input_output_declarations |
|
3437 ; |
|
3438 |
|
3439 |
|
3440 function_var_decls: |
|
3441 VAR CONSTANT var2_init_decl_list END_VAR |
|
3442 {$$ = new function_var_decls_c(new constant_option_c(), $3);} |
|
3443 | VAR var2_init_decl_list END_VAR |
|
3444 {$$ = new function_var_decls_c(NULL, $2);} |
|
3445 ; |
|
3446 |
|
3447 /* intermediate helper symbol for function_var_decls */ |
|
3448 var2_init_decl_list: |
|
3449 var2_init_decl ';' |
|
3450 {$$ = new var2_init_decl_list_c(); $$->add_element($1);} |
|
3451 | var2_init_decl_list var2_init_decl ';' |
|
3452 {$$ = $1; $$->add_element($2);} |
|
3453 ; |
|
3454 |
|
3455 |
|
3456 function_body: |
|
3457 statement_list {$$ = $1;} /* if we leave it for the default action we get a type clash! */ |
|
3458 | instruction_list {$$ = $1;} /* if we leave it for the default action we get a type clash! */ |
|
3459 /* |
|
3460 | ladder_diagram |
|
3461 | function_block_diagram |
|
3462 */ |
|
3463 ; |
|
3464 |
|
3465 |
|
3466 var2_init_decl: |
|
3467 var1_init_decl |
|
3468 | array_var_init_decl |
|
3469 | structured_var_init_decl |
|
3470 | string_var_declaration |
|
3471 ; |
|
3472 |
|
3473 |
|
3474 |
|
3475 /*****************************/ |
|
3476 /* B 1.5.2 - Function Blocks */ |
|
3477 /*****************************/ |
|
3478 function_block_type_name: |
|
3479 prev_declared_derived_function_block_name |
|
3480 | standard_function_block_name |
|
3481 ; |
|
3482 |
|
3483 |
|
3484 standard_function_block_name: standard_function_block_name_token {$$ = new identifier_c($1);}; |
|
3485 |
|
3486 derived_function_block_name: identifier; |
|
3487 |
|
3488 |
|
3489 function_block_declaration: |
|
3490 FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations_list function_block_body END_FUNCTION_BLOCK |
|
3491 {$$ = new function_block_declaration_c($2, $3, $4); |
|
3492 library_element_symtable.insert($2, prev_declared_derived_function_block_name_token); |
|
3493 /* Clear the variable_name_symtable. Since |
|
3494 * we have finished parsing the function block, |
|
3495 * the variable names are now out of scope, so |
|
3496 * are no longer valid! |
|
3497 */ |
|
3498 variable_name_symtable.pop(); |
|
3499 } |
|
3500 ; |
|
3501 |
|
3502 |
|
3503 |
|
3504 /* intermediate helper symbol for function_declaration */ |
|
3505 /* { io_var_declarations | other_var_declarations } */ |
|
3506 /* |
|
3507 * NOTE: we re-use the var_declarations_list_c |
|
3508 */ |
|
3509 io_OR_other_var_declarations_list: |
|
3510 /* empty */ |
|
3511 {$$ = new var_declarations_list_c();} |
|
3512 | io_OR_other_var_declarations_list io_var_declarations |
|
3513 {$$ = $1; $$->add_element($2);} |
|
3514 | io_OR_other_var_declarations_list other_var_declarations |
|
3515 {$$ = $1; $$->add_element($2);} |
|
3516 ; |
|
3517 |
|
3518 /* NOTE: |
|
3519 * The IEC specification gives the following definition: |
|
3520 * other_var_declarations ::= |
|
3521 * external_var_declarations |
|
3522 * | var_declarations |
|
3523 * | retentive_var_declarations |
|
3524 * | non_retentive_var_declarations |
|
3525 * | temp_var_decls |
|
3526 * | incompl_located_var_declarations |
|
3527 * |
|
3528 * Nvertheless, the symbol non_retentive_var_declarations |
|
3529 * is not defined in the spec. This seems to me (Mario) |
|
3530 * to be a typo, so non_retentive_var_declarations |
|
3531 * has been replaced with non_retentive_var_decls |
|
3532 * in the following rule! |
|
3533 */ |
|
3534 other_var_declarations: |
|
3535 temp_var_decls |
|
3536 | non_retentive_var_decls |
|
3537 | external_var_declarations |
|
3538 | var_declarations |
|
3539 | retentive_var_declarations |
|
3540 | incompl_located_var_declarations |
|
3541 ; |
|
3542 |
|
3543 |
|
3544 temp_var_decls: |
|
3545 VAR_TEMP temp_var_decls_list END_VAR |
|
3546 {$$ = new temp_var_decls_c($2);} |
|
3547 ; |
|
3548 |
|
3549 |
|
3550 /* intermediate helper symbol for temp_var_decls */ |
|
3551 temp_var_decls_list: |
|
3552 temp_var_decl ';' |
|
3553 {$$ = new temp_var_decls_list_c(); $$->add_element($1);} |
|
3554 | temp_var_decls_list temp_var_decl ';' |
|
3555 {$$ = $1; $$->add_element($2);} |
|
3556 ; |
|
3557 |
|
3558 |
|
3559 non_retentive_var_decls: |
|
3560 VAR NON_RETAIN var_init_decl_list END_VAR |
|
3561 {$$ = new non_retentive_var_decls_c($3);} |
|
3562 ; |
|
3563 |
|
3564 |
|
3565 |
|
3566 function_block_body: |
|
3567 statement_list {$$ = $1;} |
|
3568 | instruction_list {$$ = $1;} |
|
3569 /* |
|
3570 | sequential_function_chart |
|
3571 | ladder_diagram |
|
3572 | function_block_diagram |
|
3573 | <other languages> |
|
3574 */ |
|
3575 ; |
|
3576 |
|
3577 |
|
3578 |
|
3579 |
|
3580 /**********************/ |
|
3581 /* B 1.5.3 - Programs */ |
|
3582 /**********************/ |
|
3583 program_type_name: identifier; |
|
3584 |
|
3585 |
|
3586 program_declaration: |
|
3587 PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM |
|
3588 {$$ = new program_declaration_c($2, $3, $4); |
|
3589 library_element_symtable.insert($2, prev_declared_program_type_name_token); |
|
3590 /* Clear the variable_name_symtable. Since |
|
3591 * we have finished parsing the program declaration, |
|
3592 * the variable names are now out of scope, so |
|
3593 * are no longer valid! |
|
3594 */ |
|
3595 variable_name_symtable.pop(); |
|
3596 } |
|
3597 ; |
|
3598 |
|
3599 |
|
3600 /* helper symbol for program_declaration */ |
|
3601 /* |
|
3602 * NOTE: we re-use the var_declarations_list_c |
|
3603 */ |
|
3604 program_var_declarations_list: |
|
3605 /* empty */ |
|
3606 {$$ = new var_declarations_list_c();} |
|
3607 | program_var_declarations_list io_var_declarations |
|
3608 {$$ = $1; $$->add_element($2);} |
|
3609 | program_var_declarations_list other_var_declarations |
|
3610 {$$ = $1; $$->add_element($2);} |
|
3611 | program_var_declarations_list located_var_declarations |
|
3612 {$$ = $1; $$->add_element($2);} |
|
3613 /* |
|
3614 | program_var_declarations_list program_access_decls |
|
3615 {$$ = $1; $$->add_element($2);} |
|
3616 */ |
|
3617 ; |
|
3618 |
|
3619 |
|
3620 /* TODO ... */ |
|
3621 /* |
|
3622 program_access_decls: |
|
3623 VAR_ACCESS program_access_decl_list END_VAR |
|
3624 ; |
|
3625 */ |
|
3626 |
|
3627 /* helper symbol for program_access_decls */ |
|
3628 /* |
|
3629 program_access_decl_list: |
|
3630 program_access_decl ';' |
|
3631 | program_access_decl_list program_access_decl ';' |
|
3632 ; |
|
3633 */ |
|
3634 |
|
3635 /* |
|
3636 program_access_decl: |
|
3637 access_name ':' symbolic_variable ':' non_generic_type_name |
|
3638 | access_name ':' symbolic_variable ':' non_generic_type_name direction |
|
3639 ; |
|
3640 */ |
|
3641 |
|
3642 |
|
3643 |
|
3644 /********************************************/ |
|
3645 /* B 1.6 Sequential Function Chart elements */ |
|
3646 /********************************************/ |
|
3647 /* TODO ... */ |
|
3648 |
|
3649 /* |
|
3650 sequential_function_chart: |
|
3651 sfc_network |
|
3652 | sequential_function_chart sfc_network |
|
3653 ; |
|
3654 |
|
3655 sfc_network: |
|
3656 initial_step |
|
3657 | sfc_network step |
|
3658 | sfc_network transition |
|
3659 | sfc_network action |
|
3660 ; |
|
3661 |
|
3662 initial_step: |
|
3663 INITIAL_STEP step_name ':' action_association_list END_STEP |
|
3664 ; |
|
3665 |
|
3666 step: |
|
3667 STEP step_name ':' action_association_list END_STEP |
|
3668 ; |
|
3669 |
|
3670 /* helper symbol for: |
|
3671 * - initial_step |
|
3672 * - step |
|
3673 * |
|
3674 action_association_list: |
|
3675 /* empty * |
|
3676 | action_association_list action_association ';' |
|
3677 ; |
|
3678 |
|
3679 step_name: identifier; |
|
3680 |
|
3681 action_association: |
|
3682 action_name '(' action_qualifier indicator_name_list ')' |
|
3683 ; |
|
3684 |
|
3685 /* helper symbol for action_association * |
|
3686 indicator_name_list: |
|
3687 /* empty * |
|
3688 | indicator_name_list ',' indicator_name |
|
3689 ; |
|
3690 |
|
3691 action_name: identifier; |
|
3692 |
|
3693 action_qualifier: |
|
3694 /* empty * |
|
3695 | N |
|
3696 | R |
|
3697 | S |
|
3698 | P |
|
3699 | timed_qualifier ',' action_time |
|
3700 ; |
|
3701 |
|
3702 timed_qualifier: |
|
3703 L |
|
3704 | D |
|
3705 | SD |
|
3706 | DS |
|
3707 | SL |
|
3708 ; |
|
3709 |
|
3710 action_time: |
|
3711 duration |
|
3712 | variable_name |
|
3713 ; |
|
3714 |
|
3715 indicator_name: variable_name; |
|
3716 |
|
3717 transition: |
|
3718 TRANSITION FROM steps TO steps transition_condition END_TRANSITION |
|
3719 | TRANSITION transition_name FROM steps TO steps transition_condition END_TRANSITION |
|
3720 | TRANSITION '(' PRIORITY ASSIGN integer ')' FROM steps TO steps transition_condition END_TRANSITION |
|
3721 | TRANSITION transition_name '(' PRIORITY ASSIGN integer ')' FROM steps TO steps transition_condition END_TRANSITION |
|
3722 ; |
|
3723 |
|
3724 transition_name: identifier; |
|
3725 |
|
3726 steps: |
|
3727 step_name |
|
3728 | '(' step_name_list ')' |
|
3729 ; |
|
3730 |
|
3731 |
|
3732 step_name_list: |
|
3733 step_name ',' step_name |
|
3734 | step_name_list ',' step_name |
|
3735 ; |
|
3736 |
|
3737 |
|
3738 transition_condition: |
|
3739 ':' simple_instruction_list |
|
3740 | ASSIGN expression ';' |
|
3741 | ':' fbd_network |
|
3742 | ':' rung |
|
3743 ; |
|
3744 |
|
3745 action: |
|
3746 ACTION action_name ':' function_block_body END_ACTION |
|
3747 ; |
|
3748 */ |
|
3749 |
|
3750 /********************************/ |
|
3751 /* B 1.7 Configuration elements */ |
|
3752 /********************************/ |
|
3753 /* NOTE: |
|
3754 * It is not clear from reading the specification to which namespace |
|
3755 * the names of resources, tasks and programs belong to. |
|
3756 * |
|
3757 * The following syntax assumes that resource and program names belong to the |
|
3758 * same namespace as the variables defined within |
|
3759 * the resource/configuration (i.e. VAR_GLOBAL). |
|
3760 * Task names belong to a namespace all of their own, since they don't |
|
3761 * produce conflicts in the syntax parser, so we might just as well |
|
3762 * leave them be! ;-) |
|
3763 * The above decision was made taking into |
|
3764 * account that inside a VAR_CONFIG declaration global variables |
|
3765 * may be referenced starting off from the resource name as: |
|
3766 * resource_name.program_name.variable_name |
|
3767 * Notice how resource names and program names are used in a very similar |
|
3768 * manner as are variable names. |
|
3769 * Using a single namespace for all the above mentioned names |
|
3770 * also makes it easier to write the syntax parser!! ;-) Using a private |
|
3771 * namespace for each of the name types (resource names, program names, |
|
3772 * global varaiable names), i.e. letting the names be re-used across |
|
3773 * each of the groups (resource, program, global variables), produces |
|
3774 * reduce/reduce conflicts in the syntax parser. Actually, it is only |
|
3775 * the resource names that need to be distinguished into a |
|
3776 * prev_delcared_resource_name so as not to conflict with [gloabl] variable |
|
3777 * names in the 'data' construct. |
|
3778 * The program names are only tracked to make sure that two programs do not |
|
3779 * get the same name. |
|
3780 * |
|
3781 * Using a single namespace does have the drawback that the user will |
|
3782 * not be able to re-use names for resources or programs if these |
|
3783 * have already been used to name a variable! |
|
3784 * |
|
3785 * If it ever becomes necessary to change this interpretation of |
|
3786 * the syntax, then this section of the syntax parser must be updated! |
|
3787 */ |
|
3788 prev_declared_global_var_name: prev_declared_global_var_name_token {$$ = new identifier_c($1);}; |
|
3789 prev_declared_resource_name: prev_declared_resource_name_token {$$ = new identifier_c($1);}; |
|
3790 prev_declared_program_name: prev_declared_program_name_token {$$ = new identifier_c($1);}; |
|
3791 // prev_declared_task_name: prev_declared_task_name_token {$$ = new identifier_c($1);}; |
|
3792 |
|
3793 |
|
3794 |
|
3795 |
|
3796 |
|
3797 |
|
3798 configuration_name: identifier; |
|
3799 |
|
3800 /* NOTE: The specification states that valid resource type names |
|
3801 * are implementation defined, i.e. each implementaion will define |
|
3802 * what resource types it supports. |
|
3803 * We are implementing this syntax parser to be used by any |
|
3804 * implementation, so at the moment we accept any identifier |
|
3805 * as a resource type name. |
|
3806 * This implementation should probably be changed in the future. We |
|
3807 * should probably have a resource_type_name_token, and let the |
|
3808 * implementation load the global symbol library with the |
|
3809 * accepted resource type names before parsing the code. |
|
3810 * |
|
3811 */ |
|
3812 resource_type_name: any_identifier; |
|
3813 |
|
3814 configuration_declaration: |
|
3815 CONFIGURATION configuration_name |
|
3816 optional_global_var_declarations |
|
3817 single_resource_declaration |
|
3818 {variable_name_symtable.pop();} |
|
3819 optional_access_declarations |
|
3820 optional_instance_specific_initializations |
|
3821 END_CONFIGURATION |
|
3822 {$$ = new configuration_declaration_c($2, $3, $4, $6, $7); |
|
3823 library_element_symtable.insert($2, prev_declared_configuration_name_token); |
|
3824 variable_name_symtable.pop(); |
|
3825 } |
|
3826 | CONFIGURATION configuration_name |
|
3827 optional_global_var_declarations |
|
3828 resource_declaration_list |
|
3829 optional_access_declarations |
|
3830 optional_instance_specific_initializations |
|
3831 END_CONFIGURATION |
|
3832 {$$ = new configuration_declaration_c($2, $3, $4, $5, $6); |
|
3833 library_element_symtable.insert($2, prev_declared_configuration_name_token); |
|
3834 variable_name_symtable.pop(); |
|
3835 } |
|
3836 | CONFIGURATION error END_CONFIGURATION |
|
3837 {$$ = NULL; |
|
3838 print_err_msg(current_filename, @2.last_line, "error in configuration declaration."); |
|
3839 /* yychar */ |
|
3840 yyerrok; |
|
3841 } |
|
3842 ; |
|
3843 |
|
3844 // helper symbol for |
|
3845 // - configuration_declaration |
|
3846 // - resource_declaration |
|
3847 // |
|
3848 optional_global_var_declarations: |
|
3849 // empty |
|
3850 {$$ = NULL;} |
|
3851 | global_var_declarations |
|
3852 ; |
|
3853 |
|
3854 |
|
3855 // helper symbol for configuration_declaration // |
|
3856 optional_access_declarations: |
|
3857 // empty |
|
3858 {$$ = NULL;} |
|
3859 //| access_declarations |
|
3860 ; |
|
3861 |
|
3862 // helper symbol for configuration_declaration // |
|
3863 optional_instance_specific_initializations: |
|
3864 // empty |
|
3865 {$$ = NULL;} |
|
3866 | instance_specific_initializations |
|
3867 ; |
|
3868 |
|
3869 // helper symbol for configuration_declaration // |
|
3870 resource_declaration_list: |
|
3871 resource_declaration |
|
3872 {$$ = new resource_declaration_list_c(); $$->add_element($1);} |
|
3873 | resource_declaration_list resource_declaration |
|
3874 {$$ = $1; $$->add_element($2);} |
|
3875 ; |
|
3876 |
|
3877 |
|
3878 resource_declaration: |
|
3879 RESOURCE {variable_name_symtable.push();} resource_name ON resource_type_name |
|
3880 optional_global_var_declarations |
|
3881 single_resource_declaration |
|
3882 END_RESOURCE |
|
3883 {$$ = new resource_declaration_c($3, $5, $6, $7); |
|
3884 variable_name_symtable.pop(); |
|
3885 variable_name_symtable.insert($3, prev_declared_resource_name_token); |
|
3886 } |
|
3887 ; |
|
3888 |
|
3889 |
|
3890 single_resource_declaration: |
|
3891 task_configuration_list program_configuration_list |
|
3892 {$$ = new single_resource_declaration_c($1, $2);} |
|
3893 ; |
|
3894 |
|
3895 |
|
3896 // helper symbol for single_resource_declaration // |
|
3897 task_configuration_list: |
|
3898 // empty |
|
3899 {$$ = new task_configuration_list_c();} |
|
3900 | task_configuration_list task_configuration ';' |
|
3901 {$$ = $1; $$->add_element($2);} |
|
3902 ; |
|
3903 |
|
3904 |
|
3905 // helper symbol for single_resource_declaration // |
|
3906 program_configuration_list: |
|
3907 program_configuration ';' |
|
3908 {$$ = new program_configuration_list_c(); $$->add_element($1);} |
|
3909 | program_configuration_list program_configuration ';' |
|
3910 {$$ = $1; $$->add_element($2);} |
|
3911 ; |
|
3912 |
|
3913 |
|
3914 resource_name: identifier; |
|
3915 |
|
3916 /* |
|
3917 access_declarations: |
|
3918 VAR_ACCESS access_declaration_list END_VAR |
|
3919 {$$ = NULL;} |
|
3920 ; |
|
3921 |
|
3922 // helper symbol for access_declarations // |
|
3923 access_declaration_list: |
|
3924 access_declaration ';' |
|
3925 | access_declaration_list access_declaration ';' |
|
3926 ; |
|
3927 |
|
3928 |
|
3929 access_declaration: |
|
3930 access_name ':' access_path ':' non_generic_type_name |
|
3931 | access_name ':' access_path ':' non_generic_type_name direction |
|
3932 ; |
|
3933 |
|
3934 |
|
3935 access_path: |
|
3936 direct_variable |
|
3937 | prev_delcared_resource_name '.' direct_variable |
|
3938 | any_fb_name_list symbolic_variable |
|
3939 | prev_delcared_resource_name '.' any_fb_name_list symbolic_variable |
|
3940 | prev_delcared_program_name '.' any_fb_name_list symbolic_variable |
|
3941 | prev_delcared_resource_name '.' prev_delcared_program_name '.' any_fb_name_list symbolic_variable |
|
3942 ; |
|
3943 */ |
|
3944 |
|
3945 // helper symbol for |
|
3946 // - access_path |
|
3947 // - instance_specific_init |
|
3948 // |
|
3949 /* NOTE: The fb_name_list refers to funtion block variables |
|
3950 * that have been declared in a scope outside the one we are |
|
3951 * currently parsing, so we must accept them to be any_identifier! |
|
3952 * |
|
3953 * Beware that other locations of this syntax parser also require |
|
3954 * a fb_name_list. In those locations the function blocks are being declared, |
|
3955 * so only currently un-used identifiers (i.e. identifier) may be accepted. |
|
3956 * |
|
3957 * In order to distinguish the two, here we use any_fb_name_list, while |
|
3958 * in the the locations we simply use fb_name_list! |
|
3959 */ |
|
3960 any_fb_name_list: |
|
3961 // empty |
|
3962 {$$ = new any_fb_name_list_c();} |
|
3963 //| fb_name_list fb_name '.' |
|
3964 | any_fb_name_list any_identifier '.' |
|
3965 {$$ = $1; $$->add_element($2);} |
|
3966 ; |
|
3967 |
|
3968 |
|
3969 |
|
3970 global_var_reference: |
|
3971 // [resource_name '.'] global_var_name ['.' structure_element_name] // |
|
3972 prev_declared_global_var_name |
|
3973 {$$ = new global_var_reference_c(NULL, $1, NULL);} |
|
3974 | prev_declared_global_var_name '.' structure_element_name |
|
3975 {$$ = new global_var_reference_c(NULL, $1, $3);} |
|
3976 | prev_declared_resource_name '.' prev_declared_global_var_name |
|
3977 {$$ = new global_var_reference_c($1, $3, NULL);} |
|
3978 | prev_declared_resource_name '.' prev_declared_global_var_name '.' structure_element_name |
|
3979 {$$ = new global_var_reference_c($1, $3, $5);} |
|
3980 ; |
|
3981 |
|
3982 |
|
3983 //access_name: identifier; |
|
3984 |
|
3985 |
|
3986 program_output_reference: |
|
3987 /* NOTE: |
|
3988 * program_output_reference is merely used within data_source. |
|
3989 * data_source is merely used within task_initialization |
|
3990 * task_initialization appears in a configuration declaration |
|
3991 * _before_ the programs are declared, so we cannot use |
|
3992 * prev_declared_program_name, as what might seem correct at first. |
|
3993 * |
|
3994 * The semantic checker must later check whether the identifier |
|
3995 * used really refers to a program declared after the task |
|
3996 * initialization! |
|
3997 */ |
|
3998 // prev_declared_program_name '.' symbolic_variable |
|
3999 program_name '.' symbolic_variable |
|
4000 {$$ = new program_output_reference_c($1, $3);} |
|
4001 ; |
|
4002 |
|
4003 program_name: identifier; |
|
4004 |
|
4005 /* |
|
4006 direction: |
|
4007 READ_WRITE |
|
4008 {$$ = NULL;} |
|
4009 | READ_ONLY |
|
4010 {$$ = NULL;} |
|
4011 ; |
|
4012 */ |
|
4013 |
|
4014 task_configuration: |
|
4015 TASK task_name task_initialization |
|
4016 {$$ = new task_configuration_c($2, $3);} |
|
4017 ; |
|
4018 |
|
4019 /* NOTE: The specification does nopt mention the namespace to which task names |
|
4020 * should belong to. Unlike resource and program names, for the moment we |
|
4021 * let the task names belong to their own private namespace, as they do not |
|
4022 * produce any conflicts in the syntax parser. |
|
4023 * If in the future our interpretation of the spec. turns out to be incorrect, |
|
4024 * the definition of task_name may have to be changed! |
|
4025 */ |
|
4026 task_name: any_identifier; |
|
4027 |
|
4028 task_initialization: |
|
4029 // '(' [SINGLE ASSIGN data_source ','] [INTERVAL ASSIGN data_source ','] PRIORITY ASSIGN integer ')' // |
|
4030 '(' PRIORITY ASSIGN integer ')' |
|
4031 {$$ = new task_initialization_c(NULL, NULL, $4);} |
|
4032 | '(' SINGLE ASSIGN data_source ',' PRIORITY ASSIGN integer ')' |
|
4033 {$$ = new task_initialization_c($4, NULL, $8);} |
|
4034 | '(' INTERVAL ASSIGN data_source ',' PRIORITY ASSIGN integer ')' |
|
4035 {$$ = new task_initialization_c(NULL, $4, $8);} |
|
4036 | '(' SINGLE ASSIGN data_source ',' INTERVAL ASSIGN data_source ',' PRIORITY ASSIGN integer ')' |
|
4037 {$$ = new task_initialization_c($4, $8, $12);} |
|
4038 ; |
|
4039 |
|
4040 data_source: |
|
4041 constant |
|
4042 | global_var_reference |
|
4043 | program_output_reference |
|
4044 | direct_variable |
|
4045 ; |
|
4046 |
|
4047 program_configuration: |
|
4048 // PROGRAM [RETAIN | NON_RETAIN] program_name [WITH task_name] ':' program_type_name ['(' prog_conf_elements ')'] // |
|
4049 PROGRAM program_name optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements |
|
4050 {$$ = new program_configuration_c(NULL, $2, $3, $5, $6); |
|
4051 variable_name_symtable.insert($2, prev_declared_program_name_token); |
|
4052 } |
|
4053 | PROGRAM RETAIN program_name optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements |
|
4054 {$$ = new program_configuration_c(new retain_option_c(), $3, $4, $6, $7); |
|
4055 variable_name_symtable.insert($3, prev_declared_program_name_token); |
|
4056 } |
|
4057 | PROGRAM NON_RETAIN program_name optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements |
|
4058 {$$ = new program_configuration_c(new non_retain_option_c(), $3, $4, $6, $7); |
|
4059 variable_name_symtable.insert($3, prev_declared_program_name_token); |
|
4060 } |
|
4061 ; |
|
4062 |
|
4063 // helper symbol for program_configuration // |
|
4064 optional_task_name: |
|
4065 // empty // |
|
4066 {$$ = NULL;} |
|
4067 | WITH task_name |
|
4068 {$$ = $2;} |
|
4069 ; |
|
4070 |
|
4071 // helper symbol for program_configuration // |
|
4072 optional_prog_conf_elements: |
|
4073 // empty // |
|
4074 {$$ = NULL;} |
|
4075 | '(' prog_conf_elements ')' |
|
4076 {$$ = $2;} |
|
4077 ; |
|
4078 |
|
4079 |
|
4080 prog_conf_elements: |
|
4081 prog_conf_element |
|
4082 {$$ = new prog_conf_elements_c(); $$->add_element($1);} |
|
4083 | prog_conf_elements ',' prog_conf_element |
|
4084 {$$ = $1; $$->add_element($3);} |
|
4085 ; |
|
4086 |
|
4087 |
|
4088 prog_conf_element: |
|
4089 fb_task |
|
4090 | prog_cnxn |
|
4091 ; |
|
4092 |
|
4093 |
|
4094 fb_task: |
|
4095 // fb_name WITH task_name |
|
4096 /* NOTE: The fb_name refers to funtion block variables |
|
4097 * that have been declared in a scope outside the one we are |
|
4098 * currently parsing, so we must accept them to be any_identifier! |
|
4099 */ |
|
4100 any_identifier WITH task_name |
|
4101 {$$ = new fb_task_c($1, $3);} |
|
4102 ; |
|
4103 |
|
4104 |
|
4105 /* NOTE: |
|
4106 * The semantics of configuring a program are rather confusing, so here is |
|
4107 * my (Mario) understanding on the issue... |
|
4108 * |
|
4109 * A function/program may have as its input variables a simple variable |
|
4110 * (BYTE, WORD, etc...), an array (ARRAY [1 .. 3] OF BYTE, ...) , or a structure. |
|
4111 * Nevertheless, when calling this function from within a st or il language statement |
|
4112 * it is not possible to allocate a value to a single element of the array or structure |
|
4113 * typed input variable, as the accepted syntax is simply '(' variable_name ':=' variable ')' |
|
4114 * Notice how the variable_name does not include things such as 'a.elem1' or 'a[1]'! |
|
4115 * |
|
4116 * Nevertheless, when configuring a program from within a configuration, |
|
4117 * it becomes possible to allocate values to individual elements of the |
|
4118 * array or structured type input variable, as the syntax is now |
|
4119 * '(' symbolic_variable ':=' data_sink|prog_data_source ')' |
|
4120 * Notice how the symbolic_variable _does_ include things such as 'a.elem1' or 'a[1]'! |
|
4121 * |
|
4122 * Conclusion: Unlike other locations in the syntax where SENDTO appears, |
|
4123 * here it is not valid to replace symbolic_variable with any_identifier! |
|
4124 * Nevertheless, it is also not correct to leave symbolic_variable as it is, |
|
4125 * as we have defined it to only include previously declared variables, |
|
4126 * which is not the case in this situation. Here symbolic_variable is refering |
|
4127 * to variables that were defined within the scope of the program that is being |
|
4128 * called, and _not_ within the scope of the configuration that is calling the |
|
4129 * program, so the variables in question are not declared in the current scope! |
|
4130 * |
|
4131 * We therefore need to define a new symbolic_variable, that accepts any_identifier |
|
4132 * instead of previosuly declared variable names, to be used in the definition of |
|
4133 * prog_cnxn! |
|
4134 */ |
|
4135 prog_cnxn: |
|
4136 any_symbolic_variable ASSIGN prog_data_source |
|
4137 {$$ = new prog_cnxn_assign_c($1, $3);} |
|
4138 | any_symbolic_variable SENDTO data_sink |
|
4139 {$$ = new prog_cnxn_sendto_c($1, $3);} |
|
4140 ; |
|
4141 |
|
4142 prog_data_source: |
|
4143 constant |
|
4144 | enumerated_value |
|
4145 | global_var_reference |
|
4146 | direct_variable |
|
4147 ; |
|
4148 |
|
4149 data_sink: |
|
4150 global_var_reference |
|
4151 | direct_variable |
|
4152 ; |
|
4153 |
|
4154 instance_specific_initializations: |
|
4155 VAR_CONFIG instance_specific_init_list END_VAR |
|
4156 {$$ = new instance_specific_initializations_c($2);} |
|
4157 ; |
|
4158 |
|
4159 // helper symbol for instance_specific_initializations // |
|
4160 instance_specific_init_list: |
|
4161 instance_specific_init ';' |
|
4162 {$$ = new instance_specific_init_list_c(); $$->add_element($1);} |
|
4163 | instance_specific_init_list instance_specific_init ';' |
|
4164 {$$ = $1; $$->add_element($2);} |
|
4165 ; |
|
4166 |
|
4167 |
|
4168 instance_specific_init: |
|
4169 // |
|
4170 // resource_name '.' program_name '.' {fb_name '.'} |
|
4171 // ((variable_name [location] ':' located_var_spec_init) | (fb_name ':' function_block_type_name ':=' structure_initialization)) |
|
4172 // |
|
4173 // prev_declared_resource_name '.' prev_declared_program_name '.' any_fb_name_list variable_name ':' located_var_spec_init |
|
4174 /* NOTE: variable_name has been changed to any_identifier (and not simply identifier) because the |
|
4175 * variables being referenced have been declared outside the scope currently being parsed! |
|
4176 */ |
|
4177 /* NOTE: program_name has not been changed to prev_declared_program_name because the |
|
4178 * programs being referenced have been declared outside the scope currently being parsed! |
|
4179 * The programs are only kept inside the scope of the resource in which they are defined. |
|
4180 */ |
|
4181 prev_declared_resource_name '.' program_name '.' any_fb_name_list any_identifier ':' located_var_spec_init |
|
4182 {$$ = new instance_specific_init_c($1, $3, $5, $6, NULL, $8);} |
|
4183 | prev_declared_resource_name '.' program_name '.' any_fb_name_list any_identifier location ':' located_var_spec_init |
|
4184 {$$ = new instance_specific_init_c($1, $3, $5, $6, $7, $9);} |
|
4185 | prev_declared_resource_name '.' program_name '.' any_fb_name_list any_identifier ':' fb_initialization |
|
4186 {$5->add_element($6); $$ = new instance_specific_init_c($1, $3, $5, NULL, NULL, $8);} |
|
4187 ; |
|
4188 |
|
4189 |
|
4190 /* helper symbol for instance_specific_init */ |
|
4191 fb_initialization: |
|
4192 function_block_type_name ASSIGN structure_initialization |
|
4193 {$$ = new fb_initialization_c($1, $3);} |
|
4194 ; |
|
4195 |
|
4196 /***********************************/ |
|
4197 /* B 2.1 Instructions and Operands */ |
|
4198 /***********************************/ |
|
4199 /* helper symbol for many IL instructions, etc... */ |
|
4200 /* eat up any extra EOL tokens... */ |
|
4201 |
|
4202 eol_list: |
|
4203 EOL |
|
4204 | eol_list EOL |
|
4205 ; |
|
4206 |
|
4207 /* |
|
4208 eol_list: |
|
4209 '\n' |
|
4210 | eol_list '\n' |
|
4211 ; |
|
4212 */ |
|
4213 |
|
4214 instruction_list: |
|
4215 il_instruction |
|
4216 {$$ = new instruction_list_c(); $$->add_element($1);} |
|
4217 | instruction_list il_instruction |
|
4218 {$$ = $1; $$->add_element($2);} |
|
4219 | instruction_list pragma |
|
4220 {$$ = $1; $$->add_element($2);} |
|
4221 | instruction_list error |
|
4222 {$$ = $1; |
|
4223 print_err_msg(current_filename, @2.last_line, "error in IL instruction."); |
|
4224 /* yychar */ |
|
4225 yyerrok; |
|
4226 } |
|
4227 ; |
|
4228 |
|
4229 |
|
4230 |
|
4231 il_instruction: |
|
4232 il_incomplete_instruction eol_list |
|
4233 {$$ = new il_instruction_c(NULL, $1);} |
|
4234 | label ':' il_incomplete_instruction eol_list |
|
4235 {$$ = new il_instruction_c($1, $3);} |
|
4236 ; |
|
4237 |
|
4238 |
|
4239 /* helper symbol for il_instruction */ |
|
4240 il_incomplete_instruction: |
|
4241 il_simple_operation |
|
4242 | il_expression |
|
4243 | il_jump_operation |
|
4244 | il_fb_call |
|
4245 | il_formal_funct_call |
|
4246 | il_return_operator |
|
4247 ; |
|
4248 |
|
4249 |
|
4250 label: identifier; |
|
4251 |
|
4252 |
|
4253 |
|
4254 il_simple_operation: |
|
4255 il_simple_operator |
|
4256 {$$ = new il_simple_operation_c($1, NULL);} |
|
4257 | il_simple_operator_noclash il_operand |
|
4258 {$$ = new il_simple_operation_c($1, $2);} |
|
4259 | il_simple_operator_clash_il_operand |
|
4260 {$$ = new il_simple_operation_c($1.first, $1.second);} |
|
4261 /* NOTE: the line |
|
4262 * | il_simple_operator |
|
4263 * already contains the 'NOT' operator, as well as all the |
|
4264 * expression operators ('MOD', 'AND', etc...), all of which |
|
4265 * may also be a function name! This means that these operators/functions, |
|
4266 * without any operands, could be reduced to either an operator or a |
|
4267 * function call. I (Mario) have chosen to reduce it to an operator. |
|
4268 * |
|
4269 * The line |
|
4270 * | function_name |
|
4271 * has been replaced with the lines |
|
4272 * | function_name_no_clashes |
|
4273 * in order to include all possible function names except |
|
4274 * those whose names coincide with operators !! |
|
4275 */ |
|
4276 | function_name_no_clashes |
|
4277 {$$ = new il_function_call_c($1, NULL);} |
|
4278 /* NOTE: the line |
|
4279 * | il_simple_operator il_operand |
|
4280 * already contains the 'NOT', 'MOD', etc. operators, followed by a single il_operand, |
|
4281 * which may also be reduced to a function name with an operand_list of a single |
|
4282 * il_operand! This would lead us to a reduce/reduce conflict! |
|
4283 * |
|
4284 * I (Mario) have chosen to reduce it to an operand, rather than a function call. |
|
4285 * |
|
4286 * The line |
|
4287 * | function_name il_operand_list |
|
4288 * has been replaced with the line |
|
4289 * | function_name_no_clashes il_operand_list |
|
4290 * in order to include all possible function names except |
|
4291 * for the function names which clash with expression and simple operators. |
|
4292 * |
|
4293 * Note that: |
|
4294 * this alternative syntax does not cover the possibility of |
|
4295 * the function 'NOT', 'MOD', etc... being called with more than one il_operand! |
|
4296 * We therefore need to include an extra rule where the |
|
4297 * function_name_expression_clashes and function_name_simpleop_clashes |
|
4298 * are followed by a il_operand_list with __two__ or more il_operands!! |
|
4299 */ |
|
4300 | function_name_no_clashes il_operand_list |
|
4301 {$$ = new il_function_call_c($1, $2);} |
|
4302 | il_simple_operator_clash_il_operand ',' il_operand_list |
|
4303 {list_c *list = new il_operand_list_c(); |
|
4304 list->add_element($1.second); |
|
4305 FOR_EACH_ELEMENT(elem, $3, {list->add_element(elem);}) |
|
4306 $$ = new il_function_call_c(il_operator_c_2_identifier_c($1.first), list); |
|
4307 } |
|
4308 ; |
|
4309 |
|
4310 |
|
4311 |
|
4312 il_simple_operator_clash_il_operand: |
|
4313 il_simple_operator_clash il_operand |
|
4314 {$$.first = $1; $$.second = $2;} |
|
4315 ; |
|
4316 |
|
4317 |
|
4318 |
|
4319 il_expression: |
|
4320 il_expr_operator_noclash '(' eol_list ')' |
|
4321 {$$ = new il_expression_c($1, NULL, NULL);} |
|
4322 | il_expr_operator_noclash '(' il_operand eol_list ')' |
|
4323 {$$ = new il_expression_c($1, $3, NULL);} |
|
4324 | il_expr_operator_noclash '(' eol_list simple_instr_list ')' |
|
4325 {$$ = new il_expression_c($1, NULL, $4);} |
|
4326 | il_expr_operator_noclash '(' il_operand eol_list simple_instr_list ')' |
|
4327 {$$ = new il_expression_c($1, $3, $5);} |
|
4328 /* |
|
4329 */ |
|
4330 | il_expr_operator_clash '(' eol_list ')' |
|
4331 {$$ = new il_expression_c($1, NULL, NULL);} |
|
4332 | il_expr_operator_clash '(' il_operand eol_list ')' |
|
4333 {$$ = new il_expression_c($1, $3, NULL);} |
|
4334 | il_expr_operator_clash '(' il_operand eol_list simple_instr_list ')' |
|
4335 {$$ = new il_expression_c($1, $3, $5);} |
|
4336 /* |
|
4337 */ |
|
4338 | il_expr_operator_clash_eol_list simple_instr_list ')' |
|
4339 {$$ = new il_expression_c($1, NULL, $2);} |
|
4340 ; |
|
4341 |
|
4342 |
|
4343 il_jump_operation: |
|
4344 il_jump_operator label |
|
4345 {$$ = new il_jump_operation_c($1, $2);} |
|
4346 ; |
|
4347 |
|
4348 |
|
4349 il_fb_call: |
|
4350 il_call_operator prev_declared_fb_name |
|
4351 {$$ = new il_fb_call_c($1, $2, NULL, NULL);} |
|
4352 | il_call_operator prev_declared_fb_name '(' ')' |
|
4353 {$$ = new il_fb_call_c($1, $2, NULL, NULL);} |
|
4354 | il_call_operator prev_declared_fb_name '(' eol_list ')' |
|
4355 {$$ = new il_fb_call_c($1, $2, NULL, NULL);} |
|
4356 | il_call_operator prev_declared_fb_name '(' il_operand_list ')' |
|
4357 {$$ = new il_fb_call_c($1, $2, $4, NULL);} |
|
4358 | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')' |
|
4359 {$$ = new il_fb_call_c($1, $2, NULL, $5);} |
|
4360 ; |
|
4361 |
|
4362 |
|
4363 /* NOTE: Please read note above the definition of function_name_without_clashes */ |
|
4364 il_formal_funct_call: |
|
4365 /* function_name '(' eol_list ')' */ |
|
4366 /* NOTE: il_formal_funct_call is only used in the definition of |
|
4367 * - il_incomplete_instruction |
|
4368 * - il_simple_instruction |
|
4369 * In both of the above, il_expression also |
|
4370 * shows up as another option. This means that the functions whose |
|
4371 * names clash with expressions, followed by '(' eol_list ')', are |
|
4372 * already included. We must therefore leave them out in this |
|
4373 * definition in order to remove reduce/reduce conflicts. |
|
4374 * |
|
4375 * In summary: 'MOD' '(' eol_list ')', and all other functions whose |
|
4376 * names clash with expressions may be interpreted by the syntax by |
|
4377 * two different routes. I (Mario) chose to interpret them |
|
4378 * as operators, rather than as function calls! |
|
4379 */ |
|
4380 function_name_no_clashes '(' eol_list ')' |
|
4381 {$$ = new il_formal_funct_call_c($1, NULL);} |
|
4382 | function_name_simpleop_clashes '(' eol_list ')' |
|
4383 {$$ = new il_formal_funct_call_c($1, NULL);} |
|
4384 /* | function_name '(' eol_list il_param_list ')' */ |
|
4385 | function_name_no_clashes '(' eol_list il_param_list ')' |
|
4386 {$$ = new il_formal_funct_call_c($1, $4);} |
|
4387 | function_name_simpleop_clashes '(' eol_list il_param_list ')' |
|
4388 {$$ = new il_formal_funct_call_c($1, $4);} |
|
4389 /* the function_name_expression_clashes had to be first reduced to |
|
4390 * an intermediary symbol in order to remove a reduce/reduce conflict. |
|
4391 * In essence, the syntax requires more than one look ahead token |
|
4392 * in order to be parsed. We resolve this by reducing a collection of |
|
4393 * symbols into a temporary symbol (il_expr_operator_clash_eol_list), that |
|
4394 * will later be replaced by the correct symbol. The correct symbol will |
|
4395 * now be determined by a single look ahead token, as all the common |
|
4396 * symbols have been reduced to the temporary symbol |
|
4397 * il_expr_operator_clash_eol_list ! |
|
4398 * |
|
4399 * Unfortunately, this work around results in the wrong symbol |
|
4400 * being created for the abstract syntax tree. |
|
4401 * We need to figure out which symbol was created, destroy it, |
|
4402 * and create the correct symbol for our case. |
|
4403 * This is a lot of work, so I put it in a function |
|
4404 * at the end of this file... il_operator_c_2_identifier_c() |
|
4405 */ |
|
4406 | il_expr_operator_clash_eol_list il_param_list ')' |
|
4407 {$$ = new il_formal_funct_call_c(il_operator_c_2_identifier_c($1), $2);} |
|
4408 ; |
|
4409 |
|
4410 |
|
4411 il_expr_operator_clash_eol_list: |
|
4412 il_expr_operator_clash '(' eol_list |
|
4413 {$$ = $1;} |
|
4414 ; |
|
4415 |
|
4416 |
|
4417 il_operand: |
|
4418 variable |
|
4419 | enumerated_value |
|
4420 | constant |
|
4421 ; |
|
4422 |
|
4423 |
|
4424 il_operand_list: |
|
4425 il_operand |
|
4426 {$$ = new il_operand_list_c(); $$->add_element($1);} |
|
4427 | il_operand_list ',' il_operand |
|
4428 {$$ = $1; $$->add_element($3);} |
|
4429 ; |
|
4430 |
|
4431 |
|
4432 simple_instr_list: |
|
4433 il_simple_instruction |
|
4434 {$$ = new simple_instr_list_c(); $$->add_element($1);} |
|
4435 | simple_instr_list il_simple_instruction |
|
4436 {$$ = $1; $$->add_element($2);} |
|
4437 ; |
|
4438 |
|
4439 |
|
4440 il_simple_instruction: |
|
4441 il_simple_operation eol_list |
|
4442 | il_expression eol_list |
|
4443 | il_formal_funct_call eol_list |
|
4444 ; |
|
4445 |
|
4446 |
|
4447 /* NOTE: the correct definition of il_param_list is |
|
4448 * il_param_list ::= {il_param_instruction} il_param_last_instruction |
|
4449 * |
|
4450 * where {...} denotes zero or many il_param_instruction's. |
|
4451 * |
|
4452 * We could do this by defining the following: |
|
4453 * il_param_list: il_param_instruction_list il_param_last_instruction; |
|
4454 * il_param_instruction_list : ** empty ** | il_param_instruction_list il_param_instruction; |
|
4455 * |
|
4456 * Unfortunately, the above leads to reduce/reduce conflicts. |
|
4457 * The chosen alternative (as follows) does not have any conflicts! |
|
4458 * il_param_list: il_param_last_instruction | il_param_instruction_list il_param_last_instruction; |
|
4459 * il_param_instruction_list : il_param_instruction_list | il_param_instruction_list il_param_instruction; |
|
4460 */ |
|
4461 il_param_list: |
|
4462 il_param_instruction_list il_param_last_instruction |
|
4463 {$$ = $1; $$->add_element($2);} |
|
4464 | il_param_last_instruction |
|
4465 {$$ = new il_param_list_c(); $$->add_element($1);} |
|
4466 ; |
|
4467 |
|
4468 |
|
4469 /* Helper symbol for il_param_list */ |
|
4470 il_param_instruction_list: |
|
4471 il_param_instruction |
|
4472 {$$ = new il_param_list_c(); $$->add_element($1);} |
|
4473 | il_param_instruction_list il_param_instruction |
|
4474 {$$ = $1; $$->add_element($2);} |
|
4475 ; |
|
4476 |
|
4477 |
|
4478 il_param_instruction: |
|
4479 il_param_assignment ',' eol_list |
|
4480 | il_param_out_assignment ',' eol_list |
|
4481 ; |
|
4482 |
|
4483 |
|
4484 il_param_last_instruction: |
|
4485 il_param_assignment eol_list |
|
4486 | il_param_out_assignment eol_list |
|
4487 ; |
|
4488 |
|
4489 |
|
4490 il_param_assignment: |
|
4491 il_assign_operator il_operand |
|
4492 {$$ = new il_param_assignment_c($1, $2, NULL);} |
|
4493 | il_assign_operator '(' eol_list simple_instr_list ')' |
|
4494 {$$ = new il_param_assignment_c($1, NULL, $4);} |
|
4495 ; |
|
4496 |
|
4497 |
|
4498 il_param_out_assignment: |
|
4499 il_assign_out_operator variable |
|
4500 {$$ = new il_param_out_assignment_c($1, $2);} |
|
4501 ; |
|
4502 |
|
4503 |
|
4504 |
|
4505 /*******************/ |
|
4506 /* B 2.2 Operators */ |
|
4507 /*******************/ |
|
4508 sendto_identifier: sendto_identifier_token {$$ = new identifier_c($1);}; |
|
4509 |
|
4510 |
|
4511 /* NOTE: |
|
4512 * The spec includes the operator 'EQ ' |
|
4513 * Note that EQ is followed by a space. |
|
4514 * I am considering this a typo, and defining the operator |
|
4515 * as 'EQ' |
|
4516 * (Mario) |
|
4517 */ |
|
4518 LD_operator: LD {$$ = new LD_operator_c();}; |
|
4519 LDN_operator: LDN {$$ = new LDN_operator_c();}; |
|
4520 ST_operator: ST {$$ = new ST_operator_c();}; |
|
4521 STN_operator: STN {$$ = new STN_operator_c();}; |
|
4522 NOT_operator: NOT {$$ = new NOT_operator_c();}; |
|
4523 S_operator: S {$$ = new S_operator_c();}; |
|
4524 R_operator: R {$$ = new R_operator_c();}; |
|
4525 S1_operator: S1 {$$ = new S1_operator_c();}; |
|
4526 R1_operator: R1 {$$ = new R1_operator_c();}; |
|
4527 CLK_operator: CLK {$$ = new CLK_operator_c();}; |
|
4528 CU_operator: CU {$$ = new CU_operator_c();}; |
|
4529 CD_operator: CD {$$ = new CD_operator_c();}; |
|
4530 PV_operator: PV {$$ = new PV_operator_c();}; |
|
4531 IN_operator: IN {$$ = new IN_operator_c();}; |
|
4532 PT_operator: PT {$$ = new PT_operator_c();}; |
|
4533 AND_operator: AND {$$ = new AND_operator_c();}; |
|
4534 AND2_operator: AND2 {$$ = new AND_operator_c();}; /* '&' in the source code! */ |
|
4535 OR_operator: OR {$$ = new OR_operator_c();}; |
|
4536 XOR_operator: XOR {$$ = new XOR_operator_c();}; |
|
4537 ANDN_operator: ANDN {$$ = new ANDN_operator_c();}; |
|
4538 ANDN2_operator: ANDN2 {$$ = new ANDN_operator_c();}; /* '&N' in the source code! */ |
|
4539 ORN_operator: ORN {$$ = new ORN_operator_c();}; |
|
4540 XORN_operator: XORN {$$ = new XORN_operator_c();}; |
|
4541 ADD_operator: ADD {$$ = new ADD_operator_c();}; |
|
4542 SUB_operator: SUB {$$ = new SUB_operator_c();}; |
|
4543 MUL_operator: MUL {$$ = new MUL_operator_c();}; |
|
4544 DIV_operator: DIV {$$ = new DIV_operator_c();}; |
|
4545 MOD_operator: MOD {$$ = new MOD_operator_c();}; |
|
4546 GT_operator: GT {$$ = new GT_operator_c();}; |
|
4547 GE_operator: GE {$$ = new GE_operator_c();}; |
|
4548 EQ_operator: EQ {$$ = new EQ_operator_c();}; |
|
4549 LT_operator: LT {$$ = new LT_operator_c();}; |
|
4550 LE_operator: LE {$$ = new LE_operator_c();}; |
|
4551 NE_operator: NE {$$ = new NE_operator_c();}; |
|
4552 CAL_operator: CAL {$$ = new CAL_operator_c();}; |
|
4553 CALC_operator: CALC {$$ = new CALC_operator_c();}; |
|
4554 CALCN_operator: CALCN {$$ = new CALCN_operator_c();}; |
|
4555 RET_operator: RET {$$ = new RET_operator_c();}; |
|
4556 RETC_operator: RETC {$$ = new RETC_operator_c();}; |
|
4557 RETCN_operator: RETCN {$$ = new RETCN_operator_c();}; |
|
4558 JMP_operator: JMP {$$ = new JMP_operator_c();}; |
|
4559 JMPC_operator: JMPC {$$ = new JMPC_operator_c();}; |
|
4560 JMPCN_operator: JMPCN {$$ = new JMPCN_operator_c();}; |
|
4561 |
|
4562 /* |
|
4563 MAY CONFLICT WITH STANDARD FUNCTION NAMES!!! |
|
4564 |
|
4565 NOT_operator: NOT {new NOT_operator_c();}; |
|
4566 |
|
4567 AND_operator: AND {new AND_operator_c();}; |
|
4568 OR_operator: OR {new OR_operator_c();}; |
|
4569 XOR_operator: XOR {new XOR_operator_c();}; |
|
4570 |
|
4571 ADD_operator: ADD {new ADD_operator_c();}; |
|
4572 SUB_operator: SUB {new SUB_operator_c();}; |
|
4573 MUL_operator: MUL {new MUL_operator_c();}; |
|
4574 DIV_operator: DIV {new DIV_operator_c();}; |
|
4575 MOD_operator: MOD {new MOD_operator_c();}; |
|
4576 |
|
4577 GT_operator: GT {new GT_operator_c();}; |
|
4578 GE_operator: GE {new GE_operator_c();}; |
|
4579 EQ_operator: EQ {new EQ_operator_c();}; |
|
4580 LT_operator: LT {new LT_operator_c();}; |
|
4581 LE_operator: LE {new LE_operator_c();}; |
|
4582 NE_operator: NE {new NE_operator_c();}; |
|
4583 */ |
|
4584 |
|
4585 |
|
4586 il_simple_operator: |
|
4587 il_simple_operator_clash |
|
4588 | il_simple_operator_noclash |
|
4589 ; |
|
4590 |
|
4591 |
|
4592 il_simple_operator_noclash: |
|
4593 LD_operator |
|
4594 | LDN_operator |
|
4595 | ST_operator |
|
4596 | STN_operator |
|
4597 | S_operator |
|
4598 | R_operator |
|
4599 | S1_operator |
|
4600 | R1_operator |
|
4601 | CLK_operator |
|
4602 | CU_operator |
|
4603 | CD_operator |
|
4604 | PV_operator |
|
4605 | IN_operator |
|
4606 | PT_operator |
|
4607 | il_expr_operator_noclash |
|
4608 ; |
|
4609 |
|
4610 |
|
4611 il_simple_operator_clash: |
|
4612 il_simple_operator_clash1 |
|
4613 | il_simple_operator_clash2 |
|
4614 ; |
|
4615 |
|
4616 il_simple_operator_clash1: |
|
4617 NOT_operator |
|
4618 ; |
|
4619 |
|
4620 il_simple_operator_clash2: |
|
4621 il_expr_operator_clash |
|
4622 ; |
|
4623 |
|
4624 |
|
4625 /* |
|
4626 il_expr_operator: |
|
4627 il_expr_operator_noclash |
|
4628 | il_expr_operator_clash |
|
4629 ; |
|
4630 */ |
|
4631 |
|
4632 il_expr_operator_clash: |
|
4633 AND_operator |
|
4634 | OR_operator |
|
4635 | XOR_operator |
|
4636 | ADD_operator |
|
4637 | SUB_operator |
|
4638 | MUL_operator |
|
4639 | DIV_operator |
|
4640 | MOD_operator |
|
4641 | GT_operator |
|
4642 | GE_operator |
|
4643 | EQ_operator |
|
4644 | LT_operator |
|
4645 | LE_operator |
|
4646 | NE_operator |
|
4647 ; |
|
4648 |
|
4649 |
|
4650 il_expr_operator_noclash: |
|
4651 ANDN_operator |
|
4652 | ANDN2_operator /* string '&N' in source code! */ |
|
4653 | AND2_operator /* string '&' in source code! */ |
|
4654 | ORN_operator |
|
4655 | XORN_operator |
|
4656 ; |
|
4657 |
|
4658 |
|
4659 |
|
4660 |
|
4661 il_assign_operator: |
|
4662 /* variable_name ASSIGN */ |
|
4663 any_identifier ASSIGN |
|
4664 ; |
|
4665 |
|
4666 |
|
4667 il_assign_out_operator: |
|
4668 /* variable_name SENDTO */ |
|
4669 /* any_identifier SENDTO */ |
|
4670 sendto_identifier SENDTO |
|
4671 {$$ = new il_assign_out_operator_c(NULL, $1);} |
|
4672 /*| NOT variable_name SENDTO */ |
|
4673 | NOT sendto_identifier SENDTO |
|
4674 {$$ = new il_assign_out_operator_c(new not_paramassign_c(), $2);} |
|
4675 ; |
|
4676 |
|
4677 |
|
4678 il_call_operator: |
|
4679 CAL_operator |
|
4680 | CALC_operator |
|
4681 | CALCN_operator |
|
4682 ; |
|
4683 |
|
4684 |
|
4685 il_return_operator: |
|
4686 RET_operator |
|
4687 | RETC_operator |
|
4688 | RETCN_operator |
|
4689 ; |
|
4690 |
|
4691 |
|
4692 il_jump_operator: |
|
4693 JMP_operator |
|
4694 | JMPC_operator |
|
4695 | JMPCN_operator |
|
4696 ; |
|
4697 |
|
4698 |
|
4699 /***********************/ |
|
4700 /* B 3.1 - Expressions */ |
|
4701 /***********************/ |
|
4702 expression: |
|
4703 xor_expression |
|
4704 | expression OR xor_expression |
|
4705 {$$ = new or_expression_c($1, $3);} |
|
4706 ; |
|
4707 |
|
4708 xor_expression: |
|
4709 and_expression |
|
4710 | xor_expression XOR and_expression |
|
4711 {$$ = new xor_expression_c($1, $3);} |
|
4712 ; |
|
4713 |
|
4714 and_expression: |
|
4715 comparison |
|
4716 | and_expression '&' comparison |
|
4717 {$$ = new and_expression_c($1, $3);} |
|
4718 | and_expression AND comparison |
|
4719 {$$ = new and_expression_c($1, $3);} |
|
4720 /* NOTE: The lexical parser never returns the token '&'. |
|
4721 * The '&' string is interpreted by the lexcial parser as the token |
|
4722 * AND2! |
|
4723 * This means that the first rule with '&' is actually not required, |
|
4724 * but we leave it in nevertheless just in case we later decide |
|
4725 * to remove theh AND2 token... |
|
4726 */ |
|
4727 | and_expression AND2 comparison |
|
4728 {$$ = new and_expression_c($1, $3);} |
|
4729 ; |
|
4730 |
|
4731 comparison: |
|
4732 equ_expression |
|
4733 | comparison '=' equ_expression |
|
4734 {$$ = new equ_expression_c($1, $3);} |
|
4735 | comparison OPER_NE equ_expression |
|
4736 {$$ = new notequ_expression_c($1, $3);} |
|
4737 ; |
|
4738 |
|
4739 equ_expression: |
|
4740 add_expression |
|
4741 | equ_expression '<' add_expression |
|
4742 {$$ = new lt_expression_c($1, $3);} |
|
4743 | equ_expression '>' add_expression |
|
4744 {$$ = new gt_expression_c($1, $3);} |
|
4745 | equ_expression OPER_LE add_expression |
|
4746 {$$ = new le_expression_c($1, $3);} |
|
4747 | equ_expression OPER_GE add_expression |
|
4748 {$$ = new ge_expression_c($1, $3);} |
|
4749 ; |
|
4750 |
|
4751 /* Not required... |
|
4752 comparison_operator: '<' | '>' | '>=' '<=' |
|
4753 */ |
|
4754 |
|
4755 add_expression: |
|
4756 term |
|
4757 | add_expression '+' term |
|
4758 {$$ = new add_expression_c($1, $3);} |
|
4759 | add_expression '-' term |
|
4760 {$$ = new sub_expression_c($1, $3);} |
|
4761 ; |
|
4762 |
|
4763 /* Not required... |
|
4764 add_operator: '+' | '-' |
|
4765 */ |
|
4766 |
|
4767 term: |
|
4768 power_expression |
|
4769 | term '*' power_expression |
|
4770 {$$ = new mul_expression_c($1, $3);} |
|
4771 | term '/' power_expression |
|
4772 {$$ = new div_expression_c($1, $3);} |
|
4773 | term MOD power_expression |
|
4774 {$$ = new mod_expression_c($1, $3);} |
|
4775 ; |
|
4776 |
|
4777 /* Not required... |
|
4778 multiply_operator: '*' | '/' | 'MOD' |
|
4779 */ |
|
4780 |
|
4781 power_expression: |
|
4782 unary_expression |
|
4783 | power_expression OPER_EXP unary_expression |
|
4784 {$$ = new power_expression_c($1, $3);} |
|
4785 ; |
|
4786 |
|
4787 |
|
4788 unary_expression: |
|
4789 primary_expression |
|
4790 | '-' primary_expression |
|
4791 {$$ = new neg_expression_c($2);} |
|
4792 | NOT primary_expression |
|
4793 {$$ = new not_expression_c($2);} |
|
4794 ; |
|
4795 |
|
4796 /* Not required... |
|
4797 unary_operator: '-' | 'NOT' |
|
4798 */ |
|
4799 |
|
4800 |
|
4801 /* NOTE: using constant as a possible symbol for primary_expression |
|
4802 * leads to a reduce/reduce conflict. |
|
4803 * |
|
4804 * The text '-9' may be parsed as either a |
|
4805 * expression<-primary_expression<-constant<-signed_integer |
|
4806 * (i.e. the constant 9 negative) |
|
4807 * OR |
|
4808 * expression<-unary_expression<-constant<-integer |
|
4809 * (i.e. the constant 9, preceded by a unary negation) |
|
4810 * |
|
4811 * To remove the conlfict, we only allow constants without |
|
4812 * a preceding '-' to be used in primary_expression |
|
4813 */ |
|
4814 primary_expression: |
|
4815 /* constant */ |
|
4816 non_negative_constant |
|
4817 | enumerated_value |
|
4818 | variable |
|
4819 | '(' expression ')' |
|
4820 {$$ = $2;} |
|
4821 | function_invocation |
|
4822 ; |
|
4823 |
|
4824 |
|
4825 /* intermediate helper symbol for primary_expression */ |
|
4826 /* NOTE: function_name includes the standard function name 'NOT' ! |
|
4827 * This introduces a reduce/reduce conflict, as NOT(var) |
|
4828 * may be parsed as either a function_invocation, or a |
|
4829 * unary_expression. |
|
4830 * |
|
4831 * I (Mario) have opted to remove the possible reduction |
|
4832 * to function invocation, which means replacing the rule |
|
4833 * function_name '(' param_assignment_list ')' |
|
4834 * with |
|
4835 * function_name_no_NOT_clashes '(' param_assignment_list ')' |
|
4836 * |
|
4837 * Notice how the new rule does not include the situation where |
|
4838 * the function NOT is called with more than one parameter, which |
|
4839 * the original rule does include! Callinf the NOT function with more |
|
4840 * than one argument is probably a semantic error anyway, so it |
|
4841 * doesn't make much sense to take it into account. |
|
4842 * |
|
4843 * Nevertheless, if we were to to it entirely correctly, |
|
4844 * leaving the semantic checks for the next compiler stage, |
|
4845 * this syntax parser would need to include such a possibility. |
|
4846 * |
|
4847 * We will leave this out for now. No need to complicate the syntax |
|
4848 * more than the specification does by contradicting itself, and |
|
4849 * letting names clash! |
|
4850 */ |
|
4851 function_invocation: |
|
4852 /* function_name '(' param_assignment_list ')' */ |
|
4853 function_name_no_NOT_clashes '(' param_assignment_list ')' |
|
4854 {$$ = new function_invocation_c($1, $3);} |
|
4855 ; |
|
4856 |
|
4857 |
|
4858 /********************/ |
|
4859 /* B 3.2 Statements */ |
|
4860 /********************/ |
|
4861 statement_list: |
|
4862 /* empty */ |
|
4863 {$$ = new statement_list_c();} |
|
4864 | statement_list statement ';' |
|
4865 {$$ = $1; $$->add_element($2);} |
|
4866 | statement_list pragma |
|
4867 {$$ = $1; $$->add_element($2);} |
|
4868 | statement_list error ';' |
|
4869 {$$ = $1; |
|
4870 print_err_msg(current_filename, @2.last_line, "error in statement."); |
|
4871 /* yychar */ |
|
4872 yyerrok; |
|
4873 } |
|
4874 ; |
|
4875 |
|
4876 |
|
4877 statement: |
|
4878 assignment_statement |
|
4879 | subprogram_control_statement |
|
4880 | selection_statement |
|
4881 | iteration_statement |
|
4882 ; |
|
4883 |
|
4884 |
|
4885 /*********************************/ |
|
4886 /* B 3.2.1 Assignment Statements */ |
|
4887 /*********************************/ |
|
4888 assignment_statement: |
|
4889 variable ASSIGN expression |
|
4890 {$$ = new assignment_statement_c($1, $3);} |
|
4891 ; |
|
4892 |
|
4893 |
|
4894 |
|
4895 |
|
4896 /*****************************************/ |
|
4897 /* B 3.2.2 Subprogram Control Statements */ |
|
4898 /*****************************************/ |
|
4899 subprogram_control_statement: |
|
4900 fb_invocation |
|
4901 | return_statement |
|
4902 ; |
|
4903 |
|
4904 |
|
4905 return_statement: |
|
4906 RETURN {$$ = new return_statement_c();} |
|
4907 ; |
|
4908 |
|
4909 |
|
4910 |
|
4911 fb_invocation: |
|
4912 prev_declared_fb_name '(' ')' |
|
4913 {$$ = new fb_invocation_c($1, NULL); } |
|
4914 | prev_declared_fb_name '(' param_assignment_list ')' |
|
4915 {$$ = new fb_invocation_c($1, $3);} |
|
4916 ; |
|
4917 |
|
4918 |
|
4919 /* helper symbol for |
|
4920 * - fb_invocation |
|
4921 * - function_invocation |
|
4922 */ |
|
4923 param_assignment_list: |
|
4924 param_assignment |
|
4925 {$$ = new param_assignment_list_c(); $$->add_element($1);} |
|
4926 | param_assignment_list ',' param_assignment |
|
4927 {$$ = $1; $$->add_element($3);} |
|
4928 ; |
|
4929 |
|
4930 |
|
4931 |
|
4932 param_assignment: |
|
4933 /* variable_name ASSIGN expression */ |
|
4934 any_identifier ASSIGN expression |
|
4935 {$$ = new input_variable_param_assignment_c($1, $3);} |
|
4936 | expression |
|
4937 /*| variable_name SENDTO variable */ |
|
4938 /*| any_identifier SENDTO variable */ |
|
4939 | sendto_identifier SENDTO variable |
|
4940 {$$ = new output_variable_param_assignment_c(NULL,$1, $3);} |
|
4941 /*| variable_name SENDTO variable */ |
|
4942 /*| NOT any_identifier SENDTO variable*/ |
|
4943 | NOT sendto_identifier SENDTO variable |
|
4944 {$$ = new output_variable_param_assignment_c(new not_paramassign_c(),$2, $4);} |
|
4945 ; |
|
4946 |
|
4947 |
|
4948 |
|
4949 |
|
4950 |
|
4951 /********************************/ |
|
4952 /* B 3.2.3 Selection Statements */ |
|
4953 /********************************/ |
|
4954 selection_statement: |
|
4955 if_statement |
|
4956 | case_statement |
|
4957 ; |
|
4958 |
|
4959 |
|
4960 if_statement: |
|
4961 IF expression THEN statement_list elseif_statement_list END_IF |
|
4962 {$$ = new if_statement_c($2, $4, $5, NULL);} |
|
4963 | IF expression THEN statement_list elseif_statement_list ELSE statement_list END_IF |
|
4964 {$$ = new if_statement_c($2, $4, $5, $7);} |
|
4965 ; |
|
4966 |
|
4967 /* helper symbol for if_statement */ |
|
4968 elseif_statement_list: |
|
4969 /* empty */ |
|
4970 {$$ = new elseif_statement_list_c();} |
|
4971 | elseif_statement_list elseif_statement |
|
4972 {$$ = $1; $$->add_element($2);} |
|
4973 ; |
|
4974 |
|
4975 /* helper symbol for elseif_statement_list */ |
|
4976 elseif_statement: |
|
4977 ELSIF expression THEN statement_list |
|
4978 {$$ = new elseif_statement_c($2, $4);} |
|
4979 ; |
|
4980 |
|
4981 |
|
4982 case_statement: |
|
4983 CASE expression OF case_element_list END_CASE |
|
4984 {$$ = new case_statement_c($2, $4, NULL);} |
|
4985 | CASE expression OF case_element_list ELSE statement_list END_CASE |
|
4986 {$$ = new case_statement_c($2, $4, $6);} |
|
4987 ; |
|
4988 |
|
4989 |
|
4990 /* helper symbol for case_statement */ |
|
4991 case_element_list: |
|
4992 case_element |
|
4993 {$$ = new case_element_list_c(); $$->add_element($1);} |
|
4994 | case_element_list case_element |
|
4995 {$$ = $1; $$->add_element($2);} |
|
4996 ; |
|
4997 |
|
4998 |
|
4999 case_element: |
|
5000 case_list ':' statement_list |
|
5001 {$$ = new case_element_c($1, $3);} |
|
5002 ; |
|
5003 |
|
5004 |
|
5005 case_list: |
|
5006 case_list_element |
|
5007 {$$ = new case_list_c(); $$->add_element($1);} |
|
5008 | case_list ',' case_list_element |
|
5009 {$$ = $1; $$->add_element($3);} |
|
5010 ; |
|
5011 |
|
5012 |
|
5013 case_list_element: |
|
5014 signed_integer |
|
5015 | enumerated_value |
|
5016 | subrange |
|
5017 ; |
|
5018 |
|
5019 |
|
5020 |
|
5021 |
|
5022 |
|
5023 /********************************/ |
|
5024 /* B 3.2.4 Iteration Statements */ |
|
5025 /********************************/ |
|
5026 iteration_statement: |
|
5027 for_statement |
|
5028 | while_statement |
|
5029 | repeat_statement |
|
5030 | exit_statement |
|
5031 ; |
|
5032 |
|
5033 |
|
5034 for_statement: |
|
5035 FOR control_variable ASSIGN expression TO expression BY expression DO statement_list END_FOR |
|
5036 {$$ = new for_statement_c($2, $4, $6, $8, $10);} |
|
5037 | FOR control_variable ASSIGN expression TO expression DO statement_list END_FOR |
|
5038 {$$ = new for_statement_c($2, $4, $6, NULL, $8);} |
|
5039 ; |
|
5040 |
|
5041 /* The spec has the syntax |
|
5042 * control_variable: identifier; |
|
5043 * but then defines the semantics of control_variable |
|
5044 * (Section 3.3.2.4) as being of an integer type |
|
5045 * (e.g., SINT, INT, or DINT). |
|
5046 * |
|
5047 * Obviously this presuposes that the control_variable |
|
5048 * must have been declared in some VAR .. END_VAR |
|
5049 * construct, so I (Mario) changed the syntax to read |
|
5050 * control_variable: prev_declared_variable_name; |
|
5051 */ |
|
5052 control_variable: prev_declared_variable_name {$$ = $1;}; |
|
5053 |
|
5054 /* Integrated directly into for_statement */ |
|
5055 /* |
|
5056 for_list: |
|
5057 expression TO expression [BY expression] |
|
5058 ; |
|
5059 */ |
|
5060 |
|
5061 |
|
5062 while_statement: |
|
5063 WHILE expression DO statement_list END_WHILE |
|
5064 {$$ = new while_statement_c($2, $4);} |
|
5065 ; |
|
5066 |
|
5067 |
|
5068 repeat_statement: |
|
5069 REPEAT statement_list UNTIL expression END_REPEAT |
|
5070 {$$ = new repeat_statement_c($2, $4);} |
|
5071 ; |
|
5072 |
|
5073 |
|
5074 exit_statement: |
|
5075 EXIT {$$ = new exit_statement_c();} |
|
5076 ; |
|
5077 |
|
5078 |
|
5079 |
|
5080 |
|
5081 |
|
5082 %% |
|
5083 |
|
5084 #include <stdio.h> /* required for printf() */ |
|
5085 #include <errno.h> |
|
5086 #include "../util/symtable.hh" |
|
5087 |
|
5088 /* variables defined in code generated by flex... */ |
|
5089 extern FILE *yyin; |
|
5090 extern int yylineno; |
|
5091 |
|
5092 /* The following function is called automatically by bison whenever it comes across |
|
5093 * an error. Unfortunately it calls this function before executing the code that handles |
|
5094 * the error itself, so we cannot print out the correct line numbers of the error location |
|
5095 * over here. |
|
5096 * Our solution is to store the current error message in a global variable, and have all |
|
5097 * error action handlers call the function print_err_msg() after setting the location |
|
5098 * (line number) variable correctly. |
|
5099 */ |
|
5100 const char *current_error_msg; |
|
5101 void yyerror (const char *error_msg) { |
|
5102 current_error_msg = error_msg; |
|
5103 /* fprintf(stderr, "error %d: %s\n", yynerrs // global variable //, error_msg); */ |
|
5104 print_include_stack(); |
|
5105 } |
|
5106 |
|
5107 |
|
5108 void print_err_msg(const char *filename, int lineno, const char *additional_error_msg) { |
|
5109 fprintf(stderr, "error %d: %s\n", yynerrs, additional_error_msg); |
|
5110 print_include_stack(); |
|
5111 fprintf(stderr, "%s:%d: %s\n", filename, lineno, current_error_msg); |
|
5112 } |
|
5113 |
|
5114 /* Function only called from within flex! |
|
5115 * |
|
5116 * search for a symbol in either of the two symbol tables |
|
5117 * declared above, and return the token id of the first |
|
5118 * symbol found. |
|
5119 * Searches first in the variables, and only if not found |
|
5120 * does it continue searching in the library elements |
|
5121 */ |
|
5122 int get_identifier_token(const char *identifier_str) { |
|
5123 // std::cout << "get_identifier_token(" << identifier_str << "): \n"; |
|
5124 int token_id; |
|
5125 |
|
5126 if ((token_id = variable_name_symtable.find_value(identifier_str)) == variable_name_symtable.end_value()) |
|
5127 if ((token_id = library_element_symtable.find_value(identifier_str)) == library_element_symtable.end_value()) |
|
5128 return identifier_token; |
|
5129 return token_id; |
|
5130 } |
|
5131 |
|
5132 |
|
5133 |
|
5134 /* convert between an il_operator to a function name */ |
|
5135 /* This a kludge! |
|
5136 * It is required because our language requires more than one |
|
5137 * look ahead token, and bison only works with one! |
|
5138 */ |
|
5139 #define op_2_str(op, str) {\ |
|
5140 op ## _operator_c *ptr = dynamic_cast<op ## _operator_c *>(il_operator); \ |
|
5141 if (ptr != NULL) name = str; \ |
|
5142 } |
|
5143 |
|
5144 /* NOTE: this code is very ugly and un-eficient, but I (Mario) have many |
|
5145 * more things to worry about right now, so just let it be... |
|
5146 */ |
|
5147 symbol_c *il_operator_c_2_identifier_c(symbol_c *il_operator) { |
|
5148 const char *name = NULL; |
|
5149 |
|
5150 op_2_str(NOT, "NOT"); |
|
5151 |
|
5152 op_2_str(AND, "AND"); |
|
5153 op_2_str(OR, "OR"); |
|
5154 op_2_str(XOR, "XOR"); |
|
5155 op_2_str(ADD, "ADD"); |
|
5156 op_2_str(SUB, "SUB"); |
|
5157 op_2_str(MUL, "MUL"); |
|
5158 op_2_str(DIV, "DIV"); |
|
5159 op_2_str(MOD, "MOD"); |
|
5160 op_2_str(GT, "GT"); |
|
5161 op_2_str(GE, "GE"); |
|
5162 op_2_str(EQ, "EQ"); |
|
5163 op_2_str(LT, "LT"); |
|
5164 op_2_str(LE, "LE"); |
|
5165 op_2_str(NE, "NE"); |
|
5166 |
|
5167 op_2_str(LD, "LD"); |
|
5168 op_2_str(LDN, "LDN"); |
|
5169 op_2_str(ST, "ST"); |
|
5170 op_2_str(STN, "STN"); |
|
5171 |
|
5172 op_2_str(S, "S"); |
|
5173 op_2_str(R, "R"); |
|
5174 op_2_str(S1, "S1"); |
|
5175 op_2_str(R1, "R1"); |
|
5176 |
|
5177 op_2_str(CLK, "CLK"); |
|
5178 op_2_str(CU, "CU"); |
|
5179 op_2_str(CD, "CD"); |
|
5180 op_2_str(PV, "PV"); |
|
5181 op_2_str(IN, "IN"); |
|
5182 op_2_str(PT, "PT"); |
|
5183 |
|
5184 op_2_str(ANDN, "ANDN"); |
|
5185 op_2_str(ORN, "ORN"); |
|
5186 op_2_str(XORN, "XORN"); |
|
5187 |
|
5188 op_2_str(ADD, "ADD"); |
|
5189 op_2_str(SUB, "SUB"); |
|
5190 op_2_str(MUL, "MUL"); |
|
5191 op_2_str(DIV, "DIV"); |
|
5192 |
|
5193 op_2_str(GT, "GT"); |
|
5194 op_2_str(GE, "GE"); |
|
5195 op_2_str(EQ, "EQ"); |
|
5196 op_2_str(LT, "LT"); |
|
5197 op_2_str(LE, "LE"); |
|
5198 op_2_str(NE, "NE"); |
|
5199 |
|
5200 op_2_str(CAL, "CAL"); |
|
5201 op_2_str(CALC, "CALC"); |
|
5202 op_2_str(CALCN, "CALCN"); |
|
5203 op_2_str(RET, "RET"); |
|
5204 op_2_str(RETC, "RETC"); |
|
5205 op_2_str(RETCN, "RETCN"); |
|
5206 op_2_str(JMP, "JMP"); |
|
5207 op_2_str(JMPC, "JMPC"); |
|
5208 op_2_str(JMPCN, "JMPCN"); |
|
5209 |
|
5210 if (name == NULL) |
|
5211 ERROR; |
|
5212 |
|
5213 free(il_operator); |
|
5214 return new identifier_c(strdup(name)); |
|
5215 } |
|
5216 |
|
5217 |
|
5218 |
|
5219 |
|
5220 /* |
|
5221 * Join two strings together. Allocate space with malloc(3). |
|
5222 */ |
|
5223 static char *strdup2(const char *a, const char *b) { |
|
5224 char *res = (char *)malloc(strlen(a) + strlen(b) + 1); |
|
5225 |
|
5226 if (!res) |
|
5227 return NULL; |
|
5228 return strcat(strcpy(res, a), b); /* safe, actually */ |
|
5229 } |
|
5230 |
|
5231 /* |
|
5232 * Join three strings together. Allocate space with malloc(3). |
|
5233 */ |
|
5234 static char *strdup3(const char *a, const char *b, const char *c) { |
|
5235 char *res = (char *)malloc(strlen(a) + strlen(b) + strlen(c) + 1); |
|
5236 |
|
5237 if (!res) |
|
5238 return NULL; |
|
5239 return strcat(strcat(strcpy(res, a), b), c); /* safe, actually */ |
|
5240 } |
|
5241 |
|
5242 |
|
5243 |
|
5244 |
|
5245 const char *standard_function_names[] = { |
|
5246 // 2.5.1.5.1 Type conversion functions |
|
5247 /* |
|
5248 *_TO_** |
|
5249 TRUNC |
|
5250 *_BCD_TO_** |
|
5251 **_TO_BCD_* |
|
5252 (REAL or LREAL to SINT, INT, DINT or LINT) |
|
5253 */ |
|
5254 "TRUNC", |
|
5255 "TIME_TO_REAL", |
|
5256 // 2.5.1.5.2 Numerical functions |
|
5257 // Table 23 - Standard functions of one numeric variable |
|
5258 "ABS","SQRT","LN","LOG","EXP","SIN","COS","TAN","ASIN","ACOS","ATAN", |
|
5259 // Table 24 - Standard arithmetic functions |
|
5260 "ADD","MUL","SUB","DIV","MOD"/* See note (a) */,"EXPT","MOVE", |
|
5261 // 2.5.1.5.3 Bit string functions |
|
5262 // Table 25 - Standard bit shift functions |
|
5263 "SHL","SHR","ROR","ROL", |
|
5264 // 2.5.1.5.4 Selection and comparison functions |
|
5265 // Table 26 - Standard bitwise Boolean functions |
|
5266 "AND","OR","XOR","NOT", |
|
5267 // Table 27 - Standard selection functions |
|
5268 "SEL","MAX","MIN","LIMIT","MUX", |
|
5269 // Table 28 - Standard comparison functions |
|
5270 "GT","GE","EQ","LE","LT","NE", |
|
5271 // 2.5.1.5.5 Character string functions |
|
5272 // Table 29 - Standard character string functions |
|
5273 "LEN","LEFT","RIGHT","MID","CONCAT","INSERT","DELETE","REPLACE","FIND", |
|
5274 // 2.5.1.5.6 Functions of time data types |
|
5275 // Table 30 - Functions of time data types |
|
5276 "ADD_TIME","ADD_TOD_TIME","ADD_DT_TIME","SUB_TIME","SUB_DATE_DATE", |
|
5277 "SUB_TOD_TIME","SUB_TOD_TOD","SUB_DT_TIME","SUB_DT_DT","MULTIME", |
|
5278 "DIVTIME","CONCAT_DATE_TOD", |
|
5279 // 2.5.1.5.7 Functions of enumerated data types |
|
5280 // Table 31 - Functions of enumerated data types |
|
5281 // "SEL", /* already above! We cannot have duplicates! */ |
|
5282 // "MUX", /* already above! We cannot have duplicates! */ |
|
5283 // "EQ", /* already above! We cannot have duplicates! */ |
|
5284 // "NE", /* already above! We cannot have duplicates! */ |
|
5285 |
|
5286 /* end of array marker! Do not remove! */ |
|
5287 NULL |
|
5288 |
|
5289 /* Note (a): |
|
5290 * This function has a name equal to a reserved keyword. |
|
5291 * This means that adding it here is irrelevant because the |
|
5292 * lexical parser will consider it the XXX token before |
|
5293 * it interprets it as an identifier and looks it up |
|
5294 * in the library elements symbol table. |
|
5295 */ |
|
5296 }; |
|
5297 |
|
5298 |
|
5299 |
|
5300 |
|
5301 const char *standard_function_block_names[] = { |
|
5302 // 2.5.2.3.1 Bistable elements |
|
5303 // Table 34 - Standard bistable function blocks |
|
5304 //"SR","RS", |
|
5305 // 2.5.2.3.2 Edge detection |
|
5306 // Table 35 - Standard edge detection function blocks |
|
5307 "R_TRIG","F_TRIG", |
|
5308 // 2.5.2.3.3 Counters |
|
5309 // Table 36 - Standard counter function blocks |
|
5310 "CTU","CTU_LINT","CTU_UDINT","CTU_ULINT", |
|
5311 "CTD","CTD_DINT","CTD_LINT","CTD_UDINT", |
|
5312 "CTUD","CTUD_DINT","CTUD_LINT","CTUD_ULINT", |
|
5313 // 2.5.2.3.4 Timers |
|
5314 // Table 37 - Standard timer function blocks |
|
5315 "TP","TON","TOF", |
|
5316 /* end of array marker! Do not remove! */ |
|
5317 NULL |
|
5318 }; |
|
5319 |
|
5320 |
|
5321 #define LIBFILE "ieclib.txt" |
|
5322 #define DEF_LIBFILENAME LIBDIRECTORY "/" LIBFILE |
|
5323 |
|
5324 int stage1_2(const char *filename, const char *includedir, symbol_c **tree_root_ref) { |
|
5325 FILE *in_file = NULL, *lib_file = NULL; |
|
5326 char *libfilename = NULL; |
|
5327 |
|
5328 if((in_file = fopen(filename, "r")) == NULL) { |
|
5329 char *errmsg = strdup2("Error opening main file ", filename); |
|
5330 perror(errmsg); |
|
5331 free(errmsg); |
|
5332 return -1; |
|
5333 } |
|
5334 |
|
5335 if (includedir != NULL) { |
|
5336 if ((libfilename = strdup3(includedir, "/", LIBFILE)) == NULL) { |
|
5337 fprintf (stderr, "Out of memory. Bailing out!\n"); |
|
5338 return -1; |
|
5339 } |
|
5340 |
|
5341 if((lib_file = fopen(libfilename, "r")) == NULL) { |
|
5342 char *errmsg = strdup2("Error opening library file ", libfilename); |
|
5343 perror(errmsg); |
|
5344 free(errmsg); |
|
5345 } |
|
5346 } |
|
5347 |
|
5348 if (lib_file == NULL) { |
|
5349 /* we try again... */ |
|
5350 if ((libfilename = strdup(DEF_LIBFILENAME)) == NULL) { |
|
5351 fprintf (stderr, "Out of memory. Bailing out!\n"); |
|
5352 return -1; |
|
5353 } |
|
5354 |
|
5355 if((lib_file = fopen(libfilename, "r")) == NULL) { |
|
5356 char *errmsg = strdup2("Error opening library file ", libfilename); |
|
5357 perror(errmsg); |
|
5358 free(errmsg); |
|
5359 } |
|
5360 } |
|
5361 |
|
5362 if (lib_file == NULL) { |
|
5363 /* we give up... */ |
|
5364 free(libfilename); |
|
5365 fclose(in_file); |
|
5366 return -1; |
|
5367 } |
|
5368 |
|
5369 /* first parse the standard library file... */ |
|
5370 yyin = lib_file; |
|
5371 yylineno = 1; |
|
5372 allow_function_overloading = true; |
|
5373 current_filename = libfilename; |
|
5374 if (yyparse() != 0) |
|
5375 ERROR; |
|
5376 |
|
5377 if (yynerrs > 0) { |
|
5378 fprintf (stderr, "\nFound %d error(s) in %s. Bailing out!\n", yynerrs /* global variable */, libfilename); |
|
5379 ERROR; |
|
5380 } |
|
5381 free(libfilename); |
|
5382 fclose(lib_file); |
|
5383 |
|
5384 /* if by any chance the library is not complete, we |
|
5385 * now add the missing reserved keywords to the list!!! |
|
5386 */ |
|
5387 for(int i = 0; standard_function_names[i] != NULL; i++) |
|
5388 if (library_element_symtable.find_value(standard_function_names[i]) == |
|
5389 library_element_symtable.end_value()) |
|
5390 library_element_symtable.insert(standard_function_names[i], standard_function_name_token); |
|
5391 |
|
5392 for(int i = 0; standard_function_block_names[i] != NULL; i++) |
|
5393 if (library_element_symtable.find_value(standard_function_block_names[i]) == |
|
5394 library_element_symtable.end_value()) |
|
5395 library_element_symtable.insert(standard_function_block_names[i], standard_function_block_name_token); |
|
5396 |
|
5397 #if YYDEBUG |
|
5398 yydebug = 1; |
|
5399 #endif |
|
5400 |
|
5401 /* now parse the input file... */ |
|
5402 yyin = in_file; |
|
5403 yylineno = 1; |
|
5404 allow_function_overloading = false; |
|
5405 current_filename = filename; |
|
5406 if (yyparse() != 0) |
|
5407 exit(EXIT_FAILURE); |
|
5408 |
|
5409 if (yynerrs > 0) { |
|
5410 fprintf (stderr, "\nFound %d error(s). Bailing out!\n", yynerrs /* global variable */); |
|
5411 exit(EXIT_FAILURE); |
|
5412 } |
|
5413 |
|
5414 if (tree_root_ref != NULL) |
|
5415 *tree_root_ref = tree_root; |
|
5416 |
|
5417 fclose(in_file); |
|
5418 return 0; |
|
5419 } |
|
5420 |
|
5421 |
|
5422 |