@@ -25,6 +25,8 @@ def lex_error msg
2525 end
2626
2727 class Token
28+ ALWAYS_ACCEPTABLE = Proc . new { |context | true }
29+
2830 include Puppet ::Util ::MethodHelper
2931
3032 attr_accessor :regex , :name , :string , :skip , :incr_line , :skip_text , :accumulate
@@ -40,15 +42,23 @@ def initialize(string_or_regex, name, options = {})
4042 end
4143
4244 set_options ( options )
45+ @acceptable_when = ALWAYS_ACCEPTABLE
4346 end
4447
4548 def to_s
4649 string or @name . to_s
4750 end
4851
4952 def acceptable? ( context = { } )
50- # By default tokens are aceeptable in any context
51- true
53+ @acceptable_when . call ( context )
54+ end
55+
56+ # Define when the token is able to match.
57+ # This provides context that cannot be expressed otherwise, such as feature flags.
58+ #
59+ # @param block [Proc] a proc that given a context returns a boolean
60+ def acceptable_when ( block )
61+ @acceptable_when = block
5262 end
5363 end
5464
@@ -157,15 +167,40 @@ def each
157167 "<boolean>" => :BOOLEAN
158168 )
159169
170+ module Contextual
171+ QUOTE_TOKENS = [ :DQPRE , :DQMID ]
172+ REGEX_INTRODUCING_TOKENS = [ :NODE , :LBRACE , :RBRACE , :MATCH , :NOMATCH , :COMMA ]
173+
174+ NOT_INSIDE_QUOTES = Proc . new do |context |
175+ !QUOTE_TOKENS . include? context [ :after ]
176+ end
177+
178+ INSIDE_QUOTES = Proc . new do |context |
179+ QUOTE_TOKENS . include? context [ :after ]
180+ end
181+
182+ IN_REGEX_POSITION = Proc . new do |context |
183+ REGEX_INTRODUCING_TOKENS . include? context [ :after ]
184+ end
185+
186+ IN_STRING_INTERPOLATION = Proc . new do |context |
187+ context [ :string_interpolation_depth ] > 0
188+ end
189+
190+ DASHED_VARIABLES_ALLOWED = Proc . new do |context |
191+ Puppet [ :allow_variables_with_dashes ]
192+ end
193+
194+ VARIABLE_AND_DASHES_ALLOWED = Proc . new do |context |
195+ Contextual ::DASHED_VARIABLES_ALLOWED . call ( context ) and TOKENS [ :VARIABLE ] . acceptable? ( context )
196+ end
197+ end
198+
160199 # Numbers are treated separately from names, so that they may contain dots.
161200 TOKENS . add_token :NUMBER , %r{\b (?:0[xX][0-9A-Fa-f]+|0?\d +(?:\. \d +)?(?:[eE]-?\d +)?)\b } do |lexer , value |
162201 [ TOKENS [ :NAME ] , value ]
163202 end
164- #:stopdoc: # Issue #4161
165- def ( TOKENS [ :NUMBER ] ) . acceptable? ( context = { } )
166- ![ :DQPRE , :DQMID ] . include? context [ :after ]
167- end
168- #:startdoc:
203+ TOKENS [ :NUMBER ] . acceptable_when Contextual ::NOT_INSIDE_QUOTES
169204
170205 TOKENS . add_token :NAME , %r{((::)?[a-z0-9][-\w ]*)(::[a-z0-9][-\w ]*)*} do |lexer , value |
171206 string_token = self
@@ -179,13 +214,9 @@ def (TOKENS[:NUMBER]).acceptable?(context={})
179214 end
180215 [ string_token , value ]
181216 end
182- [ :NAME , :CLASSNAME , :CLASSREF ] . each { |name_token |
183- #:stopdoc: # Issue #4161
184- def ( TOKENS [ name_token ] ) . acceptable? ( context = { } )
185- ![ :DQPRE , :DQMID ] . include? context [ :after ]
186- end
187- #:startdoc:
188- }
217+ [ :NAME , :CLASSREF ] . each do |name_token |
218+ TOKENS [ name_token ] . acceptable_when Contextual ::NOT_INSIDE_QUOTES
219+ end
189220
190221 TOKENS . add_token :COMMENT , %r{#.*} , :accumulate => true , :skip => true do |lexer , value |
191222 value . sub! ( /# ?/ , '' )
@@ -208,12 +239,7 @@ def (TOKENS[name_token]).acceptable?(context={})
208239 regex = value . sub ( %r{\A /} , "" ) . sub ( %r{/\Z } , '' ) . gsub ( "\\ /" , "/" )
209240 [ self , Regexp . new ( regex ) ]
210241 end
211-
212- #:stopdoc: # Issue #4161
213- def ( TOKENS [ :REGEX ] ) . acceptable? ( context = { } )
214- [ :NODE , :LBRACE , :RBRACE , :MATCH , :NOMATCH , :COMMA ] . include? context [ :after ]
215- end
216- #:startdoc:
242+ TOKENS [ :REGEX ] . acceptable_when Contextual ::IN_REGEX_POSITION
217243
218244 TOKENS . add_token :RETURN , "\n " , :skip => true , :incr_line => true , :skip_text => true
219245
@@ -231,20 +257,14 @@ def (TOKENS[:REGEX]).acceptable?(context={})
231257 TOKENS . add_token :DQCONT , /\} / do |lexer , value |
232258 lexer . tokenize_interpolated_string ( DQ_continuation_token_types )
233259 end
234- #:stopdoc: # Issue #4161
235- def ( TOKENS [ :DQCONT ] ) . acceptable? ( context = { } )
236- context [ :string_interpolation_depth ] > 0
237- end
238- #:startdoc:
260+ TOKENS [ :DQCONT ] . acceptable_when Contextual ::IN_STRING_INTERPOLATION
239261
240262 TOKENS . add_token :DOLLAR_VAR_WITH_DASH , %r{\$ (?:::)?(?:[-\w ]+::)*[-\w ]+} do |lexer , value |
241263 lexer . warn_if_variable_has_hyphen ( value )
242264
243265 [ TOKENS [ :VARIABLE ] , value [ 1 ..-1 ] ]
244266 end
245- def ( TOKENS [ :DOLLAR_VAR_WITH_DASH ] ) . acceptable? ( context = { } )
246- Puppet [ :allow_variables_with_dashes ]
247- end
267+ TOKENS [ :DOLLAR_VAR_WITH_DASH ] . acceptable_when Contextual ::DASHED_VARIABLES_ALLOWED
248268
249269 TOKENS . add_token :DOLLAR_VAR , %r{\$ (::)?(\w +::)*\w +} do |lexer , value |
250270 [ TOKENS [ :VARIABLE ] , value [ 1 ..-1 ] ]
@@ -255,19 +275,10 @@ def (TOKENS[:DOLLAR_VAR_WITH_DASH]).acceptable?(context = {})
255275
256276 [ TOKENS [ :VARIABLE ] , value ]
257277 end
258- #:stopdoc: # Issue #4161
259- def ( TOKENS [ :VARIABLE_WITH_DASH ] ) . acceptable? ( context = { } )
260- Puppet [ :allow_variables_with_dashes ] and TOKENS [ :VARIABLE ] . acceptable? ( context )
261- end
262- #:startdoc:
278+ TOKENS [ :VARIABLE_WITH_DASH ] . acceptable_when Contextual ::VARIABLE_AND_DASHES_ALLOWED
263279
264280 TOKENS . add_token :VARIABLE , %r{(::)?(\w +::)*\w +}
265- #:stopdoc: # Issue #4161
266- def ( TOKENS [ :VARIABLE ] ) . acceptable? ( context = { } )
267- [ :DQPRE , :DQMID ] . include? context [ :after ]
268- end
269- #:startdoc:
270-
281+ TOKENS [ :VARIABLE ] . acceptable_when Contextual ::INSIDE_QUOTES
271282
272283 TOKENS . sort_tokens
273284
0 commit comments