Class: Iro::Ruby::Parser

Inherits:
Base
  • Object
show all
Defined in:
lib/iro/ruby/parser.rb

Constant Summary collapse

EVENT_NAME_TO_HIGHLIGT_NAME =
{
  tstring_content: 'String',
  CHAR: 'Character',
  int: 'Number',
  float: 'Float',
  
  comment: 'Comment',
  embdoc: 'Comment',
  embdoc_beg: 'Comment',
  embdoc_end: 'Comment',

  regexp_beg: 'Delimiter',
  regexp_end: 'Delimiter',
  heredoc_beg: 'Delimiter',
  heredoc_end: 'Delimiter',
  tstring_beg: 'Delimiter',
  tstring_end: 'Delimiter',
  embexpr_beg: 'Delimiter',
  embexpr_end: 'Delimiter',
  backtick: 'Delimiter',

  symbeg: 'rubySymbolDelimiter',

  ivar: 'rubyInstanceVariable',
  cvar: 'rubyClassVariable',
  gvar: 'rubyGlobalVariable',
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeParser

Returns a new instance of Parser.



46
47
48
49
50
# File 'lib/iro/ruby/parser.rb', line 46

def initialize(*)
  super
  @tokens = {}
  @end_stack = []
end

Instance Attribute Details

#tokensObject (readonly)

Returns the value of attribute tokens.



44
45
46
# File 'lib/iro/ruby/parser.rb', line 44

def tokens
  @tokens
end

Class Method Details

.tokens(source) ⇒ Object



195
196
197
198
199
# File 'lib/iro/ruby/parser.rb', line 195

def self.tokens(source)
  parser = self.new(source)
  parser.parse
  parser.tokens
end

Instance Method Details

#highlight_end_as(group) ⇒ Object



70
71
72
# File 'lib/iro/ruby/parser.rb', line 70

def highlight_end_as(group)
  register_scanner_event group, @end_stack.pop
end

#highlight_keyword_like_method(ident) ⇒ Object



184
185
186
187
188
189
190
191
192
193
# File 'lib/iro/ruby/parser.rb', line 184

def highlight_keyword_like_method(ident)
  case ident.content
  when 'private', 'public', 'protected', 'private_class_method',
       'attr_reader', 'attr_writer', 'attr_accessor', 'attr',
       'include', 'extend', 'prepend', 'module_function', 'refine', 'using',
       'raise', 'fail', 'catch', 'throw',
       'require', 'require_relative'
    register_scanner_event 'Keyword', ident # TODO: Change highlight group
  end
end

#kw_group(str) ⇒ Object



119
120
121
122
123
124
# File 'lib/iro/ruby/parser.rb', line 119

def kw_group(str)
  {
    'def' => 'rubyDefine',
    'alias' => 'rubyDefine',
  }[str] || 'Keyword'
end

#on_command(ident, _) ⇒ Object



180
181
182
# File 'lib/iro/ruby/parser.rb', line 180

def on_command(ident, _)
  highlight_keyword_like_method(ident)
end

#on_const_path_ref(_base, name) ⇒ Object



167
168
169
170
# File 'lib/iro/ruby/parser.rb', line 167

def on_const_path_ref(_base, name)
  register_scanner_event 'Type', name
  nil
end

#on_def(name, params, body) ⇒ Object



126
127
128
129
130
131
# File 'lib/iro/ruby/parser.rb', line 126

def on_def(name, params, body)
  unhighlight! name if name.kw_type?
  register_scanner_event 'rubyFunction', name
  highlight_end_as 'rubyDefine'
  nil
end

#on_defs(recv, period, name, params, body) ⇒ Object



133
134
135
136
137
138
# File 'lib/iro/ruby/parser.rb', line 133

def on_defs(recv, period, name, params, body)
  unhighlight! name if name.kw_type?
  register_scanner_event 'rubyFunction', name
  highlight_end_as 'rubyDefine'
  nil
end

#on_fcall(ident) ⇒ Object



172
173
174
# File 'lib/iro/ruby/parser.rb', line 172

def on_fcall(ident)
  highlight_keyword_like_method(ident)
end

#on_kw(str) ⇒ Object



100
101
102
103
104
105
106
107
108
109
# File 'lib/iro/ruby/parser.rb', line 100

def on_kw(str)
  super.tap do |result|
    if str == 'end'
      @end_stack << result
    else
      group = kw_group(str)
      register_token group, [lineno, column+1, str.size]
    end
  end
end

#on_label(str) ⇒ Object

foo: bar ^^^ rubySymbol

^ no highlight


114
115
116
117
# File 'lib/iro/ruby/parser.rb', line 114

def on_label(str)
  register_token 'rubySymbol', [lineno, column+1, str.size-1]
  super
end

#on_symbol(node) ⇒ Object



140
141
142
143
144
# File 'lib/iro/ruby/parser.rb', line 140

def on_symbol(node)
  unhighlight! node if node.gvar_type? || node.ivar_type? || node.cvar_type? || node.kw_type?
  register_scanner_event 'rubySymbol', node
  nil
end

#on_top_const_ref(name) ⇒ Object Also known as: on_const_ref



161
162
163
164
# File 'lib/iro/ruby/parser.rb', line 161

def on_top_const_ref(name)
  register_scanner_event 'Type', name
  nil
end

#on_var_field(name) ⇒ Object



156
157
158
159
# File 'lib/iro/ruby/parser.rb', line 156

def on_var_field(name)
  register_scanner_event 'Type', name if name.const_type?
  nil
end

#on_var_ref(name) ⇒ Object



146
147
148
149
150
151
152
153
154
# File 'lib/iro/ruby/parser.rb', line 146

def on_var_ref(name)
  case name.type
  when :@ident
    register_scanner_event 'rubyLocalVariable', name
  when :@const
    register_scanner_event 'Type', name
  end
  nil
end

#on_vcall(ident) ⇒ Object



176
177
178
# File 'lib/iro/ruby/parser.rb', line 176

def on_vcall(ident)
  highlight_keyword_like_method(ident)
end

#parseObject



52
53
54
55
56
57
# File 'lib/iro/ruby/parser.rb', line 52

def parse
  super
  @end_stack.each do |end_kw|
    register_scanner_event 'Keyword', end_kw
  end
end

#register_scanner_event(group, event) ⇒ Object

TODO: Maybe multiline support is needed.



65
66
67
68
# File 'lib/iro/ruby/parser.rb', line 65

def register_scanner_event(group, event)
  pos = event.position
  register_token group, [pos[0], pos[1]+1, event.content.size]
end

#register_token(group, token) ⇒ Object



59
60
61
62
# File 'lib/iro/ruby/parser.rb', line 59

def register_token(group, token)
  @tokens[group] ||= []
  @tokens[group] << token
end

#unhighlight!(scanner_event) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/iro/ruby/parser.rb', line 74

def unhighlight!(scanner_event)
  t = scanner_event.type[1..-1].to_sym
  group = EVENT_NAME_TO_HIGHLIGT_NAME[t] ||
    (scanner_event.kw_type? && kw_group(scanner_event.content))
  raise 'bug' unless group

  t = scanner_event.position + [scanner_event.content.size]
  t[1] += 1
  @tokens[group].reject! { |ev| ev == t }
  @end_stack.reject!{|e| e == scanner_event} if scanner_event.kw_type? && scanner_event.content == 'end'
end