OSDN Git Service

b7626e34d5c61902416b082979e0ab9877fb64cd
[tortoisegit/TortoiseGitJp.git] / ext / scintilla / src / LexProgress.cxx
1 // Scintilla source code edit control\r
2 /** @file LexProgress.cxx\r
3  **  Lexer for Progress 4GL.\r
4  ** Based on LexCPP.cxx of Neil Hodgson <neilh@scintilla.org>\r
5   **/\r
6 // Copyright 2006-2007 by Yuval Papish <Yuval@YuvCom.com>\r
7 // The License.txt file describes the conditions under which this software may be distributed.\r
8 \r
9 /** TODO:\r
10 WebSpeed support in html lexer\r
11 Support "end triggers" expression of the triggers phrase\r
12 change lmPS to lmProgress\r
13 Support more than 6 comments levels\r
14 **/\r
15 #include <stdlib.h>\r
16 #include <string.h>\r
17 #include <ctype.h>\r
18 #include <stdio.h>\r
19 #include <stdarg.h>\r
20 \r
21 #include "Platform.h"\r
22 \r
23 #include "PropSet.h"\r
24 #include "Accessor.h"\r
25 #include "StyleContext.h"\r
26 #include "KeyWords.h"\r
27 #include "Scintilla.h"\r
28 #include "SciLexer.h"\r
29 \r
30 #ifdef SCI_NAMESPACE\r
31 using namespace Scintilla;\r
32 #endif\r
33 \r
34 static inline bool IsAWordChar(int ch) {\r
35         return (ch < 0x80) && (isalnum(ch) || ch == '_');\r
36 }\r
37 \r
38 static inline bool IsAWordStart(int ch) {\r
39         return (ch < 0x80) && (isalpha(ch) || ch == '_');\r
40 }\r
41 \r
42 enum SentenceStart { SetSentenceStart = 0xf, ResetSentenceStart = 0x10}; // true -> bit = 0\r
43 \r
44 static void Colourise4glDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],\r
45                             Accessor &styler) {\r
46 \r
47     WordList &keywords1 = *keywordlists[0];\r
48     WordList &keywords2 = *keywordlists[1];\r
49     WordList &keywords3 = *keywordlists[2];\r
50     //WordList &keywords4 = *keywordlists[3];\r
51     //WordList &keywords5 = *keywordlists[4];\r
52 \r
53         int visibleChars = 0;\r
54         int mask;\r
55 \r
56         StyleContext sc(startPos, length, initStyle, styler);\r
57 \r
58         for (; sc.More(); sc.Forward()) {\r
59 \r
60                 if (sc.atLineStart) {\r
61                         // Reset states to begining of colourise so no surprises\r
62                         // if different sets of lines lexed.\r
63                         visibleChars = 0;\r
64                 }\r
65 \r
66                 // Handle line continuation generically.\r
67                 if (sc.ch == '~') {\r
68                         if (sc.chNext > ' ') {\r
69                                 // skip special char after ~\r
70                                 sc.Forward();\r
71                                 continue;\r
72                         }\r
73                         else {\r
74                                 // Skip whitespace between ~ and EOL\r
75                                 while (sc.More() && (sc.chNext == ' ' || sc.chNext == '\t') ) {\r
76                                         sc.Forward();\r
77                                 }\r
78                                 if (sc.chNext == '\n' || sc.chNext == '\r') {\r
79                                         sc.Forward();\r
80                                         if (sc.ch == '\r' && sc.chNext == '\n') {\r
81                                                 sc.Forward();\r
82                                         }\r
83                                         sc.Forward();\r
84                                         continue;\r
85                                 }\r
86                         }\r
87                 }\r
88                 // Determine if a new state should be terminated.\r
89                 mask = sc.state & 0x10;\r
90                 switch (sc.state & 0xf) {\r
91                         case SCE_4GL_OPERATOR:\r
92                                 sc.SetState(SCE_4GL_DEFAULT | mask);\r
93                                 break;\r
94                         case SCE_4GL_NUMBER:\r
95                                 if (!(IsADigit(sc.ch))) {\r
96                                         sc.SetState(SCE_4GL_DEFAULT | mask);\r
97                                 }\r
98                                 break;\r
99                         case SCE_4GL_IDENTIFIER:\r
100                                 if (!IsAWordChar(sc.ch) && sc.ch != '-') {\r
101                                         char s[1000];\r
102                                         sc.GetCurrentLowered(s, sizeof(s));\r
103                                         if (((sc.state & 0x10) == 0) && keywords2.InList(s) || keywords3.InList(s)) {\r
104                                                 sc.ChangeState(SCE_4GL_BLOCK | ResetSentenceStart);\r
105                                         }\r
106                                         else if (keywords1.InList(s)) {\r
107                                                 if ((s[0] == 'e' && s[1] =='n' && s[2] == 'd' && !isalnum(s[3]) && s[3] != '-') ||\r
108                                                         (s[0] == 'f' && s[1] =='o' && s[2] == 'r' && s[3] == 'w' && s[4] =='a' && s[5] == 'r' && s[6] == 'd'&& !isalnum(s[7]))) {\r
109                                                         sc.ChangeState(SCE_4GL_END | ResetSentenceStart);\r
110                                                 }\r
111                                                 else if ((s[0] == 'e' && s[1] =='l' && s[2] == 's' && s[3] == 'e') ||\r
112                                                                  (s[0] == 't' && s[1] =='h' && s[2] == 'e' && s[3] == 'n')) {\r
113                                                         sc.ChangeState(SCE_4GL_WORD & SetSentenceStart);\r
114                                                 }\r
115                                                 else {\r
116                                                         sc.ChangeState(SCE_4GL_WORD | ResetSentenceStart);\r
117                                                 }\r
118                                         }\r
119                                         sc.SetState(SCE_4GL_DEFAULT | (sc.state & 0x10));\r
120                                 }\r
121                                 break;\r
122                         case SCE_4GL_PREPROCESSOR:\r
123                                 if (sc.atLineStart) {\r
124                                         sc.SetState(SCE_4GL_DEFAULT & SetSentenceStart);\r
125                                 } else if (sc.ch == '*' && sc.chNext == '/') {\r
126                                         sc.ForwardSetState(SCE_4GL_DEFAULT | mask);\r
127                                 }\r
128                                 break;\r
129                         case SCE_4GL_STRING:\r
130                                 if (sc.ch == '\"') {\r
131                                         sc.ForwardSetState(SCE_4GL_DEFAULT | mask);\r
132                                 }\r
133                                 break;\r
134                         case SCE_4GL_CHARACTER:\r
135                                 if (sc.ch == '\'') {\r
136                                         sc.ForwardSetState(SCE_4GL_DEFAULT | mask);\r
137                                 }\r
138                                 break;\r
139                         default:\r
140                                 if ((sc.state & 0xf) >= SCE_4GL_COMMENT1) {\r
141                                         if (sc.ch == '*' && sc.chNext == '/') {\r
142                                                 sc.Forward();\r
143                                                 if ((sc.state & 0xf) == SCE_4GL_COMMENT1) {\r
144                                                         sc.ForwardSetState(SCE_4GL_DEFAULT | mask);\r
145                                                 }\r
146                                                 else\r
147                                                         sc.SetState((sc.state & 0x1f) - 1);\r
148                                         } else if (sc.ch == '/' && sc.chNext == '*') {\r
149                                                 sc.Forward();\r
150                                                 sc.SetState((sc.state & 0x1f) + 1);\r
151                                         }\r
152                                 }\r
153                 }\r
154 \r
155                 // Determine if a new state should be entered.\r
156                 mask = sc.state & 0x10;\r
157                 if ((sc.state & 0xf) == SCE_4GL_DEFAULT) {\r
158                         if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {\r
159                                 sc.SetState(SCE_4GL_NUMBER | ResetSentenceStart);\r
160                         } else if (IsAWordStart(sc.ch) || (sc.ch == '@')) {\r
161                                 sc.SetState(SCE_4GL_IDENTIFIER | mask);\r
162                         } else if (sc.ch == '/' && sc.chNext == '*') {\r
163                                 sc.SetState(SCE_4GL_COMMENT1 | mask);\r
164                                 sc.Forward();\r
165                         } else if (sc.ch == '\"') {\r
166                                 sc.SetState(SCE_4GL_STRING | ResetSentenceStart);\r
167                         } else if (sc.ch == '\'') {\r
168                                 sc.SetState(SCE_4GL_CHARACTER | ResetSentenceStart);\r
169                         } else if (sc.ch == '&' && visibleChars == 0 && ((sc.state & 0x10) == 0)) {\r
170                                 sc.SetState(SCE_4GL_PREPROCESSOR | ResetSentenceStart);\r
171                                 // Skip whitespace between & and preprocessor word\r
172                                 do {\r
173                                         sc.Forward();\r
174                                 } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());\r
175                         // Handle syntactical line termination\r
176                         } else if ((sc.ch == '.' || sc.ch == ':' || sc.ch == '}') && (sc.chNext == ' ' || sc.chNext == '\t' || sc.chNext == '\n' || sc.chNext == '\r')) {\r
177                                 sc.SetState(sc.state & SetSentenceStart);\r
178                         } else if (isoperator(static_cast<char>(sc.ch))) {\r
179                                 if (sc.ch == ':')\r
180                                         sc.SetState(SCE_4GL_OPERATOR & SetSentenceStart);\r
181                                 else\r
182                                         sc.SetState(SCE_4GL_OPERATOR | ResetSentenceStart);\r
183                         }\r
184                 }\r
185 \r
186                 if (!IsASpace(sc.ch)) {\r
187                         visibleChars++;\r
188                 }\r
189         }\r
190         sc.Complete();\r
191 }\r
192 \r
193 static bool IsStreamCommentStyle(int style) {\r
194         return (style & 0xf) >= SCE_4GL_COMMENT1 ;\r
195 }\r
196 \r
197 // Store both the current line's fold level and the next lines in the\r
198 // level store to make it easy to pick up with each increment\r
199 // and to make it possible to fiddle the current level for "} else {".\r
200 static void FoldNoBox4glDoc(unsigned int startPos, int length, int initStyle,\r
201                             Accessor &styler) {\r
202         bool foldComment = styler.GetPropertyInt("fold.comment") != 0;\r
203         bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;\r
204         bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;\r
205         unsigned int endPos = startPos + length;\r
206         int visibleChars = 0;\r
207         int lineCurrent = styler.GetLine(startPos);\r
208         int levelCurrent = SC_FOLDLEVELBASE;\r
209         if (lineCurrent > 0)\r
210                 levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;\r
211         int levelMinCurrent = levelCurrent;\r
212         int levelNext = levelCurrent;\r
213         char chNext = static_cast<char>(tolower(styler[startPos]));\r
214         int styleNext = styler.StyleAt(startPos);\r
215         int style = initStyle;\r
216         for (unsigned int i = startPos; i < endPos; i++) {\r
217                 char ch = chNext;\r
218                 chNext = static_cast<char>(tolower(styler.SafeGetCharAt(i + 1)));\r
219                 int stylePrev = style;\r
220                 style = styleNext;\r
221                 styleNext = styler.StyleAt(i + 1);\r
222                 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');\r
223                 if (foldComment && IsStreamCommentStyle(style)) {\r
224                         if (!IsStreamCommentStyle(stylePrev)) {\r
225                                 levelNext++;\r
226                         } else if (!IsStreamCommentStyle(styleNext)) { // && !atEOL) {\r
227                                 // Comments don't end at end of line and the next character may be unstyled.\r
228                                 levelNext--;\r
229                         }\r
230                 }\r
231                 else if ((style & 0xf) == SCE_4GL_BLOCK && !isalnum(chNext)) {\r
232                         levelNext++;\r
233                 }\r
234                 else if ((style & 0xf) == SCE_4GL_END  && (ch == 'e' || ch == 'f')) {\r
235                         levelNext--;\r
236                 }\r
237                 if (atEOL) {\r
238                         int levelUse = levelCurrent;\r
239                         if (foldAtElse) {\r
240                                 levelUse = levelMinCurrent;\r
241                         }\r
242                         int lev = levelUse | levelNext << 16;\r
243                         if (visibleChars == 0 && foldCompact)\r
244                                 lev |= SC_FOLDLEVELWHITEFLAG;\r
245                         if (levelUse < levelNext)\r
246                                 lev |= SC_FOLDLEVELHEADERFLAG;\r
247                         if (lev != styler.LevelAt(lineCurrent)) {\r
248                                 styler.SetLevel(lineCurrent, lev);\r
249                         }\r
250                         lineCurrent++;\r
251                         levelCurrent = levelNext;\r
252                         levelMinCurrent = levelCurrent;\r
253                         visibleChars = 0;\r
254                 }\r
255                 if (!isspacechar(ch))\r
256                         visibleChars++;\r
257         }\r
258 }\r
259 \r
260 static void Fold4glDoc(unsigned int startPos, int length, int initStyle, WordList *[],\r
261                        Accessor &styler) {\r
262         FoldNoBox4glDoc(startPos, length, initStyle, styler);\r
263 }\r
264 \r
265 static const char * const FglWordLists[] = {\r
266             "Primary keywords and identifiers",\r
267             "Secondary keywords and identifiers",\r
268             "Documentation comment keywords",\r
269             "Unused",\r
270             "Global classes and typedefs",\r
271             0,\r
272         };\r
273 \r
274 LexerModule lmProgress(SCLEX_PS, Colourise4glDoc, "progress", Fold4glDoc, FglWordLists);\r
275 \r
276 \r