plcopen/structures.py
changeset 1784 64beb9e9c749
parent 1782 5b6ad7a7fd9d
child 1828 396da88d7b5c
equal deleted inserted replaced
1729:31e63e25b4cc 1784:64beb9e9c749
    20 #
    20 #
    21 # You should have received a copy of the GNU General Public License
    21 # You should have received a copy of the GNU General Public License
    22 # along with this program; if not, write to the Free Software
    22 # along with this program; if not, write to the Free Software
    23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    24 
    24 
    25 import string, re
    25 import string
       
    26 import re
    26 from plcopen import LoadProject
    27 from plcopen import LoadProject
    27 from collections import OrderedDict
    28 from collections import OrderedDict
    28 from definitions import *
    29 from definitions import *
    29 
    30 
    30 TypeHierarchy = dict(TypeHierarchy_list)
    31 TypeHierarchy = dict(TypeHierarchy_list)
    31 
    32 
    32 """
    33 
    33 returns true if the given data type is the same that "reference" meta-type or one of its types.
       
    34 """
       
    35 def IsOfType(type, reference):
    34 def IsOfType(type, reference):
       
    35     """
       
    36     Returns true if the given data type is the same that "reference" meta-type or one of its types.
       
    37     """
    36     if reference is None:
    38     if reference is None:
    37         return True
    39         return True
    38     elif type == reference:
    40     elif type == reference:
    39         return True
    41         return True
    40     else:
    42     else:
    41         parent_type = TypeHierarchy[type]
    43         parent_type = TypeHierarchy[type]
    42         if parent_type is not None:
    44         if parent_type is not None:
    43             return IsOfType(parent_type, reference)
    45             return IsOfType(parent_type, reference)
    44     return False
    46     return False
    45 
    47 
    46 """
    48 
    47 returns list of all types that correspont to the ANY* meta type
       
    48 """
       
    49 def GetSubTypes(type):
    49 def GetSubTypes(type):
       
    50     """
       
    51     Returns list of all types that correspont to the ANY* meta type
       
    52     """
    50     return [typename for typename, parenttype in TypeHierarchy.items() if not typename.startswith("ANY") and IsOfType(typename, type)]
    53     return [typename for typename, parenttype in TypeHierarchy.items() if not typename.startswith("ANY") and IsOfType(typename, type)]
       
    54 
    51 
    55 
    52 DataTypeRange = dict(DataTypeRange_list)
    56 DataTypeRange = dict(DataTypeRange_list)
    53 
    57 
    54 """
    58 """
    55 Ordered list of common Function Blocks defined in the IEC 61131-3
    59 Ordered list of common Function Blocks defined in the IEC 61131-3
    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()
   264 for section in StdBlckLst:
   275 for section in StdBlckLst:
   265     for desc in section["list"]:
   276     for desc in section["list"]:
   266         words = desc["comment"].split('"')
   277         words = desc["comment"].split('"')
   267         if len(words) > 1:
   278         if len(words) > 1:
   268             desc["comment"] = words[1]
   279             desc["comment"] = words[1]
   269         desc["usage"] = ("\n (%s) => (%s)" % 
   280         desc["usage"] = ("\n (%s) => (%s)" %
   270             (", ".join(["%s:%s" % (input[1], input[0]) 
   281                          (", ".join(["%s:%s" % (input[1], input[0])
   271                         for input in desc["inputs"]]),
   282                                      for input in desc["inputs"]]),
   272              ", ".join(["%s:%s" % (output[1], output[0]) 
   283                           ", ".join(["%s:%s" % (output[1], output[0])
   273                         for output in desc["outputs"]])))
   284                                      for output in desc["outputs"]])))
   274         BlkLst = StdBlckDct.setdefault(desc["name"],[])
   285         BlkLst = StdBlckDct.setdefault(desc["name"], [])
   275         BlkLst.append((section["name"], desc))
   286         BlkLst.append((section["name"], desc))
   276 
   287 
   277 #-------------------------------------------------------------------------------
   288 # -------------------------------------------------------------------------------
   278 #                            Languages Keywords
   289 #                            Languages Keywords
   279 #-------------------------------------------------------------------------------
   290 # -------------------------------------------------------------------------------
   280 
   291 
   281 # Keywords for Pou Declaration
   292 # Keywords for Pou Declaration
   282 POU_BLOCK_START_KEYWORDS = ["FUNCTION", "FUNCTION_BLOCK", "PROGRAM"]
   293 POU_BLOCK_START_KEYWORDS = ["FUNCTION", "FUNCTION_BLOCK", "PROGRAM"]
   283 POU_BLOCK_END_KEYWORDS = ["END_FUNCTION", "END_FUNCTION_BLOCK", "END_PROGRAM"]
   294 POU_BLOCK_END_KEYWORDS = ["END_FUNCTION", "END_FUNCTION_BLOCK", "END_PROGRAM"]
   284 POU_KEYWORDS = ["EN", "ENO", "F_EDGE", "R_EDGE"] + POU_BLOCK_START_KEYWORDS + POU_BLOCK_END_KEYWORDS
   295 POU_KEYWORDS = ["EN", "ENO", "F_EDGE", "R_EDGE"] + POU_BLOCK_START_KEYWORDS + POU_BLOCK_END_KEYWORDS
   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"]
   336                                                               SFC_BLOCK_END_KEYWORDS, ST_BLOCK_END_KEYWORDS]),
   351                                                               SFC_BLOCK_END_KEYWORDS, ST_BLOCK_END_KEYWORDS]),
   337                                     (IEC_KEYWORDS, [POU_KEYWORDS, TYPE_KEYWORDS, VAR_KEYWORDS, CONFIG_KEYWORDS,
   352                                     (IEC_KEYWORDS, [POU_KEYWORDS, TYPE_KEYWORDS, VAR_KEYWORDS, CONFIG_KEYWORDS,
   338                                                     SFC_KEYWORDS, IL_KEYWORDS, ST_KEYWORDS])]:
   353                                                     SFC_KEYWORDS, IL_KEYWORDS, ST_KEYWORDS])]:
   339     for keywords in keywords_list:
   354     for keywords in keywords_list:
   340         all_keywords.extend([keyword for keyword in keywords if keyword not in all_keywords])
   355         all_keywords.extend([keyword for keyword in keywords if keyword not in all_keywords])
   341 
       
   342