rus3 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,48 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Rus3::Parser
3
+ module Rus3
4
4
 
5
5
  class Lexer < Enumerator
6
6
 
7
7
  # Indicates the version of the lexer class
8
- LEXER_VERSION = "0.1.1"
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
9
17
 
10
18
  # :stopdoc:
11
19
 
12
- TYPES = [
13
- # delimiters
14
- :lparen,
15
- :rparen,
16
- :vec_lparen,
17
- # value types
18
- :boolean,
19
- :ident,
20
- :char,
21
- :string,
22
- :number,
23
- # operators
24
- :op_proc,
25
- # keywords
26
- :if,
27
- :define,
28
- # control
29
- :illegal,
30
- ]
31
-
32
- BOOLEAN = /\A#(f|t)\Z/
20
+ BOOLEAN = /\A#(f(alse)?|t(rue)?)\Z/
33
21
  STRING = /\A\"[^\"]*\"\Z/
34
22
 
35
23
  # idents
36
- EXTENDED = "\\->"
37
- IDENT_PAT = "[a-zA-Z_][\\w?!#{EXTENDED}]*"
24
+ EXTENDED_CHARS = "!\\$%&\\*\\+\\-\\./:<=>\\?@\\^_~"
25
+ IDENT_PAT = "[a-zA-Z_][a-zA-Z0-9#{EXTENDED_CHARS}]*"
38
26
  IDENTIFIER = Regexp.new("\\A#{IDENT_PAT}\\Z")
39
27
 
40
- EXTENDED_REGEXP = Regexp.new("[#{EXTENDED}]")
41
- EXTENDED_MAP = { "-" => "_", ">" => "to_"}
42
-
43
28
  # operators
44
29
  ARITHMETIC_OPS = /\A[+\-*\/%]\Z/
45
- COMPARISON_OPS = /\A[<>]=?\Z/
30
+ COMPARISON_OPS = /\A([<>]=?|=)\Z/
46
31
 
47
32
  # numbers
48
33
  REAL_PAT = "(([1-9][0-9]*)|0)(\.[0-9]+)?"
@@ -65,20 +50,8 @@ module Rus3::Parser
65
50
  CHAR_PAT = "(#{SINGLE_CHAR_PAT}|#{SPACE_PAT}|#{NEWLINE_PAT})"
66
51
  CHAR = Regexp.new("\\A#{CHAR_PREFIX}#{CHAR_PAT}\\Z")
67
52
 
68
- KEYWORDS = {
69
- "LAMBDA" => :lambda,
70
- "IF" => :if,
71
- "SET!" => :set!,
72
- "DEFINE" => :define,
73
- "COND" => :cond,
74
- "LET" => :let,
75
- "ELSE" => :else, # may use with :cond
76
- }
77
-
78
53
  # :startdoc:
79
54
 
80
- Token = Struct.new(:type, :literal) # :nodoc:
81
-
82
55
  class << self
83
56
 
84
57
  def new(exp, _ = nil)
@@ -90,10 +63,10 @@ module Rus3::Parser
90
63
  }
91
64
  end
92
65
 
93
- S2R_MAP = { "(" => "[ ", ")" => " ]" } # :nodoc:
66
+ S2R_MAP = { "(" => "[ ", ")" => " ] ", "'" => " ' " } # :nodoc:
94
67
 
95
68
  def tokenize(exp)
96
- source = exp.gsub(/[()]/, S2R_MAP)
69
+ source = exp.gsub(/[()']/, S2R_MAP)
97
70
 
98
71
  source.split(" ").map { |literal|
99
72
  case literal
@@ -101,23 +74,20 @@ module Rus3::Parser
101
74
  Token.new(:lparen, literal)
102
75
  when "]"
103
76
  Token.new(:rparen, literal)
77
+ when "."
78
+ Token.new(:dot, literal)
79
+ when "'"
80
+ Token.new(:quotation, literal)
104
81
  when "#["
105
82
  Token.new(:vec_lparen, literal)
106
83
  when BOOLEAN
107
84
  Token.new(:boolean, literal)
108
85
  when IDENTIFIER
109
- key = literal.upcase
110
- if KEYWORDS.keys.include?(key)
111
- Token.new(KEYWORDS[key], literal)
112
- else
113
- Token.new(:ident, literal.gsub(EXTENDED_REGEXP, EXTENDED_MAP))
114
- end
86
+ Token.new(:identifier, literal)
115
87
  when CHAR
116
- Token.new(:char, literal)
88
+ Token.new(:character, literal)
117
89
  when STRING
118
90
  Token.new(:string, literal)
119
- when "="
120
- Token.new(:op_proc, "==")
121
91
  when ARITHMETIC_OPS, COMPARISON_OPS
122
92
  Token.new(:op_proc, literal)
123
93
  when REAL_NUM, RATIONAL, COMPLEX, PURE_IMAG
data/lib/rus3/parser.rb CHANGED
@@ -1,46 +1,59 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "readline"
4
+
3
5
  module Rus3
4
6
 
5
7
  module Parser
6
- require "readline"
7
- require_relative "parser/lexer"
8
8
 
9
9
  # Indicates the version of the parser module.
10
- VERSION = "0.1.0"
10
+ VERSION = "0.2.0"
11
11
 
12
12
  # A base class to derived a parser.
13
13
  class Parser
14
14
 
15
15
  # Holds a prompt string. It is intended to be set in the REPL
16
16
  # loop.
17
- attr_accessor :prompt
17
+ attr_reader :prompt
18
+
19
+ # Constructs the version string.
20
+
21
+ def version
22
+ "parser-module :version #{VERSION}"
23
+ end
18
24
 
19
25
  def initialize
20
26
  @prompt = ""
21
27
  end
22
28
 
23
- # Constructs the version string.
24
-
25
- def version
26
- "Parser version #{VERSION}"
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]
27
34
  end
28
35
 
29
- # Reads an expression from the passed IO instance. Returns nil
30
- # when reaches to EOF.
36
+ # Reads program source from the passed IO instance, then returns
37
+ # the AST (abstract syntax tree). Returns nil when reaches to
38
+ # EOF.
31
39
 
32
40
  def read(io = STDIN)
33
- exp = Readline::readline(@prompt, true)
34
- exp.nil? ? nil : parse(exp)
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)
35
48
  end
36
49
 
37
50
  protected
38
51
 
39
- # Parses the passed expression, then returns the processed
40
- # expression to be evaluated by an evaluator. How to process
41
- # depends on each derived parser class.
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.
42
55
 
43
- def parse(exp)
56
+ def parse(program_source)
44
57
  nil
45
58
  end
46
59
 
@@ -48,24 +61,27 @@ module Rus3
48
61
 
49
62
  require_relative "parser/scheme_parser"
50
63
 
51
- DEFAULT_PARSER = SchemeParser # :nodoc:
52
-
53
64
  # :stopdoc:
54
65
 
55
66
  class PassthroughParser < Parser
56
- PARSER_VERSION = "0.1.0"
67
+ PARSER_VERSION = "0.2.0"
57
68
 
58
69
  def version
59
- super + " (Pass Through Parser version: #{PARSER_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}]
60
77
  end
61
- end
62
78
 
63
- def parse(exp)
64
- exp
65
79
  end
66
80
 
67
81
  # :startdoc:
68
82
 
83
+ DEFAULT_PARSER = SchemeParser # :nodoc:
84
+
69
85
  end
70
86
 
71
87
  end
@@ -1,368 +1,657 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Rus3::Parser
3
+ module Rus3
4
4
 
5
- # A simple parser to read a s-expression for Scheme.
6
- class SchemeParser < Parser
5
+ module Parser
7
6
 
8
- # Indicates the version of the parser class
9
- PARSER_VERSION = "0.1.1"
7
+ # A simple parser to read a s-expression for Scheme.
8
+ class SchemeParser < Parser
10
9
 
11
- # Constructs the version string.
10
+ # Indicates the version of the parser class
11
+ PARSER_VERSION = "0.2.0"
12
12
 
13
- def version
14
- vmsg = "(scheme-parser-version . #{PARSER_VERSION})"
15
- vmsg += " (scheme-lexer-version . #{Lexer::LEXER_VERSION})"
16
- super + " (#{vmsg})"
17
- end
13
+ # Constructs the version string.
18
14
 
19
- def initialize
20
- super
21
- end
15
+ def version
16
+ vmsg = "(scheme-parser :version #{PARSER_VERSION})"
17
+ vmsg += " #{Lexer.version}"
18
+ super + " (#{vmsg})"
19
+ end
22
20
 
23
- # Set the prompt which includes "scheme" label.
21
+ def initialize
22
+ super
23
+ @lexer = nil
24
+ @curr_token = @peek_token = nil
25
+ end
24
26
 
25
- def prompt=(str)
26
- index = str.index(">")
27
- @prompt = str[0...index] + "(scheme)" + str[index..-1]
28
- end
27
+ # Parses a portion of or the whole program source then returns a
28
+ # AST structure.
29
29
 
30
- # Parses a s-expression then translates it to a expression for Ruby.
31
- #
32
- # Converts a s-expression (scheme-expression or just S expression)
33
- # to an i-expression (intermediate-expression), then translate an
34
- # i-expression into a r-expression (ruby-expression). An
35
- # i-expression is represented with an Array object in Ruby. A
36
- # r-expression is a String object which could be directly
37
- # evaluated by `Kernel.eval`.
38
- #
39
- # Supported S-expression type:
40
- #
41
- # - primitive expression (s_exp -> r_exp)
42
- # - empty list
43
- # - "()" -> "[]"
44
- #
45
- # - variable reference
46
- # - identifier (symbol) -> "foo"
47
- #
48
- # - literal expression
49
- # - boolean: #f or #t -> `false` or `true`
50
- # - string -> "hoge", "bogo", ...
51
- # - number -> 1.23, Rational(4, 5), Complex(6, 7), ...
52
- #
53
- # - procedure call (s_exp -> i_exp -> r_exp)
54
- # - (+ (* 3 4) (/ 5 6)) ... s_exp
55
- # -> ["add", ["mult", "3", "4"],
56
- # ["div", "5", "6"]] ... i_exp
57
- # -> "add(mul(3, 4), div(5, 6))" ... r_exp
58
- #
59
- # - ((lambda (x) (+ x x)) 4) ... s_exp
60
- # -> [["lambda", ["x"], ["add", "x", "x"]], 4] ... i_exp
61
- # -> "lambda { |x| add(x, x) }.call(4)" ... r_exp
62
- #
63
- # - procedure (s_exp -> i_exp -> r_exp)
64
- # - (lambda (x) (+ x x)) ... s_exp
65
- # -> ["lambda", ["x"], ["add", "x", "x"]] ... i_exp
66
- # -> "lambda { |x| add(x, x) }" ... r_exp
67
- #
68
- # - conditionals (s_exp -> i_exp -> r_exp)
69
- # - (if (= n 0) 1 (* n (- n 1))) ... s_exp
70
- # -> ["if", ["eqv?", "n", "0"],
71
- # "1" ["mul", "n", ["subtract", "n", "1"]]] ... i_exp
72
- # -> "if eqv?(n, 0);
73
- # 1;
74
- # else;
75
- # mul(n, subtract(n, 1));
76
- # end" ... r_exp
77
- #
78
- # - assignment (s_exp -> i_exp -> r_exp)
79
- # - (set! x 2) ... s_exp
80
- # -> ["set!", "x", "2"] ... i_exp
81
- # -> "x = 2" ... r_exp
82
- #
83
- # - define procedure (s_exp -> i_exp -> r_exp)
84
- # - (define (fact n) (if (= n 0) 1 (* n (fact (- n 1))))) ... s_exp
85
- # -> ["define", ["fact", "n"],
86
- # ["if", ["eqv?", "n", "0"], "1",
87
- # ["mul", "n", ["fact", ["subtract", "n", "1"]]]]] ... i_exp
88
- # -> "def fact(n);
89
- # if n == 0;
90
- # 1;
91
- # else;
92
- # n * fact((n - 1));
93
- # end" ... r_exp
94
- #
95
- # - derived expression
96
- # - conditionals (s_exp -> i_exp -> r_exp)
97
- # - (cond ((> 3 2) "greater")
98
- # ((< 3 2) "less")
99
- # (else "equal")) ... s_exp
100
- # -> ["cond", [[["gt?", "3", "2"], "\"greater\""],
101
- # [["lt?", "3", "2"], "\"less\""],
102
- # ["else", "\"equal\""]]] ... i_exp
103
- # -> "if gt?(3,2);
104
- # 'greater';
105
- # elsif lt?(3,2);
106
- # 'less';
107
- # else;
108
- # 'equal';
109
- # end" ... r_exp
110
- #
111
- # - building construct (s_exp -> i_exp -> r_exp)
112
- # - (let ((x 2) (y 3))
113
- # (* x y)) ... s_exp
114
- # -> ["let", [["x", "2"], ["y", "3"]],
115
- # ["mul", "x", "y"]] ... i_exp
116
- # -> "lambda { |x, y| mul(x, y) }.call(2, 3)" ... r_exp
117
- #
118
- # - vector (s_exp -> r_exp)
119
- # - #(1 2 #(3 4) 5)
120
- # -> "vector(1, 2, vector(3, 4), 5)"
121
- #
122
- # - list (s_exp -> r_exp)
123
- # - (1 2 3 (4 5) (6 7 8) 9 0)
124
- # -> "[1, 2, 3, [4, 5], [6, 7, 8], 9, 0]"
125
-
126
- def parse(s_exp)
127
- parse_tokens(Lexer.new(s_exp))
128
- end
30
+ def parse(program_source)
31
+ @lexer = Lexer.new(program_source)
32
+ parse_program
33
+ end
129
34
 
130
- def parse_tokens(lexer) # :nodoc:
131
- r_exps = []
132
- loop { r_exps << parse_s_exp(lexer) }
133
- r_exps.join("\n")
134
- end
35
+ # :stopdoc:
135
36
 
136
- def parse_s_exp(lexer)
137
- r_exp = nil
138
- token = lexer.next
139
- case token.type
140
- when :lparen
141
- i_exp = parse_compound(lexer)
142
- r_exp = translate(i_exp)
143
- when :vec_lparen
144
- r_exp = parse_vector(lexer)
145
- else
146
- r_exp = parse_primitive(token)
147
- end
148
- r_exp
149
- end
37
+ private
150
38
 
151
- def parse_primitive(token)
152
- r_exp = nil
153
- case token.type
154
- when *Lexer::KEYWORDS.values
155
- r_exp = translate_ident(token.literal)
156
- when :string
157
- r_exp = token.literal
158
- when :ident, :boolean, :char, :number, :op_proc
159
- trans_method_name = "translate_#{token.type}".intern
160
- r_exp = self.send(trans_method_name, token.literal)
161
- else
162
- raise Rus3::SchemeSyntaxError, token.literal
163
- end
164
- r_exp
165
- end
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
166
48
 
167
- def parse_vector(lexer)
168
- r_exp = "vector("
169
- Kernel.loop {
170
- token = lexer.peek
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
171
122
  case token.type
172
- when :lparen
173
- lexer.next
174
- i_exp = parse_compound(lexer)
175
- r_exp += translate(i_exp)
176
123
  when :vec_lparen
177
- lexer.next
178
- r_exp += parse_vector(lexer)
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
179
149
  when :rparen
180
- lexer.next
181
- r_exp = r_exp.sub(/,\s*\Z/, "") + ")"
182
- break
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
+ }
183
230
  else
184
- r_exp += parse_s_exp(lexer)
231
+ formals = Rus3::AST.instantiate(:identifier, token.literal)
185
232
  end
186
- r_exp += ", "
187
- }
188
- r_exp
189
- 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
190
322
 
191
- def parse_compound(lexer)
192
- i_exp = []
193
- Kernel.loop {
194
- token = lexer.next
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
195
380
  case token.type
196
381
  when :lparen
197
- i_exp << parse_compound(lexer)
198
- when :rparen
199
- break
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
200
425
  else
201
- i_exp << parse_primitive(token)
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
202
482
  end
483
+ push_back_token(token) if node.nil?
484
+ node
485
+ end
486
+
487
+ SCM_CHAR_TO_RB_MAP = {
488
+ "*" => "_star",
489
+ "-" => "_",
203
490
  }
204
- i_exp
205
- end
206
491
 
207
- def translate_ident(s_exp_literal)
208
- "#{s_exp_literal}"
209
- end
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
210
496
 
211
- def translate_boolean(s_exp_literal)
212
- # literal == "#f" or #t"
213
- (s_exp_literal[1] == "f") ? "false" : "true"
214
- end
497
+ def not_implemented_yet(feature)
498
+ raise Rus3::NotImplementedYetError, feature
499
+ end
215
500
 
216
- def translate_char(s_exp_literal)
217
- c = s_exp_literal[2..-1]
218
- case c
219
- when "space"
220
- c = " "
221
- when "newline"
222
- c = "\n"
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
223
514
  end
224
- "Char.new(\"#{c}\")"
225
- end
226
515
 
227
- def translate_number(s_exp_literal)
228
- if s_exp_literal.include?("/") # rational?
229
- denominator, numerator = s_exp_literal.split("/").map{|s| Kernel.eval(s)}
230
- "Rational(#{denominator}, #{numerator})"
231
- else
232
- Kernel.eval(s_exp_literal).to_s
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
233
537
  end
234
- end
235
538
 
236
- OP_PROCS = {
237
- "+" => "add",
238
- "-" => "subtract",
239
- "*" => "mul",
240
- "/" => "div",
241
- "%" => "mod",
242
- "<" => "lt?",
243
- "<=" => "le?",
244
- ">" => "gt?",
245
- ">=" => "ge?",
246
- "==" => "eqv?",
247
- }
248
-
249
- def translate_op_proc(s_exp_literal)
250
- OP_PROCS[s_exp_literal]
251
- end
539
+ def prase_test
540
+ parse_expression
541
+ end
252
542
 
253
- def translate(i_exp)
254
- r_exp = nil
543
+ def parse_case
544
+ not_implemented_yet("case")
545
+ end
255
546
 
256
- if i_exp.instance_of?(Array)
257
- return "[]" if i_exp.empty? # an empty list
547
+ def parse_and
548
+ not_implemented_yet("and")
549
+ end
258
550
 
259
- case i_exp[0]
260
- when "lambda", "if", "set!", "define", "cond", "let"
261
- keyword = i_exp[0]
262
- trans_method_name = "translate_#{keyword}".intern
263
- r_exp = self.send(trans_method_name, i_exp)
264
- else # procedure call
265
- r_exp = translate_proc_call(i_exp)
266
- end
267
- else
268
- r_exp = i_exp
551
+ def parse_or
552
+ not_implemented_yet("or")
269
553
  end
270
- r_exp
271
- end
272
554
 
273
- def translate_proc_call(i_exp)
274
- proc = i_exp[0]
555
+ def parse_when
556
+ not_implemented_yet("when")
557
+ end
275
558
 
276
- if proc.instance_of?(Array)
277
- raise Rus3::SchemeSyntaxError, i_exp if i_exp[0][0] != "lambda"
278
- lambda_proc = translate_lambda(proc)
279
- proc = "#{lambda_proc}.call"
559
+ def parse_unless
560
+ not_implemented_yet("unless")
280
561
  end
281
562
 
282
- args = i_exp[1..-1].map {|e| translate(e) }
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)
283
570
 
284
- "#{proc}(#{args.join(', ')})"
285
- end
571
+ let_node.bind_specs = parse_bind_specs
572
+ let_node.body = read_body
573
+ next_token # skip :rparen
286
574
 
287
- def translate_lambda(i_exp)
288
- formals = i_exp[1]
289
- body = i_exp[2..-1]
575
+ let_node
576
+ end
290
577
 
291
- if body.instance_of?(Array)
292
- body = translate_body(body)
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
293
590
  end
294
591
 
295
- "lambda {|#{formals.join(', ')}| #{body}}"
296
- end
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
297
600
 
298
- def translate_if(i_exp)
299
- test = translate(i_exp[1])
300
- consequent = translate(i_exp[2])
301
- alternate = translate(i_exp[3])
601
+ def parse_let_star
602
+ not_implemented_yet("let*")
603
+ end
302
604
 
303
- if_exp = "if #{test}; #{consequent}"
304
- if_exp += "; else; #{alternate}" if alternate
305
- if_exp += "; end"
605
+ def parse_letrec
606
+ not_implemented_yet("letrec")
607
+ end
306
608
 
307
- if_exp
308
- end
609
+ def parse_letrec_star
610
+ not_implemented_yet("letrec*")
611
+ end
309
612
 
310
- def translate_set!(i_exp)
311
- ident = i_exp[1]
312
- value = translate(i_exp[2])
313
- "#{ident} = #{value}"
314
- end
613
+ def parse_let_values
614
+ not_implemented_yet("let-values")
615
+ end
315
616
 
316
- def translate_define(i_exp)
317
- if i_exp[1].instance_of?(Array)
318
- name = i_exp[1][0]
319
- params = i_exp[1][1..-1]
320
- body = translate_body(i_exp[2..-1])
617
+ def parse_let_star_values
618
+ not_implemented_yet("let*-values")
619
+ end
321
620
 
322
- "def #{name}(#{params.join(', ')}); #{body}; end"
323
- else
324
- ident = i_exp[1]
325
- value = translate(i_exp[2])
326
- "#{ident} = #{value}"
621
+ def parse_begin
622
+ not_implemented_yet("begin")
327
623
  end
328
- end
329
624
 
330
- def translate_cond(i_exp)
331
- test = translate(i_exp[1][0])
332
- exp = translate(i_exp[1][1])
333
- r_exp = "if #{test}; #{exp}"
625
+ def parse_do
626
+ not_implemented_yet("do")
627
+ end
334
628
 
335
- i_exp[2..-1].each { |clause|
336
- exp = translate(clause[1])
337
- if clause[0] == "else"
338
- r_exp += "; else; #{exp}"
339
- else
340
- test = translate(clause[0])
341
- r_exp += "; elsif #{test}; #{exp}"
342
- end
343
- }
344
- r_exp += "; end"
629
+ def parse_delay
630
+ not_implemented_yet("delay")
631
+ end
345
632
 
346
- r_exp
347
- end
633
+ def parse_delay_force
634
+ not_implemented_yet("delay-force")
635
+ end
348
636
 
349
- def translate_let(i_exp)
350
- bindings = i_exp[1].to_h
351
- body = translate(i_exp[2])
637
+ def parse_parameterize
638
+ not_implemented_yet("parameterize")
639
+ end
352
640
 
353
- params = bindings.keys.join(", ")
354
- args = bindings.values.map{|e| translate(e)}.join(", ")
641
+ def parse_guard
642
+ not_implemented_yet("guard")
643
+ end
355
644
 
356
- "lambda {|#{params}| #{body}}.call(#{args})"
357
- end
645
+ def parse_case_lambda
646
+ not_implemented_yet("case-lambda")
647
+ end
358
648
 
359
- def translate_body(i_exps)
360
- r_exps = []
361
- i_exps.map { |i_exp|
362
- r_exps << translate(i_exp)
363
- }
364
- r_exps.join(";")
365
- end
649
+ def parse_quasiquotation
650
+ nil
651
+ end
366
652
 
653
+ # :startdoc:
654
+
655
+ end
367
656
  end
368
657
  end