ios_parser 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|