nginx_config_parser 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,3 @@
1
+ == 1.0.0 / 2008-01-21
2
+
3
+ * Initial release.
data/Manifest.txt ADDED
@@ -0,0 +1,20 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/nginx_config_parser.rb
6
+ lib/nginx_config_parser/configuration.rb
7
+ lib/nginx_config_parser/scanner.rb
8
+ src/scanner.rl
9
+ tasks/annotations.rake
10
+ tasks/doc.rake
11
+ tasks/gem.rake
12
+ tasks/manifest.rake
13
+ tasks/ragel.rake
14
+ tasks/rubyforge.rake
15
+ tasks/setup.rb
16
+ tasks/spec.rake
17
+ tasks/test.rake
18
+ test/fixtures/ezra/conf/nginx.conf
19
+ test/fixtures/simple/conf/nginx.conf
20
+ test/parser_test.rb
data/README.txt ADDED
@@ -0,0 +1,73 @@
1
+ nginx_config_parser
2
+ by Bruce Williams
3
+
4
+ == DESCRIPTION:
5
+
6
+ A simple Nginx Configuration parser that generates an object graph for
7
+ traversal and can emit tidied [simple] configurations.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * Currently ignores `if' statements (focused on only parsing static config)
12
+
13
+ == SYNOPSIS:
14
+
15
+ With a file like:
16
+
17
+ user nobody www; # this is a 'setting' with key 'user'
18
+ workers 1;
19
+
20
+ http { # this is a 'section' with name 'http'
21
+ server {
22
+ location / { # this is a section with value = ['/']
23
+
24
+ }
25
+ }
26
+ }
27
+
28
+ Parse
29
+
30
+ config = NginxConfigParser.parse(File.read('/path/to/nginx.conf'))
31
+ p config.settings
32
+ # => {'user' => ['nobody', 'www'], 'workers' => 1}
33
+ config.each do |section|
34
+ p section.name # eg: 'http'
35
+ section.each do |subsection|
36
+ p section.name # eg: server
37
+ # Emit config (`if's and comments are stripped)
38
+ puts config
39
+
40
+ == REQUIREMENTS:
41
+
42
+ * Pure Ruby parser, no compiler needed
43
+ * No dependencies outside Ruby's standard library
44
+ * Should work with Ruby 1.8 and 1.9
45
+
46
+ == INSTALL:
47
+
48
+ * sudo gem install nginx_config_parser
49
+
50
+ == LICENSE:
51
+
52
+ (The MIT License)
53
+
54
+ Copyright (c) 2008 Bruce Williams
55
+
56
+ Permission is hereby granted, free of charge, to any person obtaining
57
+ a copy of this software and associated documentation files (the
58
+ 'Software'), to deal in the Software without restriction, including
59
+ without limitation the rights to use, copy, modify, merge, publish,
60
+ distribute, sublicense, and/or sell copies of the Software, and to
61
+ permit persons to whom the Software is furnished to do so, subject to
62
+ the following conditions:
63
+
64
+ The above copyright notice and this permission notice shall be
65
+ included in all copies or substantial portions of the Software.
66
+
67
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
68
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
69
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
70
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
71
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
72
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
73
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ # Look in the tasks/setup.rb file for the various options that can be
2
+ # configured in this Rakefile. The .rake files in the tasks directory
3
+ # are where the options are used.
4
+
5
+ load 'tasks/setup.rb'
6
+
7
+ ensure_in_path 'lib'
8
+ require 'nginx_config_parser'
9
+
10
+ task :default => :test
11
+
12
+ PROJ.name = 'nginx_config_parser'
13
+ PROJ.summary = 'A simple nginx.conf parser and emitter'
14
+ PROJ.authors = 'Bruce Williams'
15
+ PROJ.email = 'bruce@codefluency.com'
16
+ PROJ.url = 'http://codefluency.rubyforge.org/nginx_config_parser'
17
+ PROJ.description = paragraphs_of('README.txt', 1).join("\n\n")
18
+ PROJ.changes = paragraphs_of('History.txt', 0..1).join("\n\n")
19
+ PROJ.rubyforge_name = 'codefluency'
20
+ PROJ.exclude << '\.git$'
21
+ PROJ.exclude << '\._[^\/]*$'
@@ -0,0 +1,62 @@
1
+ # $Id$
2
+
3
+ # Equivalent to a header guard in C/C++
4
+ # Used to prevent the class/module from being loaded more than once
5
+ unless defined? NginxConfigParser
6
+
7
+ module NginxConfigParser
8
+
9
+ # :stopdoc:
10
+ VERSION = '1.0.0'
11
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
12
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
13
+ # :startdoc:
14
+
15
+ # Returns the version string for the library.
16
+ #
17
+ def self.version
18
+ VERSION
19
+ end
20
+
21
+ # Returns the library path for the module. If any arguments are given,
22
+ # they will be joined to the end of the libray path using
23
+ # <tt>File.join</tt>.
24
+ #
25
+ def self.libpath( *args )
26
+ args.empty? ? LIBPATH : ::File.join(LIBPATH, *args)
27
+ end
28
+
29
+ # Returns the lpath for the module. If any arguments are given,
30
+ # they will be joined to the end of the path using
31
+ # <tt>File.join</tt>.
32
+ #
33
+ def self.path( *args )
34
+ args.empty? ? PATH : ::File.join(PATH, *args)
35
+ end
36
+
37
+ # Utility method used to rquire all files ending in .rb that lie in the
38
+ # directory below this file that has the same name as the filename passed
39
+ # in. Optionally, a specific _directory_ name can be passed in such that
40
+ # the _filename_ does not have to be equivalent to the directory.
41
+ #
42
+ def self.require_all_libs_relative_to( fname, dir = nil )
43
+ dir ||= ::File.basename(fname, '.*')
44
+ search_me = ::File.expand_path(
45
+ ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
46
+
47
+ Dir.glob(search_me).sort.each {|rb| require rb}
48
+ end
49
+
50
+ # Parse configuration
51
+ # * Returns an instance of NginxConfigParser::Configuration
52
+ def self.parse(input)
53
+ NginxConfigParser::Scanner.parse(input)
54
+ end
55
+
56
+ end # module NginxConfigParser
57
+
58
+ NginxConfigParser.require_all_libs_relative_to __FILE__
59
+
60
+ end # unless defined?
61
+
62
+ # EOF
@@ -0,0 +1,68 @@
1
+ module NginxConfigParser
2
+
3
+ class Configuration
4
+
5
+ include Enumerable
6
+
7
+ attr_reader :settings
8
+ def initialize(level=0)
9
+ @level = level
10
+ @settings = {}
11
+ end
12
+
13
+ # Add a setting
14
+ def []=(key, value)
15
+ @settings[key] = value
16
+ end
17
+
18
+ # An array of child sections
19
+ def sections
20
+ @sections ||= []
21
+ end
22
+
23
+ # Add a child section
24
+ def section(name, value)
25
+ section = Section.new(@level + 1, name, value)
26
+ sections << section
27
+ section
28
+ end
29
+
30
+ def each(&block)
31
+ sections.each(&block)
32
+ end
33
+
34
+ def to_s #:nodoc:
35
+ lines = @settings.map do |key, value|
36
+ (' ' * @level) << [key, Array(value)].flatten.compact.join(' ') << ';'
37
+ end
38
+ lines.push(*sections.map { |section| section.to_s})
39
+ lines.join("\n")
40
+ end
41
+
42
+ end
43
+
44
+
45
+ # A Section of settings
46
+ class Section < Configuration
47
+
48
+ attr_reader :name, :value
49
+ def initialize(level, name, value=nil)
50
+ @name = name
51
+ @value = value
52
+ super(level)
53
+ end
54
+
55
+ def to_s #:nodoc:
56
+ lines = []
57
+ lines << ((' ' * (@level - 1)) << [@name, Array(@value)].flatten.compact.map { |v| v.to_s }.join(' ') << ' {')
58
+ @settings.each do |key, value|
59
+ lines << ((' ' * @level) << [key, Array(value)].flatten.join(' ') << ';')
60
+ end
61
+ lines.push(*sections.map { |section| section.to_s})
62
+ lines << ((' ' * (@level - 1)) << '}')
63
+ lines.join("\n")
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -0,0 +1,510 @@
1
+ # line 1 "src/scanner.rl"
2
+ module NginxConfigParser
3
+
4
+ module Scanner
5
+
6
+ class ConfigurationError < ::SyntaxError; end
7
+
8
+ class << self
9
+
10
+ # line 55 "src/scanner.rl"
11
+
12
+
13
+
14
+ def parse(data)
15
+ # Stuff for Ragel
16
+ data = data.unpack("c*") if data.is_a?(String)
17
+ eof, stack = 0, []
18
+ # The list of words to fill for identifiers and values
19
+ words = []
20
+ # The stack of contexts, used to accumulate data at
21
+ # the appropriate level
22
+ contexts = [Configuration.new]
23
+
24
+ # line 25 "src/scanner.rb"
25
+ class << self
26
+ attr_accessor :_nginx_actions
27
+ private :_nginx_actions, :_nginx_actions=
28
+ end
29
+ self._nginx_actions = [
30
+ 0, 1, 0, 1, 1, 1, 2, 1,
31
+ 3, 1, 4, 1, 5, 1, 6, 1,
32
+ 7, 1, 8, 1, 9, 1, 10, 1,
33
+ 11, 1, 12, 1, 13, 1, 14, 1,
34
+ 15
35
+ ]
36
+
37
+ class << self
38
+ attr_accessor :_nginx_key_offsets
39
+ private :_nginx_key_offsets, :_nginx_key_offsets=
40
+ end
41
+ self._nginx_key_offsets = [
42
+ 0, 1, 5, 6, 11, 12, 13, 18,
43
+ 21, 22, 23, 30, 35, 39, 42, 48
44
+ ]
45
+
46
+ class << self
47
+ attr_accessor :_nginx_trans_keys
48
+ private :_nginx_trans_keys, :_nginx_trans_keys=
49
+ end
50
+ self._nginx_trans_keys = [
51
+ 10, 32, 40, 9, 13, 41, 32, 41,
52
+ 123, 9, 13, 125, 10, 32, 35, 105,
53
+ 9, 13, 32, 9, 13, 10, 102, 32,
54
+ 35, 59, 123, 125, 9, 13, 32, 59,
55
+ 123, 9, 13, 32, 125, 9, 13, 32,
56
+ 9, 13, 10, 32, 59, 123, 9, 13,
57
+ 32, 59, 123, 9, 13, 0
58
+ ]
59
+
60
+ class << self
61
+ attr_accessor :_nginx_single_lengths
62
+ private :_nginx_single_lengths, :_nginx_single_lengths=
63
+ end
64
+ self._nginx_single_lengths = [
65
+ 1, 2, 1, 3, 1, 1, 3, 1,
66
+ 1, 1, 5, 3, 2, 1, 4, 3
67
+ ]
68
+
69
+ class << self
70
+ attr_accessor :_nginx_range_lengths
71
+ private :_nginx_range_lengths, :_nginx_range_lengths=
72
+ end
73
+ self._nginx_range_lengths = [
74
+ 0, 1, 0, 1, 0, 0, 1, 1,
75
+ 0, 0, 1, 1, 1, 1, 1, 1
76
+ ]
77
+
78
+ class << self
79
+ attr_accessor :_nginx_index_offsets
80
+ private :_nginx_index_offsets, :_nginx_index_offsets=
81
+ end
82
+ self._nginx_index_offsets = [
83
+ 0, 2, 6, 8, 13, 15, 17, 22,
84
+ 25, 27, 29, 36, 41, 45, 48, 54
85
+ ]
86
+
87
+ class << self
88
+ attr_accessor :_nginx_indicies
89
+ private :_nginx_indicies, :_nginx_indicies=
90
+ end
91
+ self._nginx_indicies = [
92
+ 2, 1, 3, 4, 3, 0, 5, 4,
93
+ 5, 5, 6, 5, 4, 7, 6, 10,
94
+ 9, 12, 13, 14, 12, 11, 12, 12,
95
+ 15, 2, 1, 3, 16, 18, 19, 20,
96
+ 21, 22, 18, 17, 23, 23, 23, 23,
97
+ 17, 18, 25, 18, 24, 25, 25, 26,
98
+ 10, 9, 9, 9, 9, 19, 25, 23,
99
+ 23, 25, 17, 0
100
+ ]
101
+
102
+ class << self
103
+ attr_accessor :_nginx_trans_targs_wi
104
+ private :_nginx_trans_targs_wi, :_nginx_trans_targs_wi=
105
+ end
106
+ self._nginx_trans_targs_wi = [
107
+ 6, 0, 6, 1, 2, 3, 4, 6,
108
+ 10, 5, 10, 6, 7, 8, 9, 6,
109
+ 6, 11, 12, 14, 10, 10, 15, 10,
110
+ 10, 13, 10
111
+ ]
112
+
113
+ class << self
114
+ attr_accessor :_nginx_trans_actions_wi
115
+ private :_nginx_trans_actions_wi, :_nginx_trans_actions_wi=
116
+ end
117
+ self._nginx_trans_actions_wi = [
118
+ 31, 0, 25, 0, 0, 0, 0, 21,
119
+ 19, 0, 11, 23, 0, 5, 5, 29,
120
+ 27, 0, 0, 5, 7, 9, 0, 13,
121
+ 17, 0, 15
122
+ ]
123
+
124
+ class << self
125
+ attr_accessor :_nginx_to_state_actions
126
+ private :_nginx_to_state_actions, :_nginx_to_state_actions=
127
+ end
128
+ self._nginx_to_state_actions = [
129
+ 0, 0, 0, 0, 0, 0, 1, 0,
130
+ 0, 0, 1, 0, 0, 0, 0, 0
131
+ ]
132
+
133
+ class << self
134
+ attr_accessor :_nginx_from_state_actions
135
+ private :_nginx_from_state_actions, :_nginx_from_state_actions=
136
+ end
137
+ self._nginx_from_state_actions = [
138
+ 0, 0, 0, 0, 0, 0, 3, 0,
139
+ 0, 0, 3, 0, 0, 0, 0, 0
140
+ ]
141
+
142
+ class << self
143
+ attr_accessor :_nginx_eof_trans
144
+ private :_nginx_eof_trans, :_nginx_eof_trans=
145
+ end
146
+ self._nginx_eof_trans = [
147
+ 1, 1, 1, 1, 1, 9, 0, 16,
148
+ 17, 17, 0, 24, 25, 27, 24, 24
149
+ ]
150
+
151
+ class << self
152
+ attr_accessor :nginx_start
153
+ end
154
+ self.nginx_start = 6;
155
+ class << self
156
+ attr_accessor :nginx_first_final
157
+ end
158
+ self.nginx_first_final = 6;
159
+ class << self
160
+ attr_accessor :nginx_error
161
+ end
162
+ self.nginx_error = -1;
163
+
164
+ class << self
165
+ attr_accessor :nginx_en_statement
166
+ end
167
+ self.nginx_en_statement = 10;
168
+ class << self
169
+ attr_accessor :nginx_en_main
170
+ end
171
+ self.nginx_en_main = 6;
172
+
173
+ # line 68 "src/scanner.rl"
174
+
175
+ # line 176 "src/scanner.rb"
176
+ begin
177
+ p ||= 0
178
+ pe ||= data.length
179
+ cs = nginx_start
180
+ top = 0
181
+ ts = nil
182
+ te = nil
183
+ act = 0
184
+ end
185
+ # line 69 "src/scanner.rl"
186
+
187
+ # line 188 "src/scanner.rb"
188
+ begin
189
+ _klen, _trans, _keys, _acts, _nacts = nil
190
+ _goto_level = 0
191
+ _resume = 10
192
+ _eof_trans = 15
193
+ _again = 20
194
+ _test_eof = 30
195
+ _out = 40
196
+ while true
197
+ _trigger_goto = false
198
+ if _goto_level <= 0
199
+ if p == pe
200
+ _goto_level = _test_eof
201
+ next
202
+ end
203
+ end
204
+ if _goto_level <= _resume
205
+ _acts = _nginx_from_state_actions[cs]
206
+ _nacts = _nginx_actions[_acts]
207
+ _acts += 1
208
+ while _nacts > 0
209
+ _nacts -= 1
210
+ _acts += 1
211
+ case _nginx_actions[_acts - 1]
212
+ when 1 then
213
+ # line 1 "src/scanner.rl"
214
+ begin
215
+ ts = p
216
+ end
217
+ # line 1 "src/scanner.rl"
218
+ # line 219 "src/scanner.rb"
219
+ end # from state action switch
220
+ end
221
+ if _trigger_goto
222
+ next
223
+ end
224
+ _keys = _nginx_key_offsets[cs]
225
+ _trans = _nginx_index_offsets[cs]
226
+ _klen = _nginx_single_lengths[cs]
227
+ _break_match = false
228
+
229
+ begin
230
+ if _klen > 0
231
+ _lower = _keys
232
+ _upper = _keys + _klen - 1
233
+
234
+ loop do
235
+ break if _upper < _lower
236
+ _mid = _lower + ( (_upper - _lower) >> 1 )
237
+
238
+ if data[p] < _nginx_trans_keys[_mid]
239
+ _upper = _mid - 1
240
+ elsif data[p] > _nginx_trans_keys[_mid]
241
+ _lower = _mid + 1
242
+ else
243
+ _trans += (_mid - _keys)
244
+ _break_match = true
245
+ break
246
+ end
247
+ end # loop
248
+ break if _break_match
249
+ _keys += _klen
250
+ _trans += _klen
251
+ end
252
+ _klen = _nginx_range_lengths[cs]
253
+ if _klen > 0
254
+ _lower = _keys
255
+ _upper = _keys + (_klen << 1) - 2
256
+ loop do
257
+ break if _upper < _lower
258
+ _mid = _lower + (((_upper-_lower) >> 1) & ~1)
259
+ if data[p] < _nginx_trans_keys[_mid]
260
+ _upper = _mid - 2
261
+ elsif data[p] > _nginx_trans_keys[_mid+1]
262
+ _lower = _mid + 2
263
+ else
264
+ _trans += ((_mid - _keys) >> 1)
265
+ _break_match = true
266
+ break
267
+ end
268
+ end # loop
269
+ break if _break_match
270
+ _trans += _klen
271
+ end
272
+ end while false
273
+ _trans = _nginx_indicies[_trans]
274
+ end
275
+ if _goto_level <= _eof_trans
276
+ cs = _nginx_trans_targs_wi[_trans]
277
+ if _nginx_trans_actions_wi[_trans] != 0
278
+ _acts = _nginx_trans_actions_wi[_trans]
279
+ _nacts = _nginx_actions[_acts]
280
+ _acts += 1
281
+ while _nacts > 0
282
+ _nacts -= 1
283
+ _acts += 1
284
+ case _nginx_actions[_acts - 1]
285
+ when 2 then
286
+ # line 1 "src/scanner.rl"
287
+ begin
288
+ te = p+1
289
+ end
290
+ # line 1 "src/scanner.rl"
291
+ when 3 then
292
+ # line 20 "src/scanner.rl"
293
+ begin
294
+ te = p+1
295
+ begin
296
+ name = words.shift
297
+ values = words.dup
298
+ contexts.last[name] = value_of(values)
299
+ words.clear
300
+ begin
301
+ top -= 1
302
+ cs = stack[top]
303
+ _trigger_goto = true
304
+ _goto_level = _again
305
+ break
306
+ end
307
+
308
+ end
309
+ end
310
+ # line 20 "src/scanner.rl"
311
+ when 4 then
312
+ # line 31 "src/scanner.rl"
313
+ begin
314
+ te = p+1
315
+ begin
316
+ name = words.shift
317
+ values = words.dup
318
+ contexts << contexts.last.section(name, value_of(values))
319
+ words.clear
320
+ begin
321
+ stack[top] = cs
322
+ top+= 1
323
+ cs = 10
324
+ _trigger_goto = true
325
+ _goto_level = _again
326
+ break
327
+ end
328
+
329
+ end
330
+ end
331
+ # line 31 "src/scanner.rl"
332
+ when 5 then
333
+ # line 43 "src/scanner.rl"
334
+ begin
335
+ te = p+1
336
+ end
337
+ # line 43 "src/scanner.rl"
338
+ when 6 then
339
+ # line 28 "src/scanner.rl"
340
+ begin
341
+ te = p
342
+ p = p - 1; begin words << data[ts...te].pack('c*') end
343
+ end
344
+ # line 28 "src/scanner.rl"
345
+ when 7 then
346
+ # line 39 "src/scanner.rl"
347
+ begin
348
+ te = p
349
+ p = p - 1; begin
350
+ contexts.pop
351
+ begin
352
+ top -= 1
353
+ cs = stack[top]
354
+ _trigger_goto = true
355
+ _goto_level = _again
356
+ break
357
+ end
358
+
359
+ end
360
+ end
361
+ # line 39 "src/scanner.rl"
362
+ when 8 then
363
+ # line 43 "src/scanner.rl"
364
+ begin
365
+ te = p
366
+ p = p - 1; end
367
+ # line 43 "src/scanner.rl"
368
+ when 9 then
369
+ # line 28 "src/scanner.rl"
370
+ begin
371
+ begin p = ((te))-1; end
372
+ begin words << data[ts...te].pack('c*') end
373
+ end
374
+ # line 28 "src/scanner.rl"
375
+ when 10 then
376
+ # line 48 "src/scanner.rl"
377
+ begin
378
+ te = p+1
379
+ end
380
+ # line 48 "src/scanner.rl"
381
+ when 11 then
382
+ # line 50 "src/scanner.rl"
383
+ begin
384
+ te = p+1
385
+ begin words.clear; p = p - 1; begin
386
+ stack[top] = cs
387
+ top+= 1
388
+ cs = 10
389
+ _trigger_goto = true
390
+ _goto_level = _again
391
+ break
392
+ end
393
+ end
394
+ end
395
+ # line 50 "src/scanner.rl"
396
+ when 12 then
397
+ # line 52 "src/scanner.rl"
398
+ begin
399
+ te = p+1
400
+ end
401
+ # line 52 "src/scanner.rl"
402
+ when 13 then
403
+ # line 50 "src/scanner.rl"
404
+ begin
405
+ te = p
406
+ p = p - 1; begin words.clear; p = p - 1; begin
407
+ stack[top] = cs
408
+ top+= 1
409
+ cs = 10
410
+ _trigger_goto = true
411
+ _goto_level = _again
412
+ break
413
+ end
414
+ end
415
+ end
416
+ # line 50 "src/scanner.rl"
417
+ when 14 then
418
+ # line 52 "src/scanner.rl"
419
+ begin
420
+ te = p
421
+ p = p - 1; end
422
+ # line 52 "src/scanner.rl"
423
+ when 15 then
424
+ # line 50 "src/scanner.rl"
425
+ begin
426
+ begin p = ((te))-1; end
427
+ begin words.clear; p = p - 1; begin
428
+ stack[top] = cs
429
+ top+= 1
430
+ cs = 10
431
+ _trigger_goto = true
432
+ _goto_level = _again
433
+ break
434
+ end
435
+ end
436
+ end
437
+ # line 50 "src/scanner.rl"
438
+ # line 439 "src/scanner.rb"
439
+ end # action switch
440
+ end
441
+ end
442
+ if _trigger_goto
443
+ next
444
+ end
445
+ end
446
+ if _goto_level <= _again
447
+ _acts = _nginx_to_state_actions[cs]
448
+ _nacts = _nginx_actions[_acts]
449
+ _acts += 1
450
+ while _nacts > 0
451
+ _nacts -= 1
452
+ _acts += 1
453
+ case _nginx_actions[_acts - 1]
454
+ when 0 then
455
+ # line 1 "src/scanner.rl"
456
+ begin
457
+ ts = nil; end
458
+ # line 1 "src/scanner.rl"
459
+ # line 460 "src/scanner.rb"
460
+ end # to state action switch
461
+ end
462
+ if _trigger_goto
463
+ next
464
+ end
465
+ p += 1
466
+ if p != pe
467
+ _goto_level = _resume
468
+ next
469
+ end
470
+ end
471
+ if _goto_level <= _test_eof
472
+ if p == eof
473
+ if _nginx_eof_trans[cs] > 0
474
+ _trans = _nginx_eof_trans[cs] - 1;
475
+ _goto_level = _eof_trans
476
+ next;
477
+ end
478
+ end
479
+ end
480
+ if _goto_level <= _out
481
+ break
482
+ end
483
+ end
484
+ end
485
+ # line 70 "src/scanner.rl"
486
+ # This is a little more forgiving than
487
+ # using <tt>pop</tt> and validating balance
488
+ contexts.first
489
+ end
490
+
491
+ #######
492
+ private
493
+ #######
494
+
495
+ # Return single values if only one word,
496
+ # and make it an integer if possible
497
+ def value_of(words)
498
+ return nil if words.empty?
499
+ return words unless words.size == 1
500
+ parsed_words = words.map do |word|
501
+ Integer(word) rescue word
502
+ end
503
+ parsed_words.size == 1 ? parsed_words.pop : parsed_words
504
+ end
505
+
506
+ end
507
+
508
+ end
509
+
510
+ end