OSDN Git Service

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