rbs 3.6.1 → 3.9.5

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.
Files changed (268) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/comments.yml +2 -2
  3. data/.github/workflows/dependabot.yml +1 -1
  4. data/.github/workflows/ruby.yml +34 -10
  5. data/.github/workflows/windows.yml +20 -3
  6. data/.gitignore +1 -0
  7. data/.rubocop.yml +26 -1
  8. data/CHANGELOG.md +241 -0
  9. data/Rakefile +54 -4
  10. data/config.yml +317 -0
  11. data/core/array.rbs +1756 -1591
  12. data/core/basic_object.rbs +38 -35
  13. data/core/comparable.rbs +1 -1
  14. data/core/complex.rbs +166 -94
  15. data/core/data.rbs +2 -2
  16. data/core/dir.rbs +2 -18
  17. data/core/encoding.rbs +12 -32
  18. data/core/enumerable.rbs +270 -266
  19. data/core/enumerator.rbs +14 -4
  20. data/core/env.rbs +1 -1
  21. data/core/errno.rbs +33 -16
  22. data/core/errors.rbs +6 -2
  23. data/core/exception.rbs +342 -167
  24. data/core/fiber.rbs +3 -2
  25. data/core/file.rbs +26 -75
  26. data/core/float.rbs +125 -72
  27. data/core/gc.rbs +158 -42
  28. data/core/hash.rbs +122 -143
  29. data/core/integer.rbs +79 -50
  30. data/core/io/buffer.rbs +49 -43
  31. data/core/io.rbs +108 -151
  32. data/core/kernel.rbs +341 -209
  33. data/core/match_data.rbs +76 -2
  34. data/core/math.rbs +0 -36
  35. data/core/method.rbs +2 -2
  36. data/core/module.rbs +32 -27
  37. data/core/nil_class.rbs +2 -2
  38. data/core/numeric.rbs +101 -104
  39. data/core/object.rbs +1 -5
  40. data/core/object_space/weak_key_map.rbs +3 -4
  41. data/core/object_space.rbs +3 -3
  42. data/core/proc.rbs +82 -14
  43. data/core/process.rbs +110 -58
  44. data/core/ractor.rbs +57 -4
  45. data/core/range.rbs +114 -87
  46. data/core/rational.rbs +0 -2
  47. data/core/rbs/unnamed/argf.rbs +237 -36
  48. data/core/rbs/unnamed/env_class.rbs +35 -53
  49. data/core/rbs/unnamed/random.rbs +1 -2
  50. data/core/regexp.rbs +10 -56
  51. data/core/ruby_vm.rbs +88 -9
  52. data/core/rubygems/config_file.rbs +3 -0
  53. data/core/rubygems/errors.rbs +3 -6
  54. data/core/rubygems/platform.rbs +0 -9
  55. data/core/rubygems/rubygems.rbs +3 -6
  56. data/core/rubygems/version.rbs +8 -8
  57. data/core/set.rbs +4 -16
  58. data/core/string.rbs +271 -264
  59. data/core/struct.rbs +6 -18
  60. data/core/symbol.rbs +14 -21
  61. data/core/thread.rbs +32 -35
  62. data/core/time.rbs +131 -50
  63. data/core/trace_point.rbs +124 -113
  64. data/core/true_class.rbs +0 -1
  65. data/core/unbound_method.rbs +1 -1
  66. data/core/warning.rbs +9 -2
  67. data/docs/architecture.md +1 -1
  68. data/docs/syntax.md +17 -10
  69. data/ext/rbs_extension/extconf.rb +11 -0
  70. data/ext/rbs_extension/location.c +61 -29
  71. data/ext/rbs_extension/location.h +4 -3
  72. data/ext/rbs_extension/main.c +23 -1
  73. data/ext/rbs_extension/parser.c +506 -517
  74. data/ext/rbs_extension/parserstate.c +109 -30
  75. data/ext/rbs_extension/parserstate.h +6 -4
  76. data/ext/rbs_extension/rbs_extension.h +1 -10
  77. data/{ext/rbs_extension → include/rbs}/constants.h +21 -19
  78. data/include/rbs/ruby_objs.h +72 -0
  79. data/include/rbs/util/rbs_constant_pool.h +219 -0
  80. data/include/rbs.h +7 -0
  81. data/lib/rbs/annotate/annotations.rb +3 -3
  82. data/lib/rbs/annotate/rdoc_source.rb +2 -2
  83. data/lib/rbs/ast/declarations.rb +9 -4
  84. data/lib/rbs/ast/directives.rb +10 -0
  85. data/lib/rbs/ast/members.rb +2 -0
  86. data/lib/rbs/ast/type_param.rb +2 -12
  87. data/lib/rbs/cli/diff.rb +3 -3
  88. data/lib/rbs/cli/validate.rb +2 -1
  89. data/lib/rbs/cli.rb +16 -16
  90. data/lib/rbs/collection/config/lockfile_generator.rb +58 -8
  91. data/lib/rbs/collection/config.rb +5 -3
  92. data/lib/rbs/collection/sources/rubygems.rb +1 -1
  93. data/lib/rbs/collection.rb +1 -0
  94. data/lib/rbs/definition.rb +51 -34
  95. data/lib/rbs/definition_builder/ancestor_builder.rb +5 -3
  96. data/lib/rbs/definition_builder.rb +83 -24
  97. data/lib/rbs/environment.rb +33 -18
  98. data/lib/rbs/environment_loader.rb +6 -1
  99. data/lib/rbs/errors.rb +24 -0
  100. data/lib/rbs/locator.rb +2 -0
  101. data/lib/rbs/method_type.rb +2 -0
  102. data/lib/rbs/namespace.rb +1 -0
  103. data/lib/rbs/parser_aux.rb +40 -3
  104. data/lib/rbs/prototype/rb.rb +20 -12
  105. data/lib/rbs/prototype/rbi.rb +11 -6
  106. data/lib/rbs/prototype/runtime/value_object_generator.rb +7 -5
  107. data/lib/rbs/prototype/runtime.rb +7 -5
  108. data/lib/rbs/subtractor.rb +3 -3
  109. data/lib/rbs/test/hook.rb +47 -42
  110. data/lib/rbs/test/type_check.rb +7 -5
  111. data/lib/rbs/type_name.rb +14 -9
  112. data/lib/rbs/types.rb +63 -14
  113. data/lib/rbs/unit_test/spy.rb +4 -2
  114. data/lib/rbs/unit_test/type_assertions.rb +19 -13
  115. data/lib/rbs/unit_test/with_aliases.rb +3 -1
  116. data/lib/rbs/validator.rb +7 -1
  117. data/lib/rbs/version.rb +1 -1
  118. data/lib/rbs/writer.rb +10 -5
  119. data/lib/rbs.rb +1 -0
  120. data/lib/rdoc_plugin/parser.rb +2 -2
  121. data/rbs.gemspec +6 -2
  122. data/sig/ancestor_graph.rbs +5 -5
  123. data/sig/annotate/rdoc_source.rbs +2 -0
  124. data/sig/cli.rbs +2 -0
  125. data/sig/collection/config/lockfile_generator.rbs +9 -1
  126. data/sig/declarations.rbs +10 -3
  127. data/sig/definition.rbs +80 -12
  128. data/sig/definition_builder.rbs +18 -4
  129. data/sig/directives.rbs +17 -1
  130. data/sig/environment.rbs +3 -1
  131. data/sig/errors.rbs +19 -0
  132. data/sig/namespace.rbs +2 -3
  133. data/sig/parser.rbs +5 -1
  134. data/sig/prototype/rb.rbs +1 -1
  135. data/sig/resolver/constant_resolver.rbs +2 -2
  136. data/sig/resolver/context.rbs +1 -1
  137. data/sig/subtractor.rbs +1 -1
  138. data/sig/test/type_check.rbs +2 -2
  139. data/sig/type_alias_dependency.rbs +2 -2
  140. data/sig/type_alias_regularity.rbs +6 -6
  141. data/sig/type_param.rbs +4 -4
  142. data/sig/typename.rbs +8 -5
  143. data/sig/types.rbs +1 -1
  144. data/sig/unit_test/spy.rbs +2 -0
  145. data/sig/unit_test/type_assertions.rbs +2 -0
  146. data/sig/use_map.rbs +1 -1
  147. data/sig/validator.rbs +6 -2
  148. data/sig/vendorer.rbs +1 -1
  149. data/sig/writer.rbs +1 -1
  150. data/{ext/rbs_extension → src}/constants.c +35 -36
  151. data/src/ruby_objs.c +799 -0
  152. data/src/util/rbs_constant_pool.c +342 -0
  153. data/stdlib/base64/0/base64.rbs +0 -9
  154. data/stdlib/benchmark/0/benchmark.rbs +11 -2
  155. data/stdlib/bigdecimal/0/big_decimal.rbs +26 -182
  156. data/stdlib/cgi/0/core.rbs +60 -3
  157. data/stdlib/cgi/0/manifest.yaml +1 -0
  158. data/stdlib/coverage/0/coverage.rbs +0 -3
  159. data/stdlib/csv/0/csv.rbs +18 -58
  160. data/stdlib/csv/0/manifest.yaml +1 -0
  161. data/stdlib/date/0/date.rbs +27 -42
  162. data/stdlib/did_you_mean/0/did_you_mean.rbs +1 -6
  163. data/stdlib/digest/0/digest.rbs +25 -2
  164. data/stdlib/erb/0/erb.rbs +0 -1
  165. data/stdlib/etc/0/etc.rbs +51 -34
  166. data/stdlib/fileutils/0/fileutils.rbs +3 -44
  167. data/stdlib/io-console/0/io-console.rbs +69 -15
  168. data/stdlib/ipaddr/0/ipaddr.rbs +16 -4
  169. data/stdlib/json/0/json.rbs +107 -120
  170. data/stdlib/logger/0/log_device.rbs +1 -1
  171. data/stdlib/logger/0/logger.rbs +3 -18
  172. data/stdlib/minitest/0/kernel.rbs +2 -2
  173. data/stdlib/minitest/0/minitest/abstract_reporter.rbs +4 -1
  174. data/stdlib/minitest/0/minitest/assertion.rbs +1 -0
  175. data/stdlib/minitest/0/minitest/assertions.rbs +58 -13
  176. data/stdlib/minitest/0/minitest/backtrace_filter.rbs +7 -0
  177. data/stdlib/minitest/0/minitest/bench_spec.rbs +8 -8
  178. data/stdlib/minitest/0/minitest/benchmark.rbs +17 -16
  179. data/stdlib/minitest/0/minitest/compress.rbs +13 -0
  180. data/stdlib/minitest/0/minitest/error_on_warning.rbs +3 -0
  181. data/stdlib/minitest/0/minitest/mock.rbs +9 -5
  182. data/stdlib/minitest/0/minitest/parallel/executor.rbs +4 -0
  183. data/stdlib/minitest/0/minitest/parallel/test/class_methods.rbs +0 -1
  184. data/stdlib/minitest/0/minitest/pride_io.rbs +8 -0
  185. data/stdlib/minitest/0/minitest/pride_lol.rbs +2 -0
  186. data/stdlib/minitest/0/minitest/progress_reporter.rbs +1 -1
  187. data/stdlib/minitest/0/minitest/reportable.rbs +2 -0
  188. data/stdlib/minitest/0/minitest/runnable.rbs +33 -1
  189. data/stdlib/minitest/0/minitest/spec/dsl/instance_methods.rbs +1 -1
  190. data/stdlib/minitest/0/minitest/spec/dsl.rbs +10 -6
  191. data/stdlib/minitest/0/minitest/spec.rbs +1 -1
  192. data/stdlib/minitest/0/minitest/statistics_reporter.rbs +5 -0
  193. data/stdlib/minitest/0/minitest/summary_reporter.rbs +0 -7
  194. data/stdlib/minitest/0/minitest/test/lifecycle_hooks.rbs +1 -1
  195. data/stdlib/minitest/0/minitest/test.rbs +7 -14
  196. data/stdlib/minitest/0/minitest/unexpected_error.rbs +2 -0
  197. data/stdlib/minitest/0/minitest/unexpected_warning.rbs +6 -0
  198. data/stdlib/minitest/0/minitest/unit.rbs +1 -2
  199. data/stdlib/minitest/0/minitest.rbs +41 -892
  200. data/stdlib/monitor/0/monitor.rbs +13 -4
  201. data/stdlib/net-http/0/net-http.rbs +42 -109
  202. data/stdlib/nkf/0/nkf.rbs +30 -0
  203. data/stdlib/objspace/0/objspace.rbs +1 -2
  204. data/stdlib/observable/0/observable.rbs +1 -1
  205. data/stdlib/open-uri/0/manifest.yaml +1 -0
  206. data/stdlib/open-uri/0/open-uri.rbs +52 -0
  207. data/stdlib/open3/0/open3.rbs +0 -8
  208. data/stdlib/openssl/0/manifest.yaml +1 -0
  209. data/stdlib/openssl/0/openssl.rbs +235 -143
  210. data/stdlib/optparse/0/optparse.rbs +58 -18
  211. data/stdlib/pathname/0/pathname.rbs +2 -8
  212. data/stdlib/pp/0/pp.rbs +3 -1
  213. data/stdlib/prettyprint/0/prettyprint.rbs +0 -4
  214. data/stdlib/pstore/0/pstore.rbs +0 -6
  215. data/stdlib/psych/0/core_ext.rbs +12 -0
  216. data/stdlib/psych/0/psych.rbs +15 -4
  217. data/stdlib/pty/0/pty.rbs +46 -4
  218. data/stdlib/rdoc/0/code_object.rbs +0 -4
  219. data/stdlib/rdoc/0/markup.rbs +10 -12
  220. data/stdlib/rdoc/0/rdoc.rbs +13 -8
  221. data/stdlib/resolv/0/resolv.rbs +21 -12
  222. data/stdlib/ripper/0/ripper.rbs +0 -2
  223. data/stdlib/securerandom/0/securerandom.rbs +7 -2
  224. data/stdlib/shellwords/0/shellwords.rbs +11 -12
  225. data/stdlib/singleton/0/singleton.rbs +0 -1
  226. data/stdlib/socket/0/addrinfo.rbs +1 -2
  227. data/stdlib/socket/0/basic_socket.rbs +0 -5
  228. data/stdlib/socket/0/socket.rbs +32 -27
  229. data/stdlib/socket/0/tcp_server.rbs +0 -3
  230. data/stdlib/socket/0/tcp_socket.rbs +36 -3
  231. data/stdlib/socket/0/udp_socket.rbs +0 -1
  232. data/stdlib/socket/0/unix_server.rbs +0 -3
  233. data/stdlib/socket/0/unix_socket.rbs +4 -2
  234. data/{core/string_io.rbs → stdlib/stringio/0/stringio.rbs} +1 -1
  235. data/stdlib/strscan/0/string_scanner.rbs +1265 -422
  236. data/stdlib/tempfile/0/tempfile.rbs +135 -28
  237. data/stdlib/time/0/time.rbs +48 -35
  238. data/stdlib/timeout/0/timeout.rbs +11 -8
  239. data/stdlib/tmpdir/0/tmpdir.rbs +10 -3
  240. data/stdlib/tsort/0/tsort.rbs +0 -4
  241. data/stdlib/uri/0/common.rbs +28 -30
  242. data/stdlib/uri/0/ftp.rbs +1 -1
  243. data/stdlib/uri/0/generic.rbs +22 -18
  244. data/stdlib/uri/0/http.rbs +2 -2
  245. data/stdlib/uri/0/rfc2396_parser.rbs +3 -0
  246. data/stdlib/zlib/0/buf_error.rbs +1 -70
  247. data/stdlib/zlib/0/data_error.rbs +1 -70
  248. data/stdlib/zlib/0/deflate.rbs +8 -72
  249. data/stdlib/zlib/0/error.rbs +1 -70
  250. data/stdlib/zlib/0/gzip_file/crc_error.rbs +2 -105
  251. data/stdlib/zlib/0/gzip_file/error.rbs +2 -105
  252. data/stdlib/zlib/0/gzip_file/length_error.rbs +2 -105
  253. data/stdlib/zlib/0/gzip_file/no_footer.rbs +2 -105
  254. data/stdlib/zlib/0/gzip_file.rbs +1 -71
  255. data/stdlib/zlib/0/gzip_reader.rbs +3 -74
  256. data/stdlib/zlib/0/gzip_writer.rbs +1 -70
  257. data/stdlib/zlib/0/inflate.rbs +4 -71
  258. data/stdlib/zlib/0/mem_error.rbs +1 -70
  259. data/stdlib/zlib/0/need_dict.rbs +1 -70
  260. data/stdlib/zlib/0/stream_end.rbs +1 -70
  261. data/stdlib/zlib/0/stream_error.rbs +1 -70
  262. data/stdlib/zlib/0/version_error.rbs +1 -70
  263. data/stdlib/zlib/0/zlib.rbs +0 -2
  264. data/stdlib/zlib/0/zstream.rbs +4 -72
  265. metadata +17 -13
  266. data/ext/rbs_extension/ruby_objs.c +0 -602
  267. data/ext/rbs_extension/ruby_objs.h +0 -51
  268. data/stdlib/minitest/0/manifest.yaml +0 -2
@@ -1,108 +1,426 @@
1
1
  # <!-- rdoc-file=ext/strscan/strscan.c -->
2
- # StringScanner provides for lexical scanning operations on a String. Here is
3
- # an example of its usage:
4
- #
2
+ # Class `StringScanner` supports processing a stored string as a stream;
3
+ # this code creates a new `StringScanner` object with string `'foobarbaz'`:
5
4
  # require 'strscan'
5
+ # scanner = StringScanner.new('foobarbaz')
6
6
  #
7
- # s = StringScanner.new('This is an example string')
8
- # s.eos? # -> false
9
- #
10
- # p s.scan(/\w+/) # -> "This"
11
- # p s.scan(/\w+/) # -> nil
12
- # p s.scan(/\s+/) # -> " "
13
- # p s.scan(/\s+/) # -> nil
14
- # p s.scan(/\w+/) # -> "is"
15
- # s.eos? # -> false
16
- #
17
- # p s.scan(/\s+/) # -> " "
18
- # p s.scan(/\w+/) # -> "an"
19
- # p s.scan(/\s+/) # -> " "
20
- # p s.scan(/\w+/) # -> "example"
21
- # p s.scan(/\s+/) # -> " "
22
- # p s.scan(/\w+/) # -> "string"
23
- # s.eos? # -> true
24
- #
25
- # p s.scan(/\s+/) # -> nil
26
- # p s.scan(/\w+/) # -> nil
27
- #
28
- # Scanning a string means remembering the position of a *scan pointer*, which is
29
- # just an index. The point of scanning is to move forward a bit at a time, so
30
- # matches are sought after the scan pointer; usually immediately after it.
31
- #
32
- # Given the string "test string", here are the pertinent scan pointer positions:
33
- #
34
- # t e s t s t r i n g
35
- # 0 1 2 ... 1
36
- # 0
37
- #
38
- # When you #scan for a pattern (a regular expression), the match must occur at
39
- # the character after the scan pointer. If you use #scan_until, then the match
40
- # can occur anywhere after the scan pointer. In both cases, the scan pointer
41
- # moves *just beyond* the last character of the match, ready to scan again from
42
- # the next character onwards. This is demonstrated by the example above.
43
- #
44
- # ## Method Categories
45
- #
46
- # There are other methods besides the plain scanners. You can look ahead in the
47
- # string without actually scanning. You can access the most recent match. You
48
- # can modify the string being scanned, reset or terminate the scanner, find out
49
- # or change the position of the scan pointer, skip ahead, and so on.
7
+ # ## About the Examples
8
+ # All examples here assume that `StringScanner` has been required:
9
+ # require 'strscan'
50
10
  #
51
- # ### Advancing the Scan Pointer
11
+ # Some examples here assume that these constants are defined:
12
+ # MULTILINE_TEXT = <<~EOT
13
+ # Go placidly amid the noise and haste,
14
+ # and remember what peace there may be in silence.
15
+ # EOT
52
16
  #
53
- # * #getch
54
- # * #get_byte
55
- # * #scan
56
- # * #scan_until
57
- # * #skip
58
- # * #skip_until
17
+ # HIRAGANA_TEXT = 'こんにちは'
59
18
  #
19
+ # ENGLISH_TEXT = 'Hello'
60
20
  #
61
- # ### Looking Ahead
21
+ # Some examples here assume that certain helper methods are defined:
22
+ # * `put_situation(scanner)`:
23
+ # Displays the values of the scanner's
24
+ # methods #pos, #charpos, #rest, and #rest_size.
25
+ # * `put_match_values(scanner)`:
26
+ # Displays the scanner's [match
27
+ # values](rdoc-ref:StringScanner@Match+Values).
28
+ # * `match_values_cleared?(scanner)`:
29
+ # Returns whether the scanner's [match
30
+ # values](rdoc-ref:StringScanner@Match+Values) are cleared.
31
+ # See examples [[here]](ext/strscan/helper_methods_md.html).
32
+ # ## The `StringScanner` Object
33
+ # This code creates a `StringScanner` object
34
+ # (we'll call it simply a *scanner*),
35
+ # and shows some of its basic properties:
36
+ # scanner = StringScanner.new('foobarbaz')
37
+ # scanner.string # => "foobarbaz"
38
+ # put_situation(scanner)
39
+ # # Situation:
40
+ # # pos: 0
41
+ # # charpos: 0
42
+ # # rest: "foobarbaz"
43
+ # # rest_size: 9
62
44
  #
63
- # * #check
64
- # * #check_until
65
- # * #exist?
66
- # * #match?
67
- # * #peek
45
+ # The scanner has:
46
+ # * A *stored string*, which is:
47
+ # * Initially set by StringScanner.new(string) to the given `string`
48
+ # (`'foobarbaz'` in the example above).
49
+ # * Modifiable by methods #string=(new_string) and #concat(more_string).
50
+ # * Returned by method #string.
51
+ # More at [Stored String](rdoc-ref:StringScanner@Stored+String) below.
52
+ # * A *position*;
53
+ # a zero-based index into the bytes of the stored string (*not* into its
54
+ # characters):
55
+ # * Initially set by StringScanner.new to `0`.
56
+ # * Returned by method #pos.
57
+ # * Modifiable explicitly by methods #reset, #terminate, and
58
+ # #pos=(new_pos).
59
+ # * Modifiable implicitly (various traversing methods, among others).
60
+ # More at [Byte
61
+ # Position](rdoc-ref:StringScanner@Byte+Position+-28Position-29) below.
62
+ # * A *target substring*,
63
+ # which is a trailing substring of the stored string;
64
+ # it extends from the current position to the end of the stored string:
65
+ # * Initially set by StringScanner.new(string) to the given `string`
66
+ # (`'foobarbaz'` in the example above).
67
+ # * Returned by method #rest.
68
+ # * Modified by any modification to either the stored string or the
69
+ # position.
70
+ # **Most importantly**:
71
+ # the searching and traversing methods operate on the target substring,
72
+ # which may be (and often is) less than the entire stored string.
73
+ # More at [Target Substring](rdoc-ref:StringScanner@Target+Substring) below.
74
+ # ## Stored String
75
+ # The *stored string* is the string stored in the `StringScanner` object.
76
+ # Each of these methods sets, modifies, or returns the stored string:
77
+ # Method | Effect
78
+ # --------------------|-----------------------------------------------
79
+ # ::new(string) | Creates a new scanner for the given string.
80
+ # #string=(new_string)| Replaces the existing stored string.
81
+ # #concat(more_string)|Appends a string to the existing stored string.
82
+ # #string | Returns the stored string.
83
+ # ## Positions
84
+ # A `StringScanner` object maintains a zero-based *byte position*
85
+ # and a zero-based *character position*.
86
+ # Each of these methods explicitly sets positions:
87
+ # Method | Effect
88
+ # ------------------------|--------------------------------------------------------
89
+ # #reset |Sets both positions to zero (begining of stored string).
90
+ # #terminate | Sets both positions to the end of the stored string.
91
+ # #pos=(new_byte_position)| Sets byte position; adjusts character position.
92
+ # ### Byte Position (Position)
93
+ # The byte position (or simply *position*)
94
+ # is a zero-based index into the bytes in the scanner's stored string;
95
+ # for a new `StringScanner` object, the byte position is zero.
96
+ # When the byte position is:
97
+ # * Zero (at the beginning), the target substring is the entire stored string.
98
+ # * Equal to the size of the stored string (at the end),
99
+ # the target substring is the empty string `''`.
100
+ # To get or set the byte position:
101
+ # * #pos: returns the byte position.
102
+ # * #pos=(new_pos): sets the byte position.
103
+ # Many methods use the byte position as the basis for finding matches;
104
+ # many others set, increment, or decrement the byte position:
105
+ # scanner = StringScanner.new('foobar')
106
+ # scanner.pos # => 0
107
+ # scanner.scan(/foo/) # => "foo" # Match found.
108
+ # scanner.pos # => 3 # Byte position incremented.
109
+ # scanner.scan(/foo/) # => nil # Match not found.
110
+ # scanner.pos # => 3 # Byte position not changed.
68
111
  #
112
+ # Some methods implicitly modify the byte position;
113
+ # see:
114
+ # * [Setting the Target
115
+ # Substring](rdoc-ref:StringScanner@Setting+the+Target+Substring).
116
+ # * [Traversing the Target
117
+ # Substring](rdoc-ref:StringScanner@Traversing+the+Target+Substring).
118
+ # The values of these methods are derived directly from the values of #pos and
119
+ # #string:
120
+ # * #charpos: the [character
121
+ # position](rdoc-ref:StringScanner@Character+Position).
122
+ # * #rest: the [target substring](rdoc-ref:StringScanner@Target+Substring).
123
+ # * #rest_size: `rest.size`.
124
+ # ### Character Position
125
+ # The character position is a zero-based index into the *characters*
126
+ # in the stored string;
127
+ # for a new `StringScanner` object, the character position is zero.
128
+ # Method #charpos returns the character position;
129
+ # its value may not be reset explicitly.
130
+ # Some methods change (increment or reset) the character position;
131
+ # see:
132
+ # * [Setting the Target
133
+ # Substring](rdoc-ref:StringScanner@Setting+the+Target+Substring).
134
+ # * [Traversing the Target
135
+ # Substring](rdoc-ref:StringScanner@Traversing+the+Target+Substring).
136
+ # Example (string includes multi-byte characters):
137
+ # scanner = StringScanner.new(ENGLISH_TEXT) # Five 1-byte characters.
138
+ # scanner.concat(HIRAGANA_TEXT) # Five 3-byte characters
139
+ # scanner.string # => "Helloこんにちは" # Twenty bytes in all.
140
+ # put_situation(scanner)
141
+ # # Situation:
142
+ # # pos: 0
143
+ # # charpos: 0
144
+ # # rest: "Helloこんにちは"
145
+ # # rest_size: 20
146
+ # scanner.scan(/Hello/) # => "Hello" # Five 1-byte characters.
147
+ # put_situation(scanner)
148
+ # # Situation:
149
+ # # pos: 5
150
+ # # charpos: 5
151
+ # # rest: "こんにちは"
152
+ # # rest_size: 15
153
+ # scanner.getch # => "こ" # One 3-byte character.
154
+ # put_situation(scanner)
155
+ # # Situation:
156
+ # # pos: 8
157
+ # # charpos: 6
158
+ # # rest: "んにちは"
159
+ # # rest_size: 12
69
160
  #
70
- # ### Finding Where we Are
161
+ # ## Target Substring
162
+ # The target substring is the the part of the [stored
163
+ # string](rdoc-ref:StringScanner@Stored+String)
164
+ # that extends from the current [byte
165
+ # position](rdoc-ref:StringScanner@Byte+Position+-28Position-29) to the end of
166
+ # the stored string;
167
+ # it is always either:
168
+ # * The entire stored string (byte position is zero).
169
+ # * A trailing substring of the stored string (byte position positive).
170
+ # The target substring is returned by method #rest,
171
+ # and its size is returned by method #rest_size.
172
+ # Examples:
173
+ # scanner = StringScanner.new('foobarbaz')
174
+ # put_situation(scanner)
175
+ # # Situation:
176
+ # # pos: 0
177
+ # # charpos: 0
178
+ # # rest: "foobarbaz"
179
+ # # rest_size: 9
180
+ # scanner.pos = 3
181
+ # put_situation(scanner)
182
+ # # Situation:
183
+ # # pos: 3
184
+ # # charpos: 3
185
+ # # rest: "barbaz"
186
+ # # rest_size: 6
187
+ # scanner.pos = 9
188
+ # put_situation(scanner)
189
+ # # Situation:
190
+ # # pos: 9
191
+ # # charpos: 9
192
+ # # rest: ""
193
+ # # rest_size: 0
71
194
  #
72
- # * #beginning_of_line? (`#bol?`)
73
- # * #eos?
74
- # * #rest?
75
- # * #rest_size
76
- # * #pos
195
+ # ### Setting the Target Substring
196
+ # The target substring is set whenever:
197
+ # * The [stored string](rdoc-ref:StringScanner@Stored+String) is set (position
198
+ # reset to zero; target substring set to stored string).
199
+ # * The [byte position](rdoc-ref:StringScanner@Byte+Position+-28Position-29)
200
+ # is set (target substring adjusted accordingly).
201
+ # ### Querying the Target Substring
202
+ # This table summarizes (details and examples at the links):
203
+ # Method | Returns
204
+ # ----------|---------------------------------
205
+ # #rest | Target substring.
206
+ # #rest_size|Size (bytes) of target substring.
207
+ # ### Searching the Target Substring
208
+ # A *search* method examines the target substring,
209
+ # but does not advance the [positions](rdoc-ref:StringScanner@Positions)
210
+ # or (by implication) shorten the target substring.
211
+ # This table summarizes (details and examples at the links):
212
+ # Method | Returns |Sets Match Values?
213
+ # ---------------------|---------------------------------------------|------------------
214
+ # #check(pattern) | Matched leading substring or +nil+. | Yes.
215
+ # #check_until(pattern)| Matched substring (anywhere) or +nil+. | Yes.
216
+ # #exist?(pattern) | Matched substring (anywhere) end index. | Yes.
217
+ # #match?(pattern) | Size of matched leading substring or +nil+. | Yes.
218
+ # #peek(size) | Leading substring of given length (bytes). | No.
219
+ # #peek_byte | Integer leading byte or +nil+. | No.
220
+ # #rest |Target substring (from byte position to end).| No.
221
+ # ### Traversing the Target Substring
222
+ # A *traversal* method examines the target substring,
223
+ # and, if successful:
224
+ # * Advances the [positions](rdoc-ref:StringScanner@Positions).
225
+ # * Shortens the target substring.
226
+ # This table summarizes (details and examples at links):
227
+ # Method | Returns |Sets Match Values?
228
+ # --------------------|----------------------------------------------------|------------------
229
+ # #get_byte | Leading byte or +nil+. | No.
230
+ # #getch | Leading character or +nil+. | No.
231
+ # #scan(pattern) | Matched leading substring or +nil+. | Yes.
232
+ # #scan_byte | Integer leading byte or +nil+. | No.
233
+ # #scan_until(pattern)| Matched substring (anywhere) or +nil+. | Yes.
234
+ # #skip(pattern) | Matched leading substring size or +nil+. | Yes.
235
+ # #skip_until(pattern)|Position delta to end-of-matched-substring or +nil+.| Yes.
236
+ # #unscan | +self+. | No.
237
+ # ## Querying the Scanner
238
+ # Each of these methods queries the scanner object
239
+ # without modifying it (details and examples at links)
240
+ # Method | Returns
241
+ # -------------------|--------------------------------
242
+ # #beginning_of_line?| +true+ or +false+.
243
+ # #charpos | Character position.
244
+ # #eos? | +true+ or +false+.
245
+ # #fixed_anchor? | +true+ or +false+.
246
+ # #inspect |String representation of +self+.
247
+ # #pos | Byte position.
248
+ # #rest | Target substring.
249
+ # #rest_size | Size of target substring.
250
+ # #string | Stored string.
251
+ # ## Matching
252
+ # `StringScanner` implements pattern matching via Ruby class
253
+ # [Regexp](https://docs.ruby-lang.org/en/master/Regexp.html),
254
+ # and its matching behaviors are the same as Ruby's
255
+ # except for the [fixed-anchor
256
+ # property](rdoc-ref:StringScanner@Fixed-Anchor+Property).
257
+ # ### Matcher Methods
258
+ # Each *matcher method* takes a single argument `pattern`,
259
+ # and attempts to find a matching substring in the [target
260
+ # substring](rdoc-ref:StringScanner@Target+Substring).
261
+ # Method | Pattern Type |Matches Target Substring| Success Return |May Update Positions?
262
+ # ------------|-----------------|------------------------|------------------|---------------------
263
+ # #check |Regexp or String.| At beginning. |Matched substring.| No.
264
+ # #check_until|Regexp or String.| Anywhere. | Substring. | No.
265
+ # #match? |Regexp or String.| At beginning. | Match size. | No.
266
+ # #exist? |Regexp or String.| Anywhere. | Substring size. | No.
267
+ # #scan |Regexp or String.| At beginning. |Matched substring.| Yes.
268
+ # #scan_until |Regexp or String.| Anywhere. | Substring. | Yes.
269
+ # #skip |Regexp or String.| At beginning. | Match size. | Yes.
270
+ # #skip_until |Regexp or String.| Anywhere. | Substring size. | Yes.
77
271
  #
272
+ # Which matcher you choose will depend on:
273
+ # * Where you want to find a match:
274
+ # * Only at the beginning of the target substring:
275
+ # #check, #match?, #scan, #skip.
276
+ # * Anywhere in the target substring:
277
+ # #check_until, #exist?, #scan_until, #skip_until.
278
+ # * Whether you want to:
279
+ # * Traverse, by advancing the positions:
280
+ # #scan, #scan_until, #skip, #skip_until.
281
+ # * Keep the positions unchanged:
282
+ # #check, #check_until, #match?, #exist?.
283
+ # * What you want for the return value:
284
+ # * The matched substring: #check, #scan.
285
+ # * The substring: #check_until, #scan_until.
286
+ # * The match size: #match?, #skip.
287
+ # * The substring size: #exist?, #skip_until.
288
+ # ### Match Values
289
+ # The *match values* in a `StringScanner` object
290
+ # generally contain the results of the most recent attempted match.
291
+ # Each match value may be thought of as:
292
+ # * *Clear*: Initially, or after an unsuccessful match attempt:
293
+ # usually, `false`, `nil`, or `{}`.
294
+ # * *Set*: After a successful match attempt:
295
+ # `true`, string, array, or hash.
296
+ # Each of these methods clears match values:
297
+ # * ::new(string).
298
+ # * #reset.
299
+ # * #terminate.
300
+ # Each of these methods attempts a match based on a pattern,
301
+ # and either sets match values (if successful) or clears them (if not);
302
+ # * #check(pattern)
303
+ # * #check_until(pattern)
304
+ # * #exist?(pattern)
305
+ # * #match?(pattern)
306
+ # * #scan(pattern)
307
+ # * #scan_until(pattern)
308
+ # * #skip(pattern)
309
+ # * #skip_until(pattern)
310
+ # #### Basic Match Values
311
+ # Basic match values are those not related to captures.
312
+ # Each of these methods returns a basic match value:
313
+ # Method | Return After Match |Return After No Match
314
+ # -------------|--------------------------------------|---------------------
315
+ # #matched? | +true+. | +false+.
316
+ # #matched_size| Size of matched substring. | +nil+.
317
+ # #matched | Matched substring. | +nil+.
318
+ # #pre_match |Substring preceding matched substring.| +nil+.
319
+ # #post_match |Substring following matched substring.| +nil+.
78
320
  #
79
- # ### Setting Where we Are
321
+ # See examples below.
322
+ # #### Captured Match Values
323
+ # Captured match values are those related to
324
+ # [captures](https://docs.ruby-lang.org/en/master/Regexp.html#class-Regexp-label
325
+ # -Groups+and+Captures).
326
+ # Each of these methods returns a captured match value:
327
+ # Method | Return After Match |Return After No Match
328
+ # ---------------|---------------------------------------|---------------------
329
+ # #size | Count of captured substrings. | +nil+.
330
+ # #[](n) | <tt>n</tt>th captured substring. | +nil+.
331
+ # #captures | Array of all captured substrings. | +nil+.
332
+ # #values_at(*n) |Array of specified captured substrings.| +nil+.
333
+ # #named_captures| Hash of named captures. | <tt>{}</tt>.
80
334
  #
81
- # * #reset
82
- # * #terminate
83
- # * #pos=
335
+ # See examples below.
336
+ # #### Match Values Examples
337
+ # Successful basic match attempt (no captures):
338
+ # scanner = StringScanner.new('foobarbaz')
339
+ # scanner.exist?(/bar/)
340
+ # put_match_values(scanner)
341
+ # # Basic match values:
342
+ # # matched?: true
343
+ # # matched_size: 3
344
+ # # pre_match: "foo"
345
+ # # matched : "bar"
346
+ # # post_match: "baz"
347
+ # # Captured match values:
348
+ # # size: 1
349
+ # # captures: []
350
+ # # named_captures: {}
351
+ # # values_at: ["bar", nil]
352
+ # # []:
353
+ # # [0]: "bar"
354
+ # # [1]: nil
84
355
  #
356
+ # Failed basic match attempt (no captures);
357
+ # scanner = StringScanner.new('foobarbaz')
358
+ # scanner.exist?(/nope/)
359
+ # match_values_cleared?(scanner) # => true
85
360
  #
86
- # ### Match Data
361
+ # Successful unnamed capture match attempt:
362
+ # scanner = StringScanner.new('foobarbazbatbam')
363
+ # scanner.exist?(/(foo)bar(baz)bat(bam)/)
364
+ # put_match_values(scanner)
365
+ # # Basic match values:
366
+ # # matched?: true
367
+ # # matched_size: 15
368
+ # # pre_match: ""
369
+ # # matched : "foobarbazbatbam"
370
+ # # post_match: ""
371
+ # # Captured match values:
372
+ # # size: 4
373
+ # # captures: ["foo", "baz", "bam"]
374
+ # # named_captures: {}
375
+ # # values_at: ["foobarbazbatbam", "foo", "baz", "bam", nil]
376
+ # # []:
377
+ # # [0]: "foobarbazbatbam"
378
+ # # [1]: "foo"
379
+ # # [2]: "baz"
380
+ # # [3]: "bam"
381
+ # # [4]: nil
87
382
  #
88
- # * #matched
89
- # * #matched?
90
- # * #matched_size
91
- # * `#[]`
92
- # * #pre_match
93
- # * #post_match
383
+ # Successful named capture match attempt;
384
+ # same as unnamed above, except for #named_captures:
385
+ # scanner = StringScanner.new('foobarbazbatbam')
386
+ # scanner.exist?(/(?<x>foo)bar(?<y>baz)bat(?<z>bam)/)
387
+ # scanner.named_captures # => {"x"=>"foo", "y"=>"baz", "z"=>"bam"}
94
388
  #
389
+ # Failed unnamed capture match attempt:
390
+ # scanner = StringScanner.new('somestring')
391
+ # scanner.exist?(/(foo)bar(baz)bat(bam)/)
392
+ # match_values_cleared?(scanner) # => true
95
393
  #
96
- # ### Miscellaneous
394
+ # Failed named capture match attempt;
395
+ # same as unnamed above, except for #named_captures:
396
+ # scanner = StringScanner.new('somestring')
397
+ # scanner.exist?(/(?<x>foo)bar(?<y>baz)bat(?<z>bam)/)
398
+ # match_values_cleared?(scanner) # => false
399
+ # scanner.named_captures # => {"x"=>nil, "y"=>nil, "z"=>nil}
97
400
  #
98
- # * `<<`
99
- # * #concat
100
- # * #string
101
- # * #string=
102
- # * #unscan
401
+ # ## Fixed-Anchor Property
402
+ # Pattern matching in `StringScanner` is the same as in Ruby's,
403
+ # except for its fixed-anchor property,
404
+ # which determines the meaning of `'\A'`:
405
+ # * `false` (the default): matches the current byte position.
406
+ # scanner = StringScanner.new('foobar')
407
+ # scanner.scan(/\A./) # => "f"
408
+ # scanner.scan(/\A./) # => "o"
409
+ # scanner.scan(/\A./) # => "o"
410
+ # scanner.scan(/\A./) # => "b"
103
411
  #
412
+ # * `true`: matches the beginning of the target substring;
413
+ # never matches unless the byte position is zero:
414
+ # scanner = StringScanner.new('foobar', fixed_anchor: true)
415
+ # scanner.scan(/\A./) # => "f"
416
+ # scanner.scan(/\A./) # => nil
417
+ # scanner.reset
418
+ # scanner.scan(/\A./) # => "f"
104
419
  #
105
- # There are aliases to several of the methods.
420
+ # The fixed-anchor property is set when the `StringScanner` object is created,
421
+ # and may not be modified
422
+ # (see StringScanner.new);
423
+ # method #fixed_anchor? returns the setting.
106
424
  #
107
425
  class StringScanner
108
426
  # <!--
@@ -114,61 +432,103 @@ class StringScanner
114
432
  def self.must_C_version: () -> self
115
433
 
116
434
  # <!-- rdoc-file=ext/strscan/strscan.c -->
117
- # Appends `str` to the string being scanned. This method does not affect scan
118
- # pointer.
119
- #
120
- # s = StringScanner.new("Fri Dec 12 1975 14:39")
121
- # s.scan(/Fri /)
122
- # s << " +1000 GMT"
123
- # s.string # -> "Fri Dec 12 1975 14:39 +1000 GMT"
124
- # s.scan(/Dec/) # -> "Dec"
435
+ # * Appends the given `more_string`
436
+ # to the [stored string](rdoc-ref:StringScanner@Stored+String).
437
+ # * Returns `self`.
438
+ # * Does not affect the [positions](rdoc-ref:StringScanner@Positions)
439
+ # or [match values](rdoc-ref:StringScanner@Match+Values).
440
+ # scanner = StringScanner.new('foo')
441
+ # scanner.string # => "foo"
442
+ # scanner.terminate
443
+ # scanner.concat('barbaz') # => #<StringScanner 3/9 "foo" @ "barba...">
444
+ # scanner.string # => "foobarbaz"
445
+ # put_situation(scanner)
446
+ # # Situation:
447
+ # # pos: 3
448
+ # # charpos: 3
449
+ # # rest: "barbaz"
450
+ # # rest_size: 6
125
451
  #
126
452
  def <<: (String) -> self
127
453
 
128
454
  # <!--
129
455
  # rdoc-file=ext/strscan/strscan.c
130
- # - [](n)
456
+ # - [](specifier) -> substring or nil
131
457
  # -->
132
- # Returns the n-th subgroup in the most recent match.
133
- #
134
- # s = StringScanner.new("Fri Dec 12 1975 14:39")
135
- # s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
136
- # s[0] # -> "Fri Dec 12 "
137
- # s[1] # -> "Fri"
138
- # s[2] # -> "Dec"
139
- # s[3] # -> "12"
140
- # s.post_match # -> "1975 14:39"
141
- # s.pre_match # -> ""
142
- #
143
- # s.reset
144
- # s.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /) # -> "Fri Dec 12 "
145
- # s[0] # -> "Fri Dec 12 "
146
- # s[1] # -> "Fri"
147
- # s[2] # -> "Dec"
148
- # s[3] # -> "12"
149
- # s[:wday] # -> "Fri"
150
- # s[:month] # -> "Dec"
151
- # s[:day] # -> "12"
152
- # s.post_match # -> "1975 14:39"
153
- # s.pre_match # -> ""
458
+ # Returns a captured substring or `nil`;
459
+ # see [Captured Match Values](rdoc-ref:StringScanner@Captured+Match+Values).
460
+ # When there are captures:
461
+ # scanner = StringScanner.new('Fri Dec 12 1975 14:39')
462
+ # scanner.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /)
463
+ #
464
+ # * `specifier` zero: returns the entire matched substring:
465
+ # scanner[0] # => "Fri Dec 12 "
466
+ # scanner.pre_match # => ""
467
+ # scanner.post_match # => "1975 14:39"
468
+ #
469
+ # * `specifier` positive integer. returns the `n`th capture, or `nil` if out
470
+ # of range:
471
+ # scanner[1] # => "Fri"
472
+ # scanner[2] # => "Dec"
473
+ # scanner[3] # => "12"
474
+ # scanner[4] # => nil
475
+ #
476
+ # * `specifier` negative integer. counts backward from the last subgroup:
477
+ # scanner[-1] # => "12"
478
+ # scanner[-4] # => "Fri Dec 12 "
479
+ # scanner[-5] # => nil
480
+ #
481
+ # * `specifier` symbol or string. returns the named subgroup, or `nil` if no
482
+ # such:
483
+ # scanner[:wday] # => "Fri"
484
+ # scanner['wday'] # => "Fri"
485
+ # scanner[:month] # => "Dec"
486
+ # scanner[:day] # => "12"
487
+ # scanner[:nope] # => nil
488
+ #
489
+ # When there are no captures, only `[0]` returns non-`nil`:
490
+ # scanner = StringScanner.new('foobarbaz')
491
+ # scanner.exist?(/bar/)
492
+ # scanner[0] # => "bar"
493
+ # scanner[1] # => nil
494
+ #
495
+ # For a failed match, even `[0]` returns `nil`:
496
+ # scanner.scan(/nope/) # => nil
497
+ # scanner[0] # => nil
498
+ # scanner[1] # => nil
154
499
  #
155
500
  def []: (Integer) -> String?
156
501
 
157
502
  # <!--
158
503
  # rdoc-file=ext/strscan/strscan.c
159
- # - beginning_of_line?()
504
+ # - beginning_of_line? -> true or false
160
505
  # -->
161
- # Returns `true` if and only if the scan pointer is at the beginning of the
162
- # line.
506
+ # Returns whether the
507
+ # [position](rdoc-ref:StringScanner@Byte+Position+-28Position-29) is at the
508
+ # beginning of a line;
509
+ # that is, at the beginning of the [stored
510
+ # string](rdoc-ref:StringScanner@Stored+String)
511
+ # or immediately after a newline:
512
+ # scanner = StringScanner.new(MULTILINE_TEXT)
513
+ # scanner.string
514
+ # # => "Go placidly amid the noise and haste,\nand remember what peace there may be in silence.\n"
515
+ # scanner.pos # => 0
516
+ # scanner.beginning_of_line? # => true
517
+ #
518
+ # scanner.scan_until(/,/) # => "Go placidly amid the noise and haste,"
519
+ # scanner.beginning_of_line? # => false
163
520
  #
164
- # s = StringScanner.new("test\ntest\n")
165
- # s.bol? # => true
166
- # s.scan(/te/)
167
- # s.bol? # => false
168
- # s.scan(/st\n/)
169
- # s.bol? # => true
170
- # s.terminate
171
- # s.bol? # => true
521
+ # scanner.scan(/\n/) # => "\n"
522
+ # scanner.beginning_of_line? # => true
523
+ #
524
+ # scanner.terminate
525
+ # scanner.beginning_of_line? # => true
526
+ #
527
+ # scanner.concat('x')
528
+ # scanner.terminate
529
+ # scanner.beginning_of_line? # => false
530
+ #
531
+ # StringScanner#bol? is an alias for StringScanner#beginning_of_line?.
172
532
  #
173
533
  def beginning_of_line?: () -> bool
174
534
 
@@ -176,16 +536,23 @@ class StringScanner
176
536
 
177
537
  # <!--
178
538
  # rdoc-file=ext/strscan/strscan.c
179
- # - captures
539
+ # - captures -> substring_array or nil
180
540
  # -->
181
- # Returns the subgroups in the most recent match (not including the full match).
182
- # If nothing was priorly matched, it returns nil.
541
+ # Returns the array of [captured match
542
+ # values](rdoc-ref:StringScanner@Captured+Match+Values) at indexes `(1..)`
543
+ # if the most recent match attempt succeeded, or `nil` otherwise:
544
+ # scanner = StringScanner.new('Fri Dec 12 1975 14:39')
545
+ # scanner.captures # => nil
546
+ #
547
+ # scanner.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /)
548
+ # scanner.captures # => ["Fri", "Dec", "12"]
549
+ # scanner.values_at(*0..4) # => ["Fri Dec 12 ", "Fri", "Dec", "12", nil]
550
+ #
551
+ # scanner.exist?(/Fri/)
552
+ # scanner.captures # => []
183
553
  #
184
- # s = StringScanner.new("Fri Dec 12 1975 14:39")
185
- # s.scan(/(\w+) (\w+) (\d+) (1980)?/) # -> "Fri Dec 12 "
186
- # s.captures # -> ["Fri", "Dec", "12", nil]
187
- # s.scan(/(\w+) (\w+) (\d+) (1980)?/) # -> nil
188
- # s.captures # -> nil
554
+ # scanner.scan(/nope/)
555
+ # scanner.captures # => nil
189
556
  #
190
557
  def captures: () -> Array[String]?
191
558
 
@@ -193,51 +560,116 @@ class StringScanner
193
560
  # rdoc-file=ext/strscan/strscan.c
194
561
  # - charpos()
195
562
  # -->
196
- # Returns the character position of the scan pointer. In the 'reset' position,
197
- # this value is zero. In the 'terminated' position (i.e. the string is
198
- # exhausted), this value is the size of the string.
199
- #
200
- # In short, it's a 0-based index into the string.
201
- #
202
- # s = StringScanner.new("abc\u00e4def\u00f6ghi")
203
- # s.charpos # -> 0
204
- # s.scan_until(/\u00e4/) # -> "abc\u00E4"
205
- # s.pos # -> 5
206
- # s.charpos # -> 4
563
+ # call-seq:
564
+ # charpos -> character_position
565
+ # Returns the [character position](rdoc-ref:StringScanner@Character+Position)
566
+ # (initially zero),
567
+ # which may be different from the [byte
568
+ # position](rdoc-ref:StringScanner@Byte+Position+-28Position-29)
569
+ # given by method #pos:
570
+ # scanner = StringScanner.new(HIRAGANA_TEXT)
571
+ # scanner.string # => "こんにちは"
572
+ # scanner.getch # => "こ" # 3-byte character.
573
+ # scanner.getch # => "ん" # 3-byte character.
574
+ # put_situation(scanner)
575
+ # # Situation:
576
+ # # pos: 6
577
+ # # charpos: 2
578
+ # # rest: "にちは"
579
+ # # rest_size: 9
207
580
  #
208
581
  def charpos: () -> Integer
209
582
 
210
583
  # <!--
211
584
  # rdoc-file=ext/strscan/strscan.c
212
- # - check(pattern)
585
+ # - check(pattern) -> matched_substring or nil
213
586
  # -->
214
- # This returns the value that #scan would return, without advancing the scan
215
- # pointer. The match register is affected, though.
216
- #
217
- # s = StringScanner.new("Fri Dec 12 1975 14:39")
218
- # s.check /Fri/ # -> "Fri"
219
- # s.pos # -> 0
220
- # s.matched # -> "Fri"
221
- # s.check /12/ # -> nil
222
- # s.matched # -> nil
223
- #
224
- # Mnemonic: it "checks" to see whether a #scan will return a value.
587
+ # Attempts to [match](rdoc-ref:StringScanner@Matching) the given `pattern`
588
+ # at the beginning of the [target
589
+ # substring](rdoc-ref:StringScanner@Target+Substring);
590
+ # does not modify the [positions](rdoc-ref:StringScanner@Positions).
591
+ # If the match succeeds:
592
+ # * Returns the matched substring.
593
+ # * Sets all [match values](rdoc-ref:StringScanner@Match+Values).
594
+ # scanner = StringScanner.new('foobarbaz')
595
+ # scanner.pos = 3
596
+ # scanner.check('bar') # => "bar"
597
+ # put_match_values(scanner)
598
+ # # Basic match values:
599
+ # # matched?: true
600
+ # # matched_size: 3
601
+ # # pre_match: "foo"
602
+ # # matched : "bar"
603
+ # # post_match: "baz"
604
+ # # Captured match values:
605
+ # # size: 1
606
+ # # captures: []
607
+ # # named_captures: {}
608
+ # # values_at: ["bar", nil]
609
+ # # []:
610
+ # # [0]: "bar"
611
+ # # [1]: nil
612
+ # # => 0..1
613
+ # put_situation(scanner)
614
+ # # Situation:
615
+ # # pos: 3
616
+ # # charpos: 3
617
+ # # rest: "barbaz"
618
+ # # rest_size: 6
619
+ #
620
+ # If the match fails:
621
+ # * Returns `nil`.
622
+ # * Clears all [match values](rdoc-ref:StringScanner@Match+Values).
623
+ # scanner.check(/nope/) # => nil
624
+ # match_values_cleared?(scanner) # => true
225
625
  #
226
626
  def check: (Regexp) -> String?
227
627
 
228
628
  # <!--
229
629
  # rdoc-file=ext/strscan/strscan.c
230
- # - check_until(pattern)
630
+ # - check_until(pattern) -> substring or nil
231
631
  # -->
232
- # This returns the value that #scan_until would return, without advancing the
233
- # scan pointer. The match register is affected, though.
234
- #
235
- # s = StringScanner.new("Fri Dec 12 1975 14:39")
236
- # s.check_until /12/ # -> "Fri Dec 12"
237
- # s.pos # -> 0
238
- # s.matched # -> 12
239
- #
240
- # Mnemonic: it "checks" to see whether a #scan_until will return a value.
632
+ # Attempts to [match](rdoc-ref:StringScanner@Matching) the given `pattern`
633
+ # anywhere (at any
634
+ # [position](rdoc-ref:StringScanner@Byte+Position+-28Position-29))
635
+ # in the [target substring](rdoc-ref:StringScanner@Target+Substring);
636
+ # does not modify the [positions](rdoc-ref:StringScanner@Positions).
637
+ # If the match succeeds:
638
+ # * Sets all [match values](rdoc-ref:StringScanner@Match+Values).
639
+ # * Returns the matched substring,
640
+ # which extends from the current
641
+ # [position](rdoc-ref:StringScanner@Byte+Position+-28Position-29)
642
+ # to the end of the matched substring.
643
+ # scanner = StringScanner.new('foobarbazbatbam')
644
+ # scanner.pos = 6
645
+ # scanner.check_until(/bat/) # => "bazbat"
646
+ # put_match_values(scanner)
647
+ # # Basic match values:
648
+ # # matched?: true
649
+ # # matched_size: 3
650
+ # # pre_match: "foobarbaz"
651
+ # # matched : "bat"
652
+ # # post_match: "bam"
653
+ # # Captured match values:
654
+ # # size: 1
655
+ # # captures: []
656
+ # # named_captures: {}
657
+ # # values_at: ["bat", nil]
658
+ # # []:
659
+ # # [0]: "bat"
660
+ # # [1]: nil
661
+ # put_situation(scanner)
662
+ # # Situation:
663
+ # # pos: 6
664
+ # # charpos: 6
665
+ # # rest: "bazbatbam"
666
+ # # rest_size: 9
667
+ #
668
+ # If the match fails:
669
+ # * Clears all [match values](rdoc-ref:StringScanner@Match+Values).
670
+ # * Returns `nil`.
671
+ # scanner.check_until(/nope/) # => nil
672
+ # match_values_cleared?(scanner) # => true
241
673
  #
242
674
  def check_until: (Regexp) -> String
243
675
 
@@ -251,17 +683,24 @@ class StringScanner
251
683
 
252
684
  # <!--
253
685
  # rdoc-file=ext/strscan/strscan.c
254
- # - concat(str)
255
- # - <<(str)
686
+ # - concat(more_string) -> self
256
687
  # -->
257
- # Appends `str` to the string being scanned. This method does not affect scan
258
- # pointer.
259
- #
260
- # s = StringScanner.new("Fri Dec 12 1975 14:39")
261
- # s.scan(/Fri /)
262
- # s << " +1000 GMT"
263
- # s.string # -> "Fri Dec 12 1975 14:39 +1000 GMT"
264
- # s.scan(/Dec/) # -> "Dec"
688
+ # * Appends the given `more_string`
689
+ # to the [stored string](rdoc-ref:StringScanner@Stored+String).
690
+ # * Returns `self`.
691
+ # * Does not affect the [positions](rdoc-ref:StringScanner@Positions)
692
+ # or [match values](rdoc-ref:StringScanner@Match+Values).
693
+ # scanner = StringScanner.new('foo')
694
+ # scanner.string # => "foo"
695
+ # scanner.terminate
696
+ # scanner.concat('barbaz') # => #<StringScanner 3/9 "foo" @ "barba...">
697
+ # scanner.string # => "foobarbaz"
698
+ # put_situation(scanner)
699
+ # # Situation:
700
+ # # pos: 3
701
+ # # charpos: 3
702
+ # # rest: "barbaz"
703
+ # # rest_size: 6
265
704
  #
266
705
  alias concat <<
267
706
 
@@ -275,43 +714,74 @@ class StringScanner
275
714
 
276
715
  # <!--
277
716
  # rdoc-file=ext/strscan/strscan.c
278
- # - eos?()
717
+ # - eos? -> true or false
279
718
  # -->
280
- # Returns `true` if the scan pointer is at the end of the string.
281
- #
282
- # s = StringScanner.new('test string')
283
- # p s.eos? # => false
284
- # s.scan(/test/)
285
- # p s.eos? # => false
286
- # s.terminate
287
- # p s.eos? # => true
719
+ # Returns whether the
720
+ # [position](rdoc-ref:StringScanner@Byte+Position+-28Position-29)
721
+ # is at the end of the [stored string](rdoc-ref:StringScanner@Stored+String):
722
+ # scanner = StringScanner.new('foobarbaz')
723
+ # scanner.eos? # => false
724
+ # pos = 3
725
+ # scanner.eos? # => false
726
+ # scanner.terminate
727
+ # scanner.eos? # => true
288
728
  #
289
729
  def eos?: () -> bool
290
730
 
291
731
  # <!--
292
732
  # rdoc-file=ext/strscan/strscan.c
293
- # - exist?(pattern)
733
+ # - exist?(pattern) -> byte_offset or nil
294
734
  # -->
295
- # Looks *ahead* to see if the `pattern` exists *anywhere* in the string, without
296
- # advancing the scan pointer. This predicates whether a #scan_until will return
297
- # a value.
298
- #
299
- # s = StringScanner.new('test string')
300
- # s.exist? /s/ # -> 3
301
- # s.scan /test/ # -> "test"
302
- # s.exist? /s/ # -> 2
303
- # s.exist? /e/ # -> nil
735
+ # Attempts to [match](rdoc-ref:StringScanner@Matching) the given `pattern`
736
+ # anywhere (at any
737
+ # [position](rdoc-ref:StringScanner@Byte+Position+-28Position-29))
738
+ # n the [target substring](rdoc-ref:StringScanner@Target+Substring);
739
+ # does not modify the [positions](rdoc-ref:StringScanner@Positions).
740
+ # If the match succeeds:
741
+ # * Returns a byte offset:
742
+ # the distance in bytes between the current
743
+ # [position](rdoc-ref:StringScanner@Byte+Position+-28Position-29)
744
+ # and the end of the matched substring.
745
+ # * Sets all [match values](rdoc-ref:StringScanner@Match+Values).
746
+ # scanner = StringScanner.new('foobarbazbatbam')
747
+ # scanner.pos = 6
748
+ # scanner.exist?(/bat/) # => 6
749
+ # put_match_values(scanner)
750
+ # # Basic match values:
751
+ # # matched?: true
752
+ # # matched_size: 3
753
+ # # pre_match: "foobarbaz"
754
+ # # matched : "bat"
755
+ # # post_match: "bam"
756
+ # # Captured match values:
757
+ # # size: 1
758
+ # # captures: []
759
+ # # named_captures: {}
760
+ # # values_at: ["bat", nil]
761
+ # # []:
762
+ # # [0]: "bat"
763
+ # # [1]: nil
764
+ # put_situation(scanner)
765
+ # # Situation:
766
+ # # pos: 6
767
+ # # charpos: 6
768
+ # # rest: "bazbatbam"
769
+ # # rest_size: 9
770
+ #
771
+ # If the match fails:
772
+ # * Returns `nil`.
773
+ # * Clears all [match values](rdoc-ref:StringScanner@Match+Values).
774
+ # scanner.exist?(/nope/) # => nil
775
+ # match_values_cleared?(scanner) # => true
304
776
  #
305
777
  def exist?: (Regexp) -> Integer?
306
778
 
307
779
  # <!--
308
780
  # rdoc-file=ext/strscan/strscan.c
309
- # - scanner.fixed_anchor? -> true or false
781
+ # - fixed_anchor? -> true or false
310
782
  # -->
311
- # Whether `scanner` uses fixed anchor mode or not.
312
- #
313
- # If fixed anchor mode is used, `\A` always matches the beginning of the string.
314
- # Otherwise, `\A` always matches the current position.
783
+ # Returns whether the [fixed-anchor
784
+ # property](rdoc-ref:StringScanner@Fixed-Anchor+Property) is set.
315
785
  #
316
786
  def fixed_anchor?: () -> bool
317
787
 
@@ -319,18 +789,30 @@ class StringScanner
319
789
  # rdoc-file=ext/strscan/strscan.c
320
790
  # - get_byte()
321
791
  # -->
322
- # Scans one byte and returns it. This method is not multibyte character
323
- # sensitive. See also: #getch.
324
- #
325
- # s = StringScanner.new('ab')
326
- # s.get_byte # => "a"
327
- # s.get_byte # => "b"
328
- # s.get_byte # => nil
329
- #
330
- # s = StringScanner.new("\244\242".force_encoding("euc-jp"))
331
- # s.get_byte # => "\xA4"
332
- # s.get_byte # => "\xA2"
333
- # s.get_byte # => nil
792
+ # call-seq:
793
+ # get_byte -> byte_as_character or nil
794
+ # Returns the next byte, if available:
795
+ # * If the [position](rdoc-ref:StringScanner@Byte+Position+-28Position-29)
796
+ # is not at the end of the [stored
797
+ # string](rdoc-ref:StringScanner@Stored+String):
798
+ # * Returns the next byte.
799
+ # * Increments the [byte
800
+ # position](rdoc-ref:StringScanner@Byte+Position+-28Position-29).
801
+ # * Adjusts the [character
802
+ # position](rdoc-ref:StringScanner@Character+Position).
803
+ # scanner = StringScanner.new(HIRAGANA_TEXT)
804
+ # # => #<StringScanner 0/15 @ "\xE3\x81\x93\xE3\x82...">
805
+ # scanner.string # => "こんにちは"
806
+ # [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\xE3", 1, 1]
807
+ # [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x81", 2, 2]
808
+ # [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x93", 3, 1]
809
+ # [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\xE3", 4, 2]
810
+ # [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x82", 5, 3]
811
+ # [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x93", 6, 2]
812
+ #
813
+ # * Otherwise, returns `nil`, and does not change the positions.
814
+ # scanner.terminate
815
+ # [scanner.get_byte, scanner.pos, scanner.charpos] # => [nil, 15, 5]
334
816
  #
335
817
  def get_byte: () -> String?
336
818
 
@@ -346,103 +828,185 @@ class StringScanner
346
828
  # rdoc-file=ext/strscan/strscan.c
347
829
  # - getch()
348
830
  # -->
349
- # Scans one character and returns it. This method is multibyte character
350
- # sensitive.
351
- #
352
- # s = StringScanner.new("ab")
353
- # s.getch # => "a"
354
- # s.getch # => "b"
355
- # s.getch # => nil
356
- #
357
- # s = StringScanner.new("\244\242".force_encoding("euc-jp"))
358
- # s.getch # => "\x{A4A2}" # Japanese hira-kana "A" in EUC-JP
359
- # s.getch # => nil
831
+ # call-seq:
832
+ # getch -> character or nil
833
+ # Returns the next (possibly multibyte) character,
834
+ # if available:
835
+ # * If the [position](rdoc-ref:StringScanner@Byte+Position+-28Position-29)
836
+ # is at the beginning of a character:
837
+ # * Returns the character.
838
+ # * Increments the [character
839
+ # position](rdoc-ref:StringScanner@Character+Position) by 1.
840
+ # * Increments the [byte
841
+ # position](rdoc-ref:StringScanner@Byte+Position+-28Position-29)
842
+ # by the size (in bytes) of the character.
843
+ # scanner = StringScanner.new(HIRAGANA_TEXT)
844
+ # scanner.string # => "こんにちは"
845
+ # [scanner.getch, scanner.pos, scanner.charpos] # => ["こ", 3, 1]
846
+ # [scanner.getch, scanner.pos, scanner.charpos] # => ["ん", 6, 2]
847
+ # [scanner.getch, scanner.pos, scanner.charpos] # => ["に", 9, 3]
848
+ # [scanner.getch, scanner.pos, scanner.charpos] # => ["ち", 12, 4]
849
+ # [scanner.getch, scanner.pos, scanner.charpos] # => ["は", 15, 5]
850
+ # [scanner.getch, scanner.pos, scanner.charpos] # => [nil, 15, 5]
851
+ #
852
+ # * If the [position](rdoc-ref:StringScanner@Byte+Position+-28Position-29) is
853
+ # within a multi-byte character
854
+ # (that is, not at its beginning),
855
+ # behaves like #get_byte (returns a 1-byte character):
856
+ # scanner.pos = 1
857
+ # [scanner.getch, scanner.pos, scanner.charpos] # => ["\x81", 2, 2]
858
+ # [scanner.getch, scanner.pos, scanner.charpos] # => ["\x93", 3, 1]
859
+ # [scanner.getch, scanner.pos, scanner.charpos] # => ["ん", 6, 2]
860
+ #
861
+ # * If the [position](rdoc-ref:StringScanner@Byte+Position+-28Position-29) is
862
+ # at the end of the [stored string](rdoc-ref:StringScanner@Stored+String),
863
+ # returns `nil` and does not modify the positions:
864
+ # scanner.terminate
865
+ # [scanner.getch, scanner.pos, scanner.charpos] # => [nil, 15, 5]
360
866
  #
361
867
  def getch: () -> String?
362
868
 
363
869
  # <!--
364
870
  # rdoc-file=ext/strscan/strscan.c
365
- # - inspect()
871
+ # - inspect -> string
366
872
  # -->
367
- # Returns a string that represents the StringScanner object, showing:
368
- # * the current position
369
- # * the size of the string
370
- # * the characters surrounding the scan pointer
371
- #
372
- # s = StringScanner.new("Fri Dec 12 1975 14:39") s.inspect # ->
373
- # '#<StringScanner 0/21 @ "Fri D...">' s.scan_until /12/ # -> "Fri Dec
374
- # 12" s.inspect # -> '#<StringScanner 10/21 "...ec 12" @ "
375
- # 1975...">'
873
+ # Returns a string representation of `self` that may show:
874
+ # 1. The current
875
+ # [position](rdoc-ref:StringScanner@Byte+Position+-28Position-29).
876
+ # 2. The size (in bytes) of the [stored
877
+ # string](rdoc-ref:StringScanner@Stored+String).
878
+ # 3. The substring preceding the current position.
879
+ # 4. The substring following the current position (which is also the [target
880
+ # substring](rdoc-ref:StringScanner@Target+Substring)).
881
+ # scanner = StringScanner.new("Fri Dec 12 1975 14:39")
882
+ # scanner.pos = 11
883
+ # scanner.inspect # => "#<StringScanner 11/21 \"...c 12 \" @ \"1975 ...\">"
884
+ #
885
+ # If at beginning-of-string, item 4 above (following substring) is omitted:
886
+ # scanner.reset
887
+ # scanner.inspect # => "#<StringScanner 0/21 @ \"Fri D...\">"
888
+ #
889
+ # If at end-of-string, all items above are omitted:
890
+ # scanner.terminate
891
+ # scanner.inspect # => "#<StringScanner fin>"
376
892
  #
377
893
  def inspect: () -> String
378
894
 
379
895
  # <!--
380
896
  # rdoc-file=ext/strscan/strscan.c
381
- # - match?(pattern)
897
+ # - match?(pattern) -> updated_position or nil
382
898
  # -->
383
- # Tests whether the given `pattern` is matched from the current scan pointer.
384
- # Returns the length of the match, or `nil`. The scan pointer is not advanced.
385
- #
386
- # s = StringScanner.new('test string')
387
- # p s.match?(/\w+/) # -> 4
388
- # p s.match?(/\w+/) # -> 4
389
- # p s.match?("test") # -> 4
390
- # p s.match?(/\s+/) # -> nil
899
+ # Attempts to [match](rdoc-ref:StringScanner@Matching) the given `pattern`
900
+ # at the beginning of the [target
901
+ # substring](rdoc-ref:StringScanner@Target+Substring);
902
+ # does not modify the [positions](rdoc-ref:StringScanner@Positions).
903
+ # If the match succeeds:
904
+ # * Sets [match values](rdoc-ref:StringScanner@Match+Values).
905
+ # * Returns the size in bytes of the matched substring.
906
+ # scanner = StringScanner.new('foobarbaz')
907
+ # scanner.pos = 3
908
+ # scanner.match?(/bar/) => 3
909
+ # put_match_values(scanner)
910
+ # # Basic match values:
911
+ # # matched?: true
912
+ # # matched_size: 3
913
+ # # pre_match: "foo"
914
+ # # matched : "bar"
915
+ # # post_match: "baz"
916
+ # # Captured match values:
917
+ # # size: 1
918
+ # # captures: []
919
+ # # named_captures: {}
920
+ # # values_at: ["bar", nil]
921
+ # # []:
922
+ # # [0]: "bar"
923
+ # # [1]: nil
924
+ # put_situation(scanner)
925
+ # # Situation:
926
+ # # pos: 3
927
+ # # charpos: 3
928
+ # # rest: "barbaz"
929
+ # # rest_size: 6
930
+ #
931
+ # If the match fails:
932
+ # * Clears match values.
933
+ # * Returns `nil`.
934
+ # * Does not increment positions.
935
+ # scanner.match?(/nope/) # => nil
936
+ # match_values_cleared?(scanner) # => true
391
937
  #
392
938
  def match?: (Regexp) -> Integer?
393
939
 
394
940
  # <!--
395
941
  # rdoc-file=ext/strscan/strscan.c
396
- # - matched()
942
+ # - matched -> matched_substring or nil
397
943
  # -->
398
- # Returns the last matched string.
399
- #
400
- # s = StringScanner.new('test string')
401
- # s.match?(/\w+/) # -> 4
402
- # s.matched # -> "test"
944
+ # Returns the matched substring from the most recent
945
+ # [match](rdoc-ref:StringScanner@Matching) attempt
946
+ # if it was successful,
947
+ # or `nil` otherwise;
948
+ # see [Basic Matched Values](rdoc-ref:StringScanner@Basic+Match+Values):
949
+ # scanner = StringScanner.new('foobarbaz')
950
+ # scanner.matched # => nil
951
+ # scanner.pos = 3
952
+ # scanner.match?(/bar/) # => 3
953
+ # scanner.matched # => "bar"
954
+ # scanner.match?(/nope/) # => nil
955
+ # scanner.matched # => nil
403
956
  #
404
957
  def matched: () -> String?
405
958
 
406
959
  # <!--
407
960
  # rdoc-file=ext/strscan/strscan.c
408
- # - matched?()
961
+ # - matched? -> true or false
409
962
  # -->
410
- # Returns `true` if and only if the last match was successful.
411
- #
412
- # s = StringScanner.new('test string')
413
- # s.match?(/\w+/) # => 4
414
- # s.matched? # => true
415
- # s.match?(/\d+/) # => nil
416
- # s.matched? # => false
963
+ # Returns `true` of the most recent [match
964
+ # attempt](rdoc-ref:StringScanner@Matching) was successful,
965
+ # `false` otherwise;
966
+ # see [Basic Matched Values](rdoc-ref:StringScanner@Basic+Match+Values):
967
+ # scanner = StringScanner.new('foobarbaz')
968
+ # scanner.matched? # => false
969
+ # scanner.pos = 3
970
+ # scanner.exist?(/baz/) # => 6
971
+ # scanner.matched? # => true
972
+ # scanner.exist?(/nope/) # => nil
973
+ # scanner.matched? # => false
417
974
  #
418
975
  def matched?: () -> bool
419
976
 
420
977
  # <!--
421
978
  # rdoc-file=ext/strscan/strscan.c
422
- # - matched_size()
979
+ # - matched_size -> substring_size or nil
423
980
  # -->
424
- # Returns the size of the most recent match in bytes, or `nil` if there was no
425
- # recent match. This is different than `matched.size`, which will return the
426
- # size in characters.
981
+ # Returns the size (in bytes) of the matched substring
982
+ # from the most recent match [match attempt](rdoc-ref:StringScanner@Matching) if
983
+ # it was successful,
984
+ # or `nil` otherwise;
985
+ # see [Basic Matched Values](rdoc-ref:StringScanner@Basic+Match+Values):
986
+ # scanner = StringScanner.new('foobarbaz')
987
+ # scanner.matched_size # => nil
427
988
  #
428
- # s = StringScanner.new('test string')
429
- # s.check /\w+/ # -> "test"
430
- # s.matched_size # -> 4
431
- # s.check /\d+/ # -> nil
432
- # s.matched_size # -> nil
989
+ # pos = 3
990
+ # scanner.exist?(/baz/) # => 9
991
+ # scanner.matched_size # => 3
992
+ #
993
+ # scanner.exist?(/nope/) # => nil
994
+ # scanner.matched_size # => nil
433
995
  #
434
996
  def matched_size: () -> Integer?
435
997
 
436
998
  # <!--
437
999
  # rdoc-file=ext/strscan/strscan.c
438
- # - peek(len)
1000
+ # - peek(length) -> substring
439
1001
  # -->
440
- # Extracts a string corresponding to `string[pos,len]`, without advancing the
441
- # scan pointer.
442
- #
443
- # s = StringScanner.new('test string')
444
- # s.peek(7) # => "test st"
445
- # s.peek(7) # => "test st"
1002
+ # Returns the substring `string[pos, length]`;
1003
+ # does not update [match values](rdoc-ref:StringScanner@Match+Values) or
1004
+ # [positions](rdoc-ref:StringScanner@Positions):
1005
+ # scanner = StringScanner.new('foobarbaz')
1006
+ # scanner.pos = 3
1007
+ # scanner.peek(3) # => "bar"
1008
+ # scanner.terminate
1009
+ # scanner.peek(3) # => ""
446
1010
  #
447
1011
  def peek: (Integer) -> String
448
1012
 
@@ -455,27 +1019,42 @@ class StringScanner
455
1019
  def peep: (Integer) -> String
456
1020
 
457
1021
  # <!-- rdoc-file=ext/strscan/strscan.c -->
458
- # Returns the byte position of the scan pointer. In the 'reset' position, this
459
- # value is zero. In the 'terminated' position (i.e. the string is exhausted),
460
- # this value is the bytesize of the string.
461
- #
462
- # In short, it's a 0-based index into bytes of the string.
463
- #
464
- # s = StringScanner.new('test string')
465
- # s.pos # -> 0
466
- # s.scan_until /str/ # -> "test str"
467
- # s.pos # -> 8
468
- # s.terminate # -> #<StringScanner fin>
469
- # s.pos # -> 11
1022
+ # call-seq:
1023
+ # pos -> byte_position
1024
+ # Returns the integer [byte
1025
+ # position](rdoc-ref:StringScanner@Byte+Position+-28Position-29),
1026
+ # which may be different from the [character
1027
+ # position](rdoc-ref:StringScanner@Character+Position):
1028
+ # scanner = StringScanner.new(HIRAGANA_TEXT)
1029
+ # scanner.string # => "こんにちは"
1030
+ # scanner.pos # => 0
1031
+ # scanner.getch # => "こ" # 3-byte character.
1032
+ # scanner.charpos # => 1
1033
+ # scanner.pos # => 3
470
1034
  #
471
1035
  def pointer: () -> Integer
472
1036
 
473
1037
  # <!-- rdoc-file=ext/strscan/strscan.c -->
474
- # Sets the byte position of the scan pointer.
475
- #
476
- # s = StringScanner.new('test string')
477
- # s.pos = 7 # -> 7
478
- # s.rest # -> "ring"
1038
+ # call-seq:
1039
+ # pos = n -> n
1040
+ # pointer = n -> n
1041
+ # Sets the [byte position](rdoc-ref:StringScanner@Byte+Position+-28Position-29)
1042
+ # and the [character position](rdoc-ref:StringScanner@Positions);
1043
+ # returns `n`.
1044
+ # Does not affect [match values](rdoc-ref:StringScanner@Match+Values).
1045
+ # For non-negative `n`, sets the position to `n`:
1046
+ # scanner = StringScanner.new(HIRAGANA_TEXT)
1047
+ # scanner.string # => "こんにちは"
1048
+ # scanner.pos = 3 # => 3
1049
+ # scanner.rest # => "んにちは"
1050
+ # scanner.charpos # => 1
1051
+ #
1052
+ # For negative `n`, counts from the end of the [stored
1053
+ # string](rdoc-ref:StringScanner@Stored+String):
1054
+ # scanner.pos = -9 # => -9
1055
+ # scanner.pos # => 6
1056
+ # scanner.rest # => "にちは"
1057
+ # scanner.charpos # => 2
479
1058
  #
480
1059
  def pointer=: (Integer) -> Integer
481
1060
 
@@ -483,77 +1062,124 @@ class StringScanner
483
1062
  # rdoc-file=ext/strscan/strscan.c
484
1063
  # - pos()
485
1064
  # -->
486
- # Returns the byte position of the scan pointer. In the 'reset' position, this
487
- # value is zero. In the 'terminated' position (i.e. the string is exhausted),
488
- # this value is the bytesize of the string.
489
- #
490
- # In short, it's a 0-based index into bytes of the string.
491
- #
492
- # s = StringScanner.new('test string')
493
- # s.pos # -> 0
494
- # s.scan_until /str/ # -> "test str"
495
- # s.pos # -> 8
496
- # s.terminate # -> #<StringScanner fin>
497
- # s.pos # -> 11
1065
+ # call-seq:
1066
+ # pos -> byte_position
1067
+ # Returns the integer [byte
1068
+ # position](rdoc-ref:StringScanner@Byte+Position+-28Position-29),
1069
+ # which may be different from the [character
1070
+ # position](rdoc-ref:StringScanner@Character+Position):
1071
+ # scanner = StringScanner.new(HIRAGANA_TEXT)
1072
+ # scanner.string # => "こんにちは"
1073
+ # scanner.pos # => 0
1074
+ # scanner.getch # => "こ" # 3-byte character.
1075
+ # scanner.charpos # => 1
1076
+ # scanner.pos # => 3
498
1077
  #
499
1078
  def pos: () -> Integer
500
1079
 
501
1080
  # <!--
502
1081
  # rdoc-file=ext/strscan/strscan.c
503
- # - pos=(n)
1082
+ # - pos=(p1)
504
1083
  # -->
505
- # Sets the byte position of the scan pointer.
506
- #
507
- # s = StringScanner.new('test string')
508
- # s.pos = 7 # -> 7
509
- # s.rest # -> "ring"
1084
+ # call-seq:
1085
+ # pos = n -> n
1086
+ # pointer = n -> n
1087
+ # Sets the [byte position](rdoc-ref:StringScanner@Byte+Position+-28Position-29)
1088
+ # and the [character position](rdoc-ref:StringScanner@Positions);
1089
+ # returns `n`.
1090
+ # Does not affect [match values](rdoc-ref:StringScanner@Match+Values).
1091
+ # For non-negative `n`, sets the position to `n`:
1092
+ # scanner = StringScanner.new(HIRAGANA_TEXT)
1093
+ # scanner.string # => "こんにちは"
1094
+ # scanner.pos = 3 # => 3
1095
+ # scanner.rest # => "んにちは"
1096
+ # scanner.charpos # => 1
1097
+ #
1098
+ # For negative `n`, counts from the end of the [stored
1099
+ # string](rdoc-ref:StringScanner@Stored+String):
1100
+ # scanner.pos = -9 # => -9
1101
+ # scanner.pos # => 6
1102
+ # scanner.rest # => "にちは"
1103
+ # scanner.charpos # => 2
510
1104
  #
511
1105
  def pos=: (Integer) -> Integer
512
1106
 
513
1107
  # <!--
514
1108
  # rdoc-file=ext/strscan/strscan.c
515
- # - post_match()
1109
+ # - post_match -> substring
516
1110
  # -->
517
- # Returns the ***post**-match* (in the regular expression sense) of the last
518
- # scan.
1111
+ # Returns the substring that follows the matched substring
1112
+ # from the most recent match attempt if it was successful,
1113
+ # or `nil` otherwise;
1114
+ # see [Basic Match Values](rdoc-ref:StringScanner@Basic+Match+Values):
1115
+ # scanner = StringScanner.new('foobarbaz')
1116
+ # scanner.post_match # => nil
519
1117
  #
520
- # s = StringScanner.new('test string')
521
- # s.scan(/\w+/) # -> "test"
522
- # s.scan(/\s+/) # -> " "
523
- # s.pre_match # -> "test"
524
- # s.post_match # -> "string"
1118
+ # scanner.pos = 3
1119
+ # scanner.match?(/bar/) # => 3
1120
+ # scanner.post_match # => "baz"
1121
+ #
1122
+ # scanner.match?(/nope/) # => nil
1123
+ # scanner.post_match # => nil
525
1124
  #
526
1125
  def post_match: () -> String
527
1126
 
528
1127
  # <!--
529
1128
  # rdoc-file=ext/strscan/strscan.c
530
- # - pre_match()
1129
+ # - pre_match -> substring
531
1130
  # -->
532
- # Returns the ***pre**-match* (in the regular expression sense) of the last
533
- # scan.
1131
+ # Returns the substring that precedes the matched substring
1132
+ # from the most recent match attempt if it was successful,
1133
+ # or `nil` otherwise;
1134
+ # see [Basic Match Values](rdoc-ref:StringScanner@Basic+Match+Values):
1135
+ # scanner = StringScanner.new('foobarbaz')
1136
+ # scanner.pre_match # => nil
534
1137
  #
535
- # s = StringScanner.new('test string')
536
- # s.scan(/\w+/) # -> "test"
537
- # s.scan(/\s+/) # -> " "
538
- # s.pre_match # -> "test"
539
- # s.post_match # -> "string"
1138
+ # scanner.pos = 3
1139
+ # scanner.exist?(/baz/) # => 6
1140
+ # scanner.pre_match # => "foobar" # Substring of entire string, not just target string.
1141
+ #
1142
+ # scanner.exist?(/nope/) # => nil
1143
+ # scanner.pre_match # => nil
540
1144
  #
541
1145
  def pre_match: () -> String
542
1146
 
543
1147
  # <!--
544
1148
  # rdoc-file=ext/strscan/strscan.c
545
- # - reset()
1149
+ # - reset -> self
546
1150
  # -->
547
- # Reset the scan pointer (index 0) and clear matching data.
1151
+ # Sets both [byte position](rdoc-ref:StringScanner@Byte+Position+-28Position-29)
1152
+ # and [character position](rdoc-ref:StringScanner@Character+Position) to zero,
1153
+ # and clears [match values](rdoc-ref:StringScanner@Match+Values);
1154
+ # returns `self`:
1155
+ # scanner = StringScanner.new('foobarbaz')
1156
+ # scanner.exist?(/bar/) # => 6
1157
+ # scanner.reset # => #<StringScanner 0/9 @ "fooba...">
1158
+ # put_situation(scanner)
1159
+ # # Situation:
1160
+ # # pos: 0
1161
+ # # charpos: 0
1162
+ # # rest: "foobarbaz"
1163
+ # # rest_size: 9
1164
+ # # => nil
1165
+ # match_values_cleared?(scanner) # => true
548
1166
  #
549
1167
  def reset: () -> void
550
1168
 
551
1169
  # <!--
552
1170
  # rdoc-file=ext/strscan/strscan.c
553
- # - rest()
1171
+ # - rest -> target_substring
554
1172
  # -->
555
- # Returns the "rest" of the string (i.e. everything after the scan pointer). If
556
- # there is no more data (eos? = true), it returns `""`.
1173
+ # Returns the 'rest' of the [stored
1174
+ # string](rdoc-ref:StringScanner@Stored+String) (all after the current
1175
+ # [position](rdoc-ref:StringScanner@Byte+Position+-28Position-29)),
1176
+ # which is the [target substring](rdoc-ref:StringScanner@Target+Substring):
1177
+ # scanner = StringScanner.new('foobarbaz')
1178
+ # scanner.rest # => "foobarbaz"
1179
+ # scanner.pos = 3
1180
+ # scanner.rest # => "barbaz"
1181
+ # scanner.terminate
1182
+ # scanner.rest # => ""
557
1183
  #
558
1184
  def rest: () -> String
559
1185
 
@@ -573,9 +1199,19 @@ class StringScanner
573
1199
 
574
1200
  # <!--
575
1201
  # rdoc-file=ext/strscan/strscan.c
576
- # - rest_size()
1202
+ # - rest_size -> integer
577
1203
  # -->
578
- # `s.rest_size` is equivalent to `s.rest.size`.
1204
+ # Returns the size (in bytes) of the #rest of the [stored
1205
+ # string](rdoc-ref:StringScanner@Stored+String):
1206
+ # scanner = StringScanner.new('foobarbaz')
1207
+ # scanner.rest # => "foobarbaz"
1208
+ # scanner.rest_size # => 9
1209
+ # scanner.pos = 3
1210
+ # scanner.rest # => "barbaz"
1211
+ # scanner.rest_size # => 6
1212
+ # scanner.terminate
1213
+ # scanner.rest # => ""
1214
+ # scanner.rest_size # => 0
579
1215
  #
580
1216
  def rest_size: () -> Integer
581
1217
 
@@ -590,19 +1226,53 @@ class StringScanner
590
1226
 
591
1227
  # <!--
592
1228
  # rdoc-file=ext/strscan/strscan.c
593
- # - scan(pattern) => String
1229
+ # - scan(p1)
594
1230
  # -->
595
- # Tries to match with `pattern` at the current position. If there's a match, the
596
- # scanner advances the "scan pointer" and returns the matched string. Otherwise,
597
- # the scanner returns `nil`.
598
- #
599
- # s = StringScanner.new('test string')
600
- # p s.scan(/\w+/) # -> "test"
601
- # p s.scan(/\w+/) # -> nil
602
- # p s.scan(/\s+/) # -> " "
603
- # p s.scan("str") # -> "str"
604
- # p s.scan(/\w+/) # -> "ing"
605
- # p s.scan(/./) # -> nil
1231
+ # call-seq:
1232
+ # scan(pattern) -> substring or nil
1233
+ # Attempts to [match](rdoc-ref:StringScanner@Matching) the given `pattern`
1234
+ # at the beginning of the [target
1235
+ # substring](rdoc-ref:StringScanner@Target+Substring).
1236
+ # If the match succeeds:
1237
+ # * Returns the matched substring.
1238
+ # * Increments the [byte
1239
+ # position](rdoc-ref:StringScanner@Byte+Position+-28Position-29) by
1240
+ # `substring.bytesize`,
1241
+ # and may increment the [character
1242
+ # position](rdoc-ref:StringScanner@Character+Position).
1243
+ # * Sets [match values](rdoc-ref:StringScanner@Match+Values).
1244
+ # scanner = StringScanner.new(HIRAGANA_TEXT)
1245
+ # scanner.string # => "こんにちは"
1246
+ # scanner.pos = 6
1247
+ # scanner.scan(/に/) # => "に"
1248
+ # put_match_values(scanner)
1249
+ # # Basic match values:
1250
+ # # matched?: true
1251
+ # # matched_size: 3
1252
+ # # pre_match: "こん"
1253
+ # # matched : "に"
1254
+ # # post_match: "ちは"
1255
+ # # Captured match values:
1256
+ # # size: 1
1257
+ # # captures: []
1258
+ # # named_captures: {}
1259
+ # # values_at: ["に", nil]
1260
+ # # []:
1261
+ # # [0]: "に"
1262
+ # # [1]: nil
1263
+ # put_situation(scanner)
1264
+ # # Situation:
1265
+ # # pos: 9
1266
+ # # charpos: 3
1267
+ # # rest: "ちは"
1268
+ # # rest_size: 6
1269
+ #
1270
+ # If the match fails:
1271
+ # * Returns `nil`.
1272
+ # * Does not increment byte and character positions.
1273
+ # * Clears match values.
1274
+ # scanner.scan(/nope/) # => nil
1275
+ # match_values_cleared?(scanner) # => true
606
1276
  #
607
1277
  def scan: (Regexp) -> String?
608
1278
 
@@ -620,16 +1290,54 @@ class StringScanner
620
1290
 
621
1291
  # <!--
622
1292
  # rdoc-file=ext/strscan/strscan.c
623
- # - scan_until(pattern)
1293
+ # - scan_until(p1)
624
1294
  # -->
625
- # Scans the string *until* the `pattern` is matched. Returns the substring up
626
- # to and including the end of the match, advancing the scan pointer to that
627
- # location. If there is no match, `nil` is returned.
628
- #
629
- # s = StringScanner.new("Fri Dec 12 1975 14:39")
630
- # s.scan_until(/1/) # -> "Fri Dec 1"
631
- # s.pre_match # -> "Fri Dec "
632
- # s.scan_until(/XYZ/) # -> nil
1295
+ # call-seq:
1296
+ # scan_until(pattern) -> substring or nil
1297
+ # Attempts to [match](rdoc-ref:StringScanner@Matching) the given `pattern`
1298
+ # anywhere (at any
1299
+ # [position](rdoc-ref:StringScanner@Byte+Position+-28Position-29)) in the
1300
+ # [target substring](rdoc-ref:StringScanner@Target+Substring).
1301
+ # If the match attempt succeeds:
1302
+ # * Sets [match values](rdoc-ref:StringScanner@Match+Values).
1303
+ # * Sets the [byte
1304
+ # position](rdoc-ref:StringScanner@Byte+Position+-28Position-29) to the end
1305
+ # of the matched substring;
1306
+ # may adjust the [character
1307
+ # position](rdoc-ref:StringScanner@Character+Position).
1308
+ # * Returns the matched substring.
1309
+ # scanner = StringScanner.new(HIRAGANA_TEXT)
1310
+ # scanner.string # => "こんにちは"
1311
+ # scanner.pos = 6
1312
+ # scanner.scan_until(/ち/) # => "にち"
1313
+ # put_match_values(scanner)
1314
+ # # Basic match values:
1315
+ # # matched?: true
1316
+ # # matched_size: 3
1317
+ # # pre_match: "こんに"
1318
+ # # matched : "ち"
1319
+ # # post_match: "は"
1320
+ # # Captured match values:
1321
+ # # size: 1
1322
+ # # captures: []
1323
+ # # named_captures: {}
1324
+ # # values_at: ["ち", nil]
1325
+ # # []:
1326
+ # # [0]: "ち"
1327
+ # # [1]: nil
1328
+ # put_situation(scanner)
1329
+ # # Situation:
1330
+ # # pos: 12
1331
+ # # charpos: 4
1332
+ # # rest: "は"
1333
+ # # rest_size: 3
1334
+ #
1335
+ # If the match attempt fails:
1336
+ # * Clears match data.
1337
+ # * Returns `nil`.
1338
+ # * Does not update positions.
1339
+ # scanner.scan_until(/nope/) # => nil
1340
+ # match_values_cleared?(scanner) # => true
633
1341
  #
634
1342
  def scan_until: (Regexp) -> String?
635
1343
 
@@ -646,110 +1354,237 @@ class StringScanner
646
1354
 
647
1355
  # <!--
648
1356
  # rdoc-file=ext/strscan/strscan.c
649
- # - size
1357
+ # - size -> captures_count
650
1358
  # -->
651
- # Returns the amount of subgroups in the most recent match. The full match
652
- # counts as a subgroup.
1359
+ # Returns the count of captures if the most recent match attempt succeeded,
1360
+ # `nil` otherwise;
1361
+ # see [Captures Match Values](rdoc-ref:StringScanner@Captured+Match+Values):
1362
+ # scanner = StringScanner.new('Fri Dec 12 1975 14:39')
1363
+ # scanner.size # => nil
1364
+ #
1365
+ # pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) /
1366
+ # scanner.match?(pattern)
1367
+ # scanner.values_at(*0..scanner.size) # => ["Fri Dec 12 ", "Fri", "Dec", "12", nil]
1368
+ # scanner.size # => 4
653
1369
  #
654
- # s = StringScanner.new("Fri Dec 12 1975 14:39")
655
- # s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
656
- # s.size # -> 4
1370
+ # scanner.match?(/nope/) # => nil
1371
+ # scanner.size # => nil
657
1372
  #
658
1373
  def size: () -> Integer
659
1374
 
660
1375
  # <!--
661
1376
  # rdoc-file=ext/strscan/strscan.c
662
- # - skip(pattern)
1377
+ # - skip(p1)
663
1378
  # -->
664
- # Attempts to skip over the given `pattern` beginning with the scan pointer. If
665
- # it matches, the scan pointer is advanced to the end of the match, and the
666
- # length of the match is returned. Otherwise, `nil` is returned.
667
- #
668
- # It's similar to #scan, but without returning the matched string.
669
- #
670
- # s = StringScanner.new('test string')
671
- # p s.skip(/\w+/) # -> 4
672
- # p s.skip(/\w+/) # -> nil
673
- # p s.skip(/\s+/) # -> 1
674
- # p s.skip("st") # -> 2
675
- # p s.skip(/\w+/) # -> 4
676
- # p s.skip(/./) # -> nil
1379
+ # call-seq:
1380
+ # skip(pattern) match_size or nil
1381
+ # Attempts to [match](rdoc-ref:StringScanner@Matching) the given `pattern`
1382
+ # at the beginning of the [target
1383
+ # substring](rdoc-ref:StringScanner@Target+Substring);
1384
+ # If the match succeeds:
1385
+ # * Increments the [byte
1386
+ # position](rdoc-ref:StringScanner@Byte+Position+-28Position-29) by
1387
+ # substring.bytesize,
1388
+ # and may increment the [character
1389
+ # position](rdoc-ref:StringScanner@Character+Position).
1390
+ # * Sets [match values](rdoc-ref:StringScanner@Match+Values).
1391
+ # * Returns the size (bytes) of the matched substring.
1392
+ # scanner = StringScanner.new(HIRAGANA_TEXT)
1393
+ # scanner.string # => "こんにちは"
1394
+ # scanner.pos = 6
1395
+ # scanner.skip(/に/) # => 3
1396
+ # put_match_values(scanner)
1397
+ # # Basic match values:
1398
+ # # matched?: true
1399
+ # # matched_size: 3
1400
+ # # pre_match: "こん"
1401
+ # # matched : "に"
1402
+ # # post_match: "ちは"
1403
+ # # Captured match values:
1404
+ # # size: 1
1405
+ # # captures: []
1406
+ # # named_captures: {}
1407
+ # # values_at: ["に", nil]
1408
+ # # []:
1409
+ # # [0]: "に"
1410
+ # # [1]: nil
1411
+ # put_situation(scanner)
1412
+ # # Situation:
1413
+ # # pos: 9
1414
+ # # charpos: 3
1415
+ # # rest: "ちは"
1416
+ # # rest_size: 6
1417
+ #
1418
+ # scanner.skip(/nope/) # => nil
1419
+ # match_values_cleared?(scanner) # => true
677
1420
  #
678
1421
  def skip: (Regexp) -> Integer?
679
1422
 
680
1423
  # <!--
681
1424
  # rdoc-file=ext/strscan/strscan.c
682
- # - skip_until(pattern)
1425
+ # - skip_until(p1)
683
1426
  # -->
684
- # Advances the scan pointer until `pattern` is matched and consumed. Returns
685
- # the number of bytes advanced, or `nil` if no match was found.
686
- #
687
- # Look ahead to match `pattern`, and advance the scan pointer to the *end* of
688
- # the match. Return the number of characters advanced, or `nil` if the match
689
- # was unsuccessful.
690
- #
691
- # It's similar to #scan_until, but without returning the intervening string.
692
- #
693
- # s = StringScanner.new("Fri Dec 12 1975 14:39")
694
- # s.skip_until /12/ # -> 10
695
- # s #
1427
+ # call-seq:
1428
+ # skip_until(pattern) -> matched_substring_size or nil
1429
+ # Attempts to [match](rdoc-ref:StringScanner@Matching) the given `pattern`
1430
+ # anywhere (at any
1431
+ # [position](rdoc-ref:StringScanner@Byte+Position+-28Position-29)) in the
1432
+ # [target substring](rdoc-ref:StringScanner@Target+Substring);
1433
+ # does not modify the positions.
1434
+ # If the match attempt succeeds:
1435
+ # * Sets [match values](rdoc-ref:StringScanner@Match+Values).
1436
+ # * Returns the size of the matched substring.
1437
+ # scanner = StringScanner.new(HIRAGANA_TEXT)
1438
+ # scanner.string # => "こんにちは"
1439
+ # scanner.pos = 6
1440
+ # scanner.skip_until(/ち/) # => 6
1441
+ # put_match_values(scanner)
1442
+ # # Basic match values:
1443
+ # # matched?: true
1444
+ # # matched_size: 3
1445
+ # # pre_match: "こんに"
1446
+ # # matched : "ち"
1447
+ # # post_match: "は"
1448
+ # # Captured match values:
1449
+ # # size: 1
1450
+ # # captures: []
1451
+ # # named_captures: {}
1452
+ # # values_at: ["ち", nil]
1453
+ # # []:
1454
+ # # [0]: "ち"
1455
+ # # [1]: nil
1456
+ # put_situation(scanner)
1457
+ # # Situation:
1458
+ # # pos: 12
1459
+ # # charpos: 4
1460
+ # # rest: "は"
1461
+ # # rest_size: 3
1462
+ #
1463
+ # If the match attempt fails:
1464
+ # * Clears match values.
1465
+ # * Returns `nil`.
1466
+ # scanner.skip_until(/nope/) # => nil
1467
+ # match_values_cleared?(scanner) # => true
696
1468
  #
697
1469
  def skip_until: (Regexp) -> Integer?
698
1470
 
699
1471
  # <!--
700
1472
  # rdoc-file=ext/strscan/strscan.c
701
- # - string()
1473
+ # - string -> stored_string
702
1474
  # -->
703
- # Returns the string being scanned.
1475
+ # Returns the [stored string](rdoc-ref:StringScanner@Stored+String):
1476
+ # scanner = StringScanner.new('foobar')
1477
+ # scanner.string # => "foobar"
1478
+ # scanner.concat('baz')
1479
+ # scanner.string # => "foobarbaz"
704
1480
  #
705
1481
  def string: () -> String
706
1482
 
707
1483
  # <!--
708
1484
  # rdoc-file=ext/strscan/strscan.c
709
- # - string=(str)
1485
+ # - string = other_string -> other_string
710
1486
  # -->
711
- # Changes the string being scanned to `str` and resets the scanner. Returns
712
- # `str`.
1487
+ # Replaces the [stored string](rdoc-ref:StringScanner@Stored+String) with the
1488
+ # given `other_string`:
1489
+ # * Sets both [positions](rdoc-ref:StringScanner@Positions) to zero.
1490
+ # * Clears [match values](rdoc-ref:StringScanner@Match+Values).
1491
+ # * Returns `other_string`.
1492
+ # scanner = StringScanner.new('foobar')
1493
+ # scanner.scan(/foo/)
1494
+ # put_situation(scanner)
1495
+ # # Situation:
1496
+ # # pos: 3
1497
+ # # charpos: 3
1498
+ # # rest: "bar"
1499
+ # # rest_size: 3
1500
+ # match_values_cleared?(scanner) # => false
1501
+ #
1502
+ # scanner.string = 'baz' # => "baz"
1503
+ # put_situation(scanner)
1504
+ # # Situation:
1505
+ # # pos: 0
1506
+ # # charpos: 0
1507
+ # # rest: "baz"
1508
+ # # rest_size: 3
1509
+ # match_values_cleared?(scanner) # => true
713
1510
  #
714
1511
  def string=: (String) -> String
715
1512
 
716
1513
  # <!--
717
1514
  # rdoc-file=ext/strscan/strscan.c
718
- # - terminate
719
- # - clear
1515
+ # - terminate()
720
1516
  # -->
721
- # Sets the scan pointer to the end of the string and clear matching data.
1517
+ # call-seq:
1518
+ # terminate -> self
1519
+ # Sets the scanner to end-of-string;
1520
+ # returns `self`:
1521
+ # * Sets both [positions](rdoc-ref:StringScanner@Positions) to end-of-stream.
1522
+ # * Clears [match values](rdoc-ref:StringScanner@Match+Values).
1523
+ # scanner = StringScanner.new(HIRAGANA_TEXT)
1524
+ # scanner.string # => "こんにちは"
1525
+ # scanner.scan_until(/に/)
1526
+ # put_situation(scanner)
1527
+ # # Situation:
1528
+ # # pos: 9
1529
+ # # charpos: 3
1530
+ # # rest: "ちは"
1531
+ # # rest_size: 6
1532
+ # match_values_cleared?(scanner) # => false
1533
+ #
1534
+ # scanner.terminate # => #<StringScanner fin>
1535
+ # put_situation(scanner)
1536
+ # # Situation:
1537
+ # # pos: 15
1538
+ # # charpos: 5
1539
+ # # rest: ""
1540
+ # # rest_size: 0
1541
+ # match_values_cleared?(scanner) # => true
722
1542
  #
723
1543
  def terminate: () -> void
724
1544
 
725
1545
  # <!--
726
1546
  # rdoc-file=ext/strscan/strscan.c
727
- # - unscan()
1547
+ # - unscan -> self
728
1548
  # -->
729
- # Sets the scan pointer to the previous position. Only one previous position is
730
- # remembered, and it changes with each scanning operation.
731
- #
732
- # s = StringScanner.new('test string')
733
- # s.scan(/\w+/) # => "test"
734
- # s.unscan
735
- # s.scan(/../) # => "te"
736
- # s.scan(/\d/) # => nil
737
- # s.unscan # ScanError: unscan failed: previous match record not exist
1549
+ # Sets the [position](rdoc-ref:StringScanner@Byte+Position+-28Position-29) to
1550
+ # its value previous to the recent successful
1551
+ # [match](rdoc-ref:StringScanner@Matching) attempt:
1552
+ # scanner = StringScanner.new('foobarbaz')
1553
+ # scanner.scan(/foo/)
1554
+ # put_situation(scanner)
1555
+ # # Situation:
1556
+ # # pos: 3
1557
+ # # charpos: 3
1558
+ # # rest: "barbaz"
1559
+ # # rest_size: 6
1560
+ # scanner.unscan
1561
+ # # => #<StringScanner 0/9 @ "fooba...">
1562
+ # put_situation(scanner)
1563
+ # # Situation:
1564
+ # # pos: 0
1565
+ # # charpos: 0
1566
+ # # rest: "foobarbaz"
1567
+ # # rest_size: 9
1568
+ #
1569
+ # Raises an exception if match values are clear:
1570
+ # scanner.scan(/nope/) # => nil
1571
+ # match_values_cleared?(scanner) # => true
1572
+ # scanner.unscan # Raises StringScanner::Error.
738
1573
  #
739
1574
  def unscan: () -> void
740
1575
 
741
1576
  # <!--
742
1577
  # rdoc-file=ext/strscan/strscan.c
743
- # - scanner.values_at( i1, i2, ... iN ) -> an_array
1578
+ # - values_at(*specifiers) -> array_of_captures or nil
744
1579
  # -->
745
- # Returns the subgroups in the most recent match at the given indices. If
746
- # nothing was priorly matched, it returns nil.
747
- #
748
- # s = StringScanner.new("Fri Dec 12 1975 14:39")
749
- # s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
750
- # s.values_at 0, -1, 5, 2 # -> ["Fri Dec 12 ", "12", nil, "Dec"]
751
- # s.scan(/(\w+) (\w+) (\d+) /) # -> nil
752
- # s.values_at 0, -1, 5, 2 # -> nil
1580
+ # Returns an array of captured substrings, or `nil` of none.
1581
+ # For each `specifier`, the returned substring is `[specifier]`;
1582
+ # see #[].
1583
+ # scanner = StringScanner.new('Fri Dec 12 1975 14:39')
1584
+ # pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) /
1585
+ # scanner.match?(pattern)
1586
+ # scanner.values_at(*0..3) # => ["Fri Dec 12 ", "Fri", "Dec", "12"]
1587
+ # scanner.values_at(*%i[wday month day]) # => ["Fri", "Dec", "12"]
753
1588
  #
754
1589
  def values_at: (*Integer) -> Array[String]?
755
1590
 
@@ -757,24 +1592,32 @@ class StringScanner
757
1592
 
758
1593
  # <!--
759
1594
  # rdoc-file=ext/strscan/strscan.c
760
- # - StringScanner.new(string, fixed_anchor: false)
761
- # - StringScanner.new(string, dup = false)
1595
+ # - StringScanner.new(string, fixed_anchor: false) -> string_scanner
762
1596
  # -->
763
- # Creates a new StringScanner object to scan over the given `string`.
764
- #
765
- # If `fixed_anchor` is `true`, `\A` always matches the beginning of the string.
766
- # Otherwise, `\A` always matches the current position.
767
- #
768
- # `dup` argument is obsolete and not used now.
1597
+ # Returns a new `StringScanner` object whose [stored
1598
+ # string](rdoc-ref:StringScanner@Stored+String)
1599
+ # is the given `string`;
1600
+ # sets the [fixed-anchor
1601
+ # property](rdoc-ref:StringScanner@Fixed-Anchor+Property):
1602
+ # scanner = StringScanner.new('foobarbaz')
1603
+ # scanner.string # => "foobarbaz"
1604
+ # scanner.fixed_anchor? # => false
1605
+ # put_situation(scanner)
1606
+ # # Situation:
1607
+ # # pos: 0
1608
+ # # charpos: 0
1609
+ # # rest: "foobarbaz"
1610
+ # # rest_size: 9
769
1611
  #
770
1612
  def initialize: (String, ?bool dup, ?fixed_anchor: bool) -> untyped
771
1613
 
772
1614
  # <!--
773
1615
  # rdoc-file=ext/strscan/strscan.c
774
- # - dup
775
- # - clone
1616
+ # - dup -> shallow_copy
776
1617
  # -->
777
- # Duplicates a StringScanner object.
1618
+ # Returns a shallow copy of `self`;
1619
+ # the [stored string](rdoc-ref:StringScanner@Stored+String) in the copy is the
1620
+ # same string as in `self`.
778
1621
  #
779
1622
  def initialize_copy: (StringScanner) -> void
780
1623
  end