nydp 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +58 -0
- data/Rakefile +1 -0
- data/bin/nydp +5 -0
- data/bin/nydp-tests +5 -0
- data/lib/lisp/boot.nydp +219 -0
- data/lib/lisp/test-runner.nydp +39 -0
- data/lib/lisp/tests/foundation-test.nydp +28 -0
- data/lib/nydp.rb +143 -0
- data/lib/nydp/assignment.rb +40 -0
- data/lib/nydp/builtin.rb +8 -0
- data/lib/nydp/builtin/apply.rb +16 -0
- data/lib/nydp/builtin/car.rb +5 -0
- data/lib/nydp/builtin/cdr.rb +5 -0
- data/lib/nydp/builtin/cdr_set.rb +8 -0
- data/lib/nydp/builtin/comment.rb +5 -0
- data/lib/nydp/builtin/cons.rb +16 -0
- data/lib/nydp/builtin/divide.rb +13 -0
- data/lib/nydp/builtin/error.rb +6 -0
- data/lib/nydp/builtin/eval.rb +14 -0
- data/lib/nydp/builtin/greater_than.rb +10 -0
- data/lib/nydp/builtin/hash.rb +30 -0
- data/lib/nydp/builtin/inspect.rb +5 -0
- data/lib/nydp/builtin/is_equal.rb +5 -0
- data/lib/nydp/builtin/less_than.rb +10 -0
- data/lib/nydp/builtin/millisecs.rb +7 -0
- data/lib/nydp/builtin/minus.rb +13 -0
- data/lib/nydp/builtin/plus.rb +28 -0
- data/lib/nydp/builtin/pre_compile.rb +5 -0
- data/lib/nydp/builtin/puts.rb +7 -0
- data/lib/nydp/builtin/quit.rb +5 -0
- data/lib/nydp/builtin/random_string.rb +11 -0
- data/lib/nydp/builtin/times.rb +13 -0
- data/lib/nydp/builtin/to_string.rb +12 -0
- data/lib/nydp/builtin/to_sym.rb +21 -0
- data/lib/nydp/builtin/vm_info.rb +13 -0
- data/lib/nydp/closure.rb +17 -0
- data/lib/nydp/compiler.rb +49 -0
- data/lib/nydp/cond.rb +56 -0
- data/lib/nydp/context_symbol.rb +22 -0
- data/lib/nydp/error.rb +4 -0
- data/lib/nydp/function_invocation.rb +52 -0
- data/lib/nydp/helper.rb +32 -0
- data/lib/nydp/interpreted_function.rb +79 -0
- data/lib/nydp/lexical_context.rb +38 -0
- data/lib/nydp/literal.rb +40 -0
- data/lib/nydp/pair.rb +112 -0
- data/lib/nydp/parser.rb +123 -0
- data/lib/nydp/string_atom.rb +24 -0
- data/lib/nydp/string_token.rb +21 -0
- data/lib/nydp/symbol.rb +47 -0
- data/lib/nydp/symbol_lookup.rb +43 -0
- data/lib/nydp/tokeniser.rb +80 -0
- data/lib/nydp/truth.rb +37 -0
- data/lib/nydp/version.rb +3 -0
- data/lib/nydp/vm.rb +76 -0
- data/nydp.gemspec +27 -0
- data/spec/boot_spec.rb +119 -0
- data/spec/embedded_spec.rb +106 -0
- data/spec/nypd_spec.rb +127 -0
- data/spec/pair_spec.rb +102 -0
- data/spec/parser_spec.rb +191 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/symbol_spec.rb +32 -0
- metadata +176 -0
data/lib/nydp/cond.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Nydp
|
2
|
+
class ExecuteConditionalInstruction
|
3
|
+
extend Helper
|
4
|
+
attr_reader :when_true, :when_false
|
5
|
+
|
6
|
+
def initialize when_true, when_false
|
7
|
+
@when_true, @when_false = when_true, when_false
|
8
|
+
end
|
9
|
+
|
10
|
+
def execute vm
|
11
|
+
arg = vm.pop_arg
|
12
|
+
truth = !Nydp.NIL.is?(arg)
|
13
|
+
vm.push_instructions (truth ? when_true : when_false), vm.peek_context
|
14
|
+
end
|
15
|
+
|
16
|
+
def inspect
|
17
|
+
"when_true:#{when_true.inspect}:when_false:#{when_false.inspect}"
|
18
|
+
end
|
19
|
+
def to_s
|
20
|
+
"#{when_true.car.to_s} #{when_false.car.to_s}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Cond
|
25
|
+
extend Helper
|
26
|
+
include Helper
|
27
|
+
attr_reader :condition, :conditional
|
28
|
+
|
29
|
+
def initialize cond, when_true, when_false
|
30
|
+
@condition, @conditional = cond, cons(ExecuteConditionalInstruction.new(when_true, when_false))
|
31
|
+
end
|
32
|
+
|
33
|
+
def execute vm
|
34
|
+
vm.push_instructions conditional, vm.peek_context
|
35
|
+
vm.push_instructions condition, vm.peek_context
|
36
|
+
end
|
37
|
+
|
38
|
+
def inspect
|
39
|
+
"cond:#{condition.inspect}:#{conditional.inspect}"
|
40
|
+
end
|
41
|
+
def to_s
|
42
|
+
"(cond #{condition.car.to_s} #{conditional.to_s})"
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.build expressions, bindings
|
46
|
+
if expressions.is_a? Nydp::Pair
|
47
|
+
cond = cons Compiler.compile expressions.car, bindings
|
48
|
+
when_true = cons Compiler.compile expressions.cdr.car, bindings
|
49
|
+
when_false = cons Compiler.compile expressions.cdr.cdr.car, bindings
|
50
|
+
new(cond, when_true, when_false)
|
51
|
+
else
|
52
|
+
raise "can't compile Cond: #{expr.inspect}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Nydp
|
2
|
+
class ContextSymbol
|
3
|
+
attr_accessor :depth, :name
|
4
|
+
|
5
|
+
def initialize depth, name
|
6
|
+
@depth, @name = depth, name
|
7
|
+
end
|
8
|
+
|
9
|
+
def value context
|
10
|
+
context.nth(depth).at(name)
|
11
|
+
end
|
12
|
+
|
13
|
+
def assign value, context
|
14
|
+
context.nth(depth).set(name, value)
|
15
|
+
end
|
16
|
+
|
17
|
+
def inspect; to_s; end
|
18
|
+
def to_s
|
19
|
+
"[#{depth}]#{name}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/nydp/error.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Nydp
|
2
|
+
class InvokeFunctionInstruction
|
3
|
+
def initialize arg_count, source_expression
|
4
|
+
@source_expression = source_expression
|
5
|
+
@arg_count = arg_count
|
6
|
+
end
|
7
|
+
|
8
|
+
def execute vm
|
9
|
+
args = vm.pop_args @arg_count
|
10
|
+
args.car.invoke vm, args.cdr
|
11
|
+
rescue Exception => e
|
12
|
+
puts "failed to execute fn #{args.inspect}"
|
13
|
+
puts "source was #{source}"
|
14
|
+
puts "function was #{args.car.inspect}"
|
15
|
+
vm.error e
|
16
|
+
end
|
17
|
+
|
18
|
+
def inspect
|
19
|
+
"#{self.class.name}:#{source}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def source
|
23
|
+
@source_expression
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s
|
27
|
+
source
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class FunctionInvocation
|
32
|
+
extend Helper
|
33
|
+
|
34
|
+
def self.build expression, bindings
|
35
|
+
new cons(InvokeFunctionInstruction.new(expression.size, expression)), Compiler.compile_each(expression, bindings), expression
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize function_instruction, argument_instructions, source
|
39
|
+
@function_instruction, @argument_instructions, @source = function_instruction, argument_instructions, source
|
40
|
+
end
|
41
|
+
|
42
|
+
def execute vm
|
43
|
+
vm.push_instructions @function_instruction, vm.peek_context
|
44
|
+
vm.push_instructions @argument_instructions, vm.peek_context
|
45
|
+
end
|
46
|
+
|
47
|
+
def inspect; "#function_invocation:#{to_s}"; end
|
48
|
+
def to_s
|
49
|
+
@source.to_s
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/nydp/helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Nydp
|
2
|
+
module Helper
|
3
|
+
def sym? expr, name
|
4
|
+
expr.is_a?(Nydp::Symbol) && (expr.is? name)
|
5
|
+
end
|
6
|
+
|
7
|
+
def pair? expr
|
8
|
+
expr.is_a?(Nydp::Pair)
|
9
|
+
end
|
10
|
+
|
11
|
+
def cons a, b=Nydp.NIL
|
12
|
+
Nydp::Pair.new a, b
|
13
|
+
end
|
14
|
+
|
15
|
+
def list *args
|
16
|
+
Nydp::Pair.from_list args
|
17
|
+
end
|
18
|
+
|
19
|
+
def sym name, ns
|
20
|
+
Nydp::Symbol.mk name, ns
|
21
|
+
end
|
22
|
+
|
23
|
+
def literal? expr
|
24
|
+
case expr
|
25
|
+
when String, Float, Integer, Fixnum, Nydp.NIL, Nydp::Symbol, Nydp::StringAtom, Nydp::Truth, Nydp::Nil
|
26
|
+
true
|
27
|
+
else
|
28
|
+
false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'nydp/lexical_context'
|
2
|
+
require 'nydp/closure'
|
3
|
+
|
4
|
+
module Nydp
|
5
|
+
class PopArg
|
6
|
+
def self.execute vm
|
7
|
+
vm.pop_arg
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.to_s
|
11
|
+
""
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.inspect
|
15
|
+
"#pop_arg"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class InterpretedFunction
|
20
|
+
include Helper
|
21
|
+
extend Helper
|
22
|
+
|
23
|
+
attr_accessor :arg_names, :body
|
24
|
+
|
25
|
+
def invoke vm, parent_context, arg_values
|
26
|
+
lc = LexicalContext.new parent_context
|
27
|
+
setup_context lc, arg_names, arg_values
|
28
|
+
vm.push_instructions self.body, lc
|
29
|
+
end
|
30
|
+
|
31
|
+
def setup_context context, names, values
|
32
|
+
if pair? names
|
33
|
+
context.set names.car, values.car
|
34
|
+
setup_context context, names.cdr, values.cdr
|
35
|
+
elsif Nydp.NIL.isnt? names
|
36
|
+
context.set names, values
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.build arg_list, body, bindings
|
41
|
+
my_params = { }
|
42
|
+
index_parameters arg_list, my_params
|
43
|
+
ifn = Nydp::InterpretedFunction.new
|
44
|
+
ifn.arg_names = arg_list
|
45
|
+
ifn.body = compile_body body, cons(my_params, bindings), []
|
46
|
+
ifn
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.compile_body body_forms, bindings, instructions
|
50
|
+
instructions << Nydp::Compiler.compile(body_forms.car, bindings)
|
51
|
+
|
52
|
+
rest = body_forms.cdr
|
53
|
+
if Nydp.NIL.is? rest
|
54
|
+
return Pair.from_list(instructions)
|
55
|
+
else
|
56
|
+
instructions << PopArg
|
57
|
+
compile_body rest, bindings, instructions
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.index_parameters arg_list, hsh
|
62
|
+
if pair? arg_list
|
63
|
+
index_parameters arg_list.car, hsh
|
64
|
+
index_parameters arg_list.cdr, hsh
|
65
|
+
elsif Nydp.NIL.isnt? arg_list
|
66
|
+
hsh[arg_list] = hsh.size
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def execute vm
|
71
|
+
vm.push_arg Closure.new(self, vm.peek_context)
|
72
|
+
end
|
73
|
+
|
74
|
+
def inspect; to_s; end
|
75
|
+
def to_s
|
76
|
+
"(fn #{arg_names.to_s} #{body.map { |b| b.to_s}.join(' ')})"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Nydp::LexicalContext
|
2
|
+
attr_reader :values, :parent
|
3
|
+
|
4
|
+
def initialize parent
|
5
|
+
@parent = parent
|
6
|
+
@values = { }
|
7
|
+
end
|
8
|
+
|
9
|
+
def nth n
|
10
|
+
case n
|
11
|
+
when 0
|
12
|
+
self
|
13
|
+
when -1
|
14
|
+
raise "wrong nesting level"
|
15
|
+
else
|
16
|
+
parent.nth(n - 1)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def at name
|
21
|
+
values[name]
|
22
|
+
end
|
23
|
+
|
24
|
+
def set name, value
|
25
|
+
values[name] = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s_with_indent str
|
29
|
+
me = @values.map { |k, v|
|
30
|
+
[str, k, "=>", v].join ' '
|
31
|
+
}.join "\n"
|
32
|
+
me + (parent ? parent.to_s_with_indent(" #{str}") : '')
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
to_s_with_indent ''
|
37
|
+
end
|
38
|
+
end
|
data/lib/nydp/literal.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Nydp
|
2
|
+
class Literal
|
3
|
+
attr_reader :expression
|
4
|
+
|
5
|
+
def initialize expression
|
6
|
+
@expression = expression
|
7
|
+
end
|
8
|
+
|
9
|
+
def lisp_apply
|
10
|
+
expression
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.build expression, bindings
|
14
|
+
new expression
|
15
|
+
end
|
16
|
+
|
17
|
+
def execute vm
|
18
|
+
vm.push_arg expression
|
19
|
+
end
|
20
|
+
|
21
|
+
def inspect; @expression.inspect; end
|
22
|
+
def to_s ; @expression.to_s ; end
|
23
|
+
|
24
|
+
def coerce _
|
25
|
+
[_, expression]
|
26
|
+
end
|
27
|
+
|
28
|
+
def > other
|
29
|
+
other < expression
|
30
|
+
end
|
31
|
+
|
32
|
+
def < other
|
33
|
+
other > expression
|
34
|
+
end
|
35
|
+
|
36
|
+
def == other
|
37
|
+
other.is_a?(Literal) && (self.expression == other.expression)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/nydp/pair.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
class Nydp::Pair
|
2
|
+
include Nydp::Helper, Enumerable
|
3
|
+
extend Nydp::Helper
|
4
|
+
|
5
|
+
attr_accessor :car, :cdr
|
6
|
+
|
7
|
+
def initialize car, cdr
|
8
|
+
@car, @cdr = car, cdr
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.mk a, b
|
12
|
+
new a, b
|
13
|
+
end
|
14
|
+
|
15
|
+
def caar; car.car; end
|
16
|
+
def cadr; cdr.car; end
|
17
|
+
def cdar; car.cdr; end
|
18
|
+
def cddr; cdr.cdr; end
|
19
|
+
|
20
|
+
def self.parse_list list
|
21
|
+
if sym? list.slice(-2), "."
|
22
|
+
from_list(list[0...-2], list.slice(-1))
|
23
|
+
else
|
24
|
+
from_list list
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.from_list list, last=Nydp.NIL, n=0
|
29
|
+
if n >= list.size
|
30
|
+
last
|
31
|
+
else
|
32
|
+
mk list[n], from_list(list, last, n+1)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def copy
|
37
|
+
cons(car, cdr.copy)
|
38
|
+
end
|
39
|
+
|
40
|
+
def + other
|
41
|
+
copy.append other
|
42
|
+
end
|
43
|
+
|
44
|
+
def == other
|
45
|
+
(other.respond_to? :car) && (self.car == other.car) && (self.cdr == other.cdr)
|
46
|
+
end
|
47
|
+
|
48
|
+
def size
|
49
|
+
1 + (cdr.is_a?(Nydp::Pair) ? cdr.size : 0)
|
50
|
+
end
|
51
|
+
|
52
|
+
def each &block
|
53
|
+
yield car
|
54
|
+
cdr.each(&block) unless Nydp.NIL.is?(cdr)
|
55
|
+
end
|
56
|
+
|
57
|
+
def inspect
|
58
|
+
"(#{inspect_rest})"
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_s
|
62
|
+
if car.is_a?(Nydp::Symbol) && car.is?(:quote)
|
63
|
+
if Nydp.NIL.is? cdr.cdr
|
64
|
+
"'#{cdr.car.to_s}"
|
65
|
+
else
|
66
|
+
"'#{cdr.to_s}"
|
67
|
+
end
|
68
|
+
else
|
69
|
+
"(#{to_s_rest})"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_s_rest
|
74
|
+
cdr_s = if cdr.is_a?(self.class)
|
75
|
+
cdr.to_s_rest
|
76
|
+
elsif Nydp.NIL.is? cdr
|
77
|
+
nil
|
78
|
+
else
|
79
|
+
". #{cdr.to_s}"
|
80
|
+
end
|
81
|
+
|
82
|
+
[car.to_s, cdr_s].compact.join " "
|
83
|
+
end
|
84
|
+
|
85
|
+
def inspect_rest
|
86
|
+
cdr_s = if cdr.is_a?(self.class)
|
87
|
+
cdr.inspect_rest
|
88
|
+
elsif cdr == Nydp.NIL
|
89
|
+
nil
|
90
|
+
else
|
91
|
+
". #{cdr.inspect}"
|
92
|
+
end
|
93
|
+
|
94
|
+
[car.inspect, cdr_s].compact.join " "
|
95
|
+
end
|
96
|
+
|
97
|
+
def append pair
|
98
|
+
if Nydp.NIL.is? self.cdr
|
99
|
+
self.cdr = pair
|
100
|
+
elsif pair? self.cdr
|
101
|
+
self.cdr.append pair
|
102
|
+
else
|
103
|
+
raise "can't append #{pair} to list #{self} : cdr is #{self.cdr.inspect}"
|
104
|
+
end
|
105
|
+
self
|
106
|
+
end
|
107
|
+
|
108
|
+
def repush instructions, _
|
109
|
+
instructions.push self
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
data/lib/nydp/parser.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
module Nydp
|
2
|
+
class Parser
|
3
|
+
attr_accessor :ns
|
4
|
+
|
5
|
+
def initialize ns
|
6
|
+
@ns = ns
|
7
|
+
end
|
8
|
+
|
9
|
+
def sym name
|
10
|
+
Nydp::Symbol.mk name.to_sym, ns
|
11
|
+
end
|
12
|
+
|
13
|
+
def read_list token_stream, termination_token
|
14
|
+
list = []
|
15
|
+
token = token_stream.next_token
|
16
|
+
while token != nil && token.first != termination_token
|
17
|
+
list << next_form(token, token_stream)
|
18
|
+
token = token_stream.next_token
|
19
|
+
end
|
20
|
+
Pair.parse_list list
|
21
|
+
end
|
22
|
+
|
23
|
+
def prefix_list prefix, list
|
24
|
+
case prefix
|
25
|
+
when "'"
|
26
|
+
Pair.from_list [sym(:quote), list]
|
27
|
+
when "`"
|
28
|
+
Pair.from_list [sym(:quasiquote), list]
|
29
|
+
when ","
|
30
|
+
Pair.from_list [sym(:unquote), list]
|
31
|
+
when ",@"
|
32
|
+
Pair.from_list [sym(:"unquote-splicing"), list]
|
33
|
+
else
|
34
|
+
list
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def split_sym syms, pfx
|
39
|
+
return Pair.from_list [pfx] + syms.map { |s| parse_symbol s }
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse_symbol txt
|
43
|
+
case txt
|
44
|
+
when /^'(.+)$/
|
45
|
+
Pair.from_list [sym(:quote), parse_symbol($1)]
|
46
|
+
when /^`(.+)$/
|
47
|
+
Pair.from_list [sym(:quasiquote), parse_symbol($1)]
|
48
|
+
when /^,@(.+)$/
|
49
|
+
Pair.from_list [sym(:"unquote-splicing"), parse_symbol($1)]
|
50
|
+
when /^,(.+)$/
|
51
|
+
Pair.from_list [sym(:unquote), parse_symbol($1)]
|
52
|
+
else
|
53
|
+
syms = txt.to_s.split /\./
|
54
|
+
return split_sym syms, sym(:"dot-syntax") if syms.length > 1
|
55
|
+
|
56
|
+
syms = txt.split /::/
|
57
|
+
return split_sym syms, sym(:"colon-colon-syntax") if syms.length > 1
|
58
|
+
|
59
|
+
syms = txt.split /:/
|
60
|
+
return split_sym syms, sym(:"colon-syntax") if syms.length > 1
|
61
|
+
|
62
|
+
syms = txt.split /->/
|
63
|
+
return split_sym syms, sym(:"arrow-syntax") if syms.length > 1
|
64
|
+
|
65
|
+
syms = txt.split(/=>/)
|
66
|
+
return split_sym syms, sym(:"rocket-syntax") if syms.length > 1
|
67
|
+
|
68
|
+
sym txt
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def close_delimiter_for opener
|
73
|
+
case opener
|
74
|
+
when '"'
|
75
|
+
/"/
|
76
|
+
when /.*{$/
|
77
|
+
/}/
|
78
|
+
when /<<(.+)$/
|
79
|
+
Regexp.new $1
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def next_form token, token_stream
|
84
|
+
return nil if token.nil?
|
85
|
+
case token.first
|
86
|
+
when :embed_suffix
|
87
|
+
Nydp.NIL
|
88
|
+
when :string_open_delim
|
89
|
+
string token_stream, token.last, close_delimiter_for(token.last)
|
90
|
+
when :left_paren
|
91
|
+
prefix_list token[1], read_list(token_stream, :right_paren)
|
92
|
+
when :symbol
|
93
|
+
parse_symbol token.last
|
94
|
+
when :comment
|
95
|
+
Pair.from_list [sym(:comment), token.last]
|
96
|
+
else
|
97
|
+
token.last
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def expression token_stream
|
102
|
+
next_form token_stream.next_token, token_stream
|
103
|
+
end
|
104
|
+
|
105
|
+
def string token_stream, open_delimiter, close_delimiter
|
106
|
+
fragments = [sym(:"string-pieces")]
|
107
|
+
string_token = token_stream.next_string_fragment(open_delimiter, close_delimiter)
|
108
|
+
fragments << string_token
|
109
|
+
while !(string_token.is_a? StringFragmentCloseToken)
|
110
|
+
fragments << expression(token_stream)
|
111
|
+
string_token = token_stream.next_string_fragment('', close_delimiter)
|
112
|
+
fragments << string_token
|
113
|
+
end
|
114
|
+
|
115
|
+
if fragments.size == 2
|
116
|
+
tok = fragments[1]
|
117
|
+
return Nydp::StringAtom.new tok.string, tok
|
118
|
+
else
|
119
|
+
return Pair.from_list fragments
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|