rubysl-irb 1.0.2 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -2
  3. data/lib/irb/cmd/chws.rb +6 -6
  4. data/lib/irb/cmd/fork.rb +10 -10
  5. data/lib/irb/cmd/help.rb +24 -14
  6. data/lib/irb/cmd/load.rb +8 -7
  7. data/lib/irb/cmd/nop.rb +8 -8
  8. data/lib/irb/cmd/pushws.rb +6 -5
  9. data/lib/irb/cmd/subirb.rb +6 -7
  10. data/lib/irb/completion.rb +90 -58
  11. data/lib/irb/context.rb +197 -30
  12. data/lib/irb/ext/change-ws.rb +17 -10
  13. data/lib/irb/ext/history.rb +20 -10
  14. data/lib/irb/ext/loader.rb +22 -12
  15. data/lib/irb/ext/math-mode.rb +16 -6
  16. data/lib/irb/ext/multi-irb.rb +69 -24
  17. data/lib/irb/ext/save-history.rb +87 -37
  18. data/lib/irb/ext/tracer.rb +17 -7
  19. data/lib/irb/ext/use-loader.rb +14 -6
  20. data/lib/irb/ext/workspaces.rb +16 -6
  21. data/lib/irb/extend-command.rb +92 -34
  22. data/lib/irb/frame.rb +18 -5
  23. data/lib/irb/help.rb +20 -19
  24. data/lib/irb/init.rb +156 -104
  25. data/lib/irb/input-method.rb +96 -23
  26. data/lib/irb/inspector.rb +145 -0
  27. data/lib/irb/lc/.document +4 -0
  28. data/lib/irb/lc/error.rb +8 -7
  29. data/lib/irb/lc/{help-message.rb → help-message} +14 -11
  30. data/lib/irb/lc/ja/encoding_aliases.rb +10 -0
  31. data/lib/irb/lc/ja/error.rb +19 -16
  32. data/lib/irb/lc/ja/help-message +33 -28
  33. data/lib/irb/locale.rb +83 -85
  34. data/lib/irb/magic-file.rb +37 -0
  35. data/lib/irb/notifier.rb +101 -15
  36. data/lib/irb/output-method.rb +38 -32
  37. data/lib/irb/ruby-lex.rb +143 -81
  38. data/lib/irb/ruby-token.rb +13 -19
  39. data/lib/irb/slex.rb +26 -27
  40. data/lib/irb/src_encoding.rb +4 -0
  41. data/lib/irb/version.rb +6 -7
  42. data/lib/irb/workspace.rb +22 -15
  43. data/lib/irb/ws-for-case-2.rb +5 -6
  44. data/lib/irb/xmp.rb +91 -4
  45. data/lib/rubysl/irb/irb.rb +523 -175
  46. data/lib/rubysl/irb/version.rb +1 -1
  47. data/rubysl-irb.gemspec +7 -6
  48. metadata +35 -15
@@ -0,0 +1,37 @@
1
+ module IRB
2
+ class << (MagicFile = Object.new)
3
+ # see parser_magic_comment in parse.y
4
+ ENCODING_SPEC_RE = %r"coding\s*[=:]\s*([[:alnum:]\-_]+)"
5
+
6
+ def open(path)
7
+ io = File.open(path, 'rb')
8
+ line = io.gets
9
+ line = io.gets if line[0,2] == "#!"
10
+ encoding = detect_encoding(line)
11
+ internal_encoding = encoding
12
+ encoding ||= default_src_encoding
13
+ io.rewind
14
+ io.set_encoding(encoding, internal_encoding)
15
+
16
+ if block_given?
17
+ begin
18
+ return (yield io)
19
+ ensure
20
+ io.close
21
+ end
22
+ else
23
+ return io
24
+ end
25
+ end
26
+
27
+ private
28
+ def detect_encoding(line)
29
+ return unless line[0] == ?#
30
+ line = line[1..-1]
31
+ line = $1 if line[/-\*-\s*(.*?)\s*-*-$/]
32
+ return nil unless ENCODING_SPEC_RE =~ line
33
+ encoding = $1
34
+ return encoding.sub(/-(?:mac|dos|unix)/i, '')
35
+ end
36
+ end
37
+ end
data/lib/irb/notifier.rb CHANGED
@@ -1,79 +1,120 @@
1
1
  #
2
- # notifier.rb - optput methods used by irb
3
- # $Release Version: 0.9.5$
4
- # $Revision: 11708 $
5
- # $Date: 2007-02-12 15:01:19 -0800 (Mon, 12 Feb 2007) $
2
+ # notifier.rb - output methods used by irb
3
+ # $Release Version: 0.9.6$
4
+ # $Revision$
6
5
  # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
6
  #
8
7
  # --
9
8
  #
10
- #
9
+ #
11
10
  #
12
11
 
13
12
  require "e2mmap"
14
13
  require "irb/output-method"
15
14
 
16
15
  module IRB
16
+ # An output formatter used internally by the lexer.
17
17
  module Notifier
18
18
  extend Exception2MessageMapper
19
- def_exception :ErrUndefinedNotifier,
19
+ def_exception :ErrUndefinedNotifier,
20
20
  "undefined notifier level: %d is specified"
21
- def_exception :ErrUnrecognizedLevel,
21
+ def_exception :ErrUnrecognizedLevel,
22
22
  "unrecognized notifier level: %s is specified"
23
23
 
24
+ # Define a new Notifier output source, returning a new CompositeNotifier
25
+ # with the given +prefix+ and +output_method+.
26
+ #
27
+ # The optional +prefix+ will be appended to all objects being inspected
28
+ # during output, using the given +output_method+ as the output source. If
29
+ # no +output_method+ is given, StdioOuputMethod will be used, and all
30
+ # expressions will be sent directly to STDOUT without any additional
31
+ # formatting.
24
32
  def def_notifier(prefix = "", output_method = StdioOutputMethod.new)
25
33
  CompositeNotifier.new(prefix, output_method)
26
34
  end
27
35
  module_function :def_notifier
28
-
29
- class AbstructNotifier
36
+
37
+ # An abstract class, or superclass, for CompositeNotifier and
38
+ # LeveledNotifier to inherit. It provides several wrapper methods for the
39
+ # OutputMethod object used by the Notifier.
40
+ class AbstractNotifier
41
+ # Creates a new Notifier object
30
42
  def initialize(prefix, base_notifier)
31
43
  @prefix = prefix
32
44
  @base_notifier = base_notifier
33
45
  end
34
46
 
47
+ # The +prefix+ for this Notifier, which is appended to all objects being
48
+ # inspected during output.
35
49
  attr_reader :prefix
36
50
 
51
+ # A wrapper method used to determine whether notifications are enabled.
52
+ #
53
+ # Defaults to +true+.
37
54
  def notify?
38
55
  true
39
56
  end
40
57
 
58
+ # See OutputMethod#print for more detail.
41
59
  def print(*opts)
42
60
  @base_notifier.print prefix, *opts if notify?
43
61
  end
44
62
 
63
+ # See OutputMethod#printn for more detail.
45
64
  def printn(*opts)
46
65
  @base_notifier.printn prefix, *opts if notify?
47
66
  end
48
67
 
68
+ # See OutputMethod#printf for more detail.
49
69
  def printf(format, *opts)
50
70
  @base_notifier.printf(prefix + format, *opts) if notify?
51
71
  end
52
72
 
73
+ # See OutputMethod#puts for more detail.
53
74
  def puts(*objs)
54
75
  if notify?
55
76
  @base_notifier.puts(*objs.collect{|obj| prefix + obj.to_s})
56
77
  end
57
78
  end
58
79
 
80
+ # Same as #ppx, except it uses the #prefix given during object
81
+ # initialization.
82
+ # See OutputMethod#ppx for more detail.
59
83
  def pp(*objs)
60
84
  if notify?
61
85
  @base_notifier.ppx @prefix, *objs
62
86
  end
63
87
  end
64
88
 
89
+ # Same as #pp, except it concatenates the given +prefix+ with the #prefix
90
+ # given during object initialization.
91
+ #
92
+ # See OutputMethod#ppx for more detail.
65
93
  def ppx(prefix, *objs)
66
94
  if notify?
67
95
  @base_notifier.ppx @prefix+prefix, *objs
68
96
  end
69
97
  end
70
98
 
99
+ # Execute the given block if notifications are enabled.
71
100
  def exec_if
72
101
  yield(@base_notifier) if notify?
73
102
  end
74
103
  end
75
104
 
76
- class CompositeNotifier<AbstructNotifier
105
+ # A class that can be used to create a group of notifier objects with the
106
+ # intent of representing a leveled notification system for irb.
107
+ #
108
+ # This class will allow you to generate other notifiers, and assign them
109
+ # the appropriate level for output.
110
+ #
111
+ # The Notifier class provides a class-method Notifier.def_notifier to
112
+ # create a new composite notifier. Using the first composite notifier
113
+ # object you create, sibling notifiers can be initialized with
114
+ # #def_notifier.
115
+ class CompositeNotifier<AbstractNotifier
116
+ # Create a new composite notifier object with the given +prefix+, and
117
+ # +base_notifier+ to use for output.
77
118
  def initialize(prefix, base_notifier)
78
119
  super
79
120
 
@@ -81,20 +122,42 @@ module IRB
81
122
  @level_notifier = D_NOMSG
82
123
  end
83
124
 
125
+ # List of notifiers in the group
84
126
  attr_reader :notifiers
85
127
 
128
+ # Creates a new LeveledNotifier in the composite #notifiers group.
129
+ #
130
+ # The given +prefix+ will be assigned to the notifier, and +level+ will
131
+ # be used as the index of the #notifiers Array.
132
+ #
133
+ # This method returns the newly created instance.
86
134
  def def_notifier(level, prefix = "")
87
135
  notifier = LeveledNotifier.new(self, level, prefix)
88
136
  @notifiers[level] = notifier
89
137
  notifier
90
138
  end
91
139
 
140
+ # Returns the leveled notifier for this object
92
141
  attr_reader :level_notifier
93
142
  alias level level_notifier
94
143
 
144
+ # Sets the leveled notifier for this object.
145
+ #
146
+ # When the given +value+ is an instance of AbstractNotifier,
147
+ # #level_notifier is set to the given object.
148
+ #
149
+ # When an Integer is given, #level_notifier is set to the notifier at the
150
+ # index +value+ in the #notifiers Array.
151
+ #
152
+ # If no notifier exists at the index +value+ in the #notifiers Array, an
153
+ # ErrUndefinedNotifier exception is raised.
154
+ #
155
+ # An ErrUnrecognizedLevel exception is raised if the given +value+ is not
156
+ # found in the existing #notifiers Array, or an instance of
157
+ # AbstractNotifier
95
158
  def level_notifier=(value)
96
159
  case value
97
- when AbstructNotifier
160
+ when AbstractNotifier
98
161
  @level_notifier = value
99
162
  when Integer
100
163
  l = @notifiers[value]
@@ -108,38 +171,61 @@ module IRB
108
171
  alias level= level_notifier=
109
172
  end
110
173
 
111
- class LeveledNotifier<AbstructNotifier
174
+ # A leveled notifier is comparable to the composite group from
175
+ # CompositeNotifier#notifiers.
176
+ class LeveledNotifier<AbstractNotifier
112
177
  include Comparable
113
178
 
179
+ # Create a new leveled notifier with the given +base+, and +prefix+ to
180
+ # send to AbstractNotifier.new
181
+ #
182
+ # The given +level+ is used to compare other leveled notifiers in the
183
+ # CompositeNotifier group to determine whether or not to output
184
+ # notifications.
114
185
  def initialize(base, level, prefix)
115
186
  super(prefix, base)
116
-
187
+
117
188
  @level = level
118
189
  end
119
190
 
191
+ # The current level of this notifier object
120
192
  attr_reader :level
121
193
 
194
+ # Compares the level of this notifier object with the given +other+
195
+ # notifier.
196
+ #
197
+ # See the Comparable module for more information.
122
198
  def <=>(other)
123
199
  @level <=> other.level
124
200
  end
125
-
201
+
202
+ # Whether to output messages to the output method, depending on the level
203
+ # of this notifier object.
126
204
  def notify?
127
205
  @base_notifier.level >= self
128
206
  end
129
207
  end
130
208
 
209
+ # NoMsgNotifier is a LeveledNotifier that's used as the default notifier
210
+ # when creating a new CompositeNotifier.
211
+ #
212
+ # This notifier is used as the +zero+ index, or level +0+, for
213
+ # CompositeNotifier#notifiers, and will not output messages of any sort.
131
214
  class NoMsgNotifier<LeveledNotifier
215
+ # Creates a new notifier that should not be used to output messages.
132
216
  def initialize
133
217
  @base_notifier = nil
134
218
  @level = 0
135
219
  @prefix = ""
136
220
  end
137
221
 
222
+ # Ensures notifications are ignored, see AbstractNotifier#notify? for
223
+ # more information.
138
224
  def notify?
139
225
  false
140
226
  end
141
227
  end
142
228
 
143
- D_NOMSG = NoMsgNotifier.new
229
+ D_NOMSG = NoMsgNotifier.new # :nodoc:
144
230
  end
145
231
  end
@@ -1,33 +1,38 @@
1
1
  #
2
- # output-method.rb - optput methods used by irb
3
- # $Release Version: 0.9.5$
4
- # $Revision: 11708 $
5
- # $Date: 2007-02-12 15:01:19 -0800 (Mon, 12 Feb 2007) $
2
+ # output-method.rb - output methods used by irb
3
+ # $Release Version: 0.9.6$
4
+ # $Revision$
6
5
  # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
6
  #
8
7
  # --
9
8
  #
10
- #
9
+ #
11
10
  #
12
11
 
13
12
  require "e2mmap"
14
13
 
15
14
  module IRB
16
- # OutputMethod
17
- # StdioOutputMethod
18
-
15
+ # An abstract output class for IO in irb. This is mainly used internally by
16
+ # IRB::Notifier. You can define your own output method to use with Irb.new,
17
+ # or Context.new
19
18
  class OutputMethod
20
- @RCS_ID='-$Id: output-method.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
19
+ extend Exception2MessageMapper
20
+ def_exception :NotImplementedError, "Need to define `%s'"
21
+
21
22
 
23
+ # Open this method to implement your own output method, raises a
24
+ # NotImplementedError if you don't define #print in your own class.
22
25
  def print(*opts)
23
- IRB.fail NotImplementError, "print"
26
+ OutputMethod.Raise NotImplementedError, "print"
24
27
  end
25
28
 
29
+ # Prints the given +opts+, with a newline delimiter.
26
30
  def printn(*opts)
27
31
  print opts.join(" "), "\n"
28
32
  end
29
33
 
30
- # extend printf
34
+ # Extends IO#printf to format the given +opts+ for Kernel#sprintf using
35
+ # #parse_printf_format
31
36
  def printf(format, *opts)
32
37
  if /(%*)%I/ =~ format
33
38
  format, opts = parse_printf_format(format, opts)
@@ -35,31 +40,22 @@ module IRB
35
40
  print sprintf(format, *opts)
36
41
  end
37
42
 
38
- # %
39
- # <�ե饰> [#0- +]
40
- # <�Ǿ��ե��������> (\*|\*[1-9][0-9]*\$|[1-9][0-9]*)
41
- # <����>.(\*|\*[1-9][0-9]*\$|[1-9][0-9]*|)?
42
- # #<Ĺ������ʸ��>(hh|h|l|ll|L|q|j|z|t)
43
- # <�Ѵ�����ʸ��>[diouxXeEfgGcsb%]
43
+ # Returns an array of the given +format+ and +opts+ to be used by
44
+ # Kernel#sprintf, if there was a successful Regexp match in the given
45
+ # +format+ from #printf
46
+ #
47
+ # %
48
+ # <flag> [#0- +]
49
+ # <minimum field width> (\*|\*[1-9][0-9]*\$|[1-9][0-9]*)
50
+ # <precision>.(\*|\*[1-9][0-9]*\$|[1-9][0-9]*|)?
51
+ # #<length modifier>(hh|h|l|ll|L|q|j|z|t)
52
+ # <conversion specifier>[diouxXeEfgGcsb%]
44
53
  def parse_printf_format(format, opts)
45
54
  return format, opts if $1.size % 2 == 1
46
55
  end
47
56
 
48
- def foo(format)
49
- pos = 0
50
- inspects = []
51
- format.scan(/%[#0\-+ ]?(\*(?=[^0-9])|\*[1-9][0-9]*\$|[1-9][0-9]*(?=[^0-9]))?(\.(\*(?=[^0-9])|\*[1-9][0-9]*\$|[1-9][0-9]*(?=[^0-9])))?(([1-9][0-9]*\$)*)([diouxXeEfgGcsb%])/) {|f, p, pp, pos, new_pos, c|
52
- puts [f, p, pp, pos, new_pos, c].join("!")
53
- pos = new_pos if new_pos
54
- if c == "I"
55
- inspects.push pos.to_i
56
- (f||"")+(p||"")+(pp||"")+(pos||"")+"s"
57
- else
58
- $&
59
- end
60
- }
61
- end
62
-
57
+ # Calls #print on each element in the given +objs+, followed by a newline
58
+ # character.
63
59
  def puts(*objs)
64
60
  for obj in objs
65
61
  print(*obj)
@@ -67,17 +63,27 @@ module IRB
67
63
  end
68
64
  end
69
65
 
66
+ # Prints the given +objs+ calling Object#inspect on each.
67
+ #
68
+ # See #puts for more detail.
70
69
  def pp(*objs)
71
70
  puts(*objs.collect{|obj| obj.inspect})
72
71
  end
73
72
 
73
+ # Prints the given +objs+ calling Object#inspect on each and appending the
74
+ # given +prefix+.
75
+ #
76
+ # See #puts for more detail.
74
77
  def ppx(prefix, *objs)
75
78
  puts(*objs.collect{|obj| prefix+obj.inspect})
76
79
  end
77
80
 
78
81
  end
79
82
 
83
+ # A standard output printer
80
84
  class StdioOutputMethod<OutputMethod
85
+ # Prints the given +opts+ to standard output, see IO#print for more
86
+ # information.
81
87
  def print(*opts)
82
88
  STDOUT.print(*opts)
83
89
  end
data/lib/irb/ruby-lex.rb CHANGED
@@ -1,32 +1,32 @@
1
1
  #
2
- # irb/ruby-lex.rb - ruby lexcal analizer
3
- # $Release Version: 0.9.5$
4
- # $Revision: 11708 $
5
- # $Date: 2007-02-12 15:01:19 -0800 (Mon, 12 Feb 2007) $
2
+ # irb/ruby-lex.rb - ruby lexcal analyzer
3
+ # $Release Version: 0.9.6$
4
+ # $Revision$
6
5
  # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
6
  #
8
7
  # --
9
8
  #
10
- #
9
+ #
11
10
  #
12
11
 
13
12
  require "e2mmap"
14
13
  require "irb/slex"
15
14
  require "irb/ruby-token"
16
15
 
16
+ # :stopdoc:
17
17
  class RubyLex
18
- @RCS_ID='-$Id: ruby-lex.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
18
+ @RCS_ID='-$Id$-'
19
19
 
20
20
  extend Exception2MessageMapper
21
21
  def_exception(:AlreadyDefinedToken, "Already defined token(%s)")
22
22
  def_exception(:TkReading2TokenNoKey, "key nothing(key='%s')")
23
23
  def_exception(:TkSymbol2TokenNoKey, "key nothing(key='%s')")
24
- def_exception(:TkReading2TokenDuplicateError,
24
+ def_exception(:TkReading2TokenDuplicateError,
25
25
  "key duplicate(token_n='%s', key='%s')")
26
26
  def_exception(:SyntaxError, "%s")
27
27
 
28
28
  def_exception(:TerminateLineInput, "Terminate Line Input")
29
-
29
+
30
30
  include RubyToken
31
31
 
32
32
  class << self
@@ -54,7 +54,8 @@ class RubyLex
54
54
  @lex_state = EXPR_BEG
55
55
  @space_seen = false
56
56
  @here_header = false
57
-
57
+ @post_symbeg = false
58
+
58
59
  @continue = false
59
60
  @line = ""
60
61
 
@@ -77,7 +78,7 @@ class RubyLex
77
78
  # io functions
78
79
  def set_input(io, p = nil, &block)
79
80
  @io = io
80
- if p and p.respond_to?(:call)
81
+ if p.respond_to?(:call)
81
82
  @input = p
82
83
  elsif block_given?
83
84
  @input = block
@@ -87,12 +88,12 @@ class RubyLex
87
88
  end
88
89
 
89
90
  def get_readed
90
- if idx = @readed.reverse.index("\n")
91
- @base_char_no = idx
91
+ if idx = @readed.rindex("\n")
92
+ @base_char_no = @readed.size - (idx + 1)
92
93
  else
93
94
  @base_char_no += @readed.size
94
95
  end
95
-
96
+
96
97
  readed = @readed.join("")
97
98
  @readed = []
98
99
  readed
@@ -111,7 +112,7 @@ class RubyLex
111
112
  end
112
113
  @seek += 1
113
114
  if c == "\n"
114
- @line_no += 1
115
+ @line_no += 1
115
116
  @char_no = 0
116
117
  else
117
118
  @char_no += 1
@@ -148,12 +149,12 @@ class RubyLex
148
149
  c2 = @here_readed.pop
149
150
  end
150
151
  c = c2 unless c
151
- @rests.unshift c #c =
152
- @seek -= 1
152
+ @rests.unshift c #c =
153
+ @seek -= 1
153
154
  if c == "\n"
154
- @line_no -= 1
155
- if idx = @readed.reverse.index("\n")
156
- @char_no = @readed.size - idx
155
+ @line_no -= 1
156
+ if idx = @readed.rindex("\n")
157
+ @char_no = idx + 1
157
158
  else
158
159
  @char_no = @base_char_no + @readed.size
159
160
  end
@@ -188,7 +189,7 @@ class RubyLex
188
189
  prompt
189
190
  line = @input.call
190
191
  return nil unless line
191
- @rests.concat line.split(//)
192
+ @rests.concat line.chars.to_a
192
193
  true
193
194
  end
194
195
  private :buf_input
@@ -216,14 +217,16 @@ class RubyLex
216
217
  @lex_state = EXPR_BEG
217
218
  @space_seen = false
218
219
  @here_header = false
219
-
220
+
220
221
  @continue = false
222
+ @post_symbeg = false
223
+
221
224
  prompt
222
225
 
223
226
  @line = ""
224
227
  @exp_line_no = @line_no
225
228
  end
226
-
229
+
227
230
  def each_top_level_statement
228
231
  initialize_input
229
232
  catch(:TERM_INPUT) do
@@ -234,13 +237,13 @@ class RubyLex
234
237
  unless l = lex
235
238
  throw :TERM_INPUT if @line == ''
236
239
  else
237
- #p l
238
240
  @line.concat l
239
241
  if @ltype or @continue or @indent > 0
240
242
  next
241
243
  end
242
244
  end
243
245
  if @line != "\n"
246
+ @line.force_encoding(@io.encoding)
244
247
  yield @line, @exp_line_no
245
248
  end
246
249
  break unless l
@@ -286,6 +289,8 @@ class RubyLex
286
289
  begin
287
290
  tk = @OP.match(self)
288
291
  @space_seen = tk.kind_of?(TkSPACE)
292
+ @lex_state = EXPR_END if @post_symbeg && tk.kind_of?(TkOp)
293
+ @post_symbeg = tk.kind_of?(TkSYMBEG)
289
294
  rescue SyntaxError
290
295
  raise if @exception_on_syntax_error
291
296
  tk = TkError.new(@seek, @line_no, @char_no)
@@ -297,7 +302,7 @@ class RubyLex
297
302
  # Tracer.off
298
303
  tk
299
304
  end
300
-
305
+
301
306
  ENINDENT_CLAUSE = [
302
307
  "case", "class", "def", "do", "for", "if",
303
308
  "module", "unless", "until", "while", "begin" #, "when"
@@ -312,9 +317,11 @@ class RubyLex
312
317
  "r" => "/",
313
318
  "w" => "]",
314
319
  "W" => "]",
320
+ "i" => "]",
321
+ "I" => "]",
315
322
  "s" => ":"
316
323
  }
317
-
324
+
318
325
  PERCENT_PAREN = {
319
326
  "{" => "}",
320
327
  "[" => "]",
@@ -354,7 +361,7 @@ class RubyLex
354
361
  end
355
362
 
356
363
  @OP.def_rule("=begin",
357
- proc{|op, io| @prev_char_no == 0 && peek(0) =~ /\s/}) do
364
+ proc{|op, io| @prev_char_no == 0 && peek(0) =~ /\s/}) do
358
365
  |op, io|
359
366
  @ltype = "="
360
367
  until getc == "\n"; end
@@ -374,8 +381,8 @@ class RubyLex
374
381
  else
375
382
  @continue = false
376
383
  @lex_state = EXPR_BEG
377
- until (@indent_stack.empty? ||
378
- [TkLPAREN, TkLBRACK, TkLBRACE,
384
+ until (@indent_stack.empty? ||
385
+ [TkLPAREN, TkLBRACK, TkLBRACE,
379
386
  TkfLPAREN, TkfLBRACK, TkfLBRACE].include?(@indent_stack.last))
380
387
  @indent_stack.pop
381
388
  end
@@ -385,11 +392,12 @@ class RubyLex
385
392
  Token(TkNL)
386
393
  end
387
394
 
388
- @OP.def_rules("*", "**",
389
- "=", "==", "===",
390
- "=~", "<=>",
395
+ @OP.def_rules("*", "**",
396
+ "=", "==", "===",
397
+ "=~", "<=>",
391
398
  "<", "<=",
392
- ">", ">=", ">>") do
399
+ ">", ">=", ">>",
400
+ "!", "!=", "!~") do
393
401
  |op, io|
394
402
  case @lex_state
395
403
  when EXPR_FNAME, EXPR_DOT
@@ -400,19 +408,13 @@ class RubyLex
400
408
  Token(op)
401
409
  end
402
410
 
403
- @OP.def_rules("!", "!=", "!~") do
404
- |op, io|
405
- @lex_state = EXPR_BEG
406
- Token(op)
407
- end
408
-
409
411
  @OP.def_rules("<<") do
410
412
  |op, io|
411
413
  tk = nil
412
414
  if @lex_state != EXPR_END && @lex_state != EXPR_CLASS &&
413
415
  (@lex_state != EXPR_ARG || @space_seen)
414
416
  c = peek(0)
415
- if /\S/ =~ c && (/["'`]/ =~ c || /[\w_]/ =~ c || c == "-")
417
+ if /\S/ =~ c && (/["'`]/ =~ c || /\w/ =~ c || c == "-")
416
418
  tk = identify_here_document
417
419
  end
418
420
  end
@@ -455,7 +457,7 @@ class RubyLex
455
457
  @lex_state = EXPR_BEG;
456
458
  Token(TkQUESTION)
457
459
  else
458
- if (ch == '\\')
460
+ if (ch == '\\')
459
461
  read_escape
460
462
  end
461
463
  @lex_state = EXPR_END
@@ -469,8 +471,8 @@ class RubyLex
469
471
  @lex_state = EXPR_BEG
470
472
  Token(op)
471
473
  end
472
-
473
- @OP.def_rules("+=", "-=", "*=", "**=",
474
+
475
+ @OP.def_rules("+=", "-=", "*=", "**=",
474
476
  "&=", "|=", "^=", "<<=", ">>=", "||=", "&&=") do
475
477
  |op, io|
476
478
  @lex_state = EXPR_BEG
@@ -529,7 +531,7 @@ class RubyLex
529
531
 
530
532
  lex_int2
531
533
  end
532
-
534
+
533
535
  def lex_int2
534
536
  @OP.def_rules("]", "}", ")") do
535
537
  |op, io|
@@ -545,7 +547,7 @@ class RubyLex
545
547
  @lex_state = EXPR_BEG
546
548
  Token(TkCOLON)
547
549
  else
548
- @lex_state = EXPR_FNAME;
550
+ @lex_state = EXPR_FNAME
549
551
  Token(TkSYMBEG)
550
552
  end
551
553
  end
@@ -572,7 +574,7 @@ class RubyLex
572
574
  Token(TkOPASGN, "/") #/)
573
575
  elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/
574
576
  identify_string(op)
575
- else
577
+ else
576
578
  @lex_state = EXPR_BEG
577
579
  Token("/") #/)
578
580
  end
@@ -588,7 +590,7 @@ class RubyLex
588
590
  # @lex_state = EXPR_BEG
589
591
  # Token(OP_ASGN, :^)
590
592
  # end
591
-
593
+
592
594
  @OP.def_rules(",") do
593
595
  |op, io|
594
596
  @lex_state = EXPR_BEG
@@ -598,8 +600,8 @@ class RubyLex
598
600
  @OP.def_rules(";") do
599
601
  |op, io|
600
602
  @lex_state = EXPR_BEG
601
- until (@indent_stack.empty? ||
602
- [TkLPAREN, TkLBRACK, TkLBRACE,
603
+ until (@indent_stack.empty? ||
604
+ [TkLPAREN, TkLBRACK, TkLBRACE,
603
605
  TkfLPAREN, TkfLBRACK, TkfLBRACE].include?(@indent_stack.last))
604
606
  @indent_stack.pop
605
607
  end
@@ -617,7 +619,7 @@ class RubyLex
617
619
  @lex_state = EXPR_BEG
618
620
  Token("~")
619
621
  end
620
-
622
+
621
623
  @OP.def_rule("(") do
622
624
  |op, io|
623
625
  @indent += 1
@@ -629,7 +631,7 @@ class RubyLex
629
631
  tk_c = TkLPAREN
630
632
  end
631
633
  @indent_stack.push tk_c
632
- tk = Token(tk_c)
634
+ Token(tk_c)
633
635
  end
634
636
 
635
637
  @OP.def_rule("[]", proc{|op, io| @lex_state == EXPR_FNAME}) do
@@ -683,7 +685,7 @@ class RubyLex
683
685
  @continue = true
684
686
  Token(TkSPACE)
685
687
  else
686
- ungetc
688
+ read_escape
687
689
  Token("\\")
688
690
  end
689
691
  end
@@ -710,7 +712,7 @@ class RubyLex
710
712
 
711
713
  @OP.def_rule('@') do
712
714
  |op, io|
713
- if peek(0) =~ /[\w_@]/
715
+ if peek(0) =~ /[\w@]/
714
716
  ungetc
715
717
  identify_identifier
716
718
  else
@@ -718,7 +720,7 @@ class RubyLex
718
720
  end
719
721
  end
720
722
 
721
- # @OP.def_rule("def", proc{|op, io| /\s/ =~ io.peek(0)}) do
723
+ # @OP.def_rule("def", proc{|op, io| /\s/ =~ io.peek(0)}) do
722
724
  # |op, io|
723
725
  # @indent += 1
724
726
  # @lex_state = EXPR_FNAME
@@ -733,19 +735,19 @@ class RubyLex
733
735
  printf "MATCH: start %s: %s\n", op, io.inspect if RubyLex.debug?
734
736
  if peek(0) =~ /[0-9]/
735
737
  t = identify_number
736
- elsif peek(0) =~ /[\w_]/
738
+ elsif peek(0) =~ /[^\x00-\/:-@\[-^`{-\x7F]/
737
739
  t = identify_identifier
738
740
  end
739
741
  printf "MATCH: end %s: %s\n", op, io.inspect if RubyLex.debug?
740
742
  t
741
743
  end
742
-
744
+
743
745
  p @OP if RubyLex.debug?
744
746
  end
745
-
747
+
746
748
  def identify_gvar
747
749
  @lex_state = EXPR_END
748
-
750
+
749
751
  case ch = getc
750
752
  when /[~_*$?!@\/\\;,=:<>".]/ #"
751
753
  Token(TkGVAR, "$" + ch)
@@ -761,12 +763,12 @@ class RubyLex
761
763
  ungetc
762
764
  ungetc
763
765
  identify_identifier
764
- else
766
+ else
765
767
  ungetc
766
768
  Token("$")
767
769
  end
768
770
  end
769
-
771
+
770
772
  def identify_identifier
771
773
  token = ""
772
774
  if peek(0) =~ /[$@]/
@@ -776,12 +778,12 @@ class RubyLex
776
778
  end
777
779
  end
778
780
 
779
- while (ch = getc) =~ /\w|_/
781
+ while (ch = getc) =~ /[^\x00-\/:-@\[-^`{-\x7F]/
780
782
  print ":", ch, ":" if RubyLex.debug?
781
783
  token.concat ch
782
784
  end
783
785
  ungetc
784
-
786
+
785
787
  if (ch == "!" || ch == "?") && token[0,1] =~ /\w/ && peek(0) != "="
786
788
  token.concat getc
787
789
  end
@@ -799,7 +801,7 @@ class RubyLex
799
801
  @lex_state = EXPR_END
800
802
  return Token(TkIVAR, token)
801
803
  end
802
-
804
+
803
805
  if @lex_state != EXPR_DOT
804
806
  print token, "\n" if RubyLex.debug?
805
807
 
@@ -822,11 +824,11 @@ class RubyLex
822
824
  when "class"
823
825
  valid = false unless peek_match?(/^\s*(<<|\w|::)/)
824
826
  when "def"
825
- valid = false if peek_match?(/^\s*(([+-\/*&\|^]|<<|>>|\|\||\&\&)=|\&\&|\|\|)/)
827
+ valid = false if peek_match?(/^\s*(([+\-\/*&\|^]|<<|>>|\|\||\&\&)=|\&\&|\|\|)/)
826
828
  when "do"
827
- valid = false if peek_match?(/^\s*([+-\/*]?=|\*|<|>|\&)/)
829
+ valid = false if peek_match?(/^\s*([+\-\/*]?=|\*|<|>|\&)/)
828
830
  when *ENINDENT_CLAUSE
829
- valid = false if peek_match?(/^\s*([+-\/*]?=|\*|<|>|\&|\|)/)
831
+ valid = false if peek_match?(/^\s*([+\-\/*]?=|\*|<|>|\&|\|)/)
830
832
  else
831
833
  # no nothing
832
834
  end
@@ -910,10 +912,25 @@ class RubyLex
910
912
  end
911
913
 
912
914
  @here_header = false
913
- while l = gets
914
- l = l.sub(/(:?\r)?\n\z/, '')
915
- if (indent ? l.strip : l) == quoted
916
- break
915
+ # while l = gets
916
+ # l = l.sub(/(:?\r)?\n\z/, '')
917
+ # if (indent ? l.strip : l) == quoted
918
+ # break
919
+ # end
920
+ # end
921
+
922
+ line = ""
923
+ while ch = getc
924
+ if ch == "\n"
925
+ if line == quoted
926
+ break
927
+ end
928
+ line = ""
929
+ else
930
+ line.concat ch unless indent && line == "" && /\s/ =~ ch
931
+ if @ltype != "'" && ch == "#" && peek(0) == "{"
932
+ identify_string_dvar
933
+ end
917
934
  end
918
935
  end
919
936
 
@@ -927,7 +944,7 @@ class RubyLex
927
944
  @lex_state = EXPR_END
928
945
  Token(Ltype2Token[lt])
929
946
  end
930
-
947
+
931
948
  def identify_quotation
932
949
  ch = getc
933
950
  if lt = PERCENT_LTYPE[ch]
@@ -967,11 +984,11 @@ class RubyLex
967
984
  when /[0-7]/
968
985
  match = /[0-7_]/
969
986
  when /[89]/
970
- RubyLex.fail SyntaxError, "Illegal octal digit"
971
- else
987
+ RubyLex.fail SyntaxError, "Invalid octal digit"
988
+ else
972
989
  return Token(TkINTEGER)
973
990
  end
974
-
991
+
975
992
  len0 = true
976
993
  non_digit = false
977
994
  while ch = getc
@@ -999,7 +1016,7 @@ class RubyLex
999
1016
  end
1000
1017
  return Token(TkINTEGER)
1001
1018
  end
1002
-
1019
+
1003
1020
  type = TkINTEGER
1004
1021
  allow_point = true
1005
1022
  allow_e = true
@@ -1042,7 +1059,7 @@ class RubyLex
1042
1059
  end
1043
1060
  Token(type)
1044
1061
  end
1045
-
1062
+
1046
1063
  def identify_string(ltype, quoted = ltype)
1047
1064
  @ltype = ltype
1048
1065
  @quoted = quoted
@@ -1052,12 +1069,20 @@ class RubyLex
1052
1069
  while ch = getc
1053
1070
  if @quoted == ch and nest == 0
1054
1071
  break
1072
+ elsif @ltype != "'" && ch == "#" && peek(0) == "{"
1073
+ identify_string_dvar
1055
1074
  elsif @ltype != "'" && @ltype != "]" && @ltype != ":" and ch == "#"
1056
1075
  subtype = true
1076
+ elsif ch == '\\' and @ltype == "'" #'
1077
+ case ch = getc
1078
+ when "\\", "\n", "'"
1079
+ else
1080
+ ungetc
1081
+ end
1057
1082
  elsif ch == '\\' #'
1058
1083
  read_escape
1059
1084
  end
1060
- if PERCENT_PAREN.values.include?(@quoted)
1085
+ if PERCENT_PAREN.values.include?(@quoted)
1061
1086
  if PERCENT_PAREN[ch] == @quoted
1062
1087
  nest += 1
1063
1088
  elsif ch == @quoted
@@ -1066,7 +1091,7 @@ class RubyLex
1066
1091
  end
1067
1092
  end
1068
1093
  if @ltype == "/"
1069
- if peek(0) =~ /i|m|x|o|e|s|u|n/
1094
+ while /[imxoesun]/ =~ peek(0)
1070
1095
  getc
1071
1096
  end
1072
1097
  end
@@ -1081,7 +1106,43 @@ class RubyLex
1081
1106
  @lex_state = EXPR_END
1082
1107
  end
1083
1108
  end
1084
-
1109
+
1110
+ def identify_string_dvar
1111
+ begin
1112
+ getc
1113
+
1114
+ reserve_continue = @continue
1115
+ reserve_ltype = @ltype
1116
+ reserve_indent = @indent
1117
+ reserve_indent_stack = @indent_stack
1118
+ reserve_state = @lex_state
1119
+ reserve_quoted = @quoted
1120
+
1121
+ @ltype = nil
1122
+ @quoted = nil
1123
+ @indent = 0
1124
+ @indent_stack = []
1125
+ @lex_state = EXPR_BEG
1126
+
1127
+ loop do
1128
+ @continue = false
1129
+ prompt
1130
+ tk = token
1131
+ if @ltype or @continue or @indent > 0
1132
+ next
1133
+ end
1134
+ break if tk.kind_of?(TkRBRACE)
1135
+ end
1136
+ ensure
1137
+ @continue = reserve_continue
1138
+ @ltype = reserve_ltype
1139
+ @indent = reserve_indent
1140
+ @indent_stack = reserve_indent_stack
1141
+ @lex_state = reserve_state
1142
+ @quoted = reserve_quoted
1143
+ end
1144
+ end
1145
+
1085
1146
  def identify_comment
1086
1147
  @ltype = "#"
1087
1148
 
@@ -1097,7 +1158,7 @@ class RubyLex
1097
1158
  end
1098
1159
  return Token(TkCOMMENT)
1099
1160
  end
1100
-
1161
+
1101
1162
  def read_escape
1102
1163
  case ch = getc
1103
1164
  when "\n", "\r", "\f"
@@ -1114,7 +1175,7 @@ class RubyLex
1114
1175
  break
1115
1176
  end
1116
1177
  end
1117
-
1178
+
1118
1179
  when "x"
1119
1180
  2.times do
1120
1181
  case ch = getc
@@ -1143,7 +1204,8 @@ class RubyLex
1143
1204
  read_escape
1144
1205
  end
1145
1206
  else
1146
- # other characters
1207
+ # other characters
1147
1208
  end
1148
1209
  end
1149
1210
  end
1211
+ # :startdoc: