summaryrefslogtreecommitdiff
path: root/lib/coderay/scanners/ruby/string_state.rb
diff options
context:
space:
mode:
authormurphy <murphy@rubychan.de>2011-03-07 22:36:53 +0000
committermurphy <murphy@rubychan.de>2011-03-07 22:36:53 +0000
commitc6baf98c3e5ce3fdc9884968ba1a06fbe29ce49f (patch)
tree107a5193117263bb4e265ab4b4780eade3e73818 /lib/coderay/scanners/ruby/string_state.rb
parentfc3fb2ed266bf01fdac54cd4abcc346559159cbe (diff)
downloadcoderay-c6baf98c3e5ce3fdc9884968ba1a06fbe29ce49f.tar.gz
lots of fixes and improvements to the Ruby scanner
Diffstat (limited to 'lib/coderay/scanners/ruby/string_state.rb')
-rw-r--r--lib/coderay/scanners/ruby/string_state.rb71
1 files changed, 71 insertions, 0 deletions
diff --git a/lib/coderay/scanners/ruby/string_state.rb b/lib/coderay/scanners/ruby/string_state.rb
new file mode 100644
index 0000000..14127c6
--- /dev/null
+++ b/lib/coderay/scanners/ruby/string_state.rb
@@ -0,0 +1,71 @@
+# encoding: utf-8
+module CodeRay
+module Scanners
+
+ class Ruby
+
+ class StringState < Struct.new :type, :interpreted, :delim, :heredoc,
+ :opening_paren, :paren_depth, :pattern, :next_state # :nodoc: all
+
+ CLOSING_PAREN = Hash[ *%w[
+ ( )
+ [ ]
+ < >
+ { }
+ ] ].each { |k,v| k.freeze; v.freeze } # debug, if I try to change it with <<
+
+ STRING_PATTERN = Hash.new do |h, k|
+ delim, interpreted = *k
+ # delim = delim.dup # workaround for old Ruby
+ delim_pattern = Regexp.escape(delim)
+ if closing_paren = CLOSING_PAREN[delim]
+ delim_pattern << Regexp.escape(closing_paren)
+ end
+ delim_pattern << '\\\\' unless delim == '\\'
+
+ # special_escapes =
+ # case interpreted
+ # when :regexp_symbols
+ # '| [|?*+(){}\[\].^$]'
+ # end
+
+ h[k] =
+ if interpreted && delim != '#'
+ / (?= [#{delim_pattern}] | \# [{$@] ) /mx
+ else
+ / (?= [#{delim_pattern}] ) /mx
+ end
+ end
+
+ def initialize kind, interpreted, delim, heredoc = false
+ if heredoc
+ pattern = heredoc_pattern delim, interpreted, heredoc == :indented
+ delim = nil
+ else
+ pattern = STRING_PATTERN[ [delim, interpreted] ]
+ if closing_paren = CLOSING_PAREN[delim]
+ opening_paren = delim
+ delim = closing_paren
+ paren_depth = 1
+ end
+ end
+ super kind, interpreted, delim, heredoc, opening_paren, paren_depth, pattern, :initial
+ end
+
+ def heredoc_pattern delim, interpreted, indented
+ # delim = delim.dup # workaround for old Ruby
+ delim_pattern = Regexp.escape(delim)
+ delim_pattern = / \n #{ '(?>[ \t]*)' if indented } #{ Regexp.new delim_pattern } $ /x
+ if interpreted
+ / (?= #{delim_pattern}() | \\ | \# [{$@] ) /mx # $1 set == end of heredoc
+ else
+ / (?= #{delim_pattern}() | \\ ) /mx
+ end
+ end
+
+ end
+
+ end
+
+end
+end