diff options
author | Kornelius Kalnbach <murphy@rubychan.de> | 2016-02-13 00:47:21 +0100 |
---|---|---|
committer | Kornelius Kalnbach <murphy@rubychan.de> | 2016-02-13 00:47:21 +0100 |
commit | a1a7b2c871a0b33451292e542073a4aa743c91f2 (patch) | |
tree | 15a1842443715f6e605abfbc06d497c9f03445ac | |
parent | 7561e8ddfa64cdcefb3a79eaa14085cfb8ef2c0d (diff) | |
download | coderay-a1a7b2c871a0b33451292e542073a4aa743c91f2.tar.gz |
add json scanner using RuleBasedScanner
-rw-r--r-- | lib/coderay/scanners/json5.rb | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/lib/coderay/scanners/json5.rb b/lib/coderay/scanners/json5.rb new file mode 100644 index 0000000..c68ebb7 --- /dev/null +++ b/lib/coderay/scanners/json5.rb @@ -0,0 +1,92 @@ +module CodeRay +module Scanners + + # Scanner for JSON (JavaScript Object Notation). + class JSON5 < RuleBasedScanner + + register_for :json5 + file_extension 'json' + + KINDS_NOT_LOC = [ + :float, :char, :content, :delimiter, + :error, :integer, :operator, :value, + ] # :nodoc: + + ESCAPE = / [bfnrt\\"\/] /x # :nodoc: + UNICODE_ESCAPE = / u[a-fA-F0-9]{4} /x # :nodoc: + KEY = / (?> (?: [^\\"]+ | \\. )* ) " \s* : /mx + + state :initial do + on %r/ \s+ /x, :space + + on %r/ [:,\[{\]}] /x, :operator + + on %r/ " (?=#{KEY}) /x, push(:key), :delimiter + on %r/ " /x, push(:string), :delimiter + + on %r/ true | false | null /x, :value + on %r/ -? (?: 0 | [1-9]\d* ) (?: \.\d+ (?: e[-+]? \d+ )? | e[-+]? \d+ ) /ix, :float + on %r/ -? (?: 0 | [1-9]\d* ) (?: e[+-] \d+ )? /ix, :integer + end + + state :key, :string do + on %r/ [^\\"]+ /x, :content + + on %r/ " /x, :delimiter, pop + + on %r/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /x, :char + on %r/ \\. /mx, :content + on %r/ \\ /x, :error, pop + end + + protected + + def setup + @state = :initial + end + + # See http://json.org/ for a definition of the JSON lexic/grammar. + scan_tokens_code = <<-"RUBY" + def scan_tokens encoder, options + state = options[:state] || @state + + if [:string, :key].include? state + encoder.begin_group state + end + + states = [state] + + until eos? + + case state + +#{ @code.chomp.gsub(/^/, ' ') } + else + raise_inspect 'Unknown state: %p' % [state], encoder + + end + + end + + if options[:keep_state] + @state = state + end + + if [:string, :key].include? state + encoder.end_group state + end + + encoder + end + RUBY + + if ENV['PUTS'] + puts CodeRay.scan(scan_tokens_code, :ruby).terminal + puts "callbacks: #{callbacks.size}" + end + class_eval scan_tokens_code + + end + +end +end |