slate 0.0.5 → 0.1.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/.gitignore +1 -0
- data/README.md +5 -0
- data/lib/slate.rb +1 -0
- data/lib/slate/parser.rb +73 -0
- data/lib/slate/parser/extensions.rb +49 -0
- data/lib/slate/parser/slate_tree.treetop +31 -0
- data/lib/slate/version.rb +1 -1
- data/slate.gemspec +1 -0
- data/spec/slate/parser_spec.rb +95 -0
- metadata +25 -4
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -29,3 +29,8 @@ TODO: Write usage instructions here
|
|
29
29
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
30
30
|
4. Push to the branch (`git push origin my-new-feature`)
|
31
31
|
5. Create new Pull Request
|
32
|
+
|
33
|
+
## Contributors
|
34
|
+
|
35
|
+
Trae Robrock (https://github.com/trobrock)
|
36
|
+
Andrew Katz (https://github.com/andrewkatz)
|
data/lib/slate.rb
CHANGED
data/lib/slate/parser.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'treetop'
|
2
|
+
require 'slate/parser/extensions'
|
3
|
+
Treetop.load File.join(File.dirname(__FILE__), 'parser', 'slate_tree')
|
4
|
+
|
5
|
+
module Slate
|
6
|
+
class NotParseable < StandardError ; end
|
7
|
+
|
8
|
+
class Parser
|
9
|
+
include Singleton
|
10
|
+
|
11
|
+
def self.parse(data)
|
12
|
+
self.instance.parse(data)
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@parser = SlateTreeParser.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse(data)
|
20
|
+
raise Slate::NotParseable if data.nil?
|
21
|
+
|
22
|
+
parsed_tree = @parser.parse(data)
|
23
|
+
|
24
|
+
raise Slate::NotParseable if parsed_tree.nil?
|
25
|
+
|
26
|
+
parse_tree(parsed_tree)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def parse_tree(element, target=nil)
|
32
|
+
case element
|
33
|
+
when SlateTree::Target
|
34
|
+
target ||= Slate::Target.build(element.text_value)
|
35
|
+
when SlateTree::Function
|
36
|
+
args = arguments(element).map do |arg|
|
37
|
+
if is_target? arg
|
38
|
+
parse_tree arg
|
39
|
+
else
|
40
|
+
arg.text_value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
target.add_function element.text_value, *args
|
45
|
+
end
|
46
|
+
element.elements.each { |e| target = parse_tree(e, target) } if should_recurse?(element)
|
47
|
+
|
48
|
+
target
|
49
|
+
end
|
50
|
+
|
51
|
+
def arguments(element)
|
52
|
+
element.elements.last.elements.select do |e|
|
53
|
+
is_argument?(e) || is_target?(e)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def should_recurse?(element)
|
58
|
+
!element.terminal? && !is_function?(element)
|
59
|
+
end
|
60
|
+
|
61
|
+
def is_function?(element)
|
62
|
+
element.is_a? SlateTree::Function
|
63
|
+
end
|
64
|
+
|
65
|
+
def is_argument?(element)
|
66
|
+
element.is_a? SlateTree::Argument
|
67
|
+
end
|
68
|
+
|
69
|
+
def is_target?(element)
|
70
|
+
element.is_a? SlateTree::Target
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Slate
|
2
|
+
module SlateTree
|
3
|
+
class Target < Treetop::Runtime::SyntaxNode
|
4
|
+
def type
|
5
|
+
:target
|
6
|
+
end
|
7
|
+
|
8
|
+
def text_value
|
9
|
+
elements.detect{ |e| e.is_a? String }.text_value
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Function < Treetop::Runtime::SyntaxNode
|
14
|
+
def type
|
15
|
+
:function
|
16
|
+
end
|
17
|
+
|
18
|
+
def text_value
|
19
|
+
elements.detect{ |e| e.is_a? Token }.text_value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Token < Treetop::Runtime::SyntaxNode
|
24
|
+
def type
|
25
|
+
:token
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Argument < Treetop::Runtime::SyntaxNode
|
30
|
+
def type
|
31
|
+
:argument
|
32
|
+
end
|
33
|
+
|
34
|
+
def text_value
|
35
|
+
elements.first.text_value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class String < Treetop::Runtime::SyntaxNode
|
40
|
+
def type
|
41
|
+
:string
|
42
|
+
end
|
43
|
+
|
44
|
+
def text_value
|
45
|
+
super.gsub(/"/,'')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Slate
|
2
|
+
grammar SlateTree
|
3
|
+
rule document
|
4
|
+
(target / space)*
|
5
|
+
end
|
6
|
+
|
7
|
+
rule target
|
8
|
+
space? string space '{' space? function* space? '}' <Target>
|
9
|
+
end
|
10
|
+
|
11
|
+
rule function
|
12
|
+
token space? (target / argument)* <Function>
|
13
|
+
end
|
14
|
+
|
15
|
+
rule argument
|
16
|
+
string ','? space? <Argument>
|
17
|
+
end
|
18
|
+
|
19
|
+
rule token
|
20
|
+
[a-zA-Z]+ <Token>
|
21
|
+
end
|
22
|
+
|
23
|
+
rule string
|
24
|
+
'"' ('\"' / !'"' .)* '"' <String>
|
25
|
+
end
|
26
|
+
|
27
|
+
rule space
|
28
|
+
[\s]+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/slate/version.rb
CHANGED
data/slate.gemspec
CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |gem|
|
|
20
20
|
gem.add_dependency "rest-client", "~> 1.6.7"
|
21
21
|
gem.add_dependency "json", "~> 1.7.5"
|
22
22
|
gem.add_dependency "jruby-openssl" if RUBY_PLATFORM == 'java'
|
23
|
+
gem.add_dependency "treetop", "~> 1.4.12"
|
23
24
|
|
24
25
|
gem.add_development_dependency "rake"
|
25
26
|
gem.add_development_dependency "rspec"
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Slate::Parser do
|
4
|
+
before do
|
5
|
+
Slate.configure { |c| c.endpoint = "http://graphite" }
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should raise an exception if it cannot parse" do
|
9
|
+
expect {
|
10
|
+
Slate::Parser.parse(nil)
|
11
|
+
}.to raise_error(Slate::NotParseable)
|
12
|
+
|
13
|
+
expect {
|
14
|
+
Slate::Parser.parse("bob")
|
15
|
+
}.to raise_error(Slate::NotParseable)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should parse a basic target" do
|
19
|
+
target = Slate::Target.build("stats.web01.response_time")
|
20
|
+
|
21
|
+
Slate::Parser.parse(%q{
|
22
|
+
"stats.web01.response_time" {}
|
23
|
+
}).to_s.should == target.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should be able to parse a target with one function" do
|
27
|
+
target = Slate::Target.build("stats.web01.response_time") do |t|
|
28
|
+
t.add_function :sum
|
29
|
+
end
|
30
|
+
|
31
|
+
Slate::Parser.parse(%q{
|
32
|
+
"stats.web01.response_time" { sum }
|
33
|
+
}).to_s.should == target.to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should be able to parse a target with one function and single arg" do
|
37
|
+
target = Slate::Target.build("stats.web01.response_time") do |t|
|
38
|
+
t.add_function :summarize, "5min"
|
39
|
+
end
|
40
|
+
|
41
|
+
Slate::Parser.parse(%q{
|
42
|
+
"stats.web01.response_time" {
|
43
|
+
summarize "5min"
|
44
|
+
}
|
45
|
+
}).to_s.should == target.to_s
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should be able to parse a target with one function and multiple args" do
|
49
|
+
target = Slate::Target.build("stats.web01.response_time") do |t|
|
50
|
+
t.add_function :summarize, "5min", "avg"
|
51
|
+
end
|
52
|
+
|
53
|
+
Slate::Parser.parse(%q{
|
54
|
+
"stats.web01.response_time" {
|
55
|
+
summarize "5min", "avg"
|
56
|
+
}
|
57
|
+
}).to_s.should == target.to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should be able to parse a target with multiple functions" do
|
61
|
+
target = Slate::Target.build("stats.web01.response_time") do |t|
|
62
|
+
t.add_function :sum
|
63
|
+
t.add_function :summarize, "5min", "avg"
|
64
|
+
end
|
65
|
+
|
66
|
+
Slate::Parser.parse(%q{
|
67
|
+
"stats.web01.response_time" {
|
68
|
+
sum
|
69
|
+
summarize "5min", "avg"
|
70
|
+
}
|
71
|
+
}).to_s.should == target.to_s
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should be able to parse a really complex target" do
|
75
|
+
nested_target = Slate::Target.build("stats_counts.rack.*.status_code.*") do |t|
|
76
|
+
t.add_function :exclude, "missing"
|
77
|
+
t.add_function :sum
|
78
|
+
end
|
79
|
+
|
80
|
+
target = Slate::Target.build("stats_counts.rack.*.status_code.success") do |t|
|
81
|
+
t.add_function :sum
|
82
|
+
t.add_function :asPercent, nested_target
|
83
|
+
end
|
84
|
+
|
85
|
+
Slate::Parser.parse(%q{
|
86
|
+
"stats_counts.rack.*.status_code.success" {
|
87
|
+
sum
|
88
|
+
asPercent "stats_counts.rack.*.status_code.*" {
|
89
|
+
exclude "missing"
|
90
|
+
sum
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}).to_s.should == target.to_s
|
94
|
+
end
|
95
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rest-client
|
@@ -43,6 +43,22 @@ dependencies:
|
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: 1.7.5
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: treetop
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.4.12
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.4.12
|
46
62
|
- !ruby/object:Gem::Dependency
|
47
63
|
name: rake
|
48
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -126,12 +142,16 @@ files:
|
|
126
142
|
- lib/slate/calculation/mean.rb
|
127
143
|
- lib/slate/configuration.rb
|
128
144
|
- lib/slate/graph.rb
|
145
|
+
- lib/slate/parser.rb
|
146
|
+
- lib/slate/parser/extensions.rb
|
147
|
+
- lib/slate/parser/slate_tree.treetop
|
129
148
|
- lib/slate/target.rb
|
130
149
|
- lib/slate/version.rb
|
131
150
|
- slate.gemspec
|
132
151
|
- spec/slate/calculation/last_spec.rb
|
133
152
|
- spec/slate/calculation/mean_spec.rb
|
134
153
|
- spec/slate/graph_spec.rb
|
154
|
+
- spec/slate/parser_spec.rb
|
135
155
|
- spec/slate_spec.rb
|
136
156
|
- spec/spec_helper.rb
|
137
157
|
homepage: https://github.com/trobrock/slate
|
@@ -148,7 +168,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
148
168
|
version: '0'
|
149
169
|
segments:
|
150
170
|
- 0
|
151
|
-
hash:
|
171
|
+
hash: 3951322141183346689
|
152
172
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
173
|
none: false
|
154
174
|
requirements:
|
@@ -157,7 +177,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
157
177
|
version: '0'
|
158
178
|
segments:
|
159
179
|
- 0
|
160
|
-
hash:
|
180
|
+
hash: 3951322141183346689
|
161
181
|
requirements: []
|
162
182
|
rubyforge_project:
|
163
183
|
rubygems_version: 1.8.24
|
@@ -168,5 +188,6 @@ test_files:
|
|
168
188
|
- spec/slate/calculation/last_spec.rb
|
169
189
|
- spec/slate/calculation/mean_spec.rb
|
170
190
|
- spec/slate/graph_spec.rb
|
191
|
+
- spec/slate/parser_spec.rb
|
171
192
|
- spec/slate_spec.rb
|
172
193
|
- spec/spec_helper.rb
|