| 184 | // Function colourising an excerpt of OScript code. |
| 185 | |
| 186 | static void ColouriseOScriptDoc(unsigned int startPos, int length, |
| 187 | int initStyle, WordList *keywordlists[], |
| 188 | Accessor &styler) { |
| 189 | // I wonder how whole-line styles ended by EOLN can escape the resetting |
| 190 | // code in the loop below and overflow to the next line. Let us make sure |
| 191 | // that a new line does not start with them carried from the previous one. |
| 192 | // NOTE: An overflowing string is intentionally not checked; it reminds |
| 193 | // the developer that the string must be ended on the same line. |
| 194 | if (initStyle == SCE_OSCRIPT_LINE_COMMENT || |
| 195 | initStyle == SCE_OSCRIPT_PREPROCESSOR) { |
| 196 | initStyle = SCE_OSCRIPT_DEFAULT; |
| 197 | } |
| 198 | |
| 199 | styler.StartAt(startPos); |
| 200 | StyleContext sc(startPos, length, initStyle, styler); |
| 201 | IdentifierClassifier identifierClassifier(keywordlists); |
| 202 | |
| 203 | // It starts with true at the beginning of a line and changes to false as |
| 204 | // soon as the first non-whitespace character has been processed. |
| 205 | bool isFirstToken = true; |
| 206 | // It starts with true at the beginning of a line and changes to false as |
| 207 | // soon as the first identifier on the line is passed by. |
| 208 | bool isFirstIdentifier = true; |
| 209 | // It becomes false when #ifdef DOC (the preprocessor directive often |
| 210 | // used to start a documentation comment) is encountered and remain false |
| 211 | // until the end of the documentation block is not detected. This is done |
| 212 | // by checking for the complementary #endif preprocessor directive. |
| 213 | bool endDocComment = false; |
| 214 | |
| 215 | for (; sc.More(); sc.Forward()) { |
| 216 | |
| 217 | if (sc.atLineStart) { |
| 218 | isFirstToken = true; |
| 219 | isFirstIdentifier = true; |
| 220 | // Detect the current state is neither whitespace nor identifier. It |
| 221 | // means that no next identifier can be the first token on the line. |
| 222 | } else if (isFirstIdentifier && sc.state != SCE_OSCRIPT_DEFAULT && |
| 223 | sc.state != SCE_OSCRIPT_IDENTIFIER) { |
| 224 | isFirstIdentifier = false; |
| 225 | } |
| 226 | |
| 227 | // Check if the current state should be changed. |
| 228 | if (sc.state == SCE_OSCRIPT_OPERATOR) { |
| 229 | // Multiple-symbol operators are marked by single characters. |
| 230 | sc.SetState(SCE_OSCRIPT_DEFAULT); |
| 231 | } else if (sc.state == SCE_OSCRIPT_IDENTIFIER) { |
| 232 | if (!IsIdentifierChar(sc.ch)) { |
| 233 | // Colon after an identifier makes it a label if it is the |
| 234 | // first token on the line. |
| 235 | // KNOWN PROBLEM: If some whitespace is inserted between the |
| 236 | // identifier and the colon they will not be recognized as a |
| 237 | // label. This should not occur; at least not often. It would |
| 238 | // make the code structure less legible and examples in the |
| 239 | // Livelink documentation do not show it. |
| 240 | if (sc.Match(':') && isFirstIdentifier) { |
| 241 | sc.ChangeState(SCE_OSCRIPT_LABEL); |
| 242 | sc.ForwardSetState(SCE_OSCRIPT_DEFAULT); |
| 243 | } else { |
nothing calls this directly
no test coverage detected