65 - The name |
69 - The name |
66 - The data type |
70 - The data type |
67 - The default modifier which can be "none", "negated", "rising" or "falling" |
71 - The default modifier which can be "none", "negated", "rising" or "falling" |
68 """ |
72 """ |
69 |
73 |
70 StdBlckLibs = {libname : LoadProject(tc6fname)[0] |
74 StdBlckLibs = {libname: LoadProject(tc6fname)[0] |
71 for libname, tc6fname in StdTC6Libs} |
75 for libname, tc6fname in StdTC6Libs} |
72 StdBlckLst = [{"name" : libname, "list": |
76 StdBlckLst = [{"name": libname, "list": |
73 [GetBlockInfos(pous) for pous in lib.getpous()]} |
77 [GetBlockInfos(pous) for pous in lib.getpous()]} |
74 for libname, lib in StdBlckLibs.iteritems()] |
78 for libname, lib in StdBlckLibs.iteritems()] |
75 |
79 |
76 #------------------------------------------------------------------------------- |
80 # ------------------------------------------------------------------------------- |
77 # Test identifier |
81 # Test identifier |
78 #------------------------------------------------------------------------------- |
82 # ------------------------------------------------------------------------------- |
79 |
83 |
80 IDENTIFIER_MODEL = re.compile( |
84 IDENTIFIER_MODEL = re.compile( |
81 "(?:%(letter)s|_(?:%(letter)s|%(digit)s))(?:_?(?:%(letter)s|%(digit)s))*$" % |
85 "(?:%(letter)s|_(?:%(letter)s|%(digit)s))(?:_?(?:%(letter)s|%(digit)s))*$" % |
82 {"letter": "[a-zA-Z]", "digit": "[0-9]"}) |
86 {"letter": "[a-zA-Z]", "digit": "[0-9]"}) |
83 |
87 |
84 # Test if identifier is valid |
88 |
85 def TestIdentifier(identifier): |
89 def TestIdentifier(identifier): |
86 return IDENTIFIER_MODEL.match(identifier) is not None |
90 """ |
87 |
91 Test if identifier is valid |
88 #------------------------------------------------------------------------------- |
92 """ |
|
93 return IDENTIFIER_MODEL.match(identifier) is not None |
|
94 |
|
95 # ------------------------------------------------------------------------------- |
89 # Standard functions list generation |
96 # Standard functions list generation |
90 #------------------------------------------------------------------------------- |
97 # ------------------------------------------------------------------------------- |
91 |
98 |
92 |
99 |
93 """ |
|
94 take a .csv file and translate it it a "csv_table" |
|
95 """ |
|
96 def csv_file_to_table(file): |
100 def csv_file_to_table(file): |
97 return [ map(string.strip,line.split(';')) for line in file.xreadlines()] |
101 """ |
98 |
102 take a .csv file and translate it it a "csv_table" |
99 """ |
103 """ |
100 seek into the csv table to a section ( section_name match 1st field ) |
104 return [map(string.strip, line.split(';')) for line in file.xreadlines()] |
101 return the matching row without first field |
105 |
102 """ |
106 |
103 def find_section(section_name, table): |
107 def find_section(section_name, table): |
|
108 """ |
|
109 seek into the csv table to a section ( section_name match 1st field ) |
|
110 return the matching row without first field |
|
111 """ |
104 fields = [None] |
112 fields = [None] |
105 while(fields[0] != section_name): |
113 while(fields[0] != section_name): |
106 fields = table.pop(0) |
114 fields = table.pop(0) |
107 return fields[1:] |
115 return fields[1:] |
108 |
116 |
109 """ |
117 |
110 extract the standard functions standard parameter names and types... |
|
111 return a { ParameterName: Type, ...} |
|
112 """ |
|
113 def get_standard_funtions_input_variables(table): |
118 def get_standard_funtions_input_variables(table): |
|
119 """ |
|
120 extract the standard functions standard parameter names and types... |
|
121 return a { ParameterName: Type, ...} |
|
122 """ |
114 variables = find_section("Standard_functions_variables_types", table) |
123 variables = find_section("Standard_functions_variables_types", table) |
115 standard_funtions_input_variables = {} |
124 standard_funtions_input_variables = {} |
116 fields = [True,True] |
125 fields = [True, True] |
117 while(fields[1]): |
126 while(fields[1]): |
118 fields = table.pop(0) |
127 fields = table.pop(0) |
119 variable_from_csv = dict([(champ, val) for champ, val in zip(variables, fields[1:]) if champ!='']) |
128 variable_from_csv = dict([(champ, val) for champ, val in zip(variables, fields[1:]) if champ != '']) |
120 standard_funtions_input_variables[variable_from_csv['name']] = variable_from_csv['type'] |
129 standard_funtions_input_variables[variable_from_csv['name']] = variable_from_csv['type'] |
121 return standard_funtions_input_variables |
130 return standard_funtions_input_variables |
122 |
131 |
123 """ |
132 |
124 translate .csv file input declaration into PLCOpenEditor interessting values |
|
125 in : "(ANY_NUM, ANY_NUM)" and { ParameterName: Type, ...} |
|
126 return [("IN1","ANY_NUM","none"),("IN2","ANY_NUM","none")] |
|
127 """ |
|
128 def csv_input_translate(str_decl, variables, base): |
133 def csv_input_translate(str_decl, variables, base): |
129 decl = str_decl.replace('(','').replace(')','').replace(' ','').split(',') |
134 """ |
|
135 translate .csv file input declaration into PLCOpenEditor interessting values |
|
136 in : "(ANY_NUM, ANY_NUM)" and { ParameterName: Type, ...} |
|
137 return [("IN1","ANY_NUM","none"),("IN2","ANY_NUM","none")] |
|
138 """ |
|
139 decl = str_decl.replace('(', '').replace(')', '').replace(' ', '').split(',') |
130 params = [] |
140 params = [] |
131 |
141 |
132 len_of_not_predifined_variable = len([True for param_type in decl if param_type not in variables]) |
142 len_of_not_predifined_variable = len([True for param_type in decl if param_type not in variables]) |
133 |
143 |
134 for param_type in decl: |
144 for param_type in decl: |
135 if param_type in variables.keys(): |
145 if param_type in variables.keys(): |
136 param_name = param_type |
146 param_name = param_type |
137 param_type = variables[param_type] |
147 param_type = variables[param_type] |
138 elif len_of_not_predifined_variable > 1: |
148 elif len_of_not_predifined_variable > 1: |
139 param_name = "IN%d"%base |
149 param_name = "IN%d" % base |
140 base += 1 |
150 base += 1 |
141 else: |
151 else: |
142 param_name = "IN" |
152 param_name = "IN" |
143 params.append((param_name, param_type, "none")) |
153 params.append((param_name, param_type, "none")) |
144 return params |
154 return params |
145 |
155 |
146 |
156 |
147 """ |
157 def get_standard_funtions(table): |
148 Returns this kind of declaration for all standard functions |
158 """ |
149 |
159 Returns this kind of declaration for all standard functions |
150 [{"name" : "Numerical", 'list': [ { |
160 |
|
161 [{"name" : "Numerical", 'list': [ { |
151 'baseinputnumber': 1, |
162 'baseinputnumber': 1, |
152 'comment': 'Addition', |
163 'comment': 'Addition', |
153 'extensible': True, |
164 'extensible': True, |
154 'inputs': [ ('IN1', 'ANY_NUM', 'none'), |
165 'inputs': [ ('IN1', 'ANY_NUM', 'none'), |
155 ('IN2', 'ANY_NUM', 'none')], |
166 ('IN2', 'ANY_NUM', 'none')], |
156 'name': 'ADD', |
167 'name': 'ADD', |
157 'outputs': [('OUT', 'ANY_NUM', 'none')], |
168 'outputs': [('OUT', 'ANY_NUM', 'none')], |
158 'type': 'function'}, ...... ] },.....] |
169 'type': 'function'}, ...... ] },.....] |
159 """ |
170 """ |
160 def get_standard_funtions(table): |
171 |
161 |
|
162 variables = get_standard_funtions_input_variables(table) |
172 variables = get_standard_funtions_input_variables(table) |
163 |
173 |
164 fonctions = find_section("Standard_functions_type",table) |
174 fonctions = find_section("Standard_functions_type", table) |
165 |
175 |
166 Standard_Functions_Decl = [] |
176 Standard_Functions_Decl = [] |
167 Current_section = None |
177 Current_section = None |
168 |
178 |
169 translate = { |
179 translate = { |
170 "extensible" : lambda x: {"yes":True, "no":False}[x], |
180 "extensible": lambda x: {"yes": True, "no": False}[x], |
171 "inputs" : lambda x:csv_input_translate(x,variables,baseinputnumber), |
181 "inputs": lambda x: csv_input_translate(x, variables, baseinputnumber), |
172 "outputs":lambda x:[("OUT",x,"none")]} |
182 "outputs": lambda x: [("OUT", x, "none")]} |
173 |
183 |
174 for fields in table: |
184 for fields in table: |
175 if fields[1]: |
185 if fields[1]: |
176 # If function section name given |
186 # If function section name given |
177 if fields[0]: |
187 if fields[0]: |
178 words = fields[0].split('"') |
188 words = fields[0].split('"') |
179 if len(words) > 1: |
189 if len(words) > 1: |
180 section_name = words[1] |
190 section_name = words[1] |
181 else: |
191 else: |
182 section_name = fields[0] |
192 section_name = fields[0] |
183 Current_section = {"name" : section_name, "list" : []} |
193 Current_section = {"name": section_name, "list": []} |
184 Standard_Functions_Decl.append(Current_section) |
194 Standard_Functions_Decl.append(Current_section) |
185 Function_decl_list = [] |
195 Function_decl_list = [] |
186 if Current_section: |
196 if Current_section: |
187 Function_decl = dict([(champ, val) for champ, val in zip(fonctions, fields[1:]) if champ]) |
197 Function_decl = dict([(champ, val) for champ, val in zip(fonctions, fields[1:]) if champ]) |
188 baseinputnumber = int(Function_decl.get("baseinputnumber",1)) |
198 baseinputnumber = int(Function_decl.get("baseinputnumber", 1)) |
189 Function_decl["baseinputnumber"] = baseinputnumber |
199 Function_decl["baseinputnumber"] = baseinputnumber |
190 for param, value in Function_decl.iteritems(): |
200 for param, value in Function_decl.iteritems(): |
191 if param in translate: |
201 if param in translate: |
192 Function_decl[param] = translate[param](value) |
202 Function_decl[param] = translate[param](value) |
193 Function_decl["type"] = "function" |
203 Function_decl["type"] = "function" |
194 |
204 |
195 if Function_decl["name"].startswith('*') or Function_decl["name"].endswith('*') : |
205 if Function_decl["name"].startswith('*') or Function_decl["name"].endswith('*'): |
196 input_ovrloading_types = GetSubTypes(Function_decl["inputs"][0][1]) |
206 input_ovrloading_types = GetSubTypes(Function_decl["inputs"][0][1]) |
197 output_types = GetSubTypes(Function_decl["outputs"][0][1]) |
207 output_types = GetSubTypes(Function_decl["outputs"][0][1]) |
198 else: |
208 else: |
199 input_ovrloading_types = [None] |
209 input_ovrloading_types = [None] |
200 output_types = [None] |
210 output_types = [None] |
201 |
211 |
202 funcdeclname_orig = Function_decl["name"] |
212 funcdeclname_orig = Function_decl["name"] |
203 funcdeclname = Function_decl["name"].strip('*_') |
213 funcdeclname = Function_decl["name"].strip('*_') |
204 fdc = Function_decl["inputs"][:] |
214 fdc = Function_decl["inputs"][:] |
205 for intype in input_ovrloading_types: |
215 for intype in input_ovrloading_types: |
206 if intype != None: |
216 if intype is not None: |
207 Function_decl["inputs"] = [] |
217 Function_decl["inputs"] = [] |
208 for decl_tpl in fdc: |
218 for decl_tpl in fdc: |
209 if IsOfType(intype, decl_tpl[1]): |
219 if IsOfType(intype, decl_tpl[1]): |
210 Function_decl["inputs"] += [(decl_tpl[0], intype, decl_tpl[2])] |
220 Function_decl["inputs"] += [(decl_tpl[0], intype, decl_tpl[2])] |
211 else: |
221 else: |
212 Function_decl["inputs"] += [(decl_tpl)] |
222 Function_decl["inputs"] += [(decl_tpl)] |
213 |
223 |
214 if funcdeclname_orig.startswith('*'): |
224 if funcdeclname_orig.startswith('*'): |
215 funcdeclin = intype + '_' + funcdeclname |
225 funcdeclin = intype + '_' + funcdeclname |
216 else: |
226 else: |
217 funcdeclin = funcdeclname |
227 funcdeclin = funcdeclname |
218 else: |
228 else: |
219 funcdeclin = funcdeclname |
229 funcdeclin = funcdeclname |
220 |
230 |
221 for outype in output_types: |
231 for outype in output_types: |
222 if outype != None: |
232 if outype is not None: |
223 decl_tpl = Function_decl["outputs"][0] |
233 decl_tpl = Function_decl["outputs"][0] |
224 Function_decl["outputs"] = [ (decl_tpl[0] , outype, decl_tpl[2])] |
234 Function_decl["outputs"] = [(decl_tpl[0], outype, decl_tpl[2])] |
225 if funcdeclname_orig.endswith('*'): |
235 if funcdeclname_orig.endswith('*'): |
226 funcdeclout = funcdeclin + '_' + outype |
236 funcdeclout = funcdeclin + '_' + outype |
227 else: |
237 else: |
228 funcdeclout = funcdeclin |
238 funcdeclout = funcdeclin |
229 else: |
239 else: |
230 funcdeclout = funcdeclin |
240 funcdeclout = funcdeclin |
231 Function_decl["name"] = funcdeclout |
241 Function_decl["name"] = funcdeclout |
232 |
242 |
233 # apply filter given in "filter" column |
243 # apply filter given in "filter" column |
234 filter_name = Function_decl["filter"] |
244 filter_name = Function_decl["filter"] |
235 store = True |
245 store = True |
236 for (InTypes, OutTypes) in ANY_TO_ANY_FILTERS.get(filter_name,[]): |
246 for (InTypes, OutTypes) in ANY_TO_ANY_FILTERS.get(filter_name, []): |
237 outs = reduce(lambda a,b: a or b, |
247 outs = reduce(lambda a, b: a or b, |
238 map(lambda testtype : IsOfType( |
248 map(lambda testtype: IsOfType( |
239 Function_decl["outputs"][0][1], |
249 Function_decl["outputs"][0][1], |
240 testtype), OutTypes)) |
250 testtype), OutTypes)) |
241 inps = reduce(lambda a,b: a or b, |
251 inps = reduce(lambda a, b: a or b, |
242 map(lambda testtype : IsOfType( |
252 map(lambda testtype: IsOfType( |
243 Function_decl["inputs"][0][1], |
253 Function_decl["inputs"][0][1], |
244 testtype), InTypes)) |
254 testtype), InTypes)) |
245 if inps and outs and Function_decl["outputs"][0][1] != Function_decl["inputs"][0][1]: |
255 if inps and outs and Function_decl["outputs"][0][1] != Function_decl["inputs"][0][1]: |
246 store = True |
256 store = True |
247 break |
257 break |
248 else: |
258 else: |
249 store = False |
259 store = False |
250 if store : |
260 if store: |
251 # create the copy of decl dict to be appended to section |
261 # create the copy of decl dict to be appended to section |
252 Function_decl_copy = Function_decl.copy() |
262 Function_decl_copy = Function_decl.copy() |
253 Current_section["list"].append(Function_decl_copy) |
263 Current_section["list"].append(Function_decl_copy) |
254 else: |
264 else: |
255 raise "First function must be in a category" |
265 raise "First function must be in a category" |
256 |
266 |
257 return Standard_Functions_Decl |
267 return Standard_Functions_Decl |
|
268 |
258 |
269 |
259 StdBlckLst.extend(get_standard_funtions(csv_file_to_table(open(StdFuncsCSV)))) |
270 StdBlckLst.extend(get_standard_funtions(csv_file_to_table(open(StdFuncsCSV)))) |
260 |
271 |
261 # Dictionary to speedup block type fetching by name |
272 # Dictionary to speedup block type fetching by name |
262 StdBlckDct = OrderedDict() |
273 StdBlckDct = OrderedDict() |
311 SFC_BLOCK_END_KEYWORDS = ["END_ACTION", "END_STEP", "END_TRANSITION"] |
322 SFC_BLOCK_END_KEYWORDS = ["END_ACTION", "END_STEP", "END_TRANSITION"] |
312 SFC_KEYWORDS = ["FROM", "TO"] + SFC_BLOCK_START_KEYWORDS + SFC_BLOCK_END_KEYWORDS |
323 SFC_KEYWORDS = ["FROM", "TO"] + SFC_BLOCK_START_KEYWORDS + SFC_BLOCK_END_KEYWORDS |
313 |
324 |
314 |
325 |
315 # Keywords for Instruction List |
326 # Keywords for Instruction List |
316 IL_KEYWORDS = ["TRUE", "FALSE", "LD", "LDN", "ST", "STN", "S", "R", "AND", "ANDN", "OR", "ORN", |
327 IL_KEYWORDS = [ |
317 "XOR", "XORN", "NOT", "ADD", "SUB", "MUL", "DIV", "MOD", "GT", "GE", "EQ", "NE", |
328 "TRUE", "FALSE", "LD", "LDN", "ST", "STN", "S", "R", "AND", "ANDN", "OR", "ORN", |
318 "LE", "LT", "JMP", "JMPC", "JMPCN", "CAL", "CALC", "CALCN", "RET", "RETC", "RETCN"] |
329 "XOR", "XORN", "NOT", "ADD", "SUB", "MUL", "DIV", "MOD", "GT", "GE", "EQ", "NE", |
|
330 "LE", "LT", "JMP", "JMPC", "JMPCN", "CAL", "CALC", "CALCN", "RET", "RETC", "RETCN" |
|
331 ] |
319 |
332 |
320 |
333 |
321 # Keywords for Structured Text |
334 # Keywords for Structured Text |
322 ST_BLOCK_START_KEYWORDS = ["IF", "ELSIF", "ELSE", "CASE", "FOR", "WHILE", "REPEAT"] |
335 ST_BLOCK_START_KEYWORDS = ["IF", "ELSIF", "ELSE", "CASE", "FOR", "WHILE", "REPEAT"] |
323 ST_BLOCK_END_KEYWORDS = ["END_IF", "END_CASE", "END_FOR", "END_WHILE", "END_REPEAT"] |
336 ST_BLOCK_END_KEYWORDS = ["END_IF", "END_CASE", "END_FOR", "END_WHILE", "END_REPEAT"] |
324 ST_KEYWORDS = ["TRUE", "FALSE", "THEN", "OF", "TO", "BY", "DO", "DO", "UNTIL", "EXIT", |
337 ST_KEYWORDS = [ |
325 "RETURN", "NOT", "MOD", "AND", "XOR", "OR"] + ST_BLOCK_START_KEYWORDS + ST_BLOCK_END_KEYWORDS |
338 "TRUE", "FALSE", "THEN", "OF", "TO", "BY", "DO", "DO", "UNTIL", "EXIT", |
|
339 "RETURN", "NOT", "MOD", "AND", "XOR", "OR" |
|
340 ] + ST_BLOCK_START_KEYWORDS + ST_BLOCK_END_KEYWORDS |
326 |
341 |
327 # All the keywords of IEC |
342 # All the keywords of IEC |
328 IEC_BLOCK_START_KEYWORDS = [] |
343 IEC_BLOCK_START_KEYWORDS = [] |
329 IEC_BLOCK_END_KEYWORDS = [] |
344 IEC_BLOCK_END_KEYWORDS = [] |
330 IEC_KEYWORDS = ["E", "TRUE", "FALSE"] |
345 IEC_KEYWORDS = ["E", "TRUE", "FALSE"] |