mallinna 0.0.2

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 05a38f928da3bea1a216060832b7a371efcae6e7
4
+ data.tar.gz: 7262a8d7a83b458fe5c1943bb101013e402b546a
5
+ SHA512:
6
+ metadata.gz: 565b2a393437c24dcebe207cb1efa4e828b819d6bb980dd7a17dc13f28124f8f2eb15aebe2410a91f589c320e8690e92322069bf2d4fe0503eb1af8f54a8bc2c
7
+ data.tar.gz: ac44b2df593e894b243eaac63e41892d3c2ee74b5920f2230c0fe49273528f077215a213a4aa21a7870c11a908a55ebca57f0b8cda6419b332856a4b9e425732
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
@@ -0,0 +1,73 @@
1
+ # Malline
2
+
3
+ Malline is template engine targeting IOS/JunOS or generally configurations (or
4
+ more accurately what ever text stuff I'm doing).
5
+
6
+ It surfaced from the need to do something like this in ERB:
7
+ ```
8
+ interfaces {
9
+ <%= name %> {
10
+ description "<%if description %>";
11
+ }
12
+ }
13
+ ```
14
+
15
+ where description "description"; is only output if the code evaluates true,
16
+ keeping the template clean in common use-case
17
+
18
+ ```
19
+ Consider this code
20
+ require_relative './lib/malline'
21
+ require 'pry'
22
+ class Int
23
+ attr_accessor :name, :mtu, :description, :poop
24
+ def initialize
25
+ @name = 'xe-1/2/3.42'
26
+ @mtu = 1500
27
+ @description = 'K: S-123455 - poop customer'
28
+ @poop = true
29
+ end
30
+ def get_binding
31
+ binding
32
+ end
33
+ end
34
+
35
+ template = <<EOF
36
+ interfaces {
37
+ <% name %> {
38
+ mtu <%if mtu %>;
39
+ description "<%if description %>";
40
+ }
41
+ }
42
+ EOF
43
+
44
+ int = Int.new
45
+ cfg = Malline.run template, int.get_binding
46
+ binding.pry
47
+ ```
48
+
49
+ Real use might look something like this:
50
+ ```
51
+ [1] pry(main)> puts cfg
52
+ interfaces {
53
+ xe-1/2/3.42 {
54
+ mtu 1500;
55
+ description "K: S-123455 - poop customer";
56
+ }
57
+ }
58
+ => nil
59
+ [2] pry(main)> int.mtu = 900
60
+ => 900
61
+ [3] pry(main)> int.description = nil
62
+ => nil
63
+ [4] pry(main)> puts Malline.run template, int.get_binding
64
+ interfaces {
65
+ xe-1/2/3.42 {
66
+ mtu 900;
67
+ }
68
+ }
69
+ => nil
70
+ ```
71
+
72
+
73
+
@@ -0,0 +1,48 @@
1
+ require 'rake/testtask'
2
+
3
+ rule '.rb' => '.y' do |t|
4
+ sh "racc -l -o #{t.name} #{t.source}"
5
+ end
6
+ gemspec = eval(File.read(Dir['*.gemspec'].first))
7
+ file = [gemspec.name, gemspec.version].join('-') + '.gem'
8
+
9
+ desc 'Validate gemspec'
10
+ task :gemspec do
11
+ gemspec.validate
12
+ end
13
+
14
+ desc 'Run minitest'
15
+ task :test => :compile do
16
+ Rake::TestTask.new do |t|
17
+ t.libs.push "lib"
18
+ all = FileList['spec/*_spec.rb']
19
+ first = %w(spec/lexer_spec.rb spec/handler_spec.rb)
20
+ t.test_files = [first, all-first].flatten
21
+ t.verbose = true
22
+ end
23
+ end
24
+
25
+ desc 'Compile RACC parser'
26
+ task :compile => 'lib/malline/parser.rb'
27
+
28
+ desc 'Build gem'
29
+ task :build => [:gemspec, :test] do
30
+ system "gem build #{gemspec.name}.gemspec"
31
+ FileUtils.mkdir_p 'gems'
32
+ FileUtils.mv file, 'gems'
33
+ end
34
+
35
+ desc 'Install gem'
36
+ task :install => :build do
37
+ system "sudo sh -c \'umask 022; gem install gems/#{file}\'"
38
+ end
39
+
40
+ desc 'Remove gems'
41
+ task :clean do
42
+ FileUtils.rm_rf 'gems'
43
+ end
44
+
45
+ desc 'Push to rubygems'
46
+ task :push do
47
+ system "gem push gems/#{file}"
48
+ end
@@ -0,0 +1,14 @@
1
+ module Malline
2
+ require_relative './malline/lexer'
3
+ require_relative './malline/parser'
4
+ require_relative './malline/compiler.rb'
5
+
6
+ def self.run template, binding
7
+ lex = Lexer.new template
8
+ par = Parser.new lex
9
+ han = par.parse
10
+ com = Compiler.new han.parsed
11
+ template = com.compile
12
+ eval(template, binding)
13
+ end
14
+ end
@@ -0,0 +1,95 @@
1
+ module Malline
2
+ class Compiler
3
+ VAR = '_malline_'
4
+ OUT = VAR + '_out'
5
+ class InvalidKind < NameError; end
6
+ attr_reader :out
7
+ def initialize parsed
8
+ @parsed = parsed
9
+ @out = nil
10
+ @cmd = {
11
+ :if => {
12
+ :now => 0,
13
+ :line => [],
14
+ :id => [],
15
+ },
16
+ }
17
+ end
18
+
19
+ def compile
20
+ @out = resolve(combine)
21
+ end
22
+
23
+ def combine
24
+ out = []
25
+ @parsed.each do |e|
26
+ case kind=e.shift
27
+ when :data then data(out, *e)
28
+ when :code then code(out, *e)
29
+ else
30
+ raise InvalidKind, "'#{kind}' was not recognized"
31
+ end
32
+ end
33
+ out
34
+ end
35
+
36
+ def data out, str, lines
37
+ lines = (lines.first .. lines.last).to_a
38
+ str.lines.each_with_index do |line, index|
39
+ linenr = lines[index]
40
+ line = '%s.concat \'%s\'' % [OUT, line.gsub(/'/, %q(\\\'))]
41
+ out << [line, linenr]
42
+ end
43
+ end
44
+
45
+ def code out, cmd, str, lines
46
+ lines = (lines.first .. lines.last).to_a
47
+ str.lines.each_with_index do |line, index|
48
+ linenr = lines[index]
49
+ line = cmd_if(line, lines, @cmd[:if][:now]+=1) if cmd == :if
50
+ line = '%s.concat %s' % [OUT, line] unless cmd == :s
51
+ out << ["#{line}.to_s", linenr]
52
+ end
53
+ end
54
+
55
+
56
+ def cmd_if str, lines, id
57
+ name = VAR+'if_'+id.to_s
58
+ (lines.first .. lines.last).each do |line|
59
+ @cmd[:if][:line][line] ||= []
60
+ @cmd[:if][:line][line] << id
61
+ @cmd[:if][:id][id] = [name, str]
62
+ end
63
+ name
64
+ end
65
+
66
+ def resolve out_org
67
+ out = ["#{OUT}='';"]
68
+ cmp = []
69
+ seen = []
70
+ out_org.each do |line, line_nr|
71
+ resolve_cmd_if(line_nr, cmp, out) unless seen.include? line_nr
72
+ seen << line_nr
73
+ if not cmp.empty?
74
+ line = line + ' if ' + cmp.join(' and ')
75
+ end
76
+ out << line + ';'
77
+ end
78
+ out << "#{OUT}"
79
+ out.join "\n"
80
+ end
81
+
82
+ def resolve_cmd_if line_nr, cmp, out
83
+ cmp.clear
84
+ set = []
85
+ [@cmd[:if][:line][line_nr]].flatten.compact.each do |cmd_id|
86
+ varname, varvalue = @cmd[:if][:id][cmd_id]
87
+ set << [varname,varvalue]
88
+ cmp << varname
89
+ end
90
+ set.each do |name, value|
91
+ out << name + '=' + value + ';'
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,17 @@
1
+ module Malline
2
+ class Handler
3
+ attr_reader :parsed
4
+ attr_accessor :token_line
5
+ def initialize
6
+ @parsed = []
7
+ end
8
+
9
+ def code string, cmd=nil
10
+ @parsed << [:code, cmd, string, token_line]
11
+ end
12
+
13
+ def data string
14
+ @parsed << [:data, string, token_line]
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,36 @@
1
+ require 'strscan'
2
+ require 'stringio'
3
+
4
+ module Malline
5
+ class Lexer
6
+ TOKEN = {
7
+ :START_CODE => /<%(if|s)?/,
8
+ :END_CODE => /%>/,
9
+ }
10
+
11
+ def initialize io
12
+ io = StringIO.new io if io.class == String
13
+ @ss = StringScanner.new io.read
14
+ @token, @state = [], [:CODE, :DATA]
15
+ end
16
+
17
+ def next_token
18
+ return @token.shift unless @token.empty?
19
+ return if @ss.eos?
20
+
21
+ start = line
22
+ name = @state.rotate!.first == :DATA ? :START_CODE : :END_CODE
23
+ if data = @ss.scan_until(TOKEN[name])
24
+ @token << [name, @ss.matched, start, line]
25
+ @token << [:CMD, @ss.matched[2..-1], start, line] if @ss.matched.size > 2
26
+ [:DATA, data[0..-(@ss.matched.size+1)], start, line]
27
+ else #gobble gobble gobble
28
+ [:DATA, @ss.scan(/.*/m), start, line]
29
+ end
30
+ end
31
+
32
+ def line
33
+ @ss.string[0..@ss.pos].lines.count
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,152 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.11
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+ module Malline
9
+ class Parser < Racc::Parser
10
+
11
+
12
+ require_relative 'handler'
13
+
14
+ def initialize lexer, handler=Handler.new
15
+ @lexer = lexer
16
+ @handler = handler
17
+ super()
18
+ end
19
+
20
+ def next_token
21
+ token, string, start_line, end_line = @lexer.next_token
22
+ @handler.token_line = [start_line, end_line]
23
+ [token, string] if token
24
+ end
25
+
26
+ def parse
27
+ do_parse
28
+ @handler
29
+ end
30
+ ##### State transition tables begin ###
31
+
32
+ racc_action_table = [
33
+ 7, 5, 5, 6, 6, 9, 11, 10, 12, 13,
34
+ 14, 15 ]
35
+
36
+ racc_action_check = [
37
+ 1, 0, 1, 0, 1, 5, 5, 5, 7, 10,
38
+ 11, 13 ]
39
+
40
+ racc_action_pointer = [
41
+ -1, 0, nil, nil, nil, 2, nil, 8, nil, nil,
42
+ 5, 7, nil, 8, nil, nil ]
43
+
44
+ racc_action_default = [
45
+ -9, -9, -2, -3, -4, -9, -8, -9, -1, -5,
46
+ -9, -9, 16, -9, -7, -6 ]
47
+
48
+ racc_goto_table = [
49
+ 2, 8, 1 ]
50
+
51
+ racc_goto_check = [
52
+ 2, 2, 1 ]
53
+
54
+ racc_goto_pointer = [
55
+ nil, 2, 0, nil, nil ]
56
+
57
+ racc_goto_default = [
58
+ nil, nil, nil, 3, 4 ]
59
+
60
+ racc_reduce_table = [
61
+ 0, 0, :racc_error,
62
+ 2, 7, :_reduce_none,
63
+ 1, 7, :_reduce_none,
64
+ 1, 8, :_reduce_none,
65
+ 1, 8, :_reduce_none,
66
+ 2, 9, :_reduce_none,
67
+ 4, 9, :_reduce_6,
68
+ 3, 9, :_reduce_7,
69
+ 1, 10, :_reduce_8 ]
70
+
71
+ racc_reduce_n = 9
72
+
73
+ racc_shift_n = 16
74
+
75
+ racc_token_table = {
76
+ false => 0,
77
+ :error => 1,
78
+ :START_CODE => 2,
79
+ :END_CODE => 3,
80
+ :DATA => 4,
81
+ :CMD => 5 }
82
+
83
+ racc_nt_base = 6
84
+
85
+ racc_use_result_var = true
86
+
87
+ Racc_arg = [
88
+ racc_action_table,
89
+ racc_action_check,
90
+ racc_action_default,
91
+ racc_action_pointer,
92
+ racc_goto_table,
93
+ racc_goto_check,
94
+ racc_goto_default,
95
+ racc_goto_pointer,
96
+ racc_nt_base,
97
+ racc_reduce_table,
98
+ racc_token_table,
99
+ racc_shift_n,
100
+ racc_reduce_n,
101
+ racc_use_result_var ]
102
+
103
+ Racc_token_to_s_table = [
104
+ "$end",
105
+ "error",
106
+ "START_CODE",
107
+ "END_CODE",
108
+ "DATA",
109
+ "CMD",
110
+ "$start",
111
+ "values",
112
+ "value",
113
+ "code_block",
114
+ "data" ]
115
+
116
+ Racc_debug_parser = false
117
+
118
+ ##### State transition tables end #####
119
+
120
+ # reduce 0 omitted
121
+
122
+ # reduce 1 omitted
123
+
124
+ # reduce 2 omitted
125
+
126
+ # reduce 3 omitted
127
+
128
+ # reduce 4 omitted
129
+
130
+ # reduce 5 omitted
131
+
132
+ def _reduce_6(val, _values, result)
133
+ @handler.code(val[2], val[1].to_sym)
134
+ result
135
+ end
136
+
137
+ def _reduce_7(val, _values, result)
138
+ @handler.code val[1]
139
+ result
140
+ end
141
+
142
+ def _reduce_8(val, _values, result)
143
+ @handler.data val.first
144
+ result
145
+ end
146
+
147
+ def _reduce_none(val, _values, result)
148
+ val[0]
149
+ end
150
+
151
+ end # class Parser
152
+ end # module Malline
@@ -0,0 +1,40 @@
1
+ class Malline::Parser
2
+ token START_CODE END_CODE DATA CMD
3
+ rule
4
+ values
5
+ : values value
6
+ | value
7
+ ;
8
+ value
9
+ : code_block
10
+ | data
11
+ ;
12
+ code_block
13
+ : START_CODE END_CODE
14
+ | START_CODE CMD DATA END_CODE { @handler.code(val[2], val[1].to_sym) }
15
+ | START_CODE DATA END_CODE { @handler.code val[1] }
16
+ ;
17
+ data : DATA { @handler.data val.first }
18
+
19
+ end
20
+
21
+ ---- inner
22
+
23
+ require_relative 'handler'
24
+
25
+ def initialize lexer, handler=Handler.new
26
+ @lexer = lexer
27
+ @handler = handler
28
+ super()
29
+ end
30
+
31
+ def next_token
32
+ token, string, start_line, end_line = @lexer.next_token
33
+ @handler.token_line = [start_line, end_line]
34
+ [token, string] if token
35
+ end
36
+
37
+ def parse
38
+ do_parse
39
+ @handler
40
+ end
@@ -0,0 +1,17 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'mallinna'
3
+ s.version = '0.0.2'
4
+ s.platform = Gem::Platform::RUBY
5
+ s.authors = [ 'Saku Ytti' ]
6
+ s.email = %w( saku@ytti.fi )
7
+ s.homepage = 'https://github.com/ytti/malline'
8
+ s.summary = 'Templating language targeting IOS/JunOS configs'
9
+ s.description = 'Mostly like ERB, but <%if foo%> conditional will omit whole line unless code evaluates true'
10
+ s.rubyforge_project = s.name
11
+ s.files = `git ls-files`.split("\n")
12
+ s.require_path = 'lib'
13
+
14
+ # s.add_dependency 'bundler'
15
+
16
+ s.add_development_dependency 'racc'
17
+ end
@@ -0,0 +1,44 @@
1
+ require_relative 'spec_helper.rb'
2
+
3
+ class Int
4
+ attr_accessor :name, :mtu, :description, :vrf
5
+ def initialize
6
+ @name = 'xe-1/2/3'
7
+ @mtu = 1500
8
+ @description = 'K: S-12345 foobar \'quote\' xyzzy'
9
+ @vrf = 'VRF0001'
10
+ end
11
+ def get_binding; binding; end
12
+ end
13
+
14
+ describe Compiler do
15
+ #it "can be created with string argument" do
16
+ # Lexer.new('k').must_be_instance_of Lexer
17
+ #end
18
+
19
+ #it "can't be created without an argument" do
20
+ # ->{Lexer.new}.must_raise ArgumentError
21
+ #end
22
+
23
+ it "must pass junos example" do
24
+ int = Int.new
25
+ str = Malline.run TemplateJunOS, int.get_binding
26
+ str.must_equal ResultJunOS[0]
27
+ int.description = nil
28
+ int.mtu = 42
29
+ str = Malline.run TemplateJunOS, int.get_binding
30
+ str.must_equal ResultJunOS[1]
31
+ end
32
+
33
+ it "must pass ios example" do
34
+ int = Int.new
35
+ int.name = 'GigabitEthernet0/42'
36
+ str = Malline.run TemplateIOS, int.get_binding
37
+ str.must_equal ResultIOS[0]
38
+ int.description = 'f00fc7c8'
39
+ int.mtu = nil
40
+ int.vrf = 'xyzzy'
41
+ str = Malline.run TemplateIOS, int.get_binding
42
+ str.must_equal ResultIOS[1]
43
+ end
44
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'spec_helper.rb'
2
+
3
+ def get_handler string
4
+ lex = Lexer.new string
5
+ par = Parser.new lex
6
+ par.parse
7
+ end
8
+
9
+ describe Handler do
10
+
11
+ it "can be created" do
12
+ Handler.new.must_be_instance_of Handler
13
+ end
14
+
15
+ it "must get correctly parsed data" do
16
+ # yeah bit of a cope out :)
17
+ TEST.each do |tst|
18
+ han = get_handler tst[:string]
19
+ han.parsed.must_equal tst[:parsed]
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ require_relative 'spec_helper.rb'
2
+ describe Lexer do
3
+ it "can be created with string argument" do
4
+ Lexer.new('k').must_be_instance_of Lexer
5
+ end
6
+
7
+ it "can't be created without an argument" do
8
+ ->{Lexer.new}.must_raise ArgumentError
9
+ end
10
+
11
+ it "must lex correctly" do
12
+ # yeah bit of a cope out :)
13
+ TEST.each do |tst|
14
+ lex = Lexer.new tst[:string]
15
+ ary, token = [], nil
16
+ ary << token while token = lex.next_token
17
+ ary.must_equal tst[:lex]
18
+ end
19
+ end
20
+
21
+ describe '#line' do
22
+ it 'must not consider trailing \n as new line' do
23
+ lex = Lexer.new "foo\n"
24
+ ss = lex.instance_variable_get :@ss
25
+ ss.scan_until(/.*/m)
26
+ lex.line.must_equal 1
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,82 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/pride'
3
+ require_relative '../lib/malline.rb'
4
+ include Malline
5
+
6
+ class Int
7
+ attr_accessor :name, :mtu, :description, :vrf
8
+ def initialize
9
+ @name = 'xe-1/2/3'
10
+ @mtu = 1500
11
+ @description = 'K: S-12345 foobar \'quote\' xyzzy'
12
+ @vrf = 'VRF0001'
13
+ end
14
+ def get_binding; binding; end
15
+ end
16
+
17
+ TemplateJunOS = <<EOF
18
+ interfaces {
19
+ <% name %> {
20
+ mtu <%if mtu %>;
21
+ description "<%if description %>";
22
+ }
23
+ }
24
+ EOF
25
+ TemplateIOS = <<EOF
26
+ interface <% name %>
27
+ description <%if description %>
28
+ mtu <%if mtu %>
29
+ vrf forwarding <%if vrf %>
30
+ EOF
31
+
32
+ ResultJunOS = []
33
+ ResultJunOS << <<EOF
34
+ interfaces {
35
+ xe-1/2/3 {
36
+ mtu 1500;
37
+ description "K: S-12345 foobar 'quote' xyzzy";
38
+ }
39
+ }
40
+ EOF
41
+ ResultJunOS << <<EOF
42
+ interfaces {
43
+ xe-1/2/3 {
44
+ mtu 42;
45
+ }
46
+ }
47
+ EOF
48
+
49
+ ResultIOS = []
50
+ ResultIOS << <<EOF
51
+ interface GigabitEthernet0/42
52
+ description K: S-12345 foobar 'quote' xyzzy
53
+ mtu 1500
54
+ vrf forwarding VRF0001
55
+ EOF
56
+ ResultIOS << <<EOF
57
+ interface GigabitEthernet0/42
58
+ description f00fc7c8
59
+ vrf forwarding xyzzy
60
+ EOF
61
+
62
+
63
+ TEST = [
64
+ {
65
+ :string => "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
66
+ :lex => [[:DATA, "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", 1, 1]],
67
+ :parsed => [[:data, "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", [1, 1]]],
68
+ },
69
+
70
+ {
71
+ :string => "Lorem ipsum <%dolor sit amet%>, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
72
+ :lex => [[:DATA, "Lorem ipsum ", 1, 1], [:START_CODE, "<%", 1, 1], [:DATA, "dolor sit amet", 1, 1], [:END_CODE, "%>", 1, 1], [:DATA, ", consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", 1, 1]],
73
+ :parsed => [[:data, "Lorem ipsum ", [1, 1]], [:code, nil, "dolor sit amet", [1, 1]], [:data, ", consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", [1, 1]]],
74
+ },
75
+
76
+ {
77
+ :string => "Lorem ipsum <%dolor\nsit amet%>, con\nsectetur <%if testing\n bar\n fooi %> adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
78
+ :lex => [[:DATA, "Lorem ipsum ", 1, 1], [:START_CODE, "<%", 1, 1], [:DATA, "dolor\nsit amet", 1, 2], [:END_CODE, "%>", 1, 2], [:DATA, ", con\nsectetur ", 2, 3], [:START_CODE, "<%if", 2, 3], [:CMD, "if", 2, 3], [:DATA, " testing\n bar\n fooi ", 3, 5], [:END_CODE, "%>", 3, 5], [:DATA, " adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", 5, 5]],
79
+ :parsed => [[:data, "Lorem ipsum ", [1, 1]], [:code, nil, "dolor\nsit amet", [1, 2]], [:data, ", con\nsectetur ", [2, 3]], [:code, :if, " testing\n bar\n fooi ", [3, 5]], [:data, " adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", [5, 5]]],
80
+ },
81
+
82
+ ]
data/tst.rb ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative './lib/malline'
4
+ class Int
5
+ attr_accessor :name, :mtu, :description, :poop
6
+ def initialize
7
+ @name = 'xe-1/2/3.42'
8
+ @mtu = 1500
9
+ @description = 'K: S-123455 - poop customer'
10
+ end
11
+ def get_binding; binding; end
12
+ end
13
+
14
+ template = <<EOF
15
+ interfaces {
16
+ <% name %> {
17
+ mtu <%if mtu %>;
18
+ description "<%if description %>";
19
+ }
20
+ }
21
+ EOF
22
+
23
+ puts Malline.run template, Int.new.get_binding
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mallinna
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Saku Ytti
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: racc
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: Mostly like ERB, but <%if foo%> conditional will omit whole line unless
28
+ code evaluates true
29
+ email:
30
+ - saku@ytti.fi
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - Gemfile
36
+ - README.md
37
+ - Rakefile
38
+ - lib/malline.rb
39
+ - lib/malline/compiler.rb
40
+ - lib/malline/handler.rb
41
+ - lib/malline/lexer.rb
42
+ - lib/malline/parser.rb
43
+ - lib/malline/parser.y
44
+ - mallinna.gemspec
45
+ - spec/compiler_spec.rb
46
+ - spec/handler_spec.rb
47
+ - spec/lexer_spec.rb
48
+ - spec/spec_helper.rb
49
+ - tst.rb
50
+ homepage: https://github.com/ytti/malline
51
+ licenses: []
52
+ metadata: {}
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ requirements: []
68
+ rubyforge_project: mallinna
69
+ rubygems_version: 2.0.14
70
+ signing_key:
71
+ specification_version: 4
72
+ summary: Templating language targeting IOS/JunOS configs
73
+ test_files: []
74
+ has_rdoc: