View Javadoc

1   package org.syntax.jedit.tokenmarker;
2   
3   /*
4    * XMLTokenMarker.java - XML token marker
5    * Copyright (C) 1998, 1999 Slava Pestov
6    * Copyright (C) 2001 Tom Bradford
7    *
8    * You may use and modify this package for any purpose. Redistribution is
9    * permitted, in both source and binary form, provided that this notice
10   * remains intact in all source distributions of this package.
11   */
12  
13  import javax.swing.text.Segment;
14  
15  import org.syntax.jedit.SyntaxUtilities;
16  
17  /***
18   * XML Token Marker Rewrite
19   *
20   * @author Tom Bradford
21   * @version $Id$
22   */
23  public class XMLTokenMarker extends TokenMarker {
24     public XMLTokenMarker() {
25     }
26     
27     public byte markTokensImpl(byte token, Segment line, int lineIndex) {
28        char[] array = line.array;
29        int offset = line.offset;
30        int lastOffset = offset;
31        int length = line.count + offset;
32        
33        // Ugly hack to handle multi-line tags
34        boolean sk1 = token == Token.KEYWORD1;
35        
36        for ( int i = offset; i < length; i++ ) {
37           int ip1 = i+1;
38           char c = array[i];
39           switch ( token ) {
40              case Token.NULL: // text
41                 switch ( c ) {
42                    case '<':
43                       addToken(i-lastOffset, token);
44                       lastOffset = i;
45                       if ( SyntaxUtilities.regionMatches(false, line, ip1, "!--") ) {
46                          i += 3;
47                          token = Token.COMMENT1;
48                       }
49                       else if ( array[ip1] == '!' ) {
50                          i += 1;
51                          token = Token.COMMENT2;
52                       }
53                       else if ( array[ip1] == '?' ) {
54                          i += 1;
55                          token = Token.KEYWORD3;
56                       }
57                       else
58                          token = Token.KEYWORD1;
59                       break;
60                       
61                    case '&':
62                       addToken(i - lastOffset, token);
63                       lastOffset = i;
64                       token = Token.LABEL;
65                       break;
66                 }
67                 break;
68                 
69              case Token.KEYWORD1: // tag
70                 switch ( c ) {
71                    case '>':
72                       addToken(ip1-lastOffset, token);
73                       lastOffset = ip1;
74                       token = Token.NULL;
75                       sk1 = false;
76                       break;
77                       
78                    case ' ':
79                    case '\t':
80                       addToken(i-lastOffset, token);
81                       lastOffset = i;
82                       token = Token.KEYWORD2;
83                       sk1 = false;
84                       break;
85                       
86                    default:
87                       if ( sk1 ) {
88                          token = Token.KEYWORD2;
89                          sk1 = false;
90                       }
91                       break;
92                 }
93                 break;
94  
95              case Token.KEYWORD2: // attribute
96                 switch ( c ) {
97                     case '>':
98                       addToken(ip1-lastOffset, token);
99                       lastOffset = ip1;
100                      token = Token.NULL;
101                      break;
102                     
103                   case '/':
104                      addToken(i-lastOffset, token);
105                      lastOffset = i;
106                      token = Token.KEYWORD1;
107                      break;
108                      
109                   case '=':
110                      addToken(i-lastOffset, token);
111                      lastOffset = i;
112                      token = Token.OPERATOR;
113                }
114                break;
115                
116             case Token.OPERATOR: // equal for attribute
117                switch ( c ) {
118                   case '\"':
119                   case '\'':
120                      addToken(i-lastOffset, token);
121                      lastOffset = i;
122                      if ( c == '\"' )
123                         token = Token.LITERAL1;
124                      else
125                         token = Token.LITERAL2;
126                      break;
127                }
128                break;
129                
130             case Token.LITERAL1:
131             case Token.LITERAL2: // strings
132                if ( ( token == Token.LITERAL1 && c == '\"' )
133                  || ( token == Token.LITERAL2 && c == '\'' ) ) {
134                   addToken(ip1-lastOffset, token);
135                   lastOffset = ip1;
136                   token = Token.KEYWORD1;
137                }
138                break;
139             
140             case Token.LABEL: // entity
141                if ( c == ';' ) {
142                   addToken(ip1-lastOffset, token);
143                   lastOffset = ip1;
144                   token = Token.NULL;
145                   break;
146                }
147                break;
148                
149             case Token.COMMENT1: // Inside a comment
150                if ( SyntaxUtilities.regionMatches(false, line, i, "-->") ) {
151                   addToken((i+3)-lastOffset, token);
152                   lastOffset = i+3;
153                   token = Token.NULL;
154                }
155                break;
156 
157             case Token.COMMENT2: // Inside a declaration
158                if ( SyntaxUtilities.regionMatches(false, line, i, ">") ) {
159                   addToken(ip1-lastOffset, token);
160                   lastOffset = ip1;
161                   token = Token.NULL;
162                }
163                break;
164 
165             case Token.KEYWORD3: // Inside a processor instruction
166                if ( SyntaxUtilities.regionMatches(false, line, i, "?>") ) {
167                   addToken((i+2)-lastOffset, token);
168                   lastOffset = i+2;
169                   token = Token.NULL;
170                }
171                break;
172                
173             default:
174                throw new InternalError("Invalid state: " + token);
175          }
176       }
177       
178       switch ( token ) {
179          case Token.LABEL:
180             addToken(length-lastOffset, Token.INVALID);
181             token = Token.NULL;
182             break;
183             
184          default:
185             addToken(length-lastOffset, token);
186             break;
187       }
188       
189       return token;
190    }
191 }
192 
193