1 19 package org.netbeans.modules.ruby.lexer; 20 21 import org.netbeans.modules.ruby.lexer.RubyStringTokenId; 22 import org.netbeans.api.lexer.Token; 23 import org.netbeans.spi.lexer.Lexer; 24 import org.netbeans.spi.lexer.LexerInput; 25 import org.netbeans.spi.lexer.LexerRestartInfo; 26 import org.netbeans.spi.lexer.TokenFactory; 27 28 29 35 public final class RubyStringLexer implements Lexer<RubyStringTokenId> { 36 private static final int EOF = LexerInput.EOF; 37 private LexerInput input; 38 private TokenFactory<RubyStringTokenId> tokenFactory; 39 private boolean substituting; 40 41 46 public RubyStringLexer(LexerRestartInfo<RubyStringTokenId> info, boolean substituting) { 47 this.input = info.input(); 48 this.tokenFactory = info.tokenFactory(); 49 this.substituting = substituting; 50 assert (info.state() == null); } 52 53 public Object state() { 54 return null; 55 } 56 57 public Token<RubyStringTokenId> nextToken() { 58 return substituting ? nextTokenDoubleQuotes() : nextTokenSingleQuotes(); 59 } 60 61 public Token<RubyStringTokenId> nextTokenSingleQuotes() { 62 while (true) { 63 int ch = input.read(); 64 65 switch (ch) { 66 case EOF: 67 68 if (input.readLength() > 0) { 69 return token(RubyStringTokenId.STRING_TEXT); 70 } else { 71 return null; 72 } 73 74 case '\\': 75 76 if (input.readLength() > 1) { input.backup(1); 78 79 return tokenFactory.createToken(RubyStringTokenId.STRING_TEXT, 80 input.readLength()); 81 } 82 83 switch (ch = input.read()) { 84 case '\\': 85 case '"': 86 return token(RubyStringTokenId.STRING_ESCAPE); 87 88 default: 89 return token(RubyStringTokenId.STRING_INVALID); 90 } 91 } 92 } 93 } 94 95 public Token<RubyStringTokenId> nextTokenDoubleQuotes() { 96 while (true) { 97 int ch = input.read(); 98 99 switch (ch) { 100 case EOF: 101 102 if (input.readLength() > 0) { 103 return token(RubyStringTokenId.STRING_TEXT); 104 } else { 105 return null; 106 } 107 108 case '#': 110 111 int f = input.read(); 112 if (f == '{') { 113 if (input.readLength() > 2) { input.backup(2); 116 117 return tokenFactory.createToken(RubyStringTokenId.STRING_TEXT, 118 input.readLength()); 119 } 120 121 int c; 125 126 while (true) { 127 c = input.read(); 128 129 if ((c == EOF) || (c == '}')) { 130 break; 131 } 132 } 133 134 return token(RubyStringTokenId.EMBEDDED_RUBY); 135 } else { 136 continue; 137 } 138 139 case '\\': 140 141 if (input.readLength() > 1) { input.backup(1); 143 144 return tokenFactory.createToken(RubyStringTokenId.STRING_TEXT, 145 input.readLength()); 146 } 147 148 switch (ch = input.read()) { 149 152 case 'x': 154 155 case '0': 157 case '1': 158 case '2': 159 case '3': 160 161 switch (input.read()) { 162 case '0': 163 case '1': 164 case '2': 165 case '3': 166 case '4': 167 case '5': 168 case '6': 169 case '7': 170 171 switch (input.read()) { 172 case '0': 173 case '1': 174 case '2': 175 case '3': 176 case '4': 177 case '5': 178 case '6': 179 case '7': 180 return token(RubyStringTokenId.STRING_ESCAPE); } 182 183 input.backup(1); 184 185 continue; 186 } 187 188 input.backup(1); 189 190 continue; 192 case 'c': { 194 int next = input.read(); 196 197 if (next == 'x') { 198 return token(RubyStringTokenId.STRING_ESCAPE); 199 } else { 200 input.backup(1); 201 } 202 203 continue; 204 } 205 206 case 'C': { 208 int next = input.read(); 209 210 if (next == '-') { 211 next = input.read(); 212 213 if (next == 'x') { 214 return token(RubyStringTokenId.STRING_ESCAPE); 215 } else { 216 input.backup(2); 217 } 218 } else { 219 input.backup(1); 220 } 221 222 continue; 223 } 224 225 case 'M': { 227 int next = input.read(); 228 229 if (next == '-') { 230 next = input.read(); 231 232 if (next == 'x') { 233 return token(RubyStringTokenId.STRING_ESCAPE); 234 } else { 235 input.backup(2); 236 } 237 } else { 238 input.backup(1); 239 } 240 241 continue; 242 } 243 244 default: 249 250 return token(RubyStringTokenId.STRING_ESCAPE); 255 } 256 } 257 } 258 } 259 260 private Token<RubyStringTokenId> token(RubyStringTokenId id) { 261 return tokenFactory.createToken(id); 262 } 263 264 public void release() { 265 } 266 } 267 | Popular Tags |