Skip to content

Commit 410c7d6

Browse files
committed
add extra len result value
1 parent bb4b9cf commit 410c7d6

16 files changed

+512
-295
lines changed

Diff for: branch.v

+6-6
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ module vom
44

55
// Tests a list of `parsers` one by one until one succeeds.
66
pub fn alt(parsers []Fn) Fn {
7-
return fn [parsers] (input string) !(string, string) {
7+
return fn [parsers] (input string) !(string, string, int) {
88
for parser in parsers {
9-
temp, output := parser(input) or { continue }
10-
return temp, output
9+
temp, output, len := parser(input) or { continue }
10+
return temp, output, len
1111
}
1212
return error('`alt` failed on input `${input}` with `${parsers.len}` parsers')
1313
}
@@ -16,7 +16,7 @@ pub fn alt(parsers []Fn) Fn {
1616
// Applies a list of `parsers` in any order.
1717
// Permutation will succeed if all of the child `parsers` succeeded. It takes as argument a tuple of `parsers`, and returns a tuple of the parser results.
1818
pub fn permutation(parsers []Fn) FnMany {
19-
return fn [parsers] (input string) !(string, []string) {
19+
return fn [parsers] (input string) !(string, []string, int) {
2020
for perm in quick_perm(parsers.len) {
2121
mut functions := []Fn{}
2222
for i in perm {
@@ -25,8 +25,8 @@ pub fn permutation(parsers []Fn) FnMany {
2525
parser := tuple(functions)
2626
// the code above should just work as below, bug for now:
2727
// parser := tuple(...perm.map(parsers[index]))
28-
temp, output := parser(input) or { continue }
29-
return temp, output
28+
temp, output, len := parser(input) or { continue }
29+
return temp, output, len
3030
}
3131
return error('`permutation` failed on `${input}` because no permutations were found')
3232
}

Diff for: branch_test.v

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ module vom
22

33
fn test_alt() ! {
44
parser := alt([tag('llo'), take(9), tag('hi'), take(5)])
5-
rest, output := parser('hello...')!
5+
rest, output, len := parser('hello...')!
66
assert output == 'hello'
77
assert rest == '...'
8+
assert len == 5
89
}
910

1011
fn test_permutation() ! {
1112
parser := permutation([tag('123'), tag('abc')])
12-
rest, output := parser('abc123123abc...')!
13+
rest, output, len := parser('abc123123abc...')!
1314
assert output == ['abc', '123']
1415
assert rest == '123abc...'
16+
assert len == 6
1517
}

Diff for: bytes.v

+32-32
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,26 @@ module vom
88
// The third argument matches the escaped characters
99

1010
pub fn escaped(normal Fn, control_char rune, escapable Fn) Fn {
11-
return fn [normal, control_char, escapable] (input string) !(string, string) {
11+
return fn [normal, control_char, escapable] (input string) !(string, string, int) {
1212
check_control_char := tag(control_char.str())
13-
a, b := normal(input) or { input, '' }
14-
c, d := check_control_char(a) or { a, '' }
15-
e, f := escapable(c) or { c, '' }
16-
g, h := normal(e) or { e, '' }
13+
a, b, len1 := normal(input) or { input, '', 0 }
14+
c, d, len2 := check_control_char(a) or { a, '', 0 }
15+
e, f, len3 := escapable(c) or { c, '', 0 }
16+
g, h, len4 := normal(e) or { e, '', 0 }
1717

1818
if input == g {
1919
return error('`escaped` fail')
2020
}
21-
return g, b + d + f + h
21+
return g, b + d + f + h, len1 + len2 + len3 + len4
2222
}
2323
}
2424

2525
// Returns the longest slice that matches any character in the `pattern`.
2626
pub fn is_a(pattern string) Fn {
27-
return fn [pattern] (input string) !(string, string) {
27+
return fn [pattern] (input string) !(string, string, int) {
2828
for i, c in input {
2929
if !pattern.bytes().any(it == c) {
30-
return input[i..], input[..i]
30+
return input[i..], input[..i], i
3131
}
3232
}
3333
return error('`is_a` failed with pattern `${pattern}` on input `${input}`')
@@ -36,10 +36,10 @@ pub fn is_a(pattern string) Fn {
3636

3737
// Parse till certain characters are met.
3838
pub fn is_not(pattern string) Fn {
39-
return fn [pattern] (input string) !(string, string) {
39+
return fn [pattern] (input string) !(string, string, int) {
4040
for i, c in input {
4141
if pattern.bytes().any(it == c) {
42-
return input[i..], input[..i]
42+
return input[i..], input[..i], i
4343
}
4444
}
4545
return error('`is_not` failed with pattern `${pattern}` on input `${input}`')
@@ -48,12 +48,12 @@ pub fn is_not(pattern string) Fn {
4848

4949
// Recognizes a `pattern`.
5050
pub fn tag(pattern string) Fn {
51-
return fn [pattern] (input string) !(string, string) {
51+
return fn [pattern] (input string) !(string, string, int) {
5252
if input.len < pattern.len {
5353
return error('`tag` failed because input `${input}` is shorter than pattern `${pattern}`')
5454
}
5555
if input[..pattern.len] == pattern {
56-
return input[pattern.len..], input[..pattern.len]
56+
return input[pattern.len..], input[..pattern.len], pattern.len
5757
} else {
5858
return error('`tag` failed because `${input}[..${pattern.len}]` is not equal to pattern `${pattern}`')
5959
}
@@ -62,12 +62,12 @@ pub fn tag(pattern string) Fn {
6262

6363
// Recognizes a case insensitive `pattern`.
6464
pub fn tag_no_case(pattern string) Fn {
65-
return fn [pattern] (input string) !(string, string) {
65+
return fn [pattern] (input string) !(string, string, int) {
6666
if input.len < pattern.len {
6767
return error('`tag_no_case` failed because input `${input}` is shorter than pattern `${pattern}`')
6868
}
6969
if input[..pattern.len].to_lower() == pattern.to_lower() {
70-
return input[pattern.len..], input[..pattern.len]
70+
return input[pattern.len..], input[..pattern.len], pattern.len
7171
} else {
7272
return error('`tag_no_case` failed because `${input}[..${pattern.len}].to_lower()` is not equal to pattern `${pattern}`')
7373
}
@@ -76,21 +76,21 @@ pub fn tag_no_case(pattern string) Fn {
7676

7777
// Returns an input slice containing the first `n` input elements (Input[..`n`]).
7878
pub fn take(n int) Fn {
79-
return fn [n] (input string) !(string, string) {
79+
return fn [n] (input string) !(string, string, int) {
8080
if input.len < n {
8181
return error('`take` failed with count `${n}` on input `${input}`')
8282
} else {
83-
return input[n..], input[..n]
83+
return input[n..], input[..n], n
8484
}
8585
}
8686
}
8787

8888
// Returns the longest input slice (if any) till a predicate `condition` is met.
8989
pub fn take_till(condition fn (byte) bool) Fn {
90-
return fn [condition] (input string) !(string, string) {
90+
return fn [condition] (input string) !(string, string, int) {
9191
for i, c in input.bytes() {
9292
if condition(c) {
93-
return input[i..], input[..i]
93+
return input[i..], input[..i], i
9494
}
9595
}
9696
return error('`take_till` failed on input `${input}`')
@@ -99,10 +99,10 @@ pub fn take_till(condition fn (byte) bool) Fn {
9999

100100
// Returns the longest (at least 1) input slice till a predicate `condition` is met.
101101
pub fn take_till1(condition fn (byte) bool) Fn {
102-
return fn [condition] (input string) !(string, string) {
102+
return fn [condition] (input string) !(string, string, int) {
103103
for i, c in input.bytes() {
104104
if condition(c) && i > 0 {
105-
return input[i..], input[..i]
105+
return input[i..], input[..i], i
106106
}
107107
}
108108
return error('`take_till1` failed on input `${input}`')
@@ -111,10 +111,10 @@ pub fn take_till1(condition fn (byte) bool) Fn {
111111

112112
// Returns the input slice up to the first occurrence of the `pattern`.
113113
pub fn take_until(pattern string) Fn {
114-
return fn [pattern] (input string) !(string, string) {
114+
return fn [pattern] (input string) !(string, string, int) {
115115
for i := 0; i + pattern.len <= input.len; i++ {
116116
if input[i..i + pattern.len] == pattern {
117-
return input[i..], input[..i]
117+
return input[i..], input[..i], i
118118
}
119119
}
120120
return error('`take_until` failed on input `${input}` with pattern `${pattern}`')
@@ -123,10 +123,10 @@ pub fn take_until(pattern string) Fn {
123123

124124
// Returns the non empty input slice up to the first occurrence of the `pattern`.
125125
pub fn take_until1(pattern string) Fn {
126-
return fn [pattern] (input string) !(string, string) {
126+
return fn [pattern] (input string) !(string, string, int) {
127127
for i := 1; i + pattern.len <= input.len; i++ {
128128
if input[i..i + pattern.len] == pattern {
129-
return input[i..], input[..i]
129+
return input[i..], input[..i], i
130130
}
131131
}
132132
return error('`take_until1` failed on input `${input}` with pattern `${pattern}`')
@@ -135,34 +135,34 @@ pub fn take_until1(pattern string) Fn {
135135

136136
// Returns the longest input slice (if any) that matches the predicate `condition`.
137137
pub fn take_while(condition fn (byte) bool) Fn {
138-
return fn [condition] (input string) !(string, string) {
138+
return fn [condition] (input string) !(string, string, int) {
139139
for i, c in input.bytes() {
140140
if !condition(c) {
141-
return input[i..], input[..i]
141+
return input[i..], input[..i], i
142142
}
143143
}
144-
return '', input
144+
return '', input, input.len
145145
}
146146
}
147147

148148
// Returns the longest (at least 1) input slice that matches the predicate `condition`.
149149
pub fn take_while1(condition fn (byte) bool) Fn {
150-
return fn [condition] (input string) !(string, string) {
150+
return fn [condition] (input string) !(string, string, int) {
151151
for i, c in input.bytes() {
152152
if !condition(c) {
153153
if i == 0 {
154154
return error('`take_while` failed on input `${input}` because it returned empty')
155155
}
156-
return input[i..], input[..i]
156+
return input[i..], input[..i], i
157157
}
158158
}
159-
return '', input
159+
return '', input, input.len
160160
}
161161
}
162162

163163
// Returns the longest (m <= len <= n) input slice that matches the predicate `condition`.
164164
pub fn take_while_m_n(m int, n int, condition fn (byte) bool) Fn {
165-
return fn [m, n, condition] (input string) !(string, string) {
165+
return fn [m, n, condition] (input string) !(string, string, int) {
166166
mut longest := -1
167167
for i, c in input.bytes() {
168168
len := i + 1
@@ -174,7 +174,7 @@ pub fn take_while_m_n(m int, n int, condition fn (byte) bool) Fn {
174174
}
175175
}
176176
if longest != -1 {
177-
return input[longest..], input[..longest]
177+
return input[longest..], input[..longest], longest
178178
} else {
179179
return error('`take_while_m_n` failed on input `${input}` with m `${m}` and n `${n}`')
180180
}

0 commit comments

Comments
 (0)