mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
token: fix a new_keywords_matcher_from_array_trie bug (first word with idx 0 was ignored); add tests
This commit is contained in:
parent
a42eb3b947
commit
2db8bd62a2
@ -5,7 +5,7 @@ module token
|
|||||||
// See the module description for more details.
|
// See the module description for more details.
|
||||||
[heap]
|
[heap]
|
||||||
pub struct KeywordsMatcherTrie {
|
pub struct KeywordsMatcherTrie {
|
||||||
mut:
|
pub mut:
|
||||||
nodes []&TrieNode
|
nodes []&TrieNode
|
||||||
min_len int = 999999
|
min_len int = 999999
|
||||||
max_len int
|
max_len int
|
||||||
@ -13,9 +13,9 @@ mut:
|
|||||||
|
|
||||||
// TrieNode is a single node from a trie, used by KeywordsMatcherTrie
|
// TrieNode is a single node from a trie, used by KeywordsMatcherTrie
|
||||||
pub struct TrieNode {
|
pub struct TrieNode {
|
||||||
mut:
|
pub mut:
|
||||||
children [123]&TrieNode
|
children [123]&TrieNode
|
||||||
value int // when positive, it is a leaf node representing a match
|
value int = -1 // when != -1, it is a leaf node representing a match
|
||||||
}
|
}
|
||||||
|
|
||||||
// find tries to find the given `word` in the set of all previously added words
|
// find tries to find the given `word` in the set of all previously added words
|
||||||
@ -38,6 +38,11 @@ pub fn (km &KeywordsMatcherTrie) find(word string) int {
|
|||||||
return node.find(word)
|
return node.find(word)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn (km &KeywordsMatcherTrie) matches(word string) bool {
|
||||||
|
return km.find(word) != -1
|
||||||
|
}
|
||||||
|
|
||||||
// add_word adds the given word to the KeywordsMatcherTrie instance. It associates a non
|
// add_word adds the given word to the KeywordsMatcherTrie instance. It associates a non
|
||||||
// negative integer value to it, so later `find` could return the value, when it succeeds.
|
// negative integer value to it, so later `find` could return the value, when it succeeds.
|
||||||
[direct_array_access]
|
[direct_array_access]
|
||||||
@ -92,13 +97,14 @@ pub fn new_trie_node() &TrieNode {
|
|||||||
|
|
||||||
// show displays the information in `node`, in a more compact/readable format (recursively)
|
// show displays the information in `node`, in a more compact/readable format (recursively)
|
||||||
pub fn (node &TrieNode) show(level int) {
|
pub fn (node &TrieNode) show(level int) {
|
||||||
mut non_nil_children := 0
|
mut non_nil_children := []int{}
|
||||||
for x in node.children {
|
for idx, x in node.children {
|
||||||
if x != unsafe { nil } {
|
if x != unsafe { nil } {
|
||||||
non_nil_children++
|
non_nil_children << idx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
eprintln('> level: ${level:2} | value: ${node.value:12} | non_nil_children: ${non_nil_children:2}')
|
children := non_nil_children.map(u8(it).ascii_str())
|
||||||
|
eprintln('> level: ${level:2} | value: ${node.value:12} | non_nil_children: ${non_nil_children.len:2} | $children')
|
||||||
for x in node.children {
|
for x in node.children {
|
||||||
if x != unsafe { nil } {
|
if x != unsafe { nil } {
|
||||||
x.show(level + 1)
|
x.show(level + 1)
|
||||||
@ -134,7 +140,7 @@ pub fn (root &TrieNode) find(word string) int {
|
|||||||
// eprintln('> match_keyword: `${word:20}` | node: ${ptr_str(node)} | idx: ${idx:3}')
|
// eprintln('> match_keyword: `${word:20}` | node: ${ptr_str(node)} | idx: ${idx:3}')
|
||||||
if idx == wlen {
|
if idx == wlen {
|
||||||
k := node.value
|
k := node.value
|
||||||
if k > 0 {
|
if k != -1 {
|
||||||
// node.show(0)
|
// node.show(0)
|
||||||
return k
|
return k
|
||||||
}
|
}
|
||||||
|
13
vlib/v/token/keywords_matcher_trie_test.v
Normal file
13
vlib/v/token/keywords_matcher_trie_test.v
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import v.token
|
||||||
|
|
||||||
|
fn test_new_keywords_matcher_from_array_trie_works() {
|
||||||
|
method_names := ['filter', 'clone', 'repeat', 'reverse', 'map', 'slice', 'sort', 'contains',
|
||||||
|
'index', 'wait', 'any', 'all', 'first', 'last', 'pop']
|
||||||
|
matcher := token.new_keywords_matcher_from_array_trie(method_names)
|
||||||
|
for word in [method_names.first(), method_names.last(), 'something', 'another', 'x', 'y', '',
|
||||||
|
'---', '123', 'abc.def', 'xyz !@#'] {
|
||||||
|
res1 := matcher.find(word) != -1
|
||||||
|
res2 := word in method_names
|
||||||
|
assert res1 == res2
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user