sfp 0.2.1 → 0.3.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.
- data/.gitignore +1 -0
- data/README.md +28 -76
- data/bin/sfp +12 -78
- data/lib/sfp/SfpLangLexer.rb +608 -473
- data/lib/sfp/SfpLangParser.rb +4571 -4371
- data/lib/sfp/Sfplib.rb +30 -20
- data/lib/sfp/parser.rb +14 -6
- data/lib/sfp/sas_translator.rb +3 -1
- data/lib/sfp.rb +0 -5
- data/sfp.gemspec +6 -12
- data/src/SfpLang.g +82 -13
- metadata +22 -57
- data/bin/solver/linux-x86/downward +0 -0
- data/bin/solver/linux-x86/preprocess +0 -0
- data/bin/solver/macos/downward +0 -0
- data/bin/solver/macos/preprocess +0 -0
- data/lib/sfp/executor.rb +0 -207
- data/lib/sfp/planner.rb +0 -482
- data/lib/sfp/sas.rb +0 -966
- data/test/cloud-schemas.sfp +0 -80
- data/test/future/test1.sfp +0 -22
- data/test/nd-cloud1.sfp +0 -33
- data/test/nd-cloud2.sfp +0 -41
- data/test/nd-cloud3.sfp +0 -42
- data/test/nd-service1.sfp +0 -23
- data/test/nd-service2.sfp +0 -27
- data/test/run.sh +0 -53
- data/test/s.sfp +0 -14
- data/test/service-schemas.sfp +0 -151
- data/test/test-module1-scripts.tgz +0 -0
- data/test/test-module1.sfp +0 -20
- data/test/test1.inc +0 -9
- data/test/test1.sfp +0 -13
- data/test/test2.sfp +0 -20
- data/test/test3.inc +0 -40
- data/test/test3.sfp +0 -17
- data/test/test4.inc +0 -28
- data/test/test4.sfp +0 -22
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,21 +1,12 @@
|
|
1
1
|
SFP Parser and Planner for Ruby
|
2
2
|
===============================
|
3
3
|
- Author: Herry (herry13@gmail.com)
|
4
|
-
- Version: 0.
|
4
|
+
- Version: 0.3.4
|
5
5
|
- License: [BSD License](https://github.com/herry13/sfp-ruby/blob/master/LICENSE)
|
6
6
|
|
7
|
-
A Ruby gem that provides a Ruby interface to parse SFP language.
|
8
|
-
|
9
|
-
|
10
|
-
- Bash
|
11
|
-
- there is no representation of SFP schema or object
|
12
|
-
- a SFP procedure is a Bash script file
|
13
|
-
- SFP namespaces are represented by subdirectories of *modules* directory
|
14
|
-
- Ruby ( *under-development* )
|
15
|
-
- a SFP schema is represented by a Ruby class
|
16
|
-
- a SFP object is an instance of Ruby class
|
17
|
-
- a SFP procedure is a Ruby method
|
18
|
-
- SFP namespaces are represented by a tree of Hash data structure
|
7
|
+
A Ruby gem that provides a Ruby interface to parse [SFP language](https://github.com/herry13/nuri/wiki/SFP-language), a declarative language to specify a planning task.
|
8
|
+
|
9
|
+
Click [here](https://github.com/herry13/nuri/wiki/SFP-language), for more details about SFP language.
|
19
10
|
|
20
11
|
This is a spin-out project from [Nuri](https://github.com/herry13/nuri).
|
21
12
|
|
@@ -33,31 +24,16 @@ Requirements
|
|
33
24
|
- antlr3
|
34
25
|
- json
|
35
26
|
|
36
|
-
|
37
|
-
Supporting Platforms
|
38
|
-
--------------------
|
39
|
-
- Linux (x86, arm)
|
40
|
-
- MacOS X
|
27
|
+
Tested on: MacOS X 10.8, Ubuntu 12.04, Scientific Linux 6, Debian Wheeze Raspberry
|
41
28
|
|
42
29
|
|
43
|
-
To use as a command line
|
44
|
-
|
30
|
+
To use as a command line
|
31
|
+
------------------------
|
45
32
|
- parse a SFP file, and then print the output in JSON
|
46
33
|
|
47
34
|
$ sfp --json <sfp-file>
|
48
35
|
|
49
|
-
|
50
|
-
|
51
|
-
$ sfp <sfp-file>
|
52
|
-
|
53
|
-
The planning task must be written in [SFP language](https://github.com/herry13/nuri/wiki/SFP-language).
|
54
|
-
|
55
|
-
|
56
|
-
To generate a parallel (partial-order) plan
|
57
|
-
-------------------------------------------
|
58
|
-
- use option **--parallel** to generate a partial order plan
|
59
|
-
|
60
|
-
$ sfp --parallel <sfp-file>
|
36
|
+
To solve a planning task, you can use [sfplanner](https://github.com/herry13/sfplanner)/
|
61
37
|
|
62
38
|
|
63
39
|
To use as Ruby library
|
@@ -71,9 +47,8 @@ To use as Ruby library
|
|
71
47
|
# Determine the home directory of your SFP file.
|
72
48
|
home_dir = File.expand_path(File.dirname("my_file.sfp"))
|
73
49
|
|
74
|
-
# Create Sfp::Parser object
|
75
|
-
|
76
|
-
parser = Sfp::Parser.new({:home_dir => home_dir, :root_dir => '/'})
|
50
|
+
# Create Sfp::Parser object
|
51
|
+
parser = Sfp::Parser.new({:home_dir => "./"})
|
77
52
|
|
78
53
|
# Parse the file.
|
79
54
|
parser.parse(File.read("my_file.sfp"))
|
@@ -81,40 +56,11 @@ To use as Ruby library
|
|
81
56
|
# Get the result in Hash data structure
|
82
57
|
result = parser.root
|
83
58
|
|
84
|
-
- to solve a planning task: create a Sfp::Planner object, and then pass the file's path:
|
85
|
-
|
86
|
-
# Create Sfp::Planner object.
|
87
|
-
planner = Sfp::Planner.new
|
88
|
-
|
89
|
-
# Solve a planning task written in "my_file.sfp", then print
|
90
|
-
# the result in JSON.
|
91
|
-
puts planner.solve({:file => "my_file.sfp", :json => true})
|
92
|
-
|
93
59
|
|
94
|
-
To solve planning task and execute it using Bash scripts
|
95
|
-
--------------------------------------------------------
|
96
|
-
Parse a SFP file, print the plan in JSON, and then execute the plan by
|
97
|
-
invoking Bash scripts in directory **modules**. *Note*: the namespaces are
|
98
|
-
represented by directories e.g. executing procedure *$.a.b.foo* will be
|
99
|
-
invoking a Bash script *modules/a/b/foo*.
|
100
60
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
To execute previously generated plan file in JSON format
|
105
|
-
--------------------------------------------------------
|
106
|
-
If you have generated a plan saved in a file, then you could execute the plan by
|
107
|
-
invoking Bash scripts in directory **modules**. *Note*: the namespaces are
|
108
|
-
represented by directories e.g. executing procedure *$.a.b.foo* will be
|
109
|
-
invoking a Bash script *modules/a/b/foo*.
|
110
|
-
|
111
|
-
$ sfp --execute <plan-file>
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
Example
|
116
|
-
-------
|
117
|
-
- Create file **types.sfp** that holds required schemas:
|
61
|
+
Example of Planning Task
|
62
|
+
------------------------
|
63
|
+
- Create file **types.sfp** to hold required schemas:
|
118
64
|
|
119
65
|
schema Service {
|
120
66
|
running is false
|
@@ -146,8 +92,8 @@ Example
|
|
146
92
|
}
|
147
93
|
|
148
94
|
In this file, we have two schemas that model our domain. First, schema
|
149
|
-
**Service** with an attribute **running
|
150
|
-
changes **running**'s value from **false** to
|
95
|
+
**Service** with an attribute **running**, procedure **start** that
|
96
|
+
changes **running**'s value from **false** to **true**, and procedure
|
151
97
|
**stop** that changes **running**'s value from **true** to **false**.
|
152
98
|
|
153
99
|
We also have schema **Client** with an attribute **refer**, which is
|
@@ -155,7 +101,7 @@ Example
|
|
155
101
|
**redirect** that changes the value of **refer** with any instance if
|
156
102
|
**Service**.
|
157
103
|
|
158
|
-
- Create file **task.sfp**
|
104
|
+
- Create file **task.sfp** to hold the task:
|
159
105
|
|
160
106
|
include "types.sfp"
|
161
107
|
|
@@ -237,18 +183,24 @@ Example
|
|
237
183
|
|
238
184
|
This workflow is sequential that has 3 procedures. If you executes
|
239
185
|
the workflow in given order, it will achieves the goal state as well
|
240
|
-
as perserves the global constraints during the
|
186
|
+
as perserves the global constraints during the execution.
|
241
187
|
|
242
188
|
- To generate and execute the plan using Bash framework, we invoke **sfp**
|
243
|
-
command with an option *--
|
189
|
+
command with an option *--solve-execute* and with an argument the path of
|
244
190
|
the task file:
|
245
191
|
|
246
|
-
$ sfp --solve-execute task
|
192
|
+
$ sfp --solve-execute task.sfp
|
247
193
|
|
248
194
|
It will generate and execute the plan by invoking the Bash scripts in
|
249
195
|
the current directory (or as specified in environment variable SFP_HOME)
|
250
196
|
in the following sequence:
|
251
|
-
|
252
|
-
|
253
|
-
|
197
|
+
|
198
|
+
./modules/b/start
|
199
|
+
./modules/pc/redirect "$.b"
|
200
|
+
./modules/a/stop
|
201
|
+
|
202
|
+
- If you save the plan in a file e.g. **plan.json**, you could execute it
|
203
|
+
later using option *--execute*
|
204
|
+
|
205
|
+
$ sfp --execute plan.json
|
254
206
|
|
data/bin/sfp
CHANGED
@@ -4,93 +4,27 @@ libdir = File.expand_path(File.dirname(__FILE__))
|
|
4
4
|
require "#{libdir}/../lib/sfp"
|
5
5
|
|
6
6
|
opts = Trollop::options do
|
7
|
-
version "sfp 0.
|
7
|
+
version "sfp 0.3.4 (c) 2013 Herry"
|
8
8
|
banner <<-EOS
|
9
|
-
Parse a SFP file
|
9
|
+
Parse a SFP file and print the result in JSON format.
|
10
10
|
|
11
11
|
Usage:
|
12
|
-
sfp
|
13
|
-
|
14
|
-
where [options] are:
|
12
|
+
sfp <file>
|
15
13
|
EOS
|
16
14
|
|
17
|
-
opt :
|
18
|
-
opt :json, "parse a SFP file and print it in JSON format"
|
19
|
-
opt :solve_execute, "parse a SFP File, solve the planning task, " +
|
20
|
-
"and execute the plan with given execution framework"
|
21
|
-
opt :bash, "set Bash as the execution framework", :default => true
|
22
|
-
opt :execute, "execute a plan in given file"
|
15
|
+
opt :pretty, "Print the result in pretty JSON format.", :default => false
|
23
16
|
end
|
24
17
|
|
25
|
-
|
26
|
-
home_dir = File.expand_path(File.dirname(
|
18
|
+
def parse(filepath)
|
19
|
+
home_dir = File.expand_path(File.dirname(filepath))
|
27
20
|
parser = Sfp::Parser.new({:home_dir => home_dir})
|
28
|
-
parser.parse(File.read(
|
29
|
-
|
30
|
-
|
31
|
-
elsif opts[:solve_execute]
|
32
|
-
abort "There is no available execution framework!" if not opts[:bash]
|
33
|
-
|
34
|
-
planner = Sfp::Planner.new
|
35
|
-
plan = planner.solve({:file => ARGV[0], :parallel => opts[:parallel]})
|
36
|
-
puts "Plan: #{plan.inspect}"
|
37
|
-
executor = Sfp::BashExecutor.new
|
38
|
-
puts "Execution:"
|
39
|
-
executor.execute_plan({:plan => plan, :print_output => true})
|
40
|
-
|
41
|
-
elsif opts[:execute]
|
42
|
-
abort "There is no available execution framework!" if not opts[:bash]
|
43
|
-
|
44
|
-
plan = JSON.parse(File.read(ARGV[0]))
|
45
|
-
executor = Sfp::BashExecutor.new
|
46
|
-
executor.execute_plan({:plan => plan, :print_output => true})
|
47
|
-
|
48
|
-
elsif ARGV.length > 0
|
49
|
-
planner = Sfp::Planner.new
|
50
|
-
puts planner.solve({:file => ARGV[0], :pretty_json => true, :parallel => opts[:parallel]})
|
51
|
-
|
52
|
-
else
|
53
|
-
Trollop::help
|
54
|
-
|
21
|
+
parser.parse(File.read(filepath))
|
22
|
+
parser
|
55
23
|
end
|
56
24
|
|
57
|
-
=
|
58
|
-
|
59
|
-
|
60
|
-
home_dir = File.expand_path(File.dirname(ARGV[1]))
|
61
|
-
parser = Sfp::Parser.new({:home_dir => home_dir})
|
62
|
-
parser.parse(File.read(ARGV[1]))
|
63
|
-
puts parser.to_json({:pretty => true})
|
64
|
-
|
65
|
-
elsif ARGV.length > 1 and ARGV[0] == '--exec-ruby'
|
66
|
-
planner = Sfp::Planner.new
|
67
|
-
plan = planner.solve({:file => ARGV[1]})
|
68
|
-
puts plan.inspect
|
69
|
-
executor = Sfp::RubyExecutor.new
|
70
|
-
executor.execute_plan({:plan => plan})
|
71
|
-
|
72
|
-
elsif ARGV.length > 1 and ARGV[0] == '--exec-bash'
|
73
|
-
planner = Sfp::Planner.new
|
74
|
-
plan = planner.solve({:file => ARGV[1]})
|
75
|
-
puts "Plan: #{plan.inspect}"
|
76
|
-
executor = Sfp::BashExecutor.new
|
77
|
-
puts "Execution:"
|
78
|
-
executor.execute_plan({:plan => plan, :print_output => true})
|
79
|
-
|
80
|
-
elsif ARGV.length > 0
|
81
|
-
planner = Sfp::Planner.new
|
82
|
-
puts planner.solve({:file => ARGV[0], :pretty_json => true})
|
83
|
-
|
25
|
+
filepath = ARGV[0].to_s
|
26
|
+
if filepath != ''
|
27
|
+
puts parse(filepath).to_json({:pretty => opts[:pretty]})
|
84
28
|
else
|
85
|
-
|
86
|
-
|
87
|
-
options:
|
88
|
-
<none> parse a SFP file and solve the planning task
|
89
|
-
-p, -json parse a SFP file and print it in JSON format
|
90
|
-
-x
|
91
|
-
--exec-bash parse a SFP file, solve the planning task, and
|
92
|
-
execute the plan with Sfp::BashExecutor
|
93
|
-
|
94
|
-
"
|
29
|
+
Trollop::help
|
95
30
|
end
|
96
|
-
=end
|