]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexConf.cxx
23ed5a6c83fe1bcdc81046515522b525ea92729c
[wxWidgets.git] / src / stc / scintilla / lexers / LexConf.cxx
1 // Scintilla source code edit control
2 /** @file LexConf.cxx
3 ** Lexer for Apache Configuration Files.
4 **
5 ** First working version contributed by Ahmad Zawawi <ahmad.zawawi@gmail.com> on October 28, 2000.
6 ** i created this lexer because i needed something pretty when dealing
7 ** when Apache Configuration files...
8 **/
9 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
10 // The License.txt file describes the conditions under which this software may be distributed.
11
12 #include <stdlib.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include <stdarg.h>
16 #include <assert.h>
17 #include <ctype.h>
18
19 #include "ILexer.h"
20 #include "Scintilla.h"
21 #include "SciLexer.h"
22
23 #include "WordList.h"
24 #include "LexAccessor.h"
25 #include "Accessor.h"
26 #include "StyleContext.h"
27 #include "CharacterSet.h"
28 #include "LexerModule.h"
29
30 #ifdef SCI_NAMESPACE
31 using namespace Scintilla;
32 #endif
33
34 static void ColouriseConfDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
35 {
36 int state = SCE_CONF_DEFAULT;
37 char chNext = styler[startPos];
38 int lengthDoc = startPos + length;
39 // create a buffer large enough to take the largest chunk...
40 char *buffer = new char[length];
41 int bufferCount = 0;
42
43 // this assumes that we have 2 keyword list in conf.properties
44 WordList &directives = *keywordLists[0];
45 WordList &params = *keywordLists[1];
46
47 // go through all provided text segment
48 // using the hand-written state machine shown below
49 styler.StartAt(startPos);
50 styler.StartSegment(startPos);
51 for (int i = startPos; i < lengthDoc; i++) {
52 char ch = chNext;
53 chNext = styler.SafeGetCharAt(i + 1);
54
55 if (styler.IsLeadByte(ch)) {
56 chNext = styler.SafeGetCharAt(i + 2);
57 i++;
58 continue;
59 }
60 switch(state) {
61 case SCE_CONF_DEFAULT:
62 if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') {
63 // whitespace is simply ignored here...
64 styler.ColourTo(i,SCE_CONF_DEFAULT);
65 break;
66 } else if( ch == '#' ) {
67 // signals the start of a comment...
68 state = SCE_CONF_COMMENT;
69 styler.ColourTo(i,SCE_CONF_COMMENT);
70 } else if( ch == '.' /*|| ch == '/'*/) {
71 // signals the start of a file...
72 state = SCE_CONF_EXTENSION;
73 styler.ColourTo(i,SCE_CONF_EXTENSION);
74 } else if( ch == '"') {
75 state = SCE_CONF_STRING;
76 styler.ColourTo(i,SCE_CONF_STRING);
77 } else if( isascii(ch) && ispunct(ch) ) {
78 // signals an operator...
79 // no state jump necessary for this
80 // simple case...
81 styler.ColourTo(i,SCE_CONF_OPERATOR);
82 } else if( isascii(ch) && isalpha(ch) ) {
83 // signals the start of an identifier
84 bufferCount = 0;
85 buffer[bufferCount++] = static_cast<char>(tolower(ch));
86 state = SCE_CONF_IDENTIFIER;
87 } else if( isascii(ch) && isdigit(ch) ) {
88 // signals the start of a number
89 bufferCount = 0;
90 buffer[bufferCount++] = ch;
91 //styler.ColourTo(i,SCE_CONF_NUMBER);
92 state = SCE_CONF_NUMBER;
93 } else {
94 // style it the default style..
95 styler.ColourTo(i,SCE_CONF_DEFAULT);
96 }
97 break;
98
99 case SCE_CONF_COMMENT:
100 // if we find a newline here,
101 // we simply go to default state
102 // else continue to work on it...
103 if( ch == '\n' || ch == '\r' ) {
104 state = SCE_CONF_DEFAULT;
105 } else {
106 styler.ColourTo(i,SCE_CONF_COMMENT);
107 }
108 break;
109
110 case SCE_CONF_EXTENSION:
111 // if we find a non-alphanumeric char,
112 // we simply go to default state
113 // else we're still dealing with an extension...
114 if( (isascii(ch) && isalnum(ch)) || (ch == '_') ||
115 (ch == '-') || (ch == '$') ||
116 (ch == '/') || (ch == '.') || (ch == '*') )
117 {
118 styler.ColourTo(i,SCE_CONF_EXTENSION);
119 } else {
120 state = SCE_CONF_DEFAULT;
121 chNext = styler[i--];
122 }
123 break;
124
125 case SCE_CONF_STRING:
126 // if we find the end of a string char, we simply go to default state
127 // else we're still dealing with an string...
128 if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') || (ch == '\n') || (ch == '\r') ) {
129 state = SCE_CONF_DEFAULT;
130 }
131 styler.ColourTo(i,SCE_CONF_STRING);
132 break;
133
134 case SCE_CONF_IDENTIFIER:
135 // stay in CONF_IDENTIFIER state until we find a non-alphanumeric
136 if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') || (ch == '$') || (ch == '.') || (ch == '*')) {
137 buffer[bufferCount++] = static_cast<char>(tolower(ch));
138 } else {
139 state = SCE_CONF_DEFAULT;
140 buffer[bufferCount] = '\0';
141
142 // check if the buffer contains a keyword, and highlight it if it is a keyword...
143 if(directives.InList(buffer)) {
144 styler.ColourTo(i-1,SCE_CONF_DIRECTIVE );
145 } else if(params.InList(buffer)) {
146 styler.ColourTo(i-1,SCE_CONF_PARAMETER );
147 } else if(strchr(buffer,'/') || strchr(buffer,'.')) {
148 styler.ColourTo(i-1,SCE_CONF_EXTENSION);
149 } else {
150 styler.ColourTo(i-1,SCE_CONF_DEFAULT);
151 }
152
153 // push back the faulty character
154 chNext = styler[i--];
155
156 }
157 break;
158
159 case SCE_CONF_NUMBER:
160 // stay in CONF_NUMBER state until we find a non-numeric
161 if( (isascii(ch) && isdigit(ch)) || ch == '.') {
162 buffer[bufferCount++] = ch;
163 } else {
164 state = SCE_CONF_DEFAULT;
165 buffer[bufferCount] = '\0';
166
167 // Colourize here...
168 if( strchr(buffer,'.') ) {
169 // it is an IP address...
170 styler.ColourTo(i-1,SCE_CONF_IP);
171 } else {
172 // normal number
173 styler.ColourTo(i-1,SCE_CONF_NUMBER);
174 }
175
176 // push back a character
177 chNext = styler[i--];
178 }
179 break;
180
181 }
182 }
183 delete []buffer;
184 }
185
186 static const char * const confWordListDesc[] = {
187 "Directives",
188 "Parameters",
189 0
190 };
191
192 LexerModule lmConf(SCLEX_CONF, ColouriseConfDoc, "conf", 0, confWordListDesc);