rubasteme 0.1.2 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +35 -0
- data/examples/mini_rus3 +9 -4
- data/examples/mini_sicp_scheme +1 -1
- data/examples/sicp_scheme/evaluator.rb +18 -5
- data/exe/rubasteme +2 -2
- data/lib/rbscmlex/missing.rb +46 -0
- data/lib/rubasteme.rb +5 -0
- data/lib/rubasteme/ast.rb +11 -1
- data/lib/rubasteme/ast/branch_node.rb +221 -75
- data/lib/rubasteme/ast/leaf_node.rb +4 -0
- data/lib/rubasteme/error.rb +3 -3
- data/lib/rubasteme/parser.rb +28 -585
- data/lib/rubasteme/parser/derived_converter.rb +315 -0
- data/lib/rubasteme/parser/phase1_parser.rb +119 -0
- data/lib/rubasteme/parser/phase2_parser.rb +255 -0
- data/lib/rubasteme/version.rb +7 -2
- data/rubasteme.gemspec +1 -1
- metadata +8 -4
@@ -0,0 +1,315 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rubasteme
|
4
|
+
module Parser
|
5
|
+
|
6
|
+
module DerivedConverter
|
7
|
+
include Utils
|
8
|
+
|
9
|
+
DERIVED_IDENTIFIERS = [
|
10
|
+
"cond", "case", "and", "or", "when", "unless",
|
11
|
+
"let", "let*", "letrec", "letrec*",
|
12
|
+
"let-values", "let*-values",
|
13
|
+
"begin", "do",
|
14
|
+
"delay", "delay-force",
|
15
|
+
"parameterize",
|
16
|
+
"guard",
|
17
|
+
"case-lambda",
|
18
|
+
]
|
19
|
+
|
20
|
+
def to_derived_expression(list)
|
21
|
+
name = compose_method_name("to_", list[0].identifier).intern
|
22
|
+
if self.respond_to?(name, true)
|
23
|
+
self.send(name, list)
|
24
|
+
else
|
25
|
+
not_implemented_yet(list[0])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_cond(list)
|
30
|
+
# ( cond <cond clause> ... <else clause> )
|
31
|
+
cond = AST.instantiate(:ast_cond)
|
32
|
+
list[1..-2].each { |e|
|
33
|
+
cond.add_clause(to_cond_clause(e))
|
34
|
+
}
|
35
|
+
last = list[-1]
|
36
|
+
method = is_else_clause?(last) ? :to_else_clause : :to_cond_clause
|
37
|
+
cond.add_clause(self.send(method, last))
|
38
|
+
cond
|
39
|
+
end
|
40
|
+
|
41
|
+
def is_else_clause?(list)
|
42
|
+
ast_type?(list[0], :ast_identifier) && list[0].identifier == "else"
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_cond_clause(list)
|
46
|
+
# type 1: ( <test> )
|
47
|
+
# type 2: ( <test> <sequence> )
|
48
|
+
# type 3: ( <test> => <recipient> )
|
49
|
+
clause = nil
|
50
|
+
if is_recipient_clause?(list)
|
51
|
+
# type 3
|
52
|
+
clause = AST.instantiate(:ast_cond_recipient_clause)
|
53
|
+
clause.recipient = to_recipient(list[2..-1])
|
54
|
+
else
|
55
|
+
# type 1 and 2
|
56
|
+
clause = AST.instantiate(:ast_cond_clause)
|
57
|
+
clause.sequence = to_sequence(list[1..-1])
|
58
|
+
end
|
59
|
+
clause.test = to_test(list[0])
|
60
|
+
clause
|
61
|
+
end
|
62
|
+
|
63
|
+
def is_recipient_clause?(list)
|
64
|
+
ast_type?(list[1], :ast_identifier) && list[1].identifier == "=>"
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_else_clause(list)
|
68
|
+
# ( else <sequence> )
|
69
|
+
else_clause = AST.instantiate(:ast_else_clause)
|
70
|
+
else_clause.sequence = to_sequence(list[1..-1])
|
71
|
+
else_clause
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_test(list)
|
75
|
+
# <test> -> <expression>
|
76
|
+
parse(list)
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_recipient(list)
|
80
|
+
# <recipient> -> <expression>
|
81
|
+
parse(list)
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_case(list)
|
85
|
+
# ( case <expression> <case clause>+ )
|
86
|
+
# ( case <expression> <case clause>* ( else <sequence> ) )
|
87
|
+
# ( case <expression> <case clause>* ( else => <recipient> ) )
|
88
|
+
case_node = AST.instantiate(:ast_case)
|
89
|
+
case_node.expression = parse(list[1])
|
90
|
+
list[2..-2].each { |e|
|
91
|
+
case_node.add_clause(to_case_clause(e))
|
92
|
+
}
|
93
|
+
last = list[-1]
|
94
|
+
method = is_else_clause?(last) ? :to_case_else_clause : :to_case_clause
|
95
|
+
case_node.add_clause(self.send(method, last))
|
96
|
+
case_node
|
97
|
+
end
|
98
|
+
|
99
|
+
def to_case_clause(list)
|
100
|
+
# ( ( <datum>* ) <sequence> )
|
101
|
+
# ( ( <datum>* ) => <recipient> )
|
102
|
+
if is_recipient_clause?(list)
|
103
|
+
to_case_recipient_clause(list)
|
104
|
+
else
|
105
|
+
clause = AST.instantiate(:ast_case_clause)
|
106
|
+
clause.data = to_data(list[0])
|
107
|
+
clause.sequence = to_sequence(list[1..-1])
|
108
|
+
clause
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def to_case_recipient_clause(list)
|
113
|
+
# ( ( <datum>* ) => <recipient> )
|
114
|
+
clause = AST.instantiate(:ast_case_recipient_clause)
|
115
|
+
clause.data = to_data(list[0])
|
116
|
+
caluse.recipient = to_recipient(list[2])
|
117
|
+
end
|
118
|
+
|
119
|
+
def to_case_else_clause(list)
|
120
|
+
# ( else <sequence> )
|
121
|
+
# ( else => <recipient> )
|
122
|
+
if is_recipient_clause?(list)
|
123
|
+
to_case_else_recipient_clause(list)
|
124
|
+
else
|
125
|
+
to_else_clause(list)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def to_case_else_recipient_clause(list)
|
130
|
+
# ( else => <recipient> )
|
131
|
+
clause = AST.instantiate(:ast_else_recipient_clause)
|
132
|
+
clause.recipient = to_recipient(list[2])
|
133
|
+
clause
|
134
|
+
end
|
135
|
+
|
136
|
+
def to_data(list)
|
137
|
+
# ( <datum>* )
|
138
|
+
data = AST.instantiate(:ast_data)
|
139
|
+
list.each{|e| data << parse(e)}
|
140
|
+
data
|
141
|
+
end
|
142
|
+
|
143
|
+
def to_and(list)
|
144
|
+
to_logical_test("and", list)
|
145
|
+
end
|
146
|
+
|
147
|
+
def to_or(list)
|
148
|
+
to_logical_test("or", list)
|
149
|
+
end
|
150
|
+
|
151
|
+
def to_logical_test(type, list)
|
152
|
+
# ( and <test>* )
|
153
|
+
# ( or <test>* )
|
154
|
+
ast_type = "ast_#{type}".intern
|
155
|
+
node = AST.instantiate(ast_type)
|
156
|
+
list[1..-1].each{|e| node << to_test(e)}
|
157
|
+
node
|
158
|
+
end
|
159
|
+
|
160
|
+
def to_when(list)
|
161
|
+
to_test_and_sequence("when", list)
|
162
|
+
end
|
163
|
+
|
164
|
+
def to_unless(list)
|
165
|
+
to_test_and_sequence("unless", list)
|
166
|
+
end
|
167
|
+
|
168
|
+
def to_test_and_sequence(type, list)
|
169
|
+
# ( when <test> <sequence> )
|
170
|
+
# ( unless <test> <sequence> )
|
171
|
+
ast_type = "ast_#{type}".intern
|
172
|
+
node = AST.instantiate(ast_type)
|
173
|
+
node.test = to_test(list[1])
|
174
|
+
node.sequence = to_sequence(list[2..-1])
|
175
|
+
node
|
176
|
+
end
|
177
|
+
|
178
|
+
def to_let(list)
|
179
|
+
# ( let ( <binding spec>* ) <body> )
|
180
|
+
# ( let <identifier> ( <binding spec>* ) <body> )
|
181
|
+
let = AST.instantiate(:ast_let)
|
182
|
+
bindings_pos = 1
|
183
|
+
if ast_type?(list[1], :ast_identifier)
|
184
|
+
# named let
|
185
|
+
let.identifier = list[1]
|
186
|
+
bindings_pos += 1
|
187
|
+
end
|
188
|
+
let.bindings = to_bindings(list[bindings_pos])
|
189
|
+
let.body = to_body(list[(bindings_pos + 1)..-1])
|
190
|
+
let
|
191
|
+
end
|
192
|
+
|
193
|
+
def to_bindings(list)
|
194
|
+
# ( <binding spec>* )
|
195
|
+
bindings = AST.instantiate(:ast_bindings)
|
196
|
+
list.each { |e|
|
197
|
+
bindings.add_bind_spec(to_bind_spec(e))
|
198
|
+
}
|
199
|
+
bindings
|
200
|
+
end
|
201
|
+
|
202
|
+
def to_bind_spec(list)
|
203
|
+
# ( <identifier> <expression> )
|
204
|
+
spec = AST.instantiate(:ast_bind_spec)
|
205
|
+
spec.identifier = list[0]
|
206
|
+
spec.expression = parse(list[1])
|
207
|
+
spec
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
def to_let_star(list)
|
212
|
+
to_let_base("let_star", list)
|
213
|
+
end
|
214
|
+
|
215
|
+
def to_letrec(list)
|
216
|
+
to_let_base("letrec", list)
|
217
|
+
end
|
218
|
+
|
219
|
+
def to_letrec_star(list)
|
220
|
+
to_let_base("letrec_star", list)
|
221
|
+
end
|
222
|
+
|
223
|
+
def to_let_base(type, list)
|
224
|
+
# ( let* ( <binding spec>* ) <body> )
|
225
|
+
# ( letrec ( <binding spec>* ) <body> )
|
226
|
+
# ( letrec* ( <binding spec>* ) <body> )
|
227
|
+
ast_type = "ast_#{type}".intern
|
228
|
+
node = AST.instantiate(ast_type)
|
229
|
+
node.bindings = to_bindings(list[1])
|
230
|
+
node.body = to_body(list[2..-1])
|
231
|
+
node
|
232
|
+
end
|
233
|
+
|
234
|
+
def to_let_values(list)
|
235
|
+
not_implemented_yet("LET-VALUES")
|
236
|
+
end
|
237
|
+
|
238
|
+
def to_let_star_values(list)
|
239
|
+
not_implemented_yet("LET*-VALUES")
|
240
|
+
end
|
241
|
+
|
242
|
+
def to_begin(list)
|
243
|
+
# ( begin <sequence> )
|
244
|
+
begin_node = AST.instantiate(:ast_begin)
|
245
|
+
begin_node.sequence = to_sequence(list[1..-1])
|
246
|
+
begin_node
|
247
|
+
end
|
248
|
+
|
249
|
+
def to_do(list)
|
250
|
+
# ( do ( <iteration spec>* ) ( <test> <do result> ) <command>* )
|
251
|
+
do_node = AST.instantiate(:ast_do)
|
252
|
+
do_node.iteration_bindings = to_iteration_bindings(list[1])
|
253
|
+
do_node.test_and_do_result = to_test_and_do_result(list[2])
|
254
|
+
list[3..-1].each { |e|
|
255
|
+
do_node.add_command(parse(e))
|
256
|
+
}
|
257
|
+
do_node
|
258
|
+
end
|
259
|
+
|
260
|
+
def to_iteration_bindings(list)
|
261
|
+
# ( <iteration spec>* )
|
262
|
+
node = AST.instantiate(:ast_iteration_bindings)
|
263
|
+
list.each { |e|
|
264
|
+
node.add_iteration_spec(to_iteration_spec(e))
|
265
|
+
}
|
266
|
+
node
|
267
|
+
end
|
268
|
+
|
269
|
+
def to_iteration_spec(list)
|
270
|
+
# ( <identifier> <init> )
|
271
|
+
# ( <identifier> <init> <step> )
|
272
|
+
# <init> -> <expression>
|
273
|
+
# <step> -> <expression>
|
274
|
+
spec = AST.instantiate(:ast_iteration_spec)
|
275
|
+
spec.identifier = list[0]
|
276
|
+
spec.init = parse(list[1])
|
277
|
+
if list.size > 2
|
278
|
+
spec.step = parse(list[2])
|
279
|
+
end
|
280
|
+
spec
|
281
|
+
end
|
282
|
+
|
283
|
+
def to_test_and_do_result(list)
|
284
|
+
# ( <test> <do result> )
|
285
|
+
# <do result> -> <sequence> | <empty>
|
286
|
+
node = AST.instantiate(:ast_test_and_do_result)
|
287
|
+
node.test = to_test(list[0])
|
288
|
+
node.sequence = to_sequence(list[1..-1])
|
289
|
+
node
|
290
|
+
end
|
291
|
+
|
292
|
+
def to_delay(list)
|
293
|
+
not_implemented_yet("DELAY")
|
294
|
+
end
|
295
|
+
|
296
|
+
def to_delay_force(list)
|
297
|
+
not_implemented_yet("DELAY-FORCE")
|
298
|
+
end
|
299
|
+
|
300
|
+
def to_parameterize(list)
|
301
|
+
not_implemented_yet("PARAMETERIZE")
|
302
|
+
end
|
303
|
+
|
304
|
+
def to_guard(list)
|
305
|
+
not_implemented_yet("GUARD")
|
306
|
+
end
|
307
|
+
|
308
|
+
def to_case_lambda(list)
|
309
|
+
not_implemented_yet("CASE-LAMBDA")
|
310
|
+
end
|
311
|
+
|
312
|
+
end
|
313
|
+
|
314
|
+
end # end of Parser (module)
|
315
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rubasteme
|
4
|
+
|
5
|
+
def self.phase1_parse(source)
|
6
|
+
Parser::Phase1Parser.new.parse(Rbscmlex.lexer(source))
|
7
|
+
end
|
8
|
+
|
9
|
+
module Parser
|
10
|
+
|
11
|
+
class Phase1Parser
|
12
|
+
include Utils
|
13
|
+
|
14
|
+
def self.version
|
15
|
+
Rubasteme.send(:make_version, self.name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def version
|
19
|
+
self.class.version
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse(lexer)
|
23
|
+
return [] if lexer.nil?
|
24
|
+
parse_expression(lexer)
|
25
|
+
end
|
26
|
+
|
27
|
+
# :stopdoc:
|
28
|
+
private
|
29
|
+
|
30
|
+
def parse_expression(lexer)
|
31
|
+
if start_delimiter?(lexer.peek_token)
|
32
|
+
parse_compound_expression(lexer)
|
33
|
+
else
|
34
|
+
parse_simple_expression(lexer)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
TOKEN_START_DELIMITERS = [ # :nodoc:
|
39
|
+
:lparen, # list: ( ... )
|
40
|
+
:vec_lparen, # vector: #( ... )
|
41
|
+
:bytevec_lparen, # bytevector: #u8( ... )
|
42
|
+
:quotation, # quotation: '<something>
|
43
|
+
:backquote, # quasiquote: `<something>
|
44
|
+
:comma, # used in quasiquote
|
45
|
+
:comma_at, # used in quasiquote
|
46
|
+
:comment_lparen, # comment start
|
47
|
+
]
|
48
|
+
|
49
|
+
def start_delimiter?(token)
|
50
|
+
TOKEN_START_DELIMITERS.include?(token.type)
|
51
|
+
end
|
52
|
+
|
53
|
+
def parse_simple_expression(lexer)
|
54
|
+
type, literal = *lexer.next_token
|
55
|
+
AST.instantiate(ast_simple_type(type), literal)
|
56
|
+
end
|
57
|
+
|
58
|
+
def ast_simple_type(token_type)
|
59
|
+
case token_type
|
60
|
+
when :identifier
|
61
|
+
:ast_identifier
|
62
|
+
when :boolean, :character, :number, :string
|
63
|
+
"ast_#{token_type}".intern
|
64
|
+
when :dot
|
65
|
+
:ast_dot
|
66
|
+
else
|
67
|
+
:ast_illegal
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def parse_compound_expression(lexer)
|
72
|
+
case lexer.peek_token.type
|
73
|
+
when :vec_lparen
|
74
|
+
parse_vector(lexer)
|
75
|
+
when :quotation
|
76
|
+
parse_quotation(lexer)
|
77
|
+
when :lparen
|
78
|
+
parse_list(lexer)
|
79
|
+
else
|
80
|
+
raise SchemeSyntaxErrorError, "%s" % lexer.peek_token.literal
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def parse_list(lexer)
|
85
|
+
if lexer.peek_token(1).type == :rparen
|
86
|
+
# an empty list
|
87
|
+
lexer.skip_rparen(1)
|
88
|
+
AST.instantiate(:ast_empty_list)
|
89
|
+
else
|
90
|
+
nodes = []
|
91
|
+
parse_container(nodes, lexer)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def parse_vector(lexer)
|
96
|
+
vector = AST.instantiate(:ast_vector)
|
97
|
+
parse_container(vector, lexer)
|
98
|
+
end
|
99
|
+
|
100
|
+
def parse_container(container, lexer)
|
101
|
+
lexer.skip_token
|
102
|
+
Kernel.loop {
|
103
|
+
break if lexer.peek_token.type == :rparen
|
104
|
+
container << parse_expression(lexer)
|
105
|
+
}
|
106
|
+
lexer.skip_rparen
|
107
|
+
container
|
108
|
+
end
|
109
|
+
|
110
|
+
def parse_quotation(lexer)
|
111
|
+
lexer.skip_token
|
112
|
+
quote = AST.instantiate(:ast_identifier, "quote")
|
113
|
+
[quote, parse_expression(lexer)]
|
114
|
+
end
|
115
|
+
|
116
|
+
# :startdoc:
|
117
|
+
end # end of Phase1Parser
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,255 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rubasteme
|
4
|
+
|
5
|
+
def self.phase2_parse(source)
|
6
|
+
nodes = Parser::Phase1Parser.new.parse(Rbscmlex.lexer(source))
|
7
|
+
Parser::Phase2Parser.new.parse(nodes)
|
8
|
+
end
|
9
|
+
|
10
|
+
module Parser
|
11
|
+
|
12
|
+
require_relative "derived_converter"
|
13
|
+
|
14
|
+
class Phase2Parser
|
15
|
+
include Utils
|
16
|
+
include DerivedConverter
|
17
|
+
|
18
|
+
def self.version
|
19
|
+
Rubasteme.send(:make_version, self.name)
|
20
|
+
end
|
21
|
+
|
22
|
+
def version
|
23
|
+
self.class.version
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse(list)
|
27
|
+
if ast?(list)
|
28
|
+
list
|
29
|
+
elsif list.instance_of?(Array)
|
30
|
+
to_ast(list)
|
31
|
+
else
|
32
|
+
raise SchemeSyntaxErrorError,
|
33
|
+
"unknown syntax element; got=%s" % node.to_s
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# :stopdoc:
|
38
|
+
private
|
39
|
+
|
40
|
+
def to_ast(list)
|
41
|
+
if list.empty?
|
42
|
+
AST.instantiate(:ast_empty_list)
|
43
|
+
elsif ast_type?(list[0], :ast_identifier)
|
44
|
+
node = nil
|
45
|
+
case list[0].identifier
|
46
|
+
when "quote"
|
47
|
+
node = to_quotation(list)
|
48
|
+
when "lambda"
|
49
|
+
node = to_lambda_expression(list)
|
50
|
+
when "if"
|
51
|
+
node = to_conditional(list)
|
52
|
+
when "set!"
|
53
|
+
node = to_assignment(list)
|
54
|
+
when "let-syntax", "letrec-syntax"
|
55
|
+
node = to_macro_block(list)
|
56
|
+
when "define", "define-syntax", "define-values", "define-record-type"
|
57
|
+
node = to_definition(list)
|
58
|
+
when "include", "include-ci"
|
59
|
+
node = to_include(list)
|
60
|
+
when *DERIVED_IDENTIFIERS
|
61
|
+
node = to_derived_expression(list)
|
62
|
+
end
|
63
|
+
node || to_procedure_call(list)
|
64
|
+
elsif list[0].instance_of?(Array)
|
65
|
+
to_procedure_call(list)
|
66
|
+
else
|
67
|
+
raise SchemeSyntaxErrorError,
|
68
|
+
"invalid application; got=%s" % list.to_a.to_s
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_quotation(list)
|
73
|
+
quote = AST.instantiate(:ast_quotation)
|
74
|
+
quote << list
|
75
|
+
quote
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_procedure_call(list)
|
79
|
+
proc_call = AST.instantiate(:ast_procedure_call)
|
80
|
+
proc_call.operator = parse(list[0])
|
81
|
+
list[1..-1].each { |node|
|
82
|
+
proc_call.add_operand(parse(node))
|
83
|
+
}
|
84
|
+
proc_call
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_lambda_expression(list)
|
88
|
+
# ( lambda <formals> <body> )
|
89
|
+
lambda_exp = AST.instantiate(:ast_lambda_expression)
|
90
|
+
lambda_exp.formals = to_formals(list[1])
|
91
|
+
lambda_exp.body = to_body(list[2..-1])
|
92
|
+
lambda_exp
|
93
|
+
end
|
94
|
+
|
95
|
+
def to_formals(list)
|
96
|
+
# type 1: <identifier>
|
97
|
+
# type 2: ( <identifier 1> <identifier 2> ... )
|
98
|
+
# type 3: ( <identifier 1> <identifier 2> <dot> <identifier n> )
|
99
|
+
# => not supported yet
|
100
|
+
if ast_type?(list, :ast_identifier)
|
101
|
+
# type 1
|
102
|
+
list
|
103
|
+
else
|
104
|
+
# type 2
|
105
|
+
formals = AST.instantiate(:ast_formals)
|
106
|
+
list.each{|e| formals.add_identifier(e)}
|
107
|
+
formals
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def to_body(list)
|
112
|
+
# <body> -> <definition>* <sequence>
|
113
|
+
body = AST.instantiate(:ast_body)
|
114
|
+
definitions = AST.instantiate(:ast_internal_definitions)
|
115
|
+
|
116
|
+
i = 0
|
117
|
+
list.each { |e|
|
118
|
+
break unless is_definition?(e)
|
119
|
+
definitions.add_definition(to_definition(e))
|
120
|
+
i += 1
|
121
|
+
}
|
122
|
+
body.definitions = definitions
|
123
|
+
|
124
|
+
body.sequence = to_sequence(list[i..-1])
|
125
|
+
body
|
126
|
+
end
|
127
|
+
|
128
|
+
def to_sequence(list)
|
129
|
+
# <sequence> -> <command>* <expression>
|
130
|
+
# <command> -> <expression>
|
131
|
+
seq = AST.instantiate(:ast_sequence)
|
132
|
+
list.each { |node|
|
133
|
+
if is_definition?(node)
|
134
|
+
raise SchemeSyntaxErrorError,
|
135
|
+
"wrong position of internal definition"
|
136
|
+
end
|
137
|
+
seq.add_expression(parse(node))
|
138
|
+
}
|
139
|
+
seq
|
140
|
+
end
|
141
|
+
|
142
|
+
DEFINITION_IDENTIFIERS = [
|
143
|
+
"define",
|
144
|
+
"define-syntax",
|
145
|
+
"define-values",
|
146
|
+
"define-record-type",
|
147
|
+
]
|
148
|
+
|
149
|
+
def is_definition?(list)
|
150
|
+
list.instance_of?(Array) &&
|
151
|
+
ast_type?(list[0], :ast_identifier) &&
|
152
|
+
DEFINITION_IDENTIFIERS.include?(list[0].identifier)
|
153
|
+
end
|
154
|
+
|
155
|
+
def to_definition(list)
|
156
|
+
case list[0].identifier
|
157
|
+
when "define"
|
158
|
+
to_identifier_definition(list)
|
159
|
+
when "define-syntax"
|
160
|
+
to_define_syntax(list)
|
161
|
+
when "define-values"
|
162
|
+
to_define_values(list)
|
163
|
+
when "define-record-type"
|
164
|
+
to_define_record_type(list)
|
165
|
+
else
|
166
|
+
raise SchemeSyntaxErrorError, "not definition got=%s" % list[0].identifier
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def to_identifier_definition(list)
|
171
|
+
# type 1: (define foo 3)
|
172
|
+
# type 2: (define bar (lambda (x y) (+ x y)))
|
173
|
+
# type 3: (define (hoge n m) (display n) (display m) (* n m))
|
174
|
+
define = AST.instantiate(:ast_identifier_definition)
|
175
|
+
|
176
|
+
if ast_type?(list[1], :ast_identifier)
|
177
|
+
# type 1 and type 2
|
178
|
+
define.identifier = list[1]
|
179
|
+
define.expression = parse(list[2])
|
180
|
+
elsif list[1].instance_of?(Array)
|
181
|
+
# type 3:
|
182
|
+
# make a lambda expression, then handle as type 2
|
183
|
+
lambda_exp = AST.instantiate(:ast_lambda_expression)
|
184
|
+
lambda_exp.formals = to_formals(list[1][1..-1])
|
185
|
+
lambda_exp.body = to_body(list[2..-1])
|
186
|
+
|
187
|
+
define.identifier = list[1][0]
|
188
|
+
define.expression = lambda_exp
|
189
|
+
else
|
190
|
+
raise SchemeSyntaxErrorError, "got=%s" % list[1].to_s
|
191
|
+
end
|
192
|
+
|
193
|
+
define
|
194
|
+
end
|
195
|
+
|
196
|
+
def to_define_syntax(ast_node)
|
197
|
+
not_implemented_yet("DEFINE-SYNTAX")
|
198
|
+
end
|
199
|
+
|
200
|
+
def to_define_values(ast_node)
|
201
|
+
not_implemented_yet("DEFINE-VALUES")
|
202
|
+
end
|
203
|
+
|
204
|
+
def to_define_record_type(ast_node)
|
205
|
+
not_implemented_yet("DEFINE-RECORD-TYPE")
|
206
|
+
end
|
207
|
+
|
208
|
+
def to_includer(ast_node)
|
209
|
+
not_implemented_yet("INCLUDE or INCLUDE-CI")
|
210
|
+
end
|
211
|
+
|
212
|
+
def to_conditional(list)
|
213
|
+
# ( if <test> <consequent> )
|
214
|
+
# ( if <test> <consequent> <alternate> )
|
215
|
+
if_node = AST.instantiate(:ast_conditional)
|
216
|
+
if_node.test = parse(list[1])
|
217
|
+
if_node.consequent = parse(list[2])
|
218
|
+
|
219
|
+
if list.size > 3
|
220
|
+
if_node.alternate = parse(list[3])
|
221
|
+
end
|
222
|
+
|
223
|
+
if_node
|
224
|
+
end
|
225
|
+
|
226
|
+
def to_assignment(list)
|
227
|
+
# ( set! <identifier> <expression>)
|
228
|
+
assignment = AST.instantiate(:ast_assignment)
|
229
|
+
assignment.identifier = list[1]
|
230
|
+
assignment.expression = parse(list[2])
|
231
|
+
assignment
|
232
|
+
end
|
233
|
+
|
234
|
+
def to_macro_block(list)
|
235
|
+
not_implemented_yet("MACRO BLOCK")
|
236
|
+
end
|
237
|
+
|
238
|
+
def to_include(list)
|
239
|
+
not_implemented_yet("INCLUDE")
|
240
|
+
end
|
241
|
+
|
242
|
+
SCM_CHAR_TO_RB_MAP = {
|
243
|
+
"*" => "_star",
|
244
|
+
"-" => "_",
|
245
|
+
}
|
246
|
+
|
247
|
+
def compose_method_name(prefix, type_name)
|
248
|
+
converted_name = type_name.gsub(/[*\-]/, SCM_CHAR_TO_RB_MAP)
|
249
|
+
prefix + converted_name
|
250
|
+
end
|
251
|
+
|
252
|
+
# :startdoc:
|
253
|
+
end # end of Phase2Parser
|
254
|
+
end # end of Parser
|
255
|
+
end
|