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
add_parent_links!()
click to toggle source
# File lib/redparse/node.rb, line 738 def add_parent_links! walk{|parent,i,subi,o| o.parent=parent if Node===o } end
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
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
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