ESBify 0.0.1 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -2,3 +2,5 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+
6
+ .DS_Store
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>beforeRunningCommand</key>
6
+ <string>saveActiveFile</string>
7
+ <key>command</key>
8
+ <string>#!/usr/bin/env bash
9
+ esbify "$TM_FILEPATH"
10
+ </string>
11
+ <key>input</key>
12
+ <string>document</string>
13
+ <key>keyEquivalent</key>
14
+ <string>@b</string>
15
+ <key>name</key>
16
+ <string>Compile</string>
17
+ <key>output</key>
18
+ <string>showAsTooltip</string>
19
+ <key>scope</key>
20
+ <string>source.esb</string>
21
+ <key>uuid</key>
22
+ <string>985AA142-639A-486B-B777-B358EFE2D2BB</string>
23
+ </dict>
24
+ </plist>
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>name</key>
6
+ <string>Comments</string>
7
+ <key>scope</key>
8
+ <string>source.esb</string>
9
+ <key>settings</key>
10
+ <dict>
11
+ <key>shellVariables</key>
12
+ <array>
13
+ <dict>
14
+ <key>name</key>
15
+ <string>TM_COMMENT_START</string>
16
+ <key>value</key>
17
+ <string># </string>
18
+ </dict>
19
+ </array>
20
+ </dict>
21
+ <key>uuid</key>
22
+ <string>D248DB58-5512-4EB1-BCF1-B3FFC7B2C6AB</string>
23
+ </dict>
24
+ </plist>
@@ -0,0 +1,21 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>content</key>
6
+ <string>name: ${1:name_of_behavior}${2:
7
+ jason: ${3:jason_condition}}${4:
8
+ ctl: ${5:ctl_condition}}
9
+ action: $6
10
+
11
+ ----</string>
12
+ <key>name</key>
13
+ <string>Behavior</string>
14
+ <key>scope</key>
15
+ <string>source.esb</string>
16
+ <key>tabTrigger</key>
17
+ <string>beh</string>
18
+ <key>uuid</key>
19
+ <string>2585098C-57C4-4EA6-AE1A-FAE7CBCF7E94</string>
20
+ </dict>
21
+ </plist>
@@ -0,0 +1,27 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>content</key>
6
+ <string>name: ${1:expectation_name}${2:
7
+ agent: ${3:self}}
8
+ condition: ${4:some_condition}
9
+ phi: ${5:$1}
10
+ ${6:test_plus: $7
11
+ rho_plus:
12
+ ${8:+}}
13
+ ${9:test_minus: $0
14
+ rho_plus:
15
+ }
16
+
17
+ ------</string>
18
+ <key>name</key>
19
+ <string>Expectation</string>
20
+ <key>scope</key>
21
+ <string>source.esb</string>
22
+ <key>tabTrigger</key>
23
+ <string>exp</string>
24
+ <key>uuid</key>
25
+ <string>FEB78640-82A4-4257-AE82-F4A05C8981BE</string>
26
+ </dict>
27
+ </plist>
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>content</key>
6
+ <string>!behaviors
7
+
8
+ ${1:beh}$0</string>
9
+ <key>name</key>
10
+ <string>Header: Behaviors</string>
11
+ <key>scope</key>
12
+ <string>source.esb</string>
13
+ <key>tabTrigger</key>
14
+ <string>!</string>
15
+ <key>uuid</key>
16
+ <string>76EAC2C8-2F4E-433F-9B30-11AE8CAB3C53</string>
17
+ </dict>
18
+ </plist>
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>content</key>
6
+ <string>!expectations
7
+
8
+ ${1:exp}$0</string>
9
+ <key>name</key>
10
+ <string>Header: Expectation</string>
11
+ <key>scope</key>
12
+ <string>source.esb</string>
13
+ <key>tabTrigger</key>
14
+ <string>!</string>
15
+ <key>uuid</key>
16
+ <string>D6051F23-6604-4897-B36E-94719D45F86A</string>
17
+ </dict>
18
+ </plist>
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>content</key>
6
+ <string>!strategies
7
+
8
+ </string>
9
+ <key>name</key>
10
+ <string>Header: Strategies</string>
11
+ <key>scope</key>
12
+ <string>source.esb</string>
13
+ <key>tabTrigger</key>
14
+ <string>!</string>
15
+ <key>uuid</key>
16
+ <string>0686E761-7C22-43A0-9A55-A1B2F8B83690</string>
17
+ </dict>
18
+ </plist>
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>content</key>
6
+ <string>------------
7
+ </string>
8
+ <key>name</key>
9
+ <string>Separator</string>
10
+ <key>scope</key>
11
+ <string>source.esb</string>
12
+ <key>tabTrigger</key>
13
+ <string>-</string>
14
+ <key>uuid</key>
15
+ <string>78931B30-3E26-4FC6-AC18-3E5E9D64D62C</string>
16
+ </dict>
17
+ </plist>
@@ -0,0 +1,115 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>fileTypes</key>
6
+ <array>
7
+ <string>esb</string>
8
+ </array>
9
+ <key>foldingStartMarker</key>
10
+ <string>^[^#]\s*.*:(\s*\[?| &amp;.+)?$</string>
11
+ <key>foldingStopMarker</key>
12
+ <string>^\s*$|^\s*\}|^\s*\]|^\s*\)</string>
13
+ <key>keyEquivalent</key>
14
+ <string>^~@e</string>
15
+ <key>name</key>
16
+ <string>ESB</string>
17
+ <key>patterns</key>
18
+ <array>
19
+ <dict>
20
+ <key>include</key>
21
+ <string>#erb</string>
22
+ </dict>
23
+ <dict>
24
+ <key>match</key>
25
+ <string>!(expectation|behaviou?r|strateg(?:y|ie))s?</string>
26
+ <key>name</key>
27
+ <string>keyword.header.esb</string>
28
+ </dict>
29
+ <dict>
30
+ <key>match</key>
31
+ <string>^\s*([\w_]+\s*\:)</string>
32
+ <key>name</key>
33
+ <string>variable.key.esb</string>
34
+ </dict>
35
+ <dict>
36
+ <key>captures</key>
37
+ <dict>
38
+ <key>1</key>
39
+ <dict>
40
+ <key>name</key>
41
+ <string>keyword.operator.list.esb</string>
42
+ </dict>
43
+ </dict>
44
+ <key>match</key>
45
+ <string>^\s*([\+\-])\s*\w+</string>
46
+ <key>name</key>
47
+ <string>entity.list.esb</string>
48
+ </dict>
49
+ <dict>
50
+ <key>match</key>
51
+ <string>^---+$</string>
52
+ <key>name</key>
53
+ <string>keyword.operator.divider.esb</string>
54
+ </dict>
55
+ <dict>
56
+ <key>match</key>
57
+ <string>\#.*$</string>
58
+ <key>name</key>
59
+ <string>comment.source.esb</string>
60
+ </dict>
61
+ </array>
62
+ <key>repository</key>
63
+ <dict>
64
+ <key>erb</key>
65
+ <dict>
66
+ <key>begin</key>
67
+ <string>&lt;%+(?!&gt;)=?</string>
68
+ <key>captures</key>
69
+ <dict>
70
+ <key>0</key>
71
+ <dict>
72
+ <key>name</key>
73
+ <string>punctuation.section.embedded.ruby</string>
74
+ </dict>
75
+ </dict>
76
+ <key>end</key>
77
+ <string>%&gt;</string>
78
+ <key>name</key>
79
+ <string>source.ruby.rails.embedded.html</string>
80
+ <key>patterns</key>
81
+ <array>
82
+ <dict>
83
+ <key>captures</key>
84
+ <dict>
85
+ <key>1</key>
86
+ <dict>
87
+ <key>name</key>
88
+ <string>punctuation.definition.comment.ruby</string>
89
+ </dict>
90
+ </dict>
91
+ <key>match</key>
92
+ <string>(#).*?(?=%&gt;)</string>
93
+ <key>name</key>
94
+ <string>comment.line.number-sign.ruby</string>
95
+ </dict>
96
+ <dict>
97
+ <key>include</key>
98
+ <string>source.ruby.rails</string>
99
+ </dict>
100
+ </array>
101
+ </dict>
102
+ <key>escaped_char</key>
103
+ <dict>
104
+ <key>match</key>
105
+ <string>\\.</string>
106
+ <key>name</key>
107
+ <string>constant.character.escape.esb</string>
108
+ </dict>
109
+ </dict>
110
+ <key>scopeName</key>
111
+ <string>source.esb</string>
112
+ <key>uuid</key>
113
+ <string>B6D3CCA0-FDC8-442A-8D41-515DD8F93C50</string>
114
+ </dict>
115
+ </plist>
@@ -0,0 +1,37 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>mainMenu</key>
6
+ <dict>
7
+ <key>items</key>
8
+ <array>
9
+ <string>985AA142-639A-486B-B777-B358EFE2D2BB</string>
10
+ <string>------------------------------------</string>
11
+ <string>FEB78640-82A4-4257-AE82-F4A05C8981BE</string>
12
+ <string>2585098C-57C4-4EA6-AE1A-FAE7CBCF7E94</string>
13
+ <string>D6051F23-6604-4897-B36E-94719D45F86A</string>
14
+ <string>0686E761-7C22-43A0-9A55-A1B2F8B83690</string>
15
+ <string>76EAC2C8-2F4E-433F-9B30-11AE8CAB3C53</string>
16
+ </array>
17
+ <key>submenus</key>
18
+ <dict/>
19
+ </dict>
20
+ <key>name</key>
21
+ <string>ESB</string>
22
+ <key>ordering</key>
23
+ <array>
24
+ <string>B6D3CCA0-FDC8-442A-8D41-515DD8F93C50</string>
25
+ <string>D248DB58-5512-4EB1-BCF1-B3FFC7B2C6AB</string>
26
+ <string>985AA142-639A-486B-B777-B358EFE2D2BB</string>
27
+ <string>FEB78640-82A4-4257-AE82-F4A05C8981BE</string>
28
+ <string>2585098C-57C4-4EA6-AE1A-FAE7CBCF7E94</string>
29
+ <string>D6051F23-6604-4897-B36E-94719D45F86A</string>
30
+ <string>0686E761-7C22-43A0-9A55-A1B2F8B83690</string>
31
+ <string>76EAC2C8-2F4E-433F-9B30-11AE8CAB3C53</string>
32
+ <string>78931B30-3E26-4FC6-AC18-3E5E9D64D62C</string>
33
+ </array>
34
+ <key>uuid</key>
35
+ <string>6BD9FB9E-A820-4288-B9AF-D8588715D1D6</string>
36
+ </dict>
37
+ </plist>
@@ -22,4 +22,5 @@ Gem::Specification.new do |s|
22
22
  s.add_development_dependency "rake"
23
23
  s.add_runtime_dependency "builder"
24
24
  s.add_runtime_dependency "erubis"
25
+ s.add_runtime_dependency "fssm"
25
26
  end
data/README.md CHANGED
@@ -6,55 +6,61 @@ ESBify is a simple DSL for creating the necessary XML files for the ESB framewor
6
6
 
7
7
  $ gem install esbify
8
8
 
9
- should do the trick provided you have a recent enough installation of Ruby. Run
9
+ should do the trick provided you have a recent enough installation of Ruby. Run this to list basic usage:
10
10
 
11
11
  $ esbify -h
12
12
 
13
- to list basic usage.
14
-
15
13
  ## Syntax
16
14
 
17
- !expectations
18
-
15
+ # This is a comment
16
+
17
+ # This is a header. Anything after this header will go to the relevant file
18
+ !expectations
19
+
20
+ # And this is an element, in this case an expectation.
19
21
  name: may_not_have_bangs
22
+ # We haven't included an `agent:` label, it defaults to `self`.
20
23
  condition: played(P1, duel, P2) | responded(P1, bang, P2, duel) | played(P1, indians, P2)
21
24
  phi: requires_bang_response(P2)
22
25
  test_plus: lost_life(P2)
23
26
  test_minus: played(P2, bang, P3) | responded(P2, bang, P3, _)
24
27
  rho_plus:
25
- + has_no_bangs
28
+ + has_no_bangs # `+` means that this will be added to EXP_C
29
+ - may_not_have_bangs # `-` means this will be removed from EXP_C
26
30
  rho_minus:
27
31
  - has_no_bangs
28
-
32
+
33
+ # Lines separate elements
29
34
  ----------
30
35
 
31
- name: has_no_bangs
36
+ # As a shortcut if the first label in an element has no content it is automatically considered a name
37
+ has_no_bangs: # equivalent to `name: has_no_bangs`
32
38
  condition: requires_bang_response℗ | has_no_bangs(P)
33
39
  phi: has_no_bangs_phi(P)
40
+ # You can use embedded Ruby to process things compile time
41
+ <% if @drawing_supported %>
34
42
  test_minus: draw(P, X)
35
43
  rho_minus:
36
44
  - has_no_bangs
45
+ <% end %>
46
+ # Since test_plus (or minus) is closely related to rho_plus (or minus), the rho may be ommited
47
+ test_plus: see(Enemy)
48
+ - may_not_have_bangs
37
49
 
38
50
 
39
- # comment
40
-
51
+ # As you have guessed this goes to Behaviors.xml
41
52
  !behaviors
42
-
53
+
43
54
  name: JI plans
44
55
  jason: has_no_bangs(P)
45
56
  action: card_expectation(P, bang, 0)
46
57
 
47
58
 
59
+ ## TextMate Plugin ##
48
60
 
49
- ### Headers
50
-
51
- `!expectation`, `!behavior`, `!strategy`
52
-
53
- Are possible headers saying that the following code will be of that particular type.
54
-
55
- ### Expectations
61
+ The package contains a TextMate plugin that you may install. It provides syntax highlighting and some basic snippets.
56
62
 
57
- ### Behaviors
63
+ ### Notes on Behaviors
58
64
 
59
65
  `name` is an identifier and isn't particularly useful. When omitted, a random number will be used.
60
66
 
@@ -88,19 +94,18 @@ and p is true in s′.
88
94
  - AX p is true in a states iff or all states s′ wherethereisatransitionfromstos′,pistrue
89
95
  in s′.
90
96
  - EF p is true in a state s0 if there exists a series of transitions s0 → s1, s1 → s2, ...,
91
- sn−1 →sn suchthatpistrueinsn.
92
- - AF pistrueinastates0 ifforallseriesoftransitionss0 → s1,s1 → s2,...,sn−1 → sn
97
+ sn−1 →sn such that p is true in sn.
98
+ - AF p is true in a state s0 if for all series of transitions s0 → s1,s1 → s2,...,sn−1 → sn
93
99
  p is true in sn.
94
100
  - EG p is true in a state s0 if there exists an infinite series of transitions s0 → s1, s1 → s2,
95
101
  ... such that p is true in every si.
96
- - AG pistrueinastates0 ifforallinfiniteseriesoftransitionss0 →s1,s1 →s2,... p
102
+ - AG p is true in a state s0 if for all infinite series of transitions s0 →s1,s1 →s2,... p
97
103
  is true in every si.
98
104
  - E[p U q] is true in a state s0 if there exists a series of transitions s0 → s1, s1 → s2,
99
105
  ..., sn−1 → sn such that p is true in every state from s0 to sn−1 and q is true in state sn.
100
- - A[p U q]istrueinastates0 ifforallseriesoftransitionss0 → s1,s1 → s2,...,
106
+ - A[p U q] is true in a state s0 if for all series of transitions s0 → s1,s1 → s2,...,
101
107
  sn−1 → sn p is true in every state from s0 to sn−1 and q is true in state sn. A CTL formula is true if it is true in all initial states.
102
108
 
103
- ---
104
109
 
105
110
  `jason` is a logic inside the ASL agent.
106
111
 
data/bin/esbify CHANGED
@@ -1,12 +1,23 @@
1
1
  #!/usr/bin/env ruby
2
2
  require "optparse"
3
+ require "fssm"
3
4
  require File.dirname(__FILE__) + "/../lib/ESBify"
4
5
 
5
6
 
6
7
 
7
- options = {stdout: false, expectations: "./Expectations.xml", behaviors: "./Behaviours.xml", filter: /.*/, only: %w[expectations behaviors strategies], context: {}}
8
+ options = {stdout: false, expectations: "./Expectations.xml", behaviors: "./Behaviours.xml", strategies: "./Strategy.xml", filter: /.*/, only: %w[expectations behaviors strategies], context: {}, watch: false}
8
9
  OptionParser.new do |opts|
9
- opts.banner = "Usage: esbify [options] FILES..."
10
+ opts.banner = "Usage: esbify [options] FILES...
11
+ ESBify will parse FILES and transform them to the appropriate XML. By default it will save expectations to
12
+ Expectations.xml, behaviors to Behaviors.xml and strategies to Strategy.xml.
13
+
14
+ This can be customized with the following options:
15
+ "
16
+
17
+ opts.on("--only expectations,behaviors,strategies", Array, "Only parse these sections.") do |v|
18
+ raise ArgumentError unless v.all?{|o| %w[expectations behaviors strategies].include?(o)}
19
+ options[:only] = v
20
+ end
10
21
 
11
22
  opts.on("-e", "--expectations FILE", "Output Expectations to FILE") do |v|
12
23
  options[:expectations] = v
@@ -16,18 +27,21 @@ OptionParser.new do |opts|
16
27
  options[:behaviors] = v
17
28
  end
18
29
 
19
- opts.on("--[no-]stdout", "Print to STDOUT") do |v|
30
+ opts.on("-s", "--strategies FILE", "Output Strategies to FILE") do |v|
31
+ options[:strategies] = v
32
+ end
33
+
34
+ opts.on("--[no-]stdout", "Print all files to STDOUT insted of individual files.") do |v|
20
35
  options[:stdout] = v
21
36
  end
22
37
 
38
+ opts.separator("\nESBify will also print a list of expectation names to STDOUT.\n")
39
+
23
40
  opts.on("-f", "--filter REGEXP", "When printing out expectations, only print those matching this regexp.") do |v|
24
41
  options[:filter] = Regexp.new(v)
25
42
  end
26
43
 
27
- opts.on("--only expectations,behaviors,strategies", Array, "Only generate these files") do |v|
28
- raise ArgumentError unless v.all?{|o| %w[expectations behaviors strategies].include?(o)}
29
- options[:only] = v
30
- end
44
+ opts.separator("\nOther various options:\n")
31
45
 
32
46
  opts.on("--context HASH_OR_PATH", "A path to a ruby class or a hash of values that will be passed to ERB", "The ruby class should have a underscored filename and CamelCased classname. ") do |v|
33
47
  if v =~ /\:|=>/
@@ -40,6 +54,10 @@ OptionParser.new do |opts|
40
54
  end
41
55
  end
42
56
 
57
+ opts.on("-w", "--watch", "Watches files for changes and automatically recompiles on change.", "All files in `pwd` ending with .esb will be watched (FILES are ignored).") do |v|
58
+ options[:watch] = true
59
+ end
60
+
43
61
  opts.on_tail("-h", "--help [README]", "Call -h with README to view the readme file") do |t|
44
62
  if t == "README"
45
63
  puts File.read(File.dirname(__FILE__) + "/../README.md")
@@ -56,18 +74,38 @@ OptionParser.new do |opts|
56
74
 
57
75
  end.parse!
58
76
 
59
- parser = ESBify::Parser.new options[:context]
60
77
 
61
- ARGV.each do |f|
62
- parser.parse_file! f
63
- end
64
78
 
65
- if options[:stdout]
66
- puts parser.expectations if options[:only].include?("expectations")
67
- puts parser.behaviors if options[:only].include?("behaviors")
68
- else
69
- File.open(options[:expectations], "w") {|f| f << parser.expectations } if options[:only].include?("expectations")
70
- File.open(options[:behaviors], "w") {|f| f << parser.behaviors } if options[:only].include?("behaviors")
79
+ def run(files, options)
80
+ parser = ESBify::Parser.new options[:context]
81
+
82
+ files.each do |f|
83
+ parser.parse_file! f
84
+ end
85
+
86
+ if options[:stdout]
87
+ puts parser.expectations if options[:only].include?("expectations")
88
+ puts parser.behaviors if options[:only].include?("behaviors")
89
+ puts parser.strategies if options[:only].include?("strategies")
90
+ else
91
+ File.open(options[:expectations], "w") {|f| f << parser.expectations } if options[:only].include?("expectations")
92
+ File.open(options[:behaviors], "w") {|f| f << parser.behaviors } if options[:only].include?("behaviors")
93
+ File.open(options[:strategies], "w") {|f| f << parser.strategies } if options[:only].include?("strategies")
94
+ end
95
+ STDERR.puts "Compiled!"
96
+ puts parser.expectation.names.grep(options[:filter]).join(",")
71
97
  end
72
98
 
73
- puts parser.expectation.names.grep(options[:filter]).join(",")
99
+
100
+ if options[:watch]
101
+ run(Dir[Dir.pwd + '/*.esb'], options)
102
+
103
+ FSSM.monitor(Dir.pwd, '*.esb') do
104
+ update do |base, relative|
105
+ run(Dir[Dir.pwd + '/*.esb'], options)
106
+ end
107
+ end
108
+
109
+ else
110
+ run ARGV, options
111
+ end
@@ -3,4 +3,4 @@ require File.dirname(__FILE__) + "/ESBify/version"
3
3
  module ESBify
4
4
  # Your code goes here...
5
5
  end
6
- require File.dirname(__FILE__) + "/ESBify/parser"
6
+ require File.dirname(__FILE__) + "/ESBify/parser"
@@ -7,12 +7,22 @@ class ESBify::Base
7
7
  def defaults
8
8
 
9
9
  end
10
-
11
- def <<(sects)
12
- @data += sects.map do |sect|
13
- defaults.merge(sect)
14
- end
10
+
11
+ def keys
12
+ defaults.keys.join("|")
15
13
  end
14
+
15
+ def parse!(str)
16
+ segs = str.split(/\s*\n---+\s*\n\s*/m)
17
+ @data += segs.map do |seg|
18
+ ms = seg.scan /(?:^|\n)(#{keys})\s*\:\s*(.+?)(?=(?:\n(?:#{keys})\s*\:|\z))/m
19
+ if m1 = seg.strip.match(/(?:^)(?!#{keys})(\w+)\s*\:\s*\n/)
20
+ ms << ["name", m1[1]]
21
+ end
22
+ defaults.merge Hash[*ms.flatten.map(&:strip)]
23
+ end
24
+ end
25
+
16
26
 
17
27
  def to_xml_partial
18
28
  b = Builder::XmlMarkup.new indent: 2, margin: 1
@@ -22,15 +22,37 @@ module ESBify
22
22
  }
23
23
  end
24
24
 
25
- def <<(sects)
25
+ def parse!(str)
26
26
  @names ||= []
27
- @data += sects.map do |sect|
28
- sect["rho_plus"] = parse_mods(sect["rho_plus"]) if sect["rho_plus"]
29
- sect["rho_minus"] = parse_mods(sect["rho_minus"]) if sect["rho_minus"]
27
+ segs = str.split(/\s*\n---+\s*\n\s*/m)
28
+ @data += segs.map do |seg|
29
+ ms = seg.scan /(?:^|\n)(#{keys})\s*\:\s*(.+?)(?=(?:\n(?:#{keys})\s*\:|\z))/m
30
+ if m1 = seg.strip.match(/(?:^)(?!#{keys})(\w+)\s*\:\s*\n/)
31
+ ms << ["name", m1[1]]
32
+ end
33
+
34
+ sect = Hash[*ms.flatten.map(&:strip)]
35
+
36
+ if sect["rho_plus"]
37
+ sect["rho_plus"] = parse_mods(sect["rho_plus"])
38
+ elsif sect["test_plus"]
39
+ sect["rho_plus"] = parse_mods(sect["test_plus"])
40
+ sect["test_plus"] = sect["test_plus"].split(/^\s*(\+|\-)/).first.strip
41
+ end
42
+
43
+ if sect["rho_minus"]
44
+ sect["rho_minus"] = parse_mods(sect["rho_minus"])
45
+ elsif sect["test_minus"]
46
+ sect["rho_minus"] = parse_mods(sect["test_minus"])
47
+ sect["test_minus"] = sect["test_minus"].split(/^\s*(\+|\-)/).first.strip
48
+ end
49
+
30
50
  @names << sect["name"] if sect["name"]
31
- defaults.merge(sect)
51
+ defaults.merge sect
32
52
  end
53
+
33
54
  end
55
+
34
56
 
35
57
  def parse_mods(str)
36
58
  add_set = []
@@ -1,9 +1,17 @@
1
1
  require 'erubis'
2
2
  require File.dirname(__FILE__) + "/expectation"
3
3
  require File.dirname(__FILE__) + "/behavior"
4
- #require "./behavior"
5
- #require "./strategy"
4
+ require File.dirname(__FILE__) + "/strategy"
6
5
 
6
+
7
+ # The Parser is the top level class. It's responsibility it is to do most of the generic processing of
8
+ # the language and then delegate to the Strategy, Behavior and Expectation classes.
9
+ #
10
+ # Usage:
11
+ #
12
+ # parser = ESBify::Parser.new
13
+ # parser.parse_file! "path/to/file.esb"
14
+ # puts parser.expectations #=> "<?xml ..."
7
15
  class ESBify::Parser
8
16
 
9
17
  attr_reader :expectation
@@ -11,46 +19,52 @@ class ESBify::Parser
11
19
  def initialize(context = {})
12
20
  @expectation = ::ESBify::Expectation.new
13
21
  @behavior = ::ESBify::Behavior.new
14
- #@strategy = ::ESBify::Strategy.new
22
+ @strategy = ::ESBify::Strategy.new
15
23
 
16
24
  @context = context
17
25
  end
18
26
 
19
-
27
+ # After parsing contains the xml representation of all expectations.
20
28
  def expectations
21
29
  @expectation.to_xml
22
30
  end
23
31
 
32
+ # After parsing contains the xml representation of all behaviors.
24
33
  def behaviors
25
34
  @behavior.to_xml
26
35
  end
27
36
 
37
+ # After parsing contains the xml representation of the strategy.
28
38
  def strategies
29
39
  @strategy.to_xml
30
40
  end
41
+ alias_method :strategy, :strategies
31
42
 
43
+ # Pass a file path. File will be read and parsed.
32
44
  def parse_file!(path)
33
45
  parse! File.read(path)
34
46
  end
35
47
 
48
+ # Parse a string of esb code.
36
49
  def parse!(str)
37
50
  # Remove comments
38
51
  str = str.split("\n").map{|l| l.split('#').first }.join("\n")
52
+ # Evaluate ERB code
39
53
  str = Erubis::Eruby.new(str).evaluate(@context)
54
+ # Split by sections
40
55
  str.split(/\!(?=(?:expectation|behaviou?r|strateg(?:y|ie))s?\n)/).each do |section|
41
56
  next if section =~ /\A\s*\z/m
42
57
  m = section.match /\A(expectation|behaviou?r|strateg(?:y|ie))s?/
43
58
  txt = str.split("\n")
44
59
  txt.shift
45
60
  txt.join("\n")
46
- sect = parse_section(section)
47
61
  case m[1]
48
62
  when /expectations?/
49
- @expectation << sect
63
+ @expectation.parse! section
50
64
  when /behaviou?rs?/
51
- @behavior << sect
65
+ @behavior.parse! section
52
66
  when /strateg(?:y|ie)s?/
53
- @strategy << sect
67
+ @strategy.parse! section
54
68
  else
55
69
  raise ArgumentError
56
70
  end
@@ -58,12 +72,4 @@ class ESBify::Parser
58
72
 
59
73
  end
60
74
 
61
-
62
- def parse_section(str)
63
- segs = str.split(/\s*\n---+\s*\n\s*/m)
64
- segs.map do |seg|
65
- ms = seg.scan /(?:^|\n)([\w_]+)\s*\:\s*(.+?)(?=(?:\n[\w_]+\s*\:|\z))/m
66
- Hash[*ms.flatten.map(&:strip)]
67
- end
68
- end
69
75
  end
@@ -1,3 +1,3 @@
1
1
  module ESBify
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.1"
3
3
  end
data/test.esb CHANGED
@@ -6,4 +6,11 @@ name: test
6
6
  condition: played(1) & played(2)
7
7
  ----
8
8
  name: has_no_bangs
9
- condition: requires_bang_response(P) | has_no_bangs(P)
9
+ condition: requires_bang_response(P) | has_no_bangs(P)
10
+
11
+ ---
12
+
13
+ test_expectation:
14
+ condition: a
15
+ test_plus: a(b) & c(d)
16
+ + has_no_bangs
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ESBify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-02 00:00:00.000000000Z
12
+ date: 2012-04-07 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &70235824010600 !ruby/object:Gem::Requirement
16
+ requirement: &70218565146640 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70235824010600
24
+ version_requirements: *70218565146640
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: builder
27
- requirement: &70235824010160 !ruby/object:Gem::Requirement
27
+ requirement: &70218565146140 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70235824010160
35
+ version_requirements: *70218565146140
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: erubis
38
- requirement: &70235824009740 !ruby/object:Gem::Requirement
38
+ requirement: &70218565145640 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,18 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70235824009740
46
+ version_requirements: *70218565145640
47
+ - !ruby/object:Gem::Dependency
48
+ name: fssm
49
+ requirement: &70218565145060 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70218565145060
47
58
  description: Generates proper XML files for the ESB framework from a DSL.
48
59
  email:
49
60
  - honitom@seznam.cz
@@ -53,6 +64,16 @@ extensions: []
53
64
  extra_rdoc_files: []
54
65
  files:
55
66
  - .gitignore
67
+ - ESB.tmbundle/Commands/Compile.tmCommand
68
+ - ESB.tmbundle/Preferences/Comments.tmPreferences
69
+ - ESB.tmbundle/Snippets/Behavior.tmSnippet
70
+ - ESB.tmbundle/Snippets/Expectation.tmSnippet
71
+ - ! 'ESB.tmbundle/Snippets/Header: Behaviors.tmSnippet'
72
+ - ! 'ESB.tmbundle/Snippets/Header: Expectation.tmSnippet'
73
+ - ! 'ESB.tmbundle/Snippets/Header: Strategies.tmSnippet'
74
+ - ESB.tmbundle/Snippets/Separator.tmSnippet
75
+ - ESB.tmbundle/Syntaxes/ESB.tmLanguage
76
+ - ESB.tmbundle/info.plist
56
77
  - ESBify.gemspec
57
78
  - Gemfile
58
79
  - README.md
@@ -80,7 +101,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
80
101
  version: '0'
81
102
  segments:
82
103
  - 0
83
- hash: -1658457591522309798
104
+ hash: 1348258640709416010
84
105
  required_rubygems_version: !ruby/object:Gem::Requirement
85
106
  none: false
86
107
  requirements:
@@ -89,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
89
110
  version: '0'
90
111
  segments:
91
112
  - 0
92
- hash: -1658457591522309798
113
+ hash: 1348258640709416010
93
114
  requirements: []
94
115
  rubyforge_project: ESBify
95
116
  rubygems_version: 1.8.6