Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/history/query_parser.h" | 5 #include "chrome/browser/history/query_parser.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/i18n/break_iterator.h" | 10 #include "base/i18n/break_iterator.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 | 73 |
| 74 // A QueryNodeWord is a single word in the query. | 74 // A QueryNodeWord is a single word in the query. |
| 75 class QueryNodeWord : public QueryNode { | 75 class QueryNodeWord : public QueryNode { |
| 76 public: | 76 public: |
| 77 explicit QueryNodeWord(const string16& word); | 77 explicit QueryNodeWord(const string16& word); |
| 78 virtual ~QueryNodeWord(); | 78 virtual ~QueryNodeWord(); |
| 79 | 79 |
| 80 const string16& word() const { return word_; } | 80 const string16& word() const { return word_; } |
| 81 | 81 |
| 82 void set_literal(bool literal) { literal_ = literal; } | 82 void set_literal(bool literal) { literal_ = literal; } |
| 83 void AppendText(const string16& text) { word_ += text; } | |
|
mrossetti
2012/02/07 01:05:57
We generally only inline simple getters and setter
| |
| 83 | 84 |
| 84 // QueryNode: | 85 // QueryNode: |
| 85 virtual int AppendToSQLiteQuery(string16* query) const OVERRIDE; | 86 virtual int AppendToSQLiteQuery(string16* query) const OVERRIDE; |
| 86 virtual bool IsWord() const OVERRIDE; | 87 virtual bool IsWord() const OVERRIDE; |
| 87 virtual bool Matches(const string16& word, bool exact) const OVERRIDE; | 88 virtual bool Matches(const string16& word, bool exact) const OVERRIDE; |
| 88 virtual bool HasMatchIn( | 89 virtual bool HasMatchIn( |
| 89 const std::vector<QueryWord>& words, | 90 const std::vector<QueryWord>& words, |
| 90 Snippet::MatchPositions* match_positions) const OVERRIDE; | 91 Snippet::MatchPositions* match_positions) const OVERRIDE; |
| 91 virtual void AppendWords(std::vector<string16>* words) const OVERRIDE; | 92 virtual void AppendWords(std::vector<string16>* words) const OVERRIDE; |
| 92 | 93 |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 358 // TODO(evanm): support a locale here | 359 // TODO(evanm): support a locale here |
| 359 if (!iter.Init()) | 360 if (!iter.Init()) |
| 360 return false; | 361 return false; |
| 361 | 362 |
| 362 // To handle nesting, we maintain a stack of QueryNodeLists. | 363 // To handle nesting, we maintain a stack of QueryNodeLists. |
| 363 // The last element (back) of the stack contains the current, deepest node. | 364 // The last element (back) of the stack contains the current, deepest node. |
| 364 std::vector<QueryNodeList*> query_stack; | 365 std::vector<QueryNodeList*> query_stack; |
| 365 query_stack.push_back(root); | 366 query_stack.push_back(root); |
| 366 | 367 |
| 367 bool in_quotes = false; // whether we're currently in a quoted phrase | 368 bool in_quotes = false; // whether we're currently in a quoted phrase |
| 369 QueryNodeWord* current_word = NULL; | |
| 368 while (iter.Advance()) { | 370 while (iter.Advance()) { |
| 369 // Just found a span between 'prev' (inclusive) and 'pos' (exclusive). It | 371 // Just found a span between 'prev' (inclusive) and 'pos' (exclusive). It |
| 370 // is not necessarily a word, but could also be a sequence of punctuation | 372 // is not necessarily a word, but could also be a sequence of punctuation |
| 371 // or whitespace. | 373 // or whitespace. |
| 372 if (iter.IsWord()) { | 374 if (IsQueryQuote(query[iter.prev()])) { |
| 373 QueryNodeWord* word_node = new QueryNodeWord(iter.GetString()); | 375 if (!in_quotes) { |
| 376 QueryNodeList* quotes_node = new QueryNodePhrase; | |
| 377 query_stack.back()->AddChild(quotes_node); | |
| 378 query_stack.push_back(quotes_node); | |
| 379 in_quotes = true; | |
| 380 } else { | |
| 381 query_stack.pop_back(); // Stop adding to the quoted phrase. | |
| 382 in_quotes = false; | |
| 383 } | |
| 384 current_word = NULL; | |
| 385 } else if (iter.IsWord() || in_quotes) { | |
|
mrossetti
2012/02/07 01:05:57
Okay, as you can see from the unit tests, trying t
| |
| 386 if (current_word) { | |
| 387 current_word->AppendText(iter.GetString()); | |
| 388 } else { | |
| 389 current_word = new QueryNodeWord(iter.GetString()); | |
| 390 query_stack.back()->AddChild(current_word); | |
|
mrossetti
2012/02/07 01:05:57
Do the set_literal here...
| |
| 391 } | |
| 374 if (in_quotes) | 392 if (in_quotes) |
|
mrossetti
2012/02/07 01:05:57
...not here.
| |
| 375 word_node->set_literal(true); | 393 current_word->set_literal(true); |
| 376 query_stack.back()->AddChild(word_node); | 394 } else { // Punctuation or whitespace outside quotes. |
|
mrossetti
2012/02/07 01:05:57
These empty braces are just screaming for somethin
| |
| 377 } else { // Punctuation. | |
| 378 if (IsQueryQuote(query[iter.prev()])) { | |
| 379 if (!in_quotes) { | |
| 380 QueryNodeList* quotes_node = new QueryNodePhrase; | |
| 381 query_stack.back()->AddChild(quotes_node); | |
| 382 query_stack.push_back(quotes_node); | |
| 383 in_quotes = true; | |
| 384 } else { | |
| 385 query_stack.pop_back(); // Stop adding to the quoted phrase. | |
| 386 in_quotes = false; | |
| 387 } | |
| 388 } | |
| 389 } | 395 } |
| 390 } | 396 } |
| 391 | 397 |
| 392 root->RemoveEmptySubnodes(); | 398 root->RemoveEmptySubnodes(); |
| 393 return true; | 399 return true; |
| 394 } | 400 } |
| 395 | 401 |
| 396 void QueryParser::ExtractQueryWords(const string16& text, | 402 void QueryParser::ExtractQueryWords(const string16& text, |
| 397 std::vector<QueryWord>* words) { | 403 std::vector<QueryWord>* words) { |
| 398 base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_WORD); | 404 base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_WORD); |
| 399 // TODO(evanm): support a locale here | 405 // TODO(evanm): support a locale here |
| 400 if (!iter.Init()) | 406 if (!iter.Init()) |
| 401 return; | 407 return; |
| 402 | 408 |
| 403 while (iter.Advance()) { | 409 while (iter.Advance()) { |
| 404 // Just found a span between 'prev' (inclusive) and 'pos' (exclusive). It | 410 // Just found a span between 'prev' (inclusive) and 'pos' (exclusive). It |
| 405 // is not necessarily a word, but could also be a sequence of punctuation | 411 // is not necessarily a word, but could also be a sequence of punctuation |
| 406 // or whitespace. | 412 // or whitespace. |
| 407 if (iter.IsWord()) { | 413 if (iter.IsWord()) { |
| 408 string16 word = iter.GetString(); | 414 string16 word = iter.GetString(); |
| 409 if (!word.empty()) { | 415 if (!word.empty()) { |
| 410 words->push_back(QueryWord()); | 416 words->push_back(QueryWord()); |
| 411 words->back().word = word; | 417 words->back().word = word; |
| 412 words->back().position = iter.prev(); | 418 words->back().position = iter.prev(); |
| 413 } | 419 } |
| 414 } | 420 } |
| 415 } | 421 } |
| 416 } | 422 } |
| OLD | NEW |