rubysl-irb 1.0.2 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
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: