statsailr 0.7.1

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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +7 -0
  5. data/HISTORY.md +15 -0
  6. data/LICENSE.txt +675 -0
  7. data/README.md +287 -0
  8. data/Rakefile +10 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/example/blank.slr +3 -0
  12. data/example/category.slr +5 -0
  13. data/example/example_read.slr +10 -0
  14. data/example/iris.csv +151 -0
  15. data/example/mtcars.rda +0 -0
  16. data/example/new_mtcars.csv +33 -0
  17. data/example/new_mtcars.rda +0 -0
  18. data/example/plot_reg_example.slr +55 -0
  19. data/example/scatter.png +0 -0
  20. data/exe/sailr +54 -0
  21. data/exe/sailrREPL +75 -0
  22. data/lib/statsailr.rb +7 -0
  23. data/lib/statsailr/block_builder/sts_block.rb +167 -0
  24. data/lib/statsailr/block_builder/sts_block_parse_proc_opts.rb +168 -0
  25. data/lib/statsailr/block_to_r/proc_setting_support/proc_opt_validator.rb +52 -0
  26. data/lib/statsailr/block_to_r/proc_setting_support/proc_setting_manager.rb +49 -0
  27. data/lib/statsailr/block_to_r/proc_setting_support/proc_setting_module.rb +44 -0
  28. data/lib/statsailr/block_to_r/sts_block_to_r.rb +98 -0
  29. data/lib/statsailr/block_to_r/sts_lazy_func_gen.rb +236 -0
  30. data/lib/statsailr/block_to_r/top_stmt/top_stmt_to_r_func.rb +182 -0
  31. data/lib/statsailr/parser/sts_gram_node.rb +9 -0
  32. data/lib/statsailr/parser/sts_parse.output +831 -0
  33. data/lib/statsailr/parser/sts_parse.ry +132 -0
  34. data/lib/statsailr/parser/sts_parse.tab.rb +682 -0
  35. data/lib/statsailr/scanner/sample1.sts +37 -0
  36. data/lib/statsailr/scanner/sts_scanner.rb +433 -0
  37. data/lib/statsailr/scanner/test_sample1.rb +8 -0
  38. data/lib/statsailr/sts_build_exec.rb +304 -0
  39. data/lib/statsailr/sts_controller.rb +66 -0
  40. data/lib/statsailr/sts_output/output_manager.rb +192 -0
  41. data/lib/statsailr/sts_runner.rb +17 -0
  42. data/lib/statsailr/sts_server.rb +85 -0
  43. data/lib/statsailr/version.rb +3 -0
  44. data/statsailr.gemspec +32 -0
  45. metadata +133 -0
Binary file
@@ -0,0 +1,33 @@
1
+ "","mpg","cyl","disp","hp","drat","wt","qsec","vs","am","gear","carb","powerful"
2
+ "Mazda RX4",21,6,160,110,3.9,2.62,16.46,0,1,4,4,1
3
+ "Mazda RX4 Wag",21,6,160,110,3.9,2.875,17.02,0,1,4,4,1
4
+ "Datsun 710",22.8,4,108,93,3.85,2.32,18.61,1,1,4,1,0
5
+ "Hornet 4 Drive",21.4,6,258,110,3.08,3.215,19.44,1,0,3,1,1
6
+ "Hornet Sportabout",18.7,8,360,175,3.15,3.44,17.02,0,0,3,2,1
7
+ "Valiant",18.1,6,225,105,2.76,3.46,20.22,1,0,3,1,1
8
+ "Duster 360",14.3,8,360,245,3.21,3.57,15.84,0,0,3,4,1
9
+ "Merc 240D",24.4,4,146.7,62,3.69,3.19,20,1,0,4,2,0
10
+ "Merc 230",22.8,4,140.8,95,3.92,3.15,22.9,1,0,4,2,0
11
+ "Merc 280",19.2,6,167.6,123,3.92,3.44,18.3,1,0,4,4,1
12
+ "Merc 280C",17.8,6,167.6,123,3.92,3.44,18.9,1,0,4,4,1
13
+ "Merc 450SE",16.4,8,275.8,180,3.07,4.07,17.4,0,0,3,3,1
14
+ "Merc 450SL",17.3,8,275.8,180,3.07,3.73,17.6,0,0,3,3,1
15
+ "Merc 450SLC",15.2,8,275.8,180,3.07,3.78,18,0,0,3,3,1
16
+ "Cadillac Fleetwood",10.4,8,472,205,2.93,5.25,17.98,0,0,3,4,1
17
+ "Lincoln Continental",10.4,8,460,215,3,5.424,17.82,0,0,3,4,1
18
+ "Chrysler Imperial",14.7,8,440,230,3.23,5.345,17.42,0,0,3,4,1
19
+ "Fiat 128",32.4,4,78.7,66,4.08,2.2,19.47,1,1,4,1,0
20
+ "Honda Civic",30.4,4,75.7,52,4.93,1.615,18.52,1,1,4,2,0
21
+ "Toyota Corolla",33.9,4,71.1,65,4.22,1.835,19.9,1,1,4,1,0
22
+ "Toyota Corona",21.5,4,120.1,97,3.7,2.465,20.01,1,0,3,1,0
23
+ "Dodge Challenger",15.5,8,318,150,2.76,3.52,16.87,0,0,3,2,1
24
+ "AMC Javelin",15.2,8,304,150,3.15,3.435,17.3,0,0,3,2,1
25
+ "Camaro Z28",13.3,8,350,245,3.73,3.84,15.41,0,0,3,4,1
26
+ "Pontiac Firebird",19.2,8,400,175,3.08,3.845,17.05,0,0,3,2,1
27
+ "Fiat X1-9",27.3,4,79,66,4.08,1.935,18.9,1,1,4,1,0
28
+ "Porsche 914-2",26,4,120.3,91,4.43,2.14,16.7,0,1,5,2,0
29
+ "Lotus Europa",30.4,4,95.1,113,3.77,1.513,16.9,1,1,5,2,0
30
+ "Ford Pantera L",15.8,8,351,264,4.22,3.17,14.5,0,1,5,4,1
31
+ "Ferrari Dino",19.7,6,145,175,3.62,2.77,15.5,0,1,5,6,1
32
+ "Maserati Bora",15,8,301,335,3.54,3.57,14.6,0,1,5,8,1
33
+ "Volvo 142E",21.4,4,121,109,4.11,2.78,18.6,1,1,4,2,0
Binary file
@@ -0,0 +1,55 @@
1
+ // comment
2
+ /*
3
+ multipe line comments
4
+ */
5
+
6
+ READ builtin = "mtcars"
7
+
8
+ DATA new_mtcars set=mtcars
9
+ if(cyl > 4){
10
+ powerful = 1
11
+ }else{
12
+ powerful = 0
13
+ }
14
+ END
15
+
16
+ PROC PRINT data=new_mtcars
17
+ head 10
18
+ tail
19
+ tail / n = 10
20
+ END
21
+
22
+ PROC PLOT data=new_mtcars
23
+ scatter powerful cyl
24
+ dev.copy png / file = "scatter.png"
25
+ END
26
+
27
+ PROC CAT data=new_mtcars
28
+ /* Calculate frequencies & show in list format
29
+ */
30
+ xtabs ~ cyl + powerful
31
+ fisher.test
32
+ chisq.test
33
+ END
34
+
35
+ PROC UNI data=new_mtcars
36
+ var cyl carb
37
+ END
38
+
39
+
40
+ PROC REG data=new_mtcars
41
+ lm hp ~ factor(cyl) + factor(carb)
42
+ END
43
+
44
+ GETWD
45
+
46
+ SAVE new_mtcars file="./new_mtcars.csv"
47
+
48
+ SAVE new_mtcars file="./new_mtcars.rda"
49
+
50
+
51
+ // READ builtin = "CO2"
52
+
53
+ // DATA:SQLDF CO2v2
54
+ // SELECT Plant, conc, uptake FROM CO2 WHERE Plant IN ('Qn1','Mn1') ORDER BY uptake
55
+ // END
Binary file
data/exe/sailr ADDED
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ## Parse argumnet and initialize setting
4
+
5
+ require('optparse')
6
+ opt = OptionParser.new
7
+ params = {}
8
+ new_params = {}
9
+
10
+ opt.on('--procs-gem VAL')
11
+ opt.parse!(ARGV, into: params)
12
+
13
+ if params[:"procs-gem"]
14
+ if params[:"procs-gem"] =~ /[a-zA-Z,_-]+/
15
+ if params[:"procs-gem"].include?( "," )
16
+ new_params[:"procs_gem"] = params[:"procs-gem"].split(",")
17
+ else
18
+ new_params[:"procs_gem"] = params[:"procs-gem"]
19
+ end
20
+ else
21
+ raise "--procs-gem option takes gem name or gem names separated with comma(,)."
22
+ end
23
+ else
24
+ # nothing to be specified.
25
+ end
26
+
27
+ specified_script_path = ARGV[0]
28
+
29
+ raise "Please spcify StatSailr script path" if( specified_script_path.nil? )
30
+
31
+
32
+ ## Set path
33
+
34
+ require('pathname')
35
+
36
+ if Pathname.new(specified_script_path).relative?
37
+ $script_file_path = Dir.pwd + "/" + specified_script_path
38
+ else
39
+ $script_file_path = specified_script_path
40
+ end
41
+
42
+ raise "StatSailr script file specified does not exist" if ! File.exist?( $script_file_path )
43
+
44
+ $script_dir_path = File.dirname( $script_file_path )
45
+
46
+
47
+ ## Run
48
+
49
+ require("statsailr")
50
+
51
+ StatSailr.run( **new_params )
52
+
53
+
54
+
data/exe/sailrREPL ADDED
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ## Parse argumnet and initialize setting
4
+
5
+ require 'optparse'
6
+ opt = OptionParser.new
7
+ params = {}
8
+ new_params = {}
9
+
10
+ opt.on('--thread')
11
+ opt.on('--procs-gem VAL')
12
+ opt.parse!(ARGV, into: params)
13
+
14
+ fork_or_thread = params[:thread]
15
+ if fork_or_thread
16
+ new_params[:fork_or_thread] = "thread"
17
+ else
18
+ new_params[:fork_or_thread] = "fork"
19
+ end
20
+
21
+ if new_params[:fork_or_thread] == "fork"
22
+ if Process.respond_to?(:fork)
23
+ # "fork" is used and system has "fork" implementation.
24
+ else
25
+ raise 'fork is not implemented on this system. Please try to run sailrREPL with "--thread" option'
26
+ end
27
+ end
28
+
29
+ if params[:"procs-gem"]
30
+ if params[:"procs-gem"] =~ /[a-zA-Z,_-]+/
31
+ if params[:"procs-gem"].include?( "," )
32
+ new_params[:"procs_gem"] = params[:"procs-gem"].split(",")
33
+ else
34
+ new_params[:"procs_gem"] = params[:"procs-gem"]
35
+ end
36
+ else
37
+ raise "--procs-gem option takes gem name or gem names separated with comma(,)."
38
+ end
39
+ else
40
+ # nothing to be specified.
41
+ end
42
+
43
+ ## Main
44
+
45
+ require("statsailr")
46
+
47
+ reader, writer = IO.pipe
48
+
49
+ child_service = StatSailr::Service.start( reader , writer, **new_params )
50
+
51
+ prompt = "(^^)v: "
52
+ line = ""
53
+ print prompt
54
+ while true
55
+ line = STDIN.gets()
56
+ if line.nil? # When C-d
57
+ puts "C-d : Parent process finishes. Close pipe."
58
+ writer.close
59
+ break
60
+ elsif line =~ /^!exit/
61
+ puts "!exit : Parent process finishes. Close pipe."
62
+ writer.close
63
+ break
64
+ else
65
+ writer.write line
66
+ print prompt
67
+ end
68
+ end
69
+
70
+ case fork_or_thread
71
+ when "fork"
72
+ Process.waitpid(child_service)
73
+ when "thread"
74
+ child_service.join()
75
+ end
data/lib/statsailr.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "statsailr/version"
2
+ require "statsailr/sts_runner.rb"
3
+ require "statsailr/sts_server.rb"
4
+
5
+ module StatSailr
6
+ class Error < StandardError; end
7
+ end
@@ -0,0 +1,167 @@
1
+ require "r_bridge"
2
+ require_relative "./sts_block_parse_proc_opts.rb"
3
+
4
+ module BlockSupport
5
+ def type_adjust(obj , type)
6
+ case type
7
+ when :ident
8
+ if obj.is_a?(String)
9
+ result = RBridge::SymbolR.new( obj )
10
+ else
11
+ raise "GramNode should have string value for type(#{type.to_s})"
12
+ end
13
+ when :num
14
+ if obj.is_a?(Integer) || obj.is_a?(Float)
15
+ result = obj
16
+ else
17
+ raise "GramNode with inconsistent type(#{type.to_s}) and object(#{obj.class})"
18
+ end
19
+ when :string
20
+ if obj.is_a?(String)
21
+ result = obj
22
+ else
23
+ raise "GramNode with inconsistent type(#{type.to_s}) and object(#{obj.class})"
24
+ end
25
+ when :sign
26
+ if obj.is_a?(String)
27
+ result = RBridge::SignR.new(obj)
28
+ else
29
+ raise "GramNode with inconsistent type(#{type.to_s}) and object(#{obj.class})"
30
+ end
31
+ end
32
+ return result
33
+ end
34
+ end
35
+
36
+ class TopStmt
37
+ extend BlockSupport
38
+ attr :command, :opts
39
+
40
+ def initialize( str, hash )
41
+ @command = str
42
+ @opts = hash
43
+ end
44
+
45
+ def self.new_from_gram_node( node )
46
+ command_name = node.e1
47
+ top_opts = node.e2
48
+ if (! top_opts.nil? ) && (top_opts.size != 0 )
49
+ hash = {}
50
+ top_opts.each(){|nd|
51
+ top_opt_key = nd.e1
52
+ if(!nd.e2.nil?)
53
+ top_opt_val = type_adjust( nd.e2.e1 , nd.e2.type )
54
+ else
55
+ top_opt_val = nil
56
+ end
57
+ hash[top_opt_key] = top_opt_val
58
+ }
59
+ else
60
+ hash = {}
61
+ end
62
+ return TopStmt.new( command_name, hash)
63
+ end
64
+ end
65
+
66
+ class DataBlock
67
+ extend BlockSupport
68
+ attr :out, :opts, :script
69
+
70
+ def initialize( str, hash, script)
71
+ @out = str
72
+ @opts = hash
73
+ @script = script
74
+ end
75
+
76
+ def self.new_from_gram_node( node )
77
+ out_df = type_adjust( node.e1.e1, node.e1.type )
78
+ data_hash = {}
79
+ data_opts = node.e2
80
+
81
+ if ! data_opts.nil?
82
+ data_opts.each(){|nd|
83
+ data_opt_key = nd.e1
84
+ if(!nd.e2.nil?)
85
+ data_opt_val = type_adjust( nd.e2.e1 , nd.e2.type )
86
+ else
87
+ data_opt_val = nil
88
+ end
89
+ data_hash[data_opt_key] = data_opt_val
90
+ }
91
+ else
92
+ data_opts = {}
93
+ end
94
+
95
+ data_script = type_adjust( node.e3.e1, node.e3.type )
96
+
97
+ return DataBlock.new( out_df , data_hash , data_script)
98
+ end
99
+ end
100
+
101
+ class ProcBlock
102
+ extend BlockSupport
103
+ attr :command, :opts, :stmts
104
+
105
+ def initialize( command, opts, stmts )
106
+ @command = command
107
+ @opts = opts
108
+ @stmts = stmts
109
+ end
110
+
111
+ def self.new_from_gram_node( node )
112
+ proc_command = type_adjust( node.e1.e1, :string )
113
+
114
+ proc_opt_hash = {}
115
+ proc_opts = node.e2
116
+ if(! proc_opts.nil?)
117
+ proc_opts.each(){|nd|
118
+ proc_opt_key = nd.e1
119
+ proc_opt_val = type_adjust( nd.e2.e1 , nd.e2.type )
120
+ proc_opt_hash[proc_opt_key] = proc_opt_val
121
+ }
122
+ else
123
+ proc_opt_hash = {}
124
+ end
125
+
126
+ proc_stmts = []
127
+
128
+ proc_stmts_ori = node.e3
129
+ proc_stmts_ori.each(){|proc_stmt_ori|
130
+ proc_stmt_inst = ""
131
+ proc_stmt_arg = []
132
+ proc_stmt_opt_hash = {}
133
+
134
+ proc_stmt_inst = type_adjust( proc_stmt_ori.e1.e1, :string) # String
135
+ proc_stmt_arg_ori = proc_stmt_ori.e2
136
+ if ! proc_stmt_arg_ori.nil? then
137
+ idx = 0
138
+ while idx < proc_stmt_arg_ori.size() do
139
+ elem = proc_stmt_arg_ori[idx]
140
+ if( elem.type == :sign && elem.e1 == "/" )
141
+ break
142
+ else
143
+ x = type_adjust( elem.e1, elem.type )
144
+ proc_stmt_arg << x
145
+ idx = idx + 1
146
+ end
147
+ end
148
+ idx = idx + 1
149
+ if idx < proc_stmt_arg_ori.size()
150
+
151
+ proc_stmt_opt_hash = STSBlockParseProcOpts.include(BlockSupport).new(proc_stmt_arg_ori, idx).parse()
152
+ else
153
+ proc_stmt_opt_hash = {}
154
+ end
155
+ else # When no arguments (even )
156
+ prc_stmt_arg = []
157
+ end
158
+
159
+ proc_stmts.push( [proc_stmt_inst, proc_stmt_arg, proc_stmt_opt_hash ] )
160
+ }
161
+
162
+ return ProcBlock.new( proc_command , proc_opt_hash, proc_stmts)
163
+ end
164
+
165
+ end
166
+
167
+
@@ -0,0 +1,168 @@
1
+ class STSBlockParseProcOpts
2
+
3
+ def initialize(elems, idx)
4
+ @size = elems.size
5
+ @elems = elems
6
+ @idx = idx
7
+ @result_hash = Hash.new()
8
+ end
9
+
10
+ def has_next?()
11
+ if @idx + 1 < @size
12
+ return true
13
+ else
14
+ return false
15
+ end
16
+ end
17
+
18
+ def next_token()
19
+ if has_next?
20
+ @idx = @idx + 1
21
+ @elems[@idx]
22
+ else
23
+ nil
24
+ end
25
+ end
26
+
27
+ def peek()
28
+ if has_next?
29
+ @elems[@idx + 1]
30
+ else
31
+ nil
32
+ end
33
+ end
34
+
35
+ def current_token()
36
+ @elems[@idx]
37
+ end
38
+
39
+ # Entry point
40
+ def parse()
41
+ arg_opts()
42
+ return @result_hash
43
+ end
44
+
45
+ # The following grammar is parsed using recursive descent algorithm
46
+
47
+ # arg_opts : arg_opt
48
+ # | arg_opts arg_opt
49
+ #
50
+ # arg_opt : IDENT = primary
51
+ # | IDENT = array
52
+ # | IDENT = func
53
+ # | IDENT
54
+ #
55
+ # parimary : STRING
56
+ # | NUM
57
+ # | IDENT
58
+ #
59
+ # array : [ elems ]
60
+ #
61
+ # func : IDENT ( elems )
62
+ #
63
+ # elems : primary
64
+ # | elems , primary
65
+ #
66
+ #
67
+
68
+ def arg_opts()
69
+ arg_opt()
70
+ if has_next?
71
+ next_token()
72
+ arg_opts()
73
+ end
74
+ end
75
+
76
+ def arg_opt()
77
+ opt_key = ident()
78
+ if (!peek.nil?) && peek.type == :sign && peek.e1 == "="
79
+ next_token() # At =
80
+ if peek.type == :sign && peek.e1 == "[" # RHS of = is array
81
+ next_token() # Now at [
82
+ opt_value = array()
83
+ elsif peek.type == :ident # RHS of = is ident, meaning just ident or function
84
+ next_token()
85
+ if (! peek.nil?) && peek.type == :sign && peek.e1 == "("
86
+ opt_value = func()
87
+ else
88
+ opt_value = ident() # According to BNF, this should be parimary(). However, ident() is more direct and makes sense here.
89
+ end
90
+ elsif [:string, :num].include? peek.type
91
+ next_token()
92
+ opt_value = primary()
93
+ else
94
+ p current_token()
95
+ raise "the token should be :ident or primaries such as :ident, :num and :string after = . Current token: " + current_token().type.to_s
96
+ end
97
+ else
98
+ opt_value = true
99
+ end
100
+ @result_hash[opt_key.to_s] = opt_value
101
+ end
102
+
103
+ def array()
104
+ raise "array should start with [ " if ! (current_token.type == :sign && current_token.e1 == "[")
105
+
106
+ next_token()
107
+ ary = Array.new()
108
+ elems( ary )
109
+
110
+ raise "array should end with ] " if ! (current_token.type == :sign && current_token.e1 == "]")
111
+
112
+ return ary
113
+ end
114
+
115
+ def elems( ary )
116
+ ary.push primary()
117
+ next_token
118
+ if current_token.type == :sign && current_token.e1 == ","
119
+ next_token
120
+ elems( ary )
121
+ else
122
+ return ary
123
+ end
124
+ end
125
+
126
+ def primary()
127
+ case current_token.type
128
+ when :ident
129
+ return ident()
130
+ when :string
131
+ return string()
132
+ when :num
133
+ return num()
134
+ else
135
+ raise "the current token should be :ident, :string or :num."
136
+ end
137
+ end
138
+
139
+ def func()
140
+ func_name = ident()
141
+ parenthesis = next_token()
142
+ raise "func arg should start with ( " if ! (parenthesis.type == :sign && parenthesis.e1 == "(")
143
+
144
+ next_token()
145
+ func_args = elems( Array.new() )
146
+ raise "func should end with ) " if ! (current_token.type == :sign && current_token.e1 == ")")
147
+
148
+ func_hash = {"type" => :func , "fname" => func_name.to_s , "fargs" => func_args}
149
+ return func_hash
150
+ end
151
+
152
+ def ident()
153
+ raise "the current token should be ident" if current_token.type != :ident
154
+ return type_adjust( current_token.e1, :ident)
155
+ end
156
+
157
+ def string()
158
+ raise "the current token should be string" if current_token.type != :string
159
+ return type_adjust( current_token.e1, :string)
160
+ end
161
+
162
+ def num()
163
+ raise "the current token should be num" if current_token.type != :num
164
+ return type_adjust( current_token.e1, :num)
165
+ end
166
+ end
167
+
168
+