rubic 0.1.2 → 0.2.0
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/README.md +16 -1
- data/bin/rubic +27 -13
- data/lib/rubic.rb +1 -0
- data/lib/rubic/builtin.rb +3 -0
- data/lib/rubic/builtin/list.rb +35 -0
- data/lib/rubic/builtin/number.rb +80 -0
- data/lib/rubic/builtin/output.rb +17 -0
- data/lib/rubic/environment.rb +7 -0
- data/lib/rubic/inspector.rb +24 -0
- data/lib/rubic/interpreter.rb +51 -32
- data/lib/rubic/parser.rb +223 -144
- data/lib/rubic/parser.y +43 -18
- data/lib/rubic/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ce7e32bbc4068cda59ee86d64f3210c2b6272ae
|
4
|
+
data.tar.gz: d823d0e4f0c57f89681e0f14bb650ae700effef6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 80788b219b735f2c54aeaa57b5957e8018e8a5c34fbd074ed4fa6a85d43bed4f955eaa547f5f782ba9e482eb19233dafdf197ac77ece18d284c13f47dce0c12c
|
7
|
+
data.tar.gz: a1682bcb6a83ebff28c20da879a9bc73aa69cde0b8e86e06d2f6dbae37e74007fa5664ad8c66e115050b17af8fb683ded60c1179e1ea8b9a07471362033ea732
|
data/README.md
CHANGED
@@ -26,9 +26,24 @@ Or install it yourself as:
|
|
26
26
|
|
27
27
|
## Usage
|
28
28
|
|
29
|
+
Once you install this gem, the `rubic` executable can be used. Simply run it as:
|
30
|
+
|
31
|
+
$ rubic
|
32
|
+
|
33
|
+
then the <abbr title="Read-Eval-Print Loop">REPL</abbr> will start. Or pass the Scheme source file as:
|
34
|
+
|
35
|
+
$ rubic /path/to/your_code.scm
|
36
|
+
|
37
|
+
then the program will be executed.
|
38
|
+
|
39
|
+
You can also evaluate Scheme code from your Ruby application:
|
40
|
+
|
29
41
|
```ruby
|
42
|
+
require 'rubic'
|
30
43
|
rubic = Rubic::Interpreter.new
|
31
|
-
rubic.evaluate(
|
44
|
+
rubic.evaluate('(define x 100)')
|
45
|
+
rubic.evaluate('(+ x 3)') # => 103
|
46
|
+
rubic.evaluate('(list 1 2 3)') # => [1, [2, [3, []]]
|
32
47
|
```
|
33
48
|
|
34
49
|
## Development
|
data/bin/rubic
CHANGED
@@ -6,22 +6,36 @@ require 'readline'
|
|
6
6
|
|
7
7
|
using Rubic::Inspector
|
8
8
|
|
9
|
-
|
9
|
+
if ARGV.size == 1
|
10
|
+
file = ARGV.shift
|
11
|
+
File.open(file) do |f|
|
12
|
+
rubic = Rubic::Interpreter.new
|
10
13
|
|
11
|
-
|
12
|
-
|
14
|
+
begin
|
15
|
+
rubic.evaluate(f.read)
|
16
|
+
rescue Rubic::RubicError => e
|
17
|
+
puts "\e[31mError: #{e.message}\e[0m"
|
18
|
+
exit false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
else
|
22
|
+
# REPL mode
|
13
23
|
|
14
|
-
|
24
|
+
puts "Welcome to interactive Rubic (v#{Rubic::VERSION})"
|
25
|
+
puts 'Hit ^D to exit'
|
15
26
|
|
16
|
-
|
17
|
-
|
18
|
-
while input.
|
19
|
-
|
20
|
-
|
27
|
+
rubic = Rubic::Interpreter.new
|
28
|
+
|
29
|
+
while input = Readline.readline(">> ", true)
|
30
|
+
next if input.empty?
|
31
|
+
while input.count('(') > input.count(')')
|
32
|
+
input << Readline.readline(' | ', true)
|
33
|
+
end
|
21
34
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
35
|
+
begin
|
36
|
+
puts '=> ' + rubic.evaluate(input).inspect
|
37
|
+
rescue Rubic::RubicError => e
|
38
|
+
puts "\e[31mError: #{e.message}\e[0m"
|
39
|
+
end
|
26
40
|
end
|
27
41
|
end
|
data/lib/rubic.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Rubic
|
2
|
+
module Builtin
|
3
|
+
class List
|
4
|
+
def cons(a, b)
|
5
|
+
[a, b]
|
6
|
+
end
|
7
|
+
|
8
|
+
def car(l)
|
9
|
+
unless pair? l
|
10
|
+
raise Rubic::TypeError, "pair required, but got `#{l}'"
|
11
|
+
end
|
12
|
+
l.first
|
13
|
+
end
|
14
|
+
|
15
|
+
def cdr(l)
|
16
|
+
unless pair? l
|
17
|
+
raise Rubic::TypeError, "pair required, but got `#{l}'"
|
18
|
+
end
|
19
|
+
l.last
|
20
|
+
end
|
21
|
+
|
22
|
+
def list(*args)
|
23
|
+
args.reverse.reduce([]) {|res, e| [e, res] }
|
24
|
+
end
|
25
|
+
|
26
|
+
def pair?(suspect)
|
27
|
+
suspect.is_a?(Array) ? suspect.any? : false
|
28
|
+
end
|
29
|
+
|
30
|
+
def null?(suspect)
|
31
|
+
suspect.is_a?(Array) ? suspect.empty? : false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Rubic
|
2
|
+
module Builtin
|
3
|
+
class Number
|
4
|
+
def +(*args)
|
5
|
+
args.reduce(0) do |res, i|
|
6
|
+
unless number? i
|
7
|
+
raise Rubic::TypeError, "operation `+' is not defined between `#{res}' and `#{i}'"
|
8
|
+
end
|
9
|
+
res + i
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def -(*args)
|
14
|
+
case args.size
|
15
|
+
when 0
|
16
|
+
raise Rubic::ArgumentError, "wrong number of arguments (0 for 1+)"
|
17
|
+
when 1
|
18
|
+
-args.first
|
19
|
+
else
|
20
|
+
args.reduce do |res, i|
|
21
|
+
unless number? i
|
22
|
+
raise Rubic::TypeError, "operation `-' is not defined between `#{res}' and `#{i}'"
|
23
|
+
end
|
24
|
+
res - i
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def *(*args)
|
30
|
+
args.reduce(1) do |res, i|
|
31
|
+
unless number? i
|
32
|
+
raise Rubic::TypeError, "operation `*' is not defined between `#{res}' and `#{i}'"
|
33
|
+
end
|
34
|
+
res * i
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def /(*args)
|
39
|
+
case args.size
|
40
|
+
when 0
|
41
|
+
raise Rubic::ArgumentError, "wrong number of arguments (0 for 1+)"
|
42
|
+
when 1
|
43
|
+
1 / args.first
|
44
|
+
else
|
45
|
+
args.reduce do |res, i|
|
46
|
+
unless number? i
|
47
|
+
raise Rubic::TypeError, "operation `/' is not defined between `#{res}' and `#{i}'"
|
48
|
+
end
|
49
|
+
res / i
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def <(a, b)
|
55
|
+
unless number?(a) && number?(b)
|
56
|
+
raise Rubic::TypeError, "operation `<' is not defined between `#{a}' and `#{b}'"
|
57
|
+
end
|
58
|
+
a < b
|
59
|
+
end
|
60
|
+
|
61
|
+
def >(a, b)
|
62
|
+
unless number?(a) && number?(b)
|
63
|
+
raise Rubic::TypeError, "operation `>' is not defined between `#{a}' and `#{b}'"
|
64
|
+
end
|
65
|
+
a > b
|
66
|
+
end
|
67
|
+
|
68
|
+
define_method '=' do |a, b|
|
69
|
+
unless number?(a) && number?(b)
|
70
|
+
raise Rubic::TypeError, "operation `=' is not defined between `#{a}' and `#{b}'"
|
71
|
+
end
|
72
|
+
a == b
|
73
|
+
end
|
74
|
+
|
75
|
+
def number?(suspect)
|
76
|
+
suspect.is_a?(Integer) || suspect.is_a?(Float)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/rubic/environment.rb
CHANGED
data/lib/rubic/inspector.rb
CHANGED
@@ -14,12 +14,36 @@ module Rubic
|
|
14
14
|
"#{first.inspect} . #{last.inspect}"
|
15
15
|
end
|
16
16
|
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
"(#{to_s_rec})"
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s_rec
|
23
|
+
if empty?
|
24
|
+
''
|
25
|
+
elsif last.is_a?(Array)
|
26
|
+
[first.to_s, last.to_s_rec].join(' ').strip
|
27
|
+
else
|
28
|
+
"#{first.to_s} . #{last.to_s}"
|
29
|
+
end
|
30
|
+
end
|
17
31
|
end
|
18
32
|
|
19
33
|
refine Proc do
|
20
34
|
def inspect
|
21
35
|
"#<lambda:#{object_id}>"
|
22
36
|
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
"#<lambda:#{object_id}>"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
refine Symbol do
|
44
|
+
def inspect
|
45
|
+
to_s
|
46
|
+
end
|
23
47
|
end
|
24
48
|
end
|
25
49
|
end
|
data/lib/rubic/interpreter.rb
CHANGED
@@ -1,35 +1,29 @@
|
|
1
|
-
require 'rubic/
|
1
|
+
require 'rubic/builtin'
|
2
2
|
require 'rubic/environment'
|
3
|
+
require 'rubic/parser'
|
3
4
|
|
4
5
|
module Rubic
|
5
6
|
class Interpreter
|
6
7
|
DEFAULT_GLOBAL_VARS = {
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
'=' => -> (a, b) { a == b },
|
14
|
-
'not' => -> (a) { !a },
|
15
|
-
'cons' => -> (a, b) { [a, b] },
|
16
|
-
'car' => -> (l) { l.first },
|
17
|
-
'cdr' => -> (l) { l.last },
|
18
|
-
'nil' => [],
|
19
|
-
'list' => -> (*args) { args.reverse.reduce([]) {|res, e| [e, res] } },
|
20
|
-
'null?' => -> (l) { l.is_a?(Array) ? l.empty? : false },
|
21
|
-
'pair?' => -> (l) { l.is_a?(Array) ? l.any? : false },
|
8
|
+
:not => -> (a) { !a },
|
9
|
+
:eq? => -> (a, b) { a.equal? b },
|
10
|
+
|
11
|
+
:true => true,
|
12
|
+
:false => false,
|
13
|
+
:nil => [],
|
22
14
|
}
|
23
15
|
|
24
16
|
def initialize
|
25
17
|
@parser = Parser.new
|
26
18
|
@global = Environment.new
|
27
19
|
DEFAULT_GLOBAL_VARS.each {|k, v| @global[k] = v }
|
20
|
+
builtins = Rubic::Builtin.constants.map {|c| Rubic::Builtin.const_get(c) }
|
21
|
+
builtins.each {|ext| @global.extend(ext) }
|
28
22
|
end
|
29
23
|
|
30
24
|
def evaluate(str)
|
31
|
-
|
32
|
-
|
25
|
+
seq = @parser.parse(str)
|
26
|
+
execute_sequence(seq, @global)
|
33
27
|
end
|
34
28
|
|
35
29
|
private
|
@@ -37,34 +31,37 @@ module Rubic
|
|
37
31
|
def execute(list_or_atom, env)
|
38
32
|
# Atom
|
39
33
|
case list_or_atom
|
40
|
-
when Float, Integer
|
34
|
+
when Float, Integer, String
|
41
35
|
atom = list_or_atom
|
42
|
-
when
|
36
|
+
when Symbol
|
43
37
|
atom = env[list_or_atom]
|
44
38
|
else
|
45
39
|
# fallthrough
|
46
40
|
end
|
47
|
-
return atom
|
41
|
+
return atom unless atom.nil?
|
48
42
|
|
49
43
|
list = list_or_atom
|
50
44
|
|
51
45
|
# Empty list
|
52
|
-
return
|
46
|
+
return [] if list.empty?
|
53
47
|
|
54
48
|
# Special Forms
|
55
49
|
case list.first
|
56
50
|
when :define
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
51
|
+
if list[1].is_a?(Array) # procedure definition
|
52
|
+
_, (name, *params), *body = list
|
53
|
+
env[name] = -> (*args) do
|
54
|
+
local = Environment.new(env)
|
55
|
+
local.bind(params, args)
|
56
|
+
execute_sequence(body, local)
|
57
|
+
end
|
58
|
+
return
|
59
|
+
else # variable definition
|
60
|
+
_, name, expr = list
|
61
|
+
env[name] = execute(expr, env)
|
62
|
+
return
|
66
63
|
end
|
67
|
-
|
64
|
+
|
68
65
|
when :cond
|
69
66
|
_, *clauses = list
|
70
67
|
clauses.each do |pred, expr|
|
@@ -73,21 +70,25 @@ module Rubic
|
|
73
70
|
end
|
74
71
|
end
|
75
72
|
return
|
73
|
+
|
76
74
|
when :if
|
77
75
|
_, pred, cons, alt = list
|
78
76
|
return execute(pred, env) ? execute(cons, env) : execute(alt, env)
|
77
|
+
|
79
78
|
when :and
|
80
79
|
_, *exprs = list
|
81
80
|
exprs.each do |expr|
|
82
81
|
return false unless execute(expr, env)
|
83
82
|
end
|
84
83
|
return true
|
84
|
+
|
85
85
|
when :or
|
86
86
|
_, *exprs = list
|
87
87
|
exprs.each do |expr|
|
88
88
|
return true if execute(expr, env)
|
89
89
|
end
|
90
90
|
return false
|
91
|
+
|
91
92
|
when :lambda
|
92
93
|
_, (*params), *body = list
|
93
94
|
return -> (*args) do
|
@@ -95,11 +96,17 @@ module Rubic
|
|
95
96
|
local.bind(params, args)
|
96
97
|
execute_sequence(body, local)
|
97
98
|
end
|
99
|
+
|
98
100
|
when :let
|
99
101
|
_, (*defs), *body = list
|
100
102
|
local = Environment.new(env)
|
101
103
|
defs.each {|name, expr| local[name] = execute(expr, env) }
|
102
104
|
return execute_sequence(body, local)
|
105
|
+
|
106
|
+
when :quote
|
107
|
+
_, expr = list
|
108
|
+
return quote(expr)
|
109
|
+
|
103
110
|
else
|
104
111
|
# fallthrough
|
105
112
|
end
|
@@ -109,6 +116,10 @@ module Rubic
|
|
109
116
|
unless op.respond_to? :call
|
110
117
|
raise Rubic::RuntimeError, "`#{op}' is not a procedure"
|
111
118
|
end
|
119
|
+
required = op.arity >= 0 ? op.arity : -op.arity - 1
|
120
|
+
if op.arity >= 0 ? required != args.size : required > args.size
|
121
|
+
raise Rubic::ArgumentError, "wrong number of arguments (#{args.size} for #{required})"
|
122
|
+
end
|
112
123
|
op.call(*args)
|
113
124
|
end
|
114
125
|
|
@@ -116,5 +127,13 @@ module Rubic
|
|
116
127
|
# execute expressions sequentially and returns the last result
|
117
128
|
seq.reduce(nil) {|res, expr| res = execute(expr, env) }
|
118
129
|
end
|
130
|
+
|
131
|
+
def quote(expr)
|
132
|
+
if expr.is_a? Array
|
133
|
+
expr.map {|e| quote(e) }.reverse.reduce([]) {|res, e| [e, res] }
|
134
|
+
else
|
135
|
+
expr
|
136
|
+
end
|
137
|
+
end
|
119
138
|
end
|
120
139
|
end
|
data/lib/rubic/parser.rb
CHANGED
@@ -12,7 +12,7 @@ module Rubic
|
|
12
12
|
|
13
13
|
class Parser < Racc::Parser
|
14
14
|
|
15
|
-
module_eval(<<'...end parser.y/module_eval...', 'parser.y',
|
15
|
+
module_eval(<<'...end parser.y/module_eval...', 'parser.y', 134)
|
16
16
|
EOT = [false, nil] # end of token
|
17
17
|
SYM_CHARS = Regexp.escape("+-*/<>=?")
|
18
18
|
|
@@ -28,7 +28,7 @@ def next_token
|
|
28
28
|
case
|
29
29
|
when @s.scan(/[0-9]+(\.[0-9]+)?/)
|
30
30
|
[:NUMBER, @s[0].include?('.') ? @s[0].to_f : @s[0].to_i]
|
31
|
-
when @s.scan(/[
|
31
|
+
when @s.scan(/[()']/)
|
32
32
|
[@s[0], nil]
|
33
33
|
when @s.scan(/[A-Za-z_#{SYM_CHARS}][A-Za-z0-9_#{SYM_CHARS}]*/o)
|
34
34
|
case @s[0] # keyword check
|
@@ -48,9 +48,13 @@ def next_token
|
|
48
48
|
[:KW_LAMBDA, nil]
|
49
49
|
when 'let'
|
50
50
|
[:KW_LET, nil]
|
51
|
+
when 'quote'
|
52
|
+
[:KW_QUOTE, nil]
|
51
53
|
else
|
52
|
-
[:IDENT, @s[0]]
|
54
|
+
[:IDENT, @s[0].to_sym]
|
53
55
|
end
|
56
|
+
when @s.scan(/"([^"]*)"/)
|
57
|
+
[:STRING, @s[1]]
|
54
58
|
else
|
55
59
|
raise Rubic::ParseError, "unknown character #{@s.getch}"
|
56
60
|
end
|
@@ -64,108 +68,141 @@ end
|
|
64
68
|
##### State transition tables begin ###
|
65
69
|
|
66
70
|
racc_action_table = [
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
29,
|
74
|
-
4,
|
75
|
-
|
76
|
-
3,
|
77
|
-
|
71
|
+
3, 64, 67, 60, 4, 5, 6, 3, 37, 75,
|
72
|
+
47, 4, 5, 6, 15, 34, 63, 55, 62, 33,
|
73
|
+
65, 15, 3, 17, 20, 18, 4, 5, 6, 21,
|
74
|
+
22, 66, 23, 24, 25, 26, 15, 3, 46, 44,
|
75
|
+
3, 4, 5, 6, 4, 5, 6, 61, 40, 60,
|
76
|
+
70, 15, 3, 39, 15, 3, 4, 5, 6, 4,
|
77
|
+
5, 6, 37, 54, 29, 16, 15, 3, 76, 15,
|
78
|
+
3, 4, 5, 6, 4, 5, 6, nil, nil, nil,
|
79
|
+
nil, 15, nil, 3, 15, 73, nil, 4, 5, 6,
|
80
|
+
3, nil, 72, nil, 4, 5, 6, 15, nil, nil,
|
81
|
+
nil, 3, nil, nil, 15, 4, 5, 6, 3, nil,
|
82
|
+
nil, nil, 4, 5, 6, 15, nil, nil, nil, 3,
|
83
|
+
nil, nil, 15, 4, 5, 6, 3, nil, nil, nil,
|
84
|
+
4, 5, 6, 15, nil, nil, nil, 3, nil, 42,
|
85
|
+
15, 4, 5, 6, 3, nil, 43, nil, 4, 5,
|
86
|
+
6, 15, nil, nil, nil, 3, nil, nil, 15, 4,
|
87
|
+
5, 6, 3, nil, nil, nil, 4, 5, 6, 15,
|
88
|
+
nil, nil, nil, 3, nil, nil, 15, 4, 5, 6,
|
89
|
+
3, nil, nil, nil, 4, 5, 6, 15, nil, nil,
|
90
|
+
nil, 3, nil, nil, 15, 4, 5, 6, 3, nil,
|
91
|
+
nil, nil, 4, 5, 6, 15, nil, nil, nil, 3,
|
92
|
+
nil, nil, 15, 4, 5, 6, nil, nil, 50, nil,
|
93
|
+
nil, nil, nil, 15 ]
|
78
94
|
|
79
95
|
racc_action_check = [
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
96
|
+
0, 56, 59, 56, 0, 0, 0, 71, 35, 71,
|
97
|
+
35, 71, 71, 71, 0, 21, 53, 45, 53, 21,
|
98
|
+
57, 71, 3, 3, 3, 3, 3, 3, 3, 3,
|
99
|
+
3, 58, 3, 3, 3, 3, 3, 14, 34, 32,
|
100
|
+
15, 14, 14, 14, 15, 15, 15, 52, 25, 52,
|
101
|
+
63, 14, 70, 24, 15, 17, 70, 70, 70, 17,
|
102
|
+
17, 17, 22, 41, 16, 1, 70, 18, 74, 17,
|
103
|
+
19, 18, 18, 18, 19, 19, 19, nil, nil, nil,
|
104
|
+
nil, 18, nil, 69, 19, 69, nil, 69, 69, 69,
|
105
|
+
68, nil, 68, nil, 68, 68, 68, 69, nil, nil,
|
106
|
+
nil, 23, nil, nil, 68, 23, 23, 23, 64, nil,
|
107
|
+
nil, nil, 64, 64, 64, 23, nil, nil, nil, 62,
|
108
|
+
nil, nil, 64, 62, 62, 62, 26, nil, nil, nil,
|
109
|
+
26, 26, 26, 62, nil, nil, nil, 30, nil, 30,
|
110
|
+
26, 30, 30, 30, 31, nil, 31, nil, 31, 31,
|
111
|
+
31, 30, nil, nil, nil, 61, nil, nil, 31, 61,
|
112
|
+
61, 61, 33, nil, nil, nil, 33, 33, 33, 61,
|
113
|
+
nil, nil, nil, 51, nil, nil, 33, 51, 51, 51,
|
114
|
+
50, nil, nil, nil, 50, 50, 50, 51, nil, nil,
|
115
|
+
nil, 49, nil, nil, 50, 49, 49, 49, 38, nil,
|
116
|
+
nil, nil, 38, 38, 38, 49, nil, nil, nil, 37,
|
117
|
+
nil, nil, 38, 37, 37, 37, nil, nil, 37, nil,
|
118
|
+
nil, nil, nil, 37 ]
|
91
119
|
|
92
120
|
racc_action_pointer = [
|
93
|
-
|
94
|
-
nil,
|
95
|
-
nil,
|
96
|
-
|
97
|
-
nil,
|
98
|
-
|
99
|
-
|
121
|
+
-2, 65, nil, 20, nil, nil, nil, nil, nil, nil,
|
122
|
+
nil, nil, nil, nil, 35, 38, 64, 53, 65, 68,
|
123
|
+
nil, 13, 60, 99, 51, 46, 124, nil, nil, nil,
|
124
|
+
135, 142, 35, 160, 32, 6, nil, 207, 196, nil,
|
125
|
+
nil, 59, nil, nil, nil, 13, nil, nil, nil, 189,
|
126
|
+
178, 171, 43, 14, nil, nil, -3, 16, 27, -2,
|
127
|
+
nil, 153, 117, 44, 106, nil, nil, nil, 88, 81,
|
128
|
+
50, 5, nil, nil, 64, nil, nil ]
|
100
129
|
|
101
130
|
racc_action_default = [
|
102
|
-
-
|
103
|
-
-
|
104
|
-
|
105
|
-
-
|
106
|
-
-
|
107
|
-
-
|
108
|
-
-
|
131
|
+
-17, -35, -1, -35, -6, -7, -8, -9, -10, -11,
|
132
|
+
-12, -13, -14, -15, -18, -35, -35, -35, -35, -17,
|
133
|
+
-5, -35, -35, -35, -35, -35, -35, -16, -34, 77,
|
134
|
+
-35, -35, -35, -35, -35, -35, -24, -35, -35, -21,
|
135
|
+
-31, -35, -2, -3, -4, -35, -21, -23, -25, -35,
|
136
|
+
-35, -35, -35, -35, -33, -19, -35, -35, -35, -35,
|
137
|
+
-22, -35, -35, -35, -35, -26, -27, -28, -35, -35,
|
138
|
+
-35, -35, -29, -30, -35, -20, -32 ]
|
109
139
|
|
110
140
|
racc_goto_table = [
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
nil,
|
116
|
-
|
117
|
-
|
141
|
+
19, 36, 2, 52, 1, 30, 31, 35, 53, nil,
|
142
|
+
56, 27, 28, nil, 48, nil, nil, nil, nil, nil,
|
143
|
+
38, 32, nil, 41, nil, nil, nil, 27, 27, nil,
|
144
|
+
45, nil, nil, nil, 49, 51, nil, nil, nil, nil,
|
145
|
+
nil, nil, nil, nil, nil, nil, 57, 58, 59, 68,
|
146
|
+
69, nil, 71, nil, nil, nil, nil, nil, nil, nil,
|
147
|
+
nil, nil, nil, nil, nil, 27, 27, 74, 27 ]
|
118
148
|
|
119
149
|
racc_goto_check = [
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
nil,
|
125
|
-
|
126
|
-
|
150
|
+
3, 13, 2, 11, 1, 4, 4, 12, 14, nil,
|
151
|
+
11, 3, 3, nil, 13, nil, nil, nil, nil, nil,
|
152
|
+
3, 2, nil, 3, nil, nil, nil, 3, 3, nil,
|
153
|
+
3, nil, nil, nil, 3, 3, nil, nil, nil, nil,
|
154
|
+
nil, nil, nil, nil, nil, nil, 3, 3, 3, 4,
|
155
|
+
4, nil, 4, nil, nil, nil, nil, nil, nil, nil,
|
156
|
+
nil, nil, nil, nil, nil, 3, 3, 3, 3 ]
|
127
157
|
|
128
158
|
racc_goto_pointer = [
|
129
|
-
nil,
|
130
|
-
|
159
|
+
nil, 4, 2, -3, -12, nil, nil, nil, nil, nil,
|
160
|
+
nil, -36, -15, -21, -32 ]
|
131
161
|
|
132
162
|
racc_goto_default = [
|
133
|
-
nil,
|
134
|
-
nil, nil, nil ]
|
163
|
+
nil, nil, nil, 13, 14, 7, 8, 9, 10, 11,
|
164
|
+
12, nil, nil, nil, nil ]
|
135
165
|
|
136
166
|
racc_reduce_table = [
|
137
167
|
0, 0, :racc_error,
|
138
|
-
|
139
|
-
4,
|
140
|
-
4,
|
141
|
-
|
142
|
-
|
143
|
-
1,
|
144
|
-
1,
|
145
|
-
1,
|
146
|
-
1,
|
147
|
-
1,
|
148
|
-
1,
|
149
|
-
1,
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
168
|
+
1, 18, :_reduce_none,
|
169
|
+
4, 20, :_reduce_2,
|
170
|
+
4, 20, :_reduce_3,
|
171
|
+
4, 20, :_reduce_4,
|
172
|
+
2, 20, :_reduce_5,
|
173
|
+
1, 20, :_reduce_none,
|
174
|
+
1, 20, :_reduce_none,
|
175
|
+
1, 20, :_reduce_none,
|
176
|
+
1, 20, :_reduce_none,
|
177
|
+
1, 20, :_reduce_none,
|
178
|
+
1, 20, :_reduce_none,
|
179
|
+
1, 20, :_reduce_none,
|
180
|
+
1, 20, :_reduce_none,
|
181
|
+
1, 20, :_reduce_none,
|
182
|
+
1, 21, :_reduce_15,
|
183
|
+
2, 21, :_reduce_16,
|
184
|
+
0, 19, :_reduce_17,
|
185
|
+
1, 19, :_reduce_none,
|
186
|
+
5, 22, :_reduce_19,
|
187
|
+
8, 22, :_reduce_20,
|
188
|
+
0, 28, :_reduce_21,
|
189
|
+
2, 28, :_reduce_22,
|
190
|
+
4, 23, :_reduce_23,
|
191
|
+
1, 29, :_reduce_24,
|
192
|
+
2, 29, :_reduce_25,
|
193
|
+
4, 30, :_reduce_26,
|
194
|
+
4, 30, :_reduce_27,
|
195
|
+
6, 24, :_reduce_28,
|
196
|
+
7, 25, :_reduce_29,
|
197
|
+
7, 26, :_reduce_30,
|
198
|
+
0, 31, :_reduce_31,
|
199
|
+
5, 31, :_reduce_32,
|
200
|
+
4, 27, :_reduce_33,
|
201
|
+
2, 27, :_reduce_34 ]
|
202
|
+
|
203
|
+
racc_reduce_n = 35
|
204
|
+
|
205
|
+
racc_shift_n = 77
|
169
206
|
|
170
207
|
racc_token_table = {
|
171
208
|
false => 0,
|
@@ -176,14 +213,17 @@ racc_token_table = {
|
|
176
213
|
:KW_OR => 5,
|
177
214
|
:IDENT => 6,
|
178
215
|
:NUMBER => 7,
|
179
|
-
:
|
180
|
-
:
|
181
|
-
:
|
182
|
-
:
|
183
|
-
:
|
184
|
-
:
|
185
|
-
|
186
|
-
|
216
|
+
:STRING => 8,
|
217
|
+
:KW_DEFINE => 9,
|
218
|
+
:KW_COND => 10,
|
219
|
+
:KW_ELSE => 11,
|
220
|
+
:KW_IF => 12,
|
221
|
+
:KW_LAMBDA => 13,
|
222
|
+
:KW_LET => 14,
|
223
|
+
:KW_QUOTE => 15,
|
224
|
+
"'" => 16 }
|
225
|
+
|
226
|
+
racc_nt_base = 17
|
187
227
|
|
188
228
|
racc_use_result_var = false
|
189
229
|
|
@@ -212,21 +252,26 @@ Racc_token_to_s_table = [
|
|
212
252
|
"KW_OR",
|
213
253
|
"IDENT",
|
214
254
|
"NUMBER",
|
255
|
+
"STRING",
|
215
256
|
"KW_DEFINE",
|
216
257
|
"KW_COND",
|
217
258
|
"KW_ELSE",
|
218
259
|
"KW_IF",
|
219
260
|
"KW_LAMBDA",
|
220
261
|
"KW_LET",
|
262
|
+
"KW_QUOTE",
|
263
|
+
"\"'\"",
|
221
264
|
"$start",
|
265
|
+
"program",
|
266
|
+
"opt_seq",
|
222
267
|
"expr",
|
223
268
|
"seq",
|
224
269
|
"define",
|
225
|
-
"define_proc",
|
226
270
|
"cond",
|
227
271
|
"if",
|
228
272
|
"lambda",
|
229
273
|
"let",
|
274
|
+
"quote",
|
230
275
|
"params",
|
231
276
|
"clauses",
|
232
277
|
"clause",
|
@@ -238,30 +283,35 @@ Racc_debug_parser = false
|
|
238
283
|
|
239
284
|
# reduce 0 omitted
|
240
285
|
|
241
|
-
|
242
|
-
|
286
|
+
# reduce 1 omitted
|
287
|
+
|
288
|
+
module_eval(<<'.,.,', 'parser.y', 8)
|
289
|
+
def _reduce_2(val, _values)
|
243
290
|
[:and, *val[2]]
|
244
291
|
|
245
292
|
end
|
246
293
|
.,.,
|
247
294
|
|
248
|
-
module_eval(<<'.,.,', 'parser.y',
|
249
|
-
def
|
295
|
+
module_eval(<<'.,.,', 'parser.y', 12)
|
296
|
+
def _reduce_3(val, _values)
|
250
297
|
[:or, *val[2]]
|
251
298
|
|
252
299
|
end
|
253
300
|
.,.,
|
254
301
|
|
255
|
-
module_eval(<<'.,.,', 'parser.y',
|
256
|
-
def
|
302
|
+
module_eval(<<'.,.,', 'parser.y', 16)
|
303
|
+
def _reduce_4(val, _values)
|
257
304
|
[val[1], *val[2]]
|
258
305
|
|
259
306
|
end
|
260
307
|
.,.,
|
261
308
|
|
262
|
-
|
263
|
-
|
264
|
-
|
309
|
+
module_eval(<<'.,.,', 'parser.y', 20)
|
310
|
+
def _reduce_5(val, _values)
|
311
|
+
[]
|
312
|
+
|
313
|
+
end
|
314
|
+
.,.,
|
265
315
|
|
266
316
|
# reduce 6 omitted
|
267
317
|
|
@@ -275,118 +325,147 @@ module_eval(<<'.,.,', 'parser.y', 14)
|
|
275
325
|
|
276
326
|
# reduce 11 omitted
|
277
327
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
328
|
+
# reduce 12 omitted
|
329
|
+
|
330
|
+
# reduce 13 omitted
|
331
|
+
|
332
|
+
# reduce 14 omitted
|
333
|
+
|
334
|
+
module_eval(<<'.,.,', 'parser.y', 34)
|
335
|
+
def _reduce_15(val, _values)
|
336
|
+
[val[0]]
|
337
|
+
|
282
338
|
end
|
283
339
|
.,.,
|
284
340
|
|
285
|
-
module_eval(<<'.,.,', 'parser.y',
|
286
|
-
def
|
287
|
-
|
288
|
-
|
341
|
+
module_eval(<<'.,.,', 'parser.y', 38)
|
342
|
+
def _reduce_16(val, _values)
|
343
|
+
val[0].push(val[1])
|
344
|
+
|
345
|
+
end
|
346
|
+
.,.,
|
347
|
+
|
348
|
+
module_eval(<<'.,.,', 'parser.y', 43)
|
349
|
+
def _reduce_17(val, _values)
|
350
|
+
[]
|
351
|
+
|
289
352
|
end
|
290
353
|
.,.,
|
291
354
|
|
292
|
-
|
293
|
-
|
355
|
+
# reduce 18 omitted
|
356
|
+
|
357
|
+
module_eval(<<'.,.,', 'parser.y', 50)
|
358
|
+
def _reduce_19(val, _values)
|
294
359
|
[:define, val[2], val[3]]
|
295
360
|
|
296
361
|
end
|
297
362
|
.,.,
|
298
363
|
|
299
|
-
module_eval(<<'.,.,', 'parser.y',
|
300
|
-
def
|
301
|
-
|
302
|
-
|
364
|
+
module_eval(<<'.,.,', 'parser.y', 54)
|
365
|
+
def _reduce_20(val, _values)
|
366
|
+
[:define, [val[3], *val[4]], *val[6]]
|
367
|
+
|
303
368
|
end
|
304
369
|
.,.,
|
305
370
|
|
306
|
-
module_eval(<<'.,.,', 'parser.y',
|
307
|
-
def
|
371
|
+
module_eval(<<'.,.,', 'parser.y', 59)
|
372
|
+
def _reduce_21(val, _values)
|
308
373
|
[]
|
309
374
|
|
310
375
|
end
|
311
376
|
.,.,
|
312
377
|
|
313
|
-
module_eval(<<'.,.,', 'parser.y',
|
314
|
-
def
|
378
|
+
module_eval(<<'.,.,', 'parser.y', 63)
|
379
|
+
def _reduce_22(val, _values)
|
315
380
|
val[0].push(val[1])
|
316
381
|
|
317
382
|
end
|
318
383
|
.,.,
|
319
384
|
|
320
|
-
module_eval(<<'.,.,', 'parser.y',
|
321
|
-
def
|
385
|
+
module_eval(<<'.,.,', 'parser.y', 69)
|
386
|
+
def _reduce_23(val, _values)
|
322
387
|
[:cond, *val[2]]
|
323
388
|
|
324
389
|
end
|
325
390
|
.,.,
|
326
391
|
|
327
|
-
module_eval(<<'.,.,', 'parser.y',
|
328
|
-
def
|
392
|
+
module_eval(<<'.,.,', 'parser.y', 74)
|
393
|
+
def _reduce_24(val, _values)
|
329
394
|
[val[0]]
|
330
395
|
|
331
396
|
end
|
332
397
|
.,.,
|
333
398
|
|
334
|
-
module_eval(<<'.,.,', 'parser.y',
|
335
|
-
def
|
399
|
+
module_eval(<<'.,.,', 'parser.y', 78)
|
400
|
+
def _reduce_25(val, _values)
|
336
401
|
val[0].push(val[1])
|
337
402
|
|
338
403
|
end
|
339
404
|
.,.,
|
340
405
|
|
341
|
-
module_eval(<<'.,.,', 'parser.y',
|
342
|
-
def
|
406
|
+
module_eval(<<'.,.,', 'parser.y', 83)
|
407
|
+
def _reduce_26(val, _values)
|
343
408
|
[val[1], val[2]]
|
344
409
|
|
345
410
|
end
|
346
411
|
.,.,
|
347
412
|
|
348
|
-
module_eval(<<'.,.,', 'parser.y',
|
349
|
-
def
|
413
|
+
module_eval(<<'.,.,', 'parser.y', 87)
|
414
|
+
def _reduce_27(val, _values)
|
350
415
|
[:else, val[2]]
|
351
416
|
|
352
417
|
end
|
353
418
|
.,.,
|
354
419
|
|
355
|
-
module_eval(<<'.,.,', 'parser.y',
|
356
|
-
def
|
420
|
+
module_eval(<<'.,.,', 'parser.y', 93)
|
421
|
+
def _reduce_28(val, _values)
|
357
422
|
[:if, val[2], val[3], val[4]]
|
358
423
|
|
359
424
|
end
|
360
425
|
.,.,
|
361
426
|
|
362
|
-
module_eval(<<'.,.,', 'parser.y',
|
363
|
-
def
|
427
|
+
module_eval(<<'.,.,', 'parser.y', 99)
|
428
|
+
def _reduce_29(val, _values)
|
364
429
|
[:lambda, val[3], *val[5]]
|
365
430
|
|
366
431
|
end
|
367
432
|
.,.,
|
368
433
|
|
369
|
-
module_eval(<<'.,.,', 'parser.y',
|
370
|
-
def
|
434
|
+
module_eval(<<'.,.,', 'parser.y', 105)
|
435
|
+
def _reduce_30(val, _values)
|
371
436
|
[:let, val[3], *val[5]]
|
372
437
|
|
373
438
|
end
|
374
439
|
.,.,
|
375
440
|
|
376
|
-
module_eval(<<'.,.,', 'parser.y',
|
377
|
-
def
|
441
|
+
module_eval(<<'.,.,', 'parser.y', 109)
|
442
|
+
def _reduce_31(val, _values)
|
378
443
|
[]
|
379
444
|
|
380
445
|
end
|
381
446
|
.,.,
|
382
447
|
|
383
|
-
module_eval(<<'.,.,', 'parser.y',
|
384
|
-
def
|
448
|
+
module_eval(<<'.,.,', 'parser.y', 113)
|
449
|
+
def _reduce_32(val, _values)
|
385
450
|
val[0].push([val[2], val[3]])
|
386
451
|
|
387
452
|
end
|
388
453
|
.,.,
|
389
454
|
|
455
|
+
module_eval(<<'.,.,', 'parser.y', 119)
|
456
|
+
def _reduce_33(val, _values)
|
457
|
+
[:quote, val[2]]
|
458
|
+
|
459
|
+
end
|
460
|
+
.,.,
|
461
|
+
|
462
|
+
module_eval(<<'.,.,', 'parser.y', 123)
|
463
|
+
def _reduce_34(val, _values)
|
464
|
+
[:quote, val[1]]
|
465
|
+
|
466
|
+
end
|
467
|
+
.,.,
|
468
|
+
|
390
469
|
def _reduce_none(val, _values)
|
391
470
|
val[0]
|
392
471
|
end
|
data/lib/rubic/parser.y
CHANGED
@@ -2,6 +2,8 @@ class Parser
|
|
2
2
|
options no_result_var
|
3
3
|
|
4
4
|
rule
|
5
|
+
program : opt_seq
|
6
|
+
|
5
7
|
expr : '(' KW_AND seq ')'
|
6
8
|
{
|
7
9
|
[:and, *val[2]]
|
@@ -10,39 +12,48 @@ rule
|
|
10
12
|
{
|
11
13
|
[:or, *val[2]]
|
12
14
|
}
|
13
|
-
| '(' expr
|
15
|
+
| '(' expr opt_seq ')'
|
14
16
|
{
|
15
17
|
[val[1], *val[2]]
|
16
18
|
}
|
19
|
+
| '(' ')'
|
20
|
+
{
|
21
|
+
[]
|
22
|
+
}
|
17
23
|
| IDENT
|
18
24
|
| NUMBER
|
25
|
+
| STRING
|
19
26
|
| define
|
20
|
-
| define_proc
|
21
27
|
| cond
|
22
28
|
| if
|
23
29
|
| lambda
|
24
30
|
| let
|
31
|
+
| quote
|
25
32
|
|
26
|
-
seq
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
33
|
+
seq : expr
|
34
|
+
{
|
35
|
+
[val[0]]
|
36
|
+
}
|
37
|
+
| seq expr
|
38
|
+
{
|
39
|
+
val[0].push(val[1])
|
40
|
+
}
|
41
|
+
|
42
|
+
opt_seq : /* empty */
|
43
|
+
{
|
44
|
+
[]
|
45
|
+
}
|
46
|
+
| seq
|
34
47
|
|
35
48
|
/* Define statement */
|
36
49
|
define : '(' KW_DEFINE IDENT expr ')'
|
37
50
|
{
|
38
51
|
[:define, val[2], val[3]]
|
39
52
|
}
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
[:define_proc, [val[3], *val[4]], *val[6]]
|
45
|
-
}
|
53
|
+
| '(' KW_DEFINE '(' IDENT params ')' seq ')'
|
54
|
+
{
|
55
|
+
[:define, [val[3], *val[4]], *val[6]]
|
56
|
+
}
|
46
57
|
|
47
58
|
params : /* empty */
|
48
59
|
{
|
@@ -102,6 +113,16 @@ rule
|
|
102
113
|
{
|
103
114
|
val[0].push([val[2], val[3]])
|
104
115
|
}
|
116
|
+
|
117
|
+
/* quote expression */
|
118
|
+
quote : '(' KW_QUOTE expr ')'
|
119
|
+
{
|
120
|
+
[:quote, val[2]]
|
121
|
+
}
|
122
|
+
| '\'' expr
|
123
|
+
{
|
124
|
+
[:quote, val[1]]
|
125
|
+
}
|
105
126
|
end
|
106
127
|
|
107
128
|
---- header
|
@@ -125,7 +146,7 @@ def next_token
|
|
125
146
|
case
|
126
147
|
when @s.scan(/[0-9]+(\.[0-9]+)?/)
|
127
148
|
[:NUMBER, @s[0].include?('.') ? @s[0].to_f : @s[0].to_i]
|
128
|
-
when @s.scan(/[
|
149
|
+
when @s.scan(/[()']/)
|
129
150
|
[@s[0], nil]
|
130
151
|
when @s.scan(/[A-Za-z_#{SYM_CHARS}][A-Za-z0-9_#{SYM_CHARS}]*/o)
|
131
152
|
case @s[0] # keyword check
|
@@ -145,9 +166,13 @@ def next_token
|
|
145
166
|
[:KW_LAMBDA, nil]
|
146
167
|
when 'let'
|
147
168
|
[:KW_LET, nil]
|
169
|
+
when 'quote'
|
170
|
+
[:KW_QUOTE, nil]
|
148
171
|
else
|
149
|
-
[:IDENT, @s[0]]
|
172
|
+
[:IDENT, @s[0].to_sym]
|
150
173
|
end
|
174
|
+
when @s.scan(/"([^"]*)"/)
|
175
|
+
[:STRING, @s[1]]
|
151
176
|
else
|
152
177
|
raise Rubic::ParseError, "unknown character #{@s.getch}"
|
153
178
|
end
|
data/lib/rubic/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- notozeki
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -112,6 +112,10 @@ files:
|
|
112
112
|
- bin/rubic
|
113
113
|
- bin/setup
|
114
114
|
- lib/rubic.rb
|
115
|
+
- lib/rubic/builtin.rb
|
116
|
+
- lib/rubic/builtin/list.rb
|
117
|
+
- lib/rubic/builtin/number.rb
|
118
|
+
- lib/rubic/builtin/output.rb
|
115
119
|
- lib/rubic/environment.rb
|
116
120
|
- lib/rubic/inspector.rb
|
117
121
|
- lib/rubic/interpreter.rb
|