strscan 3.1.0 → 3.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 499afd5ba3e810119b88244dfd4f41078e201b5c1c994e827f42077cdfabb151
4
- data.tar.gz: bdc3ef1dd90c53ec6a6c6807fa1b2634587e0d7294d5a747b3837ffd7fb41a01
3
+ metadata.gz: 6f161a18c4a80f6abbc8ca40d2ec6ddb58fb41ffe6eccc3635ee496a812b5eff
4
+ data.tar.gz: 06f71160712c6ab55c234ca54c2117a15c5d05eff5ea8f958880781591dbae90
5
5
  SHA512:
6
- metadata.gz: 9d818fe222252c1e6c34b8252ab22eb206c96b320c920b647ae062a1561678bf1a235bddc9dbc3272357c5fa78e847f3790117c693a62b77a608edcf1c15eb2d
7
- data.tar.gz: b4ea287ab0209eb24229d3699548d831caa9fd9fabcf4715fa815ffad218524414a1291dcc9123a5d1c40b02d312026c049657202219f1a4cd2f5450c2fc8662
6
+ metadata.gz: '0697ad1f69c076574210187b1d58229b8f24a0c5f293083795e94732a72d872117faefb9f1df1fb6a1bade3c76a2b59a8f1013add891ededbe3dcc96590f72e1'
7
+ data.tar.gz: 60524c8b4198124b63653fa45768a6d4e56766e38937bf5c4c6a524f28b3e7d25c60b9abdabcb1d65e213ee35fae63e3e0c27911cedfecb294d159b385c0e855
data/.rdoc_options ADDED
@@ -0,0 +1,3 @@
1
+ ---
2
+ rdoc_include:
3
+ - doc
@@ -0,0 +1,124 @@
1
+ ## Helper Methods
2
+
3
+ These helper methods display values returned by scanner's methods.
4
+
5
+ ### `put_situation(scanner)`
6
+
7
+ Display scanner's situation:
8
+
9
+ - Byte position (`#pos`).
10
+ - Character position (`#charpos`)
11
+ - Target string (`#rest`) and size (`#rest_size`).
12
+
13
+ ```rb
14
+ scanner = StringScanner.new('foobarbaz')
15
+ scanner.scan(/foo/)
16
+ put_situation(scanner)
17
+ # Situation:
18
+ # pos: 3
19
+ # charpos: 3
20
+ # rest: "barbaz"
21
+ # rest_size: 6
22
+ ```
23
+
24
+ ### `put_match_values(scanner)`
25
+
26
+ Display the scanner's match values:
27
+
28
+ ```rb
29
+ scanner = StringScanner.new('Fri Dec 12 1975 14:39')
30
+ pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) /
31
+ scanner.match?(pattern)
32
+ put_match_values(scanner)
33
+ # Basic match values:
34
+ # matched?: true
35
+ # matched_size: 11
36
+ # pre_match: ""
37
+ # matched : "Fri Dec 12 "
38
+ # post_match: "1975 14:39"
39
+ # Captured match values:
40
+ # size: 4
41
+ # captures: ["Fri", "Dec", "12"]
42
+ # named_captures: {"wday"=>"Fri", "month"=>"Dec", "day"=>"12"}
43
+ # values_at: ["Fri Dec 12 ", "Fri", "Dec", "12", nil]
44
+ # []:
45
+ # [0]: "Fri Dec 12 "
46
+ # [1]: "Fri"
47
+ # [2]: "Dec"
48
+ # [3]: "12"
49
+ # [4]: nil
50
+ ```
51
+
52
+ ### `match_values_cleared?(scanner)`
53
+
54
+ Returns whether the scanner's match values are all properly cleared:
55
+
56
+ ```rb
57
+ scanner = StringScanner.new('foobarbaz')
58
+ match_values_cleared?(scanner) # => true
59
+ put_match_values(scanner)
60
+ # Basic match values:
61
+ # matched?: false
62
+ # matched_size: nil
63
+ # pre_match: nil
64
+ # matched : nil
65
+ # post_match: nil
66
+ # Captured match values:
67
+ # size: nil
68
+ # captures: nil
69
+ # named_captures: {}
70
+ # values_at: nil
71
+ # [0]: nil
72
+ scanner.scan(/foo/)
73
+ match_values_cleared?(scanner) # => false
74
+ ```
75
+
76
+ ## The Code
77
+
78
+ ```rb
79
+ def put_situation(scanner)
80
+ puts '# Situation:'
81
+ puts "# pos: #{scanner.pos}"
82
+ puts "# charpos: #{scanner.charpos}"
83
+ puts "# rest: #{scanner.rest.inspect}"
84
+ puts "# rest_size: #{scanner.rest_size}"
85
+ end
86
+
87
+ def put_match_values(scanner)
88
+ puts '# Basic match values:'
89
+ puts "# matched?: #{scanner.matched?}"
90
+ value = scanner.matched_size || 'nil'
91
+ puts "# matched_size: #{value}"
92
+ puts "# pre_match: #{scanner.pre_match.inspect}"
93
+ puts "# matched : #{scanner.matched.inspect}"
94
+ puts "# post_match: #{scanner.post_match.inspect}"
95
+ puts '# Captured match values:'
96
+ puts "# size: #{scanner.size}"
97
+ puts "# captures: #{scanner.captures}"
98
+ puts "# named_captures: #{scanner.named_captures}"
99
+ if scanner.size.nil?
100
+ puts "# values_at: #{scanner.values_at(0)}"
101
+ puts "# [0]: #{scanner[0]}"
102
+ else
103
+ puts "# values_at: #{scanner.values_at(*(0..scanner.size))}"
104
+ puts "# []:"
105
+ scanner.size.times do |i|
106
+ puts "# [#{i}]: #{scanner[i].inspect}"
107
+ end
108
+ end
109
+ end
110
+
111
+ def match_values_cleared?(scanner)
112
+ scanner.matched? == false &&
113
+ scanner.matched_size.nil? &&
114
+ scanner.matched.nil? &&
115
+ scanner.pre_match.nil? &&
116
+ scanner.post_match.nil? &&
117
+ scanner.size.nil? &&
118
+ scanner[0].nil? &&
119
+ scanner.captures.nil? &&
120
+ scanner.values_at(0..1).nil? &&
121
+ scanner.named_captures == {}
122
+ end
123
+ ```
124
+
@@ -0,0 +1,17 @@
1
+ [1]: rdoc-ref:StringScanner@Stored+String
2
+ [2]: rdoc-ref:StringScanner@Byte+Position+-28Position-29
3
+ [3]: rdoc-ref:StringScanner@Target+Substring
4
+ [4]: rdoc-ref:StringScanner@Setting+the+Target+Substring
5
+ [5]: rdoc-ref:StringScanner@Traversing+the+Target+Substring
6
+ [6]: https://docs.ruby-lang.org/en/master/Regexp.html
7
+ [7]: rdoc-ref:StringScanner@Character+Position
8
+ [8]: https://docs.ruby-lang.org/en/master/String.html#method-i-5B-5D
9
+ [9]: rdoc-ref:StringScanner@Match+Values
10
+ [10]: rdoc-ref:StringScanner@Fixed-Anchor+Property
11
+ [11]: rdoc-ref:StringScanner@Positions
12
+ [13]: rdoc-ref:StringScanner@Captured+Match+Values
13
+ [14]: rdoc-ref:StringScanner@Querying+the+Target+Substring
14
+ [15]: rdoc-ref:StringScanner@Searching+the+Target+Substring
15
+ [16]: https://docs.ruby-lang.org/en/master/Regexp.html#class-Regexp-label-Groups+and+Captures
16
+ [17]: rdoc-ref:StringScanner@Matching
17
+ [18]: rdoc-ref:StringScanner@Basic+Match+Values
@@ -0,0 +1,30 @@
1
+ call-seq:
2
+ get_byte -> byte_as_character or nil
3
+
4
+ Returns the next byte, if available:
5
+
6
+ - If the [position][2]
7
+ is not at the end of the [stored string][1]:
8
+
9
+ - Returns the next byte.
10
+ - Increments the [byte position][2].
11
+ - Adjusts the [character position][7].
12
+
13
+ ```rb
14
+ scanner = StringScanner.new(HIRAGANA_TEXT)
15
+ # => #<StringScanner 0/15 @ "\xE3\x81\x93\xE3\x82...">
16
+ scanner.string # => "こんにちは"
17
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\xE3", 1, 1]
18
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x81", 2, 2]
19
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x93", 3, 1]
20
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\xE3", 4, 2]
21
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x82", 5, 3]
22
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x93", 6, 2]
23
+ ```
24
+
25
+ - Otherwise, returns `nil`, and does not change the positions.
26
+
27
+ ```rb
28
+ scanner.terminate
29
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => [nil, 15, 5]
30
+ ```
@@ -0,0 +1,19 @@
1
+ call-seq:
2
+ charpos -> character_position
3
+
4
+ Returns the [character position][7] (initially zero),
5
+ which may be different from the [byte position][2]
6
+ given by method #pos:
7
+
8
+ ```rb
9
+ scanner = StringScanner.new(HIRAGANA_TEXT)
10
+ scanner.string # => "こんにちは"
11
+ scanner.getch # => "こ" # 3-byte character.
12
+ scanner.getch # => "ん" # 3-byte character.
13
+ put_situation(scanner)
14
+ # Situation:
15
+ # pos: 6
16
+ # charpos: 2
17
+ # rest: "にちは"
18
+ # rest_size: 9
19
+ ```
@@ -0,0 +1,14 @@
1
+ call-seq:
2
+ pos -> byte_position
3
+
4
+ Returns the integer [byte position][2],
5
+ which may be different from the [character position][7]:
6
+
7
+ ```rb
8
+ scanner = StringScanner.new(HIRAGANA_TEXT)
9
+ scanner.string # => "こんにちは"
10
+ scanner.pos # => 0
11
+ scanner.getch # => "こ" # 3-byte character.
12
+ scanner.charpos # => 1
13
+ scanner.pos # => 3
14
+ ```
@@ -0,0 +1,43 @@
1
+ call-seq:
2
+ getch -> character or nil
3
+
4
+ Returns the next (possibly multibyte) character,
5
+ if available:
6
+
7
+ - If the [position][2]
8
+ is at the beginning of a character:
9
+
10
+ - Returns the character.
11
+ - Increments the [character position][7] by 1.
12
+ - Increments the [byte position][2]
13
+ by the size (in bytes) of the character.
14
+
15
+ ```rb
16
+ scanner = StringScanner.new(HIRAGANA_TEXT)
17
+ scanner.string # => "こんにちは"
18
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["こ", 3, 1]
19
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["ん", 6, 2]
20
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["に", 9, 3]
21
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["ち", 12, 4]
22
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["は", 15, 5]
23
+ [scanner.getch, scanner.pos, scanner.charpos] # => [nil, 15, 5]
24
+ ```
25
+
26
+ - If the [position][2] is within a multi-byte character
27
+ (that is, not at its beginning),
28
+ behaves like #get_byte (returns a 1-byte character):
29
+
30
+ ```rb
31
+ scanner.pos = 1
32
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["\x81", 2, 2]
33
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["\x93", 3, 1]
34
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["ん", 6, 2]
35
+ ```
36
+
37
+ - If the [position][2] is at the end of the [stored string][1],
38
+ returns `nil` and does not modify the positions:
39
+
40
+ ```rb
41
+ scanner.terminate
42
+ [scanner.getch, scanner.pos, scanner.charpos] # => [nil, 15, 5]
43
+ ```
@@ -0,0 +1,51 @@
1
+ call-seq:
2
+ scan(pattern) -> substring or nil
3
+
4
+ Attempts to [match][17] the given `pattern`
5
+ at the beginning of the [target substring][3].
6
+
7
+ If the match succeeds:
8
+
9
+ - Returns the matched substring.
10
+ - Increments the [byte position][2] by <tt>substring.bytesize</tt>,
11
+ and may increment the [character position][7].
12
+ - Sets [match values][9].
13
+
14
+ ```rb
15
+ scanner = StringScanner.new(HIRAGANA_TEXT)
16
+ scanner.string # => "こんにちは"
17
+ scanner.pos = 6
18
+ scanner.scan(/に/) # => "に"
19
+ put_match_values(scanner)
20
+ # Basic match values:
21
+ # matched?: true
22
+ # matched_size: 3
23
+ # pre_match: "こん"
24
+ # matched : "に"
25
+ # post_match: "ちは"
26
+ # Captured match values:
27
+ # size: 1
28
+ # captures: []
29
+ # named_captures: {}
30
+ # values_at: ["に", nil]
31
+ # []:
32
+ # [0]: "に"
33
+ # [1]: nil
34
+ put_situation(scanner)
35
+ # Situation:
36
+ # pos: 9
37
+ # charpos: 3
38
+ # rest: "ちは"
39
+ # rest_size: 6
40
+ ```
41
+
42
+ If the match fails:
43
+
44
+ - Returns `nil`.
45
+ - Does not increment byte and character positions.
46
+ - Clears match values.
47
+
48
+ ```rb
49
+ scanner.scan(/nope/) # => nil
50
+ match_values_cleared?(scanner) # => true
51
+ ```
@@ -0,0 +1,52 @@
1
+ call-seq:
2
+ scan_until(pattern) -> substring or nil
3
+
4
+ Attempts to [match][17] the given `pattern`
5
+ anywhere (at any [position][2]) in the [target substring][3].
6
+
7
+ If the match attempt succeeds:
8
+
9
+ - Sets [match values][9].
10
+ - Sets the [byte position][2] to the end of the matched substring;
11
+ may adjust the [character position][7].
12
+ - Returns the matched substring.
13
+
14
+
15
+ ```rb
16
+ scanner = StringScanner.new(HIRAGANA_TEXT)
17
+ scanner.string # => "こんにちは"
18
+ scanner.pos = 6
19
+ scanner.scan_until(/ち/) # => "にち"
20
+ put_match_values(scanner)
21
+ # Basic match values:
22
+ # matched?: true
23
+ # matched_size: 3
24
+ # pre_match: "こんに"
25
+ # matched : "ち"
26
+ # post_match: "は"
27
+ # Captured match values:
28
+ # size: 1
29
+ # captures: []
30
+ # named_captures: {}
31
+ # values_at: ["ち", nil]
32
+ # []:
33
+ # [0]: "ち"
34
+ # [1]: nil
35
+ put_situation(scanner)
36
+ # Situation:
37
+ # pos: 12
38
+ # charpos: 4
39
+ # rest: "は"
40
+ # rest_size: 3
41
+ ```
42
+
43
+ If the match attempt fails:
44
+
45
+ - Clears match data.
46
+ - Returns `nil`.
47
+ - Does not update positions.
48
+
49
+ ```rb
50
+ scanner.scan_until(/nope/) # => nil
51
+ match_values_cleared?(scanner) # => true
52
+ ```
@@ -0,0 +1,27 @@
1
+ call-seq:
2
+ pos = n -> n
3
+ pointer = n -> n
4
+
5
+ Sets the [byte position][2] and the [character position][11];
6
+ returns `n`.
7
+
8
+ Does not affect [match values][9].
9
+
10
+ For non-negative `n`, sets the position to `n`:
11
+
12
+ ```rb
13
+ scanner = StringScanner.new(HIRAGANA_TEXT)
14
+ scanner.string # => "こんにちは"
15
+ scanner.pos = 3 # => 3
16
+ scanner.rest # => "んにちは"
17
+ scanner.charpos # => 1
18
+ ```
19
+
20
+ For negative `n`, counts from the end of the [stored string][1]:
21
+
22
+ ```rb
23
+ scanner.pos = -9 # => -9
24
+ scanner.pos # => 6
25
+ scanner.rest # => "にちは"
26
+ scanner.charpos # => 2
27
+ ```
@@ -0,0 +1,43 @@
1
+ call-seq:
2
+ skip(pattern) match_size or nil
3
+
4
+ Attempts to [match][17] the given `pattern`
5
+ at the beginning of the [target substring][3];
6
+
7
+ If the match succeeds:
8
+
9
+ - Increments the [byte position][2] by substring.bytesize,
10
+ and may increment the [character position][7].
11
+ - Sets [match values][9].
12
+ - Returns the size (bytes) of the matched substring.
13
+
14
+ ```rb
15
+ scanner = StringScanner.new(HIRAGANA_TEXT)
16
+ scanner.string # => "こんにちは"
17
+ scanner.pos = 6
18
+ scanner.skip(/に/) # => 3
19
+ put_match_values(scanner)
20
+ # Basic match values:
21
+ # matched?: true
22
+ # matched_size: 3
23
+ # pre_match: "こん"
24
+ # matched : "に"
25
+ # post_match: "ちは"
26
+ # Captured match values:
27
+ # size: 1
28
+ # captures: []
29
+ # named_captures: {}
30
+ # values_at: ["に", nil]
31
+ # []:
32
+ # [0]: "に"
33
+ # [1]: nil
34
+ put_situation(scanner)
35
+ # Situation:
36
+ # pos: 9
37
+ # charpos: 3
38
+ # rest: "ちは"
39
+ # rest_size: 6
40
+
41
+ scanner.skip(/nope/) # => nil
42
+ match_values_cleared?(scanner) # => true
43
+ ```
@@ -0,0 +1,49 @@
1
+ call-seq:
2
+ skip_until(pattern) -> matched_substring_size or nil
3
+
4
+ Attempts to [match][17] the given `pattern`
5
+ anywhere (at any [position][2]) in the [target substring][3];
6
+ does not modify the positions.
7
+
8
+ If the match attempt succeeds:
9
+
10
+ - Sets [match values][9].
11
+ - Returns the size of the matched substring.
12
+
13
+ ```rb
14
+ scanner = StringScanner.new(HIRAGANA_TEXT)
15
+ scanner.string # => "こんにちは"
16
+ scanner.pos = 6
17
+ scanner.skip_until(/ち/) # => 6
18
+ put_match_values(scanner)
19
+ # Basic match values:
20
+ # matched?: true
21
+ # matched_size: 3
22
+ # pre_match: "こんに"
23
+ # matched : "ち"
24
+ # post_match: "は"
25
+ # Captured match values:
26
+ # size: 1
27
+ # captures: []
28
+ # named_captures: {}
29
+ # values_at: ["ち", nil]
30
+ # []:
31
+ # [0]: "ち"
32
+ # [1]: nil
33
+ put_situation(scanner)
34
+ # Situation:
35
+ # pos: 12
36
+ # charpos: 4
37
+ # rest: "は"
38
+ # rest_size: 3
39
+ ```
40
+
41
+ If the match attempt fails:
42
+
43
+ - Clears match values.
44
+ - Returns `nil`.
45
+
46
+ ```rb
47
+ scanner.skip_until(/nope/) # => nil
48
+ match_values_cleared?(scanner) # => true
49
+ ```
@@ -0,0 +1,30 @@
1
+ call-seq:
2
+ terminate -> self
3
+
4
+ Sets the scanner to end-of-string;
5
+ returns +self+:
6
+
7
+ - Sets both [positions][11] to end-of-stream.
8
+ - Clears [match values][9].
9
+
10
+ ```rb
11
+ scanner = StringScanner.new(HIRAGANA_TEXT)
12
+ scanner.string # => "こんにちは"
13
+ scanner.scan_until(/に/)
14
+ put_situation(scanner)
15
+ # Situation:
16
+ # pos: 9
17
+ # charpos: 3
18
+ # rest: "ちは"
19
+ # rest_size: 6
20
+ match_values_cleared?(scanner) # => false
21
+
22
+ scanner.terminate # => #<StringScanner fin>
23
+ put_situation(scanner)
24
+ # Situation:
25
+ # pos: 15
26
+ # charpos: 5
27
+ # rest: ""
28
+ # rest_size: 0
29
+ match_values_cleared?(scanner) # => true
30
+ ```