To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / vendor / gems / coderay-0.9.7 / lib / coderay / scanners / scheme.rb @ 442:753f1380d6bc

History | View | Annotate | Download (4.82 KB)

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