Chris@909
|
1 # encoding: utf-8
|
Chris@909
|
2 module CodeRay
|
Chris@909
|
3 module Scanners
|
Chris@909
|
4
|
Chris@909
|
5 class Ruby
|
Chris@909
|
6
|
Chris@909
|
7 class StringState < Struct.new :type, :interpreted, :delim, :heredoc,
|
Chris@909
|
8 :opening_paren, :paren_depth, :pattern, :next_state # :nodoc: all
|
Chris@909
|
9
|
Chris@909
|
10 CLOSING_PAREN = Hash[ *%w[
|
Chris@909
|
11 ( )
|
Chris@909
|
12 [ ]
|
Chris@909
|
13 < >
|
Chris@909
|
14 { }
|
Chris@909
|
15 ] ].each { |k,v| k.freeze; v.freeze } # debug, if I try to change it with <<
|
Chris@909
|
16
|
Chris@909
|
17 STRING_PATTERN = Hash.new do |h, k|
|
Chris@909
|
18 delim, interpreted = *k
|
Chris@909
|
19 # delim = delim.dup # workaround for old Ruby
|
Chris@909
|
20 delim_pattern = Regexp.escape(delim)
|
Chris@909
|
21 if closing_paren = CLOSING_PAREN[delim]
|
Chris@909
|
22 delim_pattern << Regexp.escape(closing_paren)
|
Chris@909
|
23 end
|
Chris@909
|
24 delim_pattern << '\\\\' unless delim == '\\'
|
Chris@909
|
25
|
Chris@909
|
26 # special_escapes =
|
Chris@909
|
27 # case interpreted
|
Chris@909
|
28 # when :regexp_symbols
|
Chris@909
|
29 # '| [|?*+(){}\[\].^$]'
|
Chris@909
|
30 # end
|
Chris@909
|
31
|
Chris@909
|
32 h[k] =
|
Chris@909
|
33 if interpreted && delim != '#'
|
Chris@909
|
34 / (?= [#{delim_pattern}] | \# [{$@] ) /mx
|
Chris@909
|
35 else
|
Chris@909
|
36 / (?= [#{delim_pattern}] ) /mx
|
Chris@909
|
37 end
|
Chris@909
|
38 end
|
Chris@909
|
39
|
Chris@909
|
40 def initialize kind, interpreted, delim, heredoc = false
|
Chris@909
|
41 if heredoc
|
Chris@909
|
42 pattern = heredoc_pattern delim, interpreted, heredoc == :indented
|
Chris@909
|
43 delim = nil
|
Chris@909
|
44 else
|
Chris@909
|
45 pattern = STRING_PATTERN[ [delim, interpreted] ]
|
Chris@909
|
46 if closing_paren = CLOSING_PAREN[delim]
|
Chris@909
|
47 opening_paren = delim
|
Chris@909
|
48 delim = closing_paren
|
Chris@909
|
49 paren_depth = 1
|
Chris@909
|
50 end
|
Chris@909
|
51 end
|
Chris@909
|
52 super kind, interpreted, delim, heredoc, opening_paren, paren_depth, pattern, :initial
|
Chris@909
|
53 end
|
Chris@909
|
54
|
Chris@909
|
55 def heredoc_pattern delim, interpreted, indented
|
Chris@909
|
56 # delim = delim.dup # workaround for old Ruby
|
Chris@909
|
57 delim_pattern = Regexp.escape(delim)
|
Chris@909
|
58 delim_pattern = / (?:\A|\n) #{ '(?>[ \t]*)' if indented } #{ Regexp.new delim_pattern } $ /x
|
Chris@909
|
59 if interpreted
|
Chris@909
|
60 / (?= #{delim_pattern}() | \\ | \# [{$@] ) /mx # $1 set == end of heredoc
|
Chris@909
|
61 else
|
Chris@909
|
62 / (?= #{delim_pattern}() | \\ ) /mx
|
Chris@909
|
63 end
|
Chris@909
|
64 end
|
Chris@909
|
65
|
Chris@909
|
66 end
|
Chris@909
|
67
|
Chris@909
|
68 end
|
Chris@909
|
69
|
Chris@909
|
70 end
|
Chris@909
|
71 end
|