OSDN Git Service

Move database.yml to template
[redminele/redminele.git] / redmine / vendor / plugins / coderay-0.7.6.227 / lib / coderay / scanners / ruby / patterns.rb
1 module CodeRay
2 module Scanners
3
4   module Ruby::Patterns  # :nodoc:
5
6     RESERVED_WORDS = %w[
7       and def end in or unless begin
8       defined? ensure module redo super until
9       BEGIN break do next rescue then
10       when END case else for retry
11       while alias class elsif if not return
12       undef yield
13     ]
14
15     DEF_KEYWORDS = %w[ def ]
16     UNDEF_KEYWORDS = %w[ undef ]
17     MODULE_KEYWORDS = %w[class module]
18     DEF_NEW_STATE = WordList.new(:initial).
19       add(DEF_KEYWORDS, :def_expected).
20       add(UNDEF_KEYWORDS, :undef_expected).
21       add(MODULE_KEYWORDS, :module_expected)
22
23     IDENTS_ALLOWING_REGEXP = %w[
24       and or not while until unless if then elsif when sub sub! gsub gsub!
25       scan slice slice! split
26     ]
27     REGEXP_ALLOWED = WordList.new(false).
28       add(IDENTS_ALLOWING_REGEXP, :set)
29
30     PREDEFINED_CONSTANTS = %w[
31       nil true false self
32       DATA ARGV ARGF __FILE__ __LINE__
33     ]
34
35     IDENT_KIND = WordList.new(:ident).
36       add(RESERVED_WORDS, :reserved).
37       add(PREDEFINED_CONSTANTS, :pre_constant)
38
39     IDENT = /[a-z_][\w_]*/i
40
41     METHOD_NAME = / #{IDENT} [?!]? /ox
42     METHOD_NAME_OPERATOR = /
43       \*\*?           # multiplication and power
44       | [-+]@?        # plus, minus
45       | [\/%&|^`~]    # division, modulo or format strings, &and, |or, ^xor, `system`, tilde
46       | \[\]=?        # array getter and setter
47       | << | >>       # append or shift left, shift right
48       | <=?>? | >=?   # comparison, rocket operator
49       | ===?          # simple equality and case equality
50     /ox
51     METHOD_NAME_EX = / #{IDENT} (?:[?!]|=(?!>))? | #{METHOD_NAME_OPERATOR} /ox
52     INSTANCE_VARIABLE = / @ #{IDENT} /ox
53     CLASS_VARIABLE = / @@ #{IDENT} /ox
54     OBJECT_VARIABLE = / @@? #{IDENT} /ox
55     GLOBAL_VARIABLE = / \$ (?: #{IDENT} | [1-9]\d* | 0\w* | [~&+`'=\/,;_.<>!@$?*":\\] | -[a-zA-Z_0-9] ) /ox
56     PREFIX_VARIABLE = / #{GLOBAL_VARIABLE} |#{OBJECT_VARIABLE} /ox
57     VARIABLE = / @?@? #{IDENT} | #{GLOBAL_VARIABLE} /ox
58
59     QUOTE_TO_TYPE = {
60       '`' => :shell,
61       '/'=> :regexp,
62     }
63     QUOTE_TO_TYPE.default = :string
64
65     REGEXP_MODIFIERS = /[mixounse]*/
66     REGEXP_SYMBOLS = /[|?*+?(){}\[\].^$]/
67
68     DECIMAL = /\d+(?:_\d+)*/
69     OCTAL = /0_?[0-7]+(?:_[0-7]+)*/
70     HEXADECIMAL = /0x[0-9A-Fa-f]+(?:_[0-9A-Fa-f]+)*/
71     BINARY = /0b[01]+(?:_[01]+)*/
72
73     EXPONENT = / [eE] [+-]? #{DECIMAL} /ox
74     FLOAT_SUFFIX = / #{EXPONENT} | \. #{DECIMAL} #{EXPONENT}? /ox
75     FLOAT_OR_INT = / #{DECIMAL} (?: #{FLOAT_SUFFIX} () )? /ox
76     NUMERIC = / [-+]? (?: (?=0) (?: #{OCTAL} | #{HEXADECIMAL} | #{BINARY} ) | #{FLOAT_OR_INT} ) /ox
77
78     SYMBOL = /
79       :
80       (?:
81         #{METHOD_NAME_EX}
82       | #{PREFIX_VARIABLE}
83       | ['"]
84       )
85     /ox
86
87     # TODO investigste \M, \c and \C escape sequences
88     # (?: M-\\C-|C-\\M-|M-\\c|c\\M-|c|C-|M-)? (?: \\ (?: [0-7]{3} | x[0-9A-Fa-f]{2} | . ) )
89     # assert_equal(225, ?\M-a)
90     # assert_equal(129, ?\M-\C-a)
91     ESCAPE = /
92         [abefnrstv]
93       | M-\\C-|C-\\M-|M-\\c|c\\M-|c|C-|M-
94       |  [0-7]{1,3}
95       | x[0-9A-Fa-f]{1,2}
96       | .
97     /mx
98
99     CHARACTER = /
100       \?
101       (?:
102         [^\s\\]
103       | \\ #{ESCAPE}
104       )
105     /mx
106
107     # NOTE: This is not completely correct, but
108     # nobody needs heredoc delimiters ending with \n.
109     HEREDOC_OPEN = /
110       << (-)?              # $1 = float
111       (?:
112         ( [A-Za-z_0-9]+ )  # $2 = delim
113       |
114         ( ["'`\/] )        # $3 = quote, type
115         ( [^\n]*? ) \3     # $4 = delim
116       )
117     /mx
118
119     RUBYDOC = /
120       =begin (?!\S)
121       .*?
122       (?: \Z | ^=end (?!\S) [^\n]* )
123     /mx
124
125     DATA = /
126       __END__$
127       .*?
128       (?: \Z | (?=^\#CODE) )
129     /mx
130     
131     # Checks for a valid value to follow. This enables
132     # fancy_allowed in method calls.
133     VALUE_FOLLOWS = /
134       \s+
135       (?:
136         [%\/][^\s=]
137       |
138         <<-?\S
139       |
140         #{CHARACTER}
141       )
142     /x
143
144     RUBYDOC_OR_DATA = / #{RUBYDOC} | #{DATA} /xo
145
146     RDOC_DATA_START = / ^=begin (?!\S) | ^__END__$ /x
147
148     # FIXME: \s and = are only a workaround, they are still allowed
149     # as delimiters.
150     FANCY_START_SAVE = / % ( [qQwWxsr] | (?![a-zA-Z0-9\s=]) ) ([^a-zA-Z0-9]) /mx
151     FANCY_START_CORRECT = / % ( [qQwWxsr] | (?![a-zA-Z0-9]) ) ([^a-zA-Z0-9]) /mx
152
153     FancyStringType = {
154       'q' => [:string, false],
155       'Q' => [:string, true],
156       'r' => [:regexp, true],
157       's' => [:symbol, false],
158       'x' => [:shell, true]
159     }
160     FancyStringType['w'] = FancyStringType['q']
161     FancyStringType['W'] = FancyStringType[''] = FancyStringType['Q']
162
163     class StringState < Struct.new :type, :interpreted, :delim, :heredoc,
164       :paren, :paren_depth, :pattern, :next_state
165
166       CLOSING_PAREN = Hash[ *%w[
167         ( )
168         [ ]
169         < >
170         { }
171       ] ]
172
173       CLOSING_PAREN.values.each { |o| o.freeze }  # debug, if I try to change it with <<
174       OPENING_PAREN = CLOSING_PAREN.invert
175
176       STRING_PATTERN = Hash.new { |h, k|
177         delim, interpreted = *k
178         delim_pattern = Regexp.escape(delim.dup)
179         if closing_paren = CLOSING_PAREN[delim]
180           delim_pattern << Regexp.escape(closing_paren)
181         end
182
183
184         special_escapes =
185           case interpreted
186           when :regexp_symbols
187             '| ' + REGEXP_SYMBOLS.source
188           when :words
189             '| \s'
190           end
191
192         h[k] =
193           if interpreted and not delim == '#'
194             / (?= [#{delim_pattern}\\] | \# [{$@] #{special_escapes} ) /mx
195           else
196             / (?= [#{delim_pattern}\\] #{special_escapes} ) /mx
197           end
198       }
199
200       HEREDOC_PATTERN = Hash.new { |h, k|
201         delim, interpreted, indented = *k
202         delim_pattern = Regexp.escape(delim.dup)
203         delim_pattern = / \n #{ '(?>[\ \t]*)' if indented } #{ Regexp.new delim_pattern } $ /x
204         h[k] =
205           if interpreted
206             / (?= #{delim_pattern}() | \\ | \# [{$@] ) /mx  # $1 set == end of heredoc
207           else
208             / (?= #{delim_pattern}() | \\ ) /mx
209           end
210       }
211
212       def initialize kind, interpreted, delim, heredoc = false
213         if heredoc
214           pattern = HEREDOC_PATTERN[ [delim, interpreted, heredoc == :indented] ]
215           delim  = nil
216         else
217           pattern = STRING_PATTERN[ [delim, interpreted] ]
218           if paren = CLOSING_PAREN[delim]
219             delim, paren = paren, delim
220             paren_depth = 1
221           end
222         end
223         super kind, interpreted, delim, heredoc, paren, paren_depth, pattern, :initial
224       end
225     end unless defined? StringState
226
227   end
228
229 end
230 end