qlang 0.0.14 → 0.0.27
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.
- checksums.yaml +4 -4
- data/.coveralls.yml +2 -0
- data/Gemfile +1 -3
- data/README.md +67 -10
- data/bin/qlang +20 -0
- data/lib/qlang.rb +3 -2
- data/lib/qlang/api.rb +47 -0
- data/lib/qlang/api/func_api.rb +7 -1
- data/lib/qlang/api/integral_api.rb +17 -0
- data/lib/qlang/api/list_api.rb +8 -2
- data/lib/qlang/exec.rb +29 -15
- data/lib/qlang/iq.rb +39 -0
- data/lib/qlang/lexer/base.rb +15 -3
- data/lib/qlang/lexer/cont_lexer.rb +4 -1
- data/lib/qlang/lexer/func_lexer.rb +2 -2
- data/lib/qlang/lexer/tokens.rb +45 -0
- data/lib/qlang/lexer/wrap_lexer.rb +10 -1
- data/lib/qlang/parser.rb +40 -20
- data/lib/qlang/parser/base.rb +0 -13
- data/lib/qlang/parser/formula_parser.rb +36 -0
- data/lib/qlang/parser/func_parser.rb +6 -7
- data/lib/qlang/parser/integral_parser.rb +15 -0
- data/lib/qlang/parser/matrix_parser.rb +6 -2
- data/lib/qlang/parser/vector_parser.rb +4 -2
- data/lib/qlang/version.rb +1 -1
- data/q_lang.gemspec +2 -1
- data/spec/iq_spec.rb +141 -0
- data/spec/lexer/regular_expressions_spec.rb +18 -0
- data/spec/objects/function_spec.rb +33 -0
- data/spec/objects/integral_spec.rb +21 -0
- data/spec/objects/list_spec.rb +31 -0
- data/spec/{matrix_spec.rb → objects/matrix_spec.rb} +3 -0
- data/spec/{vector_spec.rb → objects/vector_spec.rb} +0 -0
- data/spec/q_lang_spec.rb +30 -0
- data/spec/spec_helper.rb +5 -0
- metadata +35 -27
- data/bin/dydx +0 -8
- data/bin/q_lang +0 -3
- data/iqb.rb +0 -6
- data/lib/qlang/q_on_irb.rb +0 -8
- data/spec/function_spec.rb +0 -31
- data/spec/list_spec.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 805e11f0c327e3f7fd63d3d5a0de10c34d7f120b
|
4
|
+
data.tar.gz: 420cbcdcc4461907c7092a8405cf85d6e1af40d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f08fd5daf625fcde5decd4504267fdc05e57688ac716440f71c3d0a6ab01f5b94d3a4f56ec7a0476f5892aadbf2ee69163bfc4b094655415f14ba309a8228059
|
7
|
+
data.tar.gz: e4f188b8714777ea728bbb8e7e8ab23e745867b09fe96a2f40d1fc1fa178e4d406df11aa38650e71f969d6917ec6551fa01b31f96421d19081ba52b2901a9d0b
|
data/.coveralls.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,28 +1,85 @@
|
|
1
1
|
# Qlang
|
2
2
|
|
3
|
-
|
3
|
+
[](http://badge.fury.io/rb/qlang) [](https://travis-ci.org/gogotanaka/Q) [](https://coveralls.io/r/gogotanaka/Q?branch=master) [](https://codeclimate.com/github/gogotanaka/Q) [](https://gemnasium.com/gogotanaka/Q)
|
4
4
|
|
5
|
-
|
5
|
+
Enjoy MATH with Keyboard.
|
6
6
|
|
7
|
-
|
7
|
+
### Differentiate
|
8
8
|
|
9
|
-
|
9
|
+
```
|
10
|
+
d/dx(cos(x))
|
11
|
+
=> ( - sin( x ) )
|
10
12
|
|
11
|
-
|
13
|
+
d/dx(log(x))
|
14
|
+
=> ( 1 / x )
|
12
15
|
|
13
|
-
|
16
|
+
# You can omit parentheses
|
14
17
|
|
15
|
-
|
18
|
+
d/dy y^2
|
19
|
+
=> ( 2 * y )
|
20
|
+
|
21
|
+
d/dy xy
|
22
|
+
=> ( x )
|
23
|
+
```
|
24
|
+
|
25
|
+
|
26
|
+
### Integrate
|
27
|
+
|
28
|
+
```
|
29
|
+
S(log(x)dx)[0..1]
|
30
|
+
=> - oo
|
31
|
+
|
32
|
+
S(sin(x)dx)[0..pi]
|
33
|
+
=> 2.0
|
34
|
+
|
35
|
+
S(cos(x)dx)[0..pi]
|
36
|
+
=> 0.0
|
37
|
+
```
|
38
|
+
|
39
|
+
|
40
|
+
### Matrix
|
41
|
+
|
42
|
+
```
|
43
|
+
(1 2 3; 4 5 6)
|
44
|
+
=> (1 2 3; 4 5 6)
|
45
|
+
|
46
|
+
(1 2 3; 4 5 6) + (1 2 3; 4 5 6)
|
47
|
+
=> (2 4 6; 8 10 12)
|
48
|
+
|
49
|
+
(1 2 3; 4 5 6) * (1 2 3)
|
50
|
+
=> (14 32)
|
51
|
+
```
|
52
|
+
|
53
|
+
### Function
|
54
|
+
```
|
55
|
+
f(x, y) = xy
|
56
|
+
f(1, 2)
|
57
|
+
=> 2
|
58
|
+
```
|
59
|
+
|
60
|
+
|
61
|
+
## How to use
|
62
|
+
|
63
|
+
Install it yourself as:
|
16
64
|
|
17
65
|
$ gem install qlang
|
18
66
|
|
19
|
-
|
67
|
+
### Compiler into R
|
68
|
+
|
69
|
+
$ qlang -c -R foo.q
|
70
|
+
|
71
|
+
### Compiler into Ruby
|
72
|
+
|
73
|
+
$ qlang -c -Ruby foo.q
|
74
|
+
|
75
|
+
### Interpreter
|
76
|
+
|
77
|
+
$ qlang -i
|
20
78
|
|
21
|
-
TODO: Write usage instructions here
|
22
79
|
|
23
80
|
## Contributing
|
24
81
|
|
25
|
-
1. Fork it ( https://github.com/
|
82
|
+
1. Fork it ( https://github.com/gogotanaka/Q/fork )
|
26
83
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
84
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
85
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/bin/qlang
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'qlang'
|
3
|
+
include Qlang
|
4
|
+
|
5
|
+
case ARGV.shift
|
6
|
+
when '-i'
|
7
|
+
loop do
|
8
|
+
print 'Q:-> '
|
9
|
+
begin
|
10
|
+
input = $stdin.gets
|
11
|
+
output = Iq.execute(input)
|
12
|
+
$stdout.puts output
|
13
|
+
rescue => e
|
14
|
+
puts e
|
15
|
+
end
|
16
|
+
end
|
17
|
+
when '-c'
|
18
|
+
compiler = Qlang::Exec::Compiler.new(ARGV)
|
19
|
+
compiler.parse!
|
20
|
+
end
|
data/lib/qlang.rb
CHANGED
data/lib/qlang/api.rb
CHANGED
@@ -2,8 +2,55 @@ require 'qlang/api/matrix_api'
|
|
2
2
|
require 'qlang/api/vector_api'
|
3
3
|
require 'qlang/api/list_api'
|
4
4
|
require 'qlang/api/func_api'
|
5
|
+
require 'qlang/api/integral_api'
|
5
6
|
|
6
7
|
module Qlang
|
7
8
|
module Api
|
9
|
+
# TODO:
|
10
|
+
class ::String
|
11
|
+
def rm(str_or_rgx)
|
12
|
+
gsub(str_or_rgx, '')
|
13
|
+
end
|
14
|
+
|
15
|
+
def rm!(str_or_rgx)
|
16
|
+
gsub!(str_or_rgx, '')
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def rms!(*str_or_rgxs)
|
21
|
+
str_or_rgxs.each do |str_or_rgx|
|
22
|
+
rm!(str_or_rgx)
|
23
|
+
end
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def split_by_sp
|
28
|
+
split(/ +/)
|
29
|
+
end
|
30
|
+
|
31
|
+
# FIX:
|
32
|
+
def equalize!
|
33
|
+
rms!(/\A +/, / +\z/)
|
34
|
+
if self =~ /\A\(/ && self =~ /\)\z/
|
35
|
+
rms!(/\A\(/, /\)\z/)
|
36
|
+
rms!(/\A +/, / +\z/)
|
37
|
+
else
|
38
|
+
self
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class ::Matrix
|
44
|
+
def to_q
|
45
|
+
q_rows = rows.map { |row| row.join(' ') }.join('; ')
|
46
|
+
"(#{q_rows})"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class ::Vector
|
51
|
+
def to_q
|
52
|
+
"(#{elements.join(' ')})"
|
53
|
+
end
|
54
|
+
end
|
8
55
|
end
|
9
56
|
end
|
data/lib/qlang/api/func_api.rb
CHANGED
@@ -2,7 +2,13 @@ module Qlang
|
|
2
2
|
module Api
|
3
3
|
module FuncApi
|
4
4
|
def execute(func_name, args, contents)
|
5
|
-
|
5
|
+
case $type
|
6
|
+
when :R
|
7
|
+
"#{func_name} <- function(#{ args.join(' ,') }) #{contents}"
|
8
|
+
when :Ruby
|
9
|
+
"#{func_name}(#{ args.join(' ,') }) <= #{contents}"
|
10
|
+
end
|
11
|
+
|
6
12
|
end
|
7
13
|
module_function :execute
|
8
14
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Qlang
|
2
|
+
module Api
|
3
|
+
module IntegralApi
|
4
|
+
def execute(func, delta, range)
|
5
|
+
a, b = range.split('..')
|
6
|
+
case $type
|
7
|
+
when :R
|
8
|
+
fail 'Integral is not implemented for R'
|
9
|
+
when :Ruby
|
10
|
+
"S(#{func}, #{delta})[#{a}, #{b}]"
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
module_function :execute
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/qlang/api/list_api.rb
CHANGED
@@ -2,8 +2,14 @@ module Qlang
|
|
2
2
|
module Api
|
3
3
|
module ListApi
|
4
4
|
def execute(arys)
|
5
|
-
|
6
|
-
|
5
|
+
case $type
|
6
|
+
when :R
|
7
|
+
combineds_by_equal = arys.map { |ary| "#{ary[0]}=#{ary[1]}" }.join(', ')
|
8
|
+
"list(#{combineds_by_equal})"
|
9
|
+
when :Ruby
|
10
|
+
fail 'List is not implemented for Ruby'
|
11
|
+
end
|
12
|
+
|
7
13
|
end
|
8
14
|
module_function :execute
|
9
15
|
end
|
data/lib/qlang/exec.rb
CHANGED
@@ -6,6 +6,7 @@ module Qlang
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def parse!
|
9
|
+
ch_compile_type(ARGV.shift)
|
9
10
|
parse
|
10
11
|
rescue Exception => e
|
11
12
|
raise e if @options[:trace] || e.is_a?(SystemExit)
|
@@ -18,23 +19,36 @@ module Qlang
|
|
18
19
|
exit 0
|
19
20
|
end
|
20
21
|
|
21
|
-
private
|
22
|
-
raise '#{@args[0]} is unsupported option' unless @args[0] == '-q'
|
23
|
-
filename = @args[1]
|
24
|
-
file = open_file(filename)
|
25
|
-
string = read_file(file)
|
26
|
-
print(Kconv.tosjis(Qlang.compile(string)), '\n')
|
27
|
-
file.close
|
28
|
-
end
|
22
|
+
private
|
29
23
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
24
|
+
def ch_compile_type(lang)
|
25
|
+
case lang
|
26
|
+
when '-Ruby'
|
27
|
+
Qlang.to_ruby
|
28
|
+
when '-R'
|
29
|
+
Qlang.to_r
|
30
|
+
else
|
31
|
+
print 'Q support Ruby and R now.'
|
32
|
+
end
|
33
|
+
end
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
def parse
|
36
|
+
raise '#{@args[0]} is unsupported option' unless @args[0] == '-q'
|
37
|
+
filename = @args[1]
|
38
|
+
file = open_file(filename)
|
39
|
+
string = read_file(file)
|
40
|
+
print(Kconv.tosjis(Qlang.compile(string)), '\n')
|
41
|
+
file.close
|
42
|
+
end
|
43
|
+
|
44
|
+
def open_file(filename, flag = 'r')
|
45
|
+
return if filename.nil?
|
46
|
+
File.open(filename, flag)
|
47
|
+
end
|
48
|
+
|
49
|
+
def read_file(file)
|
50
|
+
file.read
|
51
|
+
end
|
38
52
|
end
|
39
53
|
end
|
40
54
|
end
|
data/lib/qlang/iq.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Qlang
|
2
|
+
module Iq
|
3
|
+
class Dydx::Algebra::Formula
|
4
|
+
# FIX:
|
5
|
+
def to_q
|
6
|
+
str = to_s.gsub(/\*\*/, '^').rm(' * ')
|
7
|
+
str.equalize!
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.execute(code)
|
12
|
+
ruby_code = Q.to_ruby.compile(code)
|
13
|
+
ruby_obj = eval(ruby_code)
|
14
|
+
|
15
|
+
optimize_output(ruby_obj)
|
16
|
+
rescue SyntaxError
|
17
|
+
# TODO: emergency
|
18
|
+
case ruby_code
|
19
|
+
when /(\d)+(\w)/
|
20
|
+
execute("#{$1} * #{$2}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.optimize_output(ruby_obj)
|
25
|
+
case ruby_obj
|
26
|
+
when Matrix, Vector, Dydx::Algebra::Formula
|
27
|
+
ruby_obj.to_q
|
28
|
+
when Float::INFINITY
|
29
|
+
'oo'
|
30
|
+
when - Float::INFINITY
|
31
|
+
'-oo'
|
32
|
+
else
|
33
|
+
str = ruby_obj.to_s
|
34
|
+
str.equalize!
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
data/lib/qlang/lexer/base.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
require 'strscan'
|
2
|
+
require 'qlang/lexer/tokens'
|
3
|
+
|
2
4
|
|
3
5
|
module Qlang
|
4
6
|
module Lexer
|
5
7
|
class Base
|
8
|
+
attr_accessor :lexeds
|
9
|
+
include Tokens
|
6
10
|
class << self
|
7
11
|
attr_reader :token_hash
|
8
12
|
|
@@ -96,10 +100,18 @@ module Qlang
|
|
96
100
|
end
|
97
101
|
end
|
98
102
|
|
99
|
-
|
100
|
-
|
101
|
-
|
103
|
+
# NEW APIs
|
104
|
+
def parsed!(token_position, parsed)
|
105
|
+
@lexeds.delete_at(token_position)
|
106
|
+
@lexeds.insert(token_position, { R: parsed })
|
102
107
|
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def to_num(token_with_num)
|
112
|
+
token_with_num =~ /\d+/
|
113
|
+
$&.to_i
|
114
|
+
end
|
103
115
|
end
|
104
116
|
end
|
105
117
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module Qlang
|
2
2
|
module Lexer
|
3
3
|
class FuncLexer < Base
|
4
|
-
rule(
|
4
|
+
rule(%r@#{FUNCCV}@) { :FDEF }
|
5
5
|
rule(/\=/) { :EQL }
|
6
6
|
|
7
7
|
rule(/[ \t\f]/)
|
8
8
|
|
9
9
|
rule(/\r\n/) { :NLIN }
|
10
|
-
rule(
|
10
|
+
rule(/[\w\(].*/) { :FOML }
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Qlang
|
2
|
+
module Lexer
|
3
|
+
module Tokens
|
4
|
+
# FIRST TOKEN
|
5
|
+
NUM = '[0-9]+'
|
6
|
+
VAR = '[a-z]'
|
7
|
+
FUNCV = '[a-zA-Z]'
|
8
|
+
VARNUM = '[0-9a-z]'
|
9
|
+
ANYSP = ' *'
|
10
|
+
ANYSTR = '.+'
|
11
|
+
NONL = '[^\r\n]'
|
12
|
+
LPRN = '\('
|
13
|
+
RPRN = '\)'
|
14
|
+
LBRC = '\{'
|
15
|
+
RBRC = '\}'
|
16
|
+
CLN = '\:'
|
17
|
+
SCLN = ';'
|
18
|
+
CMA = '\,'
|
19
|
+
SP = ' '
|
20
|
+
|
21
|
+
# SECOND TOKEN
|
22
|
+
class ::String
|
23
|
+
def line_by(char)
|
24
|
+
"#{ANYSP}#{self}(#{ANYSP}#{char}#{ANYSP}#{self})*#{ANYSP}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
NUMS_BY_CMA = NUM.line_by(CMA)
|
28
|
+
VARS_BY_CMA = VAR.line_by(CMA)
|
29
|
+
VARNUMS_BY_CMA = VARNUM.line_by(CMA)
|
30
|
+
NUMS_BY_SP = NUM.line_by(SP)
|
31
|
+
|
32
|
+
# THIRD TOKEN
|
33
|
+
class ::String
|
34
|
+
def func_call
|
35
|
+
"#{FUNCV}#{LPRN}#{ANYSP}#{self}*#{ANYSP}#{RPRN}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
FUNCCN = NUMS_BY_CMA.func_call
|
39
|
+
FUNCCV = VARS_BY_CMA.func_call
|
40
|
+
FUNCCVN = VARNUMS_BY_CMA.func_call
|
41
|
+
|
42
|
+
NUMS_BY_SP_BY_SCLN = NUMS_BY_SP.line_by(SCLN)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|