rubylexer 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/History.txt +90 -0
  2. data/Manifest.txt +54 -3
  3. data/README.txt +4 -7
  4. data/Rakefile +3 -2
  5. data/lib/rubylexer.rb +856 -323
  6. data/lib/rubylexer/0.7.0.rb +11 -2
  7. data/lib/rubylexer/0.7.1.rb +2 -0
  8. data/lib/rubylexer/charhandler.rb +4 -4
  9. data/lib/rubylexer/context.rb +86 -9
  10. data/lib/rubylexer/rulexer.rb +455 -101
  11. data/lib/rubylexer/token.rb +166 -43
  12. data/lib/rubylexer/tokenprinter.rb +16 -8
  13. data/lib/rubylexer/version.rb +1 -1
  14. data/rubylexer.vpj +98 -0
  15. data/test/code/all_the_gems.rb +33 -0
  16. data/test/code/all_the_raas.rb +226 -0
  17. data/test/code/all_the_rubies.rb +2 -0
  18. data/test/code/deletewarns.rb +19 -1
  19. data/test/code/dumptokens.rb +39 -8
  20. data/test/code/errscan +2 -0
  21. data/test/code/isolate_error.rb +72 -0
  22. data/test/code/lexloop +14 -0
  23. data/test/code/locatetest.rb +150 -8
  24. data/test/code/regression.rb +109 -0
  25. data/test/code/rubylexervsruby.rb +53 -15
  26. data/test/code/strgen.rb +138 -0
  27. data/test/code/tarball.rb +144 -0
  28. data/test/code/testcases.rb +11 -0
  29. data/test/code/tokentest.rb +115 -24
  30. data/test/data/__eof2.rb +1 -0
  31. data/test/data/__eof5.rb +2 -0
  32. data/test/data/__eof6.rb +2 -0
  33. data/test/data/cvtesc.rb +17 -0
  34. data/test/data/g.rb +6 -0
  35. data/test/data/hd0.rb +3 -0
  36. data/test/data/hdateof.rb +2 -0
  37. data/test/data/hdempty.rb +3 -0
  38. data/test/data/hdr.rb +9 -0
  39. data/test/data/hdr_dos.rb +13 -0
  40. data/test/data/hdr_dos2.rb +18 -0
  41. data/test/data/heart.rb +2 -0
  42. data/test/data/here_escnl.rb +25 -0
  43. data/test/data/here_escnl_dos.rb +20 -0
  44. data/test/data/here_squote.rb +3 -0
  45. data/test/data/heremonsters.rb +140 -0
  46. data/test/data/heremonsters.rb.broken +68 -0
  47. data/test/data/heremonsters.rb.broken.save +68 -0
  48. data/test/data/heremonsters_dos.rb +140 -0
  49. data/test/data/heremonsters_dos.rb.broken +68 -0
  50. data/test/data/illegal_oneliners.rb +1 -0
  51. data/test/data/illegal_stanzas.rb +0 -0
  52. data/test/data/make_ws_strdelim.rb +22 -0
  53. data/test/data/maven2_builer_test.rb +82 -0
  54. data/test/data/migration.rb +8944 -0
  55. data/test/data/modl.rb +6 -0
  56. data/test/data/modl_dos.rb +7 -0
  57. data/test/data/modl_fails.rb +10 -0
  58. data/test/data/multilinestring.rb +6 -0
  59. data/test/data/oneliners.rb +555 -0
  60. data/test/data/p-op.rb +2 -0
  61. data/test/data/p.rb +3 -1710
  62. data/test/data/s.rb +90 -21
  63. data/test/data/simple.rb +1 -0
  64. data/test/data/simple_dos.rb +1 -0
  65. data/test/data/stanzas.rb +1194 -0
  66. data/test/data/strdelim_crlf.rb +6 -0
  67. data/test/data/stuff.rb +6 -0
  68. data/test/data/stuff2.rb +5 -0
  69. data/test/data/stuff3.rb +6 -0
  70. data/test/data/stuff4.rb +6 -0
  71. data/test/data/tkweird.rb +20 -0
  72. data/test/data/unending_stuff.rb +5 -0
  73. data/test/data/whatnot.rb +8 -0
  74. data/test/data/ws_strdelim.rb +0 -0
  75. data/test/test.sh +239 -0
  76. data/testing.txt +39 -50
  77. metadata +110 -12
  78. data/test/code/dl_all_gems.rb +0 -43
  79. data/test/code/unpack_all_gems.rb +0 -15
  80. data/test/data/gemlist.txt +0 -280
@@ -0,0 +1,138 @@
1
+ module Strgen
2
+ PAIRS=[
3
+ ['<','>'],
4
+ ['(',')'],
5
+ ['[',']'],
6
+ ['{','}']
7
+ ]
8
+ ALLOWED_UNNESTING_FANCY=/[^<>\[\]{}()a-z0-9_]/i
9
+ FANCY_TYPES=%w[q Q r s x w W]<<''
10
+ SIMPLE_QUOTES=%w[" ' / `]
11
+ SIMPLE_ESCAPES=%w[s n r t v f a b e]
12
+ MULTI_ESCAPES=%w[x c C M 0 1 2 3 4 5 6 7]
13
+ NON_ESCAPES=/[^#{SIMPLE_ESCAPES+MULTI_ESCAPES}]/
14
+
15
+ def Strgen.rand_char_including(allow,disallow='')
16
+ q=nil
17
+ q=rand(255).chr until ((allow===q) and not (disallow[q]))
18
+ q
19
+ end
20
+
21
+ def Strgen.rand_esc_seq(disallow,bsonly)
22
+ limit=4
23
+ bsonly[/\\/] and disallow+='\\'
24
+ (disallow['#'] or bsonly['#']) and limit=3
25
+ choice=rand limit
26
+ choice=3 if disallow[/\\/] or bsonly[/\#/]
27
+ case choice
28
+ when 0: "\\"+rand_char_including(NON_ESCAPES,disallow)
29
+ when 1: "\\"+SIMPLE_ESCAPES[rand(SIMPLE_ESCAPES.size)]
30
+ when 2:
31
+ "\\"+
32
+ case ch=MULTI_ESCAPES[rand(MULTI_ESCAPES.size)]
33
+ when "x": "x"+rand(256).to_s(16)
34
+ when "0".."7": rand(256).to_s(8)
35
+ when "c":
36
+ "c"+
37
+ if rand(2).zero?
38
+ rand_char_including(/[^\\]/,disallow+bsonly)
39
+ else
40
+ rand_esc_seq disallow+"#",bsonly
41
+ end
42
+ when "C","M":
43
+ return rand_esc_seq(disallow,bsonly) if disallow['-'] or bsonly['-']
44
+ ch+"-"+
45
+ if rand(2).zero?
46
+ rand_char_including(/[^\\]/,disallow+bsonly)
47
+ else
48
+ rand_esc_seq disallow+"#",bsonly
49
+ end
50
+ end
51
+ when 3:
52
+ '#{'+rand(9999999999).to_s+'}'
53
+ end
54
+ end
55
+
56
+ CACHE={}
57
+
58
+ def Strgen.strgen
59
+ must_be_escaped="#\\"
60
+ case rand(3)
61
+ when 0
62
+ starter=ender=SIMPLE_QUOTES[rand(SIMPLE_QUOTES.size)]
63
+ must_be_escaped<<starter
64
+ when 1
65
+ type=FANCY_TYPES[rand(FANCY_TYPES.size)]
66
+ pair=PAIRS[rand(PAIRS.size)]
67
+ starter= "%"+type+pair[0]
68
+ ender= pair[1]
69
+ must_be_escaped<<pair.to_s
70
+ when 2
71
+ type=FANCY_TYPES[rand(FANCY_TYPES.size)]
72
+ q=rand_char_including ALLOWED_UNNESTING_FANCY
73
+ /w/i===type and /\s|\v/===q and q='"'
74
+ starter= "%"+type+q
75
+ ender=q
76
+ must_be_escaped<<q
77
+ end
78
+
79
+ if starter=="/" or type=='r'
80
+ must_be_escaped+="[]{}()?+*"
81
+ end
82
+ must_be_escaped+="\0" if type=='s'
83
+ ckey=must_be_escaped
84
+ ordinary=
85
+ CACHE[ckey]||=
86
+ /[^#{must_be_escaped.gsub(/./){"\\"+$&}}]/
87
+
88
+ interior=(1..rand(40)).map{|x|
89
+ rand_char_including ordinary
90
+ }.to_s
91
+
92
+ interior["\\"] and fail
93
+
94
+ disallow=''
95
+ bsonly=starter[-1,1]+ender
96
+ # disallow+='#' if /[\#\\\-]/===starter[-1,1]
97
+ # disallow+=starter[-1,1]+ender if type=='r' or starter=='/'
98
+ disallow+="\0" if type=='s'
99
+ disallow+=must_be_escaped.gsub('\\','') if type=='r' or starter=='/'
100
+
101
+ poslimit=interior.size+1
102
+ rand(5).times{
103
+ pos=rand poslimit
104
+ interior[pos,0]=rand_esc_seq disallow,bsonly
105
+ poslimit=pos
106
+ } unless starter[-1]==?\\
107
+
108
+ interior.gsub!(/\\[a-z]/i,'') if type=='r' or starter=='/'
109
+
110
+ starter[-1]==?\r and interior.gsub!(/\A\n+/,'')
111
+
112
+ starter[1]==?s and interior=='' and interior="x"
113
+
114
+ result= starter+interior+ender
115
+
116
+ begin
117
+ begin eval "BEGIN{break};proc() do #{result} end" end while false
118
+ rescue Exception
119
+ #puts %<failing string: eval "#{result.gsub(/./){'\\x'+$&[0].to_s(16)}}">
120
+ return strgen
121
+ end
122
+
123
+ return result
124
+ end
125
+ end
126
+
127
+ if __FILE__==$0
128
+ start=Time.now
129
+ i=0
130
+ 10_000_000.times{|i|
131
+ begin
132
+ ss=Strgen.strgen
133
+ RubyLexerVsRuby.rubylexervsruby "-e#{i}", ss
134
+ rescue Exception
135
+ puts %<failing string: eval "#{ss.gsub(/./){'\\x'+$&[0].to_s(16)}}">
136
+ end
137
+ }
138
+ end
@@ -0,0 +1,144 @@
1
+ require 'open-uri'
2
+
3
+ class Tarball
4
+ PROTOCOLS=%w[http https ftp]
5
+ EXTENSIONS=%w[tar zip rb tgz tbz2 tbz gem]
6
+ EXTRA_EXTENSIONS=%w[gz bz2 Z]
7
+ EXTRA_EXTENSIONS_REX="\\.(?:#{EXTRA_EXTENSIONS.join'|'})"
8
+ VERSIONTOO='' #was: "(?:[_-](.*))"
9
+ ENDINGS="\\.(?:#{EXTENSIONS.join('|')})(?:#{EXTRA_EXTENSIONS_REX})?"
10
+ TARBALL=%r<
11
+ \A(?:#{PROTOCOLS.join('|')})://
12
+ (?:[^/]+/)+
13
+ (.*)
14
+ #{VERSIONTOO}
15
+ #{ENDINGS}
16
+ \Z
17
+ >ixo
18
+
19
+ def Tarball.unpack1gem(gem)
20
+ dir=gem.dup
21
+ dir[/\.gem$/]=''
22
+ Dir.mkdir dir rescue nil
23
+
24
+ system "tar x -f #{gem} -C #{dir}"
25
+ files_in_dir=Dir[dir+"/*"]-[dir+"/data.tar.gz",dir+"/metadata.gz"]
26
+ files_in_dir.empty? or puts "gem archive toplevel contains extra files: #{files_in_dir.join(' ')}"
27
+ system "gunzip -f #{dir}/metadata.gz -c > #{dir}/metadata"
28
+ system "tar xz -f #{dir}/data.tar.gz -C #{dir}"
29
+
30
+
31
+ (File.unlink gem rescue nil) if File.exist? dir+"/metadata.gz" and File.exist? dir+"/data.tar.gz"
32
+ (File.unlink dir+"/metadata.gz" rescue nil) if File.exist? dir+"/metadata"
33
+ files_in_dir=Dir[dir+"/*"]-[dir+"/data.tar.gz",dir+"/metadata.gz",dir+"/metadata"]-files_in_dir
34
+ (File.unlink dir+"/data.tar.gz" rescue nil) unless files_in_dir.empty?
35
+ end
36
+
37
+ def Tarball.dl_and_unpack(cachedir,url)
38
+ projectname=url[%r{[^/]+\Z}]
39
+ localname=cachedir+projectname
40
+ projectname.sub!(/#{ENDINGS}\Z/o,'')+"/"
41
+ localdir= cachedir+projectname
42
+ #localdir=localname.sub(/#{ENDINGS}\Z/o,'')+"/"
43
+
44
+ if File.exist? localdir
45
+ puts "skipping already extant #{localdir}"
46
+ return
47
+ end
48
+ begin
49
+ open(localname,"w"){|disk|
50
+ open(url){|net|
51
+ while buf=net.read(40960)
52
+ disk.write buf
53
+ end
54
+ }
55
+ }
56
+ rescue Interrupt=>e
57
+ File.unlink localname rescue nil
58
+ raise if e.class==Interrupt
59
+ return
60
+ rescue Exception
61
+ File.unlink localname rescue nil
62
+ return
63
+ end
64
+
65
+ unpack(cachedir,localname,projectname,localdir)
66
+ end
67
+
68
+ def Tarball.unpack(cachedir,localname,
69
+ projectname=localname[/\/(.*)#{ENDINGS}\Z/,1],
70
+ localdir=localname.sub(/#{ENDINGS}\Z/o,'')+"/")
71
+ cachedir[-1]==?/ or fail
72
+ localname[0,cachedir.size]==cachedir or fail
73
+
74
+ if File.exist? localdir
75
+ puts "skipping already extant #{localdir}"
76
+ return
77
+ end
78
+
79
+ #rename .tgz,.tbz2? to the full form
80
+ case localname
81
+ when /\.tgz\Z/:
82
+ oldln=localname
83
+ localname=localname[0...-4]+".tar.gz"
84
+ when /\.tbz2?\Z/:
85
+ oldln=localname
86
+ localname=localname[0...-$&.size]+".tar.bz2"
87
+ end
88
+ File.rename oldln, localname if oldln
89
+
90
+ #remove any gz or bz2 whole-archive compression
91
+ case localname
92
+ when /\.bz2\Z/:
93
+ system "bunzip2 "+localname or return
94
+ localname=localname[0...-$&.size]
95
+ when /\.(gz|Z)\Z/:
96
+ system "gunzip -f "+localname or return
97
+ localname=localname[0...-$&.size]
98
+ end
99
+
100
+ #now actually unpack the archive
101
+ case localname
102
+ when /\.rb\Z/:
103
+ Dir.mkdir localdir
104
+ File.rename localname, localdir+localname[%r{[^/]+\Z}]
105
+ when /\.gem\Z/: unpack1gem localname
106
+ when /\.zip\Z/:
107
+ filelist=`unzip -L -l #{localname}`
108
+ if $?>>8 > 1
109
+ puts "invalid zip file #{localname}"
110
+ return
111
+ end
112
+ filelist=filelist.split("\n")[3...-2]
113
+ wellformed=!filelist.find{|entry|
114
+ entry[/\A\s*[^\s]+\s+[^\s]+\s+[^\s]+\s+\^?(.*)\Z/,1][0...projectname.size] != projectname
115
+ }
116
+ if wellformed
117
+ zipopts=" -d #{cachedir}"
118
+ else
119
+ zipopts=" -d #{localdir}"
120
+ Dir.mkdir localdir
121
+ end
122
+ puts "unzip -L #{localname} #{zipopts}"
123
+ system "unzip -L #{localname} #{zipopts}"
124
+ (File.unlink localname rescue nil) if $?>>8 <= 1
125
+
126
+ when /\.tar\Z/:
127
+ wellformed=!`tar tf #{localname}`.split("\n").find{|entry|
128
+ entry[0...projectname.size] != projectname
129
+ }
130
+ if wellformed
131
+ taropts=" -C #{cachedir}"
132
+ else
133
+ taropts=" -C #{localdir}"
134
+ Dir.mkdir localdir
135
+ end
136
+ system "tar xf #{localname} #{taropts}"
137
+ File.unlink localname rescue nil
138
+
139
+ else fail "unknown tarball type: #{localname}"
140
+ end
141
+ end
142
+
143
+ end
144
+
@@ -0,0 +1,11 @@
1
+ module TestCases
2
+ # fail unless File.exist 'test/data/oneliners.rb' and File.exist 'test/data/stanzas.rb'
3
+ rldir=$:.find{|dir| File.exist? dir+'/test/data/oneliners.rb' and File.exist? dir+'/test/data/stanzas.rb' }
4
+ ONELINERS=IO.readlines(rldir+'/test/data/oneliners.rb').map{|x| x.chomp}.grep(/\A\s*[^#\s\n]/).reverse
5
+ STANZAS=IO.read(rldir+'/test/data/stanzas.rb').split("\n\n").grep(/./).reverse
6
+ STANZAS.each{|stanza| stanza<<"\n" }
7
+ ILLEGAL_ONELINERS=IO.readlines(rldir+'/test/data/illegal_oneliners.rb').map{|x| x.chomp}.grep(/\A\s*[^#\s\n]/).reverse
8
+ ILLEGAL_STANZAS=IO.read(rldir+'/test/data/illegal_stanzas.rb').split("\n\n").grep(/./).reverse
9
+ TESTCASES=ONELINERS+STANZAS
10
+ ILLEGAL_TESTCASES=ILLEGAL_ONELINERS+ILLEGAL_STANZAS
11
+ end
@@ -1,4 +1,22 @@
1
1
  #!/usr/bin/ruby
2
+ =begin legal crap
3
+ rubylexer - a ruby lexer written in ruby
4
+ Copyright (C) 2004,2005,2008 Caleb Clausen
5
+
6
+ This library is free software; you can redistribute it and/or
7
+ modify it under the terms of the GNU Lesser General Public
8
+ License as published by the Free Software Foundation; either
9
+ version 2.1 of the License, or (at your option) any later version.
10
+
11
+ This library is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ Lesser General Public License for more details.
15
+
16
+ You should have received a copy of the GNU Lesser General Public
17
+ License along with this library; if not, write to the Free Software
18
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ =end
2
20
  $Debug=true
3
21
  require "rubylexer"
4
22
  require "getoptlong"
@@ -34,24 +52,52 @@ module SimpleVerify
34
52
  end
35
53
 
36
54
  class WToken; include SimpleVerify; end
37
- class NewlineToken; include SimpleVerify; end
38
55
  class IgnoreToken; include SimpleVerify; end
39
56
  class MethNameToken; include SimpleVerify; end
40
57
 
58
+ class NewlineToken
59
+ include SimpleVerify
60
+ def verify_offset(fd)
61
+ super or fd.eof?
62
+ end
63
+ end
64
+
41
65
  class SymbolToken
42
66
  def verify_offset(fd)
43
67
  la=fd.read(2)
44
68
  case la
45
- when '%s': #stay right here
46
- when /^:/: fd.pos-=1
69
+ when '%s':
70
+ quote=fd.read(1)
71
+ ender=RubyLexer::PAIRS[quote] || quote
72
+ body=@ident[2...-1]
73
+ when /^:(['"])/:
74
+ #stay right here
75
+ quote=ender=$1
76
+ body=@ident[2...-1]
77
+ when /^:/:
78
+ fd.pos-=1
79
+ body=@ident[1..-1]
47
80
  else raise 'unrecognized symbol type'
48
81
  end
49
- @ident[1]==?" or @ident[1]==?' or fd.read(@ident.length-1)==@ident[1..-1]
82
+
83
+ bodyread=fd.read(body.length)
84
+
85
+ #punt if its too hard
86
+ if quote
87
+ bs="\\"
88
+ hardstuff= /[#{bs}#{quote}#{bs}#{ender}\#\\]/
89
+ return true if (body+bodyread).match(hardstuff)
90
+ end
50
91
 
92
+ if bodyread==body
93
+ return fd.read(1)==ender if ender
94
+ return true
95
+ end
51
96
  end
52
97
  end
53
98
 
54
99
  class EoiToken
100
+ include SimpleVerify
55
101
  def verify_offset(fd)
56
102
  result=super(fd)
57
103
  fd.eof?
@@ -78,8 +124,8 @@ end
78
124
  class HerePlaceholderToken
79
125
  def verify_offset(fd)
80
126
  '<<'==fd.read(2) or return false
81
- @dash and (?-==fd.read1 or return false)
82
- case ch=fd.read1
127
+ @dash and ('-'==fd.read(1) or return false)
128
+ case ch=fd.read(1)[0]
83
129
  when ?', ?`, ?"
84
130
  @quote==ch.chr and
85
131
  fd.read(@ender.size)==@ender and
@@ -98,14 +144,38 @@ class StringToken
98
144
  FANCY_QUOTE_BEGINNINGS= {'`'=>'%x', '['=>'%w', '{'=>'%W',
99
145
  '"'=>/('|%[^a-pr-z0-9])/i, '/'=>'%r'}
100
146
  def verify_offset(fd)
101
- str=fd.read(2)
102
- @char==str[0,1] or FANCY_QUOTE_BEGINNINGS[@char]===str or return false
147
+ fd.read(open.size)==open or return false
148
+ # str=fd.read(2)
149
+ # @char==str[0,1] or FANCY_QUOTE_BEGINNINGS[@char]===str or return false
103
150
  verify_subtoken_offsets(fd)
104
151
  end
105
152
 
106
153
  def verify_subtoken_offsets(fd)
107
154
  #verify offsets of subtokens
108
- 1.step(@elems.length-1,2) { |i| @elems[i].verify_offset(fd) or raise LexerError}
155
+ @elems.each{|elem|
156
+ case elem
157
+ when String:
158
+ #get string data to compare against,
159
+ #translating dos newlines to unix.
160
+ #(buffer mgt is a PITA)
161
+ goal=elem.size
162
+ saw=fd.read(goal)
163
+ saw.gsub!("\r\n","\n")
164
+ now_at=nil
165
+ loop do
166
+ now_at=saw.size
167
+ saw.chomp!("\r") and fd.pos-=1 and now_at-=1
168
+ break if now_at>=goal
169
+ more=fd.read([goal-now_at,2].max)
170
+ more.gsub!("\r\n","\n")
171
+ saw<<more
172
+ end
173
+ #assert now_at<=goal+1 #not needed
174
+ saw[goal..-1]='' unless goal==now_at
175
+ saw==elem or return false
176
+ else elem.verify_offset(fd) or raise LexerError
177
+ end
178
+ }
109
179
  return true
110
180
  end
111
181
 
@@ -127,7 +197,7 @@ class RubyCode
127
197
  }
128
198
  assert nexttok.nil?
129
199
  assert thistok.object_id==@ident.last.object_id
130
- assert WToken===thistok
200
+ assert(( WToken===thistok or EoiToken===thistok&&thistok.error ))
131
201
  fd.pos=endpos
132
202
  end
133
203
 
@@ -150,40 +220,52 @@ end
150
220
  # end
151
221
  #end
152
222
  end
223
+
153
224
  public
154
225
 
226
+
155
227
  def check_offset(tok,file=nil,endpos=nil)
156
- file||=@file
157
- endpos||=(@moretokens.empty?)? file.pos : @moretokens[0].offset
228
+ #the errors detected here are now reduced to warnings....
229
+ file||=@original_file
230
+ String===file and file=file.to_sequence
231
+ allow_ooo= @moretokens&&@moretokens[0]&&@moretokens[0].allow_ooo_offset unless endpos
232
+ endpos||=((@moretokens.empty?)? input_position : @moretokens[0].offset)
158
233
  oldpos=file.pos
159
234
 
160
235
  assert Integer===tok.offset
161
236
  assert Integer===endpos
162
- endpos>=tok.offset or
163
- raise RubyLexer::LexerError, "expected >=#{tok.offset}, got #{endpos}, "\
164
- "token #{tok}:#{tok.class}"
237
+ if endpos<tok.offset and !allow_ooo
238
+ $stderr.puts "expected #{endpos} to be >= #{tok.offset} token #{tok.to_s.gsub("\n","\n ")}:#{tok.class}"
239
+ end
165
240
 
166
241
  file.pos=tok.offset
167
- tok.verify_offset(file) or raise RubyLexer::LexerError, "couldn't check offset of token #{tok.class}: #{tok}"
242
+ tok.verify_offset(file) or
243
+ $stderr.puts "couldn't check offset of token #{tok.class}: #{tok.to_s.gsub("\n","\n ")} at #{tok.offset}"
168
244
  case tok
169
245
  when RubyLexer::StringToken,RubyLexer::NumberToken,
170
- RubyLexer::HereBodyToken,RubyLexer::SymbolToken: #do nothing
171
- else (file.pos==endpos) or raise RubyLexer::LexerError, "positions don't line up, expected #{endpos}, got #{file.pos}, token: #{tok}"
246
+ RubyLexer::HereBodyToken,RubyLexer::SymbolToken,
247
+ RubyLexer::HerePlaceholderToken,
248
+ RubyLexer::FileAndLineToken: #do nothing
249
+ else
250
+ file.pos==endpos or allow_ooo or
251
+ $stderr.puts "positions don't line up, expected #{endpos}, got #{file.pos}, token: #{tok.to_s.gsub("\n","\n ") }"
172
252
  end
173
253
  file.pos=oldpos
254
+ return
174
255
  end
175
256
 
176
257
 
177
258
 
178
259
 
179
260
 
180
-
181
261
  def tokentest(name,lexertype,pprinter,input=File.open(name),output=$stdout)
182
262
  input ||= File.open(name)
183
263
  if output!=$stdout
184
264
  output=File.open(output,'w')
185
265
  end
186
266
 
267
+ input=input.read if IO===input and not File===input
268
+
187
269
  fd=input
188
270
  #File.open(name) {|fd|
189
271
  lxr=lexertype.new(name,fd,1)
@@ -213,7 +295,7 @@ if __FILE__==$0
213
295
  sep,line,showzw='',1,0
214
296
  # lexertype= RumaLexer if defined? RumaLexer
215
297
  lexertype=RubyLexer
216
- insertnils=fd=name=nil
298
+ insertnils=fd=name=loop=nil
217
299
  pprinter=RubyLexer::SimpleTokenPrinter
218
300
 
219
301
  opts=GetoptLong.new \
@@ -222,27 +304,36 @@ if __FILE__==$0
222
304
  ["--keepws","-k", GetoptLong::NO_ARGUMENT],
223
305
  ["--maxws","-m", GetoptLong::NO_ARGUMENT],
224
306
  ["--implicit","-i", GetoptLong::NO_ARGUMENT],
225
- ["--implicit-all", GetoptLong::NO_ARGUMENT]
307
+ ["--implicit-all", GetoptLong::NO_ARGUMENT],
308
+ ["--loop", GetoptLong::NO_ARGUMENT]
226
309
 
227
310
  saweval=nil
228
311
  opts.each do|opt,arg|
229
312
  case opt
230
313
  when '--eval' then
231
314
  tokentest('-e',lexertype,pprinter.new(sep,line,showzw),arg)
232
- saweval=true
315
+ saweval=arg
233
316
  # when '--ruby' then lexertype=RubyLexer
234
317
  when '--keepws' then pprinter= RubyLexer::KeepWsTokenPrinter
235
318
  when '--maxws' then pprinter= RubyLexer::KeepWsTokenPrinter;sep=' '
236
319
  when '--implicit' then showzw=1
237
320
  when '--implicit-all' then showzw=2
321
+ when '--loop' then loop=true
238
322
  else raise :impossible
239
323
  end
240
324
  end
241
325
 
242
326
  pprinter =pprinter.new(sep,line,showzw)
243
327
 
244
- ARGV.empty? ? saweval || tokentest('-',lexertype,pprinter,$stdin) :
245
- ARGV.each{|fn| tokentest(fn,lexertype,pprinter) }
328
+ begin
329
+ if ARGV.empty?
330
+ saweval ?
331
+ tokentest('-e',lexertype,pprinter,saweval) :
332
+ tokentest('-',lexertype,pprinter,$stdin)
333
+ else
334
+ ARGV.each{|fn| tokentest(fn,lexertype,pprinter) }
335
+ end
246
336
  # ARGV.first[/[_.]rb$/i] and lexertype=RubyLexer #filename with _rb are special hack
337
+ end while loop
247
338
 
248
339
  end