comparison vendor/plugins/coderay-0.9.2/lib/coderay/scanners/scheme.rb @ 0:513646585e45

* Import Redmine trunk SVN rev 3859
author Chris Cannam
date Fri, 23 Jul 2010 15:52:44 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:513646585e45
1 module CodeRay
2 module Scanners
3
4 # Scheme scanner for CodeRay (by closure).
5 # Thanks to murphy for putting CodeRay into public.
6 class Scheme < Scanner
7
8 # TODO: function defs
9 # TODO: built-in functions
10
11 register_for :scheme
12 file_extension 'scm'
13
14 CORE_FORMS = %w[
15 lambda let let* letrec syntax-case define-syntax let-syntax
16 letrec-syntax begin define quote if or and cond case do delay
17 quasiquote set! cons force call-with-current-continuation call/cc
18 ]
19
20 IDENT_KIND = CaseIgnoringWordList.new(:ident).
21 add(CORE_FORMS, :reserved)
22
23 #IDENTIFIER_INITIAL = /[a-z!@\$%&\*\/\:<=>\?~_\^]/i
24 #IDENTIFIER_SUBSEQUENT = /#{IDENTIFIER_INITIAL}|\d|\.|\+|-/
25 #IDENTIFIER = /#{IDENTIFIER_INITIAL}#{IDENTIFIER_SUBSEQUENT}*|\+|-|\.{3}/
26 IDENTIFIER = /[a-zA-Z!@$%&*\/:<=>?~_^][\w!@$%&*\/:<=>?~^.+\-]*|[+-]|\.\.\./
27 DIGIT = /\d/
28 DIGIT10 = DIGIT
29 DIGIT16 = /[0-9a-f]/i
30 DIGIT8 = /[0-7]/
31 DIGIT2 = /[01]/
32 RADIX16 = /\#x/i
33 RADIX8 = /\#o/i
34 RADIX2 = /\#b/i
35 RADIX10 = /\#d/i
36 EXACTNESS = /#i|#e/i
37 SIGN = /[\+-]?/
38 EXP_MARK = /[esfdl]/i
39 EXP = /#{EXP_MARK}#{SIGN}#{DIGIT}+/
40 SUFFIX = /#{EXP}?/
41 PREFIX10 = /#{RADIX10}?#{EXACTNESS}?|#{EXACTNESS}?#{RADIX10}?/
42 PREFIX16 = /#{RADIX16}#{EXACTNESS}?|#{EXACTNESS}?#{RADIX16}/
43 PREFIX8 = /#{RADIX8}#{EXACTNESS}?|#{EXACTNESS}?#{RADIX8}/
44 PREFIX2 = /#{RADIX2}#{EXACTNESS}?|#{EXACTNESS}?#{RADIX2}/
45 UINT10 = /#{DIGIT10}+#*/
46 UINT16 = /#{DIGIT16}+#*/
47 UINT8 = /#{DIGIT8}+#*/
48 UINT2 = /#{DIGIT2}+#*/
49 DECIMAL = /#{DIGIT10}+#+\.#*#{SUFFIX}|#{DIGIT10}+\.#{DIGIT10}*#*#{SUFFIX}|\.#{DIGIT10}+#*#{SUFFIX}|#{UINT10}#{EXP}/
50 UREAL10 = /#{UINT10}\/#{UINT10}|#{DECIMAL}|#{UINT10}/
51 UREAL16 = /#{UINT16}\/#{UINT16}|#{UINT16}/
52 UREAL8 = /#{UINT8}\/#{UINT8}|#{UINT8}/
53 UREAL2 = /#{UINT2}\/#{UINT2}|#{UINT2}/
54 REAL10 = /#{SIGN}#{UREAL10}/
55 REAL16 = /#{SIGN}#{UREAL16}/
56 REAL8 = /#{SIGN}#{UREAL8}/
57 REAL2 = /#{SIGN}#{UREAL2}/
58 IMAG10 = /i|#{UREAL10}i/
59 IMAG16 = /i|#{UREAL16}i/
60 IMAG8 = /i|#{UREAL8}i/
61 IMAG2 = /i|#{UREAL2}i/
62 COMPLEX10 = /#{REAL10}@#{REAL10}|#{REAL10}\+#{IMAG10}|#{REAL10}-#{IMAG10}|\+#{IMAG10}|-#{IMAG10}|#{REAL10}/
63 COMPLEX16 = /#{REAL16}@#{REAL16}|#{REAL16}\+#{IMAG16}|#{REAL16}-#{IMAG16}|\+#{IMAG16}|-#{IMAG16}|#{REAL16}/
64 COMPLEX8 = /#{REAL8}@#{REAL8}|#{REAL8}\+#{IMAG8}|#{REAL8}-#{IMAG8}|\+#{IMAG8}|-#{IMAG8}|#{REAL8}/
65 COMPLEX2 = /#{REAL2}@#{REAL2}|#{REAL2}\+#{IMAG2}|#{REAL2}-#{IMAG2}|\+#{IMAG2}|-#{IMAG2}|#{REAL2}/
66 NUM10 = /#{PREFIX10}?#{COMPLEX10}/
67 NUM16 = /#{PREFIX16}#{COMPLEX16}/
68 NUM8 = /#{PREFIX8}#{COMPLEX8}/
69 NUM2 = /#{PREFIX2}#{COMPLEX2}/
70 NUM = /#{NUM10}|#{NUM16}|#{NUM8}|#{NUM2}/
71
72 private
73 def scan_tokens tokens,options
74
75 state = :initial
76 ident_kind = IDENT_KIND
77
78 until eos?
79 kind = match = nil
80
81 case state
82 when :initial
83 if scan(/ \s+ | \\\n /x)
84 kind = :space
85 elsif scan(/['\(\[\)\]]|#\(/)
86 kind = :operator_fat
87 elsif scan(/;.*/)
88 kind = :comment
89 elsif scan(/#\\(?:newline|space|.?)/)
90 kind = :char
91 elsif scan(/#[ft]/)
92 kind = :pre_constant
93 elsif scan(/#{IDENTIFIER}/o)
94 kind = ident_kind[matched]
95 elsif scan(/\./)
96 kind = :operator
97 elsif scan(/"/)
98 tokens << [:open, :string]
99 state = :string
100 tokens << ['"', :delimiter]
101 next
102 elsif scan(/#{NUM}/o) and not matched.empty?
103 kind = :integer
104 elsif getch
105 kind = :error
106 end
107
108 when :string
109 if scan(/[^"\\]+/) or scan(/\\.?/)
110 kind = :content
111 elsif scan(/"/)
112 tokens << ['"', :delimiter]
113 tokens << [:close, :string]
114 state = :initial
115 next
116 else
117 raise_inspect "else case \" reached; %p not handled." % peek(1),
118 tokens, state
119 end
120
121 else
122 raise "else case reached"
123 end
124
125 match ||= matched
126 if $CODERAY_DEBUG and not kind
127 raise_inspect 'Error token %p in line %d' %
128 [[match, kind], line], tokens
129 end
130 raise_inspect 'Empty token', tokens, state unless match
131
132 tokens << [match, kind]
133
134 end # until eos
135
136 if state == :string
137 tokens << [:close, :string]
138 end
139
140 tokens
141
142 end #scan_tokens
143 end #class
144 end #module scanners
145 end #module coderay