diff -r 31e63e25b4cc -r 64beb9e9c749 plcopen/structures.py --- a/plcopen/structures.py Mon Aug 21 20:17:19 2017 +0000 +++ b/plcopen/structures.py Mon Aug 21 23:22:58 2017 +0300 @@ -22,17 +22,19 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -import string, re +import string +import re from plcopen import LoadProject from collections import OrderedDict from definitions import * TypeHierarchy = dict(TypeHierarchy_list) -""" -returns true if the given data type is the same that "reference" meta-type or one of its types. -""" + def IsOfType(type, reference): + """ + Returns true if the given data type is the same that "reference" meta-type or one of its types. + """ if reference is None: return True elif type == reference: @@ -43,12 +45,14 @@ return IsOfType(parent_type, reference) return False -""" -returns list of all types that correspont to the ANY* meta type -""" + def GetSubTypes(type): + """ + Returns list of all types that correspont to the ANY* meta type + """ return [typename for typename, parenttype in TypeHierarchy.items() if not typename.startswith("ANY") and IsOfType(typename, type)] + DataTypeRange = dict(DataTypeRange_list) """ @@ -67,76 +71,82 @@ - The default modifier which can be "none", "negated", "rising" or "falling" """ -StdBlckLibs = {libname : LoadProject(tc6fname)[0] - for libname, tc6fname in StdTC6Libs} -StdBlckLst = [{"name" : libname, "list": +StdBlckLibs = {libname: LoadProject(tc6fname)[0] + for libname, tc6fname in StdTC6Libs} +StdBlckLst = [{"name": libname, "list": [GetBlockInfos(pous) for pous in lib.getpous()]} - for libname, lib in StdBlckLibs.iteritems()] - -#------------------------------------------------------------------------------- + for libname, lib in StdBlckLibs.iteritems()] + +# ------------------------------------------------------------------------------- # Test identifier -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- IDENTIFIER_MODEL = re.compile( "(?:%(letter)s|_(?:%(letter)s|%(digit)s))(?:_?(?:%(letter)s|%(digit)s))*$" % {"letter": "[a-zA-Z]", "digit": "[0-9]"}) -# Test if identifier is valid + def TestIdentifier(identifier): - return IDENTIFIER_MODEL.match(identifier) is not None - -#------------------------------------------------------------------------------- + """ + Test if identifier is valid + """ + return IDENTIFIER_MODEL.match(identifier) is not None + +# ------------------------------------------------------------------------------- # Standard functions list generation -#------------------------------------------------------------------------------- - - -""" -take a .csv file and translate it it a "csv_table" -""" +# ------------------------------------------------------------------------------- + + def csv_file_to_table(file): - return [ map(string.strip,line.split(';')) for line in file.xreadlines()] - -""" -seek into the csv table to a section ( section_name match 1st field ) -return the matching row without first field -""" + """ + take a .csv file and translate it it a "csv_table" + """ + return [map(string.strip, line.split(';')) for line in file.xreadlines()] + + def find_section(section_name, table): + """ + seek into the csv table to a section ( section_name match 1st field ) + return the matching row without first field + """ fields = [None] while(fields[0] != section_name): fields = table.pop(0) return fields[1:] -""" -extract the standard functions standard parameter names and types... -return a { ParameterName: Type, ...} -""" + def get_standard_funtions_input_variables(table): + """ + extract the standard functions standard parameter names and types... + return a { ParameterName: Type, ...} + """ variables = find_section("Standard_functions_variables_types", table) standard_funtions_input_variables = {} - fields = [True,True] + fields = [True, True] while(fields[1]): fields = table.pop(0) - variable_from_csv = dict([(champ, val) for champ, val in zip(variables, fields[1:]) if champ!='']) + variable_from_csv = dict([(champ, val) for champ, val in zip(variables, fields[1:]) if champ != '']) standard_funtions_input_variables[variable_from_csv['name']] = variable_from_csv['type'] return standard_funtions_input_variables - -""" -translate .csv file input declaration into PLCOpenEditor interessting values -in : "(ANY_NUM, ANY_NUM)" and { ParameterName: Type, ...} -return [("IN1","ANY_NUM","none"),("IN2","ANY_NUM","none")] -""" + + def csv_input_translate(str_decl, variables, base): - decl = str_decl.replace('(','').replace(')','').replace(' ','').split(',') + """ + translate .csv file input declaration into PLCOpenEditor interessting values + in : "(ANY_NUM, ANY_NUM)" and { ParameterName: Type, ...} + return [("IN1","ANY_NUM","none"),("IN2","ANY_NUM","none")] + """ + decl = str_decl.replace('(', '').replace(')', '').replace(' ', '').split(',') params = [] - + len_of_not_predifined_variable = len([True for param_type in decl if param_type not in variables]) - + for param_type in decl: if param_type in variables.keys(): param_name = param_type param_type = variables[param_type] elif len_of_not_predifined_variable > 1: - param_name = "IN%d"%base + param_name = "IN%d" % base base += 1 else: param_name = "IN" @@ -144,10 +154,11 @@ return params -""" -Returns this kind of declaration for all standard functions - - [{"name" : "Numerical", 'list': [ { +def get_standard_funtions(table): + """ + Returns this kind of declaration for all standard functions + + [{"name" : "Numerical", 'list': [ { 'baseinputnumber': 1, 'comment': 'Addition', 'extensible': True, @@ -156,21 +167,20 @@ 'name': 'ADD', 'outputs': [('OUT', 'ANY_NUM', 'none')], 'type': 'function'}, ...... ] },.....] -""" -def get_standard_funtions(table): - + """ + variables = get_standard_funtions_input_variables(table) - - fonctions = find_section("Standard_functions_type",table) + + fonctions = find_section("Standard_functions_type", table) Standard_Functions_Decl = [] Current_section = None - + translate = { - "extensible" : lambda x: {"yes":True, "no":False}[x], - "inputs" : lambda x:csv_input_translate(x,variables,baseinputnumber), - "outputs":lambda x:[("OUT",x,"none")]} - + "extensible": lambda x: {"yes": True, "no": False}[x], + "inputs": lambda x: csv_input_translate(x, variables, baseinputnumber), + "outputs": lambda x: [("OUT", x, "none")]} + for fields in table: if fields[1]: # If function section name given @@ -180,82 +190,83 @@ section_name = words[1] else: section_name = fields[0] - Current_section = {"name" : section_name, "list" : []} + Current_section = {"name": section_name, "list": []} Standard_Functions_Decl.append(Current_section) Function_decl_list = [] if Current_section: Function_decl = dict([(champ, val) for champ, val in zip(fonctions, fields[1:]) if champ]) - baseinputnumber = int(Function_decl.get("baseinputnumber",1)) + baseinputnumber = int(Function_decl.get("baseinputnumber", 1)) Function_decl["baseinputnumber"] = baseinputnumber for param, value in Function_decl.iteritems(): if param in translate: Function_decl[param] = translate[param](value) Function_decl["type"] = "function" - - if Function_decl["name"].startswith('*') or Function_decl["name"].endswith('*') : + + if Function_decl["name"].startswith('*') or Function_decl["name"].endswith('*'): input_ovrloading_types = GetSubTypes(Function_decl["inputs"][0][1]) output_types = GetSubTypes(Function_decl["outputs"][0][1]) else: input_ovrloading_types = [None] output_types = [None] - + funcdeclname_orig = Function_decl["name"] funcdeclname = Function_decl["name"].strip('*_') fdc = Function_decl["inputs"][:] for intype in input_ovrloading_types: - if intype != None: + if intype is not None: Function_decl["inputs"] = [] for decl_tpl in fdc: if IsOfType(intype, decl_tpl[1]): Function_decl["inputs"] += [(decl_tpl[0], intype, decl_tpl[2])] else: Function_decl["inputs"] += [(decl_tpl)] - + if funcdeclname_orig.startswith('*'): - funcdeclin = intype + '_' + funcdeclname + funcdeclin = intype + '_' + funcdeclname else: funcdeclin = funcdeclname else: funcdeclin = funcdeclname - + for outype in output_types: - if outype != None: + if outype is not None: decl_tpl = Function_decl["outputs"][0] - Function_decl["outputs"] = [ (decl_tpl[0] , outype, decl_tpl[2])] + Function_decl["outputs"] = [(decl_tpl[0], outype, decl_tpl[2])] if funcdeclname_orig.endswith('*'): - funcdeclout = funcdeclin + '_' + outype + funcdeclout = funcdeclin + '_' + outype else: - funcdeclout = funcdeclin + funcdeclout = funcdeclin else: - funcdeclout = funcdeclin + funcdeclout = funcdeclin Function_decl["name"] = funcdeclout # apply filter given in "filter" column filter_name = Function_decl["filter"] store = True - for (InTypes, OutTypes) in ANY_TO_ANY_FILTERS.get(filter_name,[]): - outs = reduce(lambda a,b: a or b, - map(lambda testtype : IsOfType( - Function_decl["outputs"][0][1], - testtype), OutTypes)) - inps = reduce(lambda a,b: a or b, - map(lambda testtype : IsOfType( - Function_decl["inputs"][0][1], - testtype), InTypes)) + for (InTypes, OutTypes) in ANY_TO_ANY_FILTERS.get(filter_name, []): + outs = reduce(lambda a, b: a or b, + map(lambda testtype: IsOfType( + Function_decl["outputs"][0][1], + testtype), OutTypes)) + inps = reduce(lambda a, b: a or b, + map(lambda testtype: IsOfType( + Function_decl["inputs"][0][1], + testtype), InTypes)) if inps and outs and Function_decl["outputs"][0][1] != Function_decl["inputs"][0][1]: store = True break else: store = False - if store : + if store: # create the copy of decl dict to be appended to section Function_decl_copy = Function_decl.copy() Current_section["list"].append(Function_decl_copy) else: raise "First function must be in a category" - + return Standard_Functions_Decl + StdBlckLst.extend(get_standard_funtions(csv_file_to_table(open(StdFuncsCSV)))) # Dictionary to speedup block type fetching by name @@ -266,17 +277,17 @@ words = desc["comment"].split('"') if len(words) > 1: desc["comment"] = words[1] - desc["usage"] = ("\n (%s) => (%s)" % - (", ".join(["%s:%s" % (input[1], input[0]) - for input in desc["inputs"]]), - ", ".join(["%s:%s" % (output[1], output[0]) - for output in desc["outputs"]]))) - BlkLst = StdBlckDct.setdefault(desc["name"],[]) + desc["usage"] = ("\n (%s) => (%s)" % + (", ".join(["%s:%s" % (input[1], input[0]) + for input in desc["inputs"]]), + ", ".join(["%s:%s" % (output[1], output[0]) + for output in desc["outputs"]]))) + BlkLst = StdBlckDct.setdefault(desc["name"], []) BlkLst.append((section["name"], desc)) -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- # Languages Keywords -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- # Keywords for Pou Declaration POU_BLOCK_START_KEYWORDS = ["FUNCTION", "FUNCTION_BLOCK", "PROGRAM"] @@ -313,16 +324,20 @@ # Keywords for Instruction List -IL_KEYWORDS = ["TRUE", "FALSE", "LD", "LDN", "ST", "STN", "S", "R", "AND", "ANDN", "OR", "ORN", - "XOR", "XORN", "NOT", "ADD", "SUB", "MUL", "DIV", "MOD", "GT", "GE", "EQ", "NE", - "LE", "LT", "JMP", "JMPC", "JMPCN", "CAL", "CALC", "CALCN", "RET", "RETC", "RETCN"] +IL_KEYWORDS = [ + "TRUE", "FALSE", "LD", "LDN", "ST", "STN", "S", "R", "AND", "ANDN", "OR", "ORN", + "XOR", "XORN", "NOT", "ADD", "SUB", "MUL", "DIV", "MOD", "GT", "GE", "EQ", "NE", + "LE", "LT", "JMP", "JMPC", "JMPCN", "CAL", "CALC", "CALCN", "RET", "RETC", "RETCN" +] # Keywords for Structured Text ST_BLOCK_START_KEYWORDS = ["IF", "ELSIF", "ELSE", "CASE", "FOR", "WHILE", "REPEAT"] ST_BLOCK_END_KEYWORDS = ["END_IF", "END_CASE", "END_FOR", "END_WHILE", "END_REPEAT"] -ST_KEYWORDS = ["TRUE", "FALSE", "THEN", "OF", "TO", "BY", "DO", "DO", "UNTIL", "EXIT", - "RETURN", "NOT", "MOD", "AND", "XOR", "OR"] + ST_BLOCK_START_KEYWORDS + ST_BLOCK_END_KEYWORDS +ST_KEYWORDS = [ + "TRUE", "FALSE", "THEN", "OF", "TO", "BY", "DO", "DO", "UNTIL", "EXIT", + "RETURN", "NOT", "MOD", "AND", "XOR", "OR" +] + ST_BLOCK_START_KEYWORDS + ST_BLOCK_END_KEYWORDS # All the keywords of IEC IEC_BLOCK_START_KEYWORDS = [] @@ -338,5 +353,3 @@ SFC_KEYWORDS, IL_KEYWORDS, ST_KEYWORDS])]: for keywords in keywords_list: all_keywords.extend([keyword for keyword in keywords if keyword not in all_keywords]) - -