hilbert 0.0.2700000
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 +15 -0
- data/.coveralls.yml +2 -0
- data/.gitignore +23 -0
- data/.rubocop.yml +25 -0
- data/.travis.yml +5 -0
- data/Gemfile +9 -0
- data/Guardfile +33 -0
- data/LICENSE.txt +22 -0
- data/README.md +159 -0
- data/Rakefile +20 -0
- data/bin/qlang +29 -0
- data/core/Q/Lexer.hs +9 -0
- data/core/Q/Parser.hs +9 -0
- data/core/Q.hs +19 -0
- data/ext/qlang/QMatrix/q_matrix.c +0 -0
- data/ext/qlang/extconf.rb +3 -0
- data/ext/qlang/qlang.c +65 -0
- data/ext/qlang/qlang.h +6 -0
- data/legacy_rspec/langs/Haskell/ex1_after.hs +74 -0
- data/legacy_rspec/langs/Haskell/ex1_before.hs +74 -0
- data/legacy_rspec/langs/Python/ex1_after.py +93 -0
- data/legacy_rspec/langs/Python/ex1_before.py +95 -0
- data/legacy_rspec/langs/R/ex1_after.R +89 -0
- data/legacy_rspec/langs/R/ex1_before.R +89 -0
- data/legacy_rspec/objects/list_spec.rb +31 -0
- data/legacy_rspec/objects/matrix_spec.rb +55 -0
- data/legacy_rspec/objects/vector_spec.rb +47 -0
- data/lib/qlang/api/func_api.rb +17 -0
- data/lib/qlang/api/integral_api.rb +16 -0
- data/lib/qlang/api/limit_api.rb +22 -0
- data/lib/qlang/api/list_api.rb +16 -0
- data/lib/qlang/api/matrix_api.rb +20 -0
- data/lib/qlang/api/sigma_api.rb +16 -0
- data/lib/qlang/api/vector_api.rb +19 -0
- data/lib/qlang/api.rb +23 -0
- data/lib/qlang/exec.rb +64 -0
- data/lib/qlang/iq.rb +45 -0
- data/lib/qlang/lexer/base.rb +107 -0
- data/lib/qlang/lexer/formula_lexer.rb +20 -0
- data/lib/qlang/lexer/main_lexer.rb +34 -0
- data/lib/qlang/lexer/tokens.rb +94 -0
- data/lib/qlang/lexer.rb +11 -0
- data/lib/qlang/meta_info.rb +27 -0
- data/lib/qlang/parser/base.rb +7 -0
- data/lib/qlang/parser/formula_parser.rb +36 -0
- data/lib/qlang/parser/func_parser.rb +15 -0
- data/lib/qlang/parser/integral_parser.rb +15 -0
- data/lib/qlang/parser/limit_parser.rb +16 -0
- data/lib/qlang/parser/list_parser.rb +12 -0
- data/lib/qlang/parser/matrix_parser.rb +17 -0
- data/lib/qlang/parser/sigma_parser.rb +17 -0
- data/lib/qlang/parser/vector_parser.rb +13 -0
- data/lib/qlang/parser.rb +101 -0
- data/lib/qlang/utils/langs.yml +7 -0
- data/lib/qlang/utils/ruby_ext.rb +54 -0
- data/lib/qlang/version.rb +3 -0
- data/lib/qlang.rb +37 -0
- data/qlang.gemspec +28 -0
- data/test/internal/test_tokens.rb +35 -0
- data/test/interpreter/base.rb +17 -0
- data/test/interpreter/test_differential.rb +43 -0
- data/test/interpreter/test_function.rb +44 -0
- data/test/interpreter/test_general.rb +12 -0
- data/test/interpreter/test_integral.rb +38 -0
- data/test/interpreter/test_limit.rb +37 -0
- data/test/interpreter/test_matrix.rb +70 -0
- data/test/interpreter/test_sigma.rb +25 -0
- data/test/interpreter/test_vector.rb +28 -0
- data/test/langs/test_r.rb +32 -0
- data/test/langs/test_ruby.rb +9 -0
- data/test/minitest_helper.rb +8 -0
- data/test/q_matrix/test_q_matrix.rb +13 -0
- data/test/test_qlang.rb +24 -0
- metadata +203 -0
data/lib/qlang/exec.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
module Qlang
|
2
|
+
module Exec
|
3
|
+
class Compiler
|
4
|
+
def initialize(args)
|
5
|
+
@args = args
|
6
|
+
end
|
7
|
+
|
8
|
+
def output!
|
9
|
+
ch_compile_type(@args.first)
|
10
|
+
parse_string = parse(@args[1])
|
11
|
+
write!(@args[2], parse_string)
|
12
|
+
|
13
|
+
rescue Exception => e
|
14
|
+
raise e if @options[:trace] || e.is_a?(SystemExit)
|
15
|
+
|
16
|
+
print "#{e.class}: " unless e.class == RuntimeError
|
17
|
+
puts "#{e.message}"
|
18
|
+
puts ' Use --trace for backtrace.'
|
19
|
+
exit 1
|
20
|
+
ensure
|
21
|
+
exit 0
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def ch_compile_type(lang)
|
27
|
+
case lang
|
28
|
+
when '-rb'
|
29
|
+
Qlang.to_ruby
|
30
|
+
when '-r'
|
31
|
+
Qlang.to_r
|
32
|
+
when '-py'
|
33
|
+
Qlang.to_python
|
34
|
+
else
|
35
|
+
print 'Q support only Ruby and R now.'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def parse(file_path)
|
40
|
+
file = open_file(file_path)
|
41
|
+
input_string = read_file(file)
|
42
|
+
file.close
|
43
|
+
input_string.gsub(/(.*)I love mathematics\.(.*)Q\.E\.D(.*)/m) {
|
44
|
+
"#{$1}#{Kconv.tosjis(Qlang.compile($2))}#{$3}"
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def write!(output_path, string)
|
49
|
+
open(output_path, 'w') do |f|
|
50
|
+
f.puts string
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def open_file(filename, flag = 'r')
|
55
|
+
return if filename.nil?
|
56
|
+
File.open(filename, flag)
|
57
|
+
end
|
58
|
+
|
59
|
+
def read_file(file)
|
60
|
+
file.read
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/qlang/iq.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'dydx'
|
2
|
+
include Dydx
|
3
|
+
|
4
|
+
module Qlang
|
5
|
+
module Iq
|
6
|
+
class Dydx::Algebra::Formula
|
7
|
+
# FIX:
|
8
|
+
def to_q
|
9
|
+
str = to_s.gsub(/\*\*/, '^').rm(' * ')
|
10
|
+
str.equalize!
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.execute(code)
|
15
|
+
ruby_code = Q.to_ruby.compile(code.encode('utf-8'))
|
16
|
+
ruby_obj = eval(ruby_code)
|
17
|
+
|
18
|
+
optimize_output(ruby_obj).encode('utf-8')
|
19
|
+
rescue SyntaxError
|
20
|
+
# TODO: emergency
|
21
|
+
case ruby_code
|
22
|
+
when /(\d)+(\w)/
|
23
|
+
execute("#{$1} * #{$2}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.optimize_output(ruby_obj)
|
28
|
+
|
29
|
+
case ruby_obj
|
30
|
+
when Matrix, Vector, Dydx::Algebra::Formula
|
31
|
+
ruby_obj.to_q
|
32
|
+
when Numeric
|
33
|
+
# TODO: I know you wanna way..
|
34
|
+
if ruby_obj > 10000.0 then 'oo'
|
35
|
+
elsif ruby_obj < -10000.0 then '-oo'
|
36
|
+
elsif ruby_obj.abs < Float::EPSILON then '0.0'
|
37
|
+
else ruby_obj.to_s.equalize!
|
38
|
+
end
|
39
|
+
else
|
40
|
+
str = ruby_obj.to_s
|
41
|
+
str.equalize!
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'strscan'
|
2
|
+
require 'qlang/lexer/tokens'
|
3
|
+
|
4
|
+
module Qlang
|
5
|
+
module Lexer
|
6
|
+
class Base
|
7
|
+
attr_accessor :lexeds
|
8
|
+
include Tokens
|
9
|
+
class << self
|
10
|
+
attr_reader :token_rule_hash
|
11
|
+
|
12
|
+
def rule(pattern, &token)
|
13
|
+
token ||= proc { :NULL }
|
14
|
+
@token_rule_hash ||= {}
|
15
|
+
@token_rule_hash[pattern] = token.call
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(str)
|
20
|
+
ss = StringScanner.new(str)
|
21
|
+
@lexeds = []
|
22
|
+
until ss.eos?
|
23
|
+
scan_rslt, ss = scan(ss)
|
24
|
+
if scan_rslt
|
25
|
+
@lexeds << scan_rslt unless scan_rslt[:token] == :NULL
|
26
|
+
else
|
27
|
+
fail "I'm so sorry, something wrong. Please feel free to report this."
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def scan(ss)
|
33
|
+
scan_rslt = nil
|
34
|
+
token_rule_hash.each do |pattern, token|
|
35
|
+
if ss.scan(pattern)
|
36
|
+
scan_rslt = {
|
37
|
+
token: token,
|
38
|
+
value: ss[0],
|
39
|
+
els: 4.times.inject([]) { |s,i|s << ss[i+1] }.compact
|
40
|
+
}
|
41
|
+
break
|
42
|
+
end
|
43
|
+
end
|
44
|
+
[scan_rslt, ss]
|
45
|
+
end
|
46
|
+
|
47
|
+
# Accessor
|
48
|
+
## GET(without side effect)
|
49
|
+
def get_value(num)
|
50
|
+
num = num.to_i
|
51
|
+
@lexeds[num][:value]
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_els(num)
|
55
|
+
num = num.to_i
|
56
|
+
@lexeds[num][:els]
|
57
|
+
end
|
58
|
+
|
59
|
+
def token_str
|
60
|
+
@lexeds.map.with_index { |lexed, i| ":#{lexed[:token]}#{i}" }.join
|
61
|
+
end
|
62
|
+
|
63
|
+
def token_rule_hash
|
64
|
+
self.class.token_rule_hash
|
65
|
+
end
|
66
|
+
|
67
|
+
## POST(with side effect, without idempotence.)
|
68
|
+
def parsed!(parsed, target)
|
69
|
+
case target
|
70
|
+
when Range
|
71
|
+
parsed_between!((target.first.to_i)..(target.last.to_i), parsed)
|
72
|
+
else
|
73
|
+
parsed_at!(target.to_i, parsed)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# squash!(range, token: :CONT)
|
78
|
+
def squash!(range, opts = { token: :CONT })
|
79
|
+
token = opts[:token]
|
80
|
+
range = (range.first.to_i)..(range.last.to_i)
|
81
|
+
value = values[range].join
|
82
|
+
range.count.times { @lexeds.delete_at(range.first) }
|
83
|
+
@lexeds.insert(range.first, { token: token, value: value })
|
84
|
+
end
|
85
|
+
|
86
|
+
# Legacy Accessor
|
87
|
+
def values
|
88
|
+
@lexeds.map { |lexed| lexed[:value] }
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def parsed_at!(token_position, parsed)
|
94
|
+
@lexeds.delete_at(token_position)
|
95
|
+
@lexeds.insert(token_position, { token: :R, value: parsed })
|
96
|
+
end
|
97
|
+
|
98
|
+
def parsed_between!(token_range, parsed)
|
99
|
+
start_pos = token_range.first
|
100
|
+
token_range.count.times do
|
101
|
+
@lexeds.delete_at(start_pos)
|
102
|
+
end
|
103
|
+
@lexeds.insert(start_pos, { token: :R, value: parsed })
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Qlang
|
2
|
+
module Lexer
|
3
|
+
class FormulaLexer < Base
|
4
|
+
rule(/\^/) { :EXP }
|
5
|
+
rule(/#{EMBEDDED_FUNC}/) { :BFUNC }
|
6
|
+
rule(/(pi|[1-9a-z]){2,}/) { :MUL }
|
7
|
+
rule(/(pi|[1-9a-z])/) { :SNGL }
|
8
|
+
rule(/([^\^1-9a-z]|^pi)+/) { :OTHER }
|
9
|
+
|
10
|
+
# rule(/#{OPE}/) { :OPE }
|
11
|
+
# rule(/#{FUNCV}/) { :FUNCV }
|
12
|
+
# rule(/#{VAR}/) { :VAR }
|
13
|
+
# rule(/#{NUM}/) { :NUM }
|
14
|
+
# rule(/#{LPRN}/) { :LPRN }
|
15
|
+
# rule(/#{RPRN}/) { :RPRN }
|
16
|
+
|
17
|
+
# rule(/#{ANYSP}/) { }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
module Qlang
|
5
|
+
module Lexer
|
6
|
+
class MainLexer < Base
|
7
|
+
rule(/(#{FUNCCV})#{ANYSP}#{EQL}#{ANYSP}(#{FORMULA})/) { :def_func }
|
8
|
+
rule(/#{ITGRLSYM}#{ANYSP}#{LPRN}(#{ANYSTR})#{RPRN}#{LBRCT}(#{ANYSTR})#{RBRCT}/) { :integral }
|
9
|
+
rule(/d\/d(#{VAR}) (#{FORMULA})/) { :differential }
|
10
|
+
|
11
|
+
rule(/lim#{LBRCT}(#{VAR})#{RSARW}(#{VARNUM})#{RBRCT} (#{FORMULA})/) { :limit }
|
12
|
+
|
13
|
+
rule(/#{LPRN}(#{NUMS_BY_SP})#{RPRN}/) { :vector }
|
14
|
+
rule(/#{LPRN}(#{NUMS_BY_SP_BY_SCLN_OR_NELN})#{RPRN}t/m) { :tmatrix }
|
15
|
+
rule(/#{LPRN}(#{NUMS_BY_SP_BY_SCLN_OR_NELN})#{RPRN}/m) { :matrix }
|
16
|
+
|
17
|
+
rule(/∑#{LBRCT}(#{VAR})=(#{INT}),#{ANYSP}(#{INT})#{RBRCT} (#{FORMULA})/) { :sigma }
|
18
|
+
rule(/sigma#{LBRCT}(#{VAR})=(#{INT}),#{ANYSP}(#{INT})#{RBRCT} (#{FORMULA})/) { :sigma }
|
19
|
+
|
20
|
+
rule(/#{FUNCCN}/) { :FUNCCN }
|
21
|
+
|
22
|
+
rule(/#{LPRN}/) { :LPRN }
|
23
|
+
rule(/#{RPRN}/) { :RPRN }
|
24
|
+
rule(/#{LBRCS}/) { :LBRCS }
|
25
|
+
rule(/#{RBRCS}/) { :RBRCS }
|
26
|
+
|
27
|
+
rule(/[ \t\f]/)
|
28
|
+
|
29
|
+
rule(/(\r|\n)+/) { :NULL }
|
30
|
+
|
31
|
+
rule(/[^\(\)\{\}(\n\n)]+/) { :CONT }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Qlang
|
2
|
+
module Lexer
|
3
|
+
module Tokens
|
4
|
+
# NUM
|
5
|
+
INT = /[0-9]+/
|
6
|
+
FLO = /[0-9]+\.[0-9]+/
|
7
|
+
E = /e/
|
8
|
+
PI = /pi/
|
9
|
+
INF = /oo/
|
10
|
+
NUM = /(?:#{FLO}|#{INT}|#{E}|#{PI}|#{INF})/
|
11
|
+
|
12
|
+
# FUNCTION
|
13
|
+
LPRN = /\(/
|
14
|
+
RPRN = /\)/
|
15
|
+
EMBEDDED_FUNC = /(?:sin|cos|tan|log)/
|
16
|
+
USER_FUNC = /[a-zA-Z]/
|
17
|
+
# h(x + y) != h * (x + y)
|
18
|
+
FUNCV = /(?:#{EMBEDDED_FUNC}|#{USER_FUNC})(?=#{LPRN})/
|
19
|
+
|
20
|
+
# VARIABLE
|
21
|
+
VAR = /(?:[a-d]|[f-z])/
|
22
|
+
# VAR_MUL2 = /(?!pi)#{VAR}{2}/
|
23
|
+
# #VAR_MUL3 = /(?!#{EMBEDDED_FUNC})#{VAR}{3}/
|
24
|
+
# # FIX:
|
25
|
+
# VAR_MUL = /(?!#{EMBEDDED_FUNC})#{VAR_MUL2}/
|
26
|
+
|
27
|
+
# # TERM
|
28
|
+
# TERM = /(#{NUM}|#{VAR_MUL}|#{VAR_MUL})/
|
29
|
+
|
30
|
+
# OPE
|
31
|
+
PLS = /\+/
|
32
|
+
SUB = /-/
|
33
|
+
MUL = /\*/
|
34
|
+
DIV = /\//
|
35
|
+
EXP = /(\*\*|\^)/
|
36
|
+
OPE = /(?:#{PLS}|#{SUB}|#{MUL}|#{DIV}|#{EXP})/
|
37
|
+
|
38
|
+
VARNUM = /(?:#{NUM}|#{VAR})/
|
39
|
+
ANYSP = ' *'
|
40
|
+
ANYSTR = /.+/
|
41
|
+
NONL = /[^\r\n]/
|
42
|
+
|
43
|
+
PRN = /(?:#{LPRN}|#{RPRN})/
|
44
|
+
|
45
|
+
LBRCS = /\{/
|
46
|
+
RBRCS = /\}/
|
47
|
+
BRCS = /(?:#{LBRCS}|#{RBRCS})/
|
48
|
+
|
49
|
+
LBRCT = /\[/
|
50
|
+
RBRCT = /\]/
|
51
|
+
BRCT = /(?:#{LBRCT}|#{RBRCT})/
|
52
|
+
|
53
|
+
CLN = /\:/
|
54
|
+
SCLN = /;/
|
55
|
+
CMA = /\,/
|
56
|
+
EQL = /\=/
|
57
|
+
|
58
|
+
RSARW = '->'
|
59
|
+
LSARW = '<-'
|
60
|
+
RDARW = '=>'
|
61
|
+
LDARW = '<='
|
62
|
+
SP = / /
|
63
|
+
NLIN = /(\r|\n)/
|
64
|
+
|
65
|
+
ITGRLSYM = 'S'
|
66
|
+
# FIXIT
|
67
|
+
SCLN_OR_NELN = /(?:#{SCLN}|#{NLIN})/
|
68
|
+
|
69
|
+
# TODO: what is better
|
70
|
+
class Util
|
71
|
+
def self.string_out(str, partition)
|
72
|
+
/#{ANYSP}#{str}(?:#{ANYSP}#{partition}#{ANYSP}#{str})*#{ANYSP}/
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.func_call(args)
|
76
|
+
/#{FUNCV}#{LPRN}#{ANYSP}#{args}#{ANYSP}#{RPRN}/
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
NUMS_BY_CMA = Util.string_out(NUM, CMA)
|
81
|
+
VARS_BY_CMA = Util.string_out(VAR, CMA)
|
82
|
+
VARNUMS_BY_CMA = Util.string_out(VARNUM, CMA)
|
83
|
+
NUMS_BY_SP = Util.string_out(NUM, SP)
|
84
|
+
|
85
|
+
FUNCCN = Util.func_call(NUMS_BY_CMA)
|
86
|
+
FUNCCV = Util.func_call(VARS_BY_CMA)
|
87
|
+
FUNCCVN = Util.func_call(VARNUMS_BY_CMA)
|
88
|
+
|
89
|
+
NUMS_BY_SP_BY_SCLN_OR_NELN = Util.string_out(NUMS_BY_SP, SCLN_OR_NELN)
|
90
|
+
|
91
|
+
FORMULA = /(?:#{OPE}|#{FUNCV}|#{VAR}|#{NUM}|#{PRN}|#{ANYSP})+/
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/qlang/lexer.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# $meta_info indicate what and how to do.
|
2
|
+
|
3
|
+
class MetaInfo
|
4
|
+
include Singleton
|
5
|
+
attr_accessor :lang, :opts, :mode
|
6
|
+
|
7
|
+
def _load
|
8
|
+
# compiles into R as default.
|
9
|
+
lang = :r
|
10
|
+
end
|
11
|
+
|
12
|
+
# TODO: YAML.load_file("./lib/qlang/utils/langs.yml")['langs']
|
13
|
+
def langs_hash
|
14
|
+
{
|
15
|
+
r: 'R',
|
16
|
+
ruby: 'Ruby',
|
17
|
+
python: 'Pyhton',
|
18
|
+
haskell: 'Haskell',
|
19
|
+
scala: 'Scala',
|
20
|
+
js: 'Javascript'
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def lang_str
|
25
|
+
LANGS_HASH[@lang.to_s]
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'qlang/lexer/formula_lexer'
|
2
|
+
|
3
|
+
module Qlang
|
4
|
+
module Parser
|
5
|
+
module FormulaParser
|
6
|
+
include Lexer::Tokens
|
7
|
+
|
8
|
+
def self.execute(str)
|
9
|
+
lexed = Lexer::FormulaLexer.new(str)
|
10
|
+
time = Time.now
|
11
|
+
loop do
|
12
|
+
fail "I'm so sorry, something wrong. Please feel free to report this." if Time.now > time + 10
|
13
|
+
case lexed.token_str
|
14
|
+
when /:EXP(\d+)/
|
15
|
+
new_ope = $meta_info.lang == :ruby ? '**' : '^'
|
16
|
+
lexed.parsed!(new_ope, $1)
|
17
|
+
when /:MUL(\d+)/
|
18
|
+
sss = StringScanner.new(lexed.get_value($1))
|
19
|
+
ary = []
|
20
|
+
until sss.eos?
|
21
|
+
[/pi/, /[1-9a-z]/].each do |rgx2|
|
22
|
+
ary << sss[0] if sss.scan(rgx2)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
parsed = ary.join(' * ')
|
26
|
+
|
27
|
+
lexed.parsed!(parsed, $1)
|
28
|
+
else
|
29
|
+
break
|
30
|
+
end
|
31
|
+
end
|
32
|
+
lexed.values.join
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'qlang/lexer/tokens'
|
2
|
+
module Qlang
|
3
|
+
module Parser
|
4
|
+
module FuncParser
|
5
|
+
include Base
|
6
|
+
include Lexer::Tokens
|
7
|
+
def execute(els)
|
8
|
+
def_func, formula = els[0], els[1]
|
9
|
+
def_func =~ /(#{USER_FUNC})#{LPRN}#{ANYSP}(#{VARS_BY_CMA})#{ANYSP}#{RPRN}/
|
10
|
+
FuncApi.execute($1, $2.split(' *,'), FormulaParser.execute(formula))
|
11
|
+
end
|
12
|
+
module_function :execute
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Qlang
|
2
|
+
module Parser
|
3
|
+
module IntegralParser
|
4
|
+
include Base
|
5
|
+
def execute(els)
|
6
|
+
integrated, range = els[0], els[1]
|
7
|
+
|
8
|
+
integrated.rm!(' ')
|
9
|
+
|
10
|
+
IntegralApi.execute(FormulaParser.execute(integrated[0..-3]), integrated[-2..-1], range)
|
11
|
+
end
|
12
|
+
module_function :execute
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Qlang
|
2
|
+
module Parser
|
3
|
+
module MatrixParser
|
4
|
+
include Base
|
5
|
+
def execute(els, opts = { trans: false })
|
6
|
+
trans = opts[:trans]
|
7
|
+
rows = els.first.split(/ *(?:;|\n) */).map(&:split_by_sp)
|
8
|
+
rows.all? { |row| row.count == rows.first.count }
|
9
|
+
if trans
|
10
|
+
rows = rows.transpose
|
11
|
+
end
|
12
|
+
MatrixApi.execute(rows)
|
13
|
+
end
|
14
|
+
module_function :execute
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/qlang/parser.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'qlang/api'
|
2
|
+
|
3
|
+
require 'qlang/parser/base'
|
4
|
+
require 'qlang/parser/matrix_parser'
|
5
|
+
require 'qlang/parser/vector_parser'
|
6
|
+
require 'qlang/parser/list_parser'
|
7
|
+
require 'qlang/parser/func_parser'
|
8
|
+
require 'qlang/parser/integral_parser'
|
9
|
+
require 'qlang/parser/limit_parser'
|
10
|
+
require 'qlang/parser/sigma_parser'
|
11
|
+
|
12
|
+
require 'qlang/parser/formula_parser'
|
13
|
+
|
14
|
+
module Qlang
|
15
|
+
module Parser
|
16
|
+
include Lexer::Tokens
|
17
|
+
SYM = '\w+'
|
18
|
+
ONEHASH = "#{ANYSP}#{SYM}#{CLN}#{ANYSP}#{VARNUM}#{ANYSP}" # sdf: 234
|
19
|
+
def execute(lexed)
|
20
|
+
time = Time.now
|
21
|
+
until lexed.token_str =~ /\A:(NLIN|R)\d+\z/
|
22
|
+
fail "I'm so sorry, something wrong. Please feel free to report this." if Time.now > time + 10
|
23
|
+
|
24
|
+
case lexed.token_str
|
25
|
+
when /:(vector)(\d+)/, /:(matrix)(\d+)/, /:(tmatrix)(\d+)/, /:(integral)(\d+)/, /:(def_func)(\d+)/, /:(differential)(\d+)/, /:(limit)(\d+)/, /:(sigma)(\d+)/
|
26
|
+
token_els = lexed.get_els($2)
|
27
|
+
|
28
|
+
parsed =
|
29
|
+
case $1
|
30
|
+
when 'vector'
|
31
|
+
VectorParser.execute(token_els)
|
32
|
+
when 'matrix'
|
33
|
+
MatrixParser.execute(token_els)
|
34
|
+
when 'tmatrix'
|
35
|
+
MatrixParser.execute(token_els, trans: true)
|
36
|
+
when 'limit'
|
37
|
+
LimitParser.execute(token_els)
|
38
|
+
when 'integral'
|
39
|
+
IntegralParser.execute(token_els)
|
40
|
+
when 'def_func'
|
41
|
+
FuncParser.execute(token_els)
|
42
|
+
when 'sigma'
|
43
|
+
SigmaParser.execute(token_els)
|
44
|
+
when 'differential'
|
45
|
+
del_var, formula = token_els
|
46
|
+
"d/d#{del_var}(#{FormulaParser.execute(formula)})"
|
47
|
+
end
|
48
|
+
lexed.parsed!(parsed, $2)
|
49
|
+
|
50
|
+
when /:LPRN(\d+):CONT(\d+):RPRN(\d+)/
|
51
|
+
tokens_range = $1.to_i..$3.to_i
|
52
|
+
token_val =
|
53
|
+
|
54
|
+
lexed.parsed!(
|
55
|
+
lexed.get_value($2).parentheses,
|
56
|
+
tokens_range
|
57
|
+
)
|
58
|
+
|
59
|
+
when /:LBRCS(\d+):CONT(\d+):RBRCS(\d+)/
|
60
|
+
tokens_range = $1.to_i..$3.to_i
|
61
|
+
token_val = lexed.get_value($2)
|
62
|
+
|
63
|
+
cont =
|
64
|
+
case token_val
|
65
|
+
when /#{ONEHASH}(#{CMA}#{ONEHASH})*/
|
66
|
+
ListParser.execute(token_val)
|
67
|
+
else
|
68
|
+
token_val
|
69
|
+
end
|
70
|
+
|
71
|
+
lexed.parsed!(cont, tokens_range)
|
72
|
+
|
73
|
+
when /:FUNCCN(\d+)/
|
74
|
+
token_val = lexed.get_value($1)
|
75
|
+
lexed.parsed!(token_val.parentheses, $1)
|
76
|
+
|
77
|
+
when /:CONT(\d+)/
|
78
|
+
lexed.parsed!(lexed.get_value($1), $1)
|
79
|
+
end
|
80
|
+
lexed.squash!(($1.to_i)..($1.to_i+1)) if lexed.token_str =~ /:(?:CONT|R)(\d+):(?:CONT|R)(\d+)/
|
81
|
+
end
|
82
|
+
|
83
|
+
LangEqualizer.execute(
|
84
|
+
lexed.values.join
|
85
|
+
)
|
86
|
+
end
|
87
|
+
module_function :execute
|
88
|
+
|
89
|
+
# FIXIT
|
90
|
+
class LangEqualizer
|
91
|
+
def self.execute(str)
|
92
|
+
case $meta_info.lang
|
93
|
+
when :ruby
|
94
|
+
str.gsub(/\^/, '**')
|
95
|
+
else
|
96
|
+
str
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|