rus3 0.1.2 → 0.2.0

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.
@@ -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