sardonyx 0.1.5
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 +7 -0
- data/bin/sdx +32 -0
- data/lib/sdx/compiler/compiler.rb +183 -0
- data/lib/sdx/compiler/parser.rb +522 -0
- data/lib/sdx/vm/datatypes.rb +410 -0
- data/lib/sdx/vm/scope.rb +60 -0
- data/lib/sdx/vm/variables.rb +19 -0
- data/lib/sdx/vm/vm.rb +385 -0
- metadata +51 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 134db5d432fc5be113fff903e155f16cfd8d756b3ee89846cb542fe282d831d0
|
|
4
|
+
data.tar.gz: a89c2707cb7a86c09f6ac5afe265bff9913d55c87346f7ffc75c274c0436b042
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ae6c5e8daab94393ae813c3980950ad3cf22e075820f6cdbef46cab336283098bf2aa9d80008185cba53493ea78297fec3b5c0171124082fa50f38243f83b9c7
|
|
7
|
+
data.tar.gz: 2279b27b460bc419e3992d78548e46503eec909695f813e0a6072dcc777ecfc35da19e8ab614de60f0e0356a22711ad391753bafa732b848745fe04cd35db64b
|
data/bin/sdx
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
require "sdx/compiler/parser"
|
|
3
|
+
require "sdx/compiler/compiler"
|
|
4
|
+
require "sdx/vm/vm"
|
|
5
|
+
require "stringio"
|
|
6
|
+
|
|
7
|
+
if ARGV.size == 1
|
|
8
|
+
path = [(File.expand_path File.dirname ARGV[0]), *(ENV.fetch("SDX_PATH", "").split ":")]
|
|
9
|
+
code = File.read ARGV[0]
|
|
10
|
+
lexed = Parser::Lexer.lex code
|
|
11
|
+
ast = Parser::Parser.parse lexed, path
|
|
12
|
+
bc = Compiler::Compiler.compile ast
|
|
13
|
+
vm = VM.new StringIO.new bc
|
|
14
|
+
vm.interpret
|
|
15
|
+
else
|
|
16
|
+
path = [(File.expand_path Dir.pwd), *(ENV.fetch("SDX_PATH", "").split ":")]
|
|
17
|
+
vm = VM.new StringIO.new ""
|
|
18
|
+
puts "Sardonyx v 0.0.1"
|
|
19
|
+
def exit(_) end
|
|
20
|
+
loop do
|
|
21
|
+
print "> "
|
|
22
|
+
code = gets
|
|
23
|
+
lexed = Parser::Lexer.lex code
|
|
24
|
+
ast = Parser::Parser.parse lexed, path
|
|
25
|
+
bc = Compiler::Compiler.compile ast
|
|
26
|
+
vm.bc_io = StringIO.new bc
|
|
27
|
+
vm.byte_pos = 0
|
|
28
|
+
vm.interpret
|
|
29
|
+
val = vm.stack[-1]
|
|
30
|
+
puts stringify val
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
module Compiler
|
|
2
|
+
class Compiler
|
|
3
|
+
def self.compile(ast)
|
|
4
|
+
bc = ""
|
|
5
|
+
ast.each do |line|
|
|
6
|
+
bc += self.encode_node line
|
|
7
|
+
end
|
|
8
|
+
bc + "\x16"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.encode_block(node)
|
|
12
|
+
bc = ""
|
|
13
|
+
node.children.each do |child|
|
|
14
|
+
bc += self.encode_node child
|
|
15
|
+
end
|
|
16
|
+
bc
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.encode_node(node)
|
|
20
|
+
bc = ""
|
|
21
|
+
case node.nodetype
|
|
22
|
+
when :assign
|
|
23
|
+
name = node.children[0]
|
|
24
|
+
val = node.children[1]
|
|
25
|
+
case node.value
|
|
26
|
+
when "=" # could also be +=, -=, etc.
|
|
27
|
+
bc += "#{self.encode_node val}\x01\x10#{name}\x18"
|
|
28
|
+
else
|
|
29
|
+
nil
|
|
30
|
+
end
|
|
31
|
+
when :number
|
|
32
|
+
bc += "\x21\x13#{node.value}\x18"
|
|
33
|
+
when :float
|
|
34
|
+
bc += "\x21\x15#{node.value}\x18"
|
|
35
|
+
when :string
|
|
36
|
+
bc += "\x21\x14#{node.value}\x18"
|
|
37
|
+
when :call
|
|
38
|
+
node.children.each do |item|
|
|
39
|
+
bc += self.encode_node item
|
|
40
|
+
end
|
|
41
|
+
bc += self.encode_node node.value
|
|
42
|
+
bc += "\x02"
|
|
43
|
+
when :new
|
|
44
|
+
node.children.each do |item|
|
|
45
|
+
bc += self.encode_node item
|
|
46
|
+
end
|
|
47
|
+
bc += self.encode_node node.value
|
|
48
|
+
bc += "\x31"
|
|
49
|
+
when :op
|
|
50
|
+
node.children.each do |child|
|
|
51
|
+
bc += self.encode_node child
|
|
52
|
+
end
|
|
53
|
+
case node.value
|
|
54
|
+
when "+"
|
|
55
|
+
bc += "\x23"
|
|
56
|
+
when "-"
|
|
57
|
+
bc += "\x24"
|
|
58
|
+
when "*"
|
|
59
|
+
bc += "\x25"
|
|
60
|
+
when "/"
|
|
61
|
+
bc += "\x26"
|
|
62
|
+
when "%"
|
|
63
|
+
bc += "\x27"
|
|
64
|
+
when "^"
|
|
65
|
+
bc += "\x28"
|
|
66
|
+
end
|
|
67
|
+
when :if
|
|
68
|
+
bc += self.encode_node node.value
|
|
69
|
+
case node.children[0].nodetype
|
|
70
|
+
when :block
|
|
71
|
+
i = self.encode_block node.children[0]
|
|
72
|
+
else
|
|
73
|
+
i = self.encode_node node.children[0]
|
|
74
|
+
end
|
|
75
|
+
e = nil
|
|
76
|
+
if node.children[1]
|
|
77
|
+
case node.children[1].nodetype
|
|
78
|
+
when :block
|
|
79
|
+
e = self.encode_block node.children[1]
|
|
80
|
+
else
|
|
81
|
+
e = self.encode_node node.children[1]
|
|
82
|
+
end
|
|
83
|
+
i += "\x2a#{e.size}\x18"
|
|
84
|
+
end
|
|
85
|
+
bc += "\x29#{i.size}\x18" + i
|
|
86
|
+
if e
|
|
87
|
+
bc += e
|
|
88
|
+
end
|
|
89
|
+
when :name
|
|
90
|
+
bc += "\x20#{node.value}\x18"
|
|
91
|
+
when :nil
|
|
92
|
+
bc += "\x21\x2f"
|
|
93
|
+
when :while
|
|
94
|
+
e = self.encode_node node.value
|
|
95
|
+
bc += e
|
|
96
|
+
total = e.size
|
|
97
|
+
b = nil
|
|
98
|
+
case node.children[0].nodetype
|
|
99
|
+
when :block
|
|
100
|
+
b = self.encode_block node.children[0]
|
|
101
|
+
else
|
|
102
|
+
b = self.encode_node node.children[0]
|
|
103
|
+
end
|
|
104
|
+
add = ""
|
|
105
|
+
#bc += "\x2b#{b.size}\x18"
|
|
106
|
+
total += "\x29#{b.size}\x18".size
|
|
107
|
+
add += b
|
|
108
|
+
total += b.size
|
|
109
|
+
total += "\x2a-#{total}\x18".size
|
|
110
|
+
add += "\x2a-#{total}\x18"
|
|
111
|
+
total -= "\x29#{b.size}\x18".size
|
|
112
|
+
total -= e.size
|
|
113
|
+
add = "\x2b#{total}\x18" + add
|
|
114
|
+
bc += add
|
|
115
|
+
when :for
|
|
116
|
+
bc += self.encode_node node.value
|
|
117
|
+
sym = (0...8).map { (65 + rand(26)).chr }.join
|
|
118
|
+
bc += "\x01\x10__#{sym}\x18"
|
|
119
|
+
e = "\x20__#{sym}\x18\x2e"
|
|
120
|
+
if node.children[0]
|
|
121
|
+
e += "\x01\x10#{node.children[0]}\x18"
|
|
122
|
+
else
|
|
123
|
+
e += "\x01\x10_\x18"
|
|
124
|
+
end
|
|
125
|
+
bc += e
|
|
126
|
+
total = e.size
|
|
127
|
+
b = nil
|
|
128
|
+
case node.children[1].nodetype
|
|
129
|
+
when :block
|
|
130
|
+
b = self.encode_block node.children[1]
|
|
131
|
+
else
|
|
132
|
+
b = self.encode_node node.children[1]
|
|
133
|
+
end
|
|
134
|
+
add = ""
|
|
135
|
+
total += "\x29#{b.size}\x18".size
|
|
136
|
+
add += b
|
|
137
|
+
total += b.size
|
|
138
|
+
total += "\x2a-#{total}\x18".size
|
|
139
|
+
add += "\x2a-#{total}\x18"
|
|
140
|
+
total -= "\x29#{b.size}\x18".size
|
|
141
|
+
total -= e.size
|
|
142
|
+
add = "\x2b#{total}\x18" + add
|
|
143
|
+
bc += add
|
|
144
|
+
when :fn
|
|
145
|
+
name = node.value
|
|
146
|
+
args, body = node.children
|
|
147
|
+
if body.nodetype == :block
|
|
148
|
+
body = self.encode_block body
|
|
149
|
+
else
|
|
150
|
+
body = self.encode_node body
|
|
151
|
+
end
|
|
152
|
+
body += "\x16"
|
|
153
|
+
args = args.join "\x07"
|
|
154
|
+
bc += "\x01\x17#{name}\x18#{args}\x08#{body.size}\x18"
|
|
155
|
+
bc += body
|
|
156
|
+
when :object
|
|
157
|
+
name = node.value
|
|
158
|
+
args, body = node.children
|
|
159
|
+
if body.nodetype == :block
|
|
160
|
+
body = self.encode_block body
|
|
161
|
+
else
|
|
162
|
+
body = self.encode_node body
|
|
163
|
+
end
|
|
164
|
+
body += "\x16"
|
|
165
|
+
if args
|
|
166
|
+
args = args.join "\x07"
|
|
167
|
+
else
|
|
168
|
+
args = ""
|
|
169
|
+
end
|
|
170
|
+
bc += "\x01\x30#{name}\x18#{args}\x08#{body.size}\x18"
|
|
171
|
+
bc += body
|
|
172
|
+
when :list
|
|
173
|
+
node.children.each do |item|
|
|
174
|
+
bc += self.encode_node item
|
|
175
|
+
end
|
|
176
|
+
bc += "\x21\x2c#{node.children.size}\x18"
|
|
177
|
+
else
|
|
178
|
+
nil
|
|
179
|
+
end
|
|
180
|
+
bc
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
module Parser
|
|
2
|
+
class Lexer
|
|
3
|
+
TOKENS = {
|
|
4
|
+
/\Aif/ => :if,
|
|
5
|
+
/\Aelse/ => :else,
|
|
6
|
+
/\Awhile/ => :while,
|
|
7
|
+
/\Afor/ => :for,
|
|
8
|
+
/\Ain/ => :in,
|
|
9
|
+
/\Afn/ => :fn,
|
|
10
|
+
/\Aobject/ => :object,
|
|
11
|
+
/\Anew/ => :new,
|
|
12
|
+
/\Arequire/ => :require,
|
|
13
|
+
/\A(<|>|<=|>=|==)/ => :op,
|
|
14
|
+
/\A(\+|-|\*|\/|%)?=/ => :eq,
|
|
15
|
+
/\A(\+|-|\*|\/|%)/ => :op,
|
|
16
|
+
/\A-?[0-9]+/ => :number,
|
|
17
|
+
/\A-?[0-9]+\.[0-9]+/ => :float,
|
|
18
|
+
/\A"([^"]|\\")*"/ => :string,
|
|
19
|
+
/\Anil/ => :nil,
|
|
20
|
+
/\A\(/ => :lpar,
|
|
21
|
+
/\A\)/ => :rpar,
|
|
22
|
+
/\A\[/ => :lbrack,
|
|
23
|
+
/\A\]/ => :rbrack,
|
|
24
|
+
/\A\{/ => :lbrace,
|
|
25
|
+
/\A\}/ => :rbrace,
|
|
26
|
+
/\A,/ => :comma,
|
|
27
|
+
/\A[A-Za-z_][A-Za-z0-9_]*([:.][A-Za-z_][A-Za-z0-9_]*)*/ => :name
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
def self.lex(code)
|
|
31
|
+
lexed = []
|
|
32
|
+
found = false
|
|
33
|
+
while code.size > 0
|
|
34
|
+
TOKENS.each { |re, tag|
|
|
35
|
+
if (code =~ re) != nil
|
|
36
|
+
found = true
|
|
37
|
+
m = (re.match code)
|
|
38
|
+
lexed << [ m[0], tag ]
|
|
39
|
+
code = code[(m.end 0)..code.size].lstrip
|
|
40
|
+
break
|
|
41
|
+
end
|
|
42
|
+
}
|
|
43
|
+
if !found
|
|
44
|
+
puts "Syntax error: ", code
|
|
45
|
+
Kernel.exit 1
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
lexed
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class Node
|
|
53
|
+
attr_reader :nodetype
|
|
54
|
+
attr_reader :children
|
|
55
|
+
attr_reader :value
|
|
56
|
+
|
|
57
|
+
def initialize(nodetype, value = "", children = [])
|
|
58
|
+
@nodetype = nodetype
|
|
59
|
+
@value = value
|
|
60
|
+
@children = children
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class Parser
|
|
65
|
+
def self.lookahead(tokens, toktype, n)
|
|
66
|
+
if n >= tokens.size
|
|
67
|
+
return false
|
|
68
|
+
end
|
|
69
|
+
tokens[n][1] == toktype
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.expect(tokens, toktype)
|
|
73
|
+
self.lookahead(tokens, toktype, 0)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def self.parse_name(tokens)
|
|
77
|
+
if self.expect tokens, :name
|
|
78
|
+
[ (Node.new :name, tokens[0][0], []), 1 ]
|
|
79
|
+
else
|
|
80
|
+
nil
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def self.parse_nil(tokens)
|
|
85
|
+
if self.expect tokens, :nil
|
|
86
|
+
[ (Node.new :nil, tokens[0][0], []), 1 ]
|
|
87
|
+
else
|
|
88
|
+
nil
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def self.parse_number(tokens)
|
|
93
|
+
if self.expect tokens, :number
|
|
94
|
+
[ (Node.new :number, tokens[0][0], []), 1 ]
|
|
95
|
+
else
|
|
96
|
+
nil
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def self.parse_float(tokens)
|
|
101
|
+
if self.expect tokens, :float
|
|
102
|
+
[ (Node.new :float, tokens[0][0], []), 1 ]
|
|
103
|
+
else
|
|
104
|
+
nil
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def self.parse_string(tokens)
|
|
109
|
+
if self.expect tokens, :string
|
|
110
|
+
[ (Node.new :string, tokens[0][0][1..-2], []), 1 ]
|
|
111
|
+
else
|
|
112
|
+
nil
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def self.parse_list(tokens)
|
|
117
|
+
unless (self.expect tokens, :lbrack)
|
|
118
|
+
return nil
|
|
119
|
+
end
|
|
120
|
+
tokens = tokens[1..tokens.size]
|
|
121
|
+
children = []
|
|
122
|
+
total = 1
|
|
123
|
+
while true
|
|
124
|
+
if self.expect tokens, :rbrack
|
|
125
|
+
total += 1
|
|
126
|
+
break
|
|
127
|
+
end
|
|
128
|
+
unless self.parse_expr tokens
|
|
129
|
+
return nil
|
|
130
|
+
end
|
|
131
|
+
e, part = self.parse_expr tokens
|
|
132
|
+
children << e
|
|
133
|
+
total += part
|
|
134
|
+
tokens = tokens[part..tokens.size]
|
|
135
|
+
if self.expect tokens, :rbrack
|
|
136
|
+
total += 1
|
|
137
|
+
break
|
|
138
|
+
end
|
|
139
|
+
unless (self.expect tokens, :comma)
|
|
140
|
+
return nil
|
|
141
|
+
end
|
|
142
|
+
total += 1
|
|
143
|
+
tokens = tokens[1..tokens.size]
|
|
144
|
+
end
|
|
145
|
+
[ (Node.new :list, "", children), total ]
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def self.parse_block(tokens)
|
|
149
|
+
unless (self.expect tokens, :lbrace)
|
|
150
|
+
return nil
|
|
151
|
+
end
|
|
152
|
+
tokens = tokens[1..tokens.size]
|
|
153
|
+
children = []
|
|
154
|
+
total = 1
|
|
155
|
+
while true
|
|
156
|
+
if self.expect tokens, :rbrace
|
|
157
|
+
total += 1
|
|
158
|
+
break
|
|
159
|
+
end
|
|
160
|
+
e = self.parse_expr tokens
|
|
161
|
+
if e
|
|
162
|
+
children << e[0]
|
|
163
|
+
total += e[1]
|
|
164
|
+
tokens = tokens[e[1]..tokens.size]
|
|
165
|
+
else
|
|
166
|
+
puts "Syntax error at token ", tokens[0]
|
|
167
|
+
Kernel.exit 1
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
[ (Node.new :block, "", children), total ]
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def self.parse_literal(tokens)
|
|
174
|
+
self.parse_float(tokens) || (self.parse_block tokens) || (self.parse_name tokens) || (self.parse_number tokens) || (self.parse_list tokens) || (self.parse_string tokens) || (self.parse_nil tokens)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def self.parse_call(tokens)
|
|
178
|
+
if self.lookahead tokens, :lpar, 1
|
|
179
|
+
unless (self.parse_literal tokens)
|
|
180
|
+
return nil
|
|
181
|
+
end
|
|
182
|
+
callee = (self.parse_literal tokens)
|
|
183
|
+
callee = callee[0]
|
|
184
|
+
args = []
|
|
185
|
+
tokens = tokens[2..tokens.size]
|
|
186
|
+
total = 2
|
|
187
|
+
if self.expect tokens, :rpar
|
|
188
|
+
return [ (Node.new :call, callee, args), total + 1 ]
|
|
189
|
+
end
|
|
190
|
+
while true
|
|
191
|
+
unless (self.parse_expr tokens)
|
|
192
|
+
return nil
|
|
193
|
+
end
|
|
194
|
+
arg, part = (self.parse_expr tokens)
|
|
195
|
+
total += part
|
|
196
|
+
tokens = tokens[part..tokens.size]
|
|
197
|
+
args << arg
|
|
198
|
+
total += 1
|
|
199
|
+
if self.expect tokens, :rpar
|
|
200
|
+
tokens = tokens[1..tokens.size]
|
|
201
|
+
break
|
|
202
|
+
end
|
|
203
|
+
unless (self.expect tokens, :comma)
|
|
204
|
+
return nil
|
|
205
|
+
end
|
|
206
|
+
tokens = tokens[1..tokens.size]
|
|
207
|
+
end
|
|
208
|
+
return [ (Node.new :call, callee, args), total ]
|
|
209
|
+
else
|
|
210
|
+
nil
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def self.parse_new(tokens)
|
|
215
|
+
unless self.expect tokens, :new
|
|
216
|
+
return nil
|
|
217
|
+
end
|
|
218
|
+
total = 1
|
|
219
|
+
tokens = tokens[1..tokens.size]
|
|
220
|
+
if self.lookahead tokens, :lpar, 1
|
|
221
|
+
unless (self.parse_literal tokens)
|
|
222
|
+
return nil
|
|
223
|
+
end
|
|
224
|
+
callee = (self.parse_literal tokens)
|
|
225
|
+
callee = callee[0]
|
|
226
|
+
args = []
|
|
227
|
+
tokens = tokens[2..tokens.size]
|
|
228
|
+
total += 2
|
|
229
|
+
if self.expect tokens, :rpar
|
|
230
|
+
return [ (Node.new :call, callee, args), total + 1 ]
|
|
231
|
+
end
|
|
232
|
+
while true
|
|
233
|
+
unless (self.parse_expr tokens)
|
|
234
|
+
return nil
|
|
235
|
+
end
|
|
236
|
+
arg, part = (self.parse_expr tokens)
|
|
237
|
+
total += part
|
|
238
|
+
tokens = tokens[part..tokens.size]
|
|
239
|
+
args << arg
|
|
240
|
+
total += 1
|
|
241
|
+
if self.expect tokens, :rpar
|
|
242
|
+
tokens = tokens[1..tokens.size]
|
|
243
|
+
break
|
|
244
|
+
end
|
|
245
|
+
unless (self.expect tokens, :comma)
|
|
246
|
+
return nil
|
|
247
|
+
end
|
|
248
|
+
tokens = tokens[1..tokens.size]
|
|
249
|
+
end
|
|
250
|
+
return [ (Node.new :new, callee, args), total ]
|
|
251
|
+
else
|
|
252
|
+
nil
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def self.parse_if(tokens)
|
|
257
|
+
unless self.expect tokens, :if
|
|
258
|
+
return nil
|
|
259
|
+
end
|
|
260
|
+
total = 1
|
|
261
|
+
tokens = tokens[1..tokens.size]
|
|
262
|
+
unless self.parse_expr tokens
|
|
263
|
+
return nil
|
|
264
|
+
end
|
|
265
|
+
e, part = self.parse_expr tokens
|
|
266
|
+
total += part
|
|
267
|
+
tokens = tokens[part..tokens.size]
|
|
268
|
+
unless self.parse_expr tokens
|
|
269
|
+
return nil
|
|
270
|
+
end
|
|
271
|
+
block, part = self.parse_expr tokens
|
|
272
|
+
total += part
|
|
273
|
+
tokens = tokens[part..tokens.size]
|
|
274
|
+
el = nil
|
|
275
|
+
if self.expect tokens, :else
|
|
276
|
+
total += 1
|
|
277
|
+
tokens = tokens[1..tokens.size]
|
|
278
|
+
unless self.parse_expr tokens
|
|
279
|
+
return nil
|
|
280
|
+
end
|
|
281
|
+
el, part = self.parse_expr tokens
|
|
282
|
+
total += part
|
|
283
|
+
end
|
|
284
|
+
return [ (Node.new :if, e, [block, el]), total ]
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def self.parse_while(tokens)
|
|
288
|
+
unless self.expect tokens, :while
|
|
289
|
+
return nil
|
|
290
|
+
end
|
|
291
|
+
total = 1
|
|
292
|
+
tokens = tokens[1..tokens.size]
|
|
293
|
+
unless self.parse_expr tokens
|
|
294
|
+
return nil
|
|
295
|
+
end
|
|
296
|
+
e, part = self.parse_expr tokens
|
|
297
|
+
total += part
|
|
298
|
+
tokens = tokens[part..tokens.size]
|
|
299
|
+
unless self.parse_expr tokens
|
|
300
|
+
return nil
|
|
301
|
+
end
|
|
302
|
+
block, part = self.parse_expr tokens
|
|
303
|
+
total += part
|
|
304
|
+
return [ (Node.new :while, e, [block]), total ]
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def self.parse_for(tokens)
|
|
308
|
+
unless self.expect tokens, :for
|
|
309
|
+
return nil
|
|
310
|
+
end
|
|
311
|
+
total = 1
|
|
312
|
+
tokens = tokens[1..tokens.size]
|
|
313
|
+
name = nil
|
|
314
|
+
if self.expect tokens, :name and self.lookahead tokens, :in, 1
|
|
315
|
+
name = tokens[0][0]
|
|
316
|
+
total += 2
|
|
317
|
+
tokens = tokens[2..tokens.size]
|
|
318
|
+
end
|
|
319
|
+
unless self.parse_expr tokens
|
|
320
|
+
return nil
|
|
321
|
+
end
|
|
322
|
+
e, part = self.parse_expr tokens
|
|
323
|
+
total += part
|
|
324
|
+
tokens = tokens[part..tokens.size]
|
|
325
|
+
unless self.parse_expr tokens
|
|
326
|
+
return nil
|
|
327
|
+
end
|
|
328
|
+
block, part = self.parse_expr tokens
|
|
329
|
+
total += part
|
|
330
|
+
return [ (Node.new :for, e, [name, block]), total ]
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def self.parse_op(tokens)
|
|
334
|
+
total = 0
|
|
335
|
+
unless self.parse_literal tokens
|
|
336
|
+
return nil
|
|
337
|
+
end
|
|
338
|
+
lhs, part = self.parse_literal tokens
|
|
339
|
+
total += part
|
|
340
|
+
tokens = tokens[part..tokens.size]
|
|
341
|
+
unless self.expect tokens, :op
|
|
342
|
+
return nil
|
|
343
|
+
end
|
|
344
|
+
op = tokens[0][0]
|
|
345
|
+
total += 1
|
|
346
|
+
tokens = tokens[1..tokens.size]
|
|
347
|
+
unless self.parse_expr tokens
|
|
348
|
+
return nil
|
|
349
|
+
end
|
|
350
|
+
rhs, part = self.parse_expr tokens
|
|
351
|
+
total += part
|
|
352
|
+
return [ (Node.new :op, op, [lhs, rhs]), total]
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def self.parse_assign(tokens)
|
|
356
|
+
total = 0
|
|
357
|
+
unless self.expect tokens, :name
|
|
358
|
+
return nil
|
|
359
|
+
end
|
|
360
|
+
name = tokens[0][0]
|
|
361
|
+
total += 1
|
|
362
|
+
tokens = tokens[1..tokens.size]
|
|
363
|
+
unless self.expect tokens, :eq
|
|
364
|
+
return nil
|
|
365
|
+
end
|
|
366
|
+
eq = tokens[0][0]
|
|
367
|
+
total += 1
|
|
368
|
+
tokens = tokens[1..tokens.size]
|
|
369
|
+
unless self.parse_expr tokens
|
|
370
|
+
return nil
|
|
371
|
+
end
|
|
372
|
+
rhs, part = self.parse_expr tokens
|
|
373
|
+
total += part
|
|
374
|
+
return [ (Node.new :assign, eq, [name, rhs]), total]
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
def self.parse_fn(tokens)
|
|
378
|
+
unless self.expect tokens, :fn
|
|
379
|
+
return nil
|
|
380
|
+
end
|
|
381
|
+
total = 1
|
|
382
|
+
tokens = tokens[1..tokens.size]
|
|
383
|
+
unless self.expect tokens, :name
|
|
384
|
+
return nil
|
|
385
|
+
end
|
|
386
|
+
name = tokens[0][0]
|
|
387
|
+
total += 1
|
|
388
|
+
tokens = tokens[1..tokens.size]
|
|
389
|
+
unless self.expect tokens, :lpar
|
|
390
|
+
return nil
|
|
391
|
+
end
|
|
392
|
+
total += 1
|
|
393
|
+
tokens = tokens[1..tokens.size]
|
|
394
|
+
args = []
|
|
395
|
+
while true
|
|
396
|
+
if self.expect tokens, :rpar
|
|
397
|
+
total += 1
|
|
398
|
+
tokens = tokens[1..tokens.size]
|
|
399
|
+
break
|
|
400
|
+
end
|
|
401
|
+
unless self.expect tokens, :name
|
|
402
|
+
return nil
|
|
403
|
+
end
|
|
404
|
+
args << tokens[0][0]
|
|
405
|
+
total += 1
|
|
406
|
+
tokens = tokens[1..tokens.size]
|
|
407
|
+
if self.expect tokens, :rpar
|
|
408
|
+
total += 1
|
|
409
|
+
tokens = tokens[1..tokens.size]
|
|
410
|
+
break
|
|
411
|
+
end
|
|
412
|
+
unless self.expect tokens, :comma
|
|
413
|
+
return nil
|
|
414
|
+
end
|
|
415
|
+
total += 1
|
|
416
|
+
tokens = tokens[1..tokens.size]
|
|
417
|
+
end
|
|
418
|
+
unless self.parse_expr tokens
|
|
419
|
+
return nil
|
|
420
|
+
end
|
|
421
|
+
body, part = self.parse_expr tokens
|
|
422
|
+
total += part
|
|
423
|
+
return [ (Node.new :fn, name, [args, body]), total ]
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def self.parse_object(tokens)
|
|
427
|
+
unless self.expect tokens, :object
|
|
428
|
+
return nil
|
|
429
|
+
end
|
|
430
|
+
total = 1
|
|
431
|
+
tokens = tokens[1..tokens.size]
|
|
432
|
+
unless self.expect tokens, :name
|
|
433
|
+
return nil
|
|
434
|
+
end
|
|
435
|
+
name = tokens[0][0]
|
|
436
|
+
total += 1
|
|
437
|
+
tokens = tokens[1..tokens.size]
|
|
438
|
+
args = []
|
|
439
|
+
if self.expect tokens, :lpar
|
|
440
|
+
total += 1
|
|
441
|
+
tokens = tokens[1..tokens.size]
|
|
442
|
+
while true
|
|
443
|
+
if self.expect tokens, :rpar
|
|
444
|
+
total += 1
|
|
445
|
+
tokens = tokens[1..tokens.size]
|
|
446
|
+
break
|
|
447
|
+
end
|
|
448
|
+
unless self.expect tokens, :name
|
|
449
|
+
return nil
|
|
450
|
+
end
|
|
451
|
+
args << tokens[0][0]
|
|
452
|
+
total += 1
|
|
453
|
+
tokens = tokens[1..tokens.size]
|
|
454
|
+
if self.expect tokens, :rpar
|
|
455
|
+
total += 1
|
|
456
|
+
tokens = tokens[1..tokens.size]
|
|
457
|
+
break
|
|
458
|
+
end
|
|
459
|
+
unless self.expect tokens, :comma
|
|
460
|
+
return nil
|
|
461
|
+
end
|
|
462
|
+
total += 1
|
|
463
|
+
tokens = tokens[1..tokens.size]
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
unless self.parse_expr tokens
|
|
467
|
+
return nil
|
|
468
|
+
end
|
|
469
|
+
body, part = self.parse_expr tokens
|
|
470
|
+
total += part
|
|
471
|
+
return [ (Node.new :object, name, [args, body]), total ]
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
def self.parse_require(tokens)
|
|
475
|
+
unless self.expect tokens, :require
|
|
476
|
+
return nil
|
|
477
|
+
end
|
|
478
|
+
tokens = tokens[1..tokens.size]
|
|
479
|
+
unless self.expect tokens, :string
|
|
480
|
+
return nil
|
|
481
|
+
end
|
|
482
|
+
return [ (Node.new :require, tokens[0][0][1..-2], []), 2 ]
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
def self.parse_expr(tokens)
|
|
486
|
+
(self.parse_require tokens) || (self.parse_new tokens) || (self.parse_object tokens) || (self.parse_fn tokens) || (self.parse_assign tokens) || (self.parse_op tokens) || (self.parse_call tokens) || (self.parse_literal tokens) || (self.parse_if tokens) || (self.parse_while tokens) || (self.parse_for tokens)
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
def self.parse(tokens, path)
|
|
490
|
+
parsed = []
|
|
491
|
+
while tokens.size > 0
|
|
492
|
+
e = self.parse_expr tokens
|
|
493
|
+
if e
|
|
494
|
+
if e[0].nodetype == :require
|
|
495
|
+
code = nil
|
|
496
|
+
path.each do |search|
|
|
497
|
+
begin
|
|
498
|
+
code = File.read "#{File.join(search, e[0].value)}.sdx"
|
|
499
|
+
rescue
|
|
500
|
+
nil
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
unless code
|
|
504
|
+
puts "Cannot find file #{e[0].value}.sdx anywhere in path"
|
|
505
|
+
Kernel.exit 1
|
|
506
|
+
end
|
|
507
|
+
lexed = Lexer.lex code
|
|
508
|
+
ast = self.parse lexed, path
|
|
509
|
+
parsed.concat ast
|
|
510
|
+
else
|
|
511
|
+
parsed << e[0]
|
|
512
|
+
end
|
|
513
|
+
tokens = tokens[e[1]..tokens.size]
|
|
514
|
+
else
|
|
515
|
+
puts "Syntax error at token ", tokens[0][1]
|
|
516
|
+
Kernel.exit 1
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
parsed
|
|
520
|
+
end
|
|
521
|
+
end
|
|
522
|
+
end
|