class Dyndoc::Scanner

Attributes

scan[R]

IMPORTANT: start and close delimiters are unique and not useable inside text! RMK: this differs from the actual CallManager

Public Class Methods

new(type,start=nil,stop=nil,mode=nil,escape=nil) click to toggle source
# File lib/dyndoc/base/scanner.rb, line 44
def initialize(type,start=nil,stop=nil,mode=nil,escape=nil)
  @tag_type=type
  @tag=@@type[type]
  @start=@tag[:start] unless start
  @start=/#{@start}/ if @start.is_a? String
  @stop=@tag[:stop] unless stop
  @stop=/#{@stop}/ if @stop.is_a? String
  @mode=@tag[:mode] unless mode
  @escape={:start=>@tag[:escape_start],:stop=>@tag[:escape_stop]} unless escape
  #mode corresponds to @start[@mode[:start],@mode[:length]] and @stop[@mode[:stop],@mode[:length]]
  init_strange
  @scan=StringScanner.new("")
end

Public Instance Methods

clean_stack(stack) click to toggle source

stack is a sequence of delimiters clean_stack selects only the associated open and closed delimiters!

# File lib/dyndoc/base/scanner.rb, line 62
    def clean_stack(stack)
      open_stack,keep=[],{}
      stack.each do |elt|
        if elt[1]==1
          open_stack << elt
        else
          if open_stack.empty?
            ##too many closed delimiters
          else
            keep[elt]=true
            keep[open_stack.pop]=true
          end
        end
      end
=begin
      if Dyndoc.cfg_dir[:debug]
        tmp=stack.select{|elt| !keep[elt]}.select{|e| @tag_type==:call and e[2] and e[1]==1 and e[2]!='{'}
        begin p @txt;p tmp  end unless tmp.empty?
      end
=end
      stack.select{|elt| keep[elt]}
    end
extract(res=nil,txt=nil,type=nil) click to toggle source
# File lib/dyndoc/base/scanner.rb, line 179
def extract(res=nil,txt=nil,type=nil)
  if res
    start=0
    txt2=""
    ind=0
    res2=res.map{|r|
      txt2 << txt[start...(r[:start])]
      txt2 << @@strange
      ind += 1
      r2={}
      start=r[:stop]+1
      if r[:inside].empty?
        r2[:txt]=txt[(r[:start])..(r[:stop])]
        r2[:type]=r[:type]
        r2
      else
        tmp=extract(r[:inside],txt[(r[:start])..(r[:stop])],r[:type])
        tmp
      end
    }
    txt2 << txt[start..-1]
    {:txt=>txt2,:type=>type,:inside=> res2}
  else
    res=@token[:inside].dup
    return extract(res,@token[:txt])
  end
end
init_atom() click to toggle source
# File lib/dyndoc/base/scanner.rb, line 127
def init_atom
  if @tag[:atom]
    @txt.gsub!(@tag[:atom][:match]){|w|
      m=@tag[:atom][:match].match(w)
      res=""
      (1...m.size).each{|i|
        res << (@tag[:atom][:replace][i] ? @tag[:atom][:replace][i] : m[i])
      }
      res
    }
  end
end
init_strange(strange=@@strange) click to toggle source
# File lib/dyndoc/base/scanner.rb, line 173
def init_strange(strange=@@strange)
  @strange=strange
  @re_strange=/#{Regexp.escape(@strange)}/
  @re_strange2=/(#{Regexp.escape(@strange)})/
end
rebuild_after_filter(res,filter=nil) click to toggle source
# File lib/dyndoc/base/scanner.rb, line 207
    def rebuild_after_filter(res,filter=nil)
      txt=""
      start=0
#p res
      parts=res[:txt].split(@re_strange,-1)
##puts "parts";p parts
##puts "inside";p res[:inside]
      res[:inside].map do |e|
        txt << parts.shift

        txt2= (e[:inside] ? rebuild_after_filter(e,filter) : e[:txt] )
#puts "txt2";p txt2; p [res[:type],e[:type]]
        #IMPORTANT: process has to have as the second argument e[:type] corresponding to the inside_type and as the third argument res[:type] corresponding to the out_type
##Dyndoc.warn "scan",txt2,e[:type],res[:type],(filter ? filter.process(txt2,e[:type],res[:type]) : txt2)
        txt2=((filter and !(txt2=~/\[HTML\]/)) ? filter.process(txt2,e[:type],res[:type]) : txt2)
##p [:txt2,txt2]
        txt << txt2
      end
#puts "txt";p txt
      txt << parts.shift unless parts.empty?
      txt
    end
token_stack() click to toggle source
# File lib/dyndoc/base/scanner.rb, line 85
def token_stack
  @scan.string=@txt
  @scan.pos=0
  stack,s=[],0
  mode=-2 #stop
  begin
    if mode!=-1
      p1=@scan.check_until(@start)
      if p1
        s1=@scan.pre_match.size
        m1=@scan.matched
      end
    end
    if mode!=1
      p2=@scan.check_until(@stop)
      if p2
        s2=@scan.pre_match.size
        m2=@scan.matched
      end
    end
    if p1 and p2
      mode=(s1<s2 ? 1 : -1)
    elsif p2 and !p1
      mode=-1
    elsif !p2 and p1
      mode=-3 #error
    elsif !p2 and !p1
      mode=-2 #stop
    end
    if mode==1
      stack << [s1,mode,m1] unless @escape[:start] and @escape[:start].include? m1
      @scan.scan_until(@start)
    elsif mode==-1
      s=s2
      stack << [s2,mode,m2] unless @escape[:stop] and @escape[:stop].include? m2
      @scan.scan_until(@stop)
    end
    s=@scan.pos
  end while mode>-2
  return clean_stack(stack)
end
tokenize(txt) click to toggle source
# File lib/dyndoc/base/scanner.rb, line 140
    def tokenize(txt)
      @txt=txt
      init_atom
      stack=token_stack
#p txt
#p stack
      stack2=[]
      root=block={:inside=>[]} #init bloc
      while !stack.empty?
        elt=stack.shift
        #puts "stack2";p stack2
        if elt[1]==1
          #new bloc
          parent=block
          block={:type=>elt[2][0...-1],:start=>elt[0],:inside=>[]}
          stack2 << [block,parent]
        elsif elt[1]==-1
          block,parent=stack2.pop
          block[:stop]=elt[0]+elt[2].size-1
          if parent[:start]
            block[:start] -= parent[:start]
            block[:stop] -=  parent[:start]
          end
          parent[:inside] << block
          block=parent
        end
      end
      return (@token={:txt=> @txt,:inside=> (root[:inside])})
    end