Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <svtools/syntaxhighlight.hxx>
31 : :
32 : : #include <unotools/charclass.hxx>
33 : : #include <comphelper/string.hxx>
34 : :
35 : : // ##########################################################################
36 : : // ATTENTION: all these words needs to be in small caps
37 : : // ##########################################################################
38 : : static const char* strListBasicKeyWords[] = {
39 : : "access",
40 : : "alias",
41 : : "and",
42 : : "any",
43 : : "append",
44 : : "as",
45 : : "base",
46 : : "binary",
47 : : "boolean",
48 : : "byref",
49 : : "byte",
50 : : "byval",
51 : : "call",
52 : : "case",
53 : : "cdecl",
54 : : "classmodule",
55 : : "close",
56 : : "compare",
57 : : "compatible",
58 : : "const",
59 : : "currency",
60 : : "date",
61 : : "declare",
62 : : "defbool",
63 : : "defcur",
64 : : "defdate",
65 : : "defdbl",
66 : : "deferr",
67 : : "defint",
68 : : "deflng",
69 : : "defobj",
70 : : "defsng",
71 : : "defstr",
72 : : "defvar",
73 : : "dim",
74 : : "do",
75 : : "double",
76 : : "each",
77 : : "else",
78 : : "elseif",
79 : : "end",
80 : : "end enum",
81 : : "end function",
82 : : "end if",
83 : : "end select",
84 : : "end sub",
85 : : "end type",
86 : : "endif",
87 : : "enum",
88 : : "eqv",
89 : : "erase",
90 : : "error",
91 : : "exit",
92 : : "explicit",
93 : : "for",
94 : : "function",
95 : : "get",
96 : : "global",
97 : : "gosub",
98 : : "goto",
99 : : "if",
100 : : "imp",
101 : : "implements",
102 : : "in",
103 : : "input",
104 : : "integer",
105 : : "is",
106 : : "let",
107 : : "lib",
108 : : "like",
109 : : "line",
110 : : "line input",
111 : : "local",
112 : : "lock",
113 : : "long",
114 : : "loop",
115 : : "lprint",
116 : : "lset",
117 : : "mod",
118 : : "name",
119 : : "new",
120 : : "next",
121 : : "not",
122 : : "object",
123 : : "on",
124 : : "open",
125 : : "option",
126 : : "optional",
127 : : "or",
128 : : "output",
129 : : "preserve",
130 : : "print",
131 : : "private",
132 : : "property",
133 : : "public",
134 : : "random",
135 : : "read",
136 : : "redim",
137 : : "rem",
138 : : "resume",
139 : : "return",
140 : : "rset",
141 : : "select",
142 : : "set",
143 : : "shared",
144 : : "single",
145 : : "static",
146 : : "step",
147 : : "stop",
148 : : "string",
149 : : "sub",
150 : : "system",
151 : : "text",
152 : : "then",
153 : : "to",
154 : : "type",
155 : : "typeof",
156 : : "until",
157 : : "variant",
158 : : "wend",
159 : : "while",
160 : : "with",
161 : : "write",
162 : : "xor"
163 : : };
164 : :
165 : :
166 : : static const char* strListSqlKeyWords[] = {
167 : : "all",
168 : : "and",
169 : : "any",
170 : : "as",
171 : : "asc",
172 : : "avg",
173 : : "between",
174 : : "by",
175 : : "cast",
176 : : "corresponding",
177 : : "count",
178 : : "create",
179 : : "cross",
180 : : "delete",
181 : : "desc",
182 : : "distinct",
183 : : "drop",
184 : : "escape",
185 : : "except",
186 : : "exists",
187 : : "false",
188 : : "from",
189 : : "full",
190 : : "global",
191 : : "group",
192 : : "having",
193 : : "in",
194 : : "inner",
195 : : "insert",
196 : : "intersect",
197 : : "into",
198 : : "is",
199 : : "join",
200 : : "left",
201 : : "like",
202 : : "local",
203 : : "match",
204 : : "max",
205 : : "min",
206 : : "natural",
207 : : "not",
208 : : "null",
209 : : "on",
210 : : "or",
211 : : "order",
212 : : "outer",
213 : : "right",
214 : : "select",
215 : : "set",
216 : : "some",
217 : : "sum",
218 : : "table",
219 : : "temporary",
220 : : "true",
221 : : "union",
222 : : "unique",
223 : : "unknown",
224 : : "update",
225 : : "using",
226 : : "values",
227 : : "where"
228 : : };
229 : :
230 : :
231 : 0 : extern "C" int CDECL compare_strings( const void *arg1, const void *arg2 )
232 : : {
233 : 0 : return strcmp( (char *)arg1, *(char **)arg2 );
234 : : }
235 : :
236 : :
237 : : namespace
238 : : {
239 : :
240 : : class LetterTable
241 : : {
242 : : bool IsLetterTab[256];
243 : :
244 : : public:
245 : : LetterTable( void );
246 : :
247 : 0 : inline bool isLetter( sal_Unicode c )
248 : : {
249 [ # # ]: 0 : bool bRet = (c < 256) ? IsLetterTab[c] : isLetterUnicode( c );
250 : 0 : return bRet;
251 : : }
252 : : bool isLetterUnicode( sal_Unicode c );
253 : : };
254 : :
255 : 0 : static bool isAlpha(sal_Unicode c)
256 : : {
257 [ # # ]: 0 : if (comphelper::string::isalphaAscii(c))
258 : 0 : return true;
259 [ # # ][ # # ]: 0 : static LetterTable aLetterTable;
260 : 0 : return aLetterTable.isLetter(c);
261 : : }
262 : : }
263 : :
264 : 0 : LetterTable::LetterTable( void )
265 : : {
266 [ # # ]: 0 : for( int i = 0 ; i < 256 ; ++i )
267 : 0 : IsLetterTab[i] = false;
268 : :
269 : 0 : IsLetterTab[0xC0] = true; // ?, CAPITAL LETTER A WITH GRAVE ACCENT
270 : 0 : IsLetterTab[0xC1] = true; // ?, CAPITAL LETTER A WITH ACUTE ACCENT
271 : 0 : IsLetterTab[0xC2] = true; // ?, CAPITAL LETTER A WITH CIRCUMFLEX ACCENT
272 : 0 : IsLetterTab[0xC3] = true; // ?, CAPITAL LETTER A WITH TILDE
273 : 0 : IsLetterTab[0xC4] = true; // ?, CAPITAL LETTER A WITH DIAERESIS
274 : 0 : IsLetterTab[0xC5] = true; // ?, CAPITAL LETTER A WITH RING ABOVE
275 : 0 : IsLetterTab[0xC6] = true; // ?, CAPITAL LIGATURE AE
276 : 0 : IsLetterTab[0xC7] = true; // ?, CAPITAL LETTER C WITH CEDILLA
277 : 0 : IsLetterTab[0xC8] = true; // ?, CAPITAL LETTER E WITH GRAVE ACCENT
278 : 0 : IsLetterTab[0xC9] = true; // ?, CAPITAL LETTER E WITH ACUTE ACCENT
279 : 0 : IsLetterTab[0xCA] = true; // ?, CAPITAL LETTER E WITH CIRCUMFLEX ACCENT
280 : 0 : IsLetterTab[0xCB] = true; // ?, CAPITAL LETTER E WITH DIAERESIS
281 : 0 : IsLetterTab[0xCC] = true; // ?, CAPITAL LETTER I WITH GRAVE ACCENT
282 : 0 : IsLetterTab[0xCD] = true; // ?, CAPITAL LETTER I WITH ACUTE ACCENT
283 : 0 : IsLetterTab[0xCE] = true; // ?, CAPITAL LETTER I WITH CIRCUMFLEX ACCENT
284 : 0 : IsLetterTab[0xCF] = true; // ?, CAPITAL LETTER I WITH DIAERESIS
285 : 0 : IsLetterTab[0xD0] = true; // ?, CAPITAL LETTER ETH
286 : 0 : IsLetterTab[0xD1] = true; // ?, CAPITAL LETTER N WITH TILDE
287 : 0 : IsLetterTab[0xD2] = true; // ?, CAPITAL LETTER O WITH GRAVE ACCENT
288 : 0 : IsLetterTab[0xD3] = true; // ?, CAPITAL LETTER O WITH ACUTE ACCENT
289 : 0 : IsLetterTab[0xD4] = true; // ?, CAPITAL LETTER O WITH CIRCUMFLEX ACCENT
290 : 0 : IsLetterTab[0xD5] = true; // ?, CAPITAL LETTER O WITH TILDE
291 : 0 : IsLetterTab[0xD6] = true; // ?, CAPITAL LETTER O WITH DIAERESIS
292 : 0 : IsLetterTab[0xD8] = true; // ?, CAPITAL LETTER O WITH STROKE
293 : 0 : IsLetterTab[0xD9] = true; // ?, CAPITAL LETTER U WITH GRAVE ACCENT
294 : 0 : IsLetterTab[0xDA] = true; // ?, CAPITAL LETTER U WITH ACUTE ACCENT
295 : 0 : IsLetterTab[0xDB] = true; // ?, CAPITAL LETTER U WITH CIRCUMFLEX ACCENT
296 : 0 : IsLetterTab[0xDC] = true; // ?, CAPITAL LETTER U WITH DIAERESIS
297 : 0 : IsLetterTab[0xDD] = true; // ?, CAPITAL LETTER Y WITH ACUTE ACCENT
298 : 0 : IsLetterTab[0xDE] = true; // ?, CAPITAL LETTER THORN
299 : 0 : IsLetterTab[0xDF] = true; // ?, SMALL LETTER SHARP S
300 : 0 : IsLetterTab[0xE0] = true; // ?, SMALL LETTER A WITH GRAVE ACCENT
301 : 0 : IsLetterTab[0xE1] = true; // ?, SMALL LETTER A WITH ACUTE ACCENT
302 : 0 : IsLetterTab[0xE2] = true; // ?, SMALL LETTER A WITH CIRCUMFLEX ACCENT
303 : 0 : IsLetterTab[0xE3] = true; // ?, SMALL LETTER A WITH TILDE
304 : 0 : IsLetterTab[0xE4] = true; // ?, SMALL LETTER A WITH DIAERESIS
305 : 0 : IsLetterTab[0xE5] = true; // ?, SMALL LETTER A WITH RING ABOVE
306 : 0 : IsLetterTab[0xE6] = true; // ?, SMALL LIGATURE AE
307 : 0 : IsLetterTab[0xE7] = true; // ?, SMALL LETTER C WITH CEDILLA
308 : 0 : IsLetterTab[0xE8] = true; // ?, SMALL LETTER E WITH GRAVE ACCENT
309 : 0 : IsLetterTab[0xE9] = true; // ?, SMALL LETTER E WITH ACUTE ACCENT
310 : 0 : IsLetterTab[0xEA] = true; // ?, SMALL LETTER E WITH CIRCUMFLEX ACCENT
311 : 0 : IsLetterTab[0xEB] = true; // ?, SMALL LETTER E WITH DIAERESIS
312 : 0 : IsLetterTab[0xEC] = true; // ?, SMALL LETTER I WITH GRAVE ACCENT
313 : 0 : IsLetterTab[0xED] = true; // ?, SMALL LETTER I WITH ACUTE ACCENT
314 : 0 : IsLetterTab[0xEE] = true; // ?, SMALL LETTER I WITH CIRCUMFLEX ACCENT
315 : 0 : IsLetterTab[0xEF] = true; // ?, SMALL LETTER I WITH DIAERESIS
316 : 0 : IsLetterTab[0xF0] = true; // ?, SMALL LETTER ETH
317 : 0 : IsLetterTab[0xF1] = true; // ?, SMALL LETTER N WITH TILDE
318 : 0 : IsLetterTab[0xF2] = true; // ?, SMALL LETTER O WITH GRAVE ACCENT
319 : 0 : IsLetterTab[0xF3] = true; // ?, SMALL LETTER O WITH ACUTE ACCENT
320 : 0 : IsLetterTab[0xF4] = true; // ?, SMALL LETTER O WITH CIRCUMFLEX ACCENT
321 : 0 : IsLetterTab[0xF5] = true; // ?, SMALL LETTER O WITH TILDE
322 : 0 : IsLetterTab[0xF6] = true; // ?, SMALL LETTER O WITH DIAERESIS
323 : 0 : IsLetterTab[0xF8] = true; // ?, SMALL LETTER O WITH OBLIQUE BAR
324 : 0 : IsLetterTab[0xF9] = true; // ?, SMALL LETTER U WITH GRAVE ACCENT
325 : 0 : IsLetterTab[0xFA] = true; // ?, SMALL LETTER U WITH ACUTE ACCENT
326 : 0 : IsLetterTab[0xFB] = true; // ?, SMALL LETTER U WITH CIRCUMFLEX ACCENT
327 : 0 : IsLetterTab[0xFC] = true; // ?, SMALL LETTER U WITH DIAERESIS
328 : 0 : IsLetterTab[0xFD] = true; // ?, SMALL LETTER Y WITH ACUTE ACCENT
329 : 0 : IsLetterTab[0xFE] = true; // ?, SMALL LETTER THORN
330 : 0 : IsLetterTab[0xFF] = true; // � , SMALL LETTER Y WITH DIAERESIS
331 : 0 : }
332 : :
333 : 0 : bool LetterTable::isLetterUnicode( sal_Unicode c )
334 : : {
335 : : static CharClass* pCharClass = NULL;
336 [ # # ]: 0 : if( pCharClass == NULL )
337 [ # # ][ # # ]: 0 : pCharClass = new CharClass( Application::GetSettings().GetLocale() );
[ # # ][ # # ]
338 : 0 : rtl::OUString aStr( c );
339 [ # # ][ # # ]: 0 : bool bRet = pCharClass->isLetter( aStr, 0 );
[ # # ]
340 : 0 : return bRet;
341 : : }
342 : :
343 : : // Hilfsfunktion: Zeichen-Flag Testen
344 : 0 : sal_Bool SimpleTokenizer_Impl::testCharFlags( sal_Unicode c, sal_uInt16 nTestFlags )
345 : : {
346 : 0 : bool bRet = false;
347 [ # # ][ # # ]: 0 : if( c != 0 && c <= 255 )
348 : : {
349 : 0 : bRet = ( (aCharTypeTab[c] & nTestFlags) != 0 );
350 : : }
351 [ # # ]: 0 : else if( c > 255 )
352 : : {
353 : : bRet = (( CHAR_START_IDENTIFIER | CHAR_IN_IDENTIFIER ) & nTestFlags) != 0
354 [ # # ]: 0 : ? isAlpha(c) : false;
355 : : }
356 : 0 : return bRet;
357 : : }
358 : :
359 : 0 : void SimpleTokenizer_Impl::setKeyWords( const char** ppKeyWords, sal_uInt16 nCount )
360 : : {
361 : 0 : ppListKeyWords = ppKeyWords;
362 : 0 : nKeyWordCount = nCount;
363 : 0 : }
364 : :
365 : : // Neues Token holen
366 : 0 : sal_Bool SimpleTokenizer_Impl::getNextToken( /*out*/TokenTypes& reType,
367 : : /*out*/const sal_Unicode*& rpStartPos, /*out*/const sal_Unicode*& rpEndPos )
368 : : {
369 : 0 : reType = TT_UNKNOWN;
370 : :
371 : : // Position merken
372 : 0 : rpStartPos = mpActualPos;
373 : :
374 : : // Zeichen untersuchen
375 : 0 : sal_Unicode c = peekChar();
376 [ # # ]: 0 : if( c == CHAR_EOF )
377 : 0 : return sal_False;
378 : :
379 : : // Zeichen lesen
380 : 0 : getChar();
381 : :
382 : : //*** Alle Moeglichkeiten durchgehen ***
383 : : // Space?
384 [ # # ]: 0 : if ( (testCharFlags( c, CHAR_SPACE ) == sal_True) )
385 : : {
386 [ # # ]: 0 : while( testCharFlags( peekChar(), CHAR_SPACE ) == sal_True )
387 : 0 : getChar();
388 : :
389 : 0 : reType = TT_WHITESPACE;
390 : : }
391 : :
392 : : // Identifier?
393 [ # # ]: 0 : else if ( (testCharFlags( c, CHAR_START_IDENTIFIER ) == sal_True) )
394 : : {
395 : : sal_Bool bIdentifierChar;
396 [ # # ]: 0 : do
397 : : {
398 : : // Naechstes Zeichen holen
399 : 0 : c = peekChar();
400 : 0 : bIdentifierChar = testCharFlags( c, CHAR_IN_IDENTIFIER );
401 [ # # ]: 0 : if( bIdentifierChar )
402 : 0 : getChar();
403 : : }
404 : : while( bIdentifierChar );
405 : :
406 : 0 : reType = TT_IDENTIFIER;
407 : :
408 : : // Schluesselwort-Tabelle
409 [ # # ]: 0 : if (ppListKeyWords != NULL)
410 : : {
411 : 0 : int nCount = mpActualPos - rpStartPos;
412 : :
413 : : // No keyword if string contains char > 255
414 : 0 : bool bCanBeKeyword = true;
415 [ # # ]: 0 : for( int i = 0 ; i < nCount ; i++ )
416 : : {
417 [ # # ]: 0 : if( rpStartPos[i] > 255 )
418 : : {
419 : 0 : bCanBeKeyword = false;
420 : 0 : break;
421 : : }
422 : : }
423 : :
424 [ # # ]: 0 : if( bCanBeKeyword )
425 : : {
426 : 0 : rtl::OUString aKWString(rpStartPos, nCount);
427 : : rtl::OString aByteStr = rtl::OUStringToOString(aKWString,
428 [ # # ]: 0 : RTL_TEXTENCODING_ASCII_US).toAsciiLowerCase();
429 [ # # ]: 0 : if ( bsearch( aByteStr.getStr(), ppListKeyWords, nKeyWordCount, sizeof( char* ),
430 [ # # ]: 0 : compare_strings ) )
431 : : {
432 : 0 : reType = TT_KEYWORDS;
433 : :
434 [ # # ]: 0 : if (aByteStr.equalsL(RTL_CONSTASCII_STRINGPARAM("rem")))
435 : : {
436 : : // Alle Zeichen bis Zeilen-Ende oder EOF entfernen
437 : 0 : sal_Unicode cPeek = peekChar();
438 [ # # ][ # # ]: 0 : while( cPeek != CHAR_EOF && testCharFlags( cPeek, CHAR_EOL ) == sal_False )
[ # # ][ # # ]
439 : : {
440 : 0 : c = getChar();
441 : 0 : cPeek = peekChar();
442 : : }
443 : :
444 : 0 : reType = TT_COMMENT;
445 : : }
446 : 0 : }
447 : : }
448 : : }
449 : : }
450 : :
451 : : // Operator?
452 : : // only for BASIC '\'' should be a comment, otherwise it is a normal string and handled there
453 [ # # ][ # # ]: 0 : else if ( ( testCharFlags( c, CHAR_OPERATOR ) == sal_True ) || ( (c == '\'') && (aLanguage==HIGHLIGHT_BASIC)) )
[ # # ][ # # ]
454 : : {
455 : : // parameters for SQL view
456 [ # # ][ # # ]: 0 : if ( (c==':') || (c=='?'))
457 : : {
458 [ # # ]: 0 : if (c!='?')
459 : : {
460 : : sal_Bool bIdentifierChar;
461 [ # # ]: 0 : do
462 : : {
463 : : // Naechstes Zeichen holen
464 : 0 : c = peekChar();
465 : 0 : bIdentifierChar = isAlpha(c);
466 [ # # ]: 0 : if( bIdentifierChar )
467 : 0 : getChar();
468 : : }
469 : : while( bIdentifierChar );
470 : : }
471 : 0 : reType = TT_PARAMETER;
472 : : }
473 [ # # ]: 0 : else if (c=='-')
474 : : {
475 : 0 : sal_Unicode cPeekNext = peekChar();
476 [ # # ]: 0 : if (cPeekNext=='-')
477 : : {
478 : : // Alle Zeichen bis Zeilen-Ende oder EOF entfernen
479 [ # # ][ # # ]: 0 : while( cPeekNext != CHAR_EOF && testCharFlags( cPeekNext, CHAR_EOL ) == sal_False )
[ # # ]
480 : : {
481 : 0 : getChar();
482 : 0 : cPeekNext = peekChar();
483 : : }
484 : 0 : reType = TT_COMMENT;
485 : : }
486 : : }
487 [ # # ]: 0 : else if (c=='/')
488 : : {
489 : 0 : sal_Unicode cPeekNext = peekChar();
490 [ # # ]: 0 : if (cPeekNext=='/')
491 : : {
492 : : // Alle Zeichen bis Zeilen-Ende oder EOF entfernen
493 [ # # ][ # # ]: 0 : while( cPeekNext != CHAR_EOF && testCharFlags( cPeekNext, CHAR_EOL ) == sal_False )
[ # # ]
494 : : {
495 : 0 : getChar();
496 : 0 : cPeekNext = peekChar();
497 : : }
498 : 0 : reType = TT_COMMENT;
499 : : }
500 : : }
501 : : else
502 : : {
503 : : // Kommentar ?
504 [ # # ]: 0 : if ( c == '\'' )
505 : : {
506 : 0 : c = getChar(); // '/' entfernen
507 : :
508 : : // Alle Zeichen bis Zeilen-Ende oder EOF entfernen
509 : 0 : sal_Unicode cPeek = c;
510 [ # # ][ # # ]: 0 : while( cPeek != CHAR_EOF && testCharFlags( cPeek, CHAR_EOL ) == sal_False )
[ # # ]
511 : : {
512 : 0 : getChar();
513 : 0 : cPeek = peekChar();
514 : : }
515 : :
516 : 0 : reType = TT_COMMENT;
517 : : }
518 : :
519 : : // Echter Operator, kann hier einfach behandelt werden,
520 : : // da nicht der wirkliche Operator, wie z.B. += interessiert,
521 : : // sondern nur die Tatsache, dass es sich um einen handelt.
522 [ # # ]: 0 : if( reType != TT_COMMENT )
523 : : {
524 : 0 : reType = TT_OPERATOR;
525 : : }
526 : :
527 : : }
528 : : }
529 : :
530 : : // Objekt-Trenner? Muss vor Number abgehandelt werden
531 [ # # ][ # # ]: 0 : else if( c == '.' && ( peekChar() < '0' || peekChar() > '9' ) )
[ # # ][ # # ]
532 : : {
533 : 0 : reType = TT_OPERATOR;
534 : : }
535 : :
536 : : // Zahl?
537 [ # # ]: 0 : else if( testCharFlags( c, CHAR_START_NUMBER ) == sal_True )
538 : : {
539 : 0 : reType = TT_NUMBER;
540 : :
541 : : // Zahlensystem, 10 = normal, wird bei Oct/Hex geaendert
542 : 0 : int nRadix = 10;
543 : :
544 : : // Ist es eine Hex- oder Oct-Zahl?
545 [ # # ]: 0 : if( c == '&' )
546 : : {
547 : : // Octal?
548 [ # # ][ # # ]: 0 : if( peekChar() == 'o' || peekChar() == 'O' )
[ # # ]
549 : : {
550 : : // o entfernen
551 : 0 : getChar();
552 : 0 : nRadix = 8; // Octal-Basis
553 : :
554 : : // Alle Ziffern einlesen
555 [ # # ]: 0 : while( testCharFlags( peekChar(), CHAR_IN_OCT_NUMBER ) )
556 : 0 : c = getChar();
557 : : }
558 : : // Hex?
559 [ # # ][ # # ]: 0 : else if( peekChar() == 'h' || peekChar() == 'H' )
[ # # ]
560 : : {
561 : : // x entfernen
562 : 0 : getChar();
563 : 0 : nRadix = 16; // Hex-Basis
564 : :
565 : : // Alle Ziffern einlesen und puffern
566 [ # # ]: 0 : while( testCharFlags( peekChar(), CHAR_IN_HEX_NUMBER ) )
567 : 0 : c = getChar();
568 : : }
569 : : else
570 : : {
571 : 0 : reType = TT_OPERATOR;
572 : : }
573 : : }
574 : :
575 : : // Wenn nicht Oct oder Hex als double ansehen
576 [ # # ][ # # ]: 0 : if( reType == TT_NUMBER && nRadix == 10 )
577 : : {
578 : : // Flag, ob das letzte Zeichen ein Exponent war
579 : 0 : sal_Bool bAfterExpChar = sal_False;
580 : :
581 : : // Alle Ziffern einlesen
582 [ # # ]: 0 : while( testCharFlags( peekChar(), CHAR_IN_NUMBER ) ||
[ # # # # ]
[ # # # # ]
[ # # ]
583 : 0 : (bAfterExpChar && peekChar() == '+' ) ||
584 : 0 : (bAfterExpChar && peekChar() == '-' ) )
585 : : // Nach Exponent auch +/- OK
586 : : {
587 : 0 : c = getChar(); // Zeichen lesen
588 [ # # ][ # # ]: 0 : bAfterExpChar = ( c == 'e' || c == 'E' );
589 : : }
590 : : }
591 : :
592 : : // reType = TT_NUMBER;
593 : : }
594 : :
595 : : // String?
596 [ # # ]: 0 : else if( testCharFlags( c, CHAR_START_STRING ) == sal_True )
597 : : {
598 : : // Merken, welches Zeichen den String eroeffnet hat
599 : 0 : sal_Unicode cEndString = c;
600 [ # # ]: 0 : if( c == '[' )
601 : 0 : cEndString = ']';
602 : :
603 : : // Alle Ziffern einlesen und puffern
604 [ # # ]: 0 : while( peekChar() != cEndString )
605 : : {
606 : : // #58846 EOF vor getChar() abfangen, damit EOF micht verloren geht
607 [ # # ]: 0 : if( peekChar() == CHAR_EOF )
608 : : {
609 : : // ERROR: unterminated string literal
610 : 0 : reType = TT_ERROR;
611 : 0 : break;
612 : : }
613 : 0 : c = getChar();
614 [ # # ]: 0 : if( testCharFlags( c, CHAR_EOL ) == sal_True )
615 : : {
616 : : // ERROR: unterminated string literal
617 : 0 : reType = TT_ERROR;
618 : 0 : break;
619 : : }
620 : : }
621 : :
622 : : // Zeichen lesen
623 [ # # ]: 0 : if( reType != TT_ERROR )
624 : : {
625 : 0 : getChar();
626 [ # # ]: 0 : if( cEndString == ']' )
627 : 0 : reType = TT_IDENTIFIER;
628 : : else
629 : 0 : reType = TT_STRING;
630 : : }
631 : : }
632 : :
633 : : // Zeilenende?
634 [ # # ]: 0 : else if( testCharFlags( c, CHAR_EOL ) == sal_True )
635 : : {
636 : : // Falls ein weiteres anderes EOL-Char folgt, weg damit
637 : 0 : sal_Unicode cNext = peekChar();
638 [ # # ][ # # ]: 0 : if( cNext != c && testCharFlags( cNext, CHAR_EOL ) == sal_True )
[ # # ]
639 : 0 : getChar();
640 : :
641 : : // Positions-Daten auf Zeilen-Beginn setzen
642 : 0 : nCol = 0;
643 : 0 : nLine++;
644 : :
645 : 0 : reType = TT_EOL;
646 : : }
647 : :
648 : : // Alles andere bleibt TT_UNKNOWN
649 : :
650 : :
651 : : // End-Position eintragen
652 : 0 : rpEndPos = mpActualPos;
653 : 0 : return sal_True;
654 : : }
655 : :
656 : 0 : SimpleTokenizer_Impl::SimpleTokenizer_Impl( HighlighterLanguage aLang ): aLanguage(aLang)
657 : : {
658 : 0 : memset( aCharTypeTab, 0, sizeof( aCharTypeTab ) );
659 : :
660 : : // Zeichen-Tabelle fuellen
661 : : sal_uInt16 i;
662 : :
663 : : // Zulaessige Zeichen fuer Identifier
664 : 0 : sal_uInt16 nHelpMask = (sal_uInt16)( CHAR_START_IDENTIFIER | CHAR_IN_IDENTIFIER );
665 [ # # ]: 0 : for( i = 'a' ; i <= 'z' ; i++ )
666 : 0 : aCharTypeTab[i] |= nHelpMask;
667 [ # # ]: 0 : for( i = 'A' ; i <= 'Z' ; i++ )
668 : 0 : aCharTypeTab[i] |= nHelpMask;
669 : : // '_' extra eintragen
670 : 0 : aCharTypeTab[(int)'_'] |= nHelpMask;
671 : : // AB 23.6.97: '$' ist auch erlaubt
672 : 0 : aCharTypeTab[(int)'$'] |= nHelpMask;
673 : :
674 : : // Ziffern (Identifier und Number ist moeglich)
675 : : nHelpMask = (sal_uInt16)( CHAR_IN_IDENTIFIER | CHAR_START_NUMBER |
676 : 0 : CHAR_IN_NUMBER | CHAR_IN_HEX_NUMBER );
677 [ # # ]: 0 : for( i = '0' ; i <= '9' ; i++ )
678 : 0 : aCharTypeTab[i] |= nHelpMask;
679 : :
680 : : // e und E sowie . von Hand ergaenzen
681 : 0 : aCharTypeTab[(int)'e'] |= CHAR_IN_NUMBER;
682 : 0 : aCharTypeTab[(int)'E'] |= CHAR_IN_NUMBER;
683 : 0 : aCharTypeTab[(int)'.'] |= (sal_uInt16)( CHAR_IN_NUMBER | CHAR_START_NUMBER );
684 : 0 : aCharTypeTab[(int)'&'] |= CHAR_START_NUMBER;
685 : :
686 : : // Hex-Ziffern
687 [ # # ]: 0 : for( i = 'a' ; i <= 'f' ; i++ )
688 : 0 : aCharTypeTab[i] |= CHAR_IN_HEX_NUMBER;
689 [ # # ]: 0 : for( i = 'A' ; i <= 'F' ; i++ )
690 : 0 : aCharTypeTab[i] |= CHAR_IN_HEX_NUMBER;
691 : :
692 : : // Oct-Ziffern
693 [ # # ]: 0 : for( i = '0' ; i <= '7' ; i++ )
694 : 0 : aCharTypeTab[i] |= CHAR_IN_OCT_NUMBER;
695 : :
696 : : // String-Beginn/End-Zeichen
697 : 0 : aCharTypeTab[(int)'\''] |= CHAR_START_STRING;
698 : 0 : aCharTypeTab[(int)'\"'] |= CHAR_START_STRING;
699 : 0 : aCharTypeTab[(int)'['] |= CHAR_START_STRING;
700 : 0 : aCharTypeTab[(int)'`'] |= CHAR_START_STRING;
701 : :
702 : : // Operator-Zeichen
703 : 0 : aCharTypeTab[(int)'!'] |= CHAR_OPERATOR;
704 : 0 : aCharTypeTab[(int)'%'] |= CHAR_OPERATOR;
705 : : // aCharTypeTab[(int)'&'] |= CHAR_OPERATOR; Removed because of #i14140
706 : 0 : aCharTypeTab[(int)'('] |= CHAR_OPERATOR;
707 : 0 : aCharTypeTab[(int)')'] |= CHAR_OPERATOR;
708 : 0 : aCharTypeTab[(int)'*'] |= CHAR_OPERATOR;
709 : 0 : aCharTypeTab[(int)'+'] |= CHAR_OPERATOR;
710 : 0 : aCharTypeTab[(int)','] |= CHAR_OPERATOR;
711 : 0 : aCharTypeTab[(int)'-'] |= CHAR_OPERATOR;
712 : 0 : aCharTypeTab[(int)'/'] |= CHAR_OPERATOR;
713 : 0 : aCharTypeTab[(int)':'] |= CHAR_OPERATOR;
714 : 0 : aCharTypeTab[(int)'<'] |= CHAR_OPERATOR;
715 : 0 : aCharTypeTab[(int)'='] |= CHAR_OPERATOR;
716 : 0 : aCharTypeTab[(int)'>'] |= CHAR_OPERATOR;
717 : 0 : aCharTypeTab[(int)'?'] |= CHAR_OPERATOR;
718 : 0 : aCharTypeTab[(int)'^'] |= CHAR_OPERATOR;
719 : 0 : aCharTypeTab[(int)'|'] |= CHAR_OPERATOR;
720 : 0 : aCharTypeTab[(int)'~'] |= CHAR_OPERATOR;
721 : 0 : aCharTypeTab[(int)'{'] |= CHAR_OPERATOR;
722 : 0 : aCharTypeTab[(int)'}'] |= CHAR_OPERATOR;
723 : : // aCharTypeTab[(int)'['] |= CHAR_OPERATOR; Removed because of #i17826
724 : 0 : aCharTypeTab[(int)']'] |= CHAR_OPERATOR;
725 : 0 : aCharTypeTab[(int)';'] |= CHAR_OPERATOR;
726 : :
727 : : // Space
728 : 0 : aCharTypeTab[(int)' ' ] |= CHAR_SPACE;
729 : 0 : aCharTypeTab[(int)'\t'] |= CHAR_SPACE;
730 : :
731 : : // Zeilen-Ende-Zeichen
732 : 0 : aCharTypeTab[(int)'\r'] |= CHAR_EOL;
733 : 0 : aCharTypeTab[(int)'\n'] |= CHAR_EOL;
734 : :
735 : 0 : ppListKeyWords = NULL;
736 : 0 : }
737 : :
738 : 0 : SimpleTokenizer_Impl::~SimpleTokenizer_Impl( void )
739 : : {
740 : 0 : }
741 : :
742 : 0 : SimpleTokenizer_Impl* getSimpleTokenizer( void )
743 : : {
744 : : static SimpleTokenizer_Impl* pSimpleTokenizer = NULL;
745 [ # # ]: 0 : if( !pSimpleTokenizer )
746 : 0 : pSimpleTokenizer = new SimpleTokenizer_Impl();
747 : 0 : return pSimpleTokenizer;
748 : : }
749 : :
750 : : // Heraussuchen der jeweils naechsten Funktion aus einem JavaScript-Modul
751 : 0 : sal_uInt16 SimpleTokenizer_Impl::parseLine( sal_uInt32 nParseLine, const String* aSource )
752 : : {
753 : : // Position auf den Anfang des Source-Strings setzen
754 : 0 : mpStringBegin = mpActualPos = aSource->GetBuffer();
755 : :
756 : : // Zeile und Spalte initialisieren
757 : 0 : nLine = nParseLine;
758 : 0 : nCol = 0L;
759 : :
760 : : // Variablen fuer die Out-Parameter
761 : : TokenTypes eType;
762 : : const sal_Unicode* pStartPos;
763 : : const sal_Unicode* pEndPos;
764 : :
765 : : // Schleife ueber alle Tokens
766 : 0 : sal_uInt16 nTokenCount = 0;
767 [ # # ][ # # ]: 0 : while( getNextToken( eType, pStartPos, pEndPos ) )
768 : 0 : nTokenCount++;
769 : :
770 : 0 : return nTokenCount;
771 : : }
772 : :
773 : 0 : void SimpleTokenizer_Impl::getHighlightPortions( sal_uInt32 nParseLine, const String& rLine,
774 : : /*out*/HighlightPortions& portions )
775 : : {
776 : : // Position auf den Anfang des Source-Strings setzen
777 : 0 : mpStringBegin = mpActualPos = rLine.GetBuffer();
778 : :
779 : : // Zeile und Spalte initialisieren
780 : 0 : nLine = nParseLine;
781 : 0 : nCol = 0L;
782 : :
783 : : // Variablen fuer die Out-Parameter
784 : : TokenTypes eType;
785 : : const sal_Unicode* pStartPos;
786 : : const sal_Unicode* pEndPos;
787 : :
788 : : // Schleife ueber alle Tokens
789 [ # # ][ # # ]: 0 : while( getNextToken( eType, pStartPos, pEndPos ) )
790 : : {
791 : : HighlightPortion portion;
792 : :
793 : 0 : portion.nBegin = (sal_uInt16)(pStartPos - mpStringBegin);
794 : 0 : portion.nEnd = (sal_uInt16)(pEndPos - mpStringBegin);
795 : 0 : portion.tokenType = eType;
796 : :
797 [ # # ]: 0 : portions.push_back(portion);
798 : : }
799 : 0 : }
800 : :
801 : :
802 : : //////////////////////////////////////////////////////////////////////////
803 : : // Implementierung des SyntaxHighlighter
804 : :
805 : 0 : SyntaxHighlighter::SyntaxHighlighter()
806 : : {
807 : 0 : m_pSimpleTokenizer = 0;
808 : 0 : m_pKeyWords = NULL;
809 : 0 : m_nKeyWordCount = 0;
810 : 0 : }
811 : :
812 : 0 : SyntaxHighlighter::~SyntaxHighlighter()
813 : : {
814 [ # # ]: 0 : delete m_pSimpleTokenizer;
815 : 0 : delete m_pKeyWords;
816 : 0 : }
817 : :
818 : 0 : void SyntaxHighlighter::initialize( HighlighterLanguage eLanguage_ )
819 : : {
820 : 0 : eLanguage = eLanguage_;
821 [ # # ]: 0 : delete m_pSimpleTokenizer;
822 : 0 : m_pSimpleTokenizer = new SimpleTokenizer_Impl(eLanguage);
823 : :
824 [ # # # ]: 0 : switch (eLanguage)
825 : : {
826 : : case HIGHLIGHT_BASIC:
827 : : m_pSimpleTokenizer->setKeyWords( strListBasicKeyWords,
828 : 0 : sizeof( strListBasicKeyWords ) / sizeof( char* ));
829 : 0 : break;
830 : : case HIGHLIGHT_SQL:
831 : : m_pSimpleTokenizer->setKeyWords( strListSqlKeyWords,
832 : 0 : sizeof( strListSqlKeyWords ) / sizeof( char* ));
833 : 0 : break;
834 : : default:
835 : 0 : m_pSimpleTokenizer->setKeyWords( NULL, 0 );
836 : : }
837 : 0 : }
838 : :
839 : 0 : const Range SyntaxHighlighter::notifyChange( sal_uInt32 nLine, sal_Int32 nLineCountDifference,
840 : : const String* pChangedLines, sal_uInt32 nArrayLength)
841 : : {
842 : : (void)nLineCountDifference;
843 : :
844 [ # # ]: 0 : for( sal_uInt32 i=0 ; i < nArrayLength ; i++ )
845 : 0 : m_pSimpleTokenizer->parseLine(nLine+i, &pChangedLines[i]);
846 : :
847 : 0 : return Range( nLine, nLine + nArrayLength-1 );
848 : : }
849 : :
850 : 0 : void SyntaxHighlighter::getHighlightPortions( sal_uInt32 nLine, const String& rLine,
851 : : /*out*/HighlightPortions& portions )
852 : : {
853 : 0 : m_pSimpleTokenizer->getHighlightPortions( nLine, rLine, portions );
854 : 0 : }
855 : :
856 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|