1 /** 2 * @fileoverview A class representing the tokens of a XML stream. 3 */ 4 5 goog.provide('xrx.token'); 6 7 8 9 goog.require('xrx.label'); 10 11 12 13 /** 14 * Constructs a new token. 15 * This constructor should never be called directly, but 16 * by one of the inherited token classes below. 17 * 18 * @constructor 19 * @param {!number} type The type of the token. 20 * @param {?xrx.label} label The label attached to the token. 21 * @param {?number} offset The offset relative to the start of the XML stream. 22 * @param {?number} length The number of characters occupied in the XML stream. 23 */ 24 xrx.token = function(type, label, offset, length) { 25 26 27 28 /** 29 * @private 30 */ 31 this.type_ = type; 32 33 34 35 /** 36 * @private 37 */ 38 this.label_ = label; 39 40 41 42 /** 43 * @private 44 */ 45 this.offset_ = offset; 46 47 48 49 /** 50 * @private 51 */ 52 this.length_ = length; 53 }; 54 55 56 57 /** 58 * Converts a generic token into its native form. 59 * 60 * @param {!xrx.token} token The token to convert. 61 * @return {?} 62 */ 63 xrx.token.native = function(token) { 64 var newToken; 65 var label = token.label().clone(); 66 var offset = token.offset(); 67 var length = token.length(); 68 69 var convert = function(constr) { 70 var tmp = new constr(); 71 tmp.label(label); 72 tmp.offset(offset); 73 tmp.length(length); 74 return tmp; 75 }; 76 77 switch(token.type()) { 78 case xrx.token.START_TAG: 79 newToken = convert(xrx.token.StartTag); 80 break; 81 case xrx.token.END_TAG: 82 newToken = convert(xrx.token.EndTag); 83 break; 84 case xrx.token.EMPTY_TAG: 85 newToken = convert(xrx.token.EmptyTag); 86 break; 87 case xrx.token.NOT_TAG: 88 newToken = convert(xrx.token.NotTag); 89 break; 90 case xrx.token.TAG_NAME: 91 newToken = convert(xrx.token.TagName); 92 break; 93 case xrx.token.ATTRIBUE: 94 newToken = convert(xrx.token.Attribute); 95 break; 96 case xrx.token.ATTR_NAME: 97 newToken = convert(xrx.token.AttrName); 98 break; 99 case xrx.token.ATTR_VALUE: 100 newToken = convert(xrx.token.AttrValue); 101 break; 102 default: 103 throw Error('Token is generic or unknown.'); 104 break; 105 }; 106 107 return newToken; 108 }; 109 110 111 112 /** 113 * Compares the generic type of two tokens. 114 * 115 * @param {!number} type The type to check against. 116 * @return {!boolean} 117 */ 118 xrx.token.prototype.typeOf = function(type) { 119 return this.type_ === type; 120 }; 121 122 123 124 /** 125 * Checks if two tokens are the same. 126 * Note that two tokens are considered as 'the same' 127 * if the types and the labels of the two tokens are 128 * identical. Offset and length do not play any role 129 * for 'sameness'. 130 * 131 * @param {!xrx.token} token The token to check against. 132 * @return {!boolean} 133 */ 134 xrx.token.prototype.sameAs = function(token) { 135 return this.typeOf(token.type()) && this.label_.sameAs(token.label()); 136 }; 137 138 139 140 /** 141 * See function xrx.token.sameAs(token), but overloading 142 * the type and the label separately. 143 * 144 * @param {!type} type The type to check against. 145 * @param {!label} label The label to check against. 146 * @return {!boolean} 147 */ 148 xrx.token.prototype.compare = function(type, label) { 149 return this.typeOf(type) && this.label_.sameAs(label); 150 }; 151 152 153 154 /** 155 * Indicates whether the token appears before the overloaded 156 * token (assuming a forward XML stream). 157 * 158 * @param {!xrx.token} token The token to compare. 159 * @return {!boolean} 160 */ 161 xrx.token.prototype.isBefore = function(token) { 162 return this.label_.isBefore(token.label()) || 163 (this.label_.sameAs(token.label()) && this.type_ < token.type()); 164 }; 165 166 167 168 /** 169 * Indicates whether the token appears after the overloaded 170 * token (assuming a forward XML stream). 171 * 172 * @param {!xrx.token} token The token to compare. 173 * @return {!boolean} 174 */ 175 xrx.token.prototype.isAfter = function(token) { 176 return this.label_.isAfter(token.label()) || 177 (this.label_.sameAs(token.label()) && this.type_ > token.type()); 178 }; 179 180 181 182 /** 183 * A cumulative setter function for all private members. 184 * 185 * @param {!number} type The type of the token. 186 * @param {!xrx.label} label The label attached to the token. 187 * @param {?number} offset The offset relative to the start of the XML stream. 188 * @param {?number} length The number of characters in the XML stream. 189 */ 190 xrx.token.prototype.set = function(type, label, offset, length) { 191 192 this.type_ = type; 193 this.label_ = label; 194 this.offset_ = offset; 195 this.length_ = length; 196 }; 197 198 199 200 /** 201 * A combined setter and getter function. 202 * @param {?number} opt_type The value to be set (optional). 203 * @return {!number} 204 */ 205 xrx.token.prototype.type = function(opt_type) { 206 opt_type !== undefined ? this.type_ = opt_type : null; 207 return this.type_; 208 }; 209 210 211 212 /** 213 * A combined setter and getter function. 214 * @param {?number} opt_label The value to be set (optional). 215 * @return {!number} 216 */ 217 xrx.token.prototype.label = function(opt_label) { 218 opt_label !== undefined ? this.label_ = opt_label : null; 219 return this.label_; 220 }; 221 222 223 224 /** 225 * A combined setter and getter function. 226 * @param {?number} opt_offset The value to be set (optional). 227 * @return {!number} 228 */ 229 xrx.token.prototype.offset = function(opt_offset) { 230 opt_offset !== undefined ? this.offset_ = opt_offset : null; 231 return this.offset_; 232 }; 233 234 235 236 /** 237 * A combined setter and getter function. 238 * @param {?number} opt_length The value to be set (optional). 239 * @return {!number} 240 */ 241 xrx.token.prototype.length = function(opt_length) { 242 opt_length !== undefined ? this.length_ = opt_length : null; 243 return this.length_; 244 }; 245 246 247 248 /** 249 * Constructs a new root token. 250 * @constructor 251 * @extends xrx.token 252 */ 253 xrx.token.Root = function() { 254 goog.base(this, xrx.token.ROOT, new xrx.label([0]), 0, 0); 255 }; 256 goog.inherits(xrx.token.Root, xrx.token); 257 258 259 260 /** 261 * Constructs a new start tag token. 262 * @constructor 263 * @extends xrx.token 264 */ 265 xrx.token.StartTag = function(label, opt_offset, opt_length) { 266 goog.base(this, xrx.token.START_TAG, label, opt_offset, opt_length); 267 }; 268 goog.inherits(xrx.token.StartTag, xrx.token); 269 270 271 272 /** 273 * @override 274 */ 275 xrx.token.StartTag.prototype.typeOf = function(type) { 276 return this.type_ === type || xrx.token.START_EMPTY_TAG === type || 277 xrx.token.TAG === type; 278 }; 279 280 281 282 /** 283 * Constructs a new end tag token. 284 * @constructor 285 * @extends xrx.token 286 */ 287 xrx.token.EndTag = function(label, opt_offset, opt_length) { 288 goog.base(this, xrx.token.END_TAG, label, opt_offset, opt_length); 289 }; 290 goog.inherits(xrx.token.EndTag, xrx.token); 291 292 293 294 /** 295 * @override 296 */ 297 xrx.token.EndTag.prototype.typeOf = function(type) { 298 return this.type_ === type || xrx.token.TAG === type; 299 }; 300 301 302 303 /** 304 * Constructs a new empty token. 305 * @constructor 306 * @extends xrx.token 307 */ 308 xrx.token.EmptyTag = function(label, opt_offset, opt_length) { 309 goog.base(this, xrx.token.EMPTY_TAG, label, opt_offset, opt_length); 310 }; 311 goog.inherits(xrx.token.EmptyTag, xrx.token); 312 313 314 315 /** 316 * @override 317 */ 318 xrx.token.EmptyTag.prototype.typeOf = function(type) { 319 return this.type_ === type || xrx.token.START_EMPTY_TAG === type || 320 xrx.token.TAG === type; 321 }; 322 323 324 325 /** 326 * Constructs a new not tag token. 327 * @constructor 328 * @extends xrx.token 329 */ 330 xrx.token.NotTag = function(label, opt_offset, opt_length) { 331 goog.base(this, xrx.token.NOT_TAG, label, opt_offset, opt_length); 332 }; 333 goog.inherits(xrx.token.NotTag, xrx.token); 334 335 336 337 /** 338 * Constructs a new tag name token. 339 * @constructor 340 * @extends xrx.token 341 */ 342 xrx.token.TagName = function(label, opt_offset, opt_length) { 343 goog.base(this, xrx.token.TAG_NAME, label, opt_offset, opt_length); 344 }; 345 goog.inherits(xrx.token.TagName, xrx.token); 346 347 348 349 /** 350 * Constructs a new attribute token. 351 * @constructor 352 * @extends xrx.token 353 */ 354 xrx.token.Attribute = function(label, opt_offset, opt_length) { 355 goog.base(this, xrx.token.ATTRIBUTE, label, opt_offset, opt_length); 356 }; 357 goog.inherits(xrx.token.Attribute, xrx.token); 358 359 360 361 /** 362 * Returns the tag to which the attribute belongs. 363 * @return {!xrx.token.StartEmptyTag} 364 */ 365 xrx.token.Attribute.prototype.tag = function() { 366 var label = this.label().clone(); 367 label.parent(); 368 369 return new xrx.token.StartEmptyTag(label); 370 }; 371 372 373 374 /** 375 * Constructs a new attribute name token. 376 * @constructor 377 * @extends xrx.token 378 */ 379 xrx.token.AttrName = function(label, opt_offset, opt_length) { 380 goog.base(this, xrx.token.ATTR_NAME, label, opt_offset, opt_length); 381 }; 382 goog.inherits(xrx.token.AttrName, xrx.token); 383 384 385 386 /** 387 * Returns the tag to which the attribute name belongs. 388 * @return {!xrx.token.StartEmptyTag} 389 */ 390 xrx.token.AttrName.prototype.tag = xrx.token.Attribute.prototype.tag; 391 392 393 394 /** 395 * Constructs a new attribute value token. 396 * @constructor 397 * @extends xrx.token 398 */ 399 xrx.token.AttrValue = function(label, opt_offset, opt_length) { 400 goog.base(this, xrx.token.ATTR_VALUE, label, opt_offset, opt_length); 401 }; 402 goog.inherits(xrx.token.AttrValue, xrx.token); 403 404 405 406 /** 407 * Returns the tag to which the attribute value belongs. 408 * @return {!xrx.token.StartEmptyTag} 409 */ 410 xrx.token.AttrValue.prototype.tag = xrx.token.Attribute.prototype.tag; 411 412 413 414 /** 415 * Constructs a new namespace token. 416 * @constructor 417 * @extends xrx.token 418 */ 419 xrx.token.Namespace = function(label, opt_offset, opt_length) { 420 goog.base(this, xrx.token.NAMESPACE, label, opt_offset, opt_length); 421 }; 422 goog.inherits(xrx.token.Namespace, xrx.token); 423 424 425 426 /** 427 * Constructs a new namespace prefix token. 428 * @constructor 429 * @extends xrx.token 430 */ 431 xrx.token.NsPrefix = function(label, opt_offset, opt_length) { 432 goog.base(this, xrx.token.NS_PREFIX, label, opt_offset, opt_length); 433 }; 434 goog.inherits(xrx.token.NsPrefix, xrx.token); 435 436 437 438 /** 439 * Constructs a new namespace URI token. 440 * @constructor 441 * @extends xrx.token 442 */ 443 xrx.token.NsUri = function(label, opt_offset, opt_length) { 444 goog.base(this, xrx.token.NS_URI, label, opt_offset, opt_length); 445 }; 446 goog.inherits(xrx.token.NsUri, xrx.token); 447 448 449 450 /** 451 * Constructs a new empty tag token. 452 * @constructor 453 * @extends xrx.token 454 */ 455 xrx.token.StartEmptyTag = function(label, opt_offset, opt_length) { 456 goog.base(this, xrx.token.START_EMPTY_TAG, label, opt_offset, opt_length); 457 }; 458 goog.inherits(xrx.token.StartEmptyTag, xrx.token); 459 460 461 462 /** 463 * @override 464 */ 465 xrx.token.StartEmptyTag.prototype.typeOf = function(type) { 466 return this.type_ === type || xrx.token.START_TAG === type || 467 xrx.token.EMPTY_TAG === type || xrx.token.TAG === type; 468 }; 469 470 471 472 /** 473 * Constructs a new tag token. 474 * @constructor 475 * @extends xrx.token 476 */ 477 xrx.token.Tag = function(label) { 478 goog.base(this, xrx.token.TAG, label); 479 }; 480 goog.inherits(xrx.token.Tag, xrx.token); 481 482 483 484 /** 485 * @return {boolean} 486 * @override 487 * @extends xrx.token 488 */ 489 xrx.token.Tag.prototype.typeOf = function(type) { 490 return this.type_ === type || xrx.token.START_TAG === type 491 || xrx.token.END_TAG === type || xrx.token.EMPTY_TAG === type || 492 xrx.token.START_EMPTY_TAG === type; 493 }; 494 495 496 497 /** 498 * Primary tokens 499 */ 500 /** @const */ xrx.token.ROOT = 0; 501 /** @const */ xrx.token.START_TAG = 1; 502 /** @const */ xrx.token.END_TAG = 2; 503 /** @const */ xrx.token.EMPTY_TAG = 3; 504 /** @const */ xrx.token.NOT_TAG = 12; 505 506 507 508 /** 509 * Secondary tokens 510 */ 511 /** @const */ xrx.token.TAG_NAME = 5; 512 /** @const */ xrx.token.ATTRIBUTE = 6; 513 /** @const */ xrx.token.ATTR_NAME = 7; 514 /** @const */ xrx.token.ATTR_VALUE = 8; 515 /** @const */ xrx.token.NAMESPACE = 9; 516 /** @const */ xrx.token.NS_PREFIX = 10; 517 /** @const */ xrx.token.NS_URI = 11; 518 519 520 521 /** 522 * Generic tokens 523 */ 524 /** @const */ xrx.token.UNDEFINED = -1; 525 // either xrx.token.START_TAG or 526 // xrx.token.EMPTY_TAG 527 /** @const */ xrx.token.START_EMPTY_TAG = 4; 528 // either xrx.token.END_TAG or 529 // xrx.token.START_EMPTY_TAG 530 /** @const */ xrx.token.TAG = 13; 531 532 533 534 /** 535 * Complex tokens 536 */ 537 // A selection of sequenced tokens of 538 // different type forming a peace of 539 // well-formed XML. Corresponds to what 540 // a DOM element is. 541 /** @const */ xrx.token.FRAGMENT = 14; 542 // xrx.token.START_TAG plus 543 // xrx.token.END_TAG 544 /** @const */ xrx.token.START_END = 15; 545 // same as xrx.token.FRAGMENT, but may 546 // start and end with xrx.token.NOT_TAG 547 // or even may end or start with a part 548 // of xrx.token.NOT_TAG 549 /** @const */ xrx.token.MIXED = 16; 550 551 // numbering of tokens is important to 552 // compute document order! 553