i18n-inflector-3 3.0.0

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.
@@ -0,0 +1,352 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Author:: Paweł Wilk (mailto:pw@gnu.org)
5
+ # Copyright:: (c) 2011,2012,2013 by Paweł Wilk
6
+ # License:: This program is licensed under the terms of {file:docs/LGPL GNU Lesser General Public License} or {file:docs/COPYING Ruby License}.
7
+ #
8
+ # This file contains I18n::Backend::Inflector module,
9
+ # which extends I18n::Backend::Simple by adding the ability
10
+ # to interpolate patterns containing inflection tokens
11
+ # defined in translation data.
12
+
13
+ module I18n
14
+ # @abstract This namespace is shared with I18n subsystem.
15
+ module Backend
16
+ # This module contains methods that add
17
+ # tokenized inflection support to internal I18n classes.
18
+ # It is intened to be included in the Simple backend
19
+ # module so that it will patch translate method in order
20
+ # to interpolate additional inflection tokens present in translations.
21
+ # Usually you don't have to know what's here to use it.
22
+ module Inflector
23
+ # Shortcut to configuration module.
24
+ InflectorCfg = I18n::Inflector::Config
25
+
26
+ # This accessor allows to reach API methods of the
27
+ # inflector object associated with this class.
28
+ def inflector
29
+ inflector_try_init
30
+ @inflector
31
+ end
32
+
33
+ # Cleans up internal hashes containg kinds, inflections and aliases.
34
+ #
35
+ # @api public
36
+ # @note It calls {I18n::Backend::Simple#reload! I18n::Backend::Simple#reload!}
37
+ # @return [Boolean] the result of calling ancestor's method
38
+ def reload!
39
+ @inflector = nil
40
+ super
41
+ end
42
+
43
+ # Translates given key taking care of inflections.
44
+ #
45
+ # @api public
46
+ # @see I18n::Inflector::API#interpolate
47
+ # @see I18n::Inflector::InflectionOptions
48
+ # @param [Symbol] locale locale
49
+ # @param [Symbol,String] key translation key
50
+ # @param [Hash] options a set of options to pass to the translation routines.
51
+ # @note The given +options+ along with a translated string and the given
52
+ # +locale+ are passed to
53
+ # {I18n::Backend::Simple#translate I18n::Backend::Simple#translate}
54
+ # and then the result is processed by {I18n::Inflector::API#interpolate}
55
+ # @return [String] the translated string with interpolated patterns
56
+ def translate(locale, key, options = {})
57
+ inflector_try_init
58
+
59
+ # take care about cache-awareness
60
+ cached = if options.key?(:inflector_cache_aware)
61
+ options[:inflector_cache_aware]
62
+ else
63
+ @inflector.options.cache_aware
64
+ end
65
+
66
+ if cached
67
+ interpolate_options = options
68
+ @inflector.options.prepare_options!(options)
69
+ else
70
+ interpolate_options = options.dup
71
+ @inflector.options.clean_for_translate!(options)
72
+ end
73
+
74
+ # translate string using original translate
75
+ translated_string = super
76
+
77
+ # generate a pattern from key-based inflection object
78
+ if translated_string.is_a?(Hash) && key.to_s[0..0] == InflectorCfg::Markers::STRICT_KIND
79
+ translated_string = @inflector.key_to_pattern(translated_string)
80
+ end
81
+
82
+ # interpolate string
83
+ begin
84
+ @inflector.options.prepare_options!(interpolate_options) unless cached
85
+ @inflector.interpolate(translated_string, locale, interpolate_options)
86
+
87
+ # complete the exception by adding translation key
88
+ rescue I18n::InflectionException => e
89
+ e.key = key
90
+ raise
91
+ end
92
+ end
93
+
94
+ # Stores translations in memory.
95
+ #
96
+ # @api public
97
+ # @raise [I18n::InvalidLocale] if the given +locale+ is invalid
98
+ # @raise [I18n::BadInflectionToken] if a name of some loaded token is invalid
99
+ # @raise [I18n::BadInflectionAlias] if a loaded alias points to a token that does not exists
100
+ # @raise [I18n::BadInflectionKind] if a loaded kind identifier is invalid
101
+ # @raise [I18n::DuplicatedInflectionToken] if a token has already appeard in loaded configuration
102
+ # @note If inflections are changed it will regenerate proper internal
103
+ # structures.
104
+ # @return [Hash] the stored translations
105
+ def store_translations(locale, data, options = {})
106
+ r = super
107
+ inflector_try_init
108
+ if data.respond_to?(:has_key?)
109
+ subdata = data[:i18n] || data['i18n']
110
+ unless subdata.nil?
111
+ subdata = subdata[:inflections] || subdata['inflections']
112
+ unless subdata.nil?
113
+ db, db_strict = load_inflection_tokens(locale, r[:i18n][:inflections])
114
+ @inflector.add_database(db, db_strict)
115
+ end
116
+ end
117
+ end
118
+ r
119
+ end
120
+
121
+ protected
122
+
123
+ # Initializes internal hashes used for keeping inflections configuration.
124
+ #
125
+ # @return [void]
126
+ def inflector_try_init
127
+ return if defined?(@inflector) && !@inflector.nil?
128
+
129
+ @inflector = I18n::Inflector::API.new
130
+ init_translations unless initialized?
131
+ end
132
+
133
+ # Takes care of loading inflection tokens
134
+ # for all languages (locales) that have them
135
+ # defined.
136
+ #
137
+ # @note It calls {I18n::Backend::Simple#init_translations I18n::Backend::Simple#init_translations}
138
+ # @raise [I18n::BadInflectionToken] if a name of some loaded token is invalid
139
+ # @raise [I18n::BadInflectionAlias] if a loaded alias points to a token that does not exists
140
+ # @raise [I18n::BadInflectionKind] if a loaded kind identifier is invalid
141
+ # @raise [I18n::DuplicatedInflectionToken] if a token has already appeard in loaded configuration
142
+ # @return [Boolean] +true+ if everything went fine
143
+ def init_translations
144
+ @inflector = I18n::Inflector::API.new unless defined?(@inflector) && !@inflector.nil?
145
+ super
146
+ end
147
+
148
+ # Gives an access to the internal structure containing configuration data
149
+ # for the given locale.
150
+ #
151
+ # @note Under some very rare conditions this method may be called while
152
+ # translation data is loading. It must always return when translations
153
+ # are not initialized. Otherwise it will cause loops and someone in Poland
154
+ # will eat a kittien!
155
+ # @param [Symbol] locale the locale to use
156
+ # @return [Hash,nil] part of the translation data that
157
+ # reflects inflections for the given locale or +nil+
158
+ # if translations are not initialized
159
+ def inflection_subtree(locale)
160
+ return nil unless initialized?
161
+
162
+ lookup(locale, :'i18n.inflections', [], fallback: true, raise: false)
163
+ end
164
+
165
+ # Resolves an alias for a token if the given +token+ is an alias.
166
+ #
167
+ # @note It does take care of aliasing loops (max traverses is set to 64).
168
+ # @raise [I18n::BadInflectionToken] if a name of the token that alias points to is corrupted
169
+ # @raise [I18n::BadInflectionAlias] if an alias points to token that does not exists
170
+ # @return [Symbol] the true token that alias points to if the given +token+
171
+ # is an alias or the given +token+ if it is a true token
172
+ # @overload shorten_inflection_alias(token, kind, locale)
173
+ # Resolves an alias for a token if the given +token+ is an alias for the given +locale+ and +kind+.
174
+ # @note This version uses internal subtree and needs the translation data to be initialized.
175
+ # @param [Symbol] token the token name
176
+ # @param [Symbol] kind the kind of the given token
177
+ # @param [Symbol] locale the locale to use
178
+ # @return [Symbol] the true token that alias points to if the given +token+
179
+ # is an alias or the given +token+ if it is a true token
180
+ # @overload shorten_inflection_alias(token, kind, locale, subtree)
181
+ # Resolves an alias for a token if the given +token+ is an alias for the given +locale+ and +kind+.
182
+ # @param [Symbol] token the token name
183
+ # @param [Symbol] kind the kind of the given token
184
+ # @param [Symbol] locale the locale to use
185
+ # @param [Hash] subtree the tree (in a form of nested Hashes) containing inflection tokens to scan
186
+ # @return [Symbol] the true token that alias points to if the given +token+
187
+ # is an alias or the given +token+ if it is a true token
188
+ def shorten_inflection_alias(token, kind, locale, subtree = nil, count = 0)
189
+ count += 1
190
+ return nil if count > 64
191
+
192
+ inflections_tree = subtree || inflection_subtree(locale)
193
+ return nil if inflections_tree.nil? || inflections_tree.empty?
194
+
195
+ kind_subtree = inflections_tree[kind]
196
+ value = kind_subtree[token].to_s
197
+
198
+ if value[0..0] == InflectorCfg::Markers::ALIAS
199
+ orig_token = token
200
+ token = value[1..]
201
+
202
+ raise I18n::BadInflectionToken.new(locale, token, kind) if InflectorCfg::Reserved::Tokens.invalid?(token, :DB)
203
+
204
+ token = token.to_sym
205
+ raise BadInflectionAlias.new(locale, orig_token, kind, token) if kind_subtree[token].nil?
206
+
207
+ shorten_inflection_alias(token, kind, locale, inflections_tree, count)
208
+
209
+ else
210
+ return token if kind_subtree.key?(token)
211
+
212
+ raise I18n::BadInflectionToken.new(locale, token, kind)
213
+
214
+ end
215
+ end
216
+
217
+ # Uses the inflections subtree and creates internal mappings
218
+ # to resolve kinds assigned to inflection tokens and aliases, including defaults.
219
+ # @return [I18n::Inflector::InflectionData,nil] the database containing inflections tokens
220
+ # or +nil+ if something went wrong
221
+ # @raise [I18n::BadInflectionToken] if a token identifier is invalid
222
+ # @raise [I18n::BadInflectionKind] if a kind identifier is invalid
223
+ # @raise [I18n::BadInflectionAlias] if a loaded alias points to a token that does not exists
224
+ # @raise [I18n::DuplicatedInflectionToken] if a token has already appeard in loaded configuration
225
+ # @overload load_inflection_tokens(locale)
226
+ # @note That version calls the {inflection_subtree} method to obtain internal translations data.
227
+ # Loads inflection tokens for the given locale using internal hash of stored translations. Requires
228
+ # translations to be initialized.
229
+ # @param [Symbol] locale the locale to use and work for
230
+ # @return [I18n::Inflector::InflectionData,nil] the database containing inflections tokens
231
+ # or +nil+ if something went wrong
232
+ # @overload load_inflection_tokens(locale, subtree)
233
+ # Loads inflection tokens for the given locale using datthe given in an argument
234
+ # @param [Symbol] locale the locale to use and work for
235
+ # @param [Hash] subtree the tree (in a form of nested Hashes) containing inflection tokens to scan
236
+ # @return [I18n::Inflector::InflectionData,nil] the database containing inflections tokens
237
+ # or +nil+ if something went wrong
238
+ def load_inflection_tokens(locale, subtree = nil)
239
+ inflections_tree = subtree || inflection_subtree(locale)
240
+ return nil if inflections_tree.nil? || inflections_tree.empty?
241
+
242
+ inflections_tree = deep_symbolize(inflections_tree)
243
+
244
+ idb = I18n::Inflector::InflectionData.new(locale)
245
+ idb_strict = I18n::Inflector::InflectionData_Strict.new(locale)
246
+
247
+ return nil if idb.nil? || idb_strict.nil?
248
+
249
+ inflections = prepare_inflections(locale, inflections_tree, idb, idb_strict)
250
+
251
+ # add inflection tokens and kinds to internal database
252
+ inflections.each do |orig_kind, kind, strict_kind, subdb, tokens|
253
+ # validate token's kind
254
+ if kind.to_s.empty? || InflectorCfg::Reserved::Kinds.invalid?(orig_kind, :DB)
255
+ raise I18n::BadInflectionKind.new(locale, orig_kind)
256
+ end
257
+
258
+ tokens.each_pair do |token, description|
259
+ # test for duplicate
260
+ if subdb.has_token?(token, strict_kind)
261
+ raise I18n::DuplicatedInflectionToken.new(locale, token, orig_kind,
262
+ subdb.get_kind(token, strict_kind))
263
+ end
264
+
265
+ # validate token's name
266
+ if InflectorCfg::Reserved::Tokens.invalid?(token, :DB)
267
+ raise I18n::BadInflectionToken.new(locale, token, orig_kind)
268
+ end
269
+
270
+ # validate token's description
271
+ if description.nil?
272
+ raise I18n::BadInflectionToken.new(locale, token, orig_kind, description)
273
+ elsif description.to_s[0..0] == InflectorCfg::Markers::ALIAS
274
+ next
275
+ end
276
+
277
+ # skip default token for later processing
278
+ next if token == :default
279
+
280
+ subdb.add_token(token, kind, description)
281
+ end
282
+ end
283
+
284
+ # handle aliases
285
+ inflections.each do |orig_kind, kind, _strict_kind, subdb, tokens|
286
+ tokens.each_pair do |token, description|
287
+ next if token == :default
288
+ next if description.to_s[0..0] != InflectorCfg::Markers::ALIAS
289
+
290
+ real_token = shorten_inflection_alias(token, orig_kind, locale, inflections_tree)
291
+ subdb.add_alias(token, real_token, kind) unless real_token.nil?
292
+ end
293
+
294
+ # handle default tokens
295
+ next unless tokens.key?(:default)
296
+
297
+ if subdb.has_default_token?(kind)
298
+ raise I18n::DuplicatedInflectionToken.new(locale, :default, kind,
299
+ orig_kind)
300
+ end
301
+
302
+ orig_target = tokens[:default]
303
+ target = orig_target.to_s
304
+ target = target[1..] if target[0..0] == InflectorCfg::Markers::ALIAS
305
+ raise I18n::BadInflectionToken.new(locale, token, orig_kind, orig_target) if target.empty?
306
+
307
+ target = subdb.get_true_token(target.to_sym, kind)
308
+ raise I18n::BadInflectionAlias.new(locale, :default, orig_kind, orig_target) if target.nil?
309
+
310
+ subdb.set_default_token(kind, target)
311
+ end
312
+
313
+ [idb, idb_strict]
314
+ end
315
+
316
+ # @private
317
+ def prepare_inflections(locale, inflections, idb, idb_strict)
318
+ raise I18n::BadInflectionKind.new(locale, :INFLECTIONS_ROOT) unless inflections.respond_to?(:has_key?)
319
+
320
+ I18n::Inflector::LazyHashEnumerator.for(inflections).ary_map do |kind, tokens|
321
+ next if tokens.nil? || tokens.empty?
322
+ raise I18n::BadInflectionKind.new(locale, kind) unless tokens.respond_to?(:has_key?)
323
+
324
+ subdb = idb
325
+ strict_kind = nil
326
+ orig_kind = kind
327
+ if kind.to_s[0..0] == InflectorCfg::Markers::STRICT_KIND
328
+ kind = kind.to_s[1..]
329
+ next if kind.empty?
330
+
331
+ kind = kind.to_sym
332
+ subdb = idb_strict
333
+ strict_kind = kind
334
+ end
335
+ [orig_kind, kind, strict_kind, subdb, tokens]
336
+ end
337
+ end
338
+
339
+ # @private
340
+ def deep_symbolize(obj)
341
+ obj.each_with_object({}) do |(key, value), result|
342
+ value = deep_symbolize(value) if value.is_a?(Hash)
343
+ result[begin
344
+ key.to_s.to_sym
345
+ rescue StandardError
346
+ key
347
+ end || key] = value
348
+ end
349
+ end
350
+ end
351
+ end
352
+ end
@@ -0,0 +1,289 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Author:: Paweł Wilk (mailto:pw@gnu.org)
5
+ # Copyright:: (c) 2011,2012,2013 by Paweł Wilk
6
+ # License:: This program is licensed under the terms of {file:docs/LGPL GNU Lesser General Public License} or {file:docs/COPYING Ruby License}.
7
+ #
8
+ # This file contains configuration of I18n::Inflector module.
9
+
10
+ module I18n
11
+ module Inflector
12
+ # This module contains submodules and module
13
+ # methods for handling global configuration
14
+ # of the engine.
15
+ module Config
16
+ # @private
17
+ def get_i18n_reserved_keys
18
+ return I18n::RESERVED_KEYS if defined?(I18n::RESERVED_KEYS)
19
+ return I18n::Backend::Base::RESERVED_KEYS if defined?(I18n::Backend::Base::RESERVED_KEYS)
20
+ return I18n::Backend::Simple::RESERVED_KEYS if defined?(I18n::Backend::Simple::RESERVED_KEYS)
21
+ return RESERVED_KEYS if defined?(RESERVED_KEYS)
22
+
23
+ []
24
+ end
25
+ module_function :get_i18n_reserved_keys
26
+
27
+ # @private
28
+ def all_consts(obj, f = String)
29
+ obj.constants.filter_map do |c|
30
+ v = obj.const_get(c)
31
+ (v.is_a?(f) && c != 'ALL') ? v : nil
32
+ end.uniq
33
+ end
34
+ module_function :all_consts
35
+
36
+ # @private
37
+ def gen_regexp(ary)
38
+ ::Regexp.new "[#{ary.join}]"
39
+ end
40
+ module_function :gen_regexp
41
+
42
+ # Prefix that makes option a controlling option.
43
+ OPTION_PREFIX = InflectionOptions::OPTION_PREFIX
44
+
45
+ # Regexp matching a prefix that makes option
46
+ # a controlling option.
47
+ OPTION_PREFIX_REGEXP = Regexp.new("^#{OPTION_PREFIX}")
48
+
49
+ # This module contains keys that have special
50
+ # meaning.
51
+ module Keys
52
+ # A Symbol that is used to mark default token
53
+ # in configuration and in options.
54
+ DEFAULT_TOKEN = :default
55
+
56
+ # All keys
57
+ ALL = HSet.new Config.all_consts(self, Symbol)
58
+ end
59
+
60
+ # This module contains characters that are markers
61
+ # giving the shape for a pattern and its elements.
62
+ module Markers
63
+ # A character that is used to mark pattern.
64
+ PATTERN = '@'
65
+
66
+ # A character that is used to mark a strict kind.
67
+ STRICT_KIND = '@'
68
+
69
+ # A character that is used to open a pattern.
70
+ PATTERN_BEGIN = '{'
71
+
72
+ # A character that ends a pattern.
73
+ PATTERN_END = '}'
74
+
75
+ # A character that indicates an alias.
76
+ ALIAS = '@'
77
+
78
+ # A character used to mark token value as loud.
79
+ LOUD_VALUE = '~'
80
+
81
+ # All markers.
82
+ ALL = Config.all_consts(self)
83
+ end
84
+
85
+ module Escapes
86
+ # A general esape symbol.
87
+ ESCAPE = '\\'
88
+
89
+ # A regular expression that catches escape symbols.
90
+ ESCAPE_R = /\\([^\\])/
91
+
92
+ # A list of escape symbols that cause a pattern to be escaped.
93
+ PATTERN = HSet[Markers::PATTERN, Escapes::ESCAPE]
94
+ end
95
+
96
+ # This module contains constants that define
97
+ # operators in patterns.
98
+ module Operators
99
+ # This module contains constants that define
100
+ # operators in patterns that handle token
101
+ # groups or tokens.
102
+ module Tokens
103
+ # A character used to mark patterns as complex
104
+ # and to separate token groups assigned to different
105
+ # strict kinds.
106
+ AND = '+'
107
+
108
+ # A character that is used to separate tokens
109
+ # or token groups within a pattern.
110
+ OR = '|'
111
+
112
+ # A character used to assign value to a token
113
+ # or a group of tokens.
114
+ ASSIGN = ':'
115
+
116
+ # A character used to create a virtual token
117
+ # that always matches.
118
+ WILDCARD = '*'
119
+
120
+ # All token groups operators.
121
+ ALL = Config.all_consts(self)
122
+ end
123
+
124
+ # This module contains constants that are operators
125
+ # in patterns that handle token groups or tokens.
126
+ module Token
127
+ # A character used to separate multiple tokens.
128
+ OR = ','
129
+
130
+ # A character used to mark tokens as negative.
131
+ NOT = '!'
132
+
133
+ # All token operators.
134
+ ALL = Config.all_consts(self)
135
+ end
136
+
137
+ # All operators.
138
+ ALL = Tokens::ALL | Token::ALL
139
+ end
140
+
141
+ # This module contains constants defining
142
+ # reserved characters in tokens and kinds.
143
+ module Reserved
144
+ # Reserved keys.
145
+ KEYS = HSet.new(
146
+ Config.get_i18n_reserved_keys +
147
+ Config::Keys::ALL.to_a +
148
+ InflectionOptions.known.values
149
+ )
150
+
151
+ # This module contains constants defining
152
+ # reserved characters in token identifiers.
153
+ module Tokens
154
+ # Reserved characters in token identifiers placed in configuration.
155
+ DB = (Operators::ALL | Markers::ALL) - [Markers::LOUD_VALUE]
156
+
157
+ # Reserved characters in token identifiers passed as options.
158
+ OPTION = DB
159
+
160
+ # Reserved characters in token identifiers placed in patterns.
161
+ PATTERN = OPTION - [Operators::Tokens::WILDCARD]
162
+
163
+ # This module contains constants defining
164
+ # regular expressions for reserved characters
165
+ # in token identifiers.
166
+ module Regexp
167
+ # Reserved characters in token identifiers placed in configuration.
168
+ DB = Config.gen_regexp Tokens::DB
169
+
170
+ # Reserved characters in token identifiers passed as options.
171
+ OPTION = Config.gen_regexp Tokens::OPTION
172
+
173
+ # Reserved characters in token identifiers placed in patterns.
174
+ PATTERN = Config.gen_regexp Tokens::PATTERN
175
+ end
176
+
177
+ # This method checks if the given +token+ is invalid,
178
+ # that means it's either +nil+ or empty or it matches
179
+ # the refular expression given as +root+.
180
+ #
181
+ # @api public
182
+ # @param [Symbol,String] token the identifier of a token
183
+ # @param [Regexp] root the regular expression used to test
184
+ # @return [Boolean] +true+ if the given +token+ is
185
+ # invalid, +false+ otherwise
186
+ def invalid?(token, root)
187
+ token = token.to_s
188
+ token.empty? ||
189
+ (root == Regexp::PATTERN && Keys::ALL[token.to_sym]) ||
190
+ Regexp.const_get(root) =~ token
191
+ end
192
+ module_function :invalid?
193
+ end
194
+
195
+ # This module contains constants defining
196
+ # reserved characters in kind identifiers.
197
+ module Kinds
198
+ # Reserved characters in kind identifiers placed in configuration.
199
+ DB = (Operators::ALL | Markers::ALL) - [Markers::ALIAS, Markers::LOUD_VALUE]
200
+
201
+ # Reserved characters in kind identifiers passed as option values.
202
+ OPTION = DB
203
+
204
+ # Reserved characters in kind identifiers placed in patterns.
205
+ PATTERN = (Operators::ALL | Markers::ALL) - [Markers::LOUD_VALUE]
206
+
207
+ # This module contains constants defining
208
+ # regular expressions for reserved characters
209
+ # in kind identifiers.
210
+ module Regexp
211
+ # Reserved characters in kind identifiers placed in configuration.
212
+ DB = Config.gen_regexp Kinds::DB
213
+
214
+ # Reserved characters in kind identifiers passed as option values.
215
+ OPTION = Config.gen_regexp Kinds::OPTION
216
+
217
+ # Reserved characters in kind identifiers placed in patterns.
218
+ PATTERN = Config.gen_regexp Kinds::PATTERN
219
+ end
220
+
221
+ # This method checks if the given +kind+ is invalid,
222
+ # that means it's either +nil+ or empty or it matches
223
+ # the refular expression given as +root+.
224
+ #
225
+ # @api public
226
+ # @param [Symbol,String] kind the identifier of a kind
227
+ # @param [Regexp] root the regular expression used to test
228
+ # @return [Boolean] +true+ if the given +kind+ is
229
+ # invalid, +false+ otherwise
230
+ def invalid?(kind, root)
231
+ kind = kind.to_s
232
+ kind.empty? ||
233
+ (root != Regexp::OPTION &&
234
+ (KEYS[kind.to_sym] || OPTION_PREFIX_REGEXP =~ kind)) ||
235
+ Regexp.const_get(root) =~ kind
236
+ end
237
+ module_function :invalid?
238
+ end
239
+ end
240
+
241
+ # A string for regular expression that catches patterns.
242
+ PATTERN_RESTR = "(.?)#{Markers::PATTERN}" \
243
+ "([^\\#{Markers::PATTERN_BEGIN}]*)\\#{Markers::PATTERN_BEGIN}" \
244
+ "([^\\#{Markers::PATTERN_END}]+)\\#{Markers::PATTERN_END}" \
245
+ "((?:\\#{Markers::PATTERN_BEGIN}([^\\#{Markers::PATTERN_BEGIN}" \
246
+ "]+)\\#{Markers::PATTERN_END})*)".freeze
247
+
248
+ # A string for regular expression that extracts additional patterns attached.
249
+ MULTI_RESTR = "\\#{Markers::PATTERN_BEGIN}" \
250
+ "([^\\#{Markers::PATTERN_END}]+)\\" \
251
+ "#{Markers::PATTERN_END}".freeze
252
+
253
+ # A regular expression that catches token groups or single tokens.
254
+ TOKENS_RESTR = '(?:' \
255
+ "([^#{Operators::Tokens::ASSIGN}\\#{Operators::Tokens::OR}]+)" \
256
+ "#{Operators::Tokens::ASSIGN}+" \
257
+ "([^\\#{Operators::Tokens::OR}]+)\\1?)" \
258
+ "|([^#{Operators::Tokens::ASSIGN}\\#{Operators::Tokens::OR}]+)".freeze
259
+
260
+ # A regular expression that catches patterns.
261
+ PATTERN_REGEXP = Regexp.new PATTERN_RESTR
262
+
263
+ # A regular expression that extracts additional patterns attached.
264
+ MULTI_REGEXP = Regexp.new MULTI_RESTR
265
+
266
+ # A regular expression that catches token groups or single tokens.
267
+ TOKENS_REGEXP = Regexp.new TOKENS_RESTR
268
+ end
269
+
270
+ # @private
271
+ PATTERN_MARKER = Config::Markers::PATTERN
272
+ # @private
273
+ NAMED_MARKER = Config::Markers::STRICT_KIND
274
+ # @private
275
+ ALIAS_MARKER = Config::Markers::ALIAS
276
+ # @private
277
+ ESCAPE = Config::Escapes::ESCAPE
278
+ # @private
279
+ ESCAPE_R = Config::Escapes::ESCAPE_R
280
+ # @private
281
+ ESCAPES = Config::Escapes::PATTERN
282
+ # @private
283
+ PATTERN = Config::PATTERN_REGEXP
284
+ # @private
285
+ TOKENS = Config::TOKENS_REGEXP
286
+ # @private
287
+ INFLECTOR_RESERVED_KEYS = Config::Reserved::KEYS
288
+ end
289
+ end