Adding support for coloring following elements:
authorlaurent
Wed, 08 Jun 2011 18:44:25 +0200
changeset 543 2f660878c2a7
parent 542 cce4903be769
child 544 ad4dd01c3c35
Adding support for coloring following elements:
- STRING constants
- Data type in typed literals
- Function and functionBlock parameter names
TextViewer.py
--- a/TextViewer.py	Wed Jun 08 18:35:28 2011 +0200
+++ b/TextViewer.py	Wed Jun 08 18:44:25 2011 +0200
@@ -40,9 +40,9 @@
     LETTERS.append(chr(ord('a') + i))
     LETTERS.append(chr(ord('A') + i))
 
-[STC_PLC_WORD, STC_PLC_COMMENT, STC_PLC_NUMBER, STC_PLC_VARIABLE, 
- STC_PLC_FUNCTION, STC_PLC_JUMP, STC_PLC_ERROR] = range(7)
-[SPACE, WORD, NUMBER, COMMENT] = range(4)
+[STC_PLC_WORD, STC_PLC_COMMENT, STC_PLC_NUMBER, STC_PLC_STRING, 
+ STC_PLC_VARIABLE, STC_PLC_FUNCTION, STC_PLC_JUMP, STC_PLC_ERROR] = range(8)
+[SPACE, WORD, NUMBER, STRING, WSTRING, COMMENT] = range(6)
 
 [ID_TEXTVIEWER,
 ] = [wx.NewId() for _init_ctrls in range(1)]
@@ -67,6 +67,7 @@
 re_texts["identifier"] = "((?:%(letter)s|(?:_(?:%(letter)s|%(digit)s)))(?:_?(?:%(letter)s|%(digit)s))*)"%re_texts
 IDENTIFIER_MODEL = re.compile(re_texts["identifier"])
 LABEL_MODEL = re.compile("[ \t\n]%(identifier)s:[ \t\n]"%re_texts)
+EXTENSIBLE_PARAMETER = re.compile("IN[1-9][0-9]*$")
 
 def GetCursorPos(old, new):
     old_length = len(old)
@@ -122,6 +123,7 @@
         self.StyleSetSpec(STC_PLC_FUNCTION, "fore:#7F7F00,size:%(size)d" % faces)
         self.StyleSetSpec(STC_PLC_COMMENT, "fore:#7F7F7F,size:%(size)d" % faces)
         self.StyleSetSpec(STC_PLC_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
+        self.StyleSetSpec(STC_PLC_STRING, "fore:#7F007F,size:%(size)d" % faces)
         self.StyleSetSpec(STC_PLC_JUMP, "fore:#007F00,size:%(size)d" % faces)
         self.StyleSetSpec(STC_PLC_ERROR, "fore:#FF0000,back:#FFFF00,size:%(size)d" % faces)
         
@@ -142,7 +144,8 @@
         
         self.Keywords = []
         self.Variables = {}
-        self.Functions = []
+        self.Functions = {}
+        self.TypeNames = []
         self.Jumps = []
         self.EnumeratedValues = []
         self.DisableEvents = True
@@ -153,6 +156,7 @@
         self.Debug = debug
         self.InstancePath = instancepath
         self.StructElementsStack = []
+        self.FunctionCallStack = []
         
         self.ParentWindow = window
         self.Controler = controler
@@ -286,8 +290,9 @@
         self.Colourise(0, -1)
     
     def RefreshJumpList(self):
-        self.Jumps = [jump.upper() for jump in LABEL_MODEL.findall(self.GetText())]
-        self.Colourise(0, -1)
+        if self.TextSyntax != "IL":
+            self.Jumps = [jump.upper() for jump in LABEL_MODEL.findall(self.GetText())]
+            self.Colourise(0, -1)
     
     # Buffer the last model state
     def RefreshBuffer(self):
@@ -328,15 +333,25 @@
         
         self.RefreshVariableTree()
         
-        self.Functions = []
+        self.TypeNames = [typename.upper() for typename in self.Controler.GetDataTypes(self.TagName, True, self.Debug)]
+        self.EnumeratedValues = [value.upper() for value in self.Controler.GetEnumeratedDataValues()]
+        
+        self.Functions = {}
         for category in self.Controler.GetBlockTypes(self.TagName, self.Debug):
             for blocktype in category["list"]:
                 if blocktype["type"] == "function" and blocktype["name"] not in self.Keywords and blocktype["name"] not in self.Variables.keys():
-                    self.Functions.append(blocktype["name"].upper())
-        
-        self.EnumeratedValues = []
-        for value in self.Controler.GetEnumeratedDataValues():
-            self.EnumeratedValues.append(value.upper())
+                    if self.Functions.has_key(blocktype["name"]):
+                        for name, type, modifier in blocktype["inputs"]:
+                            if name not in self.Functions[blocktype["name"]]["inputs"]:
+                                self.Functions[blocktype["name"]]["inputs"].append(name)
+                        for name, type, modifier in blocktype["outputs"]:
+                            if name not in self.Functions[blocktype["name"]]["outputs"]:
+                                self.Functions[blocktype["name"]]["outputs"].append(name)
+                        self.Functions[blocktype["name"]]["extensible"] |= blocktype["extensible"]
+                    else:
+                        self.Functions[blocktype["name"]] = {"inputs": [name for name, type, modifier in blocktype["inputs"]],
+                                                             "outputs": [name for name, type, modifier in blocktype["outputs"]],
+                                                             "extensible": blocktype["extensible"]}
         
         self.Colourise(0, -1)
     
@@ -364,6 +379,15 @@
                 return self.IsValidVariable(name_list[1:], sub_tree)
         return False
     
+    def IsFunctionParameter(self, param_name, func_name):
+        if func_name is not None:
+            func_decl = self.Functions.get(func_name, None)
+            if func_decl is not None:
+                return (param_name.upper() in func_decl["inputs"] or 
+                        param_name.upper() in func_decl["outputs"] or
+                        func_decl["extensible"] and EXTENSIBLE_PARAMETER.match(param_name.upper()) is not None)
+        return False
+        
     def OnStyleNeeded(self, event):
         self.TextChanged = True
         line = self.LineFromPosition(self.GetEndStyled())
@@ -375,6 +399,7 @@
         self.StartStyling(start_pos, 0xff)
         
         struct_elements = []
+        current_function = None
         
         current_pos = last_styled_pos
         state = SPACE
@@ -384,18 +409,19 @@
             char = chr(self.GetCharAt(current_pos)).upper()
             line += char
             if char == NEWLINE:
+                self.StructElementsStack = []
                 if state == COMMENT:
                     self.SetStyling(current_pos - last_styled_pos + 1, STC_PLC_COMMENT)
                 elif state == NUMBER:
                     self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
                 elif state == WORD:
-                    if word in self.Keywords:
+                    if word in self.Keywords or word in self.TypeNames:
                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
-                    elif self.IsValidVariable(struct_elements + [word], self.Variables):
+                    elif self.IsValidVariable(struct_elements + [word], self.Variables) or self.IsFunctionParameter(word, current_function):
                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
                     elif word in self.Functions:
                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)
-                    elif word in self.Jumps:
+                    elif self.TextSyntax == "IL" and word in self.Jumps:
                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
                     elif word in self.EnumeratedValues:
                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
@@ -422,6 +448,25 @@
                     self.SetStyling(current_pos - last_styled_pos + 2, STC_PLC_COMMENT)
                     last_styled_pos = current_pos + 1
                     state = SPACE
+            elif (line.endswith("'") or line.endswith('"')) and state not in [COMMENT, STRING, WSTRING]:
+                self.SetStyling(current_pos - last_styled_pos, 31)
+                last_styled_pos = current_pos
+                if state == WORD:
+                    struct_elements = []
+                if line.endswith("'"):
+                    state = STRING
+                else:
+                    state = WSTRING
+            elif state == STRING:
+                if line.endswith("'") and not line.endswith("$'"):
+                    self.SetStyling(current_pos - last_styled_pos + 1, STC_PLC_STRING)
+                    last_styled_pos = current_pos + 1
+                    state = SPACE
+            elif state == WSTRING:
+                if line.endswith('"') and not line.endswith('$"'):
+                    self.SetStyling(current_pos - last_styled_pos + 1, STC_PLC_STRING)
+                    last_styled_pos = current_pos + 1
+                    state = SPACE
             elif char in LETTERS:
                 if state == NUMBER:
                     word = "#"
@@ -440,15 +485,18 @@
                     state = NUMBER
                 if state == WORD and char != '.':
                     word += char
+            elif char == '(' and state == SPACE:
+                self.FunctionCallStack.append(current_function)
+                current_function = None
             else:
                 if state == WORD:
-                    if word in self.Keywords:
+                    if word in self.Keywords or word in self.TypeNames:
                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
-                    elif self.IsValidVariable(struct_elements + [word], self.Variables):
+                    elif self.IsValidVariable(struct_elements + [word], self.Variables) or self.IsFunctionParameter(word, current_function):
                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
                     elif word in self.Functions:
-                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)
-                    elif word in self.Jumps:
+                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)    
+                    elif self.TextSyntax == "IL" and word in self.Jumps:
                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
                     elif word in self.EnumeratedValues:
                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
@@ -461,10 +509,20 @@
                     if char == '.':
                         if word != "]":
                             struct_elements.append(word)
+                    elif char == '(':
+                        self.FunctionCallStack.append(current_function)
+                        if word in self.Functions:
+                            current_function = word
+                            struct_elements = []
+                        else:    
+                            if self.IsValidVariable(struct_elements + [word], self.Variables):
+                                struct_elements.append(word)
+                            current_function = None
                     else:
                         if char == '[':
                             self.StructElementsStack.append(struct_elements + [word])
                         struct_elements = []
+                    
                     word = ""
                     last_styled_pos = current_pos
                     state = SPACE
@@ -475,19 +533,27 @@
                 if char == ']':
                     if len(self.StructElementsStack) > 0:
                         struct_elements = self.StructElementsStack.pop()
+                    else:
+                        struct_elements = []
                     word = char
                     state = WORD
+                elif char == ')':
+                    struct_elements = []
+                    if len(self.FunctionCallStack) > 0:
+                        current_function = self.FunctionCallStack.pop()
+                    else:
+                        current_function = None
             current_pos += 1
         if state == COMMENT:
             self.SetStyling(current_pos - last_styled_pos + 2, STC_PLC_COMMENT)
         elif state == NUMBER:
             self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
         elif state == WORD:
-            if word in self.Keywords:
+            if word in self.Keywords or word in self.TypeNames:
                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
-            elif self.IsValidVariable(struct_elements + [word], self.Variables):
+            elif self.IsValidVariable(struct_elements + [word], self.Variables) or self.IsFunctionParameter(word, current_function):
                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
-            elif word in self.Functions:
+            elif self.TextSyntax == "IL" and word in self.Functions:
                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)
             elif word in self.Jumps:
                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)