OSDN Git Service

Enable X64 Build
[tortoisegit/TortoiseGitJp.git] / ext / scintilla / src / LexEiffel.cxx
1 // Scintilla source code edit control\r
2 /** @file LexEiffel.cxx\r
3  ** Lexer for Eiffel.\r
4  **/\r
5 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>\r
6 // The License.txt file describes the conditions under which this software may be distributed.\r
7 \r
8 #include <stdlib.h>\r
9 #include <string.h>\r
10 #include <ctype.h>\r
11 #include <stdarg.h>\r
12 #include <stdio.h>\r
13 \r
14 #include "Platform.h"\r
15 \r
16 #include "PropSet.h"\r
17 #include "Accessor.h"\r
18 #include "StyleContext.h"\r
19 #include "KeyWords.h"\r
20 #include "Scintilla.h"\r
21 #include "SciLexer.h"\r
22 \r
23 #ifdef SCI_NAMESPACE\r
24 using namespace Scintilla;\r
25 #endif\r
26 \r
27 static inline bool isEiffelOperator(unsigned int ch) {\r
28         // '.' left out as it is used to make up numbers\r
29         return ch == '*' || ch == '/' || ch == '\\' || ch == '-' || ch == '+' ||\r
30                 ch == '(' || ch == ')' || ch == '=' ||\r
31                 ch == '{' || ch == '}' || ch == '~' ||\r
32                 ch == '[' || ch == ']' || ch == ';' ||\r
33                 ch == '<' || ch == '>' || ch == ',' ||\r
34                 ch == '.' || ch == '^' || ch == '%' || ch == ':' ||\r
35                 ch == '!' || ch == '@' || ch == '?';\r
36 }\r
37 \r
38 static inline bool IsAWordChar(unsigned int  ch) {\r
39         return (ch < 0x80) && (isalnum(ch) || ch == '_');\r
40 }\r
41 \r
42 static inline bool IsAWordStart(unsigned int ch) {\r
43         return (ch < 0x80) && (isalnum(ch) || ch == '_');\r
44 }\r
45 \r
46 static void ColouriseEiffelDoc(unsigned int startPos,\r
47                             int length,\r
48                             int initStyle,\r
49                             WordList *keywordlists[],\r
50                             Accessor &styler) {\r
51 \r
52         WordList &keywords = *keywordlists[0];\r
53 \r
54         StyleContext sc(startPos, length, initStyle, styler);\r
55 \r
56         for (; sc.More(); sc.Forward()) {\r
57 \r
58                 if (sc.state == SCE_EIFFEL_STRINGEOL) {\r
59                         if (sc.ch != '\r' && sc.ch != '\n') {\r
60                                 sc.SetState(SCE_EIFFEL_DEFAULT);\r
61                         }\r
62                 } else if (sc.state == SCE_EIFFEL_OPERATOR) {\r
63                         sc.SetState(SCE_EIFFEL_DEFAULT);\r
64                 } else if (sc.state == SCE_EIFFEL_WORD) {\r
65                         if (!IsAWordChar(sc.ch)) {\r
66                                 char s[100];\r
67                                 sc.GetCurrentLowered(s, sizeof(s));\r
68                                 if (!keywords.InList(s)) {\r
69                                         sc.ChangeState(SCE_EIFFEL_IDENTIFIER);\r
70                                 }\r
71                                 sc.SetState(SCE_EIFFEL_DEFAULT);\r
72                         }\r
73                 } else if (sc.state == SCE_EIFFEL_NUMBER) {\r
74                         if (!IsAWordChar(sc.ch)) {\r
75                                 sc.SetState(SCE_EIFFEL_DEFAULT);\r
76                         }\r
77                 } else if (sc.state == SCE_EIFFEL_COMMENTLINE) {\r
78                         if (sc.ch == '\r' || sc.ch == '\n') {\r
79                                 sc.SetState(SCE_EIFFEL_DEFAULT);\r
80                         }\r
81                 } else if (sc.state == SCE_EIFFEL_STRING) {\r
82                         if (sc.ch == '%') {\r
83                                 sc.Forward();\r
84                         } else if (sc.ch == '\"') {\r
85                                 sc.Forward();\r
86                                 sc.SetState(SCE_EIFFEL_DEFAULT);\r
87                         }\r
88                 } else if (sc.state == SCE_EIFFEL_CHARACTER) {\r
89                         if (sc.ch == '\r' || sc.ch == '\n') {\r
90                                 sc.SetState(SCE_EIFFEL_STRINGEOL);\r
91                         } else if (sc.ch == '%') {\r
92                                 sc.Forward();\r
93                         } else if (sc.ch == '\'') {\r
94                                 sc.Forward();\r
95                                 sc.SetState(SCE_EIFFEL_DEFAULT);\r
96                         }\r
97                 }\r
98 \r
99                 if (sc.state == SCE_EIFFEL_DEFAULT) {\r
100                         if (sc.ch == '-' && sc.chNext == '-') {\r
101                                 sc.SetState(SCE_EIFFEL_COMMENTLINE);\r
102                         } else if (sc.ch == '\"') {\r
103                                 sc.SetState(SCE_EIFFEL_STRING);\r
104                         } else if (sc.ch == '\'') {\r
105                                 sc.SetState(SCE_EIFFEL_CHARACTER);\r
106                         } else if (IsADigit(sc.ch) || (sc.ch == '.')) {\r
107                                 sc.SetState(SCE_EIFFEL_NUMBER);\r
108                         } else if (IsAWordStart(sc.ch)) {\r
109                                 sc.SetState(SCE_EIFFEL_WORD);\r
110                         } else if (isEiffelOperator(sc.ch)) {\r
111                                 sc.SetState(SCE_EIFFEL_OPERATOR);\r
112                         }\r
113                 }\r
114         }\r
115         sc.Complete();\r
116 }\r
117 \r
118 static bool IsEiffelComment(Accessor &styler, int pos, int len) {\r
119         return len>1 && styler[pos]=='-' && styler[pos+1]=='-';\r
120 }\r
121 \r
122 static void FoldEiffelDocIndent(unsigned int startPos, int length, int,\r
123                                                    WordList *[], Accessor &styler) {\r
124         int lengthDoc = startPos + length;\r
125 \r
126         // Backtrack to previous line in case need to fix its fold status\r
127         int lineCurrent = styler.GetLine(startPos);\r
128         if (startPos > 0) {\r
129                 if (lineCurrent > 0) {\r
130                         lineCurrent--;\r
131                         startPos = styler.LineStart(lineCurrent);\r
132                 }\r
133         }\r
134         int spaceFlags = 0;\r
135         int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsEiffelComment);\r
136         char chNext = styler[startPos];\r
137         for (int i = startPos; i < lengthDoc; i++) {\r
138                 char ch = chNext;\r
139                 chNext = styler.SafeGetCharAt(i + 1);\r
140 \r
141                 if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) {\r
142                         int lev = indentCurrent;\r
143                         int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsEiffelComment);\r
144                         if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {\r
145                                 // Only non whitespace lines can be headers\r
146                                 if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {\r
147                                         lev |= SC_FOLDLEVELHEADERFLAG;\r
148                                 } else if (indentNext & SC_FOLDLEVELWHITEFLAG) {\r
149                                         // Line after is blank so check the next - maybe should continue further?\r
150                                         int spaceFlags2 = 0;\r
151                                         int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsEiffelComment);\r
152                                         if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {\r
153                                                 lev |= SC_FOLDLEVELHEADERFLAG;\r
154                                         }\r
155                                 }\r
156                         }\r
157                         indentCurrent = indentNext;\r
158                         styler.SetLevel(lineCurrent, lev);\r
159                         lineCurrent++;\r
160                 }\r
161         }\r
162 }\r
163 \r
164 static void FoldEiffelDocKeyWords(unsigned int startPos, int length, int /* initStyle */, WordList *[],\r
165                        Accessor &styler) {\r
166         unsigned int lengthDoc = startPos + length;\r
167         int visibleChars = 0;\r
168         int lineCurrent = styler.GetLine(startPos);\r
169         int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;\r
170         int levelCurrent = levelPrev;\r
171         char chNext = styler[startPos];\r
172         int stylePrev = 0;\r
173         int styleNext = styler.StyleAt(startPos);\r
174         // lastDeferred should be determined by looking back to last keyword in case\r
175         // the "deferred" is on a line before "class"\r
176         bool lastDeferred = false;\r
177         for (unsigned int i = startPos; i < lengthDoc; i++) {\r
178                 char ch = chNext;\r
179                 chNext = styler.SafeGetCharAt(i + 1);\r
180                 int style = styleNext;\r
181                 styleNext = styler.StyleAt(i + 1);\r
182                 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');\r
183                 if ((stylePrev != SCE_EIFFEL_WORD) && (style == SCE_EIFFEL_WORD)) {\r
184                         char s[20];\r
185                         unsigned int j = 0;\r
186                         while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) {\r
187                                 s[j] = styler[i + j];\r
188                                 j++;\r
189                         }\r
190                         s[j] = '\0';\r
191 \r
192                         if (\r
193                                 (strcmp(s, "check") == 0) ||\r
194                                 (strcmp(s, "debug") == 0) ||\r
195                                 (strcmp(s, "deferred") == 0) ||\r
196                                 (strcmp(s, "do") == 0) ||\r
197                                 (strcmp(s, "from") == 0) ||\r
198                                 (strcmp(s, "if") == 0) ||\r
199                                 (strcmp(s, "inspect") == 0) ||\r
200                                 (strcmp(s, "once") == 0)\r
201                         )\r
202                                 levelCurrent++;\r
203                         if (!lastDeferred && (strcmp(s, "class") == 0))\r
204                                 levelCurrent++;\r
205                         if (strcmp(s, "end") == 0)\r
206                                 levelCurrent--;\r
207                         lastDeferred = strcmp(s, "deferred") == 0;\r
208                 }\r
209 \r
210                 if (atEOL) {\r
211                         int lev = levelPrev;\r
212                         if (visibleChars == 0)\r
213                                 lev |= SC_FOLDLEVELWHITEFLAG;\r
214                         if ((levelCurrent > levelPrev) && (visibleChars > 0))\r
215                                 lev |= SC_FOLDLEVELHEADERFLAG;\r
216                         if (lev != styler.LevelAt(lineCurrent)) {\r
217                                 styler.SetLevel(lineCurrent, lev);\r
218                         }\r
219                         lineCurrent++;\r
220                         levelPrev = levelCurrent;\r
221                         visibleChars = 0;\r
222                 }\r
223                 if (!isspacechar(ch))\r
224                         visibleChars++;\r
225                 stylePrev = style;\r
226         }\r
227         // Fill in the real level of the next line, keeping the current flags as they will be filled in later\r
228         int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;\r
229         styler.SetLevel(lineCurrent, levelPrev | flagsNext);\r
230 }\r
231 \r
232 static const char * const eiffelWordListDesc[] = {\r
233         "Keywords",\r
234         0\r
235 };\r
236 \r
237 LexerModule lmEiffel(SCLEX_EIFFEL, ColouriseEiffelDoc, "eiffel", FoldEiffelDocIndent, eiffelWordListDesc);\r
238 LexerModule lmEiffelkw(SCLEX_EIFFELKW, ColouriseEiffelDoc, "eiffelkw", FoldEiffelDocKeyWords, eiffelWordListDesc);\r