| 1 | U | 1 | U | // Scintilla source code edit control |
|
|
| 3 | C | ** Lexer for C++, C, Java, and Javascript. | | 3 | C | ** Lexer for C++, C, Java, and JavaScript. |
|
| 5 | C | // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org> | | 5 | C | // Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org> |
| 6 | U | 6 | U | // The License.txt file describes the conditions under which this software may be distributed. |
|
|
|
| 14 skipped lines |
| 23 | U | 23 | U | #define KEYWORD_BOXHEADER 1 |
|
| 24 | U | 24 | U | #define KEYWORD_FOLDCONTRACTED 2 |
|
|
| 26 | C | static bool IsOKBeforeRE(const int ch) { | | 26 | C | static bool IsOKBeforeRE(int ch) { |
| 27 | U | 27 | U | return (ch == '(') || (ch == '=') || (ch == ','); |
|
|
|
| 30 | C | static inline bool IsAWordChar(const int ch) { | | 30 | C | static inline bool IsAWordChar(int ch) { |
| 31 | U | 31 | U | return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); |
|
|
|
| 34 | C | static inline bool IsAWordStart(const int ch) { | | 34 | C | static inline bool IsAWordStart(int ch) { |
| 35 | C | return (ch < 0x80) && (isalnum(ch) || ch == '_'); | | 35 | C | return (ch < 0x80) && (isalpha(ch) || ch == '_'); |
|
|
| 38 | C | static inline bool IsADoxygenChar(const int ch) { | | 38 | C | static inline bool IsADoxygenChar(int ch) { |
| 39 | C | return (islower(ch) || ch == '$' || ch == '@' || | | 39 | C | return (ch < 0x80 && islower(ch)) || ch == '$' || ch == '@' || |
| 40 | C | ch == '\\' || ch == '&' || ch == '<' || | | 40 | C | ch == '\\' || ch == '&' || ch == '<' || |
| 41 | C | ch == '>' || ch == '#' || ch == '{' || | | 41 | C | ch == '>' || ch == '#' || ch == '{' || |
| 42 | C | ch == '}' || ch == '[' || ch == ']'); | | 42 | C | ch == '}' || ch == '[' || ch == ']'; |
|
|
| 45 | C | static inline bool IsStateComment(const int state) { | | 45 | C | static bool IsSpaceEquiv(int state) { |
| 46 | C | return ((state == SCE_C_COMMENT) || | | 46 | C | return (state <= SCE_C_COMMENTDOC) || |
| 47 | C | (state == SCE_C_COMMENTLINE) || | | |
| 48 | C | (state == SCE_C_COMMENTDOC) || | | |
| 49 | C | (state == SCE_C_COMMENTDOCKEYWORD) || | | 47 | C | // including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE |
| 50 | C | (state == SCE_C_COMMENTDOCKEYWORDERROR)); | | 48 | C | (state == SCE_C_COMMENTLINEDOC) || (state == SCE_C_COMMENTDOCKEYWORD) || |
| 51 | C | } | | |
| 52 | C | | | |
| 53 | C | static inline bool IsStateString(const int state) { | | |
| 54 | C | return ((state == SCE_C_STRING) || (state == SCE_C_VERBATIM)); | | 49 | C | (state == SCE_C_COMMENTDOCKEYWORDERROR); |
|
|
| 57 | U | 52 | U | static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], |
|
| 6 skipped lines |
|
| 65 | U | 60 | U | bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; |
|
|
| 67 | R | // Do not leak onto next line | | |
| 68 | R | if (initStyle == SCE_C_STRINGEOL) | | |
| 69 | R | initStyle = SCE_C_DEFAULT; | | |
| 70 | R | | | |
| 71 | U | 62 | U | int chPrevNonWhite = ' '; |
|
| 72 | U | 63 | U | int visibleChars = 0; |
|
| 73 | U | 64 | U | bool lastWordWasUUID = false; |
|
| | | 65 | A | int styleBeforeDCKeyword = SCE_C_DEFAULT; |
| | | 66 | A | bool continuationLine = false; |
| | | 67 | A | |
| | | 68 | A | if (initStyle == SCE_C_PREPROCESSOR) { |
| | | 69 | A | // Set continuationLine if last character of previous line is '\' |
| 18 skipped lines |
| | | 88 | A | ; |
| | | 89 | A | if (styler.StyleAt(back) == SCE_C_OPERATOR) { |
| | | 90 | A | chPrevNonWhite = styler.SafeGetCharAt(back); |
| | | 91 | A | } |
| | | 92 | A | } |
|
| 75 | U | 94 | U | StyleContext sc(startPos, length, initStyle, styler); |
|
|
| 77 | U | 96 | U | for (; sc.More(); sc.Forward()) { |
|
|
| | | 98 | C | if (sc.atLineStart) { |
| 79 | C | if (sc.atLineStart && (sc.state == SCE_C_STRING)) { | | 99 | C | if (sc.state == SCE_C_STRING) { |
| 80 | C | // Prevent SCE_C_STRINGEOL from leaking back to previous line | | 100 | C | // Prevent SCE_C_STRINGEOL from leaking back to previous line which |
| | | 101 | C | // ends with a line continuation by locking in the state upto this position. |
| 81 | C | sc.SetState(SCE_C_STRING); | | 102 | C | sc.SetState(SCE_C_STRING); |
| | | 103 | C | } |
| | | 104 | C | // Reset states to begining of colourise so no surprises |
| | | 105 | C | // if different sets of lines lexed. |
| | | 106 | C | visibleChars = 0; |
| | | 107 | C | lastWordWasUUID = false; |
|
|
| 84 | U | 110 | U | // Handle line continuation generically. |
|
| 3 skipped lines |
| 88 | U | 114 | U | if (sc.ch == '\r' && sc.chNext == '\n') { |
|
|
|
| | | 117 | A | continuationLine = true; |
|
|
|
|
| 95 | U | 122 | U | // Determine if the current state should terminate. |
|
| 96 | C | if (sc.state == SCE_C_OPERATOR) { | | 123 | C | switch (sc.state) { |
| 97 | C | sc.SetState(SCE_C_DEFAULT); | | |
| 98 | C | } else if (sc.state == SCE_C_NUMBER) { | | |
| 99 | C | if (!IsAWordChar(sc.ch)) { | | |
| 100 | C | sc.SetState(SCE_C_DEFAULT); | | 124 | C | case SCE_C_OPERATOR: |
| 101 | C | } | | |
| 102 | C | } else if (sc.state == SCE_C_IDENTIFIER) { | | |
| 103 | C | if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { | | |
| 104 | C | char s[100]; | | |
| 105 | C | if (caseSensitive) { | | |
| 106 | C | sc.GetCurrent(s, sizeof(s)); | | |
| 107 | C | } else { | | |
| 108 | C | sc.GetCurrentLowered(s, sizeof(s)); | | |
| 109 | C | } | | |
| 110 | C | if (keywords.InList(s)) { | | |
| 111 | C | lastWordWasUUID = strcmp(s, "uuid") == 0; | | |
| 112 | C | sc.ChangeState(SCE_C_WORD); | | |
| 113 | C | } else if (keywords2.InList(s)) { | | |
| 114 | C | sc.ChangeState(SCE_C_WORD2); | | |
| 115 | C | } else if (keywords4.InList(s)) { | | |
| 116 | C | sc.ChangeState(SCE_C_GLOBALCLASS); | | |
| 117 | C | } | | |
| 118 | U | 125 | U | sc.SetState(SCE_C_DEFAULT); |
|
| 119 | C | } | | 126 | C | break; |
| 120 | C | } else if (sc.state == SCE_C_PREPROCESSOR) { | | 127 | C | case SCE_C_NUMBER: |
| 121 | C | if (stylingWithinPreprocessor) { | | 128 | C | // We accept almost anything because of hex. and number suffixes |
| 122 | C | if (IsASpace(sc.ch)) { | | 129 | C | if (!IsAWordChar(sc.ch)) { |
| 123 | U | 130 | U | sc.SetState(SCE_C_DEFAULT); |
|
|
| 125 | C | } else { | | 132 | C | break; |
| | | 133 | C | case SCE_C_IDENTIFIER: |
| 126 | C | if ((sc.ch == '\r') || (sc.ch == '\n') || (sc.Match('/', '*')) || (sc.Match('/', '/'))) { | | 134 | C | if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { |
| | | 135 | C | char s[1000]; |
| | | 136 | C | if (caseSensitive) { |
| | | 137 | C | sc.GetCurrent(s, sizeof(s)); |
| | | 138 | C | } else { |
| | | 139 | C | sc.GetCurrentLowered(s, sizeof(s)); |
| | | 140 | C | } |
| | | 141 | C | if (keywords.InList(s)) { |
| | | 142 | C | lastWordWasUUID = strcmp(s, "uuid") == 0; |
| | | 143 | C | sc.ChangeState(SCE_C_WORD); |
| | | 144 | C | } else if (keywords2.InList(s)) { |
| | | 145 | C | sc.ChangeState(SCE_C_WORD2); |
| | | 146 | C | } else if (keywords4.InList(s)) { |
| | | 147 | C | sc.ChangeState(SCE_C_GLOBALCLASS); |
| | | 148 | C | } |
| 127 | U | 149 | U | sc.SetState(SCE_C_DEFAULT); |
|
|
| 129 | C | } | | 151 | C | break; |
| 130 | C | } else if (sc.state == SCE_C_COMMENT) { | | |
| 131 | C | if (sc.Match('*', '/')) { | | |
| 132 | C | sc.Forward(); | | |
| 133 | C | sc.ForwardSetState(SCE_C_DEFAULT); | | |
| 134 | C | } | | |
| 135 | C | } else if (sc.state == SCE_C_COMMENTDOC) { | | 152 | C | case SCE_C_PREPROCESSOR: |
| 136 | C | if (sc.Match('*', '/')) { | | |
| 137 | C | sc.Forward(); | | |
| 138 | C | sc.ForwardSetState(SCE_C_DEFAULT); | | |
| 139 | C | } else if (sc.ch == '@' || sc.ch == '\\') { | | 153 | C | if (sc.atLineStart && !continuationLine) { |
| 140 | C | sc.SetState(SCE_C_COMMENTDOCKEYWORD); | | |
| 141 | C | } | | |
| 142 | C | } else if (sc.state == SCE_C_COMMENTLINE || sc.state == SCE_C_COMMENTLINEDOC) { | | |
| 143 | C | if (sc.ch == '\r' || sc.ch == '\n') { | | |
| 144 | C | sc.SetState(SCE_C_DEFAULT); | | 154 | C | sc.SetState(SCE_C_DEFAULT); |
| 145 | C | visibleChars = 0; | | |
| 146 | C | } | | |
| 147 | C | } else if (sc.state == SCE_C_COMMENTDOCKEYWORD) { | | 155 | C | } else if (stylingWithinPreprocessor) { |
| 148 | C | if (sc.Match('*', '/')) { | | 156 | C | if (IsASpace(sc.ch)) { |
| 149 | C | sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); | | |
| 150 | C | sc.Forward(); | | |
| 151 | C | sc.ForwardSetState(SCE_C_DEFAULT); | | 157 | C | sc.SetState(SCE_C_DEFAULT); |
| 152 | C | } else if (!IsADoxygenChar(sc.ch)) { | | 158 | C | } |
| 153 | C | char s[100]; | | |
| 154 | C | if (caseSensitive) { | | |
| 155 | C | sc.GetCurrent(s, sizeof(s)); | | |
|
| 157 | C | sc.GetCurrentLowered(s, sizeof(s)); | | |
| 158 | C | } | | |
| 159 | C | if (!isspace(sc.ch) || !keywords3.InList(s + 1)) { | | 160 | C | if (sc.Match('/', '*') || sc.Match('/', '/')) { |
| 160 | C | sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); | | 161 | C | sc.SetState(SCE_C_DEFAULT); |
| | | 162 | C | } |
|
| 162 | C | sc.SetState(SCE_C_COMMENTDOC); | | 164 | C | break; |
| 163 | C | } | | |
| 164 | C | } else if (sc.state == SCE_C_STRING) { | | 165 | C | case SCE_C_COMMENT: |
| 165 | C | if (sc.ch == '\\') { | | |
| 166 | C | if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { | | 166 | C | if (sc.Match('*', '/')) { |
|
| | | 168 | A | sc.ForwardSetState(SCE_C_DEFAULT); |
|
| 169 | C | } else if (sc.ch == '\"') { | | 170 | C | break; |
| 170 | C | sc.ForwardSetState(SCE_C_DEFAULT); | | |
| 171 | C | } else if (sc.atLineEnd) { | | |
| 172 | C | sc.ChangeState(SCE_C_STRINGEOL); | | |
| 173 | C | sc.ForwardSetState(SCE_C_DEFAULT); | | |
| 174 | C | visibleChars = 0; | | |
| 175 | C | } | | |
| 176 | C | } else if (sc.state == SCE_C_CHARACTER) { | | |
| 177 | C | if (sc.atLineEnd) { | | |
| 178 | C | sc.ChangeState(SCE_C_STRINGEOL); | | |
| 179 | C | sc.ForwardSetState(SCE_C_DEFAULT); | | 171 | C | case SCE_C_COMMENTDOC: |
| 180 | C | visibleChars = 0; | | |
| 181 | C | } else if (sc.ch == '\\') { | | 172 | C | if (sc.Match('*', '/')) { |
| 182 | C | if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { | | |
|
| | | 174 | A | sc.ForwardSetState(SCE_C_DEFAULT); |
| | | 175 | A | } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support |
| | | 176 | A | // Verify that we have the conditions to mark a comment-doc-keyword |
| | | 177 | A | if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { |
| | | 178 | A | styleBeforeDCKeyword = SCE_C_COMMENTDOC; |
| | | 179 | A | sc.SetState(SCE_C_COMMENTDOCKEYWORD); |
| | | 180 | A | } |
|
| 185 | C | } else if (sc.ch == '\'') { | | 182 | C | break; |
| 186 | C | sc.ForwardSetState(SCE_C_DEFAULT); | | |
| 187 | C | } | | |
| 188 | C | } else if (sc.state == SCE_C_REGEX) { | | 183 | C | case SCE_C_COMMENTLINE: |
| 189 | C | if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == '/') { | | 184 | C | if (sc.atLineStart) { |
| 190 | C | sc.ForwardSetState(SCE_C_DEFAULT); | | 185 | C | sc.SetState(SCE_C_DEFAULT); |
| 191 | C | } else if (sc.ch == '\\') { | | |
| 192 | C | // Gobble up the quoted character | | |
| 193 | C | if (sc.chNext == '\\' || sc.chNext == '/') { | | |
| 194 | C | sc.Forward(); | | |
|
| 196 | C | } | | 187 | C | break; |
| | | 188 | C | case SCE_C_COMMENTLINEDOC: |
| | | 189 | C | if (sc.atLineStart) { |
| | | 190 | C | sc.SetState(SCE_C_DEFAULT); |
| 197 | C | } else if (sc.state == SCE_C_VERBATIM) { | | 191 | C | } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support |
| | | 192 | C | // Verify that we have the conditions to mark a comment-doc-keyword |
| 198 | C | if (sc.ch == '\"') { | | 193 | C | if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { |
| | | 194 | C | styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC; |
| | | 195 | C | sc.SetState(SCE_C_COMMENTDOCKEYWORD); |
| | | 196 | C | } |
| | | 197 | C | } |
| | | 198 | C | break; |
| | | 199 | C | case SCE_C_COMMENTDOCKEYWORD: |
| 199 | C | if (sc.chNext == '\"') { | | 200 | C | if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) { |
| | | 201 | C | sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); |
|
| 201 | R | } else { | | |
| 202 | U | 203 | U | sc.ForwardSetState(SCE_C_DEFAULT); |
|
| | | 204 | A | } else if (!IsADoxygenChar(sc.ch)) { |
| | | 205 | A | char s[100]; |
| | | 206 | A | if (caseSensitive) { |
| | | 207 | A | sc.GetCurrent(s, sizeof(s)); |
| | | 208 | A | } else { |
| 57 skipped lines |
| | | 266 | A | } |
| | | 267 | A | break; |
| | | 268 | A | case SCE_C_UUID: |
| | | 269 | A | if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { |
| | | 270 | A | sc.SetState(SCE_C_DEFAULT); |
|
| 204 | R | } | | |
| 205 | R | } else if (sc.state == SCE_C_UUID) { | | |
| 206 | R | if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { | | |
| 207 | R | sc.SetState(SCE_C_DEFAULT); | | |
| 208 | R | } | | |
|
|
| 211 | U | 274 | U | // Determine if a new state should be entered. |
|
| 29 skipped lines |
|
| 242 | U | 305 | U | sc.SetState(SCE_C_COMMENTLINE); |
|
| 243 | U | 306 | U | } else if (sc.ch == '/' && IsOKBeforeRE(chPrevNonWhite)) { |
|
| 244 | C | sc.SetState(SCE_C_REGEX); | | 307 | C | sc.SetState(SCE_C_REGEX); // JavaScript's RegEx |
| 245 | U | 308 | U | } else if (sc.ch == '\"') { |
|
| 246 | U | 309 | U | sc.SetState(SCE_C_STRING); |
|
| 247 | U | 310 | U | } else if (sc.ch == '\'') { |
|
| 5 skipped lines |
|
|
| 255 | U | 318 | U | } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); |
|
| 256 | C | if (sc.ch == '\r' || sc.ch == '\n') { | | 319 | C | if (sc.atLineEnd) { |
| 257 | U | 320 | U | sc.SetState(SCE_C_DEFAULT); |
|
|
| 259 | U | 322 | U | } else if (isoperator(static_cast<char>(sc.ch))) { |
|
| 1 skipped line |
|
|
|
| 264 | C | if (sc.atLineEnd) { | | |
| 265 | C | // Reset states to begining of colourise so no surprises | | |
| 266 | C | // if different sets of lines lexed. | | |
| 267 | C | chPrevNonWhite = ' '; | | |
| 268 | C | visibleChars = 0; | | |
| 269 | C | lastWordWasUUID = false; | | |
| 270 | C | } | | |
| 271 | C | if (!IsASpace(sc.ch)) { | | 327 | C | if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) { |
| 272 | U | 328 | U | chPrevNonWhite = sc.ch; |
|
|
|
| | | 331 | A | continuationLine = false; |
|
|
|
|
| 279 | U | 336 | U | static bool IsStreamCommentStyle(int style) { |
|
| 280 | U | 337 | U | return style == SCE_C_COMMENT || |
|
| 281 | C | style == SCE_C_COMMENTDOC || | | 338 | C | style == SCE_C_COMMENTDOC || |
| 282 | C | style == SCE_C_COMMENTDOCKEYWORD || | | 339 | C | style == SCE_C_COMMENTDOCKEYWORD || |
| 283 | C | style == SCE_C_COMMENTDOCKEYWORDERROR; | | 340 | C | style == SCE_C_COMMENTDOCKEYWORDERROR; |
|
|
| 286 | U | 343 | U | // Store both the current line's fold level and the next lines in the |
|
| 120 skipped lines |