annotate vendor/plugins/coderay-0.9.2/lib/coderay/scanners/.svn/text-base/css.rb.svn-base @ 36:de76cd3e8c8e cc-branches

* Probably abortive experiments in extracting the branch from Hg
author Chris Cannam <chris.cannam@soundsoftware.ac.uk>
date Wed, 20 Oct 2010 10:07:29 +0100
parents 513646585e45
children
rev   line source
Chris@0 1 module CodeRay
Chris@0 2 module Scanners
Chris@0 3
Chris@0 4 class CSS < Scanner
Chris@0 5
Chris@0 6 register_for :css
Chris@0 7
Chris@0 8 KINDS_NOT_LOC = [
Chris@0 9 :comment,
Chris@0 10 :class, :pseudo_class, :type,
Chris@0 11 :constant, :directive,
Chris@0 12 :key, :value, :operator, :color, :float,
Chris@0 13 :error, :important,
Chris@0 14 ]
Chris@0 15
Chris@0 16 module RE
Chris@0 17 NonASCII = /[\x80-\xFF]/
Chris@0 18 Hex = /[0-9a-fA-F]/
Chris@0 19 Unicode = /\\#{Hex}{1,6}(?:\r\n|\s)?/ # differs from standard because it allows uppercase hex too
Chris@0 20 Escape = /#{Unicode}|\\[^\r\n\f0-9a-fA-F]/
Chris@0 21 NMChar = /[-_a-zA-Z0-9]|#{NonASCII}|#{Escape}/
Chris@0 22 NMStart = /[_a-zA-Z]|#{NonASCII}|#{Escape}/
Chris@0 23 NL = /\r\n|\r|\n|\f/
Chris@0 24 String1 = /"(?:[^\n\r\f\\"]|\\#{NL}|#{Escape})*"?/ # FIXME: buggy regexp
Chris@0 25 String2 = /'(?:[^\n\r\f\\']|\\#{NL}|#{Escape})*'?/ # FIXME: buggy regexp
Chris@0 26 String = /#{String1}|#{String2}/
Chris@0 27
Chris@0 28 HexColor = /#(?:#{Hex}{6}|#{Hex}{3})/
Chris@0 29 Color = /#{HexColor}/
Chris@0 30
Chris@0 31 Num = /-?(?:[0-9]+|[0-9]*\.[0-9]+)/
Chris@0 32 Name = /#{NMChar}+/
Chris@0 33 Ident = /-?#{NMStart}#{NMChar}*/
Chris@0 34 AtKeyword = /@#{Ident}/
Chris@0 35 Percentage = /#{Num}%/
Chris@0 36
Chris@0 37 reldimensions = %w[em ex px]
Chris@0 38 absdimensions = %w[in cm mm pt pc]
Chris@0 39 Unit = Regexp.union(*(reldimensions + absdimensions))
Chris@0 40
Chris@0 41 Dimension = /#{Num}#{Unit}/
Chris@0 42
Chris@0 43 Comment = %r! /\* (?: .*? \*/ | .* ) !mx
Chris@0 44 Function = /(?:url|alpha)\((?:[^)\n\r\f]|\\\))*\)?/
Chris@0 45
Chris@0 46 Id = /##{Name}/
Chris@0 47 Class = /\.#{Name}/
Chris@0 48 PseudoClass = /:#{Name}/
Chris@0 49 AttributeSelector = /\[[^\]]*\]?/
Chris@0 50
Chris@0 51 end
Chris@0 52
Chris@0 53 def scan_tokens tokens, options
Chris@0 54
Chris@0 55 value_expected = nil
Chris@0 56 states = [:initial]
Chris@0 57
Chris@0 58 until eos?
Chris@0 59
Chris@0 60 kind = nil
Chris@0 61 match = nil
Chris@0 62
Chris@0 63 if scan(/\s+/)
Chris@0 64 kind = :space
Chris@0 65
Chris@0 66 elsif case states.last
Chris@0 67 when :initial, :media
Chris@0 68 if scan(/(?>#{RE::Ident})(?!\()|\*/ox)
Chris@0 69 kind = :type
Chris@0 70 elsif scan RE::Class
Chris@0 71 kind = :class
Chris@0 72 elsif scan RE::Id
Chris@0 73 kind = :constant
Chris@0 74 elsif scan RE::PseudoClass
Chris@0 75 kind = :pseudo_class
Chris@0 76 elsif match = scan(RE::AttributeSelector)
Chris@0 77 # TODO: Improve highlighting inside of attribute selectors.
Chris@0 78 tokens << [:open, :string]
Chris@0 79 tokens << [match[0,1], :delimiter]
Chris@0 80 tokens << [match[1..-2], :content] if match.size > 2
Chris@0 81 tokens << [match[-1,1], :delimiter] if match[-1] == ?]
Chris@0 82 tokens << [:close, :string]
Chris@0 83 next
Chris@0 84 elsif match = scan(/@media/)
Chris@0 85 kind = :directive
Chris@0 86 states.push :media_before_name
Chris@0 87 end
Chris@0 88
Chris@0 89 when :block
Chris@0 90 if scan(/(?>#{RE::Ident})(?!\()/ox)
Chris@0 91 if value_expected
Chris@0 92 kind = :value
Chris@0 93 else
Chris@0 94 kind = :key
Chris@0 95 end
Chris@0 96 end
Chris@0 97
Chris@0 98 when :media_before_name
Chris@0 99 if scan RE::Ident
Chris@0 100 kind = :type
Chris@0 101 states[-1] = :media_after_name
Chris@0 102 end
Chris@0 103
Chris@0 104 when :media_after_name
Chris@0 105 if scan(/\{/)
Chris@0 106 kind = :operator
Chris@0 107 states[-1] = :media
Chris@0 108 end
Chris@0 109
Chris@0 110 when :comment
Chris@0 111 if scan(/(?:[^*\s]|\*(?!\/))+/)
Chris@0 112 kind = :comment
Chris@0 113 elsif scan(/\*\//)
Chris@0 114 kind = :comment
Chris@0 115 states.pop
Chris@0 116 elsif scan(/\s+/)
Chris@0 117 kind = :space
Chris@0 118 end
Chris@0 119
Chris@0 120 else
Chris@0 121 raise_inspect 'Unknown state', tokens
Chris@0 122
Chris@0 123 end
Chris@0 124
Chris@0 125 elsif scan(/\/\*/)
Chris@0 126 kind = :comment
Chris@0 127 states.push :comment
Chris@0 128
Chris@0 129 elsif scan(/\{/)
Chris@0 130 value_expected = false
Chris@0 131 kind = :operator
Chris@0 132 states.push :block
Chris@0 133
Chris@0 134 elsif scan(/\}/)
Chris@0 135 value_expected = false
Chris@0 136 if states.last == :block || states.last == :media
Chris@0 137 kind = :operator
Chris@0 138 states.pop
Chris@0 139 else
Chris@0 140 kind = :error
Chris@0 141 end
Chris@0 142
Chris@0 143 elsif match = scan(/#{RE::String}/o)
Chris@0 144 tokens << [:open, :string]
Chris@0 145 tokens << [match[0, 1], :delimiter]
Chris@0 146 tokens << [match[1..-2], :content] if match.size > 2
Chris@0 147 tokens << [match[-1, 1], :delimiter] if match.size >= 2
Chris@0 148 tokens << [:close, :string]
Chris@0 149 next
Chris@0 150
Chris@0 151 elsif match = scan(/#{RE::Function}/o)
Chris@0 152 tokens << [:open, :string]
Chris@0 153 start = match[/^\w+\(/]
Chris@0 154 tokens << [start, :delimiter]
Chris@0 155 if match[-1] == ?)
Chris@0 156 tokens << [match[start.size..-2], :content]
Chris@0 157 tokens << [')', :delimiter]
Chris@0 158 else
Chris@0 159 tokens << [match[start.size..-1], :content]
Chris@0 160 end
Chris@0 161 tokens << [:close, :string]
Chris@0 162 next
Chris@0 163
Chris@0 164 elsif scan(/(?: #{RE::Dimension} | #{RE::Percentage} | #{RE::Num} )/ox)
Chris@0 165 kind = :float
Chris@0 166
Chris@0 167 elsif scan(/#{RE::Color}/o)
Chris@0 168 kind = :color
Chris@0 169
Chris@0 170 elsif scan(/! *important/)
Chris@0 171 kind = :important
Chris@0 172
Chris@0 173 elsif scan(/rgb\([^()\n]*\)?/)
Chris@0 174 kind = :color
Chris@0 175
Chris@0 176 elsif scan(/#{RE::AtKeyword}/o)
Chris@0 177 kind = :directive
Chris@0 178
Chris@0 179 elsif match = scan(/ [+>:;,.=()\/] /x)
Chris@0 180 if match == ':'
Chris@0 181 value_expected = true
Chris@0 182 elsif match == ';'
Chris@0 183 value_expected = false
Chris@0 184 end
Chris@0 185 kind = :operator
Chris@0 186
Chris@0 187 else
Chris@0 188 getch
Chris@0 189 kind = :error
Chris@0 190
Chris@0 191 end
Chris@0 192
Chris@0 193 match ||= matched
Chris@0 194 if $CODERAY_DEBUG and not kind
Chris@0 195 raise_inspect 'Error token %p in line %d' %
Chris@0 196 [[match, kind], line], tokens
Chris@0 197 end
Chris@0 198 raise_inspect 'Empty token', tokens unless match
Chris@0 199
Chris@0 200 tokens << [match, kind]
Chris@0 201
Chris@0 202 end
Chris@0 203
Chris@0 204 tokens
Chris@0 205 end
Chris@0 206
Chris@0 207 end
Chris@0 208
Chris@0 209 end
Chris@0 210 end