rubylexer 0.7.2 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,28 @@
1
+ === 0.7.3/4-19-2009
2
+ * 9 Bugfixes:
3
+ * remember whether comma was seen in paren context
4
+ * reducing the warning load
5
+ * remember whether we're in a method def when starting a recursive lexer
6
+ * (so that class vars can be marked as being in a method if in #{})
7
+ * make sure Token#to_s always outputs _something_ halfway sensible
8
+ * make sure funclike keywords come out as a keyword
9
+ * break/next/return method after . was not detected properly
10
+ * need a NoWsToken before :: in names of compound modules
11
+ * abort implicit paren contexts when elsif seen
12
+ * all files should be world-readable now
13
+
14
+ * 9 Minor Enhancements:
15
+ * move test data into lib/ dir so I can get to it better from redparse
16
+ * split parse_keywords into separate methods for each keyword
17
+ * (I had hoped to speed up keywords, but keyword_def is still slow)
18
+ * more of the lists of keywords are now available as arrays as well
19
+ * (parenthesis) KeywordToken needs to know if it's for grouping or call
20
+ * minor speedups in newline and ident
21
+ * don't panic if rubygems not available
22
+ * make linenum publicly available in RubyCode
23
+ * various other little helper methods needed by redparse in Tokens
24
+ * hack Rakefile so 'rake test' will stay in 1 process (keeps netbeans happy)
25
+
1
26
  === 0.7.2/10-12-2008
2
27
  * 12 Minor Enhancements:
3
28
  * a new context for then kw expected
data/Manifest.txt CHANGED
@@ -43,7 +43,6 @@ test/data/23.rb
43
43
  test/data/lbrack.rb
44
44
  test/data/untitled1.rb
45
45
  test/data/rescue.rb
46
- test/data/tokentest.assert.rb.can
47
46
  test/data/pleac.rb.broken
48
47
  test/data/heart.rb
49
48
  test/data/s.rb
@@ -63,7 +62,6 @@ test/code/torment
63
62
  test/code/locatetest
64
63
  test/code/deletewarns.rb
65
64
  lib/rubylexer/0.7.1.rb
66
- rubylexer.vpj
67
65
  test/code/all_the_gems.rb
68
66
  test/code/all_the_raas.rb
69
67
  test/code/all_the_rubies.rb
@@ -73,7 +71,7 @@ test/code/lexloop
73
71
  test/code/regression.rb
74
72
  test/code/strgen.rb
75
73
  test/code/tarball.rb
76
- test/code/testcases.rb
74
+ lib/rubylexer/test/testcases.rb
77
75
  test/data/chunky.plain.rb
78
76
  test/data/cvtesc.rb
79
77
  test/data/__eof2.rb
@@ -91,10 +89,9 @@ test/data/heremonsters_dos.rb
91
89
  test/data/heremonsters_dos.rb.broken
92
90
  test/data/heremonsters.rb
93
91
  test/data/heremonsters.rb.broken
94
- test/data/heremonsters.rb.broken.save
95
92
  test/data/here_squote.rb
96
- test/data/illegal_oneliners.rb
97
- test/data/illegal_stanzas.rb
93
+ lib/rubylexer/test/illegal_oneliners.rb
94
+ lib/rubylexer/test/illegal_stanzas.rb
98
95
  test/data/make_ws_strdelim.rb
99
96
  test/data/maven2_builer_test.rb
100
97
  test/data/migration.rb
@@ -102,10 +99,10 @@ test/data/modl_dos.rb
102
99
  test/data/modl_fails.rb
103
100
  test/data/modl.rb
104
101
  test/data/multilinestring.rb
105
- test/data/oneliners.rb
102
+ lib/rubylexer/test/oneliners.rb
106
103
  test/data/simple_dos.rb
107
104
  test/data/simple.rb
108
- test/data/stanzas.rb
105
+ lib/rubylexer/test/stanzas.rb
109
106
  test/data/strdelim_crlf.rb
110
107
  test/data/stuff2.rb
111
108
  test/data/stuff3.rb
data/Rakefile CHANGED
@@ -2,9 +2,21 @@
2
2
  # Distributed under the terms of Ruby's license.
3
3
  require 'rubygems'
4
4
  require 'hoe'
5
+
6
+ if $*==["test"]
7
+ #hack to get 'rake test' to stay in one process
8
+ #which keeps netbeans happy
9
+ # Object.send :remove_const, :RubyLexer
10
+ $:<<"lib"
11
+ require 'rubylexer.rb'
12
+ require "test/unit"
13
+ require "test/code/regression.rb"
14
+ Test::Unit::AutoRunner.run
15
+ exit
16
+ end
17
+
5
18
  require 'lib/rubylexer/version.rb'
6
19
 
7
-
8
20
  readme=open("README.txt")
9
21
  readme.readline("\n=== DESCRIPTION:")
10
22
  readme.readline("\n\n")
@@ -18,8 +30,8 @@ require 'lib/rubylexer/version.rb'
18
30
  _.test_globs=["test/code/regression.rb"]
19
31
  _.description=desc
20
32
  _.summary=desc[/\A[^.]+\./]
21
- _.spec_extras={:bindir=>''}
22
- _.rdoc_pattern=/\A(howtouse\.txt|testing\.txt|README\.txt|lib\/.*\.rb)\Z/
33
+ _.spec_extras={:bindir=>'',:rdoc_options=>'-x lib/rubylexer/test'}
34
+ _.rdoc_pattern=/\A(howtouse\.txt|testing\.txt|README\.txt|lib\/[^\/]*\.rb|lib\/rubylexer\/[^\d][^\/]*\.rb)\Z/
23
35
  end
24
36
 
25
37
 
data/lib/rubylexer.rb CHANGED
@@ -52,10 +52,14 @@ class RubyLexer
52
52
  BEGINWORDLIST=%w(def class module begin for case do)+OPORBEGINWORDLIST
53
53
  OPORBEGINWORDS="(#{OPORBEGINWORDLIST.join '|'})"
54
54
  BEGINWORDS=/^(#{BEGINWORDLIST.join '|'})$/o
55
- FUNCLIKE_KEYWORDS=/^(break|next|redo|return|yield|retry|super|BEGIN|END)$/
56
- VARLIKE_KEYWORDS=/^(__FILE__|__LINE__|false|nil|self|true)$/
57
- INNERBOUNDINGWORDS="(else|elsif|ensure|in|then|rescue|when)"
58
- BINOPWORDS="(and|or)"
55
+ FUNCLIKE_KEYWORDLIST=%w/break next redo return yield retry super BEGIN END/
56
+ FUNCLIKE_KEYWORDS=/^(#{FUNCLIKE_KEYWORDLIST.join '|'})$/
57
+ VARLIKE_KEYWORDLIST=%w/__FILE__ __LINE__ false nil self true/
58
+ VARLIKE_KEYWORDS=/^(#{VARLIKE_KEYWORDLIST.join '|'})$/
59
+ INNERBOUNDINGWORDLIST=%w"else elsif ensure in then rescue when"
60
+ INNERBOUNDINGWORDS="(#{INNERBOUNDINGWORDLIST.join '|'})"
61
+ BINOPWORDLIST=%w"and or"
62
+ BINOPWORDS="(#{BINOPWORDLIST.join '|'})"
59
63
  NEVERSTARTPARAMLISTWORDS=/\A(#{OPORBEGINWORDS}|#{INNERBOUNDINGWORDS}|#{BINOPWORDS}|end)([^a-zA-Z0-9_!?=]|\Z)/o
60
64
  NEVERSTARTPARAMLISTFIRST=CharSet['aoeitrwu'] #chars that begin NEVERSTARTPARAMLIST
61
65
  NEVERSTARTPARAMLISTMAXLEN=7 #max len of a NEVERSTARTPARAMLIST
@@ -155,6 +159,7 @@ class RubyLexer
155
159
  @localvars_stack.last
156
160
  end
157
161
 
162
+ attr_accessor :in_def
158
163
  attr :localvars_stack
159
164
  attr :offset_adjust
160
165
  attr_writer :pending_here_bodies
@@ -258,6 +263,7 @@ class RubyLexer
258
263
  private
259
264
  #-----------------------------------
260
265
  def inside_method_def?
266
+ return true if (defined? @in_def) and @in_def
261
267
  @parsestack.reverse_each{|ctx|
262
268
  ctx.starter=='def' and ctx.state!=:saw_def and return true
263
269
  }
@@ -376,12 +382,14 @@ private
376
382
  @moretokens.unshift(*parse_keywords(str,oldpos) do |tok|
377
383
  #if not a keyword,
378
384
  case str
379
- when FUNCLIKE_KEYWORDS; #do nothing
385
+ when FUNCLIKE_KEYWORDS; except=tok
380
386
  when VARLIKE_KEYWORDS,RUBYKEYWORDS; raise "shouldnt see keywords here, now"
381
387
  end
382
388
  was_last=@last_operative_token
383
389
  @last_operative_token=tok if tok
384
- safe_recurse { |a| var_or_meth_name(str,was_last,oldpos,after_nonid_op?{true}) }
390
+ normally=safe_recurse { |a| var_or_meth_name(str,was_last,oldpos,after_nonid_op?{true}) }
391
+ (Array===normally ? normally[0]=except : normally=except) if except
392
+ normally
385
393
  end)
386
394
  return @moretokens.shift
387
395
  end
@@ -390,6 +398,7 @@ private
390
398
  IDENTREX={}
391
399
  def identifier_as_string(context)
392
400
  #must begin w/ letter or underscore
401
+ #char class needs changing here for utf8 support
393
402
  /[_a-z]/i===nextchar.chr or return
394
403
 
395
404
  #equals, question mark, and exclamation mark
@@ -409,7 +418,7 @@ private
409
418
  end
410
419
  @in_def_name||context==?: and trailers<<"|=(?![=~>])"
411
420
 
412
- @file.scan(IDENTREX[trailers]||=/^[_a-z][a-z0-9_]*(?:#{trailers})?/i)
421
+ @file.scan(IDENTREX[trailers]||=/^(?>[_a-z][a-z0-9_]*(?:#{trailers})?)/i)
413
422
  end
414
423
 
415
424
  #-----------------------------------
@@ -450,7 +459,7 @@ private
450
459
  @defining_lvar or case ctx=@parsestack.last
451
460
  #when ForSMContext; ctx.state==:for
452
461
  when RescueSMContext
453
- lasttok.ident=="=>" and @file.match? /\A[\s\v]*([:;#\n]|then[^a-zA-Z0-9_])/m
462
+ lasttok.ident=="=>" and @file.match?( /\A[\s\v]*([:;#\n]|then[^a-zA-Z0-9_])/m )
454
463
  #when BlockParamListLhsContext; true
455
464
  end
456
465
  end
@@ -589,20 +598,20 @@ private
589
598
  # )
590
599
 
591
600
  #look ahead for closing paren (after some whitespace...)
592
- want_parens=false if @file.match? /\A.(?:\s|\v|\#.*\n)*\)/
601
+ want_parens=false if @file.match?( /\A.(?:\s|\v|\#.*\n)*\)/ )
593
602
  # afterparen=@file.pos
594
603
  # getchar
595
604
  # ignored_tokens(true)
596
605
  # want_parens=false if nextchar==?)
597
606
  # @file.pos=afterparen
598
607
  want_parens=true if /^(return|break|next)$/===@last_operative_token.ident and not(
599
- KeywordToken===lasttok and /^(.|::)$/===lasttok.ident
608
+ KeywordToken===lasttok and /^(\.|::)$/===lasttok.ident
600
609
  )
601
610
  want_parens ? 1 : 0
602
611
  when ?},?],?),?;,(?^ unless @enable_macro), ?|, ?>, ?,, ?., ?=; 2
603
612
  when ?+, ?-, ?%, ?/, (?^ if @enable_macro)
604
613
  if /^(return|break|next)$/===@last_operative_token.ident and not(
605
- KeywordToken===lasttok and /^(.|::)$/===lasttok.ident
614
+ KeywordToken===lasttok and /^(\.|::)$/===lasttok.ident
606
615
  )
607
616
  1
608
617
  else
@@ -611,7 +620,7 @@ private
611
620
  when ?*, ?&
612
621
  # lasttok=@last_operative_token
613
622
  if /^(return|break|next)$/===@last_operative_token.ident and not(
614
- KeywordToken===lasttok and /^(.|::)$/===lasttok.ident
623
+ KeywordToken===lasttok and /^(\.|::)$/===lasttok.ident
615
624
  )
616
625
  1
617
626
  else
@@ -665,7 +674,7 @@ private
665
674
  last=result.last
666
675
  last.set_callsite! false if last.respond_to? :callsite? and last.callsite? #KeywordToken===last and last.ident==')'
667
676
  if /^(break|next|return)$/===name and
668
- !(KeywordToken===lasttok and /^(.|::)$/===lasttok.ident)
677
+ !(KeywordToken===lasttok and /^(\.|::)$/===lasttok.ident)
669
678
  ty=KWParamListContextNoParen
670
679
  else
671
680
  ty=ParamListContextNoParen
@@ -802,6 +811,9 @@ private
802
811
  #-----------------------------------
803
812
  def enable_macros!
804
813
  @enable_macro="macro"
814
+ class <<self
815
+ alias keyword_macro keyword_def
816
+ end
805
817
  end
806
818
  public :enable_macros!
807
819
 
@@ -836,13 +848,16 @@ private
836
848
  #parse keywords now, to prevent confusion over bare symbols
837
849
  #and match end with corresponding preceding def or class or whatever.
838
850
  #if arg is not a keyword, the block is called
839
- def parse_keywords(str,offset)
851
+ def parse_keywords(str,offset,&block)
840
852
  assert @moretokens.empty?
841
- assert !(KeywordToken===@last_operative_token and /A(.|::|def)\Z/===@last_operative_token.ident)
853
+ assert !(KeywordToken===@last_operative_token and /A(\.|::|def)\Z/===@last_operative_token.ident)
842
854
  result=[KeywordToken.new(str,offset)]
843
855
 
844
- case str
845
- when "end"
856
+ m="keyword_#{str}"
857
+ respond_to?(m) ? (send m,str,offset,result,&block) : block[MethNameToken.new(str)]
858
+ end
859
+ public #these have to be public so respond_to? can see them (sigh)
860
+ def keyword_end(str,offset,result)
846
861
  result.unshift(*abort_noparens!(str))
847
862
  @parsestack.last.see self,:semi #sorta hacky... should make an :end event instead?
848
863
 
@@ -859,8 +874,10 @@ private
859
874
  BEGINWORDS===start or lexerror result.last, "end does not match #{start or "nil"}"
860
875
  /^(do)$/===start and localvars.end_block
861
876
  /^(class|module|def)$/===start and @localvars_stack.pop
877
+ return result
878
+ end
862
879
 
863
- when "module"
880
+ def keyword_module(str,offset,result)
864
881
  result.first.has_end!
865
882
  @parsestack.push WantsEndContext.new(str,@linenum)
866
883
  @localvars_stack.push SymbolTable.new
@@ -885,17 +902,22 @@ private
885
902
  end
886
903
  @moretokens.push VarNameToken.new(name,offset+incr)
887
904
  break unless dc
905
+ @moretokens.push NoWsToken.new(offset+md.end(0)-2)
888
906
  @moretokens.push KeywordToken.new('::',offset+md.end(0)-2)
889
907
  end
890
908
  @moretokens.push EndHeaderToken.new(input_position)
891
-
909
+ return result
910
+ end
892
911
 
893
912
 
894
- when "class"
913
+ def keyword_class(str,offset,result)
895
914
  result.first.has_end!
896
915
  @parsestack.push ClassContext.new(str,@linenum)
916
+ return result
917
+ end
918
+
897
919
 
898
- when "if","unless" #could be infix form without end
920
+ def keyword_if(str,offset,result) #could be infix form without end
899
921
  if after_nonid_op?{false} #prefix form
900
922
  result.first.has_end!
901
923
  @parsestack.push WantsEndContext.new(str,@linenum)
@@ -903,12 +925,23 @@ private
903
925
  else #infix form
904
926
  result.unshift(*abort_noparens!(str))
905
927
  end
906
- when "elsif"
928
+ return result
929
+ end
930
+ alias keyword_unless keyword_if
931
+
932
+ def keyword_elsif(str,offset,result)
933
+ result.unshift(*abort_noparens!(str))
907
934
  @parsestack.push ExpectThenOrNlContext.new(str,@linenum)
908
- when "begin","case"
935
+ return result
936
+ end
937
+ def keyword_begin(str,offset,result)
909
938
  result.first.has_end!
910
939
  @parsestack.push WantsEndContext.new(str,@linenum)
911
- when "while","until" #could be infix form without end
940
+ return result
941
+ end
942
+
943
+ alias keyword_case keyword_begin
944
+ def keyword_while(str,offset,result) #could be infix form without end
912
945
  if after_nonid_op?{false} #prefix form
913
946
  result.first.has_end!
914
947
  @parsestack.push WantsEndContext.new(str,@linenum)
@@ -917,14 +950,21 @@ private
917
950
  else #infix form
918
951
  result.unshift(*abort_noparens!(str))
919
952
  end
920
- when "for"
953
+ return result
954
+ end
955
+
956
+ alias keyword_until keyword_while
957
+
958
+ def keyword_for(str,offset,result)
921
959
  result.first.has_end!
922
960
  result.push KwParamListStartToken.new(offset+str.length)
923
961
  # corresponding EndToken emitted leaving ForContext ("in" branch, below)
924
962
  @parsestack.push WantsEndContext.new(str,@linenum)
925
963
  #expect_do_or_end_or_nl! str #handled by ForSMContext now
926
964
  @parsestack.push ForSMContext.new(@linenum)
927
- when "do"
965
+ return result
966
+ end
967
+ def keyword_do(str,offset,result)
928
968
  result.unshift(*abort_noparens_for_do!(str))
929
969
  if ExpectDoOrNlContext===@parsestack.last
930
970
  @parsestack.pop
@@ -936,12 +976,17 @@ private
936
976
  localvars.start_block
937
977
  block_param_list_lookahead
938
978
  end
939
- when "def",@enable_macro
979
+ return result
980
+ end
981
+ def keyword_def(str,offset,result) #macros too, if enabled
940
982
  result.first.has_end!
941
983
  @parsestack.push ctx=DefContext.new(@linenum)
942
984
  ctx.state=:saw_def
943
- safe_recurse { |aa|
944
- set_last_token KeywordToken.new str #hack
985
+ old_moretokens=@moretokens
986
+ @moretokens=[]
987
+ aa=@moretokens
988
+ #safe_recurse { |aa|
989
+ set_last_token KeywordToken.new(str) #hack
945
990
  result.concat ignored_tokens
946
991
 
947
992
  #read an expr like a.b.c or a::b::c
@@ -960,7 +1005,7 @@ private
960
1005
  end until parencount==0 #@parsestack.size==old_size
961
1006
  @localvars_stack.push SymbolTable.new
962
1007
  else #no parentheses, all tail
963
- set_last_token KeywordToken.new "." #hack hack
1008
+ set_last_token KeywordToken.new(".") #hack hack
964
1009
  tokindex=result.size
965
1010
  result << tok=symbol(false,false)
966
1011
  name=tok.to_s
@@ -1006,11 +1051,11 @@ private
1006
1051
  #a could even be a keyword (eg self or block_given?).
1007
1052
  end
1008
1053
  #read tail: .b.c.d etc
1009
- result.reverse_each{|res| break set_last_token res unless StillIgnoreToken===res}
1054
+ result.reverse_each{|res| break set_last_token( res ) unless StillIgnoreToken===res}
1010
1055
  assert !(IgnoreToken===@last_operative_token)
1011
1056
  state=:expect_op
1012
1057
  @in_def_name=true
1013
- loop do
1058
+ while true
1014
1059
 
1015
1060
  #look for start of parameter list
1016
1061
  nc=(@moretokens.empty? ? nextchar.chr : @moretokens.first.to_s[0,1])
@@ -1041,7 +1086,7 @@ private
1041
1086
  when /^(\.|::)$/.token_pat
1042
1087
  lexerror tok,'expected ident' unless state==:expect_op
1043
1088
  if endofs
1044
- result.insert -2, ImplicitParamListEndToken.new(endofs)
1089
+ result.insert( -2, ImplicitParamListEndToken.new(endofs) )
1045
1090
  endofs=nil
1046
1091
  end
1047
1092
  state=:expect_name
@@ -1049,9 +1094,9 @@ private
1049
1094
  ctx.state=:def_body
1050
1095
  state==:expect_op or lexerror tok,'expected identifier'
1051
1096
  if endofs
1052
- result.insert -2,ImplicitParamListEndToken.new(tok.offset)
1097
+ result.insert( -2,ImplicitParamListEndToken.new(tok.offset) )
1053
1098
  end
1054
- result.insert -2, EndHeaderToken.new(tok.offset)
1099
+ result.insert( -2, EndHeaderToken.new(tok.offset) )
1055
1100
  break
1056
1101
  else
1057
1102
  lexerror(tok, "bizarre token in def name: " +
@@ -1059,10 +1104,13 @@ private
1059
1104
  end
1060
1105
  end
1061
1106
  @in_def_name=false
1062
- }
1063
- when "alias"
1107
+ #}
1108
+ @moretokens= old_moretokens.concat @moretokens
1109
+ return result
1110
+ end
1111
+ def keyword_alias(str,offset,result)
1064
1112
  safe_recurse { |a|
1065
- set_last_token KeywordToken.new "alias" #hack
1113
+ set_last_token KeywordToken.new( "alias" )#hack
1066
1114
  result.concat ignored_tokens
1067
1115
  res=symbol(eat_next_if(?:),false)
1068
1116
  unless res
@@ -1070,7 +1118,7 @@ private
1070
1118
  else
1071
1119
  res.ident[0]==?$ and res=VarNameToken.new(res.ident,res.offset)
1072
1120
  result<< res
1073
- set_last_token KeywordToken.new "alias" #hack
1121
+ set_last_token KeywordToken.new( "alias" )#hack
1074
1122
  result.concat ignored_tokens
1075
1123
  res=symbol(eat_next_if(?:),false)
1076
1124
  unless res
@@ -1081,10 +1129,12 @@ private
1081
1129
  end
1082
1130
  end
1083
1131
  }
1084
- when "undef"
1132
+ return result
1133
+ end
1134
+ def keyword_undef(str,offset,result)
1085
1135
  safe_recurse { |a|
1086
1136
  loop do
1087
- set_last_token KeywordToken.new "," #hack
1137
+ set_last_token KeywordToken.new( "," )#hack
1088
1138
  result.concat ignored_tokens
1089
1139
  tok=symbol(eat_next_if(?:),false)
1090
1140
  tok or lexerror(result.first,"bad symbol in undef")
@@ -1101,18 +1151,22 @@ private
1101
1151
  end
1102
1152
  }
1103
1153
 
1154
+ return result
1155
+ end
1104
1156
  # when "defined?"
1105
1157
  #defined? might have a baresymbol following it
1106
1158
  #does it need to be handled specially?
1107
1159
  #it would seem not.....
1108
1160
 
1109
- when "when"
1161
+ def keyword_when(str,offset,result)
1110
1162
  #abort_noparens! emits EndToken on leaving context
1111
1163
  result.unshift(*abort_noparens!(str))
1112
1164
  result.push KwParamListStartToken.new( offset+str.length)
1113
1165
  @parsestack.push WhenParamListContext.new(str,@linenum)
1166
+ return result
1167
+ end
1114
1168
 
1115
- when "rescue"
1169
+ def keyword_rescue(str,offset,result)
1116
1170
  unless after_nonid_op? {false}
1117
1171
  #rescue needs to be treated differently when in operator context...
1118
1172
  #i think no RescueSMContext should be pushed on the stack...
@@ -1124,8 +1178,10 @@ private
1124
1178
  @parsestack.push RescueSMContext.new(@linenum)
1125
1179
  result.unshift(*abort_noparens!(str))
1126
1180
  end
1181
+ return result
1182
+ end
1127
1183
 
1128
- when "then"
1184
+ def keyword_then(str,offset,result)
1129
1185
  result.unshift(*abort_noparens!(str))
1130
1186
  @parsestack.last.see self,:then
1131
1187
 
@@ -1133,24 +1189,38 @@ private
1133
1189
  @parsestack.pop
1134
1190
  else #error... does anyone care?
1135
1191
  end
1192
+ return result
1193
+ end
1136
1194
 
1137
- when "in"
1195
+ def keyword_in(str,offset,result)
1138
1196
  result.unshift KwParamListEndToken.new( offset)
1139
1197
  result.unshift(*abort_noparens!(str))
1140
1198
  @parsestack.last.see self,:in
1199
+ return result
1200
+ end
1141
1201
 
1142
- when /\A(#{BINOPWORDS}|#{INNERBOUNDINGWORDS})\Z/o
1202
+ def _keyword_innerbounding(str,offset,result)
1143
1203
  result.unshift(*abort_noparens!(str))
1204
+ return result
1205
+ end
1206
+ for kw in BINOPWORDLIST+INNERBOUNDINGWORDLIST-["in","then","rescue","when","elsif"]
1207
+ alias_method "keyword_#{kw}".to_sym, :_keyword_innerbounding
1208
+ end
1144
1209
 
1145
- when /\A(return|break|next)\Z/
1210
+ def keyword_return(str,offset,result)
1146
1211
  fail if KeywordToken===@last_operative_token and @last_operative_token===/\A(\.|::)\Z/
1147
1212
  tok=KeywordToken.new(str,offset)
1148
1213
  result=yield tok
1149
1214
  result[0]=tok
1150
1215
  tok.has_no_block!
1216
+ return result
1217
+ end
1218
+
1219
+ alias keyword_break keyword_return
1220
+ alias keyword_next keyword_return
1151
1221
 
1152
1222
 
1153
- when 'END'
1223
+ def keyword_END(str,offset,result)
1154
1224
  #END could be treated, lexically, just as if it is an
1155
1225
  #ordinary method, except that local vars created in
1156
1226
  #END blocks are visible to subsequent code. (Why??)
@@ -1161,7 +1231,7 @@ private
1161
1231
  safe_recurse{
1162
1232
  old=result.first
1163
1233
  result=[
1164
- MethNameToken.new(old.ident,old.offset),
1234
+ KeywordToken.new(old.ident,old.offset),
1165
1235
  ImplicitParamListStartToken.new(input_position),
1166
1236
  ImplicitParamListEndToken.new(input_position),
1167
1237
  *ignored_tokens
@@ -1173,20 +1243,31 @@ private
1173
1243
  @parsestack.push BeginEndContext.new(str,offset)
1174
1244
  }
1175
1245
  end
1246
+ return result
1247
+ end
1176
1248
 
1177
- when FUNCLIKE_KEYWORDS
1178
- result=yield MethNameToken.new(str) #should be a keyword token?
1179
-
1180
- when RUBYKEYWORDS
1181
- #do nothing
1182
-
1183
- else result=yield MethNameToken.new(str)
1184
-
1185
- end
1186
1249
 
1187
- return result
1250
+ def _keyword_funclike(str,offset,result)
1251
+ if @last_operative_token===/^(\.|::)$/
1252
+ result=yield MethNameToken.new(str) #should pass a methname token here
1253
+ else
1254
+ result=yield KeywordToken.new(str)
1255
+ end
1256
+ return result
1257
+ end
1258
+ for kw in FUNCLIKE_KEYWORDLIST-["END","return","break","next"] do
1259
+ alias_method "keyword_#{kw}".to_sym, :_keyword_funclike
1260
+ end
1261
+
1262
+ def _keyword_varlike(str,offset,result)
1263
+ #do nothing
1264
+ return result
1265
+ end
1266
+ for kw in VARLIKE_KEYWORDLIST+["defined?", "not"] do
1267
+ alias_method "keyword_#{kw}".to_sym, :_keyword_varlike
1188
1268
  end
1189
1269
 
1270
+ private
1190
1271
 
1191
1272
  #-----------------------------------
1192
1273
  def parsestack_lastnonassign_is?(obj)
@@ -1221,7 +1302,7 @@ private
1221
1302
  #-----------------------------------
1222
1303
  def block_param_list_lookahead
1223
1304
  safe_recurse{ |la|
1224
- set_last_token KeywordToken.new ';'
1305
+ set_last_token KeywordToken.new( ';' )
1225
1306
  a=ignored_tokens
1226
1307
 
1227
1308
  if eat_next_if(?|)
@@ -1267,7 +1348,7 @@ end
1267
1348
  end
1268
1349
  end
1269
1350
 
1270
- set_last_token KeywordToken.new ';'
1351
+ set_last_token KeywordToken.new( ';' )
1271
1352
  #a.concat ignored_tokens
1272
1353
 
1273
1354
  #assert @last_operative_token===';'
@@ -1313,7 +1394,7 @@ end
1313
1394
  alias === call
1314
1395
  end
1315
1396
 
1316
- set_last_token KeywordToken.new ',' #hack
1397
+ set_last_token KeywordToken.new( ',' )#hack
1317
1398
  #read local parameter names
1318
1399
  nextvar=nil
1319
1400
  loop do
@@ -1348,7 +1429,7 @@ end
1348
1429
  when /^[&*]$/.token_pat #unary form...
1349
1430
  #a NoWsToken is also expected... read it now
1350
1431
  result.concat maybe_no_ws_token #not needed?
1351
- set_last_token KeywordToken.new ','
1432
+ set_last_token KeywordToken.new( ',' )
1352
1433
  else
1353
1434
  lexerror tok,"unfamiliar var name '#{tok}'"
1354
1435
  end
@@ -1382,7 +1463,7 @@ end
1382
1463
  # !(NewlineToken===@last_operative_token) and
1383
1464
  # !(/^(end|;)$/===@last_operative_token)
1384
1465
  #result<<EndHeaderToken.new(result.last.offset+result.last.to_s.size)
1385
- set_last_token KeywordToken.new ';'
1466
+ set_last_token KeywordToken.new( ';' )
1386
1467
  result<< get1token
1387
1468
  # end
1388
1469
  }
@@ -1767,7 +1848,7 @@ end
1767
1848
  end
1768
1849
 
1769
1850
  @offset_adjust=@min_offset_adjust
1770
- @moretokens.push *optional_here_bodies
1851
+ @moretokens.push( *optional_here_bodies )
1771
1852
  ln=@linenum
1772
1853
  @moretokens.push lexerror(EscNlToken.new(@filename,ln-1,result,input_position-result.size), error),
1773
1854
  FileAndLineToken.new(@filename,ln,input_position)
@@ -1854,7 +1935,7 @@ end
1854
1935
  back1char #-1 to make newline char the next to read
1855
1936
  @linenum-=1
1856
1937
 
1857
- assert /[\r\n]/===nextchar.chr
1938
+ assert( /[\r\n]/===nextchar.chr )
1858
1939
 
1859
1940
  #retr evrything til next nl
1860
1941
  if FASTER_STRING_ESCAPES
@@ -2253,9 +2334,9 @@ end
2253
2334
  @parsestack.last.see self,:arrow
2254
2335
  when '': #plain assignment: record local variable definitions
2255
2336
  last_context_not_implicit.lhs=false
2256
- @moretokens.push *ignored_tokens(true).map{|x|
2337
+ @moretokens.push( *ignored_tokens(true).map{|x|
2257
2338
  NewlineToken===x ? EscNlToken.new(@filename,@linenum,x.ident,x.offset) : x
2258
- }
2339
+ } )
2259
2340
  @parsestack.push AssignmentRhsContext.new(@linenum)
2260
2341
  if eat_next_if ?*
2261
2342
  tok=OperatorToken.new('*', input_position-1)
@@ -2401,7 +2482,7 @@ end
2401
2482
  # 'need to find matching callsite context and end it if implicit'
2402
2483
  lasttok=last_operative_token
2403
2484
  if !(lasttok===')' and lasttok.callsite?) #or ParamListContextNoParen===parsestack.last
2404
- @moretokens.push *(abort_1_noparen!(1).push tokch)
2485
+ @moretokens.push( *(abort_1_noparen!(1).push tokch) )
2405
2486
  tokch=@moretokens.shift
2406
2487
  end
2407
2488
  #=end
@@ -2475,6 +2556,14 @@ end
2475
2556
  #-----------------------------------
2476
2557
  def comma(ch)
2477
2558
  @moretokens.push token=single_char_token(ch)
2559
+
2560
+ #if assignment rhs seen inside method param list, when param list, array or hash literal,
2561
+ # rescue where comma is expected, or method def param list
2562
+ # then end the assignment rhs now
2563
+ #+[OBS,ParamListContext|ParamListContextNoParen|WhenParamListContext|ListImmedContext|
2564
+ # (RescueSMContext&-{:state=>:rescue})|(DefContext&-{:in_body=>FalseClass|nil}),
2565
+ # AssignmentRhsContext
2566
+ #]===@parsestack
2478
2567
  if AssignmentRhsContext===@parsestack[-1] and
2479
2568
  ParamListContext===@parsestack[-2] ||
2480
2569
  ParamListContextNoParen===@parsestack[-2] ||
@@ -2487,9 +2576,9 @@ end
2487
2576
  end
2488
2577
  token.comma_type=
2489
2578
  case @parsestack[-1]
2490
- when AssignmentRhsContext: :rhs
2491
- when ParamListContext,ParamListContextNoParen: :call
2492
- when ListImmedContext: :array
2579
+ when AssignmentRhsContext; :rhs
2580
+ when ParamListContext,ParamListContextNoParen; :call
2581
+ when ListImmedContext; :array
2493
2582
  else
2494
2583
  :lhs if comma_in_lvalue_list?
2495
2584
  end