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 |
|
35 #include "derived_conversion_functions.hh" |
|
36 #include <sstream> |
|
37 |
|
38 static const int debug = 0; |
|
39 |
|
40 const char *derived_conversion_functions_c::functionDataType[] = { |
|
41 "STRING", |
|
42 "SINT" , |
|
43 "INT" , |
|
44 "DINT" , |
|
45 "LINT" , |
|
46 "USINT" , |
|
47 "UNIT" , |
|
48 "UDINT" , |
|
49 "ULINT" , |
|
50 NULL |
|
51 }; |
|
52 |
|
53 derived_conversion_functions_c::derived_conversion_functions_c(symbol_c *ignore) { |
|
54 |
|
55 } |
|
56 |
|
57 derived_conversion_functions_c::~derived_conversion_functions_c(void) { |
|
58 |
|
59 } |
|
60 |
|
61 std::string &derived_conversion_functions_c::get_declaration(symbol_c *root) { |
|
62 text = ""; |
|
63 if (NULL != root) { |
|
64 root->accept(*this); |
|
65 } |
|
66 |
|
67 return text; |
|
68 } |
|
69 |
|
70 void *derived_conversion_functions_c::visit(identifier_c *symbol) { |
|
71 currentToken = symbol->value; |
|
72 |
|
73 return NULL; |
|
74 } |
|
75 |
|
76 void *derived_conversion_functions_c::visit(enumerated_type_declaration_c *symbol) { |
|
77 std::string enumerateName; |
|
78 std::string functionName; |
|
79 std::list <std::string> enumerateValues; |
|
80 |
|
81 symbol->enumerated_type_name->accept(*this); |
|
82 enumerateName = currentToken; |
|
83 |
|
84 symbol->enumerated_spec_init->accept(*this); |
|
85 enumerateValues = currentTokenList; |
|
86 |
|
87 printStringToEnum (enumerateName, enumerateValues); |
|
88 printEnumToString (enumerateName, enumerateValues); |
|
89 for (size_t s = 8; s <= 64; s*= 2) { |
|
90 printIntegerToEnum (enumerateName, enumerateValues, true , s); |
|
91 printEnumToInteger (enumerateName, enumerateValues, true , s); |
|
92 printIntegerToEnum (enumerateName, enumerateValues, false, s); |
|
93 printEnumToInteger (enumerateName, enumerateValues, false, s); |
|
94 } |
|
95 if (debug) std::cout << text << std::endl; |
|
96 |
|
97 return NULL; |
|
98 } |
|
99 |
|
100 void *derived_conversion_functions_c::visit(enumerated_value_list_c *symbol) { |
|
101 list_c *list; |
|
102 |
|
103 currentTokenList.clear(); |
|
104 list = (list_c *)symbol; |
|
105 for (int i = 0; i < list->n; i++) { |
|
106 list->elements[i]->accept(*this); |
|
107 currentTokenList.push_back(currentToken); |
|
108 } |
|
109 |
|
110 return NULL; |
|
111 } |
|
112 |
|
113 std::string derived_conversion_functions_c::getIntegerName(bool isSigned, size_t size) { |
|
114 std::string integerType = ""; |
|
115 if (! isSigned) { |
|
116 integerType = "U"; |
|
117 } |
|
118 switch(size) { |
|
119 case 8 : integerType += "S"; break; |
|
120 case 16: break; |
|
121 case 32: integerType += "D"; break; |
|
122 case 64: integerType += "L"; break; |
|
123 default: break; |
|
124 } |
|
125 integerType +="INT"; |
|
126 |
|
127 return integerType; |
|
128 } |
|
129 |
|
130 void derived_conversion_functions_c::printStringToEnum (std::string &enumerateName, std::list<std::string> &enumerateValues) { |
|
131 std::list <std::string>::const_iterator itr; |
|
132 std::string functionName; |
|
133 |
|
134 functionName = "STRING_TO_" + enumerateName; |
|
135 text += "FUNCTION " + functionName + " : " + enumerateName; |
|
136 text += "\nVAR_INPUT\nIN : STRING;\nEND_VAR\n"; |
|
137 for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) { |
|
138 std::string value = *itr; |
|
139 text += "IF IN = '" + value + "' THEN\n"; |
|
140 text += " " + functionName + " := " + value + ";\n"; |
|
141 text += " RETURN;\n"; |
|
142 text += "END_IF;\n"; |
|
143 } |
|
144 text += "END_FUNCTION\n\n"; |
|
145 } |
|
146 |
|
147 void derived_conversion_functions_c::printEnumToString (std::string &enumerateName, std::list<std::string> &enumerateValues) { |
|
148 std::list <std::string>::const_iterator itr; |
|
149 std::string functionName; |
|
150 |
|
151 functionName = enumerateName + "_TO_STRING"; |
|
152 text += "FUNCTION " + functionName + " : STRING"; |
|
153 text += "\nVAR_INPUT\nIN : " + enumerateName + ";\nEND_VAR\n"; |
|
154 for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) { |
|
155 std::string value = *itr; |
|
156 text += "IF IN = " + value + " THEN\n"; |
|
157 text += " " + functionName + " := '" + value + "';\n"; |
|
158 text += " RETURN;\n"; |
|
159 text += "END_IF;\n"; |
|
160 } |
|
161 text += "END_FUNCTION\n\n"; |
|
162 } |
|
163 |
|
164 void derived_conversion_functions_c::printIntegerToEnum (std::string &enumerateName, std::list<std::string> &enumerateValues, bool isSigned, size_t size) { |
|
165 std::list <std::string>::const_iterator itr; |
|
166 std::string functionName; |
|
167 std::string integerType; |
|
168 int count; |
|
169 |
|
170 integerType = getIntegerName(isSigned, size); |
|
171 functionName = integerType + "_TO_" + enumerateName; |
|
172 text += "FUNCTION " + functionName + " : " + enumerateName; |
|
173 text += "\nVAR_INPUT\nIN : " + integerType + ";\nEND_VAR\n"; |
|
174 count = 0; |
|
175 for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) { |
|
176 std::string value = *itr; |
|
177 std::stringstream out; |
|
178 out << count; |
|
179 text += "IF IN = " + out.str() + " THEN\n"; |
|
180 text += " " + functionName + " := " + value + ";\n"; |
|
181 text += " RETURN;\n"; |
|
182 text += "END_IF;\n"; |
|
183 count++; |
|
184 } |
|
185 text += "END_FUNCTION\n\n"; |
|
186 } |
|
187 |
|
188 void derived_conversion_functions_c::printEnumToInteger (std::string &enumerateName, std::list<std::string> &enumerateValues, bool isSigned, size_t size) { |
|
189 std::list <std::string>::const_iterator itr; |
|
190 std::string functionName; |
|
191 std::string integerType; |
|
192 int count; |
|
193 |
|
194 integerType = getIntegerName(isSigned, size); |
|
195 functionName = enumerateName + "_TO_" + integerType; |
|
196 text += "FUNCTION " + functionName + " : " + integerType; |
|
197 text += "\nVAR_INPUT\nIN : " + enumerateName + ";\nEND_VAR\n"; |
|
198 count = 0; |
|
199 for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) { |
|
200 std::string value = *itr; |
|
201 std::stringstream out; |
|
202 out << count; |
|
203 text += "IF IN = " + value + " THEN\n"; |
|
204 text += " " + functionName + " := " + out.str() + ";\n"; |
|
205 text += " RETURN;\n"; |
|
206 text += "END_IF;\n"; |
|
207 count++; |
|
208 } |
|
209 text += "END_FUNCTION\n\n"; |
|
210 } |
|
211 |
|
212 |
|
213 |
|