rouge-lang 0.0.1

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