rubasteme 0.1.1 → 0.1.6
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/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 +29 -582
- 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 = 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
|