rouge-lang 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,78 @@
1
+ # encoding: utf-8
2
+ require 'rouge/wrappers'
3
+
4
+ module Rouge::Printer
5
+ class UnknownFormError < StandardError; end
6
+
7
+ def self.print(form, out)
8
+ case form
9
+ when Integer
10
+ out << form.to_s
11
+ when Rouge::Symbol
12
+ if form.ns_s
13
+ out << form.ns_s
14
+ out << "/"
15
+ end
16
+ out << form.name_s
17
+ when Symbol
18
+ out << form.inspect
19
+ when String
20
+ out << form.inspect
21
+ when Array
22
+ out << "["
23
+ form.each.with_index do |e, i|
24
+ out << " " unless i.zero?
25
+ print(e, out)
26
+ end
27
+ out << "]"
28
+ when Rouge::Seq::Empty
29
+ out << "()"
30
+ when Rouge::Seq::Cons
31
+ if form.length == 2 and form[0] == Rouge::Symbol[:quote]
32
+ out << "'"
33
+ print(form[1], out)
34
+ elsif form.length == 2 and form[0] == Rouge::Symbol[:var]
35
+ out << "#'"
36
+ print(form[1], out)
37
+ else
38
+ out << "("
39
+ form.each.with_index do |e, i|
40
+ out << " " unless i.zero?
41
+ print(e, out)
42
+ end
43
+ out << ")"
44
+ end
45
+ when Rouge::Var
46
+ out << "#'#{form.ns}/#{form.name}"
47
+ when Hash
48
+ out << "{"
49
+ form.each.with_index do |kv,i|
50
+ out << ", " unless i.zero?
51
+ print(kv[0], out)
52
+ out << " "
53
+ print(kv[1], out)
54
+ end
55
+ out << "}"
56
+ when NilClass
57
+ out << "nil"
58
+ when TrueClass
59
+ out << "true"
60
+ when FalseClass
61
+ out << "false"
62
+ when Class, Module
63
+ if form.name
64
+ out << "ruby/#{form.name.split('::').join('.')}"
65
+ else
66
+ out << form.inspect
67
+ end
68
+ when Rouge::Builtin
69
+ out << "rouge.builtin/#{form.inner.name}"
70
+ when Regexp
71
+ out << "#\"#{form.source}\""
72
+ else
73
+ out << form.inspect
74
+ end
75
+ end
76
+ end
77
+
78
+ # vim: set sw=2 et cc=80:
@@ -0,0 +1,433 @@
1
+ # encoding: utf-8
2
+ require 'rouge/wrappers'
3
+
4
+ class Rouge::Reader
5
+ class UnexpectedCharacterError < StandardError; end
6
+ class EndOfDataError < StandardError; end
7
+
8
+ attr_accessor :ns
9
+
10
+ @@gensym_counter = 0
11
+
12
+ def initialize(ns, input)
13
+ @ns = ns
14
+ @src = input
15
+ @n = 0
16
+ @gensyms = []
17
+ end
18
+
19
+
20
+ def lex
21
+ r =
22
+ case peek
23
+ when MAYBE_NUMBER
24
+ number
25
+ when /:/
26
+ keyword
27
+ when /"/
28
+ string
29
+ when /\(/
30
+ Rouge::Seq::Cons[*list(')')]
31
+ when /\[/
32
+ list ']'
33
+ when /#/
34
+ dispatch
35
+ when SYMBOL
36
+ # SYMBOL after \[ and #, because it includes both
37
+ symbol_or_number
38
+ when /{/
39
+ map
40
+ when /'/
41
+ quotation
42
+ when /`/
43
+ syntaxquotation
44
+ when /~/
45
+ dequotation
46
+ when /\^/
47
+ metadata
48
+ when /@/
49
+ deref
50
+ when nil
51
+ reader_raise EndOfDataError, "in #lex"
52
+ else
53
+ reader_raise UnexpectedCharacterError, "#{peek.inspect} in #lex"
54
+ end
55
+
56
+ r
57
+ end
58
+
59
+ private
60
+
61
+ def number
62
+ read_number(slurp(MAYBE_NUMBER))
63
+ end
64
+
65
+ def keyword
66
+ begin
67
+ slurp(/:"/)
68
+ @n -= 1
69
+ s = string
70
+ s.intern
71
+ rescue UnexpectedCharacterError
72
+ slurp(/^:[a-zA-Z0-9\-_!\?\*\/]+/)[1..-1].intern
73
+ end
74
+ end
75
+
76
+ def string
77
+ s = ""
78
+ t = consume
79
+ while true
80
+ c = @src[@n]
81
+
82
+ if c.nil?
83
+ reader_raise EndOfDataError, "in string, got: #{s}"
84
+ end
85
+
86
+ @n += 1
87
+
88
+ if c == t
89
+ break
90
+ end
91
+
92
+ if c == ?\\
93
+ c = consume
94
+
95
+ case c
96
+ when nil
97
+ reader_raise EndOfDataError, "in escaped string, got: #{s}"
98
+ when /[abefnrstv]/
99
+ c = {?a => ?\a,
100
+ ?b => ?\b,
101
+ ?e => ?\e,
102
+ ?f => ?\f,
103
+ ?n => ?\n,
104
+ ?r => ?\r,
105
+ ?s => ?\s,
106
+ ?t => ?\t,
107
+ ?v => ?\v}[c]
108
+ else
109
+ # Just leave it be.
110
+ end
111
+ end
112
+
113
+ s += c
114
+ end
115
+ s.freeze
116
+ end
117
+
118
+ def list(ending)
119
+ consume
120
+ r = []
121
+
122
+ while true
123
+ if peek == ending
124
+ break
125
+ end
126
+ r << lex
127
+ end
128
+
129
+ consume
130
+ r.freeze
131
+ end
132
+
133
+ def symbol_or_number
134
+ s = slurp(SYMBOL)
135
+ if (s[0] == ?- or s[0] == ?+) and s[1..-1] =~ NUMBER
136
+ read_number(s)
137
+ else
138
+ Rouge::Symbol[s.intern]
139
+ end
140
+ end
141
+
142
+ def map
143
+ consume
144
+ r = {}
145
+
146
+ while true
147
+ if peek == '}'
148
+ break
149
+ end
150
+ k = lex
151
+ v = lex
152
+ r[k] = v
153
+ end
154
+
155
+ consume
156
+ r.freeze
157
+ end
158
+
159
+ def quotation
160
+ consume
161
+ Rouge::Seq::Cons[Rouge::Symbol[:quote], lex]
162
+ end
163
+
164
+ def syntaxquotation
165
+ consume
166
+ @gensyms.unshift(@@gensym_counter += 1)
167
+ r = dequote lex
168
+ @gensyms.shift
169
+ r
170
+ end
171
+
172
+ def dequotation
173
+ consume
174
+ if peek == ?@
175
+ consume
176
+ Rouge::Splice[lex].freeze
177
+ else
178
+ Rouge::Dequote[lex].freeze
179
+ end
180
+ end
181
+
182
+ def dequote form
183
+ case form
184
+ when Rouge::Seq::Cons, Array
185
+ rest = []
186
+ group = []
187
+ form.each do |f|
188
+ if f.is_a? Rouge::Splice
189
+ if group.length > 0
190
+ rest << Rouge::Seq::Cons[Rouge::Symbol[:list], *group]
191
+ group = []
192
+ end
193
+ rest << f.inner
194
+ else
195
+ group << dequote(f)
196
+ end
197
+ end
198
+
199
+ if group.length > 0
200
+ rest << Rouge::Seq::Cons[Rouge::Symbol[:list], *group]
201
+ end
202
+
203
+ r =
204
+ if rest.length == 1
205
+ rest[0]
206
+ else
207
+ Rouge::Seq::Cons[Rouge::Symbol[:concat], *rest]
208
+ end
209
+
210
+ if form.is_a?(Array)
211
+ Rouge::Seq::Cons[Rouge::Symbol[:apply],
212
+ Rouge::Symbol[:vector],
213
+ r]
214
+ elsif rest.length > 1
215
+ Rouge::Seq::Cons[Rouge::Symbol[:seq], r]
216
+ else
217
+ r
218
+ end
219
+ when Hash
220
+ Hash[form.map {|k,v| [dequote(k), dequote(v)]}]
221
+ when Rouge::Dequote
222
+ form.inner
223
+ when Rouge::Symbol
224
+ if form.ns.nil? and form.name_s =~ /(\#)$/
225
+ Rouge::Seq::Cons[
226
+ Rouge::Symbol[:quote],
227
+ Rouge::Symbol[
228
+ ("#{form.name.to_s.gsub(/(\#)$/, '')}__" \
229
+ "#{@gensyms[0]}__auto__").intern]]
230
+ elsif form.ns or form.name_s =~ /^\./ or %w(& |).include? form.name_s
231
+ Rouge::Seq::Cons[Rouge::Symbol[:quote], form]
232
+ elsif form.ns.nil?
233
+ begin
234
+ var = @ns[form.name]
235
+ Rouge::Seq::Cons[Rouge::Symbol[:quote],
236
+ Rouge::Symbol[var.name]]
237
+ rescue Rouge::Namespace::VarNotFoundError
238
+ Rouge::Seq::Cons[Rouge::Symbol[:quote],
239
+ Rouge::Symbol[:"#{@ns.name}/#{form.name}"]]
240
+ end
241
+ else
242
+ raise "impossible, right?" # XXX: be bothered to ensure this is so
243
+ end
244
+ else
245
+ Rouge::Seq::Cons[Rouge::Symbol[:quote], form]
246
+ end
247
+ end
248
+
249
+ def regexp
250
+ s = ""
251
+ t = '"'
252
+ while true
253
+ c = @src[@n]
254
+
255
+ if c.nil?
256
+ reader_raise EndOfDataError, "in regexp, got: #{s}"
257
+ end
258
+
259
+ @n += 1
260
+
261
+ if c == t
262
+ break
263
+ end
264
+
265
+ if c == ?\\
266
+ c = "\\"
267
+ if peek == ?"
268
+ c << consume
269
+ end
270
+ end
271
+
272
+ s << c
273
+ end
274
+
275
+ Regexp.new(s).freeze
276
+ end
277
+
278
+ def dispatch
279
+ consume
280
+ case peek
281
+ when '('
282
+ body, count = dispatch_rewrite_fn(lex, 0)
283
+ Rouge::Seq::Cons[
284
+ Rouge::Symbol[:fn],
285
+ (1..count).map {|n| Rouge::Symbol[:"%#{n}"]}.freeze,
286
+ body]
287
+ when "'"
288
+ consume
289
+ Rouge::Seq::Cons[Rouge::Symbol[:var], lex]
290
+ when "_"
291
+ consume
292
+ lex
293
+ lex
294
+ when '"'
295
+ consume
296
+ regexp
297
+ else
298
+ reader_raise UnexpectedCharacterError, "#{peek.inspect} in #dispatch"
299
+ end
300
+ end
301
+
302
+ def dispatch_rewrite_fn form, count
303
+ case form
304
+ when Rouge::Seq::Cons, Array
305
+ mapped = form.map do |e|
306
+ e, count = dispatch_rewrite_fn(e, count)
307
+ e
308
+ end.freeze
309
+
310
+ if form.is_a?(Rouge::Seq::Cons)
311
+ [Rouge::Seq::Cons[*mapped], count]
312
+ else
313
+ [mapped, count]
314
+ end
315
+ when Rouge::Symbol
316
+ if form.name == :"%"
317
+ [Rouge::Symbol[:"%1"], [1, count].max]
318
+ elsif form.name.to_s =~ /^%(\d+)$/
319
+ [form, [$1.to_i, count].max]
320
+ else
321
+ [form, count]
322
+ end
323
+ else
324
+ [form, count]
325
+ end
326
+ end
327
+
328
+ def metadata
329
+ consume
330
+ meta = lex
331
+ attach = lex
332
+
333
+ if not attach.class < Rouge::Metadata
334
+ reader_raise ArgumentError,
335
+ "metadata can only be applied to classes mixing in Rouge::Metadata"
336
+ end
337
+
338
+ meta =
339
+ case meta
340
+ when Symbol
341
+ {meta => true}
342
+ when String
343
+ {:tag => meta}
344
+ else
345
+ meta
346
+ end
347
+
348
+ extant = attach.meta
349
+ if extant.nil?
350
+ attach.meta = meta
351
+ else
352
+ attach.meta = extant.merge(meta)
353
+ end
354
+
355
+ attach
356
+ end
357
+
358
+ def deref
359
+ consume
360
+ Rouge::Seq::Cons[Rouge::Symbol[:"rouge.core/deref"], lex]
361
+ end
362
+
363
+ def slurp re
364
+ @src[@n..-1] =~ re
365
+ reader_raise UnexpectedCharacterError, "#{@src[@n]} in #slurp #{re}" if !$&
366
+ @n += $&.length
367
+ $&
368
+ end
369
+
370
+ def peek
371
+ while @src[@n] =~ /[\s,;]/
372
+ if $& == ";"
373
+ while @src[@n] =~ /[^\n]/
374
+ @n += 1
375
+ end
376
+ else
377
+ @n += 1
378
+ end
379
+ end
380
+
381
+ @src[@n]
382
+ end
383
+
384
+ def consume
385
+ c = peek
386
+ @n += 1
387
+ c
388
+ end
389
+
390
+ def reader_raise ex, m
391
+ around =
392
+ "#{@src[[@n - 3, 0].max...[@n, 0].max]}" +
393
+ "#{@src[@n]}" +
394
+ "#{(@src[@n + 1..@n + 3] || "").gsub(/\n.*$/, '')}"
395
+
396
+ line = @src[0...@n].count("\n") + 1
397
+ char = @src[0...@n].reverse.index("\n") || 0 + 1
398
+
399
+ raise ex,
400
+ "around: #{around}\n" +
401
+ " ^\n" +
402
+ "line #{line} char #{char}: #{m}"
403
+ end
404
+
405
+ def read_number s
406
+ if NUMBER.match s
407
+ eval s
408
+ else
409
+ reader_raise UnexpectedCharacterError, "#{s} in #read_number"
410
+ end
411
+ end
412
+
413
+ # Loose expression for a possible numeric literal.
414
+ MAYBE_NUMBER = /^[+-]?\d[\da-fA-FxX\._+-]*/
415
+
416
+ # Ruby integer.
417
+ INT = /\d+(?:_\d+)*/
418
+
419
+ # Strict expression for a numeric literal.
420
+ NUMBER = /
421
+ ^[+-]?
422
+ (?:
423
+ (?:0[xX][\da-fA-F]+) (?# Hexadecimal integer)
424
+ | (?:0[bB][01]+) (?# Binary integer)
425
+ | (?:0\d+) (?# Octal integer)
426
+ | (?:#{INT}(?:(?:\.#{INT})?(?:[eE][+-]?#{INT})?)?) (?# Integers and floats)
427
+ )\z
428
+ /ox
429
+
430
+ SYMBOL = /^(\.\[\])|([a-zA-Z0-9\-_!&\?\*\/\.\+\|=%$<>#]+)/
431
+ end
432
+
433
+ # vim: set sw=2 et cc=80: