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