ios_parser 0.4.1 → 0.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/Guardfile +1 -1
- data/ext/ios_parser/c_lexer/lexer.c +37 -10
- data/lib/ios_parser/lexer.rb +36 -13
- data/lib/ios_parser/version.rb +1 -1
- data/lib/ios_parser.rb +1 -1
- data/spec/lib/ios_parser/ios/queryable_spec.rb +2 -2
- data/spec/lib/ios_parser/ios_spec.rb +6 -12
- data/spec/lib/ios_parser/lexer_spec.rb +15 -6
- data/spec/lib/ios_parser_spec.rb +5 -10
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 181d9adcdc7d222fe6ef05a91624aa1277274371
|
4
|
+
data.tar.gz: f9a1920092018240b8e67f972e453f5e104b8bd9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d4cf9efd75f3c563ffa92034dccbc265a5fd70778afb2f970df71641b1a94edc371befcd99e6d7bf989817b8fd1744a4d60b7340415ac7ec4fa4d2e8afd6586
|
7
|
+
data.tar.gz: 5fa9ebc0c746698ce75afd045d272826e9e48d54c86d4c20ab244e790b10f9255a36795a85331b1675d756fde9ac6b5d221bf0506391cb73a032e246e6ab41f7
|
data/CHANGELOG.md
CHANGED
data/Guardfile
CHANGED
@@ -3,7 +3,7 @@ guard :rake, task: 'compile' do
|
|
3
3
|
end
|
4
4
|
|
5
5
|
guard :rspec, cmd: 'bundle exec rspec --color --fail-fast' do
|
6
|
-
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^spec/.+_spec\.rb$})
|
7
7
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
8
8
|
watch('spec/spec_helper.rb') { 'spec' }
|
9
9
|
watch(%r{^ext/(.+)\.[ch]$}) { 'spec' }
|
@@ -81,7 +81,7 @@ int is_certificate(LexInfo *lex) {
|
|
81
81
|
return 1;
|
82
82
|
}
|
83
83
|
|
84
|
-
int
|
84
|
+
int is_banner_begin(LexInfo *lex) {
|
85
85
|
VALUE banner_ary, banner;
|
86
86
|
int token_count = RARRAY_LEN(lex->tokens);
|
87
87
|
int banner_pos = token_count - 2;
|
@@ -178,9 +178,20 @@ static VALUE initialize(VALUE self, VALUE input_text) {
|
|
178
178
|
|
179
179
|
static void process_root(LexInfo * lex);
|
180
180
|
static void process_start_of_line(LexInfo * lex);
|
181
|
+
static void start_banner(LexInfo * lex);
|
181
182
|
|
182
183
|
static void process_newline(LexInfo *lex) {
|
183
184
|
delimit(lex);
|
185
|
+
|
186
|
+
if (is_banner_begin(lex)) {
|
187
|
+
lex->token_state = LEX_STATE_BANNER;
|
188
|
+
start_banner(lex);
|
189
|
+
lex->pos = lex->pos + 1;
|
190
|
+
lex->token_start = lex->pos;
|
191
|
+
lex->token_length = 0;
|
192
|
+
return;
|
193
|
+
}
|
194
|
+
|
184
195
|
lex->token_start = lex->pos;
|
185
196
|
ADD_TOKEN(lex, ID2SYM(rb_intern("EOL")));
|
186
197
|
lex->token_state = LEX_STATE_INDENT;
|
@@ -203,7 +214,7 @@ static void process_comment(LexInfo *lex) {
|
|
203
214
|
|
204
215
|
static void process_quoted_string(LexInfo *lex) {
|
205
216
|
char c = CURRENT_CHAR(lex);
|
206
|
-
|
217
|
+
|
207
218
|
lex->token_length++;
|
208
219
|
if (!lex->string_terminator) {
|
209
220
|
lex->string_terminator = c;
|
@@ -301,24 +312,40 @@ static void start_certificate(LexInfo *lex) {
|
|
301
312
|
process_certificate(lex);
|
302
313
|
}
|
303
314
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
if (c == lex->banner_delimiter &&
|
315
|
+
int is_banner_end_char(LexInfo *lex) {
|
316
|
+
return CURRENT_CHAR(lex) == lex->banner_delimiter &&
|
308
317
|
(0 < lex->pos && '\n' == lex->text[lex->pos - 1] ||
|
309
|
-
'\n' == lex->text[lex->pos + 1])
|
318
|
+
'\n' == lex->text[lex->pos + 1]);
|
319
|
+
}
|
320
|
+
|
321
|
+
int is_banner_end_string(LexInfo *lex) {
|
322
|
+
/* onlys accept the banner-ending string "EOF" */
|
323
|
+
return (CURRENT_CHAR(lex) == 'F' &&
|
324
|
+
lex->text[lex->pos - 1] == 'O' &&
|
325
|
+
lex->text[lex->pos - 2] == 'E' &&
|
326
|
+
lex->text[lex->pos - 3] == '\n');
|
327
|
+
}
|
328
|
+
|
329
|
+
static void process_banner(LexInfo *lex) {
|
330
|
+
if (lex->banner_delimiter && is_banner_end_char(lex)) {
|
310
331
|
lex->token_length++;
|
311
332
|
delimit(lex);
|
312
333
|
lex->token_start = lex->pos;
|
313
334
|
ADD_TOKEN(lex, ID2SYM(rb_intern("BANNER_END")));
|
314
335
|
if (lex->text[lex->pos + 1] == 'C') { lex->pos++; }
|
336
|
+
} else if (!lex->banner_delimiter && is_banner_end_string(lex)) {
|
337
|
+
lex->token_length -= 1;
|
338
|
+
delimit(lex);
|
339
|
+
lex->token_start = lex->pos;
|
340
|
+
ADD_TOKEN(lex, ID2SYM(rb_intern("BANNER_END")));
|
315
341
|
} else {
|
316
342
|
lex->token_length++;
|
317
343
|
}
|
318
344
|
}
|
319
345
|
|
320
346
|
static void start_banner(LexInfo *lex) {
|
321
|
-
|
347
|
+
char c = CURRENT_CHAR(lex);
|
348
|
+
lex->banner_delimiter = (c == '\n') ? 0 : c;
|
322
349
|
ADD_TOKEN(lex, ID2SYM(rb_intern("BANNER_BEGIN")));
|
323
350
|
if ('\n' == lex->text[lex->pos + 2]) lex->pos++;
|
324
351
|
}
|
@@ -359,7 +386,7 @@ static void process_root(LexInfo *lex) {
|
|
359
386
|
if (IS_SPACE(c)) {
|
360
387
|
delimit(lex);
|
361
388
|
|
362
|
-
} else if (
|
389
|
+
} else if (is_banner_begin(lex)) {
|
363
390
|
lex->token_state = LEX_STATE_BANNER;
|
364
391
|
start_banner(lex);
|
365
392
|
lex->pos = lex->pos + 2;
|
@@ -433,7 +460,7 @@ static VALUE call(VALUE self, VALUE input_text) {
|
|
433
460
|
case (LEX_STATE_QUOTED_STRING):
|
434
461
|
process_quoted_string(lex);
|
435
462
|
break;
|
436
|
-
|
463
|
+
|
437
464
|
case (LEX_STATE_WORD):
|
438
465
|
process_word(lex);
|
439
466
|
break;
|
data/lib/ios_parser/lexer.rb
CHANGED
@@ -81,7 +81,7 @@ module IOSParser
|
|
81
81
|
self.state = :banner
|
82
82
|
tokens << make_token(:BANNER_BEGIN)
|
83
83
|
@token_start = @this_char + 2
|
84
|
-
@banner_delimiter = char
|
84
|
+
@banner_delimiter = char == "\n" ? 'EOF' : char
|
85
85
|
end
|
86
86
|
|
87
87
|
def banner_begin?
|
@@ -89,21 +89,38 @@ module IOSParser
|
|
89
89
|
end
|
90
90
|
|
91
91
|
def banner
|
92
|
-
if
|
93
|
-
|
94
|
-
|
92
|
+
if banner_end_char?
|
93
|
+
banner_end_char
|
94
|
+
elsif banner_end_string?
|
95
|
+
banner_end_string
|
95
96
|
else
|
96
97
|
token << char
|
97
98
|
end
|
98
99
|
end
|
99
100
|
|
100
|
-
def
|
101
|
+
def banner_end_string
|
102
|
+
self.state = :root
|
103
|
+
token.chomp!(@banner_delimiter[0..-2])
|
104
|
+
tokens << make_token(token) << make_token(:BANNER_END)
|
105
|
+
self.token = ''
|
106
|
+
end
|
107
|
+
|
108
|
+
def banner_end_string?
|
109
|
+
@banner_delimiter.size > 1 && (token + char).end_with?(@banner_delimiter)
|
110
|
+
end
|
111
|
+
|
112
|
+
def banner_end_char
|
101
113
|
self.state = :root
|
102
114
|
banner_end_clean_token
|
103
115
|
tokens << make_token(token) << make_token(:BANNER_END)
|
104
116
|
self.token = ''
|
105
117
|
end
|
106
118
|
|
119
|
+
def banner_end_char?
|
120
|
+
char == @banner_delimiter && (@text[@this_char - 1] == "\n" ||
|
121
|
+
@text[@this_char + 1] == "\n")
|
122
|
+
end
|
123
|
+
|
107
124
|
def banner_end_clean_token
|
108
125
|
token.slice!(0) if token[0] == 'C'
|
109
126
|
token.slice!(0) if ["\n", ' '].include?(token[0])
|
@@ -157,10 +174,9 @@ module IOSParser
|
|
157
174
|
|
158
175
|
def integer
|
159
176
|
self.state = :integer
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
when word? then word
|
177
|
+
if dot? then decimal
|
178
|
+
elsif digit? then token << char
|
179
|
+
elsif word? then word
|
164
180
|
else root
|
165
181
|
end
|
166
182
|
end
|
@@ -180,10 +196,9 @@ module IOSParser
|
|
180
196
|
|
181
197
|
def decimal
|
182
198
|
self.state = :decimal
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
when word? then word
|
199
|
+
if digit? then token << char
|
200
|
+
elsif dot? then token << char
|
201
|
+
elsif word? then word
|
187
202
|
else root
|
188
203
|
end
|
189
204
|
end
|
@@ -247,6 +262,7 @@ module IOSParser
|
|
247
262
|
|
248
263
|
def newline
|
249
264
|
delimit
|
265
|
+
return banner_begin if banner_begin?
|
250
266
|
self.state = :line_start
|
251
267
|
self.indent = 0
|
252
268
|
tokens << make_token(:EOL)
|
@@ -267,6 +283,13 @@ module IOSParser
|
|
267
283
|
|
268
284
|
def delimit
|
269
285
|
return if token.empty?
|
286
|
+
|
287
|
+
unless respond_to?(:"#{state}_token")
|
288
|
+
pos = @token_start || @this_char
|
289
|
+
raise LexError, "Unterminated #{state} starting at #{pos}: "\
|
290
|
+
"#{@text[pos..pos + 20].inspect}"
|
291
|
+
end
|
292
|
+
|
270
293
|
tokens << send(:"#{state}_token")
|
271
294
|
self.state = :root
|
272
295
|
self.token = ''
|
data/lib/ios_parser/version.rb
CHANGED
data/lib/ios_parser.rb
CHANGED
@@ -27,10 +27,8 @@ END
|
|
27
27
|
'policed-dscp-transmit'],
|
28
28
|
commands: [{ args: %w(set dscp cs1),
|
29
29
|
commands: [], pos: 114 }],
|
30
|
-
pos: 50
|
31
|
-
|
32
|
-
pos: 24
|
33
|
-
},
|
30
|
+
pos: 50 }],
|
31
|
+
pos: 24 },
|
34
32
|
|
35
33
|
{ args: %w(class other_service),
|
36
34
|
commands: [{ args: ['police', 600_000_000, 1_000_000,
|
@@ -40,12 +38,9 @@ END
|
|
40
38
|
commands: [], pos: 214 },
|
41
39
|
{ args: ['command_with_no_args'],
|
42
40
|
commands: [], pos: 230 }],
|
43
|
-
pos: 150
|
44
|
-
|
45
|
-
|
46
|
-
}],
|
47
|
-
pos: 0
|
48
|
-
}]
|
41
|
+
pos: 150 }],
|
42
|
+
pos: 128 }],
|
43
|
+
pos: 0 }]
|
49
44
|
}
|
50
45
|
end
|
51
46
|
|
@@ -98,8 +93,7 @@ END
|
|
98
93
|
'policed-dscp-transmit'],
|
99
94
|
commands: [{ args: %w(set dscp cs1),
|
100
95
|
commands: [], pos: 114 }],
|
101
|
-
pos: 50
|
102
|
-
}]
|
96
|
+
pos: 50 }]
|
103
97
|
end
|
104
98
|
|
105
99
|
context 'integer query' do
|
@@ -37,8 +37,7 @@ END
|
|
37
37
|
'police', 600_000_000, 1_000_000, 'exceed-action',
|
38
38
|
'policed-dscp-transmit', :EOL,
|
39
39
|
:INDENT,
|
40
|
-
'set', 'dscp', 'cs2', :EOL, :DEDENT, :DEDENT, :DEDENT
|
41
|
-
]
|
40
|
+
'set', 'dscp', 'cs2', :EOL, :DEDENT, :DEDENT, :DEDENT]
|
42
41
|
end
|
43
42
|
|
44
43
|
subject { klass.new.call(input).map(&:last) }
|
@@ -71,8 +70,7 @@ END
|
|
71
70
|
:DEDENT, :DEDENT, :DEDENT,
|
72
71
|
'router', 'ospf', 12_345, :EOL,
|
73
72
|
:INDENT, 'nsr', :EOL,
|
74
|
-
:DEDENT
|
75
|
-
]
|
73
|
+
:DEDENT]
|
76
74
|
end
|
77
75
|
|
78
76
|
it 'pure' do
|
@@ -125,6 +123,18 @@ END
|
|
125
123
|
it { expect(subject_pure.map(&:last)).to eq output }
|
126
124
|
end
|
127
125
|
|
126
|
+
context 'complex eos banner' do
|
127
|
+
let(:input) { "banner motd\n'''\nEOF\n" }
|
128
|
+
|
129
|
+
let(:output) do
|
130
|
+
content = input.lines[1..-2].join
|
131
|
+
['banner', 'motd', :BANNER_BEGIN, content, :BANNER_END, :EOL]
|
132
|
+
end
|
133
|
+
|
134
|
+
it { expect(subject.map(&:last)).to eq output }
|
135
|
+
it { expect(subject_pure.map(&:last)).to eq output }
|
136
|
+
end
|
137
|
+
|
128
138
|
context 'decimal number' do
|
129
139
|
let(:input) { 'boson levels at 93.2' }
|
130
140
|
let(:output) { ['boson', 'levels', 'at', 93.2] }
|
@@ -164,8 +174,7 @@ END
|
|
164
174
|
'DDDDDDDD DDDDDDDD DDDDDDDD AAAA'],
|
165
175
|
[323, :CERTIFICATE_END],
|
166
176
|
[323, :EOL],
|
167
|
-
[323, :DEDENT]
|
168
|
-
]
|
177
|
+
[323, :DEDENT]]
|
169
178
|
end
|
170
179
|
|
171
180
|
subject { klass.new.call(input) }
|
data/spec/lib/ios_parser_spec.rb
CHANGED
@@ -26,10 +26,8 @@ END
|
|
26
26
|
'policed-dscp-transmit'],
|
27
27
|
commands: [{ args: %w(set dscp cs1),
|
28
28
|
commands: [], pos: 114 }],
|
29
|
-
pos: 50
|
30
|
-
|
31
|
-
pos: 24
|
32
|
-
},
|
29
|
+
pos: 50 }],
|
30
|
+
pos: 24 },
|
33
31
|
|
34
32
|
{ args: %w(class other_service),
|
35
33
|
commands: [{ args: ['police', 600_000_000, 1_000_000,
|
@@ -39,12 +37,9 @@ END
|
|
39
37
|
commands: [], pos: 214 },
|
40
38
|
{ args: ['command_with_no_args'],
|
41
39
|
commands: [], pos: 230 }],
|
42
|
-
pos: 150
|
43
|
-
|
44
|
-
|
45
|
-
}],
|
46
|
-
pos: 0
|
47
|
-
}]
|
40
|
+
pos: 150 }],
|
41
|
+
pos: 128 }],
|
42
|
+
pos: 0 }]
|
48
43
|
}
|
49
44
|
end
|
50
45
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ios_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Miller
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-04-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -110,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
110
|
version: '0'
|
111
111
|
requirements: []
|
112
112
|
rubyforge_project:
|
113
|
-
rubygems_version: 2.5.
|
113
|
+
rubygems_version: 2.5.2
|
114
114
|
signing_key:
|
115
115
|
specification_version: 4
|
116
116
|
summary: convert network switch and router config files to structured data
|
@@ -120,4 +120,3 @@ test_files:
|
|
120
120
|
- spec/lib/ios_parser/lexer_spec.rb
|
121
121
|
- spec/lib/ios_parser_spec.rb
|
122
122
|
- spec/spec_helper.rb
|
123
|
-
has_rdoc:
|