redparse 0.8.2 → 0.8.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,17 @@
1
+ === 0.8.3 / 2009-07-01
2
+ * 7 Minor Enhancements:
3
+ * most nodes now have startline, endline, and offset
4
+ * Node.[] is more fun to use now (most attributes can be left off)
5
+ * a SequenceNode inserted into a SequenceNode now gets inlined
6
+ * new ListInNode module for the various vanilla arrays found in node trees
7
+ * HashLiteralNode#get; retrieve values from hash literal kinda like from a hash
8
+ * Nodes can be catenated with the + operator now
9
+ * Symbols inserted into a tree are converted to CallSiteNodes
10
+
11
+ * 2 Bugfixes:
12
+ * more faithful ParseTree emulation in a couple of cases
13
+ * minor fixes in node processing for some rare conditions
14
+
1
15
  === 0.8.2 / 2009-04-21
2
16
  * 14 Minor Enhancements:
3
17
  * should be no tokens left in Node tree now
data/README.txt CHANGED
@@ -60,7 +60,7 @@ Please see COPYING.LGPL for details.
60
60
 
61
61
  == Drawbacks:
62
62
 
63
- * Pathetically, rediculously slow (ok, compiler-compilers are hard...)
63
+ * Pathetically, ridiculously slow (ok, compiler-compilers are hard...)
64
64
  * Error handling is very minimal right now.
65
65
  * No warnings at all.
66
66
  * Some expressions aren't parsed correctly. see below.
@@ -82,8 +82,8 @@ Please see COPYING.LGPL for details.
82
82
 
83
83
  tree.walk{|parent,i,subi,node|
84
84
  case node
85
- when CallNode: #... do something with method calls
86
- when AssignNode: #... maybe alter assignments somehow
85
+ when RedParse::CallNode: #... do something with method calls
86
+ when RedParse::AssignNode: #... maybe alter assignments somehow
87
87
  #.... and so on
88
88
  end
89
89
  }
@@ -203,13 +203,13 @@ existing format in the future, but no incompatibility-creating changes.
203
203
  ||+BlockParams #block formal parameter list
204
204
  |+CallSiteNode #abstract, method calls
205
205
  ||| (receiver: Expr|nil, name: String, params: nil|Array[Expr+,UnaryStarNode?,UnAmpNode?],
206
- ||| block_params: BlockParams, block: Expr)
206
+ ||| blockparams: BlockParams|nil, block: Expr|nil)
207
207
  ||+CallNode #normal method calls
208
208
  ||+KWCallNode #keywords that look (more or less) like methods (BEGIN END yield return break continue next)
209
209
  |+ArrayLiteralNode #[..]
210
210
  || (Array[Expr*])
211
211
  |+IfNode #if..end and unless..end
212
- || (if: Expr, then: Expr|nil, elsifs: Array[ElsifNode+]|Nil, else: Expr|nil)
212
+ || (if: Expr, then: Expr|nil, elsifs: Array[ElsifNode+]|nil, else: Expr|nil)
213
213
  |+LoopNode #while..end and until..end
214
214
  || (while: Expr, do: Expr:nil)
215
215
  |+CaseNode #case..end
data/Rakefile CHANGED
@@ -24,7 +24,6 @@ end
24
24
  _.url = ["http://github.com/coatl/redparse/", "http://rubyforge.org/projects/redparse/"]
25
25
  _.extra_deps << ['rubylexer', '>= 0.7.4']
26
26
  _.extra_deps << ['reg', '>= 0.4.7']
27
- _.extra_deps << 'Ron'
28
27
  # _.test_globs=["test/*"]
29
28
  _.description=desc
30
29
  _.summary=desc[/\A[^.]+\./]
data/bin/redparse CHANGED
@@ -95,9 +95,12 @@ while /^-/===ARGV.first
95
95
  when "--vsparsetree"; output=:vsparsetree
96
96
  when "--vsparsetree2"; output=:vsparsetree2
97
97
  when "--update-problemfiles"; problemfiles=ProblemFiles.new
98
+ when "--tokens"; ENV['PRINT_TOKENS']='1'
99
+ when "--rawtokens"; ENV['RAW_PRINT_TOKENS']='1'
100
+ when "--stack"; ENV['PRINT_STACK']='1'
98
101
  when "--unparse"; output=:unparse
99
102
  when "--compile", "-c"; compile=true
100
- when "--macros", "--macro", "-m":
103
+ when "--macros", "--macro", "-m";
101
104
  require 'rubygems'
102
105
  require 'macro'
103
106
  parserclass=Macro::RedParseWithMacros
data/lib/redparse.rb CHANGED
@@ -296,7 +296,7 @@ end
296
296
  #do something with error nodes
297
297
  msgs=[]
298
298
  result.walk{|parent,i,subi,node|
299
- not if node.respond_to? :error and node.error?(@rubyversion)
299
+ not if node.respond_to? :error? and node.error?(@rubyversion)
300
300
  msgs<< @filename+":"+node.blame.msg
301
301
  end
302
302
  } if result.respond_to? :walk #hack hack
data/lib/redparse/node.rb CHANGED
@@ -360,6 +360,18 @@ class RedParse
360
360
  attr :string
361
361
  end
362
362
 
363
+ module ListInNode
364
+ def []=(*args)
365
+ val=args.pop
366
+ #inline symbols as callnodes
367
+ case val
368
+ when Symbol
369
+ val=CallNode[nil,val.to_s]
370
+ end
371
+ super( *args<<val )
372
+ end
373
+ end
374
+
363
375
  class Node<Array
364
376
  include Stackable
365
377
  extend Stackable::Meta
@@ -369,6 +381,12 @@ class RedParse
369
381
  replace data
370
382
  end
371
383
 
384
+ def initialize_ivars
385
+ @offset||=0
386
+ @startline||=0
387
+ @endline||=0
388
+ end
389
+
372
390
  def flattened_ivars
373
391
  result=super
374
392
  result.each_with_index{|x,i|
@@ -383,6 +401,25 @@ class RedParse
383
401
  super and flattened_ivars_equal?(other)
384
402
  end
385
403
 
404
+ def +(other)
405
+ if SequenceNode===other
406
+ SequenceNode[self,*other]
407
+ else
408
+ SequenceNode[self,other]
409
+ end
410
+ end
411
+
412
+ alias original_brackets_assign []= #needed by LiteralNode
413
+ def []=(*args)
414
+ val=args.pop
415
+ #inline symbols as callnodes
416
+ case val
417
+ when Symbol
418
+ val=CallNode[nil,val.to_s]
419
+ end
420
+ super( *args<<val )
421
+ end
422
+
386
423
  def image; "(#{inspect})" end
387
424
 
388
425
  def error? x; false end
@@ -403,9 +440,19 @@ class RedParse
403
440
  end
404
441
  attr_accessor :endline
405
442
  attr_accessor :errors
443
+ attr_reader :offset
444
+
445
+ def self.inline_symbols data
446
+ data.map!{|datum|
447
+ Symbol===datum ?
448
+ CallNode[nil,datum.to_s,nil,nil,nil] :
449
+ datum
450
+ }
451
+ end
406
452
 
407
453
  def self.[](*data)
408
454
  options=data.pop if Hash===data.last
455
+ inline_symbols data
409
456
  result=allocate
410
457
  result.instance_eval{
411
458
  replace data
@@ -413,6 +460,7 @@ class RedParse
413
460
  instance_variable_set name,val
414
461
  } if options
415
462
  }
463
+ result.initialize_ivars
416
464
  return result
417
465
  end
418
466
 
@@ -433,7 +481,7 @@ class RedParse
433
481
  ivars[ivarname.to_sym]=instance_variable_get(ivarname)
434
482
  }
435
483
  q.group(1, self.class.name+'[', ']') {
436
- displaylist= ivars.empty? ? self : self+[ivars]
484
+ displaylist= ivars.empty? ? self : dup<<ivars
437
485
  q.seplist(displaylist) {|v|
438
486
  q.pp v
439
487
  }
@@ -905,8 +953,8 @@ class RedParse
905
953
 
906
954
  class VarNode<ValueNode
907
955
  include FlattenedIvars
908
- attr_accessor :endline
909
- attr_reader :lvar_type,:in_def,:offset
956
+ attr_accessor :endline,:offset
957
+ attr_reader :lvar_type,:in_def
910
958
  attr_writer :lvalue
911
959
 
912
960
 
@@ -916,7 +964,7 @@ class RedParse
916
964
  super(tok.ident)
917
965
  @lvar_type=tok.lvar_type
918
966
  @offset=tok.offset
919
- @endline=tok.endline
967
+ @endline=@startline=tok.endline
920
968
  @in_def=tok.in_def
921
969
  end
922
970
 
@@ -924,6 +972,8 @@ class RedParse
924
972
  def ident=x; self[0]=x end
925
973
  alias image ident
926
974
  alias startline endline
975
+ alias name ident
976
+ alias name= ident=
927
977
 
928
978
  def parsetree(o)
929
979
  type=case ident[0]
@@ -999,10 +1049,6 @@ class RedParse
999
1049
  def unparse o=default_unparse_options; ident end
1000
1050
  alias lhs_unparse unparse
1001
1051
 
1002
- # def delete_extraneous_ivars!
1003
- # remove_instance_variable :@lvalue
1004
- # super
1005
- # end
1006
1052
 
1007
1053
  if false
1008
1054
  def walk #is this needed?
@@ -1174,6 +1220,30 @@ end
1174
1220
  class VarLikeNode<ValueNode; end #nil,false,true,__FILE__,__LINE__,self
1175
1221
 
1176
1222
  class SequenceNode<ListOpNode
1223
+ def initialize(*args)
1224
+ super
1225
+ @offset=self.first.offset
1226
+ end
1227
+ def +(other)
1228
+ if SequenceNode===other
1229
+ dup.push( *other )
1230
+ else
1231
+ dup.push other
1232
+ end
1233
+ end
1234
+
1235
+ def []=(*args)
1236
+ val=args.pop
1237
+ if SequenceNode===val
1238
+ val=Array.new(val)
1239
+ #munge args too
1240
+ if args.size==1 and Integer===args.first
1241
+ args<<1
1242
+ end
1243
+ end
1244
+ super( *args<<val )
1245
+ end
1246
+
1177
1247
  def image; '(;)' end
1178
1248
  def to_lisp
1179
1249
  "#{map{|x| x.to_lisp}.join("\n")}"
@@ -1224,7 +1294,12 @@ end
1224
1294
  end
1225
1295
 
1226
1296
  def unparse o=default_unparse_options
1227
- map{|expr| unparse_nl(expr,o)+expr.unparse(o)}.to_s
1297
+ return "" if empty?
1298
+ unparse_nl(first,o,'')+first.unparse(o)+
1299
+ self[1..-1].map{|expr|
1300
+ # p expr
1301
+ unparse_nl(expr,o)+expr.unparse(o)
1302
+ }.to_s
1228
1303
  end
1229
1304
  end
1230
1305
 
@@ -1325,6 +1400,7 @@ end
1325
1400
  class UnOpNode<ValueNode
1326
1401
  param_names(:op,:val)
1327
1402
  def initialize(op,val)
1403
+ @offset=op.offset
1328
1404
  op=op.ident
1329
1405
  /([&*])$/===op and op=$1+"@"
1330
1406
  /^(?:!|not)$/===op and
@@ -1408,7 +1484,8 @@ end
1408
1484
  #param_names :op,:val
1409
1485
  def initialize(star)
1410
1486
  @offset= star.offset
1411
- replace ['*@',VarNode.new(VarNameToken.new('',offset))]
1487
+ replace ['*@',var=VarNode.new(VarNameToken.new('',offset))]
1488
+ var.startline=var.endline=star.startline
1412
1489
  end
1413
1490
  attr :offset
1414
1491
  def lvars_defined_in; [] end
@@ -1434,6 +1511,7 @@ end
1434
1511
 
1435
1512
  class ConstantNode<ListOpNode
1436
1513
  def initialize(*args)
1514
+ @offset=args.first.offset
1437
1515
  args.unshift nil if args.size==2
1438
1516
  args.map!{|node|
1439
1517
  if VarNode===node and (?A..?Z)===node.ident[0]
@@ -1669,6 +1747,7 @@ end
1669
1747
  class ParenedNode<ValueNode
1670
1748
  param_names :body #, :rescues, :else!, :ensure!
1671
1749
  def initialize(lparen,body,rparen)
1750
+ @offset=lparen.offset
1672
1751
  self[0]=body
1673
1752
  end
1674
1753
 
@@ -1723,8 +1802,9 @@ end
1723
1802
 
1724
1803
  rescues=rescues().map{|resc| resc.parsetree(o)}
1725
1804
  if rescues.empty?
1726
- else_ and
1727
- body=SequenceNode.new(body,nil,else_)
1805
+ if else_
1806
+ body= body ? SequenceNode.new(body,nil,else_) : else_
1807
+ end
1728
1808
  else_=nil
1729
1809
  else
1730
1810
  target.push newtarget=[:rescue, ]
@@ -1767,15 +1847,17 @@ end
1767
1847
  include HasRescue
1768
1848
  param_names :body, :rescues, :else!, :ensure!
1769
1849
  def initialize(*args)
1850
+ @offset=args.first.offset
1770
1851
  @empty_ensure=@empty_else=@op_rescue=nil
1771
- body,rescues,else_,ensure_=*args[1...-1]
1772
- if else_
1773
- else_=else_.val or @empty_else=true
1774
- end
1775
- if ensure_
1776
- ensure_=ensure_.val or @empty_ensure=true
1777
- end
1778
- replace [body,rescues,else_,ensure_]
1852
+ body,rescues,else_,ensure_=*args[1...-1]
1853
+ rescues.extend ListInNode
1854
+ if else_
1855
+ else_=else_.val or @empty_else=true
1856
+ end
1857
+ if ensure_
1858
+ ensure_=ensure_.val or @empty_ensure=true
1859
+ end
1860
+ replace [body,rescues,else_,ensure_]
1779
1861
  end
1780
1862
 
1781
1863
  def op?; false end
@@ -1793,7 +1875,7 @@ end
1793
1875
  def special_conditions!; nil end
1794
1876
 
1795
1877
  def non_empty
1796
- body.size+rescues.size > 0 or !!ensures
1878
+ rescues.size > 0 or !!ensures or body
1797
1879
  end
1798
1880
 
1799
1881
  identity_param :non_empty, false, true
@@ -1839,7 +1921,7 @@ end
1839
1921
  # include OpNode
1840
1922
  param_names :body, :rescues #, :else!, :ensure!
1841
1923
  def initialize(expr,rescueword,backup)
1842
- replace [expr,[RescueNode[[],nil,backup]]]
1924
+ replace [expr,[RescueNode[[],nil,backup]].extend(ListInNode)]
1843
1925
  end
1844
1926
 
1845
1927
  def else; nil end
@@ -1910,7 +1992,7 @@ end
1910
1992
  class AssignmentRhsNode < Node #not to appear in final parse tree
1911
1993
  param_names :open_, :val, :close_
1912
1994
  def initialize(*args)
1913
- if args.size==1: super args.first
1995
+ if args.size==1; super args.first
1914
1996
  else super args[1]
1915
1997
  end
1916
1998
  end
@@ -1970,6 +2052,11 @@ end
1970
2052
 
1971
2053
  op=op.ident
1972
2054
 
2055
+ if Array==rhs.class
2056
+ rhs.extend ListInNode
2057
+ end
2058
+
2059
+ @offset=lhs.offset
1973
2060
  return super(lhs,op,rhs)
1974
2061
  #punting, i hope the next layer can handle += and the like
1975
2062
 
@@ -2128,7 +2215,7 @@ end
2128
2215
  UnaryStarNode===right and rhs=[:svalue, rhs]
2129
2216
 
2130
2217
  # case left
2131
- # when VarNode:
2218
+ # when VarNode;
2132
2219
  [node_type, left.ident.to_sym, rhs]
2133
2220
  # else [node_type, left.data[0].parsetree(o), left.data[1].data[0].ident.+('=').to_sym ,[:array, rhs]]
2134
2221
  # end
@@ -2222,6 +2309,9 @@ end
2222
2309
  end
2223
2310
  }
2224
2311
  replace data
2312
+ @offset=self.first.offset
2313
+ @startline=self.first.startline
2314
+ @endline=self.last.endline
2225
2315
  end
2226
2316
 
2227
2317
  def unparse o=default_unparse_options
@@ -2329,7 +2419,7 @@ end
2329
2419
  @had_parens=true
2330
2420
  end
2331
2421
 
2332
- super(data)
2422
+ super(data) unless data.empty?
2333
2423
  end
2334
2424
 
2335
2425
  def unparse o=default_unparse_options
@@ -2606,6 +2696,7 @@ end
2606
2696
  arrowrange=first..last
2607
2697
  arrows=param_list[arrowrange]
2608
2698
  h=HashLiteralNode.new(nil,arrows,nil)
2699
+ h.offset=arrows.first.offset
2609
2700
  h.startline=arrows.first.startline
2610
2701
  h.endline=arrows.last.endline
2611
2702
  param_list[arrowrange]=[h]
@@ -2623,14 +2714,18 @@ end
2623
2714
  param_list=[param_list]
2624
2715
  end
2625
2716
 
2717
+ param_list.extend ListInNode if param_list
2718
+
2626
2719
  if block
2627
2720
  @do_end=block.do_end
2628
2721
  blockparams=block.params
2629
- block=SequenceNode[*block.body] #||[]
2722
+ block=block.body #||[]
2630
2723
  end
2631
2724
  @offset=method.offset
2632
- method=method.ident
2633
- fail unless String===method
2725
+ if Token===method
2726
+ method=method.ident
2727
+ fail unless String===method
2728
+ end
2634
2729
  super(nil,method,param_list,blockparams,block)
2635
2730
  #receiver, if any, is tacked on later
2636
2731
  end
@@ -2860,7 +2955,6 @@ end
2860
2955
 
2861
2956
  class CallNode<CallSiteNode #normal method calls
2862
2957
  def initialize(method,open_paren,param_list,close_paren,block)
2863
- MethNameToken===method or fail
2864
2958
  super
2865
2959
  end
2866
2960
  end
@@ -2895,11 +2989,7 @@ end
2895
2989
  class BlockNode<ValueNode #not to appear in final parse tree
2896
2990
  param_names :params,:body
2897
2991
  def initialize(open_brace,formals,stmts,close_brace)
2898
- case stmts
2899
- when SequenceNode; stmts=Array.new(stmts)
2900
- when nil; stmts=[]
2901
- else stmts=[stmts]
2902
- end
2992
+ stmts||=SequenceNode[{:@offset => open_brace.offset, :@startline=>open_brace.startline}]
2903
2993
 
2904
2994
  formals&&=BlockParams.new(Array.new(formals))
2905
2995
  @do_end=true unless open_brace.not_real?
@@ -2935,6 +3025,7 @@ end
2935
3025
 
2936
3026
  class NopNode<ValueNode
2937
3027
  def initialize(*args)
3028
+ @startline=@endline=1
2938
3029
  super()
2939
3030
  end
2940
3031
 
@@ -2994,6 +3085,7 @@ end
2994
3085
 
2995
3086
  @open=token.open
2996
3087
  @close=token.close
3088
+ @offset=token.offset
2997
3089
  @bs_handler=str.bs_handler
2998
3090
 
2999
3091
  if /[\[{]/===@char
@@ -3019,6 +3111,16 @@ end
3019
3111
  =end
3020
3112
  end
3021
3113
 
3114
+ def initialize_ivars
3115
+ @char||='"'
3116
+ @open||='"'
3117
+ @close||='"'
3118
+ @bs_handler||=:dquote_esc_seq
3119
+ if /[\[{]/===@char
3120
+ @parses_like||=split_into_words(str)
3121
+ end
3122
+ end
3123
+
3022
3124
  def translate_escapes(str)
3023
3125
  rl=RubyLexer.new("(string escape translation hack...)",'')
3024
3126
  result=str.dup
@@ -3101,13 +3203,8 @@ end
3101
3203
 
3102
3204
  def image; '(#@char)' end
3103
3205
 
3104
- def delete_extraneous_ivars!
3105
- @parses_like.delete_extraneous_ivars! if defined? @parses_like
3106
- return super
3107
- end
3108
-
3109
3206
  def walk(*args,&callback)
3110
- return @parses_like.walk(*args,&callback) if defined? @parses_like
3207
+ @parses_like.walk(*args,&callback) if defined? @parses_like
3111
3208
  super
3112
3209
  end
3113
3210
 
@@ -3152,7 +3249,8 @@ end
3152
3249
 
3153
3250
  if tokens.size==1 and VarNameToken===tokens.first
3154
3251
  data[i]=VarNode.new tokens.first
3155
- data[i].endline=token.endline
3252
+ data[i].startline=data[i].endline=token.endline
3253
+ data[i].offset=tokens.first.offset
3156
3254
  else
3157
3255
  #parse the token list in the string inclusion
3158
3256
  parser=Thread.current[:$RedParse_parser]
@@ -3211,6 +3309,7 @@ end
3211
3309
  ]omx
3212
3310
  SQ_ODD=/#{SQ_EVEN}#{SQ_ESC}/omx
3213
3311
  def split_into_words strtok
3312
+ @offset=strtok.offset
3214
3313
  return unless /[{\[]/===@char
3215
3314
  result=ArrayLiteralNode[]
3216
3315
  result << StringNode['',{:@char=>'"',:@open=>@open,:@close=>@close,:@bs_handler=>@bs_handler}]
@@ -3343,14 +3442,14 @@ end
3343
3442
  each{|elem|
3344
3443
  case elem
3345
3444
  when String
3445
+ was_esc_nl= (elem=="\\\n") #ick
3346
3446
  elem=translate_escapes elem
3347
3447
  if saw_string
3348
- result=[:str, elem]
3448
+ vals.push [:str, elem] if !elem.empty? or was_esc_nl
3349
3449
  else
3350
3450
  saw_string=true
3351
- result=elem
3451
+ vals.push elem
3352
3452
  end
3353
- vals.push result
3354
3453
  when NopNode
3355
3454
  vals.push [:evstr]
3356
3455
  when Node #,VarNameToken
@@ -3384,7 +3483,7 @@ end
3384
3483
  charset=set
3385
3484
  end
3386
3485
  }
3387
- vals.push numopts|charset unless numopts|charset==0
3486
+ regex_options= numopts|charset unless numopts|charset==0
3388
3487
  val=/#{val}/
3389
3488
  type
3390
3489
  when '{'
@@ -3432,6 +3531,7 @@ end
3432
3531
  type=DOWNSHIFT_STRING_TYPE[type]
3433
3532
  end
3434
3533
  result= vals.unshift(type)
3534
+ result.push regex_options if regex_options
3435
3535
  end
3436
3536
  result=[:match, result] if defined? @implicit_match and @implicit_match
3437
3537
  return result
@@ -3520,6 +3620,15 @@ end
3520
3620
  super(val)
3521
3621
  end
3522
3622
 
3623
+ def self.inline_symbols data
3624
+ #don't mangle symbols when constructing node like: LiteralNode[:foo]
3625
+ data
3626
+ end
3627
+
3628
+ def []=(*args)
3629
+ original_brackets_assign( *args )
3630
+ end
3631
+
3523
3632
  def bare_method
3524
3633
  Symbol===val || StringNode===val
3525
3634
  end
@@ -3587,6 +3696,7 @@ end
3587
3696
  class VarLikeNode<ValueNode #nil,false,true,__FILE__,__LINE__,self
3588
3697
  param_names :name
3589
3698
  def initialize(name,*more)
3699
+ @offset=name.offset
3590
3700
  if name.ident=='('
3591
3701
  #simulate nil
3592
3702
  replace ['nil']
@@ -3626,6 +3736,7 @@ end
3626
3736
 
3627
3737
  class ArrayLiteralNode<ValueNode
3628
3738
  def initialize(lbrack,contents,rbrack)
3739
+ @offset=lbrack.offset
3629
3740
  contents or return super()
3630
3741
  if CommaOpNode===contents
3631
3742
  super( *contents )
@@ -3683,10 +3794,12 @@ end
3683
3794
  class IfNode < ValueNode
3684
3795
  param_names :condition,:consequent,:elsifs,:otherwise
3685
3796
  def initialize(iftok,condition,thentok,consequent,elsifs,else_,endtok)
3797
+ @offset=iftok.offset
3686
3798
  if else_
3687
3799
  else_=else_.val or @empty_else=true
3688
3800
  end
3689
3801
  condition.special_conditions! if condition.respond_to? :special_conditions!
3802
+ elsifs.extend ListInNode if elsifs
3690
3803
  super(condition,consequent,elsifs,else_)
3691
3804
  @reverse= iftok.ident=="unless"
3692
3805
  if @reverse
@@ -3789,6 +3902,7 @@ end
3789
3902
  class ElsifNode<Node
3790
3903
  param_names(:elsifword_,:condition,:thenword_,:consequent)
3791
3904
  def initialize(elsifword,condition,thenword,consequent)
3905
+ @offset=elsifword.offset
3792
3906
  condition.special_conditions! if condition.respond_to? :special_conditions!
3793
3907
  super(condition,consequent)
3794
3908
  end
@@ -3816,6 +3930,7 @@ end
3816
3930
  #this class should be abstract and have 2 concrete descendants for while and until
3817
3931
  param_names :condition, :body
3818
3932
  def initialize(loopword,condition,thenword,body,endtok)
3933
+ @offset=loopword.offset
3819
3934
  condition.special_conditions! if condition.respond_to? :special_conditions!
3820
3935
  super(condition,body)
3821
3936
  @reverse= loopword.ident=="until"
@@ -3865,9 +3980,11 @@ end
3865
3980
  alias otherwise else
3866
3981
 
3867
3982
  def initialize(caseword, condition, semi, whens, otherwise, endword)
3983
+ @offset=caseword.offset
3868
3984
  if otherwise
3869
3985
  otherwise=otherwise.val or @empty_else=true
3870
3986
  end
3987
+ whens.extend ListInNode
3871
3988
  super(condition,whens,otherwise)
3872
3989
  end
3873
3990
 
@@ -3893,16 +4010,24 @@ end
3893
4010
  end
3894
4011
 
3895
4012
  def parsetree(o)
3896
- [:case, condition&&condition.parsetree(o)]+
3897
- whens.map{|whennode| whennode.parsetree(o)}+
3898
- [otherwise&&otherwise.parsetree(o)]
4013
+ result=[:case, condition&&condition.parsetree(o)]+
4014
+ whens.map{|whennode| whennode.parsetree(o)}
4015
+ other=otherwise&&otherwise.parsetree(o)
4016
+ if other and other[0..1]==[:case, nil] and !condition
4017
+ result.concat other[2..-1]
4018
+ else
4019
+ result<<other
4020
+ end
4021
+ return result
3899
4022
  end
3900
4023
  end
3901
4024
 
3902
4025
  class WhenNode<Node #not to appear in final tree?
3903
4026
  param_names(:whenword_,:when!,:thenword_,:then!)
3904
4027
  def initialize(whenword,when_,thenword,then_)
4028
+ @offset=whenword.offset
3905
4029
  when_=Array.new(when_) if CommaOpNode===when_
4030
+ when_.extend ListInNode if when_.class==Array
3906
4031
  super(when_,then_)
3907
4032
  end
3908
4033
  alias body then
@@ -3952,6 +4077,7 @@ end
3952
4077
  class ForNode<ValueNode
3953
4078
  param_names(:forword_,:for!,:inword_,:in!,:doword_,:do!,:endword_)
3954
4079
  def initialize(forword,for_,inword,in_,doword,do_,endword)
4080
+ @offset=forword.offset
3955
4081
  #elide 1 layer of parens if present
3956
4082
  for_=for_.first if ParenedNode===for_
3957
4083
  for_=CommaOpNode===for_ ? Array.new(for_) : [for_]
@@ -4007,6 +4133,7 @@ end
4007
4133
 
4008
4134
  class HashLiteralNode<ValueNode
4009
4135
  def initialize(open,contents,close)
4136
+ @offset=open.offset rescue contents.first.offset
4010
4137
  case contents
4011
4138
  when nil; super()
4012
4139
  when ArrowOpNode; super(contents.first,contents.last)
@@ -4027,6 +4154,7 @@ end
4027
4154
  end
4028
4155
 
4029
4156
  attr :no_arrows
4157
+ attr_writer :offset
4030
4158
 
4031
4159
  def image; "({})" end
4032
4160
 
@@ -4044,12 +4172,36 @@ end
4044
4172
  return result
4045
4173
  end
4046
4174
 
4175
+ def get k
4176
+ case k
4177
+ when Node;
4178
+ k.delete_extraneous_ivars!
4179
+ k.delete_linenums!
4180
+ when Symbol, Numeric; k=LiteralNode[k]
4181
+ when true,false,nil; k=VarLikeNode[k.inspect]
4182
+ else raise ArgumentError
4183
+ end
4184
+ return as_h[k]
4185
+ end
4186
+
4187
+ def as_h
4188
+ return @h if defined? @h
4189
+ @h={}
4190
+ (0...size).step(2){|i|
4191
+ k=self[i].dup
4192
+ k.delete_extraneous_ivars!
4193
+ k.delete_linenums!
4194
+ @h[k]=self[i+1]
4195
+ }
4196
+ return @h
4197
+ end
4198
+
4047
4199
  def parsetree(o)
4048
4200
  map{|elem| elem.rescue_parsetree(o)}.unshift :hash
4049
4201
  end
4050
4202
 
4051
4203
  def error? rubyversion=1.8
4052
- return true if @no_arrows and rubyversion>=1.9
4204
+ return true if defined?(@no_arrows) and rubyversion>=1.9
4053
4205
  return super
4054
4206
  end
4055
4207
  end
@@ -4062,6 +4214,7 @@ end
4062
4214
  def initialize(if_,qm,then_,colon,else_)
4063
4215
  super(if_,then_,else_)
4064
4216
  condition.special_conditions! if condition.respond_to? :special_conditions!
4217
+ @offset=self.first.offset
4065
4218
  end
4066
4219
 
4067
4220
  def image; "(?:)" end
@@ -4088,8 +4241,9 @@ end
4088
4241
  alias else elses
4089
4242
  alias params args
4090
4243
 
4091
- def initialize(defword_,header,maybe_eq_,semi_,
4244
+ def initialize(defword,header,maybe_eq_,semi_,
4092
4245
  body,rescues,else_,ensure_,endword_)
4246
+ @offset=defword.offset
4093
4247
  @empty_else=@empty_ensure=nil
4094
4248
  # if DotCallNode===header
4095
4249
  # header=header.data[1]
@@ -4111,6 +4265,8 @@ end
4111
4265
  if ensure_
4112
4266
  ensure_=ensure_.val or @empty_ensure=true
4113
4267
  end
4268
+ args.extend ListInNode if args
4269
+ rescues.extend ListInNode if rescues
4114
4270
  replace [receiver,header,args,body,rescues,else_,ensure_]
4115
4271
  end
4116
4272
 
@@ -4194,11 +4350,11 @@ end
4194
4350
  case arg
4195
4351
  when VarNode
4196
4352
  args.push arg.ident.to_sym
4197
- when UnaryStarNode:
4353
+ when UnaryStarNode
4198
4354
  args.push "*#{arg.val.ident}".to_sym
4199
- when UnOpNode:
4355
+ when UnOpNode
4200
4356
  nil
4201
- when AssignNode:
4357
+ when AssignNode
4202
4358
  initvals << arg.parsetree(o)
4203
4359
  initvals[-1][-1]=arg.right.rescue_parsetree(o) #ugly
4204
4360
  args.push arg[0].ident.to_sym
@@ -4301,6 +4457,7 @@ end
4301
4457
  include BareSymbolUtils
4302
4458
  param_names(:aliasword_,:to,:from)
4303
4459
  def initialize(aliasword,to,from)
4460
+ @offset=aliasword.offset
4304
4461
  to=baresym2str(to)
4305
4462
  from=baresym2str(from)
4306
4463
  super(to,from)
@@ -4323,6 +4480,7 @@ end
4323
4480
  class UndefNode < ValueNode
4324
4481
  include BareSymbolUtils
4325
4482
  def initialize(first,middle,last=nil)
4483
+ @offset=first.offset
4326
4484
  if last
4327
4485
  node,newsym=first,last
4328
4486
  super(*node << baresym2str(newsym))
@@ -4359,8 +4517,10 @@ end
4359
4517
  param_names(:name,:body,:rescues,:else!,:ensure!)
4360
4518
 
4361
4519
  def initialize moduleword,name,semiword,body,rescues,else_,ensure_,endword
4520
+ @offset=moduleword.offset
4362
4521
  else_=else_.val if else_
4363
4522
  ensure_=ensure_.val if ensure_
4523
+ rescues.extend ListInNode if rescues
4364
4524
  super(name,body,rescues,else_,ensure_)
4365
4525
  end
4366
4526
 
@@ -4402,12 +4562,14 @@ end
4402
4562
  class ClassNode<NamespaceNode
4403
4563
  param_names(:name,:parent,:body,:rescues,:else!,:ensure!)
4404
4564
  def initialize(classword,name,semi,body,rescues, else_, ensure_, endword)
4565
+ @offset=classword.offset
4405
4566
  if OpNode===name
4406
4567
  name,op,parent=*name
4407
4568
  op=="<" or fail "invalid superclass expression: #{name}"
4408
4569
  end
4409
4570
  else_=else_.val if else_
4410
4571
  ensure_=ensure_.val if ensure_
4572
+ rescues.extend ListInNode if rescues
4411
4573
  super(name,parent,body,rescues,else_,ensure_)
4412
4574
  end
4413
4575
 
@@ -4450,8 +4612,10 @@ end
4450
4612
  class MetaClassNode<NamespaceNode
4451
4613
  param_names :val, :body, :rescues,:else!,:ensure!
4452
4614
  def initialize classword, leftleftword, val, semiword, body, rescues,else_,ensure_, endword
4615
+ @offset=classword.offset
4453
4616
  else_=else_.val if else_
4454
4617
  ensure_=ensure_.val if ensure_
4618
+ rescues.extend ListInNode if rescues
4455
4619
  super(val,body,rescues,else_,ensure_)
4456
4620
  end
4457
4621
 
@@ -4480,15 +4644,16 @@ end
4480
4644
  class RescueHeaderNode<Node #not to appear in final tree
4481
4645
  param_names :exceptions,:varname
4482
4646
  def initialize(rescueword,arrowword,exceptions,thenword)
4647
+ @offset=rescueword.offset
4483
4648
  case exceptions
4484
4649
  when nil
4485
- when VarNode:
4650
+ when VarNode
4486
4651
  if arrowword
4487
4652
  exvarname=exceptions
4488
4653
  exceptions=nil
4489
4654
  arrowword=nil
4490
4655
  end
4491
- when ArrowOpNode:
4656
+ when ArrowOpNode
4492
4657
  exvarname=exceptions.last
4493
4658
  exceptions=exceptions.first
4494
4659
  when CommaOpNode
@@ -4510,9 +4675,11 @@ end
4510
4675
  class RescueNode<Node
4511
4676
  param_names :exceptions,:varname,:action
4512
4677
  def initialize(rescuehdr,action,semi)
4678
+ @offset=rescuehdr.offset
4513
4679
  exlist=rescuehdr.exceptions||[]
4514
4680
  exlist=[exlist] unless exlist.class==Array
4515
4681
  fail unless exlist.class==Array
4682
+ exlist.extend ListInNode
4516
4683
  super(exlist,rescuehdr.varname,action)
4517
4684
  end
4518
4685
 
@@ -4564,6 +4731,8 @@ end
4564
4731
  when nil
4565
4732
  else [params]
4566
4733
  end
4734
+ params.extend ListInNode if params
4735
+ @offset=receiver.offset
4567
4736
  super(receiver,params)
4568
4737
  end
4569
4738
 
@@ -1,3 +1,3 @@
1
1
  class RedParse
2
- VERSION='0.8.2'
2
+ VERSION='0.8.3'
3
3
  end
@@ -89,6 +89,7 @@ class Test::Unit::TestCase
89
89
  end
90
90
  end
91
91
 
92
+ #print output immediately on failing test (at end too....)
92
93
  require 'test/unit/ui/console/testrunner'
93
94
  class Test::Unit::UI::Console::TestRunner
94
95
  alias add_fault__no_immed_output add_fault
@@ -99,6 +100,55 @@ class Test::Unit::UI::Console::TestRunner
99
100
  end
100
101
  end
101
102
 
103
+ =begin nice idea, don't work yet
104
+ class Test::Unit::TestResult
105
+ @@FAILING_CASES=[]
106
+
107
+ begin
108
+ huh #but this is running at the wrong time...
109
+ huh #need to run before tests are run but after defined
110
+ eval Marshal.load(huh).map{|name,case|
111
+ name=huh quote name
112
+ "
113
+ class #{case}
114
+ alias_method :'first_off_#{name}', :'#{name}'
115
+ undef_method :'#{name}'
116
+ end
117
+ "
118
+ }.to_s
119
+
120
+ in_a_loop{
121
+ huh #ensure methods named first_off_test* get run first
122
+ some_test_case._method=name
123
+ some_test_case.run(huh result){huh}
124
+ }
125
+
126
+ rescue Exception
127
+ #ignore it
128
+ end
129
+
130
+ alias add_error__no_error_memory add_error
131
+ def add_error x
132
+ name=x.test_name
133
+ i=name.rindex('(')
134
+ @@FAILING_CASES.push [name[0...i],name[i..-1]]
135
+
136
+ add_error__no_error_memory x
137
+ end
138
+
139
+ alias add_failure__no_error_memory add_failure
140
+ def add_failure x
141
+ name=x.test_name
142
+ i=name.rindex('(')
143
+ @@FAILING_CASES.push [name[0...i],name[i..-1]]
144
+
145
+ add_failure__no_error_memory x
146
+ end
147
+
148
+ at_exit {huh @@FAILING_CASES}
149
+ end
150
+ =end
151
+
102
152
  class ParseTree
103
153
  def put o
104
154
  o=Marshal.dump o
@@ -196,6 +246,16 @@ class RedParseTest<Test::Unit::TestCase
196
246
  FAILURE_EXAMPLES=[
197
247
  ]
198
248
  RUBYBUG_EXAMPLES=[
249
+ ' case
250
+ when 0
251
+ guecoding
252
+ else case
253
+ when eucjp_match_length
254
+ guing
255
+ end
256
+ end',
257
+
258
+ 'case; when false; else case; when nil; else 5; end; end',
199
259
  'def foo(a=b=c={}) end',
200
260
  "$11111111111111111111111111111111111111111111111111111111111111111111",
201
261
  "c do p (110).m end",
@@ -211,6 +271,23 @@ class RedParseTest<Test::Unit::TestCase
211
271
  ]
212
272
 
213
273
  ONELINERS=[
274
+ 'p (a,b=c,d); a +h'...'',
275
+ 'x{return (a,b=c,d)}'...'',
276
+ 'x{r (a,b=c,d)}'...'',
277
+ 'x{return (a,b=c,d)|1}'...'',
278
+ 'x{r (a,b=c,d)|1}'...'',
279
+ 'case; when false; else case; when nil; else 5; end; end'...'',
280
+ 'case;else case; else; end;end'...'',
281
+ 'case; else; end'...'',
282
+ 'c while d and 2.a?(b)..8'...'',
283
+ 'c while d and 888888888888888888888888888888888888888888888888888888..2.a?(b)'...'',
284
+ 'c while d and 8.8..2.a?(b)'...'',
285
+ 'c while d and 8..2.a?(b)'...'',
286
+ 'c while d and :a8..2.a?(b)'...'',
287
+ 'c while d and /8/..2.a?(b)'...'',
288
+ 'c while d and /8/../2.a?(b)/'...'',
289
+ 'c while d and 8../2.a?(b)/'...'',
290
+ 'c while d and a8../2.a?(b)/'...'',
214
291
  'z = valueo_s rescue "?"'...'',
215
292
  '"#{publi}#{}>"'...'',
216
293
  'return (@images = @old_imgs)'...'',
@@ -2742,6 +2819,24 @@ class RedParseTest<Test::Unit::TestCase
2742
2819
  END
2743
2820
 
2744
2821
  STANZAS=PASSTHRU_BSLASHES_ENTIRE+%q[
2822
+ module
2823
+ =begin =end
2824
+ =end
2825
+ A; end
2826
+
2827
+ module A
2828
+ =begin =end
2829
+ =end
2830
+ ::B; end
2831
+
2832
+ module A::
2833
+ =begin =end
2834
+ =end
2835
+ B; end
2836
+
2837
+ =begin =end
2838
+ =end
2839
+
2745
2840
  return @senders[1] =
2746
2841
  2
2747
2842
 
@@ -3747,7 +3842,7 @@ EOS
3747
3842
  end
3748
3843
  end
3749
3844
 
3750
- BEGIN{p Dir.getwd; File.unlink "problemexprs" rescue nil}
3845
+ BEGIN{File.unlink "problemexprs" rescue nil}
3751
3846
  def problem_exprs
3752
3847
  @problem_exprs||=nil
3753
3848
  return @problem_exprs if @problem_exprs
@@ -3832,9 +3927,6 @@ EOS
3832
3927
 
3833
3928
  end #until output.equal? tree
3834
3929
 
3835
- # puts "warning: unparser tests disabled for now"
3836
- # return #skip unparse tests for now
3837
-
3838
3930
  return unless nodes
3839
3931
  begin
3840
3932
  unparsed=nodes.unparse
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redparse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.8.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Caleb Clausen
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin/
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-22 00:00:00 -07:00
12
+ date: 2009-07-06 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -32,16 +32,6 @@ dependencies:
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.4.7
34
34
  version:
35
- - !ruby/object:Gem::Dependency
36
- name: Ron
37
- type: :runtime
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- version: "0"
44
- version:
45
35
  - !ruby/object:Gem::Dependency
46
36
  name: hoe
47
37
  type: :development