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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -2
- data/lib/irb/cmd/chws.rb +6 -6
- data/lib/irb/cmd/fork.rb +10 -10
- data/lib/irb/cmd/help.rb +24 -14
- data/lib/irb/cmd/load.rb +8 -7
- data/lib/irb/cmd/nop.rb +8 -8
- data/lib/irb/cmd/pushws.rb +6 -5
- data/lib/irb/cmd/subirb.rb +6 -7
- data/lib/irb/completion.rb +90 -58
- data/lib/irb/context.rb +197 -30
- data/lib/irb/ext/change-ws.rb +17 -10
- data/lib/irb/ext/history.rb +20 -10
- data/lib/irb/ext/loader.rb +22 -12
- data/lib/irb/ext/math-mode.rb +16 -6
- data/lib/irb/ext/multi-irb.rb +69 -24
- data/lib/irb/ext/save-history.rb +87 -37
- data/lib/irb/ext/tracer.rb +17 -7
- data/lib/irb/ext/use-loader.rb +14 -6
- data/lib/irb/ext/workspaces.rb +16 -6
- data/lib/irb/extend-command.rb +92 -34
- data/lib/irb/frame.rb +18 -5
- data/lib/irb/help.rb +20 -19
- data/lib/irb/init.rb +156 -104
- data/lib/irb/input-method.rb +96 -23
- data/lib/irb/inspector.rb +145 -0
- data/lib/irb/lc/.document +4 -0
- data/lib/irb/lc/error.rb +8 -7
- data/lib/irb/lc/{help-message.rb → help-message} +14 -11
- data/lib/irb/lc/ja/encoding_aliases.rb +10 -0
- data/lib/irb/lc/ja/error.rb +19 -16
- data/lib/irb/lc/ja/help-message +33 -28
- data/lib/irb/locale.rb +83 -85
- data/lib/irb/magic-file.rb +37 -0
- data/lib/irb/notifier.rb +101 -15
- data/lib/irb/output-method.rb +38 -32
- data/lib/irb/ruby-lex.rb +143 -81
- data/lib/irb/ruby-token.rb +13 -19
- data/lib/irb/slex.rb +26 -27
- data/lib/irb/src_encoding.rb +4 -0
- data/lib/irb/version.rb +6 -7
- data/lib/irb/workspace.rb +22 -15
- data/lib/irb/ws-for-case-2.rb +5 -6
- data/lib/irb/xmp.rb +91 -4
- data/lib/rubysl/irb/irb.rb +523 -175
- data/lib/rubysl/irb/version.rb +1 -1
- data/rubysl-irb.gemspec +7 -6
- 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 -
|
3
|
-
# $Release Version: 0.9.
|
4
|
-
# $Revision
|
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
|
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
|
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
|
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
|
-
|
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
|
data/lib/irb/output-method.rb
CHANGED
@@ -1,33 +1,38 @@
|
|
1
1
|
#
|
2
|
-
# output-method.rb -
|
3
|
-
# $Release Version: 0.9.
|
4
|
-
# $Revision
|
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
|
-
#
|
17
|
-
#
|
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
|
-
|
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
|
-
|
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
|
-
#
|
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
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
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
|
-
|
49
|
-
|
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
|
3
|
-
# $Release Version: 0.9.
|
4
|
-
# $Revision
|
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
|
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
|
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.
|
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
|
-
|
152
|
+
@rests.unshift c #c =
|
153
|
+
@seek -= 1
|
153
154
|
if c == "\n"
|
154
|
-
@line_no -= 1
|
155
|
-
if idx = @readed.
|
156
|
-
@char_no =
|
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.
|
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
|
-
">", ">=", ">>"
|
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 || /
|
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
|
-
|
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
|
-
|
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) =~ /[\
|
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) =~ /[
|
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) =~
|
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
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
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, "
|
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
|
-
|
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:
|