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  * Checks the token against a type.
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 empty tag token.
416  * @constructor
417  * @extends xrx.token
418  */
419 xrx.token.StartEmptyTag = function(label, opt_offset, opt_length) {
420   goog.base(this, xrx.token.START_EMPTY_TAG, label, opt_offset, opt_length);
421 };
422 goog.inherits(xrx.token.StartEmptyTag, xrx.token);
423 
424 
425 
426 /**
427  * @override
428  */
429 xrx.token.StartEmptyTag.prototype.typeOf = function(type) {
430   return this.type_ === type || xrx.token.START_TAG === type || 
431       xrx.token.EMPTY_TAG === type || xrx.token.TAG === type;
432 };
433 
434 
435 
436 /**
437  * Constructs a new tag token.
438  * @constructor
439  * @extends xrx.token
440  */
441 xrx.token.Tag = function(label) {
442   goog.base(this, xrx.token.TAG, label);
443 };
444 goog.inherits(xrx.token.Tag, xrx.token);
445 
446 
447 
448 /**
449  * @return {boolean}
450  * @override
451  * @extends xrx.token
452  */
453 xrx.token.Tag.prototype.typeOf = function(type) {
454   return this.type_ === type || xrx.token.START_TAG === type
455       || xrx.token.END_TAG === type || xrx.token.EMPTY_TAG === type || 
456       xrx.token.START_EMPTY_TAG === type;
457 };
458 
459 
460 
461 /**
462  * Primary tokens
463  */
464 /** @const */ xrx.token.ROOT = 0;
465 /** @const */ xrx.token.START_TAG = 1;
466 /** @const */ xrx.token.END_TAG = 2;
467 /** @const */ xrx.token.EMPTY_TAG = 3;
468 /** @const */ xrx.token.NOT_TAG = 9;
469 
470 
471 
472 /**
473  * Secondary tokens
474  */
475 /** @const */ xrx.token.TAG_NAME = 5;
476 /** @const */ xrx.token.ATTRIBUTE = 6;
477 /** @const */ xrx.token.ATTR_NAME = 7;
478 /** @const */ xrx.token.ATTR_VALUE = 8;
479 
480 
481 
482 /**
483  * Generic tokens
484  */
485 /** @const */ xrx.token.UNDEFINED = -1;
486 /** @const */ xrx.token.START_EMPTY_TAG = 4; // either xrx.token.START_TAG or xrx.token.EMPTY_TAG
487 /** @const */ xrx.token.TAG = 10; // either xrx.token.END_TAG or xrx.token.START_EMPTY_TAG
488 
489 
490 
491 /**
492  * Complex tokens
493  */
494 // A selection of sequenced tokens of different type forming a peace of well-formed 
495 // XML. Corresponds to what a DOM element is.
496 /** @const */ xrx.token.FRAGMENT = 11; 
497 /** @const */ xrx.token.START_END = 12; // xrx.token.START_TAG plus xrx.token.END_TAG
498 // same as xrx.token.FRAGMENT, but may start and end with xrx.token.NOT_TAG 
499 // or even may end or start with a part of xrx.token.NOT_TAG
500 /** @const */ xrx.token.MIXED = 13;
501 
502 // numbering of tokens is important to compute document order!
503