KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > PHPFormatter


1 /*
2  * PHPFormatter.java
3  *
4  * Copyright (C) 1998-2003 Peter Graves
5  * $Id: PHPFormatter.java,v 1.2 2003/05/15 15:34:01 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.j;
23
24 public final class PHPFormatter extends Formatter implements Constants
25 {
26     private static final int PHP_STATE_IDENTIFIER = STATE_LAST + 1;
27     private static final int PHP_STATE_OPERATOR = STATE_LAST + 2;
28     private static final int PHP_STATE_BRACE = STATE_LAST + 3;
29     private static final int PHP_STATE_NUMBER = STATE_LAST + 4;
30     private static final int PHP_STATE_HEXNUMBER = STATE_LAST + 5;
31     private static final int PHP_STATE_IGNORE = STATE_LAST + 6;
32     private static final int PHP_STATE_KEYWORD = STATE_LAST + 7;
33     private static final int PHP_STATE_TAG_STARTING = STATE_LAST + 8;
34     private static final int PHP_STATE_TAG = STATE_LAST + 9;
35     private static final int PHP_STATE_ATTNAME = STATE_LAST + 10;
36     private static final int PHP_STATE_EQUALS = STATE_LAST + 11;
37     private static final int PHP_STATE_ATTVALUE = STATE_LAST + 12;
38     private static final int PHP_STATE_ATTVALUE_QUOTE = STATE_LAST + 13;
39     private static final int PHP_STATE_ATTVALUE_SINGLEQUOTE = STATE_LAST + 14;
40     private static final int PHP_STATE_TAG_ENDING = STATE_LAST + 15;
41     private static final int PHP_STATE_HTML_COMMENT = STATE_LAST + 16;
42
43     private static final int PHP_FORMAT_TEXT = 0;
44     private static final int PHP_FORMAT_COMMENT = 1;
45     private static final int PHP_FORMAT_STRING = 2;
46     private static final int PHP_FORMAT_IDENTIFIER = 3;
47     private static final int PHP_FORMAT_KEYWORD = 4;
48     private static final int PHP_FORMAT_FUNCTION = 5;
49     private static final int PHP_FORMAT_OPERATOR = 6;
50     private static final int PHP_FORMAT_BRACE = 7;
51     private static final int PHP_FORMAT_NUMBER = 8;
52     private static final int PHP_FORMAT_VAR = 9;
53     private static final int PHP_FORMAT_DELIMITER = 10;
54     private static final int PHP_FORMAT_TAG = 11;
55     private static final int PHP_FORMAT_ATTRIBUTE = 12;
56     private static final int PHP_FORMAT_EQUALS = 13;
57
58     private static PHPMode mode;
59
60     public PHPFormatter(Buffer buffer)
61     {
62         this.buffer = buffer;
63         if (mode == null)
64             mode = (PHPMode) PHPMode.getMode();
65     }
66
67     private int tokenBegin = 0;
68
69     private final void endToken(StringPosition pos, int state)
70     {
71         endToken(pos.getText(), pos.getOffset(), state);
72     }
73
74     private void endToken(String JavaDoc text, int tokenEnd, int state)
75     {
76         if (tokenEnd - tokenBegin > 0) {
77             int format;
78             switch (state) {
79                 case STATE_NEUTRAL:
80                 case PHP_STATE_IGNORE:
81                     format = PHP_FORMAT_TEXT;
82                     break;
83                 case STATE_QUOTE:
84                 case STATE_SINGLEQUOTE:
85                     format = PHP_FORMAT_STRING;
86                     break;
87                 case PHP_STATE_IDENTIFIER:
88                     format = PHP_FORMAT_IDENTIFIER;
89                     break;
90                 case STATE_COMMENT:
91                 case PHP_STATE_HTML_COMMENT:
92                     format = PHP_FORMAT_COMMENT;
93                     break;
94                 case PHP_STATE_OPERATOR:
95                     format = PHP_FORMAT_OPERATOR;
96                     break;
97                 case PHP_STATE_BRACE:
98                     format = PHP_FORMAT_BRACE;
99                     break;
100                 case PHP_STATE_NUMBER:
101                 case PHP_STATE_HEXNUMBER:
102                     format = PHP_FORMAT_NUMBER;
103                     break;
104                 case PHP_STATE_KEYWORD:
105                     format = PHP_FORMAT_KEYWORD;
106                     break;
107                 case PHP_STATE_TAG_STARTING:
108                 case PHP_STATE_TAG_ENDING:
109                     format = PHP_FORMAT_DELIMITER;
110                     break;
111                 case PHP_STATE_TAG:
112                     format = PHP_FORMAT_TAG;
113                     break;
114                 case PHP_STATE_ATTNAME:
115                     format = PHP_FORMAT_ATTRIBUTE;
116                     break;
117                 case PHP_STATE_EQUALS:
118                     format = PHP_FORMAT_EQUALS;
119                     break;
120                 case PHP_STATE_ATTVALUE:
121                 case PHP_STATE_ATTVALUE_QUOTE:
122                 case PHP_STATE_ATTVALUE_SINGLEQUOTE:
123                     format = PHP_FORMAT_STRING;
124                     break;
125                 default:
126                     format = PHP_FORMAT_TEXT;
127                     break;
128             }
129             addSegment(text, tokenBegin, tokenEnd, format);
130             tokenBegin = tokenEnd;
131         }
132     }
133
134     private void parseLine(Line line)
135     {
136         String JavaDoc text;
137         if (Editor.tabsAreVisible())
138             text = Utilities.makeTabsVisible(line.getText(), buffer.getTabWidth());
139         else
140             text = Utilities.detab(line.getText(), buffer.getTabWidth());
141         tokenBegin = 0;
142
143         char quoteChar = '\0';
144         int state = getState(line.flags());
145         final int htmlState = getHtmlState(line.flags());
146         if (state == PHP_STATE_TAG) {
147             // End of tag name at end of previous line.
148
state = PHP_STATE_ATTNAME;
149         } else if (state == STATE_QUOTE)
150             quoteChar = '"';
151         else if (state == STATE_SINGLEQUOTE)
152             quoteChar = '\'';
153
154         StringPosition pos = new StringPosition(text);
155         // Skip whitespace at start of line.
156
while (!pos.atEnd() && pos.charIsWhitespace())
157             pos.next();
158         endToken(pos, state);
159
160         if (pos.atEnd())
161             return;
162
163         switch (state) {
164             case STATE_NEUTRAL:
165             case STATE_COMMENT:
166             case STATE_QUOTE:
167             case STATE_SINGLEQUOTE:
168             case PHP_STATE_IDENTIFIER:
169             case PHP_STATE_OPERATOR:
170             case PHP_STATE_BRACE:
171             case PHP_STATE_NUMBER:
172             case PHP_STATE_HEXNUMBER:
173             case PHP_STATE_KEYWORD:
174                 parseLinePHP(pos, state, htmlState);
175             default:
176                 parseLineHTML(pos, state);
177         }
178     }
179
180     private final void parseLinePHP(StringPosition pos, int state)
181     {
182         parseLinePHP(pos, state, PHP_STATE_IGNORE);
183     }
184
185     private void parseLinePHP(StringPosition pos, int state, int htmlState)
186     {
187         while (!pos.atEnd()) {
188             char c = pos.getChar();
189             if (c == '\\') {
190                 // Escape.
191
pos.skip(1);
192                 pos.next();
193                 continue;
194             }
195             if (state == STATE_COMMENT) {
196                 if (pos.lookingAt("*/")) {
197                     pos.skip(2);
198                     endToken(pos, state);
199                     state = STATE_NEUTRAL;
200                 } else
201                     pos.next();
202                 continue;
203             }
204             if (state == STATE_QUOTE) {
205                 if (c == '"') {
206                     pos.next();
207                     endToken(pos, state);
208                     state = STATE_NEUTRAL;
209                     continue;
210                 }
211                 pos.next();
212                 continue;
213             }
214             if (state == STATE_SINGLEQUOTE) {
215                 if (c == '\'') {
216                     pos.next();
217                     endToken(pos, state);
218                     state = STATE_NEUTRAL;
219                     continue;
220                 }
221                 pos.next();
222                 continue;
223             }
224             // Reaching here, we're not in a comment or a quoted string.
225
if (c == '"' || c == '\'') {
226                 endToken(pos, state);
227                 state = c == '"' ? STATE_QUOTE : STATE_SINGLEQUOTE;
228                 pos.next();
229                 continue;
230             }
231             if (pos.lookingAt("?>")) {
232                 endToken(pos, state);
233                 pos.skip(2);
234                 endToken(pos, PHP_STATE_TAG_ENDING);
235                 parseLineHTML(pos, htmlState);
236                 return;
237             }
238             if (c == '/') {
239                 if (pos.lookingAt("/*")) {
240                     endToken(pos, state);
241                     checkLastSegment();
242                     state = STATE_COMMENT;
243                     pos.skip(2);
244                 } else if (pos.lookingAt("//")) {
245                     endToken(pos, state);
246                     checkLastSegment();
247                     pos.setOffset(pos.getText().length());
248                     endToken(pos, STATE_COMMENT);
249                     return;
250                 } else
251                     pos.next();
252                 continue;
253             }
254             if (c == '#') {
255                 endToken(pos, state);
256                 checkLastSegment();
257                 pos.setOffset(pos.getText().length());
258                 endToken(pos, STATE_COMMENT);
259                 return;
260             }
261             if (isOperatorChar(c)) {
262                 if (state != PHP_STATE_OPERATOR) {
263                     endToken(pos, state);
264                     // Check for keyword (as in e.g. "char*") or var.
265
checkLastSegment();
266                     state = PHP_STATE_OPERATOR;
267                 }
268                 pos.next();
269                 continue;
270             }
271             if (c == '{' || c == '}') {
272                 if (state != PHP_STATE_BRACE) {
273                     endToken(pos, state);
274                     // Check for keyword (e.g. "try") or var.
275
checkLastSegment();
276                     state = PHP_STATE_BRACE;
277                 }
278                 pos.next();
279                 continue;
280             }
281             if (state == PHP_STATE_OPERATOR || state == PHP_STATE_BRACE) {
282                 if (mode.isIdentifierStart(c)) {
283                     endToken(pos, state);
284                     state = PHP_STATE_IDENTIFIER;
285                 } else if (Character.isDigit(c)) {
286                     endToken(pos, state);
287                     state = PHP_STATE_NUMBER;
288                 } else {
289                     endToken(pos, state);
290                     state = STATE_NEUTRAL;
291                 }
292                 pos.next();
293                 continue;
294             }
295             if (state == PHP_STATE_IDENTIFIER) {
296                 if (!mode.isIdentifierPart(c)) {
297                     endToken(pos, state);
298                     // Check for keyword or function.
299
LineSegment segment = getLastSegment();
300                     if (segment != null) {
301                         String JavaDoc segmentText = segment.getText();
302                         if (isVar(segment.getText()))
303                             segment.setFormat(PHP_FORMAT_VAR);
304                         else if (isKeyword(segment.getText()))
305                             segment.setFormat(PHP_FORMAT_KEYWORD);
306                         else if (c == '(')
307                             segment.setFormat(PHP_FORMAT_FUNCTION);
308                         else if (Character.isWhitespace(c)) {
309                             // Look ahead to see if next non-whitespace char is '('.
310
int j = pos.getOffset() + 1;
311                             final String JavaDoc text = pos.getText();
312                             final int limit = text.length();
313                             while (j < limit && Character.isWhitespace(c = text.charAt(j)))
314                                 ++j;
315                             if (c == '(')
316                                 segment.setFormat(PHP_FORMAT_FUNCTION);
317                         }
318                     }
319                     state = STATE_NEUTRAL;
320                 }
321                 pos.next();
322                 continue;
323             }
324             if (state == PHP_STATE_NUMBER) {
325                 if (Character.isDigit(c))
326                     ;
327                 else if (c == 'u' || c == 'U' || c == 'l' || c == 'L')
328                     ;
329                 else if (pos.getOffset() - tokenBegin == 1 && c == 'x' || c == 'X')
330                     state = PHP_STATE_HEXNUMBER;
331                 else {
332                     endToken(pos, state);
333                     if (mode.isIdentifierStart(c))
334                         state = PHP_STATE_IDENTIFIER;
335                     else
336                         state = STATE_NEUTRAL;
337                 }
338                 pos.next();
339                 continue;
340             }
341             if (state == PHP_STATE_HEXNUMBER) {
342                 if (Character.isDigit(c))
343                     ;
344                 else if ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
345                     ;
346                 else if (c == 'u' || c == 'U' || c == 'l' || c == 'L')
347                     ;
348                 else {
349                     endToken(pos, state);
350                     if (mode.isIdentifierStart(c))
351                         state = PHP_STATE_IDENTIFIER;
352                     else
353                         state = STATE_NEUTRAL;
354                 }
355                 pos.next();
356                 continue;
357             }
358             if (state == STATE_NEUTRAL) {
359                 if (c == '$' || mode.isIdentifierStart(c)) {
360                     endToken(pos, state);
361                     state = PHP_STATE_IDENTIFIER;
362                 } else if (Character.isDigit(c)) {
363                     endToken(pos, state);
364                     state = PHP_STATE_NUMBER;
365                 }
366             }
367             pos.next();
368         }
369         // Reached end of line.
370
endToken(pos, state);
371         if (state == PHP_STATE_IDENTIFIER) {
372             // Last token might be a keyword.
373
checkLastSegment();
374         }
375     }
376
377     private void parseLineHTML(StringPosition pos, int state)
378     {
379         if (state == 0)
380             state = PHP_STATE_IGNORE;
381         while (!pos.atEnd()) {
382             char c = pos.getChar();
383             switch (state) {
384                 case PHP_STATE_HTML_COMMENT:
385                     if (pos.lookingAt("-->")) {
386                         pos.skip(3);
387                         endToken(pos, state);
388                         state = PHP_STATE_IGNORE;
389                     } else
390                         pos.next();
391                     continue;
392                 case PHP_STATE_IGNORE:
393                     if (c == '<') {
394                         endToken(pos, state);
395                         if (pos.lookingAt("<?php")) {
396                             pos.skip(2);
397                             endToken(pos, PHP_STATE_TAG_STARTING);
398                             pos.skip(3);
399                             endToken(pos, PHP_STATE_TAG);
400                             parseLinePHP(pos, STATE_NEUTRAL);
401                             return;
402                         }
403                         if (pos.lookingAt("<?")) {
404                             pos.skip(2);
405                             endToken(pos, PHP_STATE_TAG_STARTING);
406                             parseLinePHP(pos, STATE_NEUTRAL);
407                             return;
408                         }
409                         if (pos.lookingAt("<!--")) {
410                             pos.skip(4);
411                             state = PHP_STATE_HTML_COMMENT;
412                             continue;
413                         }
414                         // Otherwise it's the opening '<' of a normal HTML tag.
415
state = PHP_STATE_TAG_STARTING;
416                     }
417                     pos.next();
418                     continue;
419                 case PHP_STATE_TAG_STARTING:
420                     if (!Character.isWhitespace(c)) {
421                         endToken(pos, state);
422                         state = PHP_STATE_TAG;
423                     }
424                     pos.next();
425                     continue;
426                 case PHP_STATE_TAG:
427                     if (Character.isWhitespace(c)) {
428                         endToken(pos, state);
429                         state = PHP_STATE_ATTNAME;
430                         pos.next();
431                     } else if (c == '>') {
432                         endToken(pos, state);
433                         pos.next();
434                         endToken(pos, PHP_STATE_TAG_ENDING);
435                         state = PHP_STATE_IGNORE;
436                     } else
437                         pos.next();
438                     continue;
439                 case PHP_STATE_ATTNAME:
440                     if (c == '=') {
441                         endToken(pos, state);
442                         pos.next();
443                         state = PHP_STATE_EQUALS;
444                     } else if (c == '>') {
445                         endToken(pos, state);
446                         pos.next();
447                         endToken(pos, PHP_STATE_TAG_ENDING);
448                         state = PHP_STATE_IGNORE;
449                     } else
450                         pos.next();
451                     continue;
452                 case PHP_STATE_EQUALS:
453                     if (!Character.isWhitespace(c)) {
454                         endToken(pos, state);
455                         if (c == '"')
456                             state = PHP_STATE_ATTVALUE_QUOTE;
457                         else if (c == '\'')
458                             state = PHP_STATE_ATTVALUE_SINGLEQUOTE;
459                         else if (pos.lookingAt("<?php")) {
460                             pos.skip(2);
461                             endToken(pos, PHP_STATE_TAG_STARTING);
462                             pos.skip(3);
463                             endToken(pos, PHP_STATE_TAG);
464                             parseLinePHP(pos, STATE_NEUTRAL, PHP_STATE_ATTVALUE);
465                         } else
466                             state = PHP_STATE_ATTVALUE;
467                     }
468                     pos.next();
469                     continue;
470                 case PHP_STATE_ATTVALUE:
471                     if (Character.isWhitespace(c)) {
472                         endToken(pos, state);
473                         pos.next();
474                         state = PHP_STATE_ATTNAME;
475                     } else if (c == '>') {
476                         endToken(pos, state);
477                         pos.next();
478                         endToken(pos, PHP_STATE_TAG_ENDING);
479                         state = PHP_STATE_IGNORE;
480                     } else
481                         pos.next();
482                     continue;
483                 case PHP_STATE_ATTVALUE_QUOTE:
484                     if (pos.lookingAt("<?php")) {
485                         endToken(pos, state);
486                         pos.skip(2);
487                         endToken(pos, PHP_STATE_TAG_STARTING);
488                         pos.skip(3);
489                         endToken(pos, PHP_STATE_TAG);
490                         parseLinePHP(pos, STATE_NEUTRAL, PHP_STATE_ATTVALUE_QUOTE);
491                     } else {
492                         pos.next();
493                         if (c == '"') {
494                             endToken(pos, state);
495                             state = PHP_STATE_ATTNAME;
496                         }
497                     }
498                     continue;
499                 case PHP_STATE_ATTVALUE_SINGLEQUOTE:
500                     if (pos.lookingAt("<?php")) {
501                         endToken(pos, state);
502                         pos.skip(2);
503                         endToken(pos, PHP_STATE_TAG_STARTING);
504                         pos.skip(3);
505                         endToken(pos, PHP_STATE_TAG);
506                         parseLinePHP(pos, STATE_NEUTRAL, PHP_STATE_ATTVALUE_QUOTE);
507                     } else {
508                         pos.next();
509                         if (c == '\'') {
510                             endToken(pos, state);
511                             state = PHP_STATE_ATTNAME;
512                         }
513                     }
514                     continue;
515                 default:
516                     Log.error("state = " + state);
517                     Debug.assertTrue(false);
518                     break;
519             }
520         }
521         // Reached end of line.
522
endToken(pos, state);
523     }
524
525     private void checkLastSegment()
526     {
527         final LineSegment segment = getLastSegment();
528         if (segment != null) {
529             if (isVar(segment.getText()))
530                 segment.setFormat(PHP_FORMAT_VAR);
531             else if (isKeyword(segment.getText()))
532                 segment.setFormat(PHP_FORMAT_KEYWORD);
533         }
534     }
535
536     public LineSegmentList formatLine(Line line)
537     {
538         clearSegmentList();
539         if (line == null) {
540             addSegment("", PHP_FORMAT_TEXT);
541             return segmentList;
542         }
543         parseLine(line);
544         return segmentList;
545     }
546
547     public boolean parseBuffer()
548     {
549         Line line = buffer.getFirstLine();
550         if (line == null)
551             return false;
552         boolean changed = false;
553         final int newFlags = makeFlags(PHP_STATE_IGNORE, 0);
554         if (newFlags != line.flags()) {
555             line.setFlags(newFlags);
556             changed = true;
557         }
558         changed = parseBufferHTML(new Position(line, 0), PHP_STATE_IGNORE,
559                                   changed);
560         buffer.setNeedsParsing(false);
561         return changed;
562     }
563
564     private boolean parseBufferPHP(Position pos, int state, int htmlState,
565         boolean changed)
566     {
567         char quoteChar = '\0';
568         while (!pos.atEnd()) {
569             char c = pos.getChar();
570             if (c == EOL) {
571                 if (pos.next()) {
572                     final int newFlags = makeFlags(state, htmlState);
573                     if (newFlags != pos.getLine().flags()) {
574                         pos.getLine().setFlags(newFlags);
575                         changed = true;
576                     }
577                     continue;
578                 } else
579                     break;
580             }
581             if (c == '\\') {
582                 // Escape.
583
pos.skip(1);
584                 pos.next();
585                 continue;
586             }
587             if (state == STATE_COMMENT) {
588                 if (c == '*' && pos.lookingAt("*/")) {
589                     state = STATE_NEUTRAL;
590                     pos.skip(2);
591                 } else
592                     pos.next();
593                 continue;
594             }
595             if (state == STATE_QUOTE || state == STATE_SINGLEQUOTE) {
596                 if (c == quoteChar) {
597                     state = STATE_NEUTRAL;
598                     quoteChar = '\0';
599                 }
600                 pos.next();
601                 continue;
602             }
603             // Not in comment or quoted string.
604
if (c == '/') {
605                 if (pos.lookingAt("//")) {
606                     // Beginning of comment. Ignore rest of line.
607
pos.setOffset(pos.getLineLength());
608                 } else if (pos.lookingAt("/*")) {
609                     state = STATE_COMMENT;
610                     pos.skip(2);
611                 } else
612                     pos.next();
613                 continue;
614             }
615             if (c == '#') {
616                 // Beginning of comment. Ignore rest of line.
617
Line next = pos.getNextLine();
618                 if (next != null) {
619                     pos.moveTo(next, 0);
620                     continue;
621                 } else
622                     break;
623             }
624             if (c == '"') {
625                 state = STATE_QUOTE;
626                 quoteChar = c;
627                 pos.next();
628                 continue;
629             }
630             if (c == '\'') {
631                 state = STATE_SINGLEQUOTE;
632                 quoteChar = c;
633                 pos.next();
634                 continue;
635             }
636             if (c == '?' && pos.lookingAt("?>")) {
637                 state = PHP_STATE_IGNORE;
638                 pos.skip(2);
639                 return parseBufferHTML(pos, state, changed);
640             }
641             // Otherwise...
642
pos.next();
643         }
644         return changed;
645     }
646
647     private boolean parseBufferHTML(Position pos, int state, boolean changed)
648     {
649         while (!pos.atEnd()) {
650             char c = pos.getChar();
651             if (c == EOL) {
652                 if (pos.next()) {
653                     final int newFlags = makeFlags(state, 0);
654                     if (newFlags != pos.getLine().flags()) {
655                         pos.getLine().setFlags(newFlags);
656                         changed = true;
657                     }
658                     continue;
659                 } else
660                     break;
661             }
662             if (c == '\\') {
663                 // Escape.
664
pos.skip(1);
665                 pos.next();
666                 continue;
667             }
668             switch (state) {
669                 case PHP_STATE_HTML_COMMENT:
670                     if (c == '-' && pos.lookingAt("-->")) {
671                         state = PHP_STATE_IGNORE;
672                         pos.skip(3);
673                     } else
674                         pos.next();
675                     continue;
676                 case PHP_STATE_IGNORE:
677                     if (c == '<') {
678                         if (pos.lookingAt("<?php")) {
679                             state = STATE_NEUTRAL;
680                             pos.skip(5);
681                             return parseBufferPHP(pos, state, 0, changed);
682                         } else if (pos.lookingAt("<?")) {
683                             state = STATE_NEUTRAL;
684                             pos.skip(2);
685                             return parseBufferPHP(pos, state, 0, changed);
686                         } else if (pos.lookingAt("<!--")) {
687                             state = PHP_STATE_HTML_COMMENT;
688                             pos.skip(4);
689                         } else {
690                             // Otherwise it's the start of an HTML tag.
691
state = PHP_STATE_TAG;
692                             pos.next();
693                         }
694                     } else
695                         pos.next();
696                     continue;
697                 case PHP_STATE_TAG:
698                     if (Character.isWhitespace(c))
699                         state = PHP_STATE_ATTNAME;
700                     else if (c == '>')
701                         state = PHP_STATE_IGNORE;
702                     pos.next();
703                     continue;
704                 case PHP_STATE_ATTNAME:
705                     if (c == '=')
706                         state = PHP_STATE_EQUALS;
707                     else if (c == '>')
708                         state = PHP_STATE_IGNORE;
709                     pos.next();
710                     continue;
711                 case PHP_STATE_EQUALS:
712                     if (!Character.isWhitespace(c)) {
713                         if (c == '"')
714                             state = PHP_STATE_ATTVALUE_QUOTE;
715                         else if (c == '\'')
716                             state = PHP_STATE_ATTVALUE_SINGLEQUOTE;
717                         else if (pos.lookingAt("<?php")) {
718                             pos.skip(5);
719                             changed = parseBufferPHP(pos, STATE_NEUTRAL,
720                                 PHP_STATE_ATTNAME, changed);
721                             state = PHP_STATE_ATTNAME;
722                             continue;
723                         } else
724                             state = PHP_STATE_ATTVALUE;
725                     }
726                     pos.next();
727                     continue;
728                 case PHP_STATE_ATTVALUE:
729                     pos.next();
730                     if (Character.isWhitespace(c)) {
731                         state = PHP_STATE_ATTNAME;
732                     } else if (c == '>') {
733                         state = PHP_STATE_IGNORE;
734                     }
735                     continue;
736                 case PHP_STATE_ATTVALUE_QUOTE:
737                     if (pos.lookingAt("<?php")) {
738                         pos.skip(5);
739                         changed = parseBufferPHP(pos, STATE_NEUTRAL,
740                             PHP_STATE_ATTVALUE_QUOTE, changed);
741                     } else {
742                         pos.next();
743                         if (c == '"')
744                             state = PHP_STATE_ATTNAME;
745                     }
746                     continue;
747                 case PHP_STATE_ATTVALUE_SINGLEQUOTE:
748                     if (pos.lookingAt("<?php")) {
749                         pos.skip(5);
750                         changed = parseBufferPHP(pos, STATE_NEUTRAL,
751                             PHP_STATE_ATTVALUE_SINGLEQUOTE, changed);
752                     } else {
753                         pos.next();
754                         if (c == '\'')
755                             state = PHP_STATE_ATTNAME;
756                     }
757                     continue;
758                 default:
759                     Debug.assertTrue(false);
760                     break;
761             }
762         }
763         return changed;
764     }
765
766     private static final int makeFlags(int state, int htmlState)
767     {
768         return (htmlState << 8) + state;
769     }
770
771     public static final int getState(int flags)
772     {
773         return flags & 0xff;
774     }
775
776     private static final int getHtmlState(int flags)
777     {
778         return (flags & 0xff00) >> 8;
779     }
780
781     private final boolean isVar(String JavaDoc s)
782     {
783         return s.length() > 0 && s.charAt(0) == '$';
784     }
785
786     private static final String JavaDoc opchars = "!&|<>=+/*-";
787
788     private static final boolean isOperatorChar(char c)
789     {
790         return opchars.indexOf(c) >= 0;
791     }
792
793     public FormatTable getFormatTable()
794     {
795         if (formatTable == null) {
796             formatTable = new FormatTable("PHPMode");
797             formatTable.addEntryFromPrefs(PHP_FORMAT_TEXT, "text");
798             formatTable.addEntryFromPrefs(PHP_FORMAT_COMMENT, "comment");
799             formatTable.addEntryFromPrefs(PHP_FORMAT_STRING, "string");
800             formatTable.addEntryFromPrefs(PHP_FORMAT_IDENTIFIER, "identifier", "text");
801             formatTable.addEntryFromPrefs(PHP_FORMAT_KEYWORD, "keyword");
802             formatTable.addEntryFromPrefs(PHP_FORMAT_FUNCTION, "function");
803             formatTable.addEntryFromPrefs(PHP_FORMAT_OPERATOR, "operator");
804             formatTable.addEntryFromPrefs(PHP_FORMAT_BRACE, "brace");
805             formatTable.addEntryFromPrefs(PHP_FORMAT_NUMBER, "number");
806             formatTable.addEntryFromPrefs(PHP_FORMAT_VAR, "var");
807             formatTable.addEntryFromPrefs(PHP_FORMAT_DELIMITER, "delimiter");
808             formatTable.addEntryFromPrefs(PHP_FORMAT_TAG, "tag");
809             formatTable.addEntryFromPrefs(PHP_FORMAT_ATTRIBUTE, "attribute");
810             formatTable.addEntryFromPrefs(PHP_FORMAT_EQUALS, "equals");
811         }
812         return formatTable;
813     }
814 }
815
Popular Tags