rus3 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -1
- data/Gemfile.lock +1 -1
- data/README.md +14 -6
- data/exe/rus3 +26 -2
- data/lib/rus3.rb +3 -0
- data/lib/rus3/ast.rb +70 -0
- data/lib/rus3/ast/branch_node.rb +412 -0
- data/lib/rus3/ast/error.rb +8 -0
- data/lib/rus3/ast/leaf_node.rb +55 -0
- data/lib/rus3/error.rb +15 -1
- data/lib/rus3/evaluator.rb +38 -54
- data/lib/rus3/evaluator/environment.rb +25 -0
- data/lib/rus3/evaluator/scheme_evaluator.rb +79 -0
- data/lib/rus3/evaluator/translator.rb +337 -0
- data/lib/rus3/{parser/lexer.rb → lexer.rb} +22 -52
- data/lib/rus3/parser.rb +39 -23
- data/lib/rus3/parser/scheme_parser.rb +595 -306
- data/lib/rus3/procedure/char.rb +21 -17
- data/lib/rus3/procedure/control.rb +28 -24
- data/lib/rus3/procedure/list.rb +210 -207
- data/lib/rus3/procedure/predicate.rb +267 -264
- data/lib/rus3/procedure/utils.rb +20 -16
- data/lib/rus3/procedure/vector.rb +68 -65
- data/lib/rus3/procedure/write.rb +107 -103
- data/lib/rus3/repl.rb +57 -47
- data/lib/rus3/token.rb +35 -0
- data/lib/rus3/version.rb +2 -2
- metadata +11 -3
@@ -1,48 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rus3
|
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.
|
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
|
-
|
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
|
-
|
37
|
-
IDENT_PAT = "[a-zA-Z_][
|
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[<>]
|
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
|
-
|
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(:
|
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.
|
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
|
-
|
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
30
|
-
# when reaches to
|
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
|
-
|
34
|
-
|
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
|
40
|
-
#
|
41
|
-
#
|
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(
|
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.
|
67
|
+
PARSER_VERSION = "0.2.0"
|
57
68
|
|
58
69
|
def version
|
59
|
-
|
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
|
3
|
+
module Rus3
|
4
4
|
|
5
|
-
|
6
|
-
class SchemeParser < Parser
|
5
|
+
module Parser
|
7
6
|
|
8
|
-
#
|
9
|
-
|
7
|
+
# A simple parser to read a s-expression for Scheme.
|
8
|
+
class SchemeParser < Parser
|
10
9
|
|
11
|
-
|
10
|
+
# Indicates the version of the parser class
|
11
|
+
PARSER_VERSION = "0.2.0"
|
12
12
|
|
13
|
-
|
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
|
-
|
20
|
-
|
21
|
-
|
15
|
+
def version
|
16
|
+
vmsg = "(scheme-parser :version #{PARSER_VERSION})"
|
17
|
+
vmsg += " #{Lexer.version}"
|
18
|
+
super + " (#{vmsg})"
|
19
|
+
end
|
22
20
|
|
23
|
-
|
21
|
+
def initialize
|
22
|
+
super
|
23
|
+
@lexer = nil
|
24
|
+
@curr_token = @peek_token = nil
|
25
|
+
end
|
24
26
|
|
25
|
-
|
26
|
-
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
131
|
-
r_exps = []
|
132
|
-
loop { r_exps << parse_s_exp(lexer) }
|
133
|
-
r_exps.join("\n")
|
134
|
-
end
|
35
|
+
# :stopdoc:
|
135
36
|
|
136
|
-
|
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
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
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
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
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
|
-
|
178
|
-
|
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
|
-
|
181
|
-
|
182
|
-
|
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
|
-
|
231
|
+
formals = Rus3::AST.instantiate(:identifier, token.literal)
|
185
232
|
end
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
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
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
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
|
-
|
198
|
-
when :
|
199
|
-
|
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
|
-
|
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
|
-
|
208
|
-
|
209
|
-
|
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
|
-
|
212
|
-
|
213
|
-
|
214
|
-
end
|
497
|
+
def not_implemented_yet(feature)
|
498
|
+
raise Rus3::NotImplementedYetError, feature
|
499
|
+
end
|
215
500
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
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
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
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
|
-
|
237
|
-
|
238
|
-
|
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
|
-
|
254
|
-
|
543
|
+
def parse_case
|
544
|
+
not_implemented_yet("case")
|
545
|
+
end
|
255
546
|
|
256
|
-
|
257
|
-
|
547
|
+
def parse_and
|
548
|
+
not_implemented_yet("and")
|
549
|
+
end
|
258
550
|
|
259
|
-
|
260
|
-
|
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
|
-
|
274
|
-
|
555
|
+
def parse_when
|
556
|
+
not_implemented_yet("when")
|
557
|
+
end
|
275
558
|
|
276
|
-
|
277
|
-
|
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
|
-
|
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
|
-
|
285
|
-
|
571
|
+
let_node.bind_specs = parse_bind_specs
|
572
|
+
let_node.body = read_body
|
573
|
+
next_token # skip :rparen
|
286
574
|
|
287
|
-
|
288
|
-
|
289
|
-
body = i_exp[2..-1]
|
575
|
+
let_node
|
576
|
+
end
|
290
577
|
|
291
|
-
|
292
|
-
|
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
|
-
|
296
|
-
|
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
|
-
|
299
|
-
|
300
|
-
|
301
|
-
alternate = translate(i_exp[3])
|
601
|
+
def parse_let_star
|
602
|
+
not_implemented_yet("let*")
|
603
|
+
end
|
302
604
|
|
303
|
-
|
304
|
-
|
305
|
-
|
605
|
+
def parse_letrec
|
606
|
+
not_implemented_yet("letrec")
|
607
|
+
end
|
306
608
|
|
307
|
-
|
308
|
-
|
609
|
+
def parse_letrec_star
|
610
|
+
not_implemented_yet("letrec*")
|
611
|
+
end
|
309
612
|
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
"#{ident} = #{value}"
|
314
|
-
end
|
613
|
+
def parse_let_values
|
614
|
+
not_implemented_yet("let-values")
|
615
|
+
end
|
315
616
|
|
316
|
-
|
317
|
-
|
318
|
-
|
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
|
-
|
323
|
-
|
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
|
-
|
331
|
-
|
332
|
-
|
333
|
-
r_exp = "if #{test}; #{exp}"
|
625
|
+
def parse_do
|
626
|
+
not_implemented_yet("do")
|
627
|
+
end
|
334
628
|
|
335
|
-
|
336
|
-
|
337
|
-
|
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
|
-
|
347
|
-
|
633
|
+
def parse_delay_force
|
634
|
+
not_implemented_yet("delay-force")
|
635
|
+
end
|
348
636
|
|
349
|
-
|
350
|
-
|
351
|
-
|
637
|
+
def parse_parameterize
|
638
|
+
not_implemented_yet("parameterize")
|
639
|
+
end
|
352
640
|
|
353
|
-
|
354
|
-
|
641
|
+
def parse_guard
|
642
|
+
not_implemented_yet("guard")
|
643
|
+
end
|
355
644
|
|
356
|
-
|
357
|
-
|
645
|
+
def parse_case_lambda
|
646
|
+
not_implemented_yet("case-lambda")
|
647
|
+
end
|
358
648
|
|
359
|
-
|
360
|
-
|
361
|
-
|
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
|