| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2009 Google Inc. All rights reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions are | |
| 6 * met: | |
| 7 * | |
| 8 * * Redistributions of source code must retain the above copyright | |
| 9 * notice, this list of conditions and the following disclaimer. | |
| 10 * * Redistributions in binary form must reproduce the above | |
| 11 * copyright notice, this list of conditions and the following disclaimer | |
| 12 * in the documentation and/or other materials provided with the | |
| 13 * distribution. | |
| 14 * * Neither the name of Google Inc. nor the names of its | |
| 15 * contributors may be used to endorse or promote products derived from | |
| 16 * this software without specific prior written permission. | |
| 17 * | |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 29 */ | |
| 30 | |
| 31 // Generate js file as follows: | |
| 32 // | |
| 33 // re2c -isc devtools/front_end/SourceHTMLTokenizer.re2js \ | |
| 34 // | sed 's|^yy\([^:]*\)*\:|case \1:|' \ | |
| 35 // | sed 's|[*]cursor[+][+]|this._charAt(cursor++)|' \ | |
| 36 // | sed 's|[[*][+][+]cursor|this._charAt(++cursor)|' \ | |
| 37 // | sed 's|[*]cursor|this._charAt(cursor)|' \ | |
| 38 // | sed 's|yych = \*\([^;]*\)|yych = this._charAt\1|' \ | |
| 39 // | sed 's|goto case \([^;]*\)|{ gotoCase = \1; continue; }|' \ | |
| 40 // | sed 's|unsigned\ int|var|' \ | |
| 41 // | sed 's|var\ yych|case 1: var yych|' > devtools/front_end/SourceHTMLTokenize
r.js | |
| 42 | |
| 43 /** | |
| 44 * @constructor | |
| 45 * @extends {WebInspector.SourceTokenizer} | |
| 46 */ | |
| 47 WebInspector.SourceHTMLTokenizer = function() | |
| 48 { | |
| 49 WebInspector.SourceTokenizer.call(this); | |
| 50 | |
| 51 // The order is determined by the generated code. | |
| 52 this._lexConditions = { | |
| 53 INITIAL: 0, | |
| 54 COMMENT: 1, | |
| 55 DOCTYPE: 2, | |
| 56 TAG: 3, | |
| 57 DSTRING: 4, | |
| 58 SSTRING: 5 | |
| 59 }; | |
| 60 this.case_INITIAL = 1000; | |
| 61 this.case_COMMENT = 1001; | |
| 62 this.case_DOCTYPE = 1002; | |
| 63 this.case_TAG = 1003; | |
| 64 this.case_DSTRING = 1004; | |
| 65 this.case_SSTRING = 1005; | |
| 66 | |
| 67 this._parseConditions = { | |
| 68 INITIAL: 0, | |
| 69 ATTRIBUTE: 1, | |
| 70 ATTRIBUTE_VALUE: 2, | |
| 71 LINKIFY: 4, | |
| 72 A_NODE: 8, | |
| 73 SCRIPT: 16, | |
| 74 STYLE: 32 | |
| 75 }; | |
| 76 | |
| 77 this.condition = this.createInitialCondition(); | |
| 78 } | |
| 79 | |
| 80 WebInspector.SourceHTMLTokenizer.prototype = { | |
| 81 createInitialCondition: function() | |
| 82 { | |
| 83 return { lexCondition: this._lexConditions.INITIAL, parseCondition: this
._parseConditions.INITIAL }; | |
| 84 }, | |
| 85 | |
| 86 set line(line) { | |
| 87 if (this._condition.internalJavaScriptTokenizerCondition) { | |
| 88 var match = /<\/script/i.exec(line); | |
| 89 if (match) { | |
| 90 this._internalJavaScriptTokenizer.line = line.substring(0, match
.index); | |
| 91 } else | |
| 92 this._internalJavaScriptTokenizer.line = line; | |
| 93 } else if (this._condition.internalCSSTokenizerCondition) { | |
| 94 var match = /<\/style/i.exec(line); | |
| 95 if (match) { | |
| 96 this._internalCSSTokenizer.line = line.substring(0, match.index)
; | |
| 97 } else | |
| 98 this._internalCSSTokenizer.line = line; | |
| 99 } | |
| 100 this._line = line; | |
| 101 }, | |
| 102 | |
| 103 _isExpectingAttribute: function() | |
| 104 { | |
| 105 return this._condition.parseCondition & this._parseConditions.ATTRIBUTE; | |
| 106 }, | |
| 107 | |
| 108 _isExpectingAttributeValue: function() | |
| 109 { | |
| 110 return this._condition.parseCondition & this._parseConditions.ATTRIBUTE_
VALUE; | |
| 111 }, | |
| 112 | |
| 113 _setExpectingAttribute: function() | |
| 114 { | |
| 115 if (this._isExpectingAttributeValue()) | |
| 116 this._condition.parseCondition ^= this._parseConditions.ATTRIBUTE_VA
LUE; | |
| 117 this._condition.parseCondition |= this._parseConditions.ATTRIBUTE; | |
| 118 }, | |
| 119 | |
| 120 _setExpectingAttributeValue: function() | |
| 121 { | |
| 122 if (this._isExpectingAttribute()) | |
| 123 this._condition.parseCondition ^= this._parseConditions.ATTRIBUTE; | |
| 124 this._condition.parseCondition |= this._parseConditions.ATTRIBUTE_VALUE; | |
| 125 }, | |
| 126 | |
| 127 /** | |
| 128 * @param {boolean=} stringEnds | |
| 129 */ | |
| 130 _stringToken: function(cursor, stringEnds) | |
| 131 { | |
| 132 if (!this._isExpectingAttributeValue()) { | |
| 133 this.tokenType = null; | |
| 134 return cursor; | |
| 135 } | |
| 136 this.tokenType = this._attrValueTokenType(); | |
| 137 if (stringEnds) | |
| 138 this._setExpectingAttribute(); | |
| 139 return cursor; | |
| 140 }, | |
| 141 | |
| 142 _attrValueTokenType: function() | |
| 143 { | |
| 144 if (this._condition.parseCondition & this._parseConditions.LINKIFY) { | |
| 145 if (this._condition.parseCondition & this._parseConditions.A_NODE) | |
| 146 return "html-external-link"; | |
| 147 return "html-resource-link"; | |
| 148 } | |
| 149 return "html-attribute-value"; | |
| 150 }, | |
| 151 | |
| 152 get _internalJavaScriptTokenizer() | |
| 153 { | |
| 154 return WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(
"text/javascript"); | |
| 155 }, | |
| 156 | |
| 157 get _internalCSSTokenizer() | |
| 158 { | |
| 159 return WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(
"text/css"); | |
| 160 }, | |
| 161 | |
| 162 scriptStarted: function(cursor) | |
| 163 { | |
| 164 this._condition.internalJavaScriptTokenizerCondition = this._internalJav
aScriptTokenizer.createInitialCondition(); | |
| 165 }, | |
| 166 | |
| 167 scriptEnded: function(cursor) | |
| 168 { | |
| 169 }, | |
| 170 | |
| 171 styleSheetStarted: function(cursor) | |
| 172 { | |
| 173 this._condition.internalCSSTokenizerCondition = this._internalCSSTokeniz
er.createInitialCondition(); | |
| 174 }, | |
| 175 | |
| 176 styleSheetEnded: function(cursor) | |
| 177 { | |
| 178 }, | |
| 179 | |
| 180 nextToken: function(cursor) | |
| 181 { | |
| 182 if (this._condition.internalJavaScriptTokenizerCondition) { | |
| 183 // Re-set line to force </script> detection first. | |
| 184 this.line = this._line; | |
| 185 if (cursor !== this._internalJavaScriptTokenizer._line.length) { | |
| 186 // Tokenizer is stateless, so restore its condition before token
izing and save it after. | |
| 187 this._internalJavaScriptTokenizer.condition = this._condition.in
ternalJavaScriptTokenizerCondition; | |
| 188 var result = this._internalJavaScriptTokenizer.nextToken(cursor)
; | |
| 189 this.tokenType = this._internalJavaScriptTokenizer.tokenType; | |
| 190 this._condition.internalJavaScriptTokenizerCondition = this._int
ernalJavaScriptTokenizer.condition; | |
| 191 return result; | |
| 192 } else if (cursor !== this._line.length) | |
| 193 delete this._condition.internalJavaScriptTokenizerCondition; | |
| 194 } else if (this._condition.internalCSSTokenizerCondition) { | |
| 195 // Re-set line to force </style> detection first. | |
| 196 this.line = this._line; | |
| 197 if (cursor !== this._internalCSSTokenizer._line.length) { | |
| 198 // Tokenizer is stateless, so restore its condition before token
izing and save it after. | |
| 199 this._internalCSSTokenizer.condition = this._condition.internalC
SSTokenizerCondition; | |
| 200 var result = this._internalCSSTokenizer.nextToken(cursor); | |
| 201 this.tokenType = this._internalCSSTokenizer.tokenType; | |
| 202 this._condition.internalCSSTokenizerCondition = this._internalCS
STokenizer.condition; | |
| 203 return result; | |
| 204 } else if (cursor !== this._line.length) | |
| 205 delete this._condition.internalCSSTokenizerCondition; | |
| 206 } | |
| 207 | |
| 208 var cursorOnEnter = cursor; | |
| 209 var gotoCase = 1; | |
| 210 var YYMARKER; | |
| 211 while (1) { | |
| 212 switch (gotoCase) | |
| 213 // Following comment is replaced with generated state machine. | |
| 214 /*!re2c | |
| 215 re2c:define:YYCTYPE = "var"; | |
| 216 re2c:define:YYCURSOR = cursor; | |
| 217 re2c:define:YYGETCONDITION = "this.getLexCondition"; | |
| 218 re2c:define:YYSETCONDITION = "this.setLexCondition"; | |
| 219 re2c:condprefix = "case this.case_"; | |
| 220 re2c:condenumprefix = "this._lexConditions."; | |
| 221 re2c:yyfill:enable = 0; | |
| 222 re2c:labelprefix = "case "; | |
| 223 re2c:indent:top = 2; | |
| 224 re2c:indent:string = " "; | |
| 225 | |
| 226 CommentContent = ([^-\r\n] | ("--" [^>]))*; | |
| 227 Comment = "<!--" CommentContent "-->"; | |
| 228 CommentStart = "<!--" CommentContent [\r\n]; | |
| 229 CommentEnd = CommentContent "-->"; | |
| 230 | |
| 231 DocTypeStart = "<!" [Dd] [Oo] [Cc] [Tt] [Yy] [Pp] [Ee]; | |
| 232 DocTypeContent = [^\r\n>]*; | |
| 233 | |
| 234 ScriptStart = "<" [Ss] [Cc] [Rr] [Ii] [Pp] [Tt]; | |
| 235 ScriptEnd = "</" [Ss] [Cc] [Rr] [Ii] [Pp] [Tt]; | |
| 236 | |
| 237 StyleStart = "<" [Ss] [Tt] [Yy] [Ll] [Ee]; | |
| 238 StyleEnd = "</" [Ss] [Tt] [Yy] [Ll] [Ee]; | |
| 239 | |
| 240 LT = "<" | "</"; | |
| 241 GT = ">"; | |
| 242 EqualSign = "="; | |
| 243 | |
| 244 DoubleStringContent = [^\r\n\"]*; | |
| 245 SingleStringContent = [^\r\n\']*; | |
| 246 StringLiteral = "\"" DoubleStringContent "\"" | "'" SingleString
Content "'"; | |
| 247 DoubleStringStart = "\"" DoubleStringContent [\r\n]; | |
| 248 DoubleStringEnd = DoubleStringContent "\""; | |
| 249 SingleStringStart = "'" SingleStringContent [\r\n]; | |
| 250 SingleStringEnd = SingleStringContent "'"; | |
| 251 | |
| 252 Identifier = [^ \r\n"'<>\[\]=]+; | |
| 253 | |
| 254 <INITIAL> Comment { this.tokenType = "html-comment"; return curs
or; } | |
| 255 <INITIAL> CommentStart => COMMENT { this.tokenType = "html-comme
nt"; return cursor; } | |
| 256 <COMMENT> CommentContent => COMMENT { this.tokenType = "html-com
ment"; return cursor; } | |
| 257 <COMMENT> CommentEnd => INITIAL { this.tokenType = "html-comment
"; return cursor; } | |
| 258 | |
| 259 <INITIAL> DocTypeStart => DOCTYPE { this.tokenType = "html-docty
pe"; return cursor; } | |
| 260 <DOCTYPE> DocTypeContent => DOCTYPE { this.tokenType = "html-doc
type"; return cursor; } | |
| 261 <DOCTYPE> GT => INITIAL { this.tokenType = "html-doctype"; retur
n cursor; } | |
| 262 | |
| 263 <INITIAL> ScriptStart => TAG | |
| 264 { | |
| 265 if (this._condition.parseCondition & this._parseConditions.S
CRIPT) { | |
| 266 // Do not tokenize script tag contents, keep lexer state
, even though processing "<". | |
| 267 this.setLexCondition(this._lexConditions.INITIAL); | |
| 268 this.tokenType = null; | |
| 269 return cursor; | |
| 270 } | |
| 271 this.tokenType = "html-tag"; | |
| 272 this._condition.parseCondition = this._parseConditions.SCRIP
T; | |
| 273 this._setExpectingAttribute(); | |
| 274 return cursor; | |
| 275 } | |
| 276 | |
| 277 <INITIAL> ScriptEnd => TAG | |
| 278 { | |
| 279 this.tokenType = "html-tag"; | |
| 280 this._condition.parseCondition = this._parseConditions.INITI
AL; | |
| 281 this.scriptEnded(cursor - 8); | |
| 282 return cursor; | |
| 283 } | |
| 284 | |
| 285 <INITIAL> StyleStart => TAG | |
| 286 { | |
| 287 if (this._condition.parseCondition & this._parseConditions.S
TYLE) { | |
| 288 // Do not tokenize style tag contents, keep lexer state,
even though processing "<". | |
| 289 this.setLexCondition(this._lexConditions.INITIAL); | |
| 290 this.tokenType = null; | |
| 291 return cursor; | |
| 292 } | |
| 293 this.tokenType = "html-tag"; | |
| 294 this._condition.parseCondition = this._parseConditions.STYLE
; | |
| 295 this._setExpectingAttribute(); | |
| 296 return cursor; | |
| 297 } | |
| 298 | |
| 299 <INITIAL> StyleEnd => TAG | |
| 300 { | |
| 301 this.tokenType = "html-tag"; | |
| 302 this._condition.parseCondition = this._parseConditions.INITI
AL; | |
| 303 this.styleSheetEnded(cursor - 7); | |
| 304 return cursor; | |
| 305 } | |
| 306 | |
| 307 <INITIAL> LT => TAG | |
| 308 { | |
| 309 if (this._condition.parseCondition & (this._parseConditions.
SCRIPT | this._parseConditions.STYLE)) { | |
| 310 // Do not tokenize script and style tag contents, keep l
exer state, even though processing "<". | |
| 311 this.setLexCondition(this._lexConditions.INITIAL); | |
| 312 this.tokenType = null; | |
| 313 return cursor; | |
| 314 } | |
| 315 | |
| 316 this._condition.parseCondition = this._parseConditions.INITI
AL; | |
| 317 this.tokenType = "html-tag"; | |
| 318 return cursor; | |
| 319 } | |
| 320 | |
| 321 <TAG> GT => INITIAL | |
| 322 { | |
| 323 this.tokenType = "html-tag"; | |
| 324 if (this._condition.parseCondition & this._parseConditions.S
CRIPT) { | |
| 325 this.scriptStarted(cursor); | |
| 326 // Do not tokenize script tag contents. | |
| 327 return cursor; | |
| 328 } | |
| 329 | |
| 330 if (this._condition.parseCondition & this._parseConditions.S
TYLE) { | |
| 331 this.styleSheetStarted(cursor); | |
| 332 // Do not tokenize style tag contents. | |
| 333 return cursor; | |
| 334 } | |
| 335 | |
| 336 this._condition.parseCondition = this._parseConditions.INITI
AL; | |
| 337 return cursor; | |
| 338 } | |
| 339 | |
| 340 <TAG> StringLiteral { return this._stringToken(cursor, true); } | |
| 341 <TAG> DoubleStringStart => DSTRING { return this._stringToken(cu
rsor); } | |
| 342 <DSTRING> DoubleStringContent => DSTRING { return this._stringTo
ken(cursor); } | |
| 343 <DSTRING> DoubleStringEnd => TAG { return this._stringToken(curs
or, true); } | |
| 344 <TAG> SingleStringStart => SSTRING { return this._stringToken(cu
rsor); } | |
| 345 <SSTRING> SingleStringContent => SSTRING { return this._stringTo
ken(cursor); } | |
| 346 <SSTRING> SingleStringEnd => TAG { return this._stringToken(curs
or, true); } | |
| 347 | |
| 348 <TAG> EqualSign => TAG | |
| 349 { | |
| 350 if (this._isExpectingAttribute()) | |
| 351 this._setExpectingAttributeValue(); | |
| 352 this.tokenType = null; | |
| 353 return cursor; | |
| 354 } | |
| 355 | |
| 356 <TAG> Identifier | |
| 357 { | |
| 358 if (this._condition.parseCondition === this._parseConditions
.SCRIPT || this._condition.parseCondition === this._parseConditions.STYLE) { | |
| 359 // Fall through if expecting attributes. | |
| 360 this.tokenType = null; | |
| 361 return cursor; | |
| 362 } | |
| 363 | |
| 364 if (this._condition.parseCondition === this._parseConditions
.INITIAL) { | |
| 365 this.tokenType = "html-tag"; | |
| 366 this._setExpectingAttribute(); | |
| 367 var token = this._line.substring(cursorOnEnter, cursor); | |
| 368 if (token === "a") | |
| 369 this._condition.parseCondition |= this._parseConditi
ons.A_NODE; | |
| 370 else if (this._condition.parseCondition & this._parseCon
ditions.A_NODE) | |
| 371 this._condition.parseCondition ^= this._parseConditi
ons.A_NODE; | |
| 372 } else if (this._isExpectingAttribute()) { | |
| 373 var token = this._line.substring(cursorOnEnter, cursor); | |
| 374 if (token === "href" || token === "src") | |
| 375 this._condition.parseCondition |= this._parseConditi
ons.LINKIFY; | |
| 376 else if (this._condition.parseCondition |= this._parseCo
nditions.LINKIFY) | |
| 377 this._condition.parseCondition ^= this._parseConditi
ons.LINKIFY; | |
| 378 this.tokenType = "html-attribute-name"; | |
| 379 } else if (this._isExpectingAttributeValue()) | |
| 380 this.tokenType = this._attrValueTokenType(); | |
| 381 else | |
| 382 this.tokenType = null; | |
| 383 return cursor; | |
| 384 } | |
| 385 <*> [^] { this.tokenType = null; return cursor; } | |
| 386 */ | |
| 387 } | |
| 388 }, | |
| 389 | |
| 390 __proto__: WebInspector.SourceTokenizer.prototype | |
| 391 } | |
| OLD | NEW |