strscan 3.1.0 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 499afd5ba3e810119b88244dfd4f41078e201b5c1c994e827f42077cdfabb151
4
- data.tar.gz: bdc3ef1dd90c53ec6a6c6807fa1b2634587e0d7294d5a747b3837ffd7fb41a01
3
+ metadata.gz: 45d46129cae1a1b9273f5500d6d15279e592946173312c034fb54387faef9d0d
4
+ data.tar.gz: fc2d15f94f2e597d57dc89c44dddce16aa0096f02a6d268c22e1595ab9c5a00f
5
5
  SHA512:
6
- metadata.gz: 9d818fe222252c1e6c34b8252ab22eb206c96b320c920b647ae062a1561678bf1a235bddc9dbc3272357c5fa78e847f3790117c693a62b77a608edcf1c15eb2d
7
- data.tar.gz: b4ea287ab0209eb24229d3699548d831caa9fd9fabcf4715fa815ffad218524414a1291dcc9123a5d1c40b02d312026c049657202219f1a4cd2f5450c2fc8662
6
+ metadata.gz: 295727ce636512083608565f16c7675509143708abce6896da39fb0b3bad4d8e69538b6574a0ed6c6d7e0f85c14569c79cdc5901b55c7c5320c3d5a7af0cc61d
7
+ data.tar.gz: 4bba01c59eb8e3062fb498d6e8468ed6def6fa36d7c5ef9a0bb24806f7d500def565e9598eb5b7958589b3145653b57991a270963d066486b4e1ba915cb3030f
data/.rdoc_options ADDED
@@ -0,0 +1,3 @@
1
+ ---
2
+ rdoc_include:
3
+ - doc
@@ -0,0 +1,128 @@
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
+ ```
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
+ ```
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
+ ```
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
+ ```
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
+
88
+ ```
89
+ def put_match_values(scanner)
90
+ puts '# Basic match values:'
91
+ puts "# matched?: #{scanner.matched?}"
92
+ value = scanner.matched_size || 'nil'
93
+ puts "# matched_size: #{value}"
94
+ puts "# pre_match: #{scanner.pre_match.inspect}"
95
+ puts "# matched : #{scanner.matched.inspect}"
96
+ puts "# post_match: #{scanner.post_match.inspect}"
97
+ puts '# Captured match values:'
98
+ puts "# size: #{scanner.size}"
99
+ puts "# captures: #{scanner.captures}"
100
+ puts "# named_captures: #{scanner.named_captures}"
101
+ if scanner.size.nil?
102
+ puts "# values_at: #{scanner.values_at(0)}"
103
+ puts "# [0]: #{scanner[0]}"
104
+ else
105
+ puts "# values_at: #{scanner.values_at(*(0..scanner.size))}"
106
+ puts "# []:"
107
+ scanner.size.times do |i|
108
+ puts "# [#{i}]: #{scanner[i].inspect}"
109
+ end
110
+ end
111
+ end
112
+ ```
113
+
114
+ ```
115
+ def match_values_cleared?(scanner)
116
+ scanner.matched? == false &&
117
+ scanner.matched_size.nil? &&
118
+ scanner.matched.nil? &&
119
+ scanner.pre_match.nil? &&
120
+ scanner.post_match.nil? &&
121
+ scanner.size.nil? &&
122
+ scanner[0].nil? &&
123
+ scanner.captures.nil? &&
124
+ scanner.values_at(0..1).nil? &&
125
+ scanner.named_captures == {}
126
+ end
127
+ ```
128
+
@@ -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
+ ```
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
+ ```
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
+ ```
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
+ ```
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
+ ```
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
+ ```
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
+ ```
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
+ ```
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
+ ```
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
+ ```
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
+ ```
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
+ ```
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
+ ```
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
+ ```
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
+ ```
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
+ ```
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
+ ```
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
+ ```