class RedParse::ListInNode::Node

Attributes

endline[RW]
errors[RW]
offset[R]
parent[RW]
startline[W]

Public Class Methods

[](*data) click to toggle source
# File lib/redparse/node.rb, line 461
def self.[](*data)
  options=data.pop if Hash===data.last
  inline_symbols data
  result=allocate
  result.instance_eval{
    replace data
    options.each_pair{|name,val|
      instance_variable_set name,val
    } if options
  }
  result.initialize_ivars
  return result
end
create(*args) click to toggle source
# File lib/redparse/node.rb, line 398
def self.create(*args)
  new(*args)
end
inline_symbols(data) click to toggle source
# File lib/redparse/node.rb, line 453
def self.inline_symbols data
  data.map!{|datum| 
    Symbol===datum ? 
      CallNode[nil,datum.to_s,nil,nil,nil] : 
      datum 
  }
end
namelist() click to toggle source
# File lib/redparse/node.rb, line 632
def self.namelist
  #@namelist
  result=superclass.namelist||[] rescue []
  result.concat @namelist if defined? @namelist
  result.uniq!
  return result
end
new(*data) click to toggle source
# File lib/redparse/node.rb, line 382
def initialize(*data)
  if Hash===data.last
    options=data.pop
    options.each_pair{|name,val|
      instance_variable_set name,val
    }
  end
  replace data
end
param_names(*names) click to toggle source
# File lib/redparse/node.rb, line 590
def self.param_names(*names)
  accessors=[]
  namelist=[]
  @namelist=[]
  names.each{|name| 
    name=name.to_s
    last=name[-1]
    name.chomp! '!' and name << ?_
    namelist << name
    unless last==?_
      accessors << "def #{name.chomp('_')}; self[#{@namelist.size}] end\n"
      accessors << "def #{name.chomp('_')}=(newval); "+
                   "newval.extend ::RedParse::ListInNode if ::Array===newval and not RedParse::Node===newval;"+
                   "self[#{@namelist.size}]=newval "+
                   "end\n"
      @namelist << name
    end
  }
  init="
    def initialize(#{namelist.join(', ')})
      replace [#{@namelist.size==1 ? 
                @namelist.first : 
                @namelist.join(', ')
            }]
    end
    alias init_data initialize
       "

  code= "class ::#{self}\n"+init+accessors.join+"\nend\n"
  if defined? DEBUGGER__ or defined? Debugger
    Tempfile.open("param_name_defs"){|f|
      f.write code
      f.flush
      load f.path
    }
  else
    eval code
  end

  @namelist.reject!{|name| /_\Z/===name }
end

Public Instance Methods

+(other) click to toggle source
# File lib/redparse/node.rb, line 406
def +(other)
  if SequenceNode===other
    SequenceNode[self,*other]
  else
    SequenceNode[self,other]
  end
end
+@() click to toggle source

convert to a Reg::Array expression. subnodes are also converted. if any matchers are present in the tree, they will be included directly into the enclosing Node's matcher. this can be a nice way to turn a (possibly deeply nested) node tree into a matcher. note: anything stored in instance variables is ignored in the matcher.

# File lib/redparse/node.rb, line 1084
def +@
  node2matcher=proc{|n|
    case n
    when Node; +n
    when Array; +[*n.map(&node2matcher)]
    else n
    end
  }
  return +[*map(&node2matcher)] & self.class
end
==(other) click to toggle source
Calls superclass method
# File lib/redparse/node.rb, line 402
def ==(other)
  super and flattened_ivars_equal?(other)
end
[]=(*args) click to toggle source
Calls superclass method
# File lib/redparse/node.rb, line 415
def []=(*args)
  val=args.pop
  #inline symbols as callnodes
  case val
  when Symbol
    val=CallNode[nil,val.to_s]
  when Integer,Float
    val=LiteralNode[val]
  end
  super( *args<<val )
end
Also aliased as: original_brackets_assign
begin_parsetree(o) click to toggle source
# File lib/redparse/node.rb, line 667
def begin_parsetree(o); parsetree(o) end
classic_inspect() click to toggle source
# File lib/redparse/node.rb, line 479
def classic_inspect
  self.class.name.dup+'['+
    map{|elem| 
      if elem.respond_to? :classic_inspect
        elem.classic_inspect
      else
        elem.inspect
      end
    }.join(', ')+
  ']'
  #this skips ivars, tho...
end
data() click to toggle source
# File lib/redparse/node.rb, line 436
def data
  unless @@data_warned
    warn "using obsolete Node#data from #{caller.first}"
    @@data_warned=true
  end
  Array.new(self)
end
Also aliased as: unwrap
deep_copy(transform={}) click to toggle source

why not use Ron::GraphWalk.graph_copy instead here?

# File lib/redparse/node.rb, line 1009
def deep_copy transform={},&override
  handler=proc{|child|
    if transform.has_key? child.__id__ 
      transform[child.__id__]
    else
      case child
      when Node 
          override&&override[child] or 
            child.deep_copy(transform,&override)
      when Array
          child.clone.map!(&handler)
      when Integer,Symbol,Float,nil,false,true,Module
          child
      else 
          child.clone
      end
    end
  }

  newdata=map(&handler)

  result=clone
  instance_variables.each{|iv| 
    unless iv=="@data" or iv==:@data
      val=instance_variable_get(iv)
      result.instance_variable_set(iv,handler[val])
    end
  }
  result.replace newdata
  return result
end
delete_extraneous_ivars!() click to toggle source
# File lib/redparse/node.rb, line 1041
def delete_extraneous_ivars!
  walk{|parent,i,subi,node|
    case node
    when Node
      node.remove_instance_variable :@offset rescue nil
      node.remove_instance_variable :@loopword_offset rescue nil
      node.remove_instance_variable :@iftok_offset rescue nil
      node.remove_instance_variable :@endline rescue nil
      node.remove_instance_variable :@lvalue rescue nil
      if node.respond_to? :lvalue 
        node.lvalue or
          node.remove_instance_variable :@lvalue rescue nil 
      end
    when Token
      print "#{node.inspect} in "; pp parent
      fail "no tokens should be present in final parse tree (maybe except VarNameToken, ick)"
    end
    true
  }
  return self
end
delete_linenums!() click to toggle source
# File lib/redparse/node.rb, line 1063
def delete_linenums!
  walk{|parent,i,subi,node|
    case node
    when Node
      node.remove_instance_variable :@endline rescue nil
      node.remove_instance_variable :@startline rescue nil
    end
    true
  }
  return self
end
depthwalk(parent=nil,index=nil,subindex=nil,&callback) click to toggle source
# File lib/redparse/node.rb, line 698
def depthwalk(parent=nil,index=nil,subindex=nil,&callback)
  (size-1).downto(0){|i|
    datum=self[i]
    case datum
    when Node
      datum.depthwalk(self,i,&callback)
    when Array
      (datum.size-1).downto(0){|j|
        x=datum[j]
        if Node===x
          x.depthwalk(self,i,j,&callback) 
        else 
          callback[self,i,j,x]
        end
      }
    else 
      callback[self, i, nil, datum]
    end
  }
  callback[ parent,index,subindex,self ]
end
depthwalk_nodes(parent=nil,index=nil,subindex=nil,&callback) click to toggle source
# File lib/redparse/node.rb, line 720
def depthwalk_nodes(parent=nil,index=nil,subindex=nil,&callback)
  (size-1).downto(0){|i|
    datum=self[i]
    case datum
    when Node
      datum.depthwalk_nodes(self,i,&callback)
    when Array
      (datum.size-1).downto(0){|j|
        x=datum[j]
        if Node===x
          x.depthwalk_nodes(self,i,j,&callback)
        end
      }
    end
  }
  callback[ parent,index,subindex,self ]
end
error?(x;) click to toggle source
# File lib/redparse/node.rb, line 433
def error? x; false end
evalable_inspect() click to toggle source
# File lib/redparse/node.rb, line 550
def evalable_inspect
  ivarnames=instance_variables-["@data", :@data]
  ivars=ivarnames.map{|ivarname| 
    val=instance_variable_get(ivarname)
    if val.respond_to?(:evalable_inspect)
      val=val.evalable_inspect
    else
      val=val.inspect
    end
    ":"+ivarname+"=>"+val 
  }.join(', ')

  bare="["+map{|val|
    if val.respond_to?(:evalable_inspect)
      val=val.evalable_inspect
    else
      val=val.inspect
    end
  }.join(", ")+"]"

  bare.gsub!(/\]\Z/, ", {"+ivars+"}]") unless ivarnames.empty?
  return self.class.name+bare
end
fixup_multiple_assignments!() click to toggle source
# File lib/redparse/node.rb, line 875
def fixup_multiple_assignments! #dead code
 result=self
 walk{|parent,i,subi,node|
  if CommaOpNode===node
    #there should be an assignnode within this node... find it
    j=nil
    list=Array.new(node)
    assignnode=nil
    list.each_with_index{|assignnode2,jj| assignnode=assignnode2
      AssignNode===assignnode and break(j=jj)
    }
    fail "CommaOpNode without any assignment in final parse tree" unless j

    #re-hang the current node with = at the top
    lhs=list[0...j]<<list[j].left
    rhs=list[j+1..-1].unshift list[j].right
    if lhs.size==1 and MultiAssign===lhs.first
      lhs=lhs.first
    else
      lhs=MultiAssign.new(lhs)
    end
    node=AssignNode.new(lhs, assignnode.op, rhs)

    #graft the new node back onto the old tree
    if parent
      if subi
        parent[i][subi]=node
      else
        parent[i]=node
      end
    else #replacement at top level
      result=node
    end

    #re-scan newly made node, since we tell caller not to scan our children
    node.fixup_multiple_assignments!

    false #skip (your old view of) my children, please
  else
    true
  end
 }
 
 return result

end
fixup_rescue_assignments!() click to toggle source
# File lib/redparse/node.rb, line 931
def fixup_rescue_assignments! #dead code
  result=self
  walk{|parent,i,subi,node|
    #if a rescue op with a single assignment on the lhs
    if RescueOpNode===node and assign=node.first and #ick
         AssignNode===assign and assign.op.ident=="=" and 
         !(assign.multi? or 
           prohibit_fixup assign.right)


      #re-hang the node with = at the top instead of rescue
      node=AssignNode.new(assign.left, assign.op,
        RescueOpNode.new(assign.right,nil,node[1][0].action)
      )
      
      #graft the new node back onto the old tree
      if parent
        if subi
          parent[i][subi]=node
        else
          parent[i]=node
        end
      else #replacement at top level
        result=node
      end

      #re-scan newly made node, since we tell caller not to scan our children
      node.fixup_rescue_assignments!

      false #skip (your old view of) my children, please
    else
      true
    end
  }
  return result
end
image() click to toggle source
# File lib/redparse/node.rb, line 427
def image; "(#{inspect})" end
initialize_ivars() click to toggle source
# File lib/redparse/node.rb, line 392
def initialize_ivars
  @offset||=0
  @startline||=0
  @endline||=0
end
inspect(label=nil,indent=0,verbose=false) click to toggle source
# File lib/redparse/node.rb, line 492
def inspect label=nil,indent=0,verbose=false
  ivarnames=instance_variables.map{|v| v.to_s }
  ivarnames-=FlattenedIvars::EXCLUDED_IVARS
  ivarnames-=noinspect_instance_variables if defined? noinspect_instance_variables
  ivarnodes=[]
  ivars=ivarnames.map{|ivarname|
    ivar=instance_variable_get(ivarname)
    if Node===ivar
      ivarnodes.push [ivarname,ivar]
      nil
    else
      ivarname[1..-1]+"="+ivar.inspect if ivar and verbose
    end
  }.compact.join(' ')


  if verbose
    pos=@startline.to_s
    pos<<"..#@endline" if @endline!=@startline
    pos<<"@#@offset"
  end
  classname=self.class.name
  classname.sub!(/^(?:RedParse::)?(.*?)(?:Node)?$/){$1}
  result= [' '*indent,"+",(label.to_s+': ' if label),classname,]
  result+=[" pos=",pos,] if pos
  result+=[" ",ivars,"\n"]
  indent+=2

  namelist=self.class.namelist
  if namelist and !namelist.empty?
    namelist.each{|name|
      val=send name rescue "{{ERROR INSPECTING ATTR #{name}}}"
      case val
        when Node; result<< val.inspect(name,indent,verbose)
        when ListInNode 
          result.push ' '*indent,"+#{name}:\n",*val.map{|v| 
            v.inspect(nil,indent+2,verbose) rescue ' '*(indent+2)+"-#{v.inspect}\n"
          }
        when nil;
        else ivars<< " #{name}=#{val.inspect}"
      end
    }
  else
    each{|val|
      case val
      when Node; result<< val.inspect(nil,indent,verbose) 
      else result<< ' '*indent+"-#{val.inspect}\n"
      end
    }
  end

  ivarnodes.each{|(name,val)|
    result<< val.inspect(name,indent)
  }

  return result.join
end
lhs_unparse(o;) click to toggle source
# File lib/redparse/node.rb, line 640
def lhs_unparse o; unparse(o) end
linerange() click to toggle source
# File lib/redparse/node.rb, line 863
def linerange
  min=9999999999999999999999999999999999999999999999999999
  max=0
  walk{|parent,i,subi,node|
    if node.respond_to? :endline and line=node.endline
      min=[min,line].min
      max=[max,line].max
    end
  }
  return min..max
end
lvalue() click to toggle source
# File lib/redparse/node.rb, line 1006
def lvalue; nil end
lvars_defined_in() click to toggle source
# File lib/redparse/node.rb, line 968
def lvars_defined_in
  result=[]
  walk {|parent,i,subi,node|
    case node
    when MethodNode,ClassNode,ModuleNode,MetaClassNode; false
    when CallSiteNode
      Node===node.receiver and
        result.concat node.receiver.lvars_defined_in 
      node.args.each{|arg| 
        result.concat arg.lvars_defined_in if Node===arg
      } if node.args
      false
    when AssignNode
      lvalue=node.left
      lvalue.respond_to? :all_current_lvars and
        result.concat lvalue.all_current_lvars 
      true
    when ForNode
      lvalue=node.for
      lvalue.respond_to? :all_current_lvars and
        result.concat lvalue.all_current_lvars 
      true
    when RescueOpNode,BeginNode
        rescues=node[1]
        rescues.each{|resc|
          name=resc.varname
          name and result.push name.ident
        }
      true
    else true
    end
  }

  result.uniq!
  return result
end
merge_replacement_session(session,tempsession) click to toggle source
# File lib/redparse/node.rb, line 839
      def merge_replacement_session session,tempsession
        ts_has_boundvars= !tempsession.keys.grep(::Symbol).empty?
        tempsession.each_pair{|k,v|
          if Integer===k
if true
            v=Reg::WithBoundRefValues.new(v,tempsession) if ts_has_boundvars
else
            v=Ron::GraphWalk.graphcopy(v){|cntr,o,i,ty,useit|
              if Reg::BoundRef===o
                useit[0]=true
                tempsession[o.name]||o
              end
            }
end
            if session.has_key? k
              v=v.chain_to session[k]
            end
            session[k]=v
          elsif "finally"==k
            session["finally"]=Array(session["finally"]).concat v
          end
        }
      end
negate(condition,offset=nil) click to toggle source
# File lib/redparse/node.rb, line 673
def negate(condition,offset=nil)
    if UnOpNode===condition and condition.op.ident[/^(!|not)$/]
      condition.val
    else
      UnOpNode.new(KeywordToken.new("not",offset),condition)
    end
end
original_brackets_assign(*args)
Alias for: []=
parsetree(o) click to toggle source
# File lib/redparse/node.rb, line 662
def parsetree(o)
  "wrong(#{inspect})"
end
parsetrees(list,o) click to toggle source
# File lib/redparse/node.rb, line 669
def parsetrees list,o
  !list.empty? and list.map{|node| node.parsetree(o)}
end
pretty_print(q) click to toggle source
# File lib/redparse/node.rb, line 574
      def pretty_print(q)
        ivarnames=instance_variables-["@data", :@data]
        ivars={}
        ivarnames.each{|ivarname| 
          ivars[ivarname.to_sym]=instance_variable_get(ivarname)
        }
        q.group(1, self.class.name+'[', ']') {
          displaylist= ivars.empty? ? self : dup<<ivars
          q.seplist(displaylist) {|v|
            q.pp v
          }
#          q.text ', '
#          q.pp_hash ivars
        }
      end
prohibit_fixup(x) click to toggle source
# File lib/redparse/node.rb, line 922
      def prohibit_fixup x
        case x
        when UnaryStarNode; true
#        when ParenedNode; x.size>1
        when CallSiteNode; x.params and !x.real_parens
        else false
        end
      end
replace_ivars_and_self(o,session,&replace_self_action) click to toggle source
# File lib/redparse/node.rb, line 818
def replace_ivars_and_self o,session,&replace_self_action
    o.instance_variables.each{|ovname|
      ov=o.instance_variable_get(ovname)
      
      replace_value ov.__id__,ov,session do |new|
        o.instance_variable_set(ovname,new)
      end
    }
    replace_value o.__id__,o,session, &replace_self_action
end
replace_value(ovid,ov,session,&replace_action) click to toggle source
# File lib/redparse/node.rb, line 829
def replace_value ovid,ov,session,&replace_action
    if session.has_key? ovid
        new= session[ovid]
        if Reg::Formula===new
          new=new.formula_value(ov,session)
        end
        replace_action[new]
    end
end
rescue_parsetree(o) click to toggle source
# File lib/redparse/node.rb, line 666
def rescue_parsetree(o); parsetree(o) end
rfind(ifnone=nil, &block) click to toggle source
# File lib/redparse/node.rb, line 804
def rfind ifnone=nil, &block
  result=find(proc{
    find{|subnode| subnode.rfind(&block) if subnode.respond_to? :rfind}
  },&block)
  return result if result
  return ifnone[] if ifnone
end
rfind_all(&block) click to toggle source
# File lib/redparse/node.rb, line 812
def rfind_all &block
  result=find_all(&block)
  each{|subnode| result.concat subnode.find_all(&block) if subnode.respond_to? :rfind_all}
  return result
end
rgrep(pattern) click to toggle source
# File lib/redparse/node.rb, line 798
def rgrep pattern
  result=grep(pattern)
  each{|subnode| result.concat subnode.rgrep(pattern) if subnode.respond_to? :rgrep}
  return result
end
short_inspect(cutoff=2) click to toggle source
# File lib/redparse/node.rb, line 429
def short_inspect(cutoff=2)
  inspect.gsub(/\n {#{cutoff*2},}.*$/,'')
end
startline() click to toggle source
# File lib/redparse/node.rb, line 446
def startline
  @startline||=endline
end
to_parsetree(*options) click to toggle source
# File lib/redparse/node.rb, line 644
def to_parsetree(*options)
  o={}
  [:newlines,:quirks,:ruby187].each{|opt| 
    o[opt]=true if options.include? opt
  }

  result=[parsetree(o)] 

  result=[] if result==[[]] || result==[nil]

  return result
end
to_parsetree_and_warnings(*options) click to toggle source
# File lib/redparse/node.rb, line 657
def to_parsetree_and_warnings(*options)
  #for now, no warnings are ever output
  return to_parsetree(*options),[]
end
to_ruby(o={}) click to toggle source
# File lib/redparse/node.rb, line 642
def to_ruby o={}; unparse(o) end
to_s() click to toggle source
# File lib/redparse/node.rb, line 475
def to_s #mostly for form inside #{ }
  unparse
end
unary() click to toggle source
# File lib/redparse/node.rb, line 1005
def unary; false end
unwrap()
Alias for: data
walk(parent=nil,index=nil,subindex=nil,&callback) click to toggle source

callback takes four parameters: parent of node currently being walked, index and subindex within that parent, and finally the actual node being walked.

# File lib/redparse/node.rb, line 684
def walk(parent=nil,index=nil,subindex=nil,&callback)
  callback[ parent,index,subindex,self ] and
  each_with_index{|datum,i|
    case datum
    when Node; datum.walk(self,i,&callback)
    when Array;
      datum.each_with_index{|x,j| 
        Node===x ? x.walk(self,i,j,&callback) : callback[self,i,j,x]
      }
    else callback[self,i,nil,datum]
    end
  }
end
xform_tree!(*xformers) click to toggle source
# File lib/redparse/node.rb, line 746
      def xform_tree!(*xformers)
        #search tree for patterns and store results of actions in session
        session={}
        depthwalk{|parent,i,subi,o|
          xformers.each{|xformer|
            if o
              tempsession={}
              xformer.xform!(o,tempsession)
              merge_replacement_session session, tempsession
            #elsif xformer===o and Reg::Transform===xformer
            #  new=xformer.right
            #  if Reg::Formula===right
            #    new=new.formula_value(o,session)
            #  end
            #  subi ? parent[i][subi]=new : parent[i]=new
            end
          }
        }
        session["final"]=true
        
        #apply saved-up actions stored in session, while making a copy of tree
        result=::Ron::GraphWalk::graphcopy(self,old2new={}){|cntr,o,i,ty,useit|
          newo=nil
          replace_value o.__id__,o,session do |val|
            newo=val
            useit[0]=true
          end
          newo
        }
        finallys=session["finally"] #finallys too
        finallys.each{|(action,arg)| action[old2new[arg.__id__],session] } if finallys

        return result
=begin was
        finallys=session["finally"]
        finallys.each{|(action,arg)| action[arg] } if finallys

        depthwalk{|parent,i,subi,o|
          next unless parent
          replace_ivars_and_self o, session do |new|
            subi ? parent[i][subi]=new : parent[i]=new
          end
        }
        replace_ivars_and_self self,session do |new|
          fail unless new
          return new
        end

        return self
=end
      end

Protected Instance Methods

unparse_maybe_parens(o,changed=[]) click to toggle source
# File lib/redparse/node.rb, line 1172
def unparse_maybe_parens(o,changed=[])
  result=unparse(o)
  if !o[:exact] and 
    case self
    when CallNode; params and params.size>0 and !real_parens
    when KWCallNode,AliasNode,UndefNode,SequenceNode; true
    when AssignNode; MultiAssign===left
    end
  then
    result="(#{result})"
    changed[0]=true
  end
  return result
end

Private Instance Methods

default_unparse_options() click to toggle source
# File lib/redparse/node.rb, line 1188
def default_unparse_options
  {:linenum=>1}
end
linked_list(arrays) click to toggle source

turn a list (array) of arrays into a linked list, in which each array has a reference to the next in turn as its last element.

# File lib/redparse/node.rb, line 1099
def linked_list(arrays)
  0.upto(arrays.size-2){|i| arrays[i]<<arrays[i+1] }
  return arrays.first
end
param_list_parse(param_list,o) click to toggle source
# File lib/redparse/node.rb, line 1138
def param_list_parse(param_list,o)
  output=[]
  star=amp=nil
  param_list_walk(param_list){|type,val,i|
    case type
    when ''
      output.concat val.map{|param| param.rescue_parsetree(o)}
    when '=>'
      output.push HashLiteralNode.new(nil,val,nil).parsetree(o)
    when '*'; star=val.parsetree(o)
    when '&'; amp=val.parsetree(o)
    end
  }
  return output,star
end
param_list_walk(param_list) { |'',normals,lownormal..i-1| ... } click to toggle source
# File lib/redparse/node.rb, line 1104
def param_list_walk(param_list)
  param_list or return
  limit=param_list.size
  i=0
  normals=[]
  lownormal=nil
  handle_normals=proc{
    yield '',normals,lownormal..i-1 if lownormal
    lownormal=nil
    normals.slice! 0..-1
  }
  while i<limit
    case param=param_list[i]
    when ArrowOpNode
      handle_normals[]
      low=i
      i+=1 while ArrowOpNode===param_list[i]
      high=i-1
      yield '=>',param_list[low..high],low..high
    when UnaryStarNode
      handle_normals[]
      yield '*',param,i
    when UnOpNode&-{:op=>"&@"}
      handle_normals[]
      yield '&',param,i
    else
      lownormal=i unless lownormal
      normals << param
    end
    i+=1
  end
  handle_normals[]
end
unparse_nl(token,o,alt=';',nl="\n") click to toggle source
# File lib/redparse/node.rb, line 1154
def unparse_nl(token,o,alt=';',nl="\n")
  fail unless alt
  #should really only emit newlines
  #to bring line count up to startline, not endline.

  linenum=
  case token 
  when Integer; token 
  when nil; return alt
  else token.startline rescue (return alt)
  end
  shy=(linenum||0)-o[:linenum]
  #warn if shy<0 ???
  return alt if shy<=0
  o[:linenum]=linenum
  return nl*shy
end