Class: BitClust::SyntaxHighlighter

Inherits:
Ripper::Filter
  • Object
show all
Includes:
HTMLUtils
Defined in:
lib/bitclust/syntax_highlighter.rb

Defined Under Namespace

Classes: CompileError, Error, ParseError

Constant Summary collapse

COLORS =
{
  CHAR: "sc",                      # ?a
  __end__: "k",                    # __END__
  backref: "vg",                   # $` $& $' $1 ...
  backtick: "sb",                  # `
  comma: nil,                      # ,
  comment: "c1",                   # #...
  const: "no",                     # Const
  cvar: "vc",                      # @@var
  embdoc: nil,                     # (=begin) document (=end)
  embdoc_beg: "cm",                # =begin
  embdoc_end: nil,                 # =end
  embexpr_beg: "si",               # #{
  embexpr_end: "si",               # (#{) }
  embvar: "n",                     # ("...) # (var")
  float: "mf",                     # 1.23 (float)
  gvar: "vg",                      # $var
  heredoc_beg: "no",               # <<EOS
  heredoc_end: "no",               # EOS
  ident: nil,                      # identifier
  ignored_nl: nil,                 # ignored \n
  int: "mi",                       # 1 (integer)
  ivar: "vi",                      # @var
  kw: "k",                         # keyword
  label: "ss",                     # label:
  lbrace: "p",                     # {
  lbracket: "p",                   # [
  lparen: "p",                     # (
  nl: nil,                         # \n
  op: "o",                         # operator
  period: "p",                     # .
  qwords_beg: "sx",                # %w(
  rbrace: "p",                     # }
  rbracket: "p",                   # ]
  regexp_beg: "sr",                # / (regexp/)
  regexp_end: nil,                 # (/regexp) /
  rparen: "p",                     # )
  semicolon: nil,                  # ;
  sp: nil,                         # space
  symbeg: "ss",                    # :
  tlambda: "o",                    # ->
  tlambeg: "p",                    # (->) {
  tstring_beg: nil,                # " (string")
  tstring_content: nil,            # (") string (")
  tstring_end: nil,                # ("string) "
  words_beg: "sx",                 # %W(
  words_sep: nil                   # (%W() )
}
LABELS =

(%W() )

{
}
KEYWORDS =
%w[
  BEGIN END alias begin break case defined\? do else elsif end
  ensure for if in next redo rescue raise retry return super then
  undef unless until when while yield
]
KEYWORDS_PSEUDO =
%w[
  loop include extend raise
  alias_method attr catch throw private module_function
  public protected true false nil __FILE__ __LINE__
]
BUILTINS_G =
%w[
  attr_reader attr_writer attr_accessor

  __id__ __send__ abort ancestors at_exit autoload binding callcc
  caller catch chomp chop class_eval class_variables clone
  const_defined\? const_get const_missing const_set constants
  display dup eval exec exit extend fail fork format freeze
  getc gets global_variables gsub hash id included_modules
  inspect instance_eval instance_method instance_methods
  instance_variable_get instance_variable_set instance_variables
  lambda load local_variables loop method method_missing
  methods module_eval name object_id open p print printf
  private_class_method private_instance_methods private_methods proc
  protected_instance_methods protected_methods public_class_method
  public_instance_methods public_methods putc puts raise rand
  readline readlines require require_relative scan select self send set_trace_func
  singleton_methods sleep split sprintf srand sub syscall system
  taint test throw to_a to_s trace_var trap untaint untrace_var warn
]
BUILTINS_Q =
%w[
  autoload block_given const_defined eql equal frozen
  include instance_of is_a iterator kind_of method_defined
  nil private_method_defined protected_method_defined
  public_method_defined respond_to tainted
]
BUILTINS_B =
%w[chomp chop exit gsub sub]

Constants included from NameUtils

NameUtils::CHAR_TO_MARK, NameUtils::CHAR_TO_NAME, NameUtils::CLASS_NAME_RE, NameUtils::CLASS_PATH_RE, NameUtils::CONST_PATH_RE, NameUtils::CONST_RE, NameUtils::GVAR_RE, NameUtils::LIBNAME_RE, NameUtils::MARK_TO_CHAR, NameUtils::MARK_TO_NAME, NameUtils::METHOD_NAME_RE, NameUtils::METHOD_SPEC_RE, NameUtils::MID, NameUtils::NAME_TO_CHAR, NameUtils::NAME_TO_MARK, NameUtils::TYPEMARK_RE

Instance Method Summary collapse

Methods included from NameUtils

build_method_id, classid2name, classname2id, classname?, decodeid, decodename_fs, decodename_url, encodeid, encodename_fs, encodename_rdocurl, encodename_url, functionname?, gvarname?, html_filename, libid2name, libname2id, libname?, method_spec?, methodid2classid, methodid2libid, methodid2mname, methodid2specparts, methodid2specstring, methodid2typechar, methodid2typemark, methodid2typename, methodname?, split_method_id, split_method_spec, typechar2mark, typechar2name, typechar?, typemark2char, typemark2name, typemark?, typename2char, typename2mark, typename?

Constructor Details

#initialize(src, filename = "-", lineno = 1) ⇒ SyntaxHighlighter

Returns a new instance of SyntaxHighlighter.



120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/bitclust/syntax_highlighter.rb', line 120

def initialize(src, filename = "-", lineno = 1)
  super
  @src = src
  @stack = []
  @name_buffer = []
  @__lexer.define_singleton_method(:on_parse_error) do |message|
    raise ParseError.new(filename, self.lineno, self.column, "#{message}\n#{src}")
  end
  @__lexer.define_singleton_method(:compile_error) do |message|
    raise CompileError.new(filename, self.lineno, self.column, "#{message}\n#{src}")
  end
end

Instance Method Details

#highlightObject



370
371
372
# File 'lib/bitclust/syntax_highlighter.rb', line 370

def highlight
  parse(+"")
end

#on___end__(token, data) ⇒ Object



363
364
365
366
367
368
# File 'lib/bitclust/syntax_highlighter.rb', line 363

def on___end__(token, data)
  on_default(:on___end__, token, data)
  style = COLORS[:comment]
  data << "<span class=\"#{style}\">#{escape_html(@src.lines[lineno..-1].join)}</span>"
  data
end

#on_const(token, data) ⇒ Object



178
179
180
181
182
183
184
185
186
187
188
# File 'lib/bitclust/syntax_highlighter.rb', line 178

def on_const(token, data)
  case
  when @stack.last == :class
    @name_buffer << token
  when @stack.last == :module
    @name_buffer << token
  else
    on_default(:on_const, token, data)
  end
  data
end

#on_default(event, token, data) ⇒ Object



133
134
135
136
137
138
139
# File 'lib/bitclust/syntax_highlighter.rb', line 133

def on_default(event, token, data)
  event_name = event.to_s.sub(/\Aon_/, "")   # :on_event --> "event"
  style = COLORS[event_name.to_sym]
  escaped_token = escape_html(token)
  data << (style ? "<span class=\"#{style}\">#{escaped_token}</span>" : escaped_token)
  data
end

#on_embdoc_beg(token, data) ⇒ Object



141
142
143
144
145
# File 'lib/bitclust/syntax_highlighter.rb', line 141

def on_embdoc_beg(token, data)
  style = COLORS[:embdoc_beg]
  data << "<span class=\"#{style}\">#{token}"
  data
end

#on_embdoc_end(token, data) ⇒ Object



147
148
149
150
# File 'lib/bitclust/syntax_highlighter.rb', line 147

def on_embdoc_end(token, data)
  data << "#{token}</span>"
  data
end

#on_embexpr_beg(token, data) ⇒ Object



353
354
355
356
# File 'lib/bitclust/syntax_highlighter.rb', line 353

def on_embexpr_beg(token, data)
  @stack.push(:embexpr)
  on_default(:on_embexpr_beg, token, data)
end

#on_embexpr_end(token, data) ⇒ Object



358
359
360
361
# File 'lib/bitclust/syntax_highlighter.rb', line 358

def on_embexpr_end(token, data)
  @stack.pop
  on_default(:on_embexpr_end, token, data)
end

#on_heredoc_beg(token, data) ⇒ Object



343
344
345
346
# File 'lib/bitclust/syntax_highlighter.rb', line 343

def on_heredoc_beg(token, data)
  @stack.push(:heredoc)
  on_default(:on_heredoc_beg, token, data)
end

#on_heredoc_end(token, data) ⇒ Object



348
349
350
351
# File 'lib/bitclust/syntax_highlighter.rb', line 348

def on_heredoc_end(token, data)
  @stack.pop
  on_default(:on_heredoc_end, token, data)
end

#on_ident(token, data) ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/bitclust/syntax_highlighter.rb', line 152

def on_ident(token, data)
  case
  when @stack.last == :symbol
    data << "#{token}</span>"
    @stack.pop
  when @stack.last == :def
    @stack.pop
    data << "<span class=\"nf\">#{token}</span>"
  when @stack.last == :embexpr
    data << "<span class=\"n\">#{token}</span>"
  when @stack.last == :heredoc
    style = COLORS[:heredoc_beg]
    data << "<span class=\"#{style}\">#{token}"
  when @stack.last == :method_call
    data << "<span class=\"nf\">#{token}</span>"
    @stack.pop
  when @stack.last == :class
    @name_buffer << token
  when BUILTINS_G.include?(token)
    data << "<span class=\"nb\">#{token}</span>"
  else
    data << token
  end
  data
end

#on_kw(token, data) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/bitclust/syntax_highlighter.rb', line 190

def on_kw(token, data)
  case
  when @stack.last == :symbol
    data << "#{token}</span>"
    @stack.pop
  when token == "module"
    @stack.push(:module)
    on_default(:on_kw, token, data)
  when token == "class"
    @stack.push(:class)
    on_default(:on_kw, token, data)
  when token == "def"
    @stack.push(:def)
    on_default(:on_kw, token, data)
  when token == "self"
    data << "<span class=\"nc\">#{token}</span>"
  else
    on_default(:on_kw, token, data)
  end
  data
end

#on_nl(token, data) ⇒ Object



250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/bitclust/syntax_highlighter.rb', line 250

def on_nl(token, data)
  case
  when @name_buffer.empty?
    return on_default(:on_nl, token, data)
  when @stack.last == :module
    name = @name_buffer.join
    data << "<span class=\"nn\">#{name}</span>"
    @stack.pop
    @name_buffer.clear
  when @stack.last == :class
    namespace = @name_buffer.values_at(0..-3).join
    operator = @name_buffer[-2]
    name = @name_buffer.last
    data << "<span class=\"nn\">#{namespace}</span>"
    data << "<span class=\"o\">#{operator}</span>"
    data << "<span class=\"nc\">#{name}</span>"
    @stack.pop
    @name_buffer.clear
  end
  on_default(:on_nl, token, data)
end

#on_op(token, data) ⇒ Object



217
218
219
220
221
222
223
224
225
226
# File 'lib/bitclust/syntax_highlighter.rb', line 217

def on_op(token, data)
  case
  when token == "::" && [:class, :module].include?(@stack.last)
    @name_buffer << token
  else
    @stack.pop if @stack.last == :method_call
    on_default(:on_op, token, data)
  end
  data
end

#on_period(token, data) ⇒ Object



212
213
214
215
# File 'lib/bitclust/syntax_highlighter.rb', line 212

def on_period(token, data)
  @stack.push(:method_call)
  on_default(:on_period, token, data)
end

#on_qwords_beg(token, data) ⇒ Object



329
330
331
332
333
334
# File 'lib/bitclust/syntax_highlighter.rb', line 329

def on_qwords_beg(token, data)
  @stack.push(:qwords)
  style = COLORS[:qwords_beg]
  data << "<span class=\"#{style}\">#{token}"
  data
end

#on_regexp_beg(token, data) ⇒ Object



272
273
274
275
276
# File 'lib/bitclust/syntax_highlighter.rb', line 272

def on_regexp_beg(token, data)
  style = COLORS[:regexp_beg]
  data << "<span class=\"#{style}\">#{token}"
  data
end

#on_regexp_end(token, data) ⇒ Object



278
279
280
281
# File 'lib/bitclust/syntax_highlighter.rb', line 278

def on_regexp_end(token, data)
  data << "#{token}</span>"
  data
end

#on_sp(token, data) ⇒ Object



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/bitclust/syntax_highlighter.rb', line 228

def on_sp(token, data)
  case
  when @name_buffer.empty?
    return on_default(:on_sp, token, data)
  when @stack.last == :module
    name = @name_buffer.join
    data << "<span class=\"nn\">#{name}</span>"
    @stack.pop
    @name_buffer.clear
  when @stack.last == :class
    namespace = @name_buffer.values_at(0..-3).join
    operator = @name_buffer[-2]
    name = @name_buffer.last
    data << "<span class=\"nn\">#{namespace}</span>"
    data << "<span class=\"o\">#{operator}</span>"
    data << "<span class=\"nc\">#{name}</span>"
    @stack.pop
    @name_buffer.clear
  end
  on_default(:on_sp, token, data)
end

#on_symbeg(token, data) ⇒ Object



283
284
285
286
287
288
# File 'lib/bitclust/syntax_highlighter.rb', line 283

def on_symbeg(token, data)
  style = COLORS[:symbeg]
  data << "<span class=\"#{style}\">#{token}"
  @stack << :symbol
  data
end

#on_tstring_beg(token, data) ⇒ Object



290
291
292
293
294
295
296
297
298
299
# File 'lib/bitclust/syntax_highlighter.rb', line 290

def on_tstring_beg(token, data)
  if token == "'"
    data << "<span class=\"s1\">#{token}"
    @stack << :string1
  else
    data << "<span class=\"s2\">#{token}</span>"
    @stack << :string2
  end
  data
end

#on_tstring_content(token, data) ⇒ Object



301
302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/bitclust/syntax_highlighter.rb', line 301

def on_tstring_content(token, data)
  case
  when @stack.last == :heredoc
    data << "<span class=\"sh\">#{escape_html(token)}</span>"
  when @stack.last == :string1
    data << escape_html(token)
  when @stack.last == :string2
    data << "<span class=\"s2\">#{escape_html(token)}</span>"
  else
    on_default(:on_tstring_content, token, data)
  end
  data
end

#on_tstring_end(token, data) ⇒ Object



315
316
317
318
319
320
321
322
323
324
325
326
327
# File 'lib/bitclust/syntax_highlighter.rb', line 315

def on_tstring_end(token, data)
  case
  when token == "'"
    data << "#{token}</span>"
  when [:qwords, :words].include?(@stack.last)
    @stack.pop
    data << "#{token}</span>"
  else
    data << "<span class=\"s2\">#{token}</span>"
  end
  @stack.pop
  data
end

#on_words_beg(token, data) ⇒ Object



336
337
338
339
340
341
# File 'lib/bitclust/syntax_highlighter.rb', line 336

def on_words_beg(token, data)
  @stack.push(:words)
  style = COLORS[:words_beg]
  data << "<span class=\"#{style}\">#{token}"
  data
end