nginx_config_parser 1.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.
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