diff options
Diffstat (limited to 'src/LexCPP.cxx')
-rw-r--r-- | src/LexCPP.cxx | 288 |
1 files changed, 152 insertions, 136 deletions
diff --git a/src/LexCPP.cxx b/src/LexCPP.cxx index 7e83fcb62..95433e3db 100644 --- a/src/LexCPP.cxx +++ b/src/LexCPP.cxx @@ -1,8 +1,8 @@ // Scintilla source code edit control /** @file LexCPP.cxx - ** Lexer for C++, C, Java, and Javascript. + ** Lexer for C++, C, Java, and JavaScript. **/ -// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org> +// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. #include <stdlib.h> @@ -23,37 +23,25 @@ #define KEYWORD_BOXHEADER 1 #define KEYWORD_FOLDCONTRACTED 2 -static bool IsOKBeforeRE(const int ch) { +static bool IsOKBeforeRE(int ch) { return (ch == '(') || (ch == '=') || (ch == ','); } -static inline bool IsAWordChar(const int ch) { +static inline bool IsAWordChar(int ch) { return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); } -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); +static inline bool IsAWordStart(int ch) { + return (ch < 0x80) && (isalpha(ch) || ch == '_'); } -static inline bool IsADoxygenChar(const int ch) { +static inline bool IsADoxygenChar(int ch) { return (islower(ch) || ch == '$' || ch == '@' || ch == '\\' || ch == '&' || ch == '<' || ch == '>' || ch == '#' || ch == '{' || ch == '}' || ch == '[' || ch == ']'); } -static inline bool IsStateComment(const int state) { - return ((state == SCE_C_COMMENT) || - (state == SCE_C_COMMENTLINE) || - (state == SCE_C_COMMENTDOC) || - (state == SCE_C_COMMENTDOCKEYWORD) || - (state == SCE_C_COMMENTDOCKEYWORDERROR)); -} - -static inline bool IsStateString(const int state) { - return ((state == SCE_C_STRING) || (state == SCE_C_VERBATIM)); -} - static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler, bool caseSensitive) { @@ -64,21 +52,26 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; - // Do not leak onto next line - if (initStyle == SCE_C_STRINGEOL) - initStyle = SCE_C_DEFAULT; - int chPrevNonWhite = ' '; int visibleChars = 0; bool lastWordWasUUID = false; + int styleBeforeDCKeyword = SCE_C_DEFAULT; StyleContext sc(startPos, length, initStyle, styler); for (; sc.More(); sc.Forward()) { - if (sc.atLineStart && (sc.state == SCE_C_STRING)) { - // Prevent SCE_C_STRINGEOL from leaking back to previous line - sc.SetState(SCE_C_STRING); + if (sc.atLineStart) { + if (sc.state == SCE_C_STRING) { + // Prevent SCE_C_STRINGEOL from leaking back to previous line which + // ends with a line continuation by locking in the state upto this position. + sc.SetState(SCE_C_STRING); + } + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + chPrevNonWhite = ' '; + visibleChars = 0; + lastWordWasUUID = false; } // Handle line continuation generically. @@ -93,122 +86,152 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo } // Determine if the current state should terminate. - if (sc.state == SCE_C_OPERATOR) { - sc.SetState(SCE_C_DEFAULT); - } else if (sc.state == SCE_C_NUMBER) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_C_DEFAULT); - } - } else if (sc.state == SCE_C_IDENTIFIER) { - if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { - char s[100]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); - } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - if (keywords.InList(s)) { - lastWordWasUUID = strcmp(s, "uuid") == 0; - sc.ChangeState(SCE_C_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_C_WORD2); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_C_GLOBALCLASS); - } + switch (sc.state) { + case SCE_C_OPERATOR: sc.SetState(SCE_C_DEFAULT); - } - } else if (sc.state == SCE_C_PREPROCESSOR) { - if (stylingWithinPreprocessor) { - if (IsASpace(sc.ch)) { + break; + case SCE_C_NUMBER: + // We accept almost anything because of hex. and number suffixes + if (!IsAWordChar(sc.ch)) { sc.SetState(SCE_C_DEFAULT); } - } else { - if ((sc.ch == '\r') || (sc.ch == '\n') || (sc.Match('/', '*')) || (sc.Match('/', '/'))) { + break; + case SCE_C_IDENTIFIER: + if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { + char s[1000]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (keywords.InList(s)) { + lastWordWasUUID = strcmp(s, "uuid") == 0; + sc.ChangeState(SCE_C_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_C_WORD2); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_C_GLOBALCLASS); + } sc.SetState(SCE_C_DEFAULT); } - } - } else if (sc.state == SCE_C_COMMENT) { - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT); - } - } else if (sc.state == SCE_C_COMMENTDOC) { - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { - sc.SetState(SCE_C_COMMENTDOCKEYWORD); - } - } - } else if (sc.state == SCE_C_COMMENTLINE || sc.state == SCE_C_COMMENTLINEDOC) { - if (sc.ch == '\r' || sc.ch == '\n') { - sc.SetState(SCE_C_DEFAULT); - visibleChars = 0; - } - } else if (sc.state == SCE_C_COMMENTDOCKEYWORD) { - if (sc.Match('*', '/')) { - sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); - sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT); - } else if (!IsADoxygenChar(sc.ch)) { - char s[100]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); + break; + case SCE_C_PREPROCESSOR: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } else if (stylingWithinPreprocessor) { + if (IsASpace(sc.ch)) { + sc.SetState(SCE_C_DEFAULT); + } } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - if (!isspace(sc.ch) || !keywords3.InList(s + 1)) { - sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); + if (sc.Match('/', '*') || sc.Match('/', '/')) { + sc.SetState(SCE_C_DEFAULT); + } } - sc.SetState(SCE_C_COMMENTDOC); - } - } else if (sc.state == SCE_C_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + break; + case SCE_C_COMMENT: + if (sc.Match('*', '/')) { sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT); } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_C_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_C_STRINGEOL); - sc.ForwardSetState(SCE_C_DEFAULT); - visibleChars = 0; - } - } else if (sc.state == SCE_C_CHARACTER) { - if (sc.atLineEnd) { - sc.ChangeState(SCE_C_STRINGEOL); - sc.ForwardSetState(SCE_C_DEFAULT); - visibleChars = 0; - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + break; + case SCE_C_COMMENTDOC: + if (sc.Match('*', '/')) { sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_C_COMMENTDOC; + sc.SetState(SCE_C_COMMENTDOCKEYWORD); + } } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_C_DEFAULT); - } - } else if (sc.state == SCE_C_REGEX) { - if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == '/') { - sc.ForwardSetState(SCE_C_DEFAULT); - } else if (sc.ch == '\\') { - // Gobble up the quoted character - if (sc.chNext == '\\' || sc.chNext == '/') { - sc.Forward(); + break; + case SCE_C_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); } - } - } else if (sc.state == SCE_C_VERBATIM) { - if (sc.ch == '\"') { - if (sc.chNext == '\"') { + break; + case SCE_C_COMMENTLINEDOC: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC; + sc.SetState(SCE_C_COMMENTDOCKEYWORD); + } + } + break; + case SCE_C_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); sc.Forward(); - } else { sc.ForwardSetState(SCE_C_DEFAULT); + } else if (!IsADoxygenChar(sc.ch)) { + char s[100]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (!isspace(sc.ch) || !keywords3.InList(s + 1)) { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); + } + sc.SetState(styleBeforeDCKeyword); + } + break; + case SCE_C_STRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_C_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_C_DEFAULT); + } + break; + case SCE_C_CHARACTER: + if (sc.atLineEnd) { + sc.ChangeState(SCE_C_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_C_DEFAULT); + } + break; + case SCE_C_REGEX: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } else if (sc.ch == '/') { + sc.ForwardSetState(SCE_C_DEFAULT); + } else if (sc.ch == '\\') { + // Gobble up the quoted character + if (sc.chNext == '\\' || sc.chNext == '/') { + sc.Forward(); + } + } + break; + case SCE_C_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } + break; + case SCE_C_VERBATIM: + if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_C_DEFAULT); + } + } + break; + case SCE_C_UUID: + if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { + sc.SetState(SCE_C_DEFAULT); } - } - } else if (sc.state == SCE_C_UUID) { - if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { - sc.SetState(SCE_C_DEFAULT); - } } // Determine if a new state should be entered. @@ -244,7 +267,7 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo else sc.SetState(SCE_C_COMMENTLINE); } else if (sc.ch == '/' && IsOKBeforeRE(chPrevNonWhite)) { - sc.SetState(SCE_C_REGEX); + sc.SetState(SCE_C_REGEX); // JavaScript's RegEx } else if (sc.ch == '\"') { sc.SetState(SCE_C_STRING); } else if (sc.ch == '\'') { @@ -256,7 +279,7 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo do { sc.Forward(); } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); - if (sc.ch == '\r' || sc.ch == '\n') { + if (sc.atLineEnd) { sc.SetState(SCE_C_DEFAULT); } } else if (isoperator(static_cast<char>(sc.ch))) { @@ -264,13 +287,6 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo } } - if (sc.atLineEnd) { - // Reset states to begining of colourise so no surprises - // if different sets of lines lexed. - chPrevNonWhite = ' '; - visibleChars = 0; - lastWordWasUUID = false; - } if (!IsASpace(sc.ch)) { chPrevNonWhite = sc.ch; visibleChars++; |