rubysl-irb 1.0.0

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 (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +25 -0
  6. data/README.md +29 -0
  7. data/Rakefile +1 -0
  8. data/lib/irb/cmd/chws.rb +33 -0
  9. data/lib/irb/cmd/fork.rb +39 -0
  10. data/lib/irb/cmd/help.rb +31 -0
  11. data/lib/irb/cmd/load.rb +67 -0
  12. data/lib/irb/cmd/nop.rb +39 -0
  13. data/lib/irb/cmd/pushws.rb +39 -0
  14. data/lib/irb/cmd/subirb.rb +43 -0
  15. data/lib/irb/completion.rb +205 -0
  16. data/lib/irb/context.rb +255 -0
  17. data/lib/irb/ext/change-ws.rb +62 -0
  18. data/lib/irb/ext/history.rb +110 -0
  19. data/lib/irb/ext/loader.rb +120 -0
  20. data/lib/irb/ext/math-mode.rb +37 -0
  21. data/lib/irb/ext/multi-irb.rb +241 -0
  22. data/lib/irb/ext/save-history.rb +70 -0
  23. data/lib/irb/ext/tracer.rb +61 -0
  24. data/lib/irb/ext/use-loader.rb +65 -0
  25. data/lib/irb/ext/workspaces.rb +56 -0
  26. data/lib/irb/extend-command.rb +264 -0
  27. data/lib/irb/frame.rb +67 -0
  28. data/lib/irb/help.rb +35 -0
  29. data/lib/irb/init.rb +258 -0
  30. data/lib/irb/input-method.rb +120 -0
  31. data/lib/irb/lc/error.rb +30 -0
  32. data/lib/irb/lc/help-message.rb +37 -0
  33. data/lib/irb/lc/ja/error.rb +27 -0
  34. data/lib/irb/lc/ja/help-message +36 -0
  35. data/lib/irb/locale.rb +184 -0
  36. data/lib/irb/notifier.rb +145 -0
  37. data/lib/irb/output-method.rb +85 -0
  38. data/lib/irb/rubinius.rb +55 -0
  39. data/lib/irb/ruby-lex.rb +1149 -0
  40. data/lib/irb/ruby-token.rb +273 -0
  41. data/lib/irb/slex.rb +285 -0
  42. data/lib/irb/version.rb +16 -0
  43. data/lib/irb/workspace.rb +107 -0
  44. data/lib/irb/ws-for-case-2.rb +15 -0
  45. data/lib/irb/xmp.rb +86 -0
  46. data/lib/irb.rb +1 -0
  47. data/lib/rubysl/irb/irb.rb +356 -0
  48. data/lib/rubysl/irb/version.rb +5 -0
  49. data/lib/rubysl/irb.rb +2 -0
  50. data/rubysl-irb.gemspec +31 -0
  51. metadata +219 -0
@@ -0,0 +1,85 @@
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) $
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+
13
+ require "e2mmap"
14
+
15
+ module IRB
16
+ # OutputMethod
17
+ # StdioOutputMethod
18
+
19
+ class OutputMethod
20
+ @RCS_ID='-$Id: output-method.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
21
+
22
+ def print(*opts)
23
+ IRB.fail NotImplementError, "print"
24
+ end
25
+
26
+ def printn(*opts)
27
+ print opts.join(" "), "\n"
28
+ end
29
+
30
+ # extend printf
31
+ def printf(format, *opts)
32
+ if /(%*)%I/ =~ format
33
+ format, opts = parse_printf_format(format, opts)
34
+ end
35
+ print sprintf(format, *opts)
36
+ end
37
+
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%]
44
+ def parse_printf_format(format, opts)
45
+ return format, opts if $1.size % 2 == 1
46
+ end
47
+
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
+
63
+ def puts(*objs)
64
+ for obj in objs
65
+ print(*obj)
66
+ print "\n"
67
+ end
68
+ end
69
+
70
+ def pp(*objs)
71
+ puts(*objs.collect{|obj| obj.inspect})
72
+ end
73
+
74
+ def ppx(prefix, *objs)
75
+ puts(*objs.collect{|obj| prefix+obj.inspect})
76
+ end
77
+
78
+ end
79
+
80
+ class StdioOutputMethod<OutputMethod
81
+ def print(*opts)
82
+ STDOUT.print(*opts)
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,55 @@
1
+ module IRB
2
+ class IrbRubinius < Irb
3
+
4
+ def show_exception(e)
5
+ puts "#{e.class}: #{e.message}"
6
+
7
+ bt = e.awesome_backtrace
8
+
9
+ continue = true
10
+ bt.each do |frame|
11
+ next unless continue
12
+ recv = frame.describe
13
+ loc = frame.position
14
+ if %r!kernel/common/eval.rb!.match(loc)
15
+ continue = false
16
+ next
17
+ end
18
+
19
+ if %r!main.irb_binding!.match(recv)
20
+ puts " from #{recv}"
21
+ break
22
+ end
23
+
24
+ if recv == "Object#__eval__" and frame.file == :"(irb)"
25
+ puts " from #{loc}"
26
+ else
27
+ puts " from #{recv} at #{loc}"
28
+ end
29
+ end
30
+
31
+ if e.parent
32
+ puts "\nCaused by:"
33
+ show_exception(e.parent)
34
+ end
35
+ end
36
+
37
+ def process_statements
38
+ @scanner.each_top_level_statement do |line, line_no|
39
+ signal_status(:IN_EVAL) do
40
+ begin
41
+ line.untaint
42
+ @context.evaluate(line, line_no)
43
+ output_value if @context.echo?
44
+ rescue SystemExit, Rubinius::ThrownValue => e
45
+ $! = e
46
+ rescue Object => e
47
+ show_exception(e)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ IRB.conf[:IRB_CLASS] = IRB::IrbRubinius
@@ -0,0 +1,1149 @@
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) $
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+
13
+ require "e2mmap"
14
+ require "irb/slex"
15
+ require "irb/ruby-token"
16
+
17
+ class RubyLex
18
+ @RCS_ID='-$Id: ruby-lex.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
19
+
20
+ extend Exception2MessageMapper
21
+ def_exception(:AlreadyDefinedToken, "Already defined token(%s)")
22
+ def_exception(:TkReading2TokenNoKey, "key nothing(key='%s')")
23
+ def_exception(:TkSymbol2TokenNoKey, "key nothing(key='%s')")
24
+ def_exception(:TkReading2TokenDuplicateError,
25
+ "key duplicate(token_n='%s', key='%s')")
26
+ def_exception(:SyntaxError, "%s")
27
+
28
+ def_exception(:TerminateLineInput, "Terminate Line Input")
29
+
30
+ include RubyToken
31
+
32
+ class << self
33
+ attr_accessor :debug_level
34
+ def debug?
35
+ @debug_level > 0
36
+ end
37
+ end
38
+ @debug_level = 0
39
+
40
+ def initialize
41
+ lex_init
42
+ set_input(STDIN)
43
+
44
+ @seek = 0
45
+ @exp_line_no = @line_no = 1
46
+ @base_char_no = 0
47
+ @char_no = 0
48
+ @rests = []
49
+ @readed = []
50
+ @here_readed = []
51
+
52
+ @indent = 0
53
+ @indent_stack = []
54
+ @lex_state = EXPR_BEG
55
+ @space_seen = false
56
+ @here_header = false
57
+
58
+ @continue = false
59
+ @line = ""
60
+
61
+ @skip_space = false
62
+ @readed_auto_clean_up = false
63
+ @exception_on_syntax_error = true
64
+
65
+ @prompt = nil
66
+ end
67
+
68
+ attr_accessor :skip_space
69
+ attr_accessor :readed_auto_clean_up
70
+ attr_accessor :exception_on_syntax_error
71
+
72
+ attr_reader :seek
73
+ attr_reader :char_no
74
+ attr_reader :line_no
75
+ attr_reader :indent
76
+
77
+ # io functions
78
+ def set_input(io, p = nil, &block)
79
+ @io = io
80
+ if p and p.respond_to?(:call)
81
+ @input = p
82
+ elsif block_given?
83
+ @input = block
84
+ else
85
+ @input = Proc.new{@io.gets}
86
+ end
87
+ end
88
+
89
+ def get_readed
90
+ if idx = @readed.reverse.index("\n")
91
+ @base_char_no = idx
92
+ else
93
+ @base_char_no += @readed.size
94
+ end
95
+
96
+ readed = @readed.join("")
97
+ @readed = []
98
+ readed
99
+ end
100
+
101
+ def getc
102
+ while @rests.empty?
103
+ # return nil unless buf_input
104
+ @rests.push nil unless buf_input
105
+ end
106
+ c = @rests.shift
107
+ if @here_header
108
+ @here_readed.push c
109
+ else
110
+ @readed.push c
111
+ end
112
+ @seek += 1
113
+ if c == "\n"
114
+ @line_no += 1
115
+ @char_no = 0
116
+ else
117
+ @char_no += 1
118
+ end
119
+ c
120
+ end
121
+
122
+ def gets
123
+ l = ""
124
+ while c = getc
125
+ l.concat(c)
126
+ break if c == "\n"
127
+ end
128
+ return nil if l == "" and c.nil?
129
+ l
130
+ end
131
+
132
+ def eof?
133
+ @io.eof?
134
+ end
135
+
136
+ def getc_of_rests
137
+ if @rests.empty?
138
+ nil
139
+ else
140
+ getc
141
+ end
142
+ end
143
+
144
+ def ungetc(c = nil)
145
+ if @here_readed.empty?
146
+ c2 = @readed.pop
147
+ else
148
+ c2 = @here_readed.pop
149
+ end
150
+ c = c2 unless c
151
+ @rests.unshift c #c =
152
+ @seek -= 1
153
+ if c == "\n"
154
+ @line_no -= 1
155
+ if idx = @readed.reverse.index("\n")
156
+ @char_no = @readed.size - idx
157
+ else
158
+ @char_no = @base_char_no + @readed.size
159
+ end
160
+ else
161
+ @char_no -= 1
162
+ end
163
+ end
164
+
165
+ def peek_equal?(str)
166
+ chrs = str.split(//)
167
+ until @rests.size >= chrs.size
168
+ return false unless buf_input
169
+ end
170
+ @rests[0, chrs.size] == chrs
171
+ end
172
+
173
+ def peek_match?(regexp)
174
+ while @rests.empty?
175
+ return false unless buf_input
176
+ end
177
+ regexp =~ @rests.join("")
178
+ end
179
+
180
+ def peek(i = 0)
181
+ while @rests.size <= i
182
+ return nil unless buf_input
183
+ end
184
+ @rests[i]
185
+ end
186
+
187
+ def buf_input
188
+ prompt
189
+ line = @input.call
190
+ return nil unless line
191
+ @rests.concat line.split(//)
192
+ true
193
+ end
194
+ private :buf_input
195
+
196
+ def set_prompt(p = nil, &block)
197
+ p = block if block_given?
198
+ if p.respond_to?(:call)
199
+ @prompt = p
200
+ else
201
+ @prompt = Proc.new{print p}
202
+ end
203
+ end
204
+
205
+ def prompt
206
+ if @prompt
207
+ @prompt.call(@ltype, @indent, @continue, @line_no)
208
+ end
209
+ end
210
+
211
+ def initialize_input
212
+ @ltype = nil
213
+ @quoted = nil
214
+ @indent = 0
215
+ @indent_stack = []
216
+ @lex_state = EXPR_BEG
217
+ @space_seen = false
218
+ @here_header = false
219
+
220
+ @continue = false
221
+ prompt
222
+
223
+ @line = ""
224
+ @exp_line_no = @line_no
225
+ end
226
+
227
+ def each_top_level_statement
228
+ initialize_input
229
+ catch(:TERM_INPUT) do
230
+ loop do
231
+ begin
232
+ @continue = false
233
+ prompt
234
+ unless l = lex
235
+ throw :TERM_INPUT if @line == ''
236
+ else
237
+ #p l
238
+ @line.concat l
239
+ if @ltype or @continue or @indent > 0
240
+ next
241
+ end
242
+ end
243
+ if @line != "\n"
244
+ yield @line, @exp_line_no
245
+ end
246
+ break unless l
247
+ @line = ''
248
+ @exp_line_no = @line_no
249
+
250
+ @indent = 0
251
+ @indent_stack = []
252
+ prompt
253
+ rescue TerminateLineInput
254
+ initialize_input
255
+ prompt
256
+ get_readed
257
+ end
258
+ end
259
+ end
260
+ end
261
+
262
+ def lex
263
+ until (((tk = token).kind_of?(TkNL) || tk.kind_of?(TkEND_OF_SCRIPT)) &&
264
+ !@continue or
265
+ tk.nil?)
266
+ #p tk
267
+ #p @lex_state
268
+ #p self
269
+ end
270
+ line = get_readed
271
+ # print self.inspect
272
+ if line == "" and tk.kind_of?(TkEND_OF_SCRIPT) || tk.nil?
273
+ nil
274
+ else
275
+ line
276
+ end
277
+ end
278
+
279
+ def token
280
+ # require "tracer"
281
+ # Tracer.on
282
+ @prev_seek = @seek
283
+ @prev_line_no = @line_no
284
+ @prev_char_no = @char_no
285
+ begin
286
+ begin
287
+ tk = @OP.match(self)
288
+ @space_seen = tk.kind_of?(TkSPACE)
289
+ rescue SyntaxError
290
+ raise if @exception_on_syntax_error
291
+ tk = TkError.new(@seek, @line_no, @char_no)
292
+ end
293
+ end while @skip_space and tk.kind_of?(TkSPACE)
294
+ if @readed_auto_clean_up
295
+ get_readed
296
+ end
297
+ # Tracer.off
298
+ tk
299
+ end
300
+
301
+ ENINDENT_CLAUSE = [
302
+ "case", "class", "def", "do", "for", "if",
303
+ "module", "unless", "until", "while", "begin" #, "when"
304
+ ]
305
+ DEINDENT_CLAUSE = ["end" #, "when"
306
+ ]
307
+
308
+ PERCENT_LTYPE = {
309
+ "q" => "\'",
310
+ "Q" => "\"",
311
+ "x" => "\`",
312
+ "r" => "/",
313
+ "w" => "]",
314
+ "W" => "]",
315
+ "s" => ":"
316
+ }
317
+
318
+ PERCENT_PAREN = {
319
+ "{" => "}",
320
+ "[" => "]",
321
+ "<" => ">",
322
+ "(" => ")"
323
+ }
324
+
325
+ Ltype2Token = {
326
+ "\'" => TkSTRING,
327
+ "\"" => TkSTRING,
328
+ "\`" => TkXSTRING,
329
+ "/" => TkREGEXP,
330
+ "]" => TkDSTRING,
331
+ ":" => TkSYMBOL
332
+ }
333
+ DLtype2Token = {
334
+ "\"" => TkDSTRING,
335
+ "\`" => TkDXSTRING,
336
+ "/" => TkDREGEXP,
337
+ }
338
+
339
+ def lex_init()
340
+ @OP = IRB::SLex.new
341
+ @OP.def_rules("\0", "\004", "\032") do |op, io|
342
+ Token(TkEND_OF_SCRIPT)
343
+ end
344
+
345
+ @OP.def_rules(" ", "\t", "\f", "\r", "\13") do |op, io|
346
+ @space_seen = true
347
+ while getc =~ /[ \t\f\r\13]/; end
348
+ ungetc
349
+ Token(TkSPACE)
350
+ end
351
+
352
+ @OP.def_rule("#") do |op, io|
353
+ identify_comment
354
+ end
355
+
356
+ @OP.def_rule("=begin",
357
+ proc{|op, io| @prev_char_no == 0 && peek(0) =~ /\s/}) do
358
+ |op, io|
359
+ @ltype = "="
360
+ until getc == "\n"; end
361
+ until peek_equal?("=end") && peek(4) =~ /\s/
362
+ until getc == "\n"; end
363
+ end
364
+ gets
365
+ @ltype = nil
366
+ Token(TkRD_COMMENT)
367
+ end
368
+
369
+ @OP.def_rule("\n") do |op, io|
370
+ print "\\n\n" if RubyLex.debug?
371
+ case @lex_state
372
+ when EXPR_BEG, EXPR_FNAME, EXPR_DOT
373
+ @continue = true
374
+ else
375
+ @continue = false
376
+ @lex_state = EXPR_BEG
377
+ until (@indent_stack.empty? ||
378
+ [TkLPAREN, TkLBRACK, TkLBRACE,
379
+ TkfLPAREN, TkfLBRACK, TkfLBRACE].include?(@indent_stack.last))
380
+ @indent_stack.pop
381
+ end
382
+ end
383
+ @here_header = false
384
+ @here_readed = []
385
+ Token(TkNL)
386
+ end
387
+
388
+ @OP.def_rules("*", "**",
389
+ "=", "==", "===",
390
+ "=~", "<=>",
391
+ "<", "<=",
392
+ ">", ">=", ">>") do
393
+ |op, io|
394
+ case @lex_state
395
+ when EXPR_FNAME, EXPR_DOT
396
+ @lex_state = EXPR_ARG
397
+ else
398
+ @lex_state = EXPR_BEG
399
+ end
400
+ Token(op)
401
+ end
402
+
403
+ @OP.def_rules("!", "!=", "!~") do
404
+ |op, io|
405
+ @lex_state = EXPR_BEG
406
+ Token(op)
407
+ end
408
+
409
+ @OP.def_rules("<<") do
410
+ |op, io|
411
+ tk = nil
412
+ if @lex_state != EXPR_END && @lex_state != EXPR_CLASS &&
413
+ (@lex_state != EXPR_ARG || @space_seen)
414
+ c = peek(0)
415
+ if /\S/ =~ c && (/["'`]/ =~ c || /[\w_]/ =~ c || c == "-")
416
+ tk = identify_here_document
417
+ end
418
+ end
419
+ unless tk
420
+ tk = Token(op)
421
+ case @lex_state
422
+ when EXPR_FNAME, EXPR_DOT
423
+ @lex_state = EXPR_ARG
424
+ else
425
+ @lex_state = EXPR_BEG
426
+ end
427
+ end
428
+ tk
429
+ end
430
+
431
+ @OP.def_rules("'", '"') do
432
+ |op, io|
433
+ identify_string(op)
434
+ end
435
+
436
+ @OP.def_rules("`") do
437
+ |op, io|
438
+ if @lex_state == EXPR_FNAME
439
+ @lex_state = EXPR_END
440
+ Token(op)
441
+ else
442
+ identify_string(op)
443
+ end
444
+ end
445
+
446
+ @OP.def_rules('?') do
447
+ |op, io|
448
+ if @lex_state == EXPR_END
449
+ @lex_state = EXPR_BEG
450
+ Token(TkQUESTION)
451
+ else
452
+ ch = getc
453
+ if @lex_state == EXPR_ARG && ch =~ /\s/
454
+ ungetc
455
+ @lex_state = EXPR_BEG;
456
+ Token(TkQUESTION)
457
+ else
458
+ if (ch == '\\')
459
+ read_escape
460
+ end
461
+ @lex_state = EXPR_END
462
+ Token(TkINTEGER)
463
+ end
464
+ end
465
+ end
466
+
467
+ @OP.def_rules("&", "&&", "|", "||") do
468
+ |op, io|
469
+ @lex_state = EXPR_BEG
470
+ Token(op)
471
+ end
472
+
473
+ @OP.def_rules("+=", "-=", "*=", "**=",
474
+ "&=", "|=", "^=", "<<=", ">>=", "||=", "&&=") do
475
+ |op, io|
476
+ @lex_state = EXPR_BEG
477
+ op =~ /^(.*)=$/
478
+ Token(TkOPASGN, $1)
479
+ end
480
+
481
+ @OP.def_rule("+@", proc{|op, io| @lex_state == EXPR_FNAME}) do
482
+ |op, io|
483
+ @lex_state = EXPR_ARG
484
+ Token(op)
485
+ end
486
+
487
+ @OP.def_rule("-@", proc{|op, io| @lex_state == EXPR_FNAME}) do
488
+ |op, io|
489
+ @lex_state = EXPR_ARG
490
+ Token(op)
491
+ end
492
+
493
+ @OP.def_rules("+", "-") do
494
+ |op, io|
495
+ catch(:RET) do
496
+ if @lex_state == EXPR_ARG
497
+ if @space_seen and peek(0) =~ /[0-9]/
498
+ throw :RET, identify_number
499
+ else
500
+ @lex_state = EXPR_BEG
501
+ end
502
+ elsif @lex_state != EXPR_END and peek(0) =~ /[0-9]/
503
+ throw :RET, identify_number
504
+ else
505
+ @lex_state = EXPR_BEG
506
+ end
507
+ Token(op)
508
+ end
509
+ end
510
+
511
+ @OP.def_rule(".") do
512
+ |op, io|
513
+ @lex_state = EXPR_BEG
514
+ if peek(0) =~ /[0-9]/
515
+ ungetc
516
+ identify_number
517
+ else
518
+ # for "obj.if" etc.
519
+ @lex_state = EXPR_DOT
520
+ Token(TkDOT)
521
+ end
522
+ end
523
+
524
+ @OP.def_rules("..", "...") do
525
+ |op, io|
526
+ @lex_state = EXPR_BEG
527
+ Token(op)
528
+ end
529
+
530
+ lex_int2
531
+ end
532
+
533
+ def lex_int2
534
+ @OP.def_rules("]", "}", ")") do
535
+ |op, io|
536
+ @lex_state = EXPR_END
537
+ @indent -= 1
538
+ @indent_stack.pop
539
+ Token(op)
540
+ end
541
+
542
+ @OP.def_rule(":") do
543
+ |op, io|
544
+ if @lex_state == EXPR_END || peek(0) =~ /\s/
545
+ @lex_state = EXPR_BEG
546
+ Token(TkCOLON)
547
+ else
548
+ @lex_state = EXPR_FNAME;
549
+ Token(TkSYMBEG)
550
+ end
551
+ end
552
+
553
+ @OP.def_rule("::") do
554
+ |op, io|
555
+ # p @lex_state.id2name, @space_seen
556
+ if @lex_state == EXPR_BEG or @lex_state == EXPR_ARG && @space_seen
557
+ @lex_state = EXPR_BEG
558
+ Token(TkCOLON3)
559
+ else
560
+ @lex_state = EXPR_DOT
561
+ Token(TkCOLON2)
562
+ end
563
+ end
564
+
565
+ @OP.def_rule("/") do
566
+ |op, io|
567
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
568
+ identify_string(op)
569
+ elsif peek(0) == '='
570
+ getc
571
+ @lex_state = EXPR_BEG
572
+ Token(TkOPASGN, "/") #/)
573
+ elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/
574
+ identify_string(op)
575
+ else
576
+ @lex_state = EXPR_BEG
577
+ Token("/") #/)
578
+ end
579
+ end
580
+
581
+ @OP.def_rules("^") do
582
+ |op, io|
583
+ @lex_state = EXPR_BEG
584
+ Token("^")
585
+ end
586
+
587
+ # @OP.def_rules("^=") do
588
+ # @lex_state = EXPR_BEG
589
+ # Token(OP_ASGN, :^)
590
+ # end
591
+
592
+ @OP.def_rules(",") do
593
+ |op, io|
594
+ @lex_state = EXPR_BEG
595
+ Token(op)
596
+ end
597
+
598
+ @OP.def_rules(";") do
599
+ |op, io|
600
+ @lex_state = EXPR_BEG
601
+ until (@indent_stack.empty? ||
602
+ [TkLPAREN, TkLBRACK, TkLBRACE,
603
+ TkfLPAREN, TkfLBRACK, TkfLBRACE].include?(@indent_stack.last))
604
+ @indent_stack.pop
605
+ end
606
+ Token(op)
607
+ end
608
+
609
+ @OP.def_rule("~") do
610
+ |op, io|
611
+ @lex_state = EXPR_BEG
612
+ Token("~")
613
+ end
614
+
615
+ @OP.def_rule("~@", proc{|op, io| @lex_state == EXPR_FNAME}) do
616
+ |op, io|
617
+ @lex_state = EXPR_BEG
618
+ Token("~")
619
+ end
620
+
621
+ @OP.def_rule("(") do
622
+ |op, io|
623
+ @indent += 1
624
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
625
+ @lex_state = EXPR_BEG
626
+ tk_c = TkfLPAREN
627
+ else
628
+ @lex_state = EXPR_BEG
629
+ tk_c = TkLPAREN
630
+ end
631
+ @indent_stack.push tk_c
632
+ tk = Token(tk_c)
633
+ end
634
+
635
+ @OP.def_rule("[]", proc{|op, io| @lex_state == EXPR_FNAME}) do
636
+ |op, io|
637
+ @lex_state = EXPR_ARG
638
+ Token("[]")
639
+ end
640
+
641
+ @OP.def_rule("[]=", proc{|op, io| @lex_state == EXPR_FNAME}) do
642
+ |op, io|
643
+ @lex_state = EXPR_ARG
644
+ Token("[]=")
645
+ end
646
+
647
+ @OP.def_rule("[") do
648
+ |op, io|
649
+ @indent += 1
650
+ if @lex_state == EXPR_FNAME
651
+ tk_c = TkfLBRACK
652
+ else
653
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
654
+ tk_c = TkLBRACK
655
+ elsif @lex_state == EXPR_ARG && @space_seen
656
+ tk_c = TkLBRACK
657
+ else
658
+ tk_c = TkfLBRACK
659
+ end
660
+ @lex_state = EXPR_BEG
661
+ end
662
+ @indent_stack.push tk_c
663
+ Token(tk_c)
664
+ end
665
+
666
+ @OP.def_rule("{") do
667
+ |op, io|
668
+ @indent += 1
669
+ if @lex_state != EXPR_END && @lex_state != EXPR_ARG
670
+ tk_c = TkLBRACE
671
+ else
672
+ tk_c = TkfLBRACE
673
+ end
674
+ @lex_state = EXPR_BEG
675
+ @indent_stack.push tk_c
676
+ Token(tk_c)
677
+ end
678
+
679
+ @OP.def_rule('\\') do
680
+ |op, io|
681
+ if getc == "\n"
682
+ @space_seen = true
683
+ @continue = true
684
+ Token(TkSPACE)
685
+ else
686
+ ungetc
687
+ Token("\\")
688
+ end
689
+ end
690
+
691
+ @OP.def_rule('%') do
692
+ |op, io|
693
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
694
+ identify_quotation
695
+ elsif peek(0) == '='
696
+ getc
697
+ Token(TkOPASGN, :%)
698
+ elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/
699
+ identify_quotation
700
+ else
701
+ @lex_state = EXPR_BEG
702
+ Token("%") #))
703
+ end
704
+ end
705
+
706
+ @OP.def_rule('$') do
707
+ |op, io|
708
+ identify_gvar
709
+ end
710
+
711
+ @OP.def_rule('@') do
712
+ |op, io|
713
+ if peek(0) =~ /[\w_@]/
714
+ ungetc
715
+ identify_identifier
716
+ else
717
+ Token("@")
718
+ end
719
+ end
720
+
721
+ # @OP.def_rule("def", proc{|op, io| /\s/ =~ io.peek(0)}) do
722
+ # |op, io|
723
+ # @indent += 1
724
+ # @lex_state = EXPR_FNAME
725
+ # # @lex_state = EXPR_END
726
+ # # until @rests[0] == "\n" or @rests[0] == ";"
727
+ # # rests.shift
728
+ # # end
729
+ # end
730
+
731
+ @OP.def_rule("") do
732
+ |op, io|
733
+ printf "MATCH: start %s: %s\n", op, io.inspect if RubyLex.debug?
734
+ if peek(0) =~ /[0-9]/
735
+ t = identify_number
736
+ elsif peek(0) =~ /[\w_]/
737
+ t = identify_identifier
738
+ end
739
+ printf "MATCH: end %s: %s\n", op, io.inspect if RubyLex.debug?
740
+ t
741
+ end
742
+
743
+ p @OP if RubyLex.debug?
744
+ end
745
+
746
+ def identify_gvar
747
+ @lex_state = EXPR_END
748
+
749
+ case ch = getc
750
+ when /[~_*$?!@\/\\;,=:<>".]/ #"
751
+ Token(TkGVAR, "$" + ch)
752
+ when "-"
753
+ Token(TkGVAR, "$-" + getc)
754
+ when "&", "`", "'", "+"
755
+ Token(TkBACK_REF, "$"+ch)
756
+ when /[1-9]/
757
+ while getc =~ /[0-9]/; end
758
+ ungetc
759
+ Token(TkNTH_REF)
760
+ when /\w/
761
+ ungetc
762
+ ungetc
763
+ identify_identifier
764
+ else
765
+ ungetc
766
+ Token("$")
767
+ end
768
+ end
769
+
770
+ def identify_identifier
771
+ token = ""
772
+ if peek(0) =~ /[$@]/
773
+ token.concat(c = getc)
774
+ if c == "@" and peek(0) == "@"
775
+ token.concat getc
776
+ end
777
+ end
778
+
779
+ while (ch = getc) =~ /\w|_/
780
+ print ":", ch, ":" if RubyLex.debug?
781
+ token.concat ch
782
+ end
783
+ ungetc
784
+
785
+ if (ch == "!" || ch == "?") && token[0,1] =~ /\w/ && peek(0) != "="
786
+ token.concat getc
787
+ end
788
+
789
+ # almost fix token
790
+
791
+ case token
792
+ when /^\$/
793
+ return Token(TkGVAR, token)
794
+ when /^\@\@/
795
+ @lex_state = EXPR_END
796
+ # p Token(TkCVAR, token)
797
+ return Token(TkCVAR, token)
798
+ when /^\@/
799
+ @lex_state = EXPR_END
800
+ return Token(TkIVAR, token)
801
+ end
802
+
803
+ if @lex_state != EXPR_DOT
804
+ print token, "\n" if RubyLex.debug?
805
+
806
+ token_c, *trans = TkReading2Token[token]
807
+ if token_c
808
+ # reserved word?
809
+
810
+ if (@lex_state != EXPR_BEG &&
811
+ @lex_state != EXPR_FNAME &&
812
+ trans[1])
813
+ # modifiers
814
+ token_c = TkSymbol2Token[trans[1]]
815
+ @lex_state = trans[0]
816
+ else
817
+ if @lex_state != EXPR_FNAME
818
+ if ENINDENT_CLAUSE.include?(token)
819
+ # check for ``class = val'' etc.
820
+ valid = true
821
+ case token
822
+ when "class"
823
+ valid = false unless peek_match?(/^\s*(<<|\w|::)/)
824
+ when "def"
825
+ valid = false if peek_match?(/^\s*(([+-\/*&\|^]|<<|>>|\|\||\&\&)=|\&\&|\|\|)/)
826
+ when "do"
827
+ valid = false if peek_match?(/^\s*([+-\/*]?=|\*|<|>|\&)/)
828
+ when *ENINDENT_CLAUSE
829
+ valid = false if peek_match?(/^\s*([+-\/*]?=|\*|<|>|\&|\|)/)
830
+ else
831
+ # no nothing
832
+ end
833
+ if valid
834
+ if token == "do"
835
+ if ![TkFOR, TkWHILE, TkUNTIL].include?(@indent_stack.last)
836
+ @indent += 1
837
+ @indent_stack.push token_c
838
+ end
839
+ else
840
+ @indent += 1
841
+ @indent_stack.push token_c
842
+ end
843
+ # p @indent_stack
844
+ end
845
+
846
+ elsif DEINDENT_CLAUSE.include?(token)
847
+ @indent -= 1
848
+ @indent_stack.pop
849
+ end
850
+ @lex_state = trans[0]
851
+ else
852
+ @lex_state = EXPR_END
853
+ end
854
+ end
855
+ return Token(token_c, token)
856
+ end
857
+ end
858
+
859
+ if @lex_state == EXPR_FNAME
860
+ @lex_state = EXPR_END
861
+ if peek(0) == '='
862
+ token.concat getc
863
+ end
864
+ elsif @lex_state == EXPR_BEG || @lex_state == EXPR_DOT
865
+ @lex_state = EXPR_ARG
866
+ else
867
+ @lex_state = EXPR_END
868
+ end
869
+
870
+ if token[0, 1] =~ /[A-Z]/
871
+ return Token(TkCONSTANT, token)
872
+ elsif token[token.size - 1, 1] =~ /[!?]/
873
+ return Token(TkFID, token)
874
+ else
875
+ return Token(TkIDENTIFIER, token)
876
+ end
877
+ end
878
+
879
+ def identify_here_document
880
+ ch = getc
881
+ # if lt = PERCENT_LTYPE[ch]
882
+ if ch == "-"
883
+ ch = getc
884
+ indent = true
885
+ end
886
+ if /['"`]/ =~ ch
887
+ lt = ch
888
+ quoted = ""
889
+ while (c = getc) && c != lt
890
+ quoted.concat c
891
+ end
892
+ else
893
+ lt = '"'
894
+ quoted = ch.dup
895
+ while (c = getc) && c =~ /\w/
896
+ quoted.concat c
897
+ end
898
+ ungetc
899
+ end
900
+
901
+ ltback, @ltype = @ltype, lt
902
+ reserve = []
903
+ while ch = getc
904
+ reserve.push ch
905
+ if ch == "\\"
906
+ reserve.push ch = getc
907
+ elsif ch == "\n"
908
+ break
909
+ end
910
+ end
911
+
912
+ @here_header = false
913
+ while l = gets
914
+ l = l.sub(/(:?\r)?\n\z/, '')
915
+ if (indent ? l.strip : l) == quoted
916
+ break
917
+ end
918
+ end
919
+
920
+ @here_header = true
921
+ @here_readed.concat reserve
922
+ while ch = reserve.pop
923
+ ungetc ch
924
+ end
925
+
926
+ @ltype = ltback
927
+ @lex_state = EXPR_END
928
+ Token(Ltype2Token[lt])
929
+ end
930
+
931
+ def identify_quotation
932
+ ch = getc
933
+ if lt = PERCENT_LTYPE[ch]
934
+ ch = getc
935
+ elsif ch =~ /\W/
936
+ lt = "\""
937
+ else
938
+ RubyLex.fail SyntaxError, "unknown type of %string"
939
+ end
940
+ # if ch !~ /\W/
941
+ # ungetc
942
+ # next
943
+ # end
944
+ #@ltype = lt
945
+ @quoted = ch unless @quoted = PERCENT_PAREN[ch]
946
+ identify_string(lt, @quoted)
947
+ end
948
+
949
+ def identify_number
950
+ @lex_state = EXPR_END
951
+
952
+ if peek(0) == "0" && peek(1) !~ /[.eE]/
953
+ getc
954
+ case peek(0)
955
+ when /[xX]/
956
+ ch = getc
957
+ match = /[0-9a-fA-F_]/
958
+ when /[bB]/
959
+ ch = getc
960
+ match = /[01_]/
961
+ when /[oO]/
962
+ ch = getc
963
+ match = /[0-7_]/
964
+ when /[dD]/
965
+ ch = getc
966
+ match = /[0-9_]/
967
+ when /[0-7]/
968
+ match = /[0-7_]/
969
+ when /[89]/
970
+ RubyLex.fail SyntaxError, "Illegal octal digit"
971
+ else
972
+ return Token(TkINTEGER)
973
+ end
974
+
975
+ len0 = true
976
+ non_digit = false
977
+ while ch = getc
978
+ if match =~ ch
979
+ if ch == "_"
980
+ if non_digit
981
+ RubyLex.fail SyntaxError, "trailing `#{ch}' in number"
982
+ else
983
+ non_digit = ch
984
+ end
985
+ else
986
+ non_digit = false
987
+ len0 = false
988
+ end
989
+ else
990
+ ungetc
991
+ if len0
992
+ RubyLex.fail SyntaxError, "numeric literal without digits"
993
+ end
994
+ if non_digit
995
+ RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number"
996
+ end
997
+ break
998
+ end
999
+ end
1000
+ return Token(TkINTEGER)
1001
+ end
1002
+
1003
+ type = TkINTEGER
1004
+ allow_point = true
1005
+ allow_e = true
1006
+ non_digit = false
1007
+ while ch = getc
1008
+ case ch
1009
+ when /[0-9]/
1010
+ non_digit = false
1011
+ when "_"
1012
+ non_digit = ch
1013
+ when allow_point && "."
1014
+ if non_digit
1015
+ RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number"
1016
+ end
1017
+ type = TkFLOAT
1018
+ if peek(0) !~ /[0-9]/
1019
+ type = TkINTEGER
1020
+ ungetc
1021
+ break
1022
+ end
1023
+ allow_point = false
1024
+ when allow_e && "e", allow_e && "E"
1025
+ if non_digit
1026
+ RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number"
1027
+ end
1028
+ type = TkFLOAT
1029
+ if peek(0) =~ /[+-]/
1030
+ getc
1031
+ end
1032
+ allow_e = false
1033
+ allow_point = false
1034
+ non_digit = ch
1035
+ else
1036
+ if non_digit
1037
+ RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number"
1038
+ end
1039
+ ungetc
1040
+ break
1041
+ end
1042
+ end
1043
+ Token(type)
1044
+ end
1045
+
1046
+ def identify_string(ltype, quoted = ltype)
1047
+ @ltype = ltype
1048
+ @quoted = quoted
1049
+ subtype = nil
1050
+ begin
1051
+ nest = 0
1052
+ while ch = getc
1053
+ if @quoted == ch and nest == 0
1054
+ break
1055
+ elsif @ltype != "'" && @ltype != "]" && @ltype != ":" and ch == "#"
1056
+ subtype = true
1057
+ elsif ch == '\\' #'
1058
+ read_escape
1059
+ end
1060
+ if PERCENT_PAREN.values.include?(@quoted)
1061
+ if PERCENT_PAREN[ch] == @quoted
1062
+ nest += 1
1063
+ elsif ch == @quoted
1064
+ nest -= 1
1065
+ end
1066
+ end
1067
+ end
1068
+ if @ltype == "/"
1069
+ if peek(0) =~ /i|m|x|o|e|s|u|n/
1070
+ getc
1071
+ end
1072
+ end
1073
+ if subtype
1074
+ Token(DLtype2Token[ltype])
1075
+ else
1076
+ Token(Ltype2Token[ltype])
1077
+ end
1078
+ ensure
1079
+ @ltype = nil
1080
+ @quoted = nil
1081
+ @lex_state = EXPR_END
1082
+ end
1083
+ end
1084
+
1085
+ def identify_comment
1086
+ @ltype = "#"
1087
+
1088
+ while ch = getc
1089
+ # if ch == "\\" #"
1090
+ # read_escape
1091
+ # end
1092
+ if ch == "\n"
1093
+ @ltype = nil
1094
+ ungetc
1095
+ break
1096
+ end
1097
+ end
1098
+ return Token(TkCOMMENT)
1099
+ end
1100
+
1101
+ def read_escape
1102
+ case ch = getc
1103
+ when "\n", "\r", "\f"
1104
+ when "\\", "n", "t", "r", "f", "v", "a", "e", "b", "s" #"
1105
+ when /[0-7]/
1106
+ ungetc ch
1107
+ 3.times do
1108
+ case ch = getc
1109
+ when /[0-7]/
1110
+ when nil
1111
+ break
1112
+ else
1113
+ ungetc
1114
+ break
1115
+ end
1116
+ end
1117
+
1118
+ when "x"
1119
+ 2.times do
1120
+ case ch = getc
1121
+ when /[0-9a-fA-F]/
1122
+ when nil
1123
+ break
1124
+ else
1125
+ ungetc
1126
+ break
1127
+ end
1128
+ end
1129
+
1130
+ when "M"
1131
+ if (ch = getc) != '-'
1132
+ ungetc
1133
+ else
1134
+ if (ch = getc) == "\\" #"
1135
+ read_escape
1136
+ end
1137
+ end
1138
+
1139
+ when "C", "c" #, "^"
1140
+ if ch == "C" and (ch = getc) != "-"
1141
+ ungetc
1142
+ elsif (ch = getc) == "\\" #"
1143
+ read_escape
1144
+ end
1145
+ else
1146
+ # other characters
1147
+ end
1148
+ end
1149
+ end