junoser 0.7.2 → 0.7.4
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 +15 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +47 -7
- data/LICENSE.txt +1 -1
- data/README.md +1 -2
- data/Rakefile +6 -3
- data/bin/console +4 -3
- data/exe/junoser +6 -5
- data/exe/junoser-squash +9 -6
- data/junoser.gemspec +15 -17
- data/lib/junoser/cli.rb +2 -2
- data/lib/junoser/development.rb +2 -0
- data/lib/junoser/display/config_store.rb +12 -12
- data/lib/junoser/display/enumerable.rb +6 -4
- data/lib/junoser/display/set.rb +15 -17
- data/lib/junoser/display/structure.rb +7 -7
- data/lib/junoser/display.rb +2 -0
- data/lib/junoser/input.rb +11 -10
- data/lib/junoser/js_ruler.rb +74 -66
- data/lib/junoser/parser.rb +164 -8
- data/lib/junoser/rule_tree/node.rb +3 -1
- data/lib/junoser/rule_tree/parser.rb +11 -8
- data/lib/junoser/rule_tree.rb +2 -0
- data/lib/junoser/ruler.rb +193 -171
- data/lib/junoser/squash.rb +16 -14
- data/lib/junoser/transformer.rb +9 -8
- data/lib/junoser/version.rb +3 -1
- data/lib/junoser/xsd/base.rb +15 -14
- data/lib/junoser/xsd/choice.rb +10 -9
- data/lib/junoser/xsd/complex_type.rb +13 -11
- data/lib/junoser/xsd/element.rb +34 -36
- data/lib/junoser/xsd/enumeration.rb +9 -8
- data/lib/junoser/xsd/parsable.rb +2 -0
- data/lib/junoser/xsd/restriction.rb +15 -13
- data/lib/junoser/xsd/sequence.rb +11 -8
- data/lib/junoser/xsd/simple_content.rb +6 -4
- data/lib/junoser/xsd/simple_type.rb +7 -5
- data/lib/junoser/xsd/union.rb +6 -4
- data/lib/junoser.rb +2 -0
- data/lib/underscorable.rb +10 -5
- metadata +5 -65
- data/.github/dependabot.yml +0 -6
- data/.github/workflows/test-linux.yaml +0 -30
- data/.gitignore +0 -11
- data/.pre-commit-config.yaml +0 -7
- data/commitlint.config.js +0 -6
data/lib/junoser/ruler.rb
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# rubocop:disable Style/PerlBackrefs -- to simplify
|
|
4
|
+
|
|
1
5
|
module Junoser
|
|
2
6
|
class Ruler
|
|
3
7
|
OFFSET = ' '
|
|
@@ -7,20 +11,20 @@ module Junoser
|
|
|
7
11
|
end
|
|
8
12
|
|
|
9
13
|
def to_rule
|
|
10
|
-
rule_header << rule << rule_footer
|
|
14
|
+
+rule_header << rule << rule_footer
|
|
11
15
|
end
|
|
12
16
|
|
|
13
17
|
def rule
|
|
14
18
|
str = @rule.read
|
|
15
19
|
str = remove_comments(str)
|
|
16
20
|
str = process_reserved_element(str)
|
|
17
|
-
str.split(
|
|
21
|
+
str.split("\n").map { |l| fmt(process_line(l)) }.join("\n")
|
|
18
22
|
end
|
|
19
23
|
|
|
20
24
|
private
|
|
21
25
|
|
|
22
26
|
def remove_comments(str)
|
|
23
|
-
str.gsub(%r
|
|
27
|
+
str.gsub(%r{\s*/\*.*\*/}, '')
|
|
24
28
|
end
|
|
25
29
|
|
|
26
30
|
def process_line(str)
|
|
@@ -29,21 +33,31 @@ module Junoser
|
|
|
29
33
|
str.gsub!(/("[^"]+")/) { "str(#{$1})" } # "foo" -> str("foo")
|
|
30
34
|
|
|
31
35
|
str.gsub!(/^(\s*)arg(\.as\(:\S+\))? \($/) { "#{$1}b(arg#{$2}," } # arg ( -> b(arg,
|
|
32
|
-
|
|
33
|
-
str.gsub!(/^(\s*)(str\(\S+\)) (
|
|
34
|
-
|
|
36
|
+
# str("foo") bar -> a(str("foo"), bar)
|
|
37
|
+
str.gsub!(/^(\s*)(str\(\S+\)) ([^ \t\n\r\f(|,]+)(\.as\(:\S+\))?(,?)$/) do
|
|
38
|
+
"#{$1}a(#{$2}, #{$3})#{$4}#{$5}"
|
|
39
|
+
end
|
|
40
|
+
# str("foo") (a | b) -> a(str("foo"), a | b)
|
|
41
|
+
str.gsub!(/^(\s*)(str\(\S+\)) (enum)?\((.*)\)(,?)$/) do
|
|
42
|
+
"#{$1}a(#{$2}, #{$3}#{$4})#{$5}"
|
|
43
|
+
end
|
|
35
44
|
str.gsub!(/^(\s*)(str\(\S+\)) \($/) { "#{$1}b(#{$2}," } # str("foo") ( -> b(str("foo"),
|
|
36
45
|
str.gsub!(/^(\s*)(enum)?(\(.*\))(\.as\(:\S\))? \($/) { "#{$1}b(#{$2}#{$3}#{$4}," } # (a | b) ( -> b((a | b),
|
|
37
|
-
|
|
38
|
-
str.gsub!(/^(\s*)(str\(\S+\)) (
|
|
39
|
-
|
|
46
|
+
# str("foo") bar ( -> b(a(str("foo"), bar),
|
|
47
|
+
str.gsub!(/^(\s*)(str\(\S+\)) ([^ \t\n\r\f(|,]+) \($/) do
|
|
48
|
+
"#{$1}b(a(#{$2}, #{$3}),"
|
|
49
|
+
end
|
|
50
|
+
# str("foo") (a | b) ( -> a(str("foo"), a | b,
|
|
51
|
+
str.gsub!(/^(\s*)(str\(\S+\)) (enum)?\((.*)\) \($/) do
|
|
52
|
+
"#{$1}a(#{$2}, #{$3}#{$4},"
|
|
53
|
+
end
|
|
40
54
|
str
|
|
41
55
|
end
|
|
42
56
|
|
|
43
57
|
def process_reserved_element(str)
|
|
44
|
-
str.gsub!
|
|
58
|
+
str.gsub!(/"\$\S+"/, 'arg')
|
|
45
59
|
|
|
46
|
-
str.gsub!
|
|
60
|
+
str.gsub!(/"groups" \(\s*s\(\s*any\s*\)\s*\)/, <<-REPLACE.strip)
|
|
47
61
|
b(a("groups", arg),
|
|
48
62
|
c(
|
|
49
63
|
configuration,
|
|
@@ -65,7 +79,7 @@ module Junoser
|
|
|
65
79
|
)
|
|
66
80
|
)
|
|
67
81
|
)
|
|
68
|
-
|
|
82
|
+
REPLACE
|
|
69
83
|
|
|
70
84
|
str.gsub! '"equal-literal"', '"="'
|
|
71
85
|
str.gsub! '"plus-literal"', '"+"'
|
|
@@ -81,55 +95,55 @@ module Junoser
|
|
|
81
95
|
str.gsub! '"tcp-flags" arg', '"tcp-flags" (quote | arg)'
|
|
82
96
|
|
|
83
97
|
str.gsub!(/^(\s*)"as-path" arg \(\s*c\(\s*arg/) do
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
98
|
+
fmt(['"as-path" arg (',
|
|
99
|
+
' c(',
|
|
100
|
+
' quote | arg'], $1)
|
|
87
101
|
end
|
|
88
102
|
|
|
89
103
|
str.gsub!(/^rule\(:regular_expression\) do\s.*?\s*end/) do
|
|
90
|
-
<<~
|
|
104
|
+
<<~REPLACE
|
|
91
105
|
rule(:regular_expression) do
|
|
92
106
|
(quote | arg).as(:arg)
|
|
93
107
|
end
|
|
94
|
-
|
|
108
|
+
REPLACE
|
|
95
109
|
end
|
|
96
110
|
|
|
97
111
|
str.gsub!(/^rule\(:login_user_object\) do\s*arg\.as\(:arg\) \(\s*c\(\s*"full-name" arg,/) do
|
|
98
|
-
<<~
|
|
112
|
+
<<~REPLACE
|
|
99
113
|
rule(:login_user_object) do
|
|
100
114
|
arg.as(:arg) (
|
|
101
115
|
sc(
|
|
102
116
|
"full-name" (quote | arg),
|
|
103
|
-
|
|
117
|
+
REPLACE
|
|
104
118
|
end
|
|
105
119
|
|
|
106
120
|
str.gsub!(/^(\s*)"location" arg,\s*"contact" arg,/) do
|
|
107
|
-
|
|
108
|
-
|
|
121
|
+
fmt(['"location" (quote | arg),',
|
|
122
|
+
'"contact" (quote | arg),'], $1)
|
|
109
123
|
end
|
|
110
124
|
|
|
111
125
|
str.gsub!(/^(\s*)"as-path" \(\s*c\(\s*"path" arg/) do
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
126
|
+
fmt(['"as-path" (',
|
|
127
|
+
' c(',
|
|
128
|
+
' "path" (quote | arg)'], $1)
|
|
115
129
|
end
|
|
116
130
|
|
|
117
131
|
str.gsub!(/^(\s*)prefix_list_items,\s*"apply-path" arg/) do
|
|
118
|
-
|
|
119
|
-
|
|
132
|
+
fmt(['"apply-path" (quote | arg),',
|
|
133
|
+
'prefix_list_items'], $1)
|
|
120
134
|
end
|
|
121
135
|
|
|
122
136
|
str.gsub!(/^(\s*)"drop-profile-map" \(\s*s\(\s*"loss-priority" \(\s*(.*\s*\),)\s*"protocol" \(\s*(.*\s*\),)\s*c\(\s*"drop-profile" (.*)/) do
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
137
|
+
fmt([
|
|
138
|
+
'"drop-profile-map" (',
|
|
139
|
+
' s(',
|
|
140
|
+
' s("loss-priority",',
|
|
141
|
+
" #{$2}",
|
|
142
|
+
' s("protocol",',
|
|
143
|
+
" #{$3}",
|
|
144
|
+
' s("drop-profile",',
|
|
145
|
+
" #{$4}"
|
|
146
|
+
], $1)
|
|
133
147
|
end
|
|
134
148
|
|
|
135
149
|
#
|
|
@@ -145,15 +159,17 @@ module Junoser
|
|
|
145
159
|
str.gsub!(/^(rule\(:server_group_type\) do\s*)c\(\s*c\(\s*arg\s*\)\s*\)/) { "#{$1}s(arg, arg)" }
|
|
146
160
|
|
|
147
161
|
str.gsub!(/^(rule\(:rib_group_inet_type\) do)\s*c\(\s*arg/) do
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
162
|
+
fmt([$1,
|
|
163
|
+
' ca(',
|
|
164
|
+
' a(arg, arg)'], '')
|
|
151
165
|
end
|
|
152
166
|
|
|
153
|
-
|
|
167
|
+
str.gsub! '"any" | "any-ipv4" | "any-ipv6"', '"any-ipv4" | "any-ipv6" | "any"'
|
|
168
|
+
|
|
169
|
+
# Fix overkill
|
|
154
170
|
str.gsub!(/^(\s*)"priority" \(\s*ca\(\s*arg\s*\)/) do
|
|
155
|
-
|
|
156
|
-
|
|
171
|
+
fmt(['"priority" (',
|
|
172
|
+
' a(arg, arg)', $1])
|
|
157
173
|
end
|
|
158
174
|
|
|
159
175
|
#
|
|
@@ -166,37 +182,37 @@ module Junoser
|
|
|
166
182
|
#
|
|
167
183
|
# "inet",
|
|
168
184
|
# "inet6"
|
|
169
|
-
str.gsub!(/"cspf"(.*\s*.*)"cspf-link"/) { %
|
|
170
|
-
str.gsub!(/"http"(.*\s*.*)"https"/) { %
|
|
171
|
-
str.gsub!(/"inet"(.*\s*.*)"inet6"/) { %
|
|
172
|
-
str.gsub!(/"icmp"(.*\s*.*)"icmp6"/) { %
|
|
173
|
-
str.gsub!(/"icmp"(.*\s*.*)"icmpv6"/) { %
|
|
174
|
-
str.gsub!(/"snmp"(.*\s*.*)"snmptrap"/) { %
|
|
175
|
-
str.gsub!(/"ospf"(.*\s*.*)"ospf3"/) { %
|
|
176
|
-
str.gsub!(/"deny"(.*\s*.*)"deny-password"/) { %
|
|
177
|
-
str.gsub!(/"no-redirects"(.*\s*.*)"no-redirects-ipv6"/) { %
|
|
178
|
-
str.gsub!(/"chassis"([^()]*)"chassis-ha-reswatch"/m) { %
|
|
185
|
+
str.gsub!(/"cspf"(.*\s*.*)"cspf-link"/) { %("cspf-link"#{$1}"cspf") }
|
|
186
|
+
str.gsub!(/"http"(.*\s*.*)"https"/) { %("https"#{$1}"http") }
|
|
187
|
+
str.gsub!(/"inet"(.*\s*.*)"inet6"/) { %("inet6"#{$1}"inet") }
|
|
188
|
+
str.gsub!(/"icmp"(.*\s*.*)"icmp6"/) { %("icmp6"#{$1}"icmp") }
|
|
189
|
+
str.gsub!(/"icmp"(.*\s*.*)"icmpv6"/) { %("icmpv6"#{$1}"icmp") }
|
|
190
|
+
str.gsub!(/"snmp"(.*\s*.*)"snmptrap"/) { %("snmptrap"#{$1}"snmp") }
|
|
191
|
+
str.gsub!(/"ospf"(.*\s*.*)"ospf3"/) { %("ospf3"#{$1}"ospf") }
|
|
192
|
+
str.gsub!(/"deny"(.*\s*.*)"deny-password"/) { %("deny-password"#{$1}"deny") }
|
|
193
|
+
str.gsub!(/"no-redirects"(.*\s*.*)"no-redirects-ipv6"/) { %("no-redirects-ipv6"#{$1}"no-redirects") }
|
|
194
|
+
str.gsub!(/"chassis"([^()]*)"chassis-ha-reswatch"/m) { %("chassis-ha-reswatch"#{$1}"chassis") }
|
|
179
195
|
str.gsub! '"tls1" | "tls11" | "tls12"', '"tls11" | "tls12" | "tls1"'
|
|
180
196
|
str.gsub!(/("group1" \| "group2" \| "group5") \| ([^)]+)/) { "#{$2} | #{$1}" }
|
|
181
197
|
|
|
182
198
|
%w[ccc ethernet-over-atm tcc vpls bridge].each do |encap|
|
|
183
|
-
str.gsub!(/"ethernet"(.*)"ethernet-#{encap}"/) { %
|
|
199
|
+
str.gsub!(/"ethernet"(.*)"ethernet-#{encap}"/) { %("ethernet-#{encap}"#{$1}"ethernet") }
|
|
184
200
|
end
|
|
185
201
|
|
|
186
202
|
str.gsub!(/^(\s*)"path" arg \(\s*c\(\s*sc\(\s*"abstract",\s*c\(\s*"loose",\s*"loose-link",\s*"strict"\s*\)\s*\)\.as\(:oneline\)/) do
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
203
|
+
fmt(['"path" arg (',
|
|
204
|
+
' c(',
|
|
205
|
+
' b(',
|
|
206
|
+
' ipaddr,',
|
|
207
|
+
' c(',
|
|
208
|
+
' "abstract",',
|
|
209
|
+
' c(',
|
|
210
|
+
' "loose-link",',
|
|
211
|
+
' "loose",',
|
|
212
|
+
' "strict"',
|
|
213
|
+
' )',
|
|
214
|
+
' ).as(:oneline)',
|
|
215
|
+
' )', $1])
|
|
200
216
|
end
|
|
201
217
|
|
|
202
218
|
#
|
|
@@ -207,7 +223,7 @@ module Junoser
|
|
|
207
223
|
str.gsub!(/\((.*) \| "vlan-id"\)/) { "(#{$1} | arg)" }
|
|
208
224
|
|
|
209
225
|
%w[filename].each do |key|
|
|
210
|
-
str.gsub! %
|
|
226
|
+
str.gsub! %("#{key}" arg), 'arg'
|
|
211
227
|
end
|
|
212
228
|
|
|
213
229
|
# "filename" fix above leaves "arg". Move to the end
|
|
@@ -226,14 +242,16 @@ module Junoser
|
|
|
226
242
|
# Fix .xsd: "arg" is missing
|
|
227
243
|
#
|
|
228
244
|
str.gsub!(/"route-filter" (\(\s*control_route_filter_type\s*\))/) { %["route-filter" arg #{$1}.as(:oneline)] }
|
|
229
|
-
str.gsub!(/"source-address-filter" (\(\s*control_source_address_filter_type\s*\))/)
|
|
245
|
+
str.gsub!(/"source-address-filter" (\(\s*control_source_address_filter_type\s*\))/) do
|
|
246
|
+
%["source-adress-filter" arg #{$1}.as(:oneline)]
|
|
247
|
+
end
|
|
230
248
|
%w[file].each do |key|
|
|
231
249
|
str.gsub!(/^(\s*"#{key}" \(\s*)c\(\s*arg,/) { "#{$1}sca(" }
|
|
232
250
|
end
|
|
233
251
|
|
|
234
252
|
# Fix .xsd: Unnecessary "arg" is added
|
|
235
253
|
%w[exact longer orlonger].each do |key|
|
|
236
|
-
str.gsub!(/^(\s*"#{key}") arg/) {
|
|
254
|
+
str.gsub!(/^(\s*"#{key}") arg/) { $1.to_s }
|
|
237
255
|
end
|
|
238
256
|
|
|
239
257
|
# Fix .xsd: "ieee-802.3ad" is invalid
|
|
@@ -247,7 +265,7 @@ module Junoser
|
|
|
247
265
|
|
|
248
266
|
# Fix .xsd: "from-zone" arg is also required
|
|
249
267
|
str.gsub!(/^ "policy" \(\s*s\(\s*arg,\s*"to-zone-name" arg,\s*(.*?)\s*\)\s*^ \),/m) do
|
|
250
|
-
|
|
268
|
+
fmt(['b(', ' s("from-zone", arg, "to-zone", arg),', " #{$1}", '),'], ' ')
|
|
251
269
|
end
|
|
252
270
|
|
|
253
271
|
# Fix .xsd: "members" accepts [ foo bar ]
|
|
@@ -282,18 +300,20 @@ module Junoser
|
|
|
282
300
|
|
|
283
301
|
# Fix .xsd: support "set protocols iccp peer xxx liveness-detection single-hop"
|
|
284
302
|
str.gsub!(/(^rule\(:peer_group\) do.*?\n(\s*)"detection-time" \(\s*c\(\s*"threshold" arg\s*\)\s*\))/m) do
|
|
285
|
-
"#{$1},\n#{
|
|
303
|
+
"#{$1},\n#{fmt('"single-hop"', $2)}"
|
|
286
304
|
end
|
|
287
305
|
|
|
288
306
|
# Fix .xsd: support "set interfaces xxx ether-options speed"
|
|
289
307
|
str.gsub! '"ethernet-1', '"1'
|
|
290
308
|
|
|
291
309
|
# Fix .xsd: support "set policy-options policy-statement xxx from policy [expression]"
|
|
292
|
-
str.gsub!(/^rule\(:policy_algebra\) do(\s*)arg\.as\(:arg\)\send/)
|
|
310
|
+
str.gsub!(/^rule\(:policy_algebra\) do(\s*)arg\.as\(:arg\)\send/) do
|
|
311
|
+
"rule(:policy_algebra) do#{$1}any.as(:arg)\nend"
|
|
312
|
+
end
|
|
293
313
|
|
|
294
314
|
# Fix .xsd: support "set interfaces xxx enable"
|
|
295
315
|
str.gsub!(/^(rule\(:interfaces_type\) do\s*[^\n]*\s*c\()(\s*)/m) do
|
|
296
|
-
%
|
|
316
|
+
%(#{$1}#{$2}"enable",#{$2})
|
|
297
317
|
end
|
|
298
318
|
|
|
299
319
|
# Fix .xsd: arg should be regular_expression
|
|
@@ -302,7 +322,7 @@ module Junoser
|
|
|
302
322
|
str
|
|
303
323
|
end
|
|
304
324
|
|
|
305
|
-
def
|
|
325
|
+
def fmt(str, offset = OFFSET)
|
|
306
326
|
case str
|
|
307
327
|
when String
|
|
308
328
|
str.empty? ? '' : offset + str
|
|
@@ -314,107 +334,109 @@ module Junoser
|
|
|
314
334
|
end
|
|
315
335
|
|
|
316
336
|
def rule_header
|
|
317
|
-
|
|
318
|
-
require 'parslet'
|
|
319
|
-
|
|
320
|
-
module Junoser
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
337
|
+
<<~HEADER
|
|
338
|
+
require 'parslet'
|
|
339
|
+
|
|
340
|
+
module Junoser
|
|
341
|
+
class Parser < Parslet::Parser
|
|
342
|
+
def parse_lines(config)
|
|
343
|
+
lines = config.split("\\n").map(&:strip)
|
|
344
|
+
lines_without_deactivate = lines.reject {|l| l =~ /^deactivate/ }
|
|
345
|
+
|
|
346
|
+
lines.inject(true) do |passed, line|
|
|
347
|
+
passed & parse_line(line, lines_without_deactivate)
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def parse_line(line, lines_without_deactivate)
|
|
352
|
+
if line =~ /^deactivate/
|
|
353
|
+
if lines_without_deactivate.grep(/^\#{line.sub(/^deactivate/, 'set')}/).empty?
|
|
354
|
+
$stderr.puts %(Corresponding "set" statement is not found: \#{line})
|
|
355
|
+
return false
|
|
356
|
+
else
|
|
357
|
+
return true
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
begin
|
|
362
|
+
# .xsd doesn't include "apply-groups"
|
|
363
|
+
if line =~ /(.*)\\s+apply-groups(-except)?\\s+(\\S+|\\[.*\\])$/
|
|
364
|
+
return $1 == 'set' ? true : parse($1)
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
parse line
|
|
368
|
+
true
|
|
369
|
+
rescue Parslet::ParseFailed
|
|
370
|
+
$stderr.puts "Invalid syntax: \#{line}"
|
|
371
|
+
false
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
# block with children maybe
|
|
376
|
+
def b(object, *children)
|
|
377
|
+
children.inject(object) {|rule, child| rule.as(:label) >> (space >> child.as(:child) | eos) }
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
# with an argument, and children maybe
|
|
381
|
+
def a(object, arg, *children)
|
|
382
|
+
b(object.as(:statement) >> space >> arg.as(:argument), *children)
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
# choice
|
|
386
|
+
def c(*objects)
|
|
387
|
+
objects.inject {|rule, object| rule | object }
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
def ca(*objects)
|
|
391
|
+
objects.inject {|rule, object| rule | object } | arg
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
# sequence
|
|
395
|
+
def s(*objects)
|
|
396
|
+
# TODO: eval "minOccurs" attribute of choice element
|
|
397
|
+
objects.inject {|rule, object| rule >> (space >> object).maybe }
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
# sequential choice
|
|
401
|
+
def sc(*objects)
|
|
402
|
+
(c(*objects) >> space.maybe).repeat(0)
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
def sca(*objects)
|
|
406
|
+
(c(*objects, arg) >> space.maybe).repeat(0)
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
def enum(object)
|
|
410
|
+
(object.as(:enum))
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
rule(:arg) { match('\\S').repeat(1) }
|
|
414
|
+
rule(:space) { match('\\s').repeat(1) }
|
|
415
|
+
rule(:any) { match('.').repeat(1) }
|
|
416
|
+
rule(:eos) { match('$') }
|
|
417
|
+
rule(:dotted) { match('[^. \\t\\n\\r\\f]').repeat(1) >> str('.') >> match('[^. \\t\\n\\r\\f]').repeat(1) }
|
|
418
|
+
rule(:quote) { str('"') >> match('[^"]').repeat(1) >> str('"') }
|
|
419
|
+
rule(:address) { match('[0-9a-fA-F:.]').repeat(1) }
|
|
420
|
+
rule(:prefix ) { address >> (str('/') >> match('[0-9]').repeat(1)).maybe }
|
|
421
|
+
|
|
422
|
+
root(:set)
|
|
423
|
+
rule(:set) { str('set') >> space >> configuration.as(:config) >> comment.maybe }
|
|
424
|
+
|
|
425
|
+
rule(:comment) { space.maybe >> (hash_comment | slash_asterisk) }
|
|
426
|
+
rule(:hash_comment) { str('#') >> any.maybe }
|
|
427
|
+
rule(:slash_asterisk) { str('/*') >> match('(?!\\*\\/).').repeat(0) >> str('*/') }
|
|
428
|
+
|
|
429
|
+
HEADER
|
|
410
430
|
end
|
|
411
431
|
|
|
412
432
|
def rule_footer
|
|
413
|
-
|
|
433
|
+
<<~FOOTER
|
|
414
434
|
|
|
415
|
-
|
|
416
|
-
end
|
|
417
|
-
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
FOOTER
|
|
418
438
|
end
|
|
419
439
|
end
|
|
420
440
|
end
|
|
441
|
+
|
|
442
|
+
# rubocop:enable Style/PerlBackrefs
|
data/lib/junoser/squash.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'junoser'
|
|
2
4
|
require 'parslet'
|
|
3
5
|
|
|
@@ -22,9 +24,9 @@ module Junoser
|
|
|
22
24
|
when /^activate /
|
|
23
25
|
delete_lines l.gsub(/^activate /, 'deactivate ')
|
|
24
26
|
when /^insert (.*) before (.*)/
|
|
25
|
-
insert_before "set #{
|
|
27
|
+
insert_before "set #{::Regexp.last_match(1)}", ::Regexp.last_match(2)
|
|
26
28
|
when /^insert (.*) after (.*)/
|
|
27
|
-
insert_after "set #{
|
|
29
|
+
insert_after "set #{::Regexp.last_match(1)}", ::Regexp.last_match(2)
|
|
28
30
|
end
|
|
29
31
|
end
|
|
30
32
|
|
|
@@ -36,11 +38,11 @@ module Junoser
|
|
|
36
38
|
|
|
37
39
|
def remove_command_context(lines)
|
|
38
40
|
lines.each_with_index do |l, i|
|
|
39
|
-
lines[i
|
|
40
|
-
if l2[-1] ==
|
|
41
|
-
lines.delete(l2) if l.include?(l2)
|
|
42
|
-
|
|
43
|
-
lines.delete(l2)
|
|
41
|
+
lines[i..].each do |l2|
|
|
42
|
+
if l2[-1] == ' ' # l2 is a command context
|
|
43
|
+
lines.delete(l2) if l.include?(l2) && (l != l2)
|
|
44
|
+
elsif l.include?("#{l2} ") # l2 has argument
|
|
45
|
+
lines.delete(l2)
|
|
44
46
|
end
|
|
45
47
|
end
|
|
46
48
|
end
|
|
@@ -48,24 +50,24 @@ module Junoser
|
|
|
48
50
|
|
|
49
51
|
def delete_lines(pattern)
|
|
50
52
|
@lines.each do |l|
|
|
51
|
-
l.sub!(/#{pattern}/) {
|
|
53
|
+
l.sub!(/#{pattern}/) { ::Regexp.last_match(1) }
|
|
52
54
|
end
|
|
53
55
|
end
|
|
54
56
|
|
|
55
57
|
def split_last_token(line)
|
|
56
58
|
tokens = join_arg(@transformer.apply(@parser.parse(line))).split("\n")
|
|
57
|
-
tokens.map!
|
|
58
|
-
t.gsub!(/arg\((.*)\)/) {
|
|
59
|
+
tokens.map! do |t|
|
|
60
|
+
t.gsub!(/arg\((.*)\)/) { ::Regexp.last_match(1).to_s } # Strip arg
|
|
59
61
|
Regexp.escape(t.strip)
|
|
60
|
-
|
|
62
|
+
end
|
|
61
63
|
|
|
62
64
|
[tokens[0..-2].join(' '), tokens.last]
|
|
63
65
|
end
|
|
64
66
|
|
|
65
67
|
# Ported from lib/junoser/display/config_store.rb
|
|
66
68
|
def join_arg(str)
|
|
67
|
-
str.gsub!(/\narg\((.*)\)$/) { "
|
|
68
|
-
str.gsub!(/arg\((.*)\)/) {
|
|
69
|
+
str.gsub!(/\narg\((.*)\)$/) { " #{::Regexp.last_match(1)}" }
|
|
70
|
+
str.gsub!(/arg\((.*)\)/) { ::Regexp.last_match(1).to_s }
|
|
69
71
|
str
|
|
70
72
|
end
|
|
71
73
|
|
|
@@ -76,7 +78,7 @@ module Junoser
|
|
|
76
78
|
|
|
77
79
|
def insert_before(statement_to_insert, key_statement)
|
|
78
80
|
key_tokens = key_statement.strip.split
|
|
79
|
-
key_statement = (statement_to_insert.strip.split[0..-(key_tokens.size+1)] + key_tokens).join(' ')
|
|
81
|
+
key_statement = (statement_to_insert.strip.split[0..-(key_tokens.size + 1)] + key_tokens).join(' ')
|
|
80
82
|
|
|
81
83
|
lines_to_insert = @lines.select { |l| l.include?(statement_to_insert) }
|
|
82
84
|
@lines.reject! { |l| l.include?(statement_to_insert) }
|
data/lib/junoser/transformer.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'parslet'
|
|
2
4
|
|
|
3
5
|
module Junoser
|
|
@@ -24,7 +26,7 @@ module Junoser
|
|
|
24
26
|
|
|
25
27
|
rule(label: simple(:label), child: sequence(:children)) do
|
|
26
28
|
Junoser::Transformer.remove_slash_asterisk children
|
|
27
|
-
%
|
|
29
|
+
%(#{label}\n#{children.join("\n")})
|
|
28
30
|
end
|
|
29
31
|
|
|
30
32
|
rule(statement: simple(:statement), argument: simple(:argument)) do
|
|
@@ -33,7 +35,7 @@ module Junoser
|
|
|
33
35
|
|
|
34
36
|
rule(statement: simple(:statement), argument: sequence(:arguments)) do
|
|
35
37
|
Junoser::Transformer.remove_slash_asterisk arguments
|
|
36
|
-
%
|
|
38
|
+
%(#{statement}\n#{arguments.join("\n")})
|
|
37
39
|
end
|
|
38
40
|
|
|
39
41
|
rule(oneline: simple(:str)) do
|
|
@@ -52,15 +54,14 @@ module Junoser
|
|
|
52
54
|
strs.join(' ')
|
|
53
55
|
end
|
|
54
56
|
|
|
55
|
-
|
|
56
57
|
def self.remove_slash_asterisk(array)
|
|
57
58
|
open = array.index("arg(/*)\n")
|
|
58
|
-
close = array.index(
|
|
59
|
+
close = array.index('arg(*/)')
|
|
60
|
+
|
|
61
|
+
return unless open && close
|
|
59
62
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
array.delete_at i
|
|
63
|
-
end
|
|
63
|
+
(open..close).reverse_each do |i|
|
|
64
|
+
array.delete_at i
|
|
64
65
|
end
|
|
65
66
|
end
|
|
66
67
|
end
|
data/lib/junoser/version.rb
CHANGED