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 / helpers / word_list.rb @ 442:753f1380d6bc

History | View | Annotate | Download (3.15 KB)

1
module CodeRay
2

    
3
# = WordList
4
# 
5
# <b>A Hash subclass designed for mapping word lists to token types.</b>
6
# 
7
# Copyright (c) 2006 by murphy (Kornelius Kalnbach) <murphy rubychan de>
8
#
9
# License:: LGPL / ask the author
10
# Version:: 1.1 (2006-Oct-19)
11
#
12
# A WordList is a Hash with some additional features.
13
# It is intended to be used for keyword recognition.
14
#
15
# WordList is highly optimized to be used in Scanners,
16
# typically to decide whether a given ident is a special token.
17
#
18
# For case insensitive words use CaseIgnoringWordList.
19
#
20
# Example:
21
#
22
#  # define word arrays
23
#  RESERVED_WORDS = %w[
24
#    asm break case continue default do else
25
#    ...
26
#  ]
27
#  
28
#  PREDEFINED_TYPES = %w[
29
#    int long short char void
30
#    ...
31
#  ]
32
#  
33
#  PREDEFINED_CONSTANTS = %w[
34
#    EOF NULL ...
35
#  ]
36
#  
37
#  # make a WordList
38
#  IDENT_KIND = WordList.new(:ident).
39
#    add(RESERVED_WORDS, :reserved).
40
#    add(PREDEFINED_TYPES, :pre_type).
41
#    add(PREDEFINED_CONSTANTS, :pre_constant)
42
#
43
#  ...
44
#
45
#  def scan_tokens tokens, options
46
#    ...
47
#    
48
#    elsif scan(/[A-Za-z_][A-Za-z_0-9]*/)
49
#      # use it
50
#      kind = IDENT_KIND[match]
51
#      ...
52
class WordList < Hash
53

    
54
  # Creates a new WordList with +default+ as default value.
55
  # 
56
  # You can activate +caching+ to store the results for every [] request.
57
  # 
58
  # With caching, methods like +include?+ or +delete+ may no longer behave
59
  # as you expect. Therefore, it is recommended to use the [] method only.
60
  def initialize default = false, caching = false, &block
61
    if block
62
      raise ArgumentError, 'Can\'t combine block with caching.' if caching
63
      super(&block)
64
    else
65
      if caching
66
        super() do |h, k|
67
          h[k] = h.fetch k, default
68
        end
69
      else
70
        super default
71
      end
72
    end
73
  end
74

    
75
  # Add words to the list and associate them with +kind+.
76
  # 
77
  # Returns +self+, so you can concat add calls.
78
  def add words, kind = true
79
    words.each do |word|
80
      self[word] = kind
81
    end
82
    self
83
  end
84

    
85
end
86

    
87

    
88
# A CaseIgnoringWordList is like a WordList, only that
89
# keys are compared case-insensitively.
90
# 
91
# Ignoring the text case is realized by sending the +downcase+ message to
92
# all keys.
93
# 
94
# Caching usually makes a CaseIgnoringWordList faster, but it has to be
95
# activated explicitely.
96
class CaseIgnoringWordList < WordList
97

    
98
  # Creates a new case-insensitive WordList with +default+ as default value.
99
  # 
100
  # You can activate caching to store the results for every [] request.
101
  # This speeds up subsequent lookups for the same word, but also
102
  # uses memory.
103
  def initialize default = false, caching = false
104
    if caching
105
      super(default, false) do |h, k|
106
        h[k] = h.fetch k.downcase, default
107
      end
108
    else
109
      super(default, false)
110
      extend Uncached
111
    end
112
  end
113
  
114
  module Uncached  # :nodoc:
115
    def [] key
116
      super(key.downcase)
117
    end
118
  end
119

    
120
  # Add +words+ to the list and associate them with +kind+.
121
  def add words, kind = true
122
    words.each do |word|
123
      self[word.downcase] = kind
124
    end
125
    self
126
  end
127

    
128
end
129

    
130
end
131

    
132
__END__
133
# check memory consumption
134
END {
135
  ObjectSpace.each_object(CodeRay::CaseIgnoringWordList) do |wl|
136
    p wl.inject(0) { |memo, key, value| memo + key.size + 24 }
137
  end
138
}