| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2005 Maksim Orlovich <maksim@kde.org> | 2 * Copyright 2005 Maksim Orlovich <maksim@kde.org> |
| 3 * Copyright (C) 2006 Apple Computer, Inc. | 3 * Copyright (C) 2006 Apple Computer, Inc. |
| 4 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> | 4 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 8 * are met: | 8 * are met: |
| 9 * | 9 * |
| 10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 26 */ | 26 */ |
| 27 | 27 |
| 28 #include "config.h" | 28 #include "config.h" |
| 29 #include "core/xml/XPathParser.h" | 29 #include "core/xml/XPathParser.h" |
| 30 | 30 |
| 31 #include "bindings/v8/ExceptionState.h" | 31 #include "bindings/v8/ExceptionState.h" |
| 32 #include "core/XPathGrammar.h" |
| 32 #include "core/dom/ExceptionCode.h" | 33 #include "core/dom/ExceptionCode.h" |
| 33 #include "core/xml/XPathEvaluator.h" | 34 #include "core/xml/XPathEvaluator.h" |
| 34 #include "core/xml/XPathNSResolver.h" | 35 #include "core/xml/XPathNSResolver.h" |
| 35 #include "core/xml/XPathPath.h" | 36 #include "core/xml/XPathPath.h" |
| 36 #include "wtf/StdLibExtras.h" | 37 #include "wtf/StdLibExtras.h" |
| 37 #include "wtf/text/StringHash.h" | 38 #include "wtf/text/StringHash.h" |
| 38 | 39 |
| 39 using namespace WebCore; | 40 using namespace WebCore; |
| 40 using namespace WTF; | 41 using namespace WTF; |
| 41 using namespace Unicode; | 42 using namespace Unicode; |
| 42 using namespace XPath; | 43 using namespace XPath; |
| 43 | 44 |
| 44 #include "core/XPathGrammar.h" | |
| 45 | |
| 46 Parser* Parser::currentParser = 0; | 45 Parser* Parser::currentParser = 0; |
| 47 | 46 |
| 48 enum XMLCat { NameStart, NameCont, NotPartOfName }; | 47 enum XMLCat { NameStart, NameCont, NotPartOfName }; |
| 49 | 48 |
| 50 typedef HashMap<String, Step::Axis> AxisNamesMap; | 49 typedef HashMap<String, Step::Axis> AxisNamesMap; |
| 51 | 50 |
| 52 static XMLCat charCat(UChar aChar) | 51 static XMLCat charCat(UChar aChar) |
| 53 { | 52 { |
| 54 //### might need to add some special cases from the XML spec. | 53 // might need to add some special cases from the XML spec. |
| 55 | 54 |
| 56 if (aChar == '_') | 55 if (aChar == '_') |
| 57 return NameStart; | 56 return NameStart; |
| 58 | 57 |
| 59 if (aChar == '.' || aChar == '-') | 58 if (aChar == '.' || aChar == '-') |
| 60 return NameCont; | 59 return NameCont; |
| 61 CharCategory category = Unicode::category(aChar); | 60 CharCategory category = Unicode::category(aChar); |
| 62 if (category & (Letter_Uppercase | Letter_Lowercase | Letter_Other | Letter_
Titlecase | Number_Letter)) | 61 if (category & (Letter_Uppercase | Letter_Lowercase | Letter_Other | Letter_
Titlecase | Number_Letter)) |
| 63 return NameStart; | 62 return NameStart; |
| 64 if (category & (Mark_NonSpacing | Mark_SpacingCombining | Mark_Enclosing | L
etter_Modifier | Number_DecimalDigit)) | 63 if (category & (Mark_NonSpacing | Mark_SpacingCombining | Mark_Enclosing | L
etter_Modifier | Number_DecimalDigit)) |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 } | 199 } |
| 201 | 200 |
| 202 Token Parser::lexNumber() | 201 Token Parser::lexNumber() |
| 203 { | 202 { |
| 204 int startPos = m_nextPos; | 203 int startPos = m_nextPos; |
| 205 bool seenDot = false; | 204 bool seenDot = false; |
| 206 | 205 |
| 207 // Go until end or a non-digits character. | 206 // Go until end or a non-digits character. |
| 208 for (; m_nextPos < m_data.length(); ++m_nextPos) { | 207 for (; m_nextPos < m_data.length(); ++m_nextPos) { |
| 209 UChar aChar = m_data[m_nextPos]; | 208 UChar aChar = m_data[m_nextPos]; |
| 210 if (aChar >= 0xff) break; | 209 if (aChar >= 0xff) |
| 210 break; |
| 211 | 211 |
| 212 if (aChar < '0' || aChar > '9') { | 212 if (aChar < '0' || aChar > '9') { |
| 213 if (aChar == '.' && !seenDot) | 213 if (aChar == '.' && !seenDot) |
| 214 seenDot = true; | 214 seenDot = true; |
| 215 else | 215 else |
| 216 break; | 216 break; |
| 217 } | 217 } |
| 218 } | 218 } |
| 219 | 219 |
| 220 return Token(NUMBER, m_data.substring(startPos, m_nextPos - startPos)); | 220 return Token(NUMBER, m_data.substring(startPos, m_nextPos - startPos)); |
| 221 } | 221 } |
| 222 | 222 |
| 223 bool Parser::lexNCName(String& name) | 223 bool Parser::lexNCName(String& name) |
| 224 { | 224 { |
| 225 int startPos = m_nextPos; | 225 int startPos = m_nextPos; |
| 226 if (m_nextPos >= m_data.length()) | 226 if (m_nextPos >= m_data.length()) |
| 227 return false; | 227 return false; |
| 228 | 228 |
| 229 if (charCat(m_data[m_nextPos]) != NameStart) | 229 if (charCat(m_data[m_nextPos]) != NameStart) |
| 230 return false; | 230 return false; |
| 231 | 231 |
| 232 // Keep going until we get a character that's not good for names. | 232 // Keep going until we get a character that's not good for names. |
| 233 for (; m_nextPos < m_data.length(); ++m_nextPos) | 233 for (; m_nextPos < m_data.length(); ++m_nextPos) { |
| 234 if (charCat(m_data[m_nextPos]) == NotPartOfName) | 234 if (charCat(m_data[m_nextPos]) == NotPartOfName) |
| 235 break; | 235 break; |
| 236 } |
| 236 | 237 |
| 237 name = m_data.substring(startPos, m_nextPos - startPos); | 238 name = m_data.substring(startPos, m_nextPos - startPos); |
| 238 return true; | 239 return true; |
| 239 } | 240 } |
| 240 | 241 |
| 241 bool Parser::lexQName(String& name) | 242 bool Parser::lexQName(String& name) |
| 242 { | 243 { |
| 243 String n1; | 244 String n1; |
| 244 if (!lexNCName(n1)) | 245 if (!lexNCName(n1)) |
| 245 return false; | 246 return false; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 } | 290 } |
| 290 case '/': | 291 case '/': |
| 291 if (peekAheadHelper() == '/') | 292 if (peekAheadHelper() == '/') |
| 292 return makeTokenAndAdvance(SLASHSLASH, 2); | 293 return makeTokenAndAdvance(SLASHSLASH, 2); |
| 293 return makeTokenAndAdvance('/'); | 294 return makeTokenAndAdvance('/'); |
| 294 case '+': | 295 case '+': |
| 295 return makeTokenAndAdvance(PLUS); | 296 return makeTokenAndAdvance(PLUS); |
| 296 case '-': | 297 case '-': |
| 297 return makeTokenAndAdvance(MINUS); | 298 return makeTokenAndAdvance(MINUS); |
| 298 case '=': | 299 case '=': |
| 299 return makeTokenAndAdvance(EQOP, EqTestOp::OP_EQ); | 300 return makeTokenAndAdvance(EQOP, EqTestOp::OpcodeEqual); |
| 300 case '!': | 301 case '!': |
| 301 if (peekAheadHelper() == '=') | 302 if (peekAheadHelper() == '=') |
| 302 return makeTokenAndAdvance(EQOP, EqTestOp::OP_NE, 2); | 303 return makeTokenAndAdvance(EQOP, EqTestOp::OpcodeNotEqual, 2); |
| 303 return Token(XPATH_ERROR); | 304 return Token(XPATH_ERROR); |
| 304 case '<': | 305 case '<': |
| 305 if (peekAheadHelper() == '=') | 306 if (peekAheadHelper() == '=') |
| 306 return makeTokenAndAdvance(RELOP, EqTestOp::OP_LE, 2); | 307 return makeTokenAndAdvance(RELOP, EqTestOp::OpcodeLessOrEqual, 2); |
| 307 return makeTokenAndAdvance(RELOP, EqTestOp::OP_LT); | 308 return makeTokenAndAdvance(RELOP, EqTestOp::OpcodeLessThan); |
| 308 case '>': | 309 case '>': |
| 309 if (peekAheadHelper() == '=') | 310 if (peekAheadHelper() == '=') |
| 310 return makeTokenAndAdvance(RELOP, EqTestOp::OP_GE, 2); | 311 return makeTokenAndAdvance(RELOP, EqTestOp::OpcodeGreaterOrEqual, 2)
; |
| 311 return makeTokenAndAdvance(RELOP, EqTestOp::OP_GT); | 312 return makeTokenAndAdvance(RELOP, EqTestOp::OpcodeGreaterThan); |
| 312 case '*': | 313 case '*': |
| 313 if (isBinaryOperatorContext()) | 314 if (isBinaryOperatorContext()) |
| 314 return makeTokenAndAdvance(MULOP, NumericOp::OP_Mul); | 315 return makeTokenAndAdvance(MULOP, NumericOp::OP_Mul); |
| 315 ++m_nextPos; | 316 ++m_nextPos; |
| 316 return Token(NAMETEST, "*"); | 317 return Token(NAMETEST, "*"); |
| 317 case '$': { // $ QName | 318 case '$': { // $ QName |
| 318 m_nextPos++; | 319 m_nextPos++; |
| 319 String name; | 320 String name; |
| 320 if (!lexQName(name)) | 321 if (!lexQName(name)) |
| 321 return Token(XPATH_ERROR); | 322 return Token(XPATH_ERROR); |
| 322 return Token(VARIABLEREFERENCE, name); | 323 return Token(VARIABLEREFERENCE, name); |
| 323 } | 324 } |
| 324 } | 325 } |
| 325 | 326 |
| 326 String name; | 327 String name; |
| 327 if (!lexNCName(name)) | 328 if (!lexNCName(name)) |
| 328 return Token(XPATH_ERROR); | 329 return Token(XPATH_ERROR); |
| 329 | 330 |
| 330 skipWS(); | 331 skipWS(); |
| 331 // If we're in an operator context, check for any operator names | 332 // If we're in an operator context, check for any operator names |
| 332 if (isBinaryOperatorContext()) { | 333 if (isBinaryOperatorContext()) { |
| 333 if (name == "and") //### hash? | 334 if (name == "and") // ### hash? |
| 334 return Token(AND); | 335 return Token(AND); |
| 335 if (name == "or") | 336 if (name == "or") |
| 336 return Token(OR); | 337 return Token(OR); |
| 337 if (name == "mod") | 338 if (name == "mod") |
| 338 return Token(MULOP, NumericOp::OP_Mod); | 339 return Token(MULOP, NumericOp::OP_Mod); |
| 339 if (name == "div") | 340 if (name == "div") |
| 340 return Token(MULOP, NumericOp::OP_Div); | 341 return Token(MULOP, NumericOp::OP_Div); |
| 341 } | 342 } |
| 342 | 343 |
| 343 // See whether we are at a : | 344 // See whether we are at a : |
| 344 if (peekCurHelper() == ':') { | 345 if (peekCurHelper() == ':') { |
| 345 m_nextPos++; | 346 m_nextPos++; |
| 346 // Any chance it's an axis name? | 347 // Any chance it's an axis name? |
| 347 if (peekCurHelper() == ':') { | 348 if (peekCurHelper() == ':') { |
| 348 m_nextPos++; | 349 m_nextPos++; |
| 349 | 350 |
| 350 //It might be an axis name. | 351 // It might be an axis name. |
| 351 Step::Axis axis; | 352 Step::Axis axis; |
| 352 if (isAxisName(name, axis)) | 353 if (isAxisName(name, axis)) |
| 353 return Token(AXISNAME, axis); | 354 return Token(AXISNAME, axis); |
| 354 // Ugh, :: is only valid in axis names -> error | 355 // Ugh, :: is only valid in axis names -> error |
| 355 return Token(XPATH_ERROR); | 356 return Token(XPATH_ERROR); |
| 356 } | 357 } |
| 357 | 358 |
| 358 // Seems like this is a fully qualified qname, or perhaps the * modified
one from NameTest | 359 // Seems like this is a fully qualified qname, or perhaps the * modified |
| 360 // one from NameTest |
| 359 skipWS(); | 361 skipWS(); |
| 360 if (peekCurHelper() == '*') { | 362 if (peekCurHelper() == '*') { |
| 361 m_nextPos++; | 363 m_nextPos++; |
| 362 return Token(NAMETEST, name + ":*"); | 364 return Token(NAMETEST, name + ":*"); |
| 363 } | 365 } |
| 364 | 366 |
| 365 // Make a full qname. | 367 // Make a full qname. |
| 366 String n2; | 368 String n2; |
| 367 if (!lexNCName(n2)) | 369 if (!lexNCName(n2)) |
| 368 return Token(XPATH_ERROR); | 370 return Token(XPATH_ERROR); |
| 369 | 371 |
| 370 name = name + ":" + n2; | 372 name = name + ":" + n2; |
| 371 } | 373 } |
| 372 | 374 |
| 373 skipWS(); | 375 skipWS(); |
| 374 if (peekCurHelper() == '(') { | 376 if (peekCurHelper() == '(') { |
| 375 //note: we don't swallow the (here! | 377 // Note: we don't swallow the ( here! |
| 376 | 378 |
| 377 //either node type of function name | 379 // Either node type of function name |
| 378 if (isNodeTypeName(name)) { | 380 if (isNodeTypeName(name)) { |
| 379 if (name == "processing-instruction") | 381 if (name == "processing-instruction") |
| 380 return Token(PI, name); | 382 return Token(PI, name); |
| 381 | 383 |
| 382 return Token(NODETYPE, name); | 384 return Token(NODETYPE, name); |
| 383 } | 385 } |
| 384 //must be a function name. | 386 // Must be a function name. |
| 385 return Token(FUNCTIONNAME, name); | 387 return Token(FUNCTIONNAME, name); |
| 386 } | 388 } |
| 387 | 389 |
| 388 // At this point, it must be NAMETEST. | 390 // At this point, it must be NAMETEST. |
| 389 return Token(NAMETEST, name); | 391 return Token(NAMETEST, name); |
| 390 } | 392 } |
| 391 | 393 |
| 392 Token Parser::nextToken() | 394 Token Parser::nextToken() |
| 393 { | 395 { |
| 394 Token toRet = nextTokenInternal(); | 396 Token toRet = nextTokenInternal(); |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 #if !ENABLE(OILPAN) | 632 #if !ENABLE(OILPAN) |
| 631 if (t == 0) | 633 if (t == 0) |
| 632 return; | 634 return; |
| 633 | 635 |
| 634 ASSERT(m_nodeTests.contains(t)); | 636 ASSERT(m_nodeTests.contains(t)); |
| 635 | 637 |
| 636 m_nodeTests.remove(t); | 638 m_nodeTests.remove(t); |
| 637 #endif | 639 #endif |
| 638 } | 640 } |
| 639 | 641 |
| OLD | NEW |