|
1 /* |
|
2 * matiec - a compiler for the programming languages defined in IEC 61131-3 |
|
3 * |
|
4 * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt) |
|
5 * Copyright (C) 2012 Manuele Conti (conti.ma@alice.it) |
|
6 * |
|
7 * |
|
8 * This program is free software: you can redistribute it and/or modify |
|
9 * it under the terms of the GNU General Public License as published by |
|
10 * the Free Software Foundation, either version 3 of the License, or |
|
11 * (at your option) any later version. |
|
12 * |
|
13 * This program is distributed in the hope that it will be useful, |
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
16 * GNU General Public License for more details. |
|
17 * |
|
18 * You should have received a copy of the GNU General Public License |
|
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
20 * |
|
21 * |
|
22 * This code is made available on the understanding that it will not be |
|
23 * used in safety-critical situations without a full and competent review. |
|
24 */ |
|
25 |
|
26 /* |
|
27 * An IEC 61131-3 compiler. |
|
28 * |
|
29 * Based on the |
|
30 * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) |
|
31 * |
|
32 */ |
|
33 |
|
34 #include <sstream> |
|
35 #include "create_enumtype_conversion_functions.hh" |
|
36 |
|
37 /* set to 1 to see debug info during execution */ |
|
38 static const int debug = 0; |
|
39 |
|
40 /* |
|
41 * functionDataType array contains all supported data type conversion. |
|
42 */ |
|
43 const char *create_enumtype_conversion_functions_c::functionDataType[] = { |
|
44 "STRING", |
|
45 "SINT" , |
|
46 "INT" , |
|
47 "DINT" , |
|
48 "LINT" , |
|
49 "USINT" , |
|
50 "UNIT" , |
|
51 "UDINT" , |
|
52 "ULINT" , |
|
53 NULL |
|
54 }; |
|
55 |
|
56 create_enumtype_conversion_functions_c::create_enumtype_conversion_functions_c(symbol_c *ignore) { |
|
57 |
|
58 } |
|
59 |
|
60 create_enumtype_conversion_functions_c::~create_enumtype_conversion_functions_c(void) { |
|
61 |
|
62 } |
|
63 |
|
64 std::string &create_enumtype_conversion_functions_c::get_declaration(symbol_c *root) { |
|
65 text = ""; |
|
66 if (NULL != root) { |
|
67 root->accept(*this); |
|
68 } |
|
69 |
|
70 return text; |
|
71 } |
|
72 |
|
73 void *create_enumtype_conversion_functions_c::visit(identifier_c *symbol) { |
|
74 currentToken = symbol->value; |
|
75 |
|
76 return NULL; |
|
77 } |
|
78 |
|
79 /**********************/ |
|
80 /* B 1.3 - Data types */ |
|
81 /**********************/ |
|
82 /********************************/ |
|
83 /* B 1.3.3 - Derived data types */ |
|
84 /********************************/ |
|
85 void *create_enumtype_conversion_functions_c::visit(enumerated_type_declaration_c *symbol) { |
|
86 std::string enumerateName; |
|
87 std::string functionName; |
|
88 std::list <std::string> enumerateValues; |
|
89 |
|
90 symbol->enumerated_type_name->accept(*this); |
|
91 enumerateName = currentToken; |
|
92 |
|
93 symbol->enumerated_spec_init->accept(*this); |
|
94 enumerateValues = currentTokenList; |
|
95 |
|
96 printStringToEnum (enumerateName, enumerateValues); |
|
97 printEnumToString (enumerateName, enumerateValues); |
|
98 for (size_t s = 8; s <= 64; s*= 2) { |
|
99 printIntegerToEnum (enumerateName, enumerateValues, true , s); |
|
100 printEnumToInteger (enumerateName, enumerateValues, true , s); |
|
101 printIntegerToEnum (enumerateName, enumerateValues, false, s); |
|
102 printEnumToInteger (enumerateName, enumerateValues, false, s); |
|
103 } |
|
104 if (debug) std::cout << text << std::endl; |
|
105 |
|
106 return NULL; |
|
107 } |
|
108 |
|
109 void *create_enumtype_conversion_functions_c::visit(enumerated_value_list_c *symbol) { |
|
110 list_c *list; |
|
111 |
|
112 currentTokenList.clear(); |
|
113 list = (list_c *)symbol; |
|
114 for (int i = 0; i < list->n; i++) { |
|
115 list->elements[i]->accept(*this); |
|
116 currentTokenList.push_back(currentToken); |
|
117 } |
|
118 |
|
119 return NULL; |
|
120 } |
|
121 |
|
122 /* |
|
123 * getIntegerName function generate a integer data name from signed and size. |
|
124 */ |
|
125 std::string create_enumtype_conversion_functions_c::getIntegerName(bool isSigned, size_t size) { |
|
126 std::string integerType = ""; |
|
127 if (! isSigned) { |
|
128 integerType = "U"; |
|
129 } |
|
130 switch(size) { |
|
131 case 8 : integerType += "S"; break; |
|
132 case 16: break; |
|
133 case 32: integerType += "D"; break; |
|
134 case 64: integerType += "L"; break; |
|
135 default: break; |
|
136 } |
|
137 integerType +="INT"; |
|
138 |
|
139 return integerType; |
|
140 } |
|
141 |
|
142 /* |
|
143 * printStringToEnum function print conversion function from STRING to <ENUM>: |
|
144 * ST Output: |
|
145 * |
|
146 |
|
147 FUNCTION STRING_TO_<ENUM> : <ENUM> |
|
148 VAR_INPUT |
|
149 IN: STRING; |
|
150 END_VAR |
|
151 IF IN = '<ENUM.VALUE_1>' THEN |
|
152 STRING_TO_<ENUM> := <ENUM.VALUE_1>; |
|
153 RETURN; |
|
154 END_IF; |
|
155 ... |
|
156 IF IN = '<ENUM.VALU_N>' THEN |
|
157 STRING_TO_<ENUM> := <ENUM.VALUE_N>; |
|
158 RETURN; |
|
159 END_IF; |
|
160 END_FUNCTION |
|
161 |
|
162 */ |
|
163 void create_enumtype_conversion_functions_c::printStringToEnum (std::string &enumerateName, std::list<std::string> &enumerateValues) { |
|
164 std::list <std::string>::const_iterator itr; |
|
165 std::string functionName; |
|
166 |
|
167 functionName = "STRING_TO_" + enumerateName; |
|
168 text += "FUNCTION " + functionName + " : " + enumerateName; |
|
169 text += "\nVAR_INPUT\nIN : STRING;\nEND_VAR\n"; |
|
170 for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) { |
|
171 std::string value = *itr; |
|
172 text += "IF IN = '" + value + "' THEN\n"; |
|
173 text += " " + functionName + " := " + value + ";\n"; |
|
174 text += " RETURN;\n"; |
|
175 text += "END_IF;\n"; |
|
176 } |
|
177 text += "END_FUNCTION\n\n"; |
|
178 } |
|
179 |
|
180 /* |
|
181 * printEnumToString function print conversion function from <ENUM> to STRING: |
|
182 * ST Output: |
|
183 * |
|
184 |
|
185 FUNCTION <ENUM>_TO_STRING : STRING |
|
186 VAR_INPUT |
|
187 IN: <ENUM>; |
|
188 END_VAR |
|
189 IF IN = <ENUM.VALUE_1> THEN |
|
190 <ENUM>_TO_STRING := '<ENUM.VALUE_1>'; |
|
191 RETURN; |
|
192 END_IF; |
|
193 ... |
|
194 IF IN = <ENUM.VALUE_N> THEN |
|
195 <ENUM>_TO_STRING := '<ENUM.VALUE_N>'; |
|
196 RETURN; |
|
197 END_IF; |
|
198 END_FUNCTION |
|
199 |
|
200 */ |
|
201 void create_enumtype_conversion_functions_c::printEnumToString (std::string &enumerateName, std::list<std::string> &enumerateValues) { |
|
202 std::list <std::string>::const_iterator itr; |
|
203 std::string functionName; |
|
204 |
|
205 functionName = enumerateName + "_TO_STRING"; |
|
206 text += "FUNCTION " + functionName + " : STRING"; |
|
207 text += "\nVAR_INPUT\nIN : " + enumerateName + ";\nEND_VAR\n"; |
|
208 for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) { |
|
209 std::string value = *itr; |
|
210 text += "IF IN = " + value + " THEN\n"; |
|
211 text += " " + functionName + " := '" + value + "';\n"; |
|
212 text += " RETURN;\n"; |
|
213 text += "END_IF;\n"; |
|
214 } |
|
215 text += "END_FUNCTION\n\n"; |
|
216 } |
|
217 |
|
218 /* |
|
219 * printIntegerToEnum function print conversion function from <INTEGER> to <ENUM>: |
|
220 * ST Output: |
|
221 * |
|
222 |
|
223 FUNCTION <INTEGER>_TO_<ENUM> : <ENUM> |
|
224 VAR_INPUT |
|
225 IN: <INTEGER>; |
|
226 END_VAR |
|
227 IF IN = 1 THEN |
|
228 <INTEGER>_TO_<ENUM> := <ENUM.VALUE_1>; |
|
229 RETURN; |
|
230 END_IF; |
|
231 ... |
|
232 IF IN = N THEN |
|
233 <INTEGER>_TO_<ENUM> := <ENUM.VALUE_N>; |
|
234 RETURN; |
|
235 END_IF; |
|
236 END_FUNCTION |
|
237 |
|
238 */ |
|
239 void create_enumtype_conversion_functions_c::printIntegerToEnum (std::string &enumerateName, std::list<std::string> &enumerateValues, bool isSigned, size_t size) { |
|
240 std::list <std::string>::const_iterator itr; |
|
241 std::string functionName; |
|
242 std::string integerType; |
|
243 int count; |
|
244 |
|
245 integerType = getIntegerName(isSigned, size); |
|
246 functionName = integerType + "_TO_" + enumerateName; |
|
247 text += "FUNCTION " + functionName + " : " + enumerateName; |
|
248 text += "\nVAR_INPUT\nIN : " + integerType + ";\nEND_VAR\n"; |
|
249 count = 0; |
|
250 for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) { |
|
251 std::string value = *itr; |
|
252 std::stringstream out; |
|
253 out << count; |
|
254 text += "IF IN = " + out.str() + " THEN\n"; |
|
255 text += " " + functionName + " := " + value + ";\n"; |
|
256 text += " RETURN;\n"; |
|
257 text += "END_IF;\n"; |
|
258 count++; |
|
259 } |
|
260 text += "END_FUNCTION\n\n"; |
|
261 } |
|
262 |
|
263 /* |
|
264 * printEnumToInteger function print conversion function from <ENUM> to <INTEGER>: |
|
265 * ST Output: |
|
266 * |
|
267 |
|
268 FUNCTION <ENUM>_TO_<INTEGER> : <INTEGER> |
|
269 VAR_INPUT |
|
270 IN: <INTEGER>; |
|
271 END_VAR |
|
272 IF IN = <ENUM.VALUE_1> THEN |
|
273 <ENUM>_TO_<INTEGER> := 1; |
|
274 RETURN; |
|
275 END_IF; |
|
276 ... |
|
277 IF IN = <ENUM.VALUE_N> THEN |
|
278 <ENUM>_TO_<INTEGER> := N; |
|
279 RETURN; |
|
280 END_IF; |
|
281 END_FUNCTION |
|
282 |
|
283 */ |
|
284 void create_enumtype_conversion_functions_c::printEnumToInteger (std::string &enumerateName, std::list<std::string> &enumerateValues, bool isSigned, size_t size) { |
|
285 std::list <std::string>::const_iterator itr; |
|
286 std::string functionName; |
|
287 std::string integerType; |
|
288 int count; |
|
289 |
|
290 integerType = getIntegerName(isSigned, size); |
|
291 functionName = enumerateName + "_TO_" + integerType; |
|
292 text += "FUNCTION " + functionName + " : " + integerType; |
|
293 text += "\nVAR_INPUT\nIN : " + enumerateName + ";\nEND_VAR\n"; |
|
294 count = 0; |
|
295 for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) { |
|
296 std::string value = *itr; |
|
297 std::stringstream out; |
|
298 out << count; |
|
299 text += "IF IN = " + value + " THEN\n"; |
|
300 text += " " + functionName + " := " + out.str() + ";\n"; |
|
301 text += " RETURN;\n"; |
|
302 text += "END_IF;\n"; |
|
303 count++; |
|
304 } |
|
305 text += "END_FUNCTION\n\n"; |
|
306 } |
|
307 |
|
308 |
|
309 |