rus3 0.2.0 → 0.2.1
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 +8 -0
- data/Gemfile.lock +6 -1
- data/lib/rus3.rb +5 -4
- data/lib/rus3/evaluator/environment.rb +2 -0
- data/lib/rus3/evaluator/scheme_evaluator.rb +7 -12
- data/lib/rus3/evaluator/translator.rb +89 -46
- data/lib/rus3/printer.rb +41 -5
- data/lib/rus3/procedure/arithmetic.rb +45 -0
- data/lib/rus3/procedure/comparison.rb +45 -0
- data/lib/rus3/repl.rb +26 -31
- data/lib/rus3/version.rb +2 -2
- data/rus3.gemspec +4 -7
- metadata +35 -13
- data/lib/rus3/ast.rb +0 -70
- data/lib/rus3/ast/branch_node.rb +0 -412
- data/lib/rus3/ast/error.rb +0 -8
- data/lib/rus3/ast/leaf_node.rb +0 -55
- data/lib/rus3/lexer.rb +0 -104
- data/lib/rus3/parser.rb +0 -87
- data/lib/rus3/parser/scheme_parser.rb +0 -657
- data/lib/rus3/token.rb +0 -35
data/lib/rus3/ast/error.rb
DELETED
data/lib/rus3/ast/leaf_node.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Rus3
|
4
|
-
module AST
|
5
|
-
|
6
|
-
class LeafNode < Node
|
7
|
-
def leaf?
|
8
|
-
true
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class BooleanNode < LeafNode
|
13
|
-
def type
|
14
|
-
:boolean
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
class IdentifierNode < LeafNode
|
19
|
-
def type
|
20
|
-
:identifier
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
class PeculiarIdentifierNode < IdentifierNode
|
25
|
-
def type
|
26
|
-
:peculiar_identifier
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
class CharacterNode < LeafNode
|
31
|
-
def type
|
32
|
-
:character
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
class StringNode < LeafNode
|
37
|
-
def type
|
38
|
-
:string
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
class NumberNode < LeafNode
|
43
|
-
def type
|
44
|
-
:number
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
class DotNode < LeafNode
|
49
|
-
def type
|
50
|
-
:dot
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
end
|
55
|
-
end
|
data/lib/rus3/lexer.rb
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Rus3
|
4
|
-
|
5
|
-
class Lexer < Enumerator
|
6
|
-
|
7
|
-
# Indicates the version of the lexer class
|
8
|
-
LEXER_VERSION = "0.2.0"
|
9
|
-
|
10
|
-
class << self
|
11
|
-
|
12
|
-
def version # :nodoc:
|
13
|
-
"(scheme-lexer :version #{LEXER_VERSION})"
|
14
|
-
end
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
# :stopdoc:
|
19
|
-
|
20
|
-
BOOLEAN = /\A#(f(alse)?|t(rue)?)\Z/
|
21
|
-
STRING = /\A\"[^\"]*\"\Z/
|
22
|
-
|
23
|
-
# idents
|
24
|
-
EXTENDED_CHARS = "!\\$%&\\*\\+\\-\\./:<=>\\?@\\^_~"
|
25
|
-
IDENT_PAT = "[a-zA-Z_][a-zA-Z0-9#{EXTENDED_CHARS}]*"
|
26
|
-
IDENTIFIER = Regexp.new("\\A#{IDENT_PAT}\\Z")
|
27
|
-
|
28
|
-
# operators
|
29
|
-
ARITHMETIC_OPS = /\A[+\-*\/%]\Z/
|
30
|
-
COMPARISON_OPS = /\A([<>]=?|=)\Z/
|
31
|
-
|
32
|
-
# numbers
|
33
|
-
REAL_PAT = "(([1-9][0-9]*)|0)(\.[0-9]+)?"
|
34
|
-
RAT_PAT = "#{REAL_PAT}\\/#{REAL_PAT}"
|
35
|
-
C_REAL_PAT = "(#{REAL_PAT}|#{RAT_PAT})"
|
36
|
-
C_IMAG_PAT = "#{C_REAL_PAT}"
|
37
|
-
COMP_PAT = "#{C_REAL_PAT}(\\+|\\-)#{C_IMAG_PAT}i"
|
38
|
-
|
39
|
-
REAL_NUM = Regexp.new("\\A[+-]?#{REAL_PAT}\\Z")
|
40
|
-
RATIONAL = Regexp.new("\\A[+-]?#{RAT_PAT}\\Z")
|
41
|
-
COMPLEX = Regexp.new("\\A[+-]?#{COMP_PAT}\\Z")
|
42
|
-
PURE_IMAG = Regexp.new("\\A[+-](#{C_IMAG_PAT})?i\\Z")
|
43
|
-
|
44
|
-
# char
|
45
|
-
SINGLE_CHAR_PAT = "."
|
46
|
-
SPACE_PAT = "space"
|
47
|
-
NEWLINE_PAT = "newline"
|
48
|
-
|
49
|
-
CHAR_PREFIX = "\#\\\\"
|
50
|
-
CHAR_PAT = "(#{SINGLE_CHAR_PAT}|#{SPACE_PAT}|#{NEWLINE_PAT})"
|
51
|
-
CHAR = Regexp.new("\\A#{CHAR_PREFIX}#{CHAR_PAT}\\Z")
|
52
|
-
|
53
|
-
# :startdoc:
|
54
|
-
|
55
|
-
class << self
|
56
|
-
|
57
|
-
def new(exp, _ = nil)
|
58
|
-
tokens = tokenize(exp)
|
59
|
-
super(tokens.size) { |y|
|
60
|
-
tokens.each { |tk|
|
61
|
-
y.yield(tk)
|
62
|
-
}
|
63
|
-
}
|
64
|
-
end
|
65
|
-
|
66
|
-
S2R_MAP = { "(" => "[ ", ")" => " ] ", "'" => " ' " } # :nodoc:
|
67
|
-
|
68
|
-
def tokenize(exp)
|
69
|
-
source = exp.gsub(/[()']/, S2R_MAP)
|
70
|
-
|
71
|
-
source.split(" ").map { |literal|
|
72
|
-
case literal
|
73
|
-
when "["
|
74
|
-
Token.new(:lparen, literal)
|
75
|
-
when "]"
|
76
|
-
Token.new(:rparen, literal)
|
77
|
-
when "."
|
78
|
-
Token.new(:dot, literal)
|
79
|
-
when "'"
|
80
|
-
Token.new(:quotation, literal)
|
81
|
-
when "#["
|
82
|
-
Token.new(:vec_lparen, literal)
|
83
|
-
when BOOLEAN
|
84
|
-
Token.new(:boolean, literal)
|
85
|
-
when IDENTIFIER
|
86
|
-
Token.new(:identifier, literal)
|
87
|
-
when CHAR
|
88
|
-
Token.new(:character, literal)
|
89
|
-
when STRING
|
90
|
-
Token.new(:string, literal)
|
91
|
-
when ARITHMETIC_OPS, COMPARISON_OPS
|
92
|
-
Token.new(:op_proc, literal)
|
93
|
-
when REAL_NUM, RATIONAL, COMPLEX, PURE_IMAG
|
94
|
-
Token.new(:number, literal)
|
95
|
-
else
|
96
|
-
Token.new(:illegal, literal)
|
97
|
-
end
|
98
|
-
}
|
99
|
-
end
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
end
|
104
|
-
end
|
data/lib/rus3/parser.rb
DELETED
@@ -1,87 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "readline"
|
4
|
-
|
5
|
-
module Rus3
|
6
|
-
|
7
|
-
module Parser
|
8
|
-
|
9
|
-
# Indicates the version of the parser module.
|
10
|
-
VERSION = "0.2.0"
|
11
|
-
|
12
|
-
# A base class to derived a parser.
|
13
|
-
class Parser
|
14
|
-
|
15
|
-
# Holds a prompt string. It is intended to be set in the REPL
|
16
|
-
# loop.
|
17
|
-
attr_reader :prompt
|
18
|
-
|
19
|
-
# Constructs the version string.
|
20
|
-
|
21
|
-
def version
|
22
|
-
"parser-module :version #{VERSION}"
|
23
|
-
end
|
24
|
-
|
25
|
-
def initialize
|
26
|
-
@prompt = ""
|
27
|
-
end
|
28
|
-
|
29
|
-
def prompt=(str)
|
30
|
-
index = str.index(">")
|
31
|
-
class_name = self.class.name.split("::")[-1]
|
32
|
-
parser_name = class_name.delete_suffix("Parser").downcase
|
33
|
-
@prompt = str[0...index] + "(#{parser_name})" + str[index..-1]
|
34
|
-
end
|
35
|
-
|
36
|
-
# Reads program source from the passed IO instance, then returns
|
37
|
-
# the AST (abstract syntax tree). Returns nil when reaches to
|
38
|
-
# EOF.
|
39
|
-
|
40
|
-
def read(io = STDIN)
|
41
|
-
program_source = nil
|
42
|
-
if io == STDIN
|
43
|
-
program_source = Readline::readline(@prompt, true)
|
44
|
-
else
|
45
|
-
program_source = io.readlines(chomp: true).join(" ")
|
46
|
-
end
|
47
|
-
program_source.nil? ? nil : parse(program_source)
|
48
|
-
end
|
49
|
-
|
50
|
-
protected
|
51
|
-
|
52
|
-
# Parses the passed program source, then returns the AST to be
|
53
|
-
# evaluated by an evaluator. How to process depends on each
|
54
|
-
# derived parser class.
|
55
|
-
|
56
|
-
def parse(program_source)
|
57
|
-
nil
|
58
|
-
end
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
require_relative "parser/scheme_parser"
|
63
|
-
|
64
|
-
# :stopdoc:
|
65
|
-
|
66
|
-
class PassthroughParser < Parser
|
67
|
-
PARSER_VERSION = "0.2.0"
|
68
|
-
|
69
|
-
def version
|
70
|
-
vmsg = "(pass-through-parser version: #{PARSER_VERSION})"
|
71
|
-
vmsg += " #{Lexer.version}"
|
72
|
-
super + " (#{vmsg})"
|
73
|
-
end
|
74
|
-
|
75
|
-
def parse(program_source)
|
76
|
-
[Lexer.new(program_source).map {|tk| tk.to_s}]
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
80
|
-
|
81
|
-
# :startdoc:
|
82
|
-
|
83
|
-
DEFAULT_PARSER = SchemeParser # :nodoc:
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
end
|
@@ -1,657 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Rus3
|
4
|
-
|
5
|
-
module Parser
|
6
|
-
|
7
|
-
# A simple parser to read a s-expression for Scheme.
|
8
|
-
class SchemeParser < Parser
|
9
|
-
|
10
|
-
# Indicates the version of the parser class
|
11
|
-
PARSER_VERSION = "0.2.0"
|
12
|
-
|
13
|
-
# Constructs the version string.
|
14
|
-
|
15
|
-
def version
|
16
|
-
vmsg = "(scheme-parser :version #{PARSER_VERSION})"
|
17
|
-
vmsg += " #{Lexer.version}"
|
18
|
-
super + " (#{vmsg})"
|
19
|
-
end
|
20
|
-
|
21
|
-
def initialize
|
22
|
-
super
|
23
|
-
@lexer = nil
|
24
|
-
@curr_token = @peek_token = nil
|
25
|
-
end
|
26
|
-
|
27
|
-
# Parses a portion of or the whole program source then returns a
|
28
|
-
# AST structure.
|
29
|
-
|
30
|
-
def parse(program_source)
|
31
|
-
@lexer = Lexer.new(program_source)
|
32
|
-
parse_program
|
33
|
-
end
|
34
|
-
|
35
|
-
# :stopdoc:
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def next_token
|
40
|
-
if @peek_token
|
41
|
-
@curr_token = @peek_token
|
42
|
-
@peek_token = nil
|
43
|
-
else
|
44
|
-
@curr_token = @lexer.next
|
45
|
-
end
|
46
|
-
@curr_token
|
47
|
-
end
|
48
|
-
|
49
|
-
def peek_token
|
50
|
-
if @peek_token.nil?
|
51
|
-
@peek_token = @lexer.next
|
52
|
-
end
|
53
|
-
@peek_token
|
54
|
-
end
|
55
|
-
|
56
|
-
def current_token
|
57
|
-
@curr_token
|
58
|
-
end
|
59
|
-
|
60
|
-
def push_back_token(token)
|
61
|
-
@peek_token = token
|
62
|
-
end
|
63
|
-
|
64
|
-
# <program> -> <expression>*
|
65
|
-
def parse_program
|
66
|
-
program = Rus3::AST.instantiate(:program)
|
67
|
-
Kernel.loop {
|
68
|
-
node = parse_expression
|
69
|
-
program << node
|
70
|
-
}
|
71
|
-
program
|
72
|
-
end
|
73
|
-
|
74
|
-
TOKEN_START_DELIMITERS = [ # :nodoc:
|
75
|
-
:lparen, # list: ( ... )
|
76
|
-
:vec_lparen, # vector: #( ... )
|
77
|
-
:bytevec_lparen, # bytevector: #u8( ... )
|
78
|
-
:quotation, # quotation: '<something>
|
79
|
-
:backquote, # quasiquote: `<something>
|
80
|
-
:comma, # used in quasiquote
|
81
|
-
:comma_at, # used in quasiquote
|
82
|
-
:comment_lparen, # comment start
|
83
|
-
]
|
84
|
-
|
85
|
-
def start_delimiter?(token)
|
86
|
-
TOKEN_START_DELIMITERS.include?(token.type)
|
87
|
-
end
|
88
|
-
|
89
|
-
# <expression> -> <simple expression> | <compound expression>
|
90
|
-
# <compound expression> -> <start delimiter> <expression>* <end delimiter>
|
91
|
-
# <start delimiter> -> <lparen> | <vec lparen> | <bytevec lparen> |
|
92
|
-
# <quotation> |
|
93
|
-
# <backquote> | <comma> | <comma at> |
|
94
|
-
# <comment lparen>
|
95
|
-
# <end delimier> -> <rparen> | <comment_rparen>
|
96
|
-
def parse_expression
|
97
|
-
if start_delimiter?(peek_token)
|
98
|
-
parse_compound_expression
|
99
|
-
else
|
100
|
-
parse_simple_expression
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
# <simple expression> -> <identifier> | <self evaluating>
|
105
|
-
# <self evaluating> -> <boolean> | <number> | <character> | <string>
|
106
|
-
def parse_simple_expression
|
107
|
-
type, literal = *next_token
|
108
|
-
type = :peculiar_identifier if type == :op_proc
|
109
|
-
Rus3::AST.instantiate(type, literal)
|
110
|
-
end
|
111
|
-
|
112
|
-
def parse_identifier
|
113
|
-
Rus3::AST.instantiate(:identifier, next_token.literal)
|
114
|
-
end
|
115
|
-
|
116
|
-
# <compound expression> -> <quotation> |
|
117
|
-
# <vector> |
|
118
|
-
# <list expression>
|
119
|
-
def parse_compound_expression
|
120
|
-
node = nil
|
121
|
-
token = peek_token
|
122
|
-
case token.type
|
123
|
-
when :vec_lparen
|
124
|
-
node = parse_vector
|
125
|
-
when :lparen
|
126
|
-
node = parse_list_expression
|
127
|
-
when :quotation
|
128
|
-
node = parse_quotation
|
129
|
-
else
|
130
|
-
raise Rus3::SchemeSynaxError, token.to_a
|
131
|
-
end
|
132
|
-
node
|
133
|
-
end
|
134
|
-
|
135
|
-
# <list expression> ->
|
136
|
-
# <procedure call> |
|
137
|
-
# <lambda expression> |
|
138
|
-
# <conditional> |
|
139
|
-
# <assignment> |
|
140
|
-
# <macro use> |
|
141
|
-
# <macro block> |
|
142
|
-
# <definition> |
|
143
|
-
# <derived expression> |
|
144
|
-
# <includer>
|
145
|
-
def parse_list_expression
|
146
|
-
node = nil
|
147
|
-
next_token # read :lparen
|
148
|
-
case peek_token.type
|
149
|
-
when :rparen
|
150
|
-
# an empty list
|
151
|
-
node = Rus3::AST.instantiate(:list)
|
152
|
-
next_token # skip :rparen
|
153
|
-
when :identifier
|
154
|
-
case peek_token.literal
|
155
|
-
when "lambda" # lambda expression
|
156
|
-
node = parse_lambda_expression
|
157
|
-
when "if" # conditional
|
158
|
-
node = parse_conditional
|
159
|
-
when "set!" # assignment
|
160
|
-
node = parse_assignment
|
161
|
-
when "let-syntax", "letrec-syntax" # macro block
|
162
|
-
node = parse_macro_block
|
163
|
-
when "define", "define-syntax", "define-values", "define-record-type", "begin"
|
164
|
-
node = parse_definition
|
165
|
-
else
|
166
|
-
node = parse_derived_expression
|
167
|
-
node = parse_macro_use if node.nil?
|
168
|
-
end
|
169
|
-
end
|
170
|
-
node || parse_procedure_call
|
171
|
-
end
|
172
|
-
|
173
|
-
def parse_macro_use
|
174
|
-
nil
|
175
|
-
end
|
176
|
-
|
177
|
-
# <procedure call> -> ( <operator> <operand>* )
|
178
|
-
def parse_procedure_call
|
179
|
-
proc_call_node = Rus3::AST.instantiate(:procedure_call,
|
180
|
-
current_token.literal)
|
181
|
-
proc_call_node.operator = parse_operator
|
182
|
-
|
183
|
-
Kernel.loop {
|
184
|
-
if peek_token.type == :rparen
|
185
|
-
next_token # skip :rparen
|
186
|
-
break
|
187
|
-
end
|
188
|
-
proc_call_node.add_operand(parse_operand)
|
189
|
-
}
|
190
|
-
proc_call_node
|
191
|
-
end
|
192
|
-
|
193
|
-
# <operator> -> <expression>
|
194
|
-
def parse_operator
|
195
|
-
parse_expression
|
196
|
-
end
|
197
|
-
|
198
|
-
# <operand> -> <expression>
|
199
|
-
def parse_operand
|
200
|
-
parse_expression
|
201
|
-
end
|
202
|
-
|
203
|
-
# <lambda expression> -> ( lambda <formals> <body> )
|
204
|
-
# <sequence> -> <command>* <expression>
|
205
|
-
# <command> -> <expression>
|
206
|
-
# <definition> ... see parse_definition
|
207
|
-
def parse_lambda_expression
|
208
|
-
lambda_node = Rus3::AST.instantiate(:lambda_expression,
|
209
|
-
next_token.literal)
|
210
|
-
lambda_node.formals = parse_formals
|
211
|
-
lambda_node.body = read_body
|
212
|
-
next_token # skip :rparen
|
213
|
-
lambda_node
|
214
|
-
end
|
215
|
-
|
216
|
-
# <formals> -> ( <identifier>* ) | <identifier> |
|
217
|
-
# ( <identifier>+ . <identifier> )
|
218
|
-
def parse_formals
|
219
|
-
token = next_token
|
220
|
-
formals = nil
|
221
|
-
if token.type == :lparen
|
222
|
-
formals = Rus3::AST.instantiate(:list)
|
223
|
-
Kernel.loop {
|
224
|
-
if peek_token.type == :rparen
|
225
|
-
next_token
|
226
|
-
break
|
227
|
-
end
|
228
|
-
formals << Rus3::AST.instantiate(:identifier, next_token.literal)
|
229
|
-
}
|
230
|
-
else
|
231
|
-
formals = Rus3::AST.instantiate(:identifier, token.literal)
|
232
|
-
end
|
233
|
-
formals
|
234
|
-
end
|
235
|
-
|
236
|
-
# <body> -> <definition>* <sequence>
|
237
|
-
def read_body
|
238
|
-
body = []
|
239
|
-
Kernel.loop {
|
240
|
-
break if peek_token.type == :rparen # end of <lambda expression>
|
241
|
-
body << parse_expression
|
242
|
-
}
|
243
|
-
body
|
244
|
-
end
|
245
|
-
|
246
|
-
# <conditional> -> ( if <test> <consequent> <alternamte> )
|
247
|
-
def parse_conditional
|
248
|
-
if_node = Rus3::AST.instantiate(:conditional, next_token.literal)
|
249
|
-
if_node.test = parse_test
|
250
|
-
if_node.consequent = parse_consequent
|
251
|
-
if peek_token.type != :rparen
|
252
|
-
if_node.alternate = parse_alternate
|
253
|
-
end
|
254
|
-
next_token # skip :rparen
|
255
|
-
if_node
|
256
|
-
end
|
257
|
-
|
258
|
-
# <test> -> <expression>
|
259
|
-
def parse_test
|
260
|
-
parse_expression
|
261
|
-
end
|
262
|
-
|
263
|
-
# <consequent> -> <expression>
|
264
|
-
def parse_consequent
|
265
|
-
parse_expression
|
266
|
-
end
|
267
|
-
|
268
|
-
# <alternate> -> <expression> | <empty>
|
269
|
-
# <empty> -> ""
|
270
|
-
def parse_alternate
|
271
|
-
parse_expression
|
272
|
-
end
|
273
|
-
|
274
|
-
# <assignment> -> ( set! <identifier> <expression> )
|
275
|
-
def parse_assignment
|
276
|
-
assignment_node = Rus3::AST.instantiate(:assignment, next_token.literal)
|
277
|
-
assignment_node.identifier = parse_identifier
|
278
|
-
assignment_node.expression = parse_expression
|
279
|
-
next_token # skip :rparen
|
280
|
-
assignment_node
|
281
|
-
end
|
282
|
-
|
283
|
-
def parse_macro_block
|
284
|
-
nil
|
285
|
-
end
|
286
|
-
|
287
|
-
# <definition> -> ( define <identifier> <expression> ) |
|
288
|
-
# ( define ( <identifier> <def formals> ) <body> ) |
|
289
|
-
# <syntax definition> |
|
290
|
-
# ( define-values <formals> <body> ) |
|
291
|
-
# ( define-record-type <identifier>
|
292
|
-
# <constructor> <identifier> <field spec>* ) |
|
293
|
-
# ( begin <definition>* )
|
294
|
-
#
|
295
|
-
# <def formals> -> <identifier>* |
|
296
|
-
# <identifier>* . <identifier>
|
297
|
-
# <constructor> -> ( <identifier> <field name>* )
|
298
|
-
# <field spec> -> ( <field name> <accessor> ) |
|
299
|
-
# ( <field name> <accessor> <mutator> )
|
300
|
-
# <field name> -> <identifier>
|
301
|
-
# <accessor> -> <identifier>
|
302
|
-
# <mutator> -> <identifier>
|
303
|
-
# <syntax definition> -> ( define-syntax <keyword> <transformer spec> )
|
304
|
-
# <transformer spec> -> ...
|
305
|
-
# :
|
306
|
-
def parse_definition
|
307
|
-
case peek_token.literal
|
308
|
-
when "define"
|
309
|
-
parse_identifier_definition
|
310
|
-
when "define-syntax"
|
311
|
-
nil # not implemented yet
|
312
|
-
when "define-values"
|
313
|
-
nil # not implemented yet
|
314
|
-
when "define-record-type"
|
315
|
-
nil # not implemented yet
|
316
|
-
when "begin"
|
317
|
-
nil # not implemented yet
|
318
|
-
else
|
319
|
-
raise Rus3::SchemeSynaxError, token.to_a
|
320
|
-
end
|
321
|
-
end
|
322
|
-
|
323
|
-
# ( define <identifier> <expression> )
|
324
|
-
# ( define ( <identifier> <def formals> ) <body> )
|
325
|
-
#
|
326
|
-
# ( define foo 3 )
|
327
|
-
# ( define bar ( lambda ( x y ) ( + x y )))
|
328
|
-
# ( deifne ( hoge n m ) ( * n m ))
|
329
|
-
|
330
|
-
def parse_identifier_definition
|
331
|
-
token = next_token # define
|
332
|
-
define_node = Rus3::AST.instantiate(:identifier_definition, token.literal)
|
333
|
-
case peek_token.type
|
334
|
-
when :lparen
|
335
|
-
next_token # skip :lparen
|
336
|
-
# procedure name
|
337
|
-
define_node.identifier = parse_identifier
|
338
|
-
|
339
|
-
def_formals = Rus3::AST.instantiate(:list)
|
340
|
-
Kernel.loop {
|
341
|
-
if peek_token.type == :rparen
|
342
|
-
next_token
|
343
|
-
break
|
344
|
-
end
|
345
|
-
def_formals << parse_identifier
|
346
|
-
}
|
347
|
-
|
348
|
-
lambda_node = Rus3::AST.instantiate(:lambda_expression, nil)
|
349
|
-
lambda_node.formals = def_formals
|
350
|
-
lambda_node.body = read_body
|
351
|
-
next_token # skip :rparen
|
352
|
-
|
353
|
-
define_node.expression = lambda_node
|
354
|
-
when :identifier
|
355
|
-
define_node.identifier = parse_identifier
|
356
|
-
define_node.expression = parse_expression
|
357
|
-
next_token
|
358
|
-
else
|
359
|
-
raise Rus3::SchemeSynaxError, current_token.to_a
|
360
|
-
end
|
361
|
-
define_node
|
362
|
-
end
|
363
|
-
|
364
|
-
# <quotation> -> '<datum> | ( quote <datum> )
|
365
|
-
def parse_quotation
|
366
|
-
token = next_token
|
367
|
-
quote_node = Rus3::AST.instantiate(:quotation, token.literal)
|
368
|
-
quote_node << parse_datum
|
369
|
-
quote_node
|
370
|
-
end
|
371
|
-
|
372
|
-
# <vetor> -> #( <datum>* )
|
373
|
-
def parse_vector
|
374
|
-
parse_data_to_rparen
|
375
|
-
end
|
376
|
-
|
377
|
-
def parse_data_to_rparen
|
378
|
-
token = next_token
|
379
|
-
ast_type = nil
|
380
|
-
case token.type
|
381
|
-
when :lparen
|
382
|
-
ast_type = :list
|
383
|
-
when :vec_lparen
|
384
|
-
ast_type = :vector
|
385
|
-
else
|
386
|
-
ast_type = :list
|
387
|
-
end
|
388
|
-
node = Rus3::AST.instantiate(ast_type, nil)
|
389
|
-
raise Rus3::SchemeSyntaxError, token.to_a unless node.branch?
|
390
|
-
Kernel.loop {
|
391
|
-
token = peek_token
|
392
|
-
break if token.type == :rparen
|
393
|
-
node << parse_datum
|
394
|
-
}
|
395
|
-
next_token # skip :rparen
|
396
|
-
node
|
397
|
-
end
|
398
|
-
|
399
|
-
# <datum> -> <simple datum> | <compound datum>
|
400
|
-
def parse_datum
|
401
|
-
if start_delimiter?(peek_token)
|
402
|
-
parse_compound_datum
|
403
|
-
else
|
404
|
-
parse_simple_datum
|
405
|
-
end
|
406
|
-
end
|
407
|
-
|
408
|
-
# <simple datum> -> <boolean> | <number> | <character> |
|
409
|
-
# <string> | <symbol>
|
410
|
-
# <symbol> -> <identifier>
|
411
|
-
#
|
412
|
-
# See `parse_simple_expression`.
|
413
|
-
def parse_simple_datum
|
414
|
-
parse_simple_expression
|
415
|
-
end
|
416
|
-
|
417
|
-
# <compound datum> -> <list> | <vector> | <bytevector> | <abbreviation>
|
418
|
-
# <abbreviation> -> <abbrev prefix> <datum>
|
419
|
-
def parse_compound_datum
|
420
|
-
case peek_token.type
|
421
|
-
when :lparen
|
422
|
-
parse_list
|
423
|
-
when :vec_lparen
|
424
|
-
parse_vector
|
425
|
-
else
|
426
|
-
raise Rus3::SchemeSyntaxError, peek_token.to_a
|
427
|
-
end
|
428
|
-
end
|
429
|
-
|
430
|
-
# <list> -> ( <datum>* ) | ( <datum>+ . <datum> )
|
431
|
-
def parse_list
|
432
|
-
parse_data_to_rparen
|
433
|
-
end
|
434
|
-
|
435
|
-
DERIVED_IDENTIFIERS = [
|
436
|
-
"cond", "case", "and", "or", "when", "unless",
|
437
|
-
"let", "let*", "letrec", "letrec*",
|
438
|
-
"let-values", "let*-values",
|
439
|
-
"begin", "do",
|
440
|
-
"delay", "delay-force",
|
441
|
-
"parameterize",
|
442
|
-
"guard",
|
443
|
-
"case-lambda",
|
444
|
-
]
|
445
|
-
|
446
|
-
# <derived expression> ->
|
447
|
-
# ( cond <cond clause>+ ) |
|
448
|
-
# ( cond <cond cluase>* ( else <sequence> ) ) |
|
449
|
-
# ( case <expression> <case caluse>+ ) |
|
450
|
-
# ( case <expression> <case caluse>* ( else <sequence> ) ) |
|
451
|
-
# ( case <expression> <case caluse>* ( else => <recipient> ) ) |
|
452
|
-
# ( and <test>* ) |
|
453
|
-
# ( or <test>* ) |
|
454
|
-
# ( when <test> <sequence> ) |
|
455
|
-
# ( unless <test> <sequence> ) |
|
456
|
-
# ( let ( <binding spec>* ) <body> ) |
|
457
|
-
# ( let <identifier> ( <binding spec>* ) <body> ) |
|
458
|
-
# ( let* ( <binding spec>* ) <body> ) |
|
459
|
-
# ( letrec ( <binding spec>* ) <body> ) |
|
460
|
-
# ( letrec* ( <binding spec>* ) <body> ) |
|
461
|
-
# ( let-values ( <my binding spec>* ) <body> ) |
|
462
|
-
# ( let*-values ( <my binding spec>* ) <body> ) |
|
463
|
-
# ( begin <sequence> ) |
|
464
|
-
# ( do ( <iteration spec>* ) ( <test> <do result> ) <command>* ) |
|
465
|
-
# ( delay <expression> ) |
|
466
|
-
# ( delay-force <expression> ) |
|
467
|
-
# ( parameterize ( ( <expression> <expression> )* ) <body> ) |
|
468
|
-
# ( guard ( <identifier> <cond clause>* ) <body> ) |
|
469
|
-
# ( case-lambda <case-lambda clause>* ) |
|
470
|
-
# <quasiquotation>
|
471
|
-
def parse_derived_expression
|
472
|
-
node = nil
|
473
|
-
token = next_token
|
474
|
-
if token.type == :identifier
|
475
|
-
if DERIVED_IDENTIFIERS.include?(token.literal)
|
476
|
-
method_name = compose_method_name("parse_", token.literal).intern
|
477
|
-
method = self.method(method_name)
|
478
|
-
node = method.call
|
479
|
-
else
|
480
|
-
node = parse_quasiquotation
|
481
|
-
end
|
482
|
-
end
|
483
|
-
push_back_token(token) if node.nil?
|
484
|
-
node
|
485
|
-
end
|
486
|
-
|
487
|
-
SCM_CHAR_TO_RB_MAP = {
|
488
|
-
"*" => "_star",
|
489
|
-
"-" => "_",
|
490
|
-
}
|
491
|
-
|
492
|
-
def compose_method_name(prefix, type_name)
|
493
|
-
converted_name = type_name.gsub(/[*\-]/, SCM_CHAR_TO_RB_MAP)
|
494
|
-
prefix + converted_name
|
495
|
-
end
|
496
|
-
|
497
|
-
def not_implemented_yet(feature)
|
498
|
-
raise Rus3::NotImplementedYetError, feature
|
499
|
-
end
|
500
|
-
|
501
|
-
# ( cond <cond clause>+ )
|
502
|
-
# ( cond <cond cluase>* ( else <sequence> ) )
|
503
|
-
def parse_cond
|
504
|
-
cond_node = Rus3::AST.instantiate(:cond, current_token.literal)
|
505
|
-
|
506
|
-
Kernel.loop {
|
507
|
-
if peek_token.type == :rparen
|
508
|
-
next_token # skip :rparen
|
509
|
-
break
|
510
|
-
end
|
511
|
-
cond_node.add_clause(parse_cond_clause)
|
512
|
-
}
|
513
|
-
cond_node
|
514
|
-
end
|
515
|
-
|
516
|
-
# <cond cluase> -> ( <test> <sequence> ) |
|
517
|
-
# ( <test> ) |
|
518
|
-
# ( <test> => <recipient> )
|
519
|
-
# <test> -> <expression>
|
520
|
-
# <recipient> -> <expression>
|
521
|
-
# <sequence> -> <command>* <expression>
|
522
|
-
# <command> -> <expression>
|
523
|
-
def parse_cond_clause
|
524
|
-
clause_node = Rus3::AST.instantiate(:cond_clause)
|
525
|
-
next_token # skip :lparen
|
526
|
-
|
527
|
-
clause_node.test = parse_test
|
528
|
-
|
529
|
-
Kernel.loop {
|
530
|
-
if peek_token.type == :rparen
|
531
|
-
next_token
|
532
|
-
break
|
533
|
-
end
|
534
|
-
clause_node.add_expression(parse_expression)
|
535
|
-
}
|
536
|
-
clause_node
|
537
|
-
end
|
538
|
-
|
539
|
-
def prase_test
|
540
|
-
parse_expression
|
541
|
-
end
|
542
|
-
|
543
|
-
def parse_case
|
544
|
-
not_implemented_yet("case")
|
545
|
-
end
|
546
|
-
|
547
|
-
def parse_and
|
548
|
-
not_implemented_yet("and")
|
549
|
-
end
|
550
|
-
|
551
|
-
def parse_or
|
552
|
-
not_implemented_yet("or")
|
553
|
-
end
|
554
|
-
|
555
|
-
def parse_when
|
556
|
-
not_implemented_yet("when")
|
557
|
-
end
|
558
|
-
|
559
|
-
def parse_unless
|
560
|
-
not_implemented_yet("unless")
|
561
|
-
end
|
562
|
-
|
563
|
-
# ( let ( <binding spec>* ) <body> ) |
|
564
|
-
# <bind spec> -> ( <identifier> <expression> )
|
565
|
-
#
|
566
|
-
# `Named let` has not supported yet.
|
567
|
-
# ( let <identifier> ( <binding spec>* ) <body> )
|
568
|
-
def parse_let
|
569
|
-
let_node = Rus3::AST.instantiate(:let, current_token.literal)
|
570
|
-
|
571
|
-
let_node.bind_specs = parse_bind_specs
|
572
|
-
let_node.body = read_body
|
573
|
-
next_token # skip :rparen
|
574
|
-
|
575
|
-
let_node
|
576
|
-
end
|
577
|
-
|
578
|
-
def parse_bind_specs
|
579
|
-
specs_node = Rus3::AST.instantiate(:list)
|
580
|
-
next_token # skip :lparen
|
581
|
-
|
582
|
-
Kernel.loop {
|
583
|
-
if peek_token.type == :rparen
|
584
|
-
next_token # skip :rparen
|
585
|
-
break
|
586
|
-
end
|
587
|
-
specs_node << parse_bind_spec
|
588
|
-
}
|
589
|
-
specs_node
|
590
|
-
end
|
591
|
-
|
592
|
-
def parse_bind_spec
|
593
|
-
spec_node = Rus3::AST::instantiate(:bind_spec)
|
594
|
-
next_token # skip :lpraren
|
595
|
-
spec_node.identifier = parse_identifier
|
596
|
-
spec_node.expression = parse_expression
|
597
|
-
next_token # skip :rparen
|
598
|
-
spec_node
|
599
|
-
end
|
600
|
-
|
601
|
-
def parse_let_star
|
602
|
-
not_implemented_yet("let*")
|
603
|
-
end
|
604
|
-
|
605
|
-
def parse_letrec
|
606
|
-
not_implemented_yet("letrec")
|
607
|
-
end
|
608
|
-
|
609
|
-
def parse_letrec_star
|
610
|
-
not_implemented_yet("letrec*")
|
611
|
-
end
|
612
|
-
|
613
|
-
def parse_let_values
|
614
|
-
not_implemented_yet("let-values")
|
615
|
-
end
|
616
|
-
|
617
|
-
def parse_let_star_values
|
618
|
-
not_implemented_yet("let*-values")
|
619
|
-
end
|
620
|
-
|
621
|
-
def parse_begin
|
622
|
-
not_implemented_yet("begin")
|
623
|
-
end
|
624
|
-
|
625
|
-
def parse_do
|
626
|
-
not_implemented_yet("do")
|
627
|
-
end
|
628
|
-
|
629
|
-
def parse_delay
|
630
|
-
not_implemented_yet("delay")
|
631
|
-
end
|
632
|
-
|
633
|
-
def parse_delay_force
|
634
|
-
not_implemented_yet("delay-force")
|
635
|
-
end
|
636
|
-
|
637
|
-
def parse_parameterize
|
638
|
-
not_implemented_yet("parameterize")
|
639
|
-
end
|
640
|
-
|
641
|
-
def parse_guard
|
642
|
-
not_implemented_yet("guard")
|
643
|
-
end
|
644
|
-
|
645
|
-
def parse_case_lambda
|
646
|
-
not_implemented_yet("case-lambda")
|
647
|
-
end
|
648
|
-
|
649
|
-
def parse_quasiquotation
|
650
|
-
nil
|
651
|
-
end
|
652
|
-
|
653
|
-
# :startdoc:
|
654
|
-
|
655
|
-
end
|
656
|
-
end
|
657
|
-
end
|