Chris@909
|
1 # encoding: utf-8
|
Chris@909
|
2 module CodeRay
|
Chris@909
|
3 module Scanners
|
Chris@909
|
4
|
Chris@909
|
5 module Ruby::Patterns # :nodoc: all
|
Chris@909
|
6
|
Chris@909
|
7 KEYWORDS = %w[
|
Chris@909
|
8 and def end in or unless begin
|
Chris@909
|
9 defined? ensure module redo super until
|
Chris@909
|
10 BEGIN break do next rescue then
|
Chris@909
|
11 when END case else for retry
|
Chris@909
|
12 while alias class elsif if not return
|
Chris@909
|
13 undef yield
|
Chris@909
|
14 ]
|
Chris@909
|
15
|
Chris@909
|
16 # See http://murfy.de/ruby-constants.
|
Chris@909
|
17 PREDEFINED_CONSTANTS = %w[
|
Chris@909
|
18 nil true false self
|
Chris@909
|
19 DATA ARGV ARGF ENV
|
Chris@909
|
20 FALSE TRUE NIL
|
Chris@909
|
21 STDERR STDIN STDOUT
|
Chris@909
|
22 TOPLEVEL_BINDING
|
Chris@909
|
23 RUBY_COPYRIGHT RUBY_DESCRIPTION RUBY_ENGINE RUBY_PATCHLEVEL
|
Chris@909
|
24 RUBY_PLATFORM RUBY_RELEASE_DATE RUBY_REVISION RUBY_VERSION
|
Chris@909
|
25 __FILE__ __LINE__ __ENCODING__
|
Chris@909
|
26 ]
|
Chris@909
|
27
|
Chris@909
|
28 IDENT_KIND = WordList.new(:ident).
|
Chris@909
|
29 add(KEYWORDS, :keyword).
|
Chris@909
|
30 add(PREDEFINED_CONSTANTS, :predefined_constant)
|
Chris@909
|
31
|
Chris@909
|
32 KEYWORD_NEW_STATE = WordList.new(:initial).
|
Chris@909
|
33 add(%w[ def ], :def_expected).
|
Chris@909
|
34 add(%w[ undef ], :undef_expected).
|
Chris@909
|
35 add(%w[ alias ], :alias_expected).
|
Chris@909
|
36 add(%w[ class module ], :module_expected)
|
Chris@909
|
37
|
Chris@909
|
38 IDENT = 'ä'[/[[:alpha:]]/] == 'ä' ? /[[:alpha:]_][[:alnum:]_]*/ : /[^\W\d]\w*/
|
Chris@909
|
39
|
Chris@909
|
40 METHOD_NAME = / #{IDENT} [?!]? /ox
|
Chris@909
|
41 METHOD_NAME_OPERATOR = /
|
Chris@909
|
42 \*\*? # multiplication and power
|
Chris@909
|
43 | [-+~]@? # plus, minus, tilde with and without at sign
|
Chris@909
|
44 | [\/%&|^`] # division, modulo or format strings, and, or, xor, system
|
Chris@909
|
45 | \[\]=? # array getter and setter
|
Chris@909
|
46 | << | >> # append or shift left, shift right
|
Chris@909
|
47 | <=?>? | >=? # comparison, rocket operator
|
Chris@909
|
48 | ===? | =~ # simple equality, case equality, match
|
Chris@909
|
49 | ![~=@]? # negation with and without at sign, not-equal and not-match
|
Chris@909
|
50 /ox
|
Chris@909
|
51 METHOD_SUFFIX = / (?: [?!] | = (?![~>]|=(?!>)) ) /x
|
Chris@909
|
52 METHOD_NAME_EX = / #{IDENT} #{METHOD_SUFFIX}? | #{METHOD_NAME_OPERATOR} /ox
|
Chris@909
|
53 METHOD_AFTER_DOT = / #{IDENT} [?!]? | #{METHOD_NAME_OPERATOR} /ox
|
Chris@909
|
54 INSTANCE_VARIABLE = / @ #{IDENT} /ox
|
Chris@909
|
55 CLASS_VARIABLE = / @@ #{IDENT} /ox
|
Chris@909
|
56 OBJECT_VARIABLE = / @@? #{IDENT} /ox
|
Chris@909
|
57 GLOBAL_VARIABLE = / \$ (?: #{IDENT} | [1-9]\d* | 0\w* | [~&+`'=\/,;_.<>!@$?*":\\] | -[a-zA-Z_0-9] ) /ox
|
Chris@909
|
58 PREFIX_VARIABLE = / #{GLOBAL_VARIABLE} | #{OBJECT_VARIABLE} /ox
|
Chris@909
|
59 VARIABLE = / @?@? #{IDENT} | #{GLOBAL_VARIABLE} /ox
|
Chris@909
|
60
|
Chris@909
|
61 QUOTE_TO_TYPE = {
|
Chris@909
|
62 '`' => :shell,
|
Chris@909
|
63 '/'=> :regexp,
|
Chris@909
|
64 }
|
Chris@909
|
65 QUOTE_TO_TYPE.default = :string
|
Chris@909
|
66
|
Chris@909
|
67 REGEXP_MODIFIERS = /[mousenix]*/
|
Chris@909
|
68
|
Chris@909
|
69 DECIMAL = /\d+(?:_\d+)*/
|
Chris@909
|
70 OCTAL = /0_?[0-7]+(?:_[0-7]+)*/
|
Chris@909
|
71 HEXADECIMAL = /0x[0-9A-Fa-f]+(?:_[0-9A-Fa-f]+)*/
|
Chris@909
|
72 BINARY = /0b[01]+(?:_[01]+)*/
|
Chris@909
|
73
|
Chris@909
|
74 EXPONENT = / [eE] [+-]? #{DECIMAL} /ox
|
Chris@909
|
75 FLOAT_SUFFIX = / #{EXPONENT} | \. #{DECIMAL} #{EXPONENT}? /ox
|
Chris@909
|
76 FLOAT_OR_INT = / #{DECIMAL} (?: #{FLOAT_SUFFIX} () )? /ox
|
Chris@909
|
77 NUMERIC = / (?: (?=0) (?: #{OCTAL} | #{HEXADECIMAL} | #{BINARY} ) | #{FLOAT_OR_INT} ) /ox
|
Chris@909
|
78
|
Chris@909
|
79 SYMBOL = /
|
Chris@909
|
80 :
|
Chris@909
|
81 (?:
|
Chris@909
|
82 #{METHOD_NAME_EX}
|
Chris@909
|
83 | #{PREFIX_VARIABLE}
|
Chris@909
|
84 | ['"]
|
Chris@909
|
85 )
|
Chris@909
|
86 /ox
|
Chris@909
|
87 METHOD_NAME_OR_SYMBOL = / #{METHOD_NAME_EX} | #{SYMBOL} /ox
|
Chris@909
|
88
|
Chris@909
|
89 SIMPLE_ESCAPE = /
|
Chris@909
|
90 [abefnrstv]
|
Chris@909
|
91 | [0-7]{1,3}
|
Chris@909
|
92 | x[0-9A-Fa-f]{1,2}
|
Chris@909
|
93 | .
|
Chris@909
|
94 /mx
|
Chris@909
|
95
|
Chris@909
|
96 CONTROL_META_ESCAPE = /
|
Chris@909
|
97 (?: M-|C-|c )
|
Chris@909
|
98 (?: \\ (?: M-|C-|c ) )*
|
Chris@909
|
99 (?: [^\\] | \\ #{SIMPLE_ESCAPE} )?
|
Chris@909
|
100 /mox
|
Chris@909
|
101
|
Chris@909
|
102 ESCAPE = /
|
Chris@909
|
103 #{CONTROL_META_ESCAPE} | #{SIMPLE_ESCAPE}
|
Chris@909
|
104 /mox
|
Chris@909
|
105
|
Chris@909
|
106 CHARACTER = /
|
Chris@909
|
107 \?
|
Chris@909
|
108 (?:
|
Chris@909
|
109 [^\s\\]
|
Chris@909
|
110 | \\ #{ESCAPE}
|
Chris@909
|
111 )
|
Chris@909
|
112 /mox
|
Chris@909
|
113
|
Chris@909
|
114 # NOTE: This is not completely correct, but
|
Chris@909
|
115 # nobody needs heredoc delimiters ending with \n.
|
Chris@909
|
116 HEREDOC_OPEN = /
|
Chris@909
|
117 << (-)? # $1 = float
|
Chris@909
|
118 (?:
|
Chris@909
|
119 ( [A-Za-z_0-9]+ ) # $2 = delim
|
Chris@909
|
120 |
|
Chris@909
|
121 ( ["'`\/] ) # $3 = quote, type
|
Chris@909
|
122 ( [^\n]*? ) \3 # $4 = delim
|
Chris@909
|
123 )
|
Chris@909
|
124 /mx
|
Chris@909
|
125
|
Chris@909
|
126 RUBYDOC = /
|
Chris@909
|
127 =begin (?!\S)
|
Chris@909
|
128 .*?
|
Chris@909
|
129 (?: \Z | ^=end (?!\S) [^\n]* )
|
Chris@909
|
130 /mx
|
Chris@909
|
131
|
Chris@909
|
132 DATA = /
|
Chris@909
|
133 __END__$
|
Chris@909
|
134 .*?
|
Chris@909
|
135 (?: \Z | (?=^\#CODE) )
|
Chris@909
|
136 /mx
|
Chris@909
|
137
|
Chris@909
|
138 RUBYDOC_OR_DATA = / #{RUBYDOC} | #{DATA} /xo
|
Chris@909
|
139
|
Chris@909
|
140 # Checks for a valid value to follow. This enables
|
Chris@909
|
141 # value_expected in method calls without parentheses.
|
Chris@909
|
142 VALUE_FOLLOWS = /
|
Chris@909
|
143 (?>[ \t\f\v]+)
|
Chris@909
|
144 (?:
|
Chris@909
|
145 [%\/][^\s=]
|
Chris@909
|
146 | <<-?\S
|
Chris@909
|
147 | [-+] \d
|
Chris@909
|
148 | #{CHARACTER}
|
Chris@909
|
149 )
|
Chris@909
|
150 /ox
|
Chris@909
|
151 KEYWORDS_EXPECTING_VALUE = WordList.new.add(%w[
|
Chris@909
|
152 and end in or unless begin
|
Chris@909
|
153 defined? ensure redo super until
|
Chris@909
|
154 break do next rescue then
|
Chris@909
|
155 when case else for retry
|
Chris@909
|
156 while elsif if not return
|
Chris@909
|
157 yield
|
Chris@909
|
158 ])
|
Chris@909
|
159
|
Chris@909
|
160 FANCY_STRING_START = / % ( [QqrsWwx] | (?![a-zA-Z0-9]) ) ([^a-zA-Z0-9]) /x
|
Chris@909
|
161 FANCY_STRING_KIND = Hash.new(:string).merge({
|
Chris@909
|
162 'r' => :regexp,
|
Chris@909
|
163 's' => :symbol,
|
Chris@909
|
164 'x' => :shell,
|
Chris@909
|
165 })
|
Chris@909
|
166 FANCY_STRING_INTERPRETED = Hash.new(true).merge({
|
Chris@909
|
167 'q' => false,
|
Chris@909
|
168 's' => false,
|
Chris@909
|
169 'w' => false,
|
Chris@909
|
170 })
|
Chris@909
|
171
|
Chris@909
|
172 end
|
Chris@909
|
173
|
Chris@909
|
174 end
|
Chris@909
|
175 end
|