summaryrefslogtreecommitdiff
path: root/lib/coderay
diff options
context:
space:
mode:
Diffstat (limited to 'lib/coderay')
-rw-r--r--lib/coderay/scanners/json.rb106
-rw-r--r--lib/coderay/styles/cycnus.rb13
2 files changed, 114 insertions, 5 deletions
diff --git a/lib/coderay/scanners/json.rb b/lib/coderay/scanners/json.rb
new file mode 100644
index 0000000..ae941a0
--- /dev/null
+++ b/lib/coderay/scanners/json.rb
@@ -0,0 +1,106 @@
+module CodeRay
+module Scanners
+
+ class JSON < Scanner
+
+ include Streamable
+
+ register_for :json
+
+ CONSTANTS = %w( true false null )
+ IDENT_KIND = WordList.new(:key).add(CONSTANTS, :reserved)
+
+ ESCAPE = / [bfnrt\\"\/] /x
+ UNICODE_ESCAPE = / u[a-fA-F0-9]{4} /x
+
+ def scan_tokens tokens, options
+
+ state = :initial
+ stack = []
+ string_delimiter = nil
+ key_expected = false
+
+ until eos?
+
+ kind = nil
+ match = nil
+
+ case state
+
+ when :initial
+ if match = scan(/ \s+ | \\\n /x)
+ tokens << [match, :space]
+ next
+ elsif match = scan(/ [:,\[{\]}] /x)
+ kind = :operator
+ case match
+ when '{': stack << :object; key_expected = true
+ when '[': stack << :array
+ when ':': key_expected = false
+ when ',': key_expected = true if stack.last == :object
+ when '}', ']': stack.pop # no error recovery, but works for valid JSON
+ end
+ elsif match = scan(/ true | false | null /x)
+ kind = IDENT_KIND[match]
+ elsif match = scan(/-?(?:0|[1-9]\d*)/)
+ kind = :integer
+ if scan(/\.\d+(?:[eE][-+]?\d+)?|[eE][-+]?\d+/)
+ match << matched
+ kind = :float
+ end
+ elsif match = scan(/"/)
+ state = key_expected ? :key : :string
+ tokens << [:open, state]
+ kind = :delimiter
+ else
+ getch
+ kind = :error
+ end
+
+ when :string, :key
+ if scan(/[^\\"]+/)
+ kind = :content
+ elsif scan(/"/)
+ tokens << ['"', :delimiter]
+ tokens << [:close, state]
+ state = :initial
+ next
+ elsif scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
+ kind = :char
+ elsif scan(/\\./m)
+ kind = :content
+ elsif scan(/ \\ | $ /x)
+ tokens << [:close, :delimiter]
+ kind = :error
+ state = :initial
+ else
+ raise_inspect "else case \" reached; %p not handled." % peek(1), tokens
+ end
+
+ else
+ raise_inspect 'Unknown state', tokens
+
+ end
+
+ match ||= matched
+ if $DEBUG and not kind
+ raise_inspect 'Error token %p in line %d' %
+ [[match, kind], line], tokens
+ end
+ raise_inspect 'Empty token', tokens unless match
+
+ tokens << [match, kind]
+
+ end
+
+ if [:string, :key].include? state
+ tokens << [:close, state]
+ end
+
+ tokens
+ end
+
+ end
+
+end
+end
diff --git a/lib/coderay/styles/cycnus.rb b/lib/coderay/styles/cycnus.rb
index 521c3c9..c0dab99 100644
--- a/lib/coderay/styles/cycnus.rb
+++ b/lib/coderay/styles/cycnus.rb
@@ -97,6 +97,8 @@ ol.CodeRay li { white-space: pre }
.r, .kw { color:#080; font-weight:bold }
.ke { color: #808; }
+.ke .dl { color: #606; }
+.ke .ch { color: #80f; }
.vl { color: #088; }
.rx { background-color:#fff0ff }
@@ -105,11 +107,12 @@ ol.CodeRay li { white-space: pre }
.rx .mod { color:#C2C }
.rx .fu { color:#404; font-weight: bold }
-.s { background-color:#fff0f0 }
-.s .s { background-color:#ffe0e0 }
-.s .s .s { background-color:#ffd0d0 }
-.s .k { color:#D20 }
-.s .dl { color:#710 }
+.s { background-color:#fff0f0 }
+.s .s { background-color:#ffe0e0 }
+.s .s .s { background-color:#ffd0d0 }
+.s .k { color: #D20; }
+.s .ch { color: #b0b; }
+.s .dl { color: #710; }
.sh { background-color:#f0fff0 }
.sh .k { color:#2B2 }