class ReVIEW::TOCParser

Public Class Methods

chapter_node(chap) click to toggle source
# File lib/review/tocparser.rb, line 27
def TOCParser.chapter_node(chap)
  toc = TOCParser.parse(chap)
  unless toc.size == 1
    $stderr.puts "warning: chapter #{toc.join} contains more than 1 chapter"
  end
  toc.first
end
parse(chap) click to toggle source
# File lib/review/tocparser.rb, line 18
def TOCParser.parse(chap)
  f = StringIO.new(chap.content, 'r:BOM|utf-8')
  stream = Preprocessor::Strip.new(f)
  new.parse(stream, chap).map do |root|
    root.number = chap.number
    root
  end
end

Public Instance Methods

compile_label(line) click to toggle source
# File lib/review/tocparser.rb, line 107
def compile_label(line)
  b = ReVIEW::TEXTBuilder.new
  dummy_book = ReVIEW::Book::Base.load
  dummy_chapter = ReVIEW::Book::Chapter.new(dummy_book, 1, '-', nil, StringIO.new)
  dummy_loc = Location.new("", StringIO.new)
  b.bind(ReVIEW::Compiler.new(b), dummy_chapter, dummy_loc)
  b.compile_inline(line)
end
error!(filename, lineno, msg) click to toggle source
# File lib/review/tocparser.rb, line 116
def error!(filename, lineno, msg)
  raise "#{filename}:#{lineno}: #{msg}"
end
get_label(line) click to toggle source
# File lib/review/tocparser.rb, line 102
def get_label(line)
  line = line.strip.sub(/\A=+\s*/, '')
  compile_label(line)
end
parse(f, chap) click to toggle source
# File lib/review/tocparser.rb, line 35
def parse(f, chap)
  roots = [] ## list of chapters
  node_stack = []
  filename = chap.path
  while line = f.gets
    case line
    when /\A\#@/
      # do nothing
    when /\A\s*\z/
      # do nothing
    when /\A(={2,})[\[\s\{]/
      lev = $1.size
      error! filename, f.lineno, "section level too deep: #{lev}" if lev > 5
      label = get_label(line)
      if node_stack.empty?
        # missing chapter label
        dummy_chapter = Chapter.new(label, chap)
        node_stack.push dummy_chapter
        roots.push dummy_chapter
      end
      next if label =~ /\A\[\// # ex) "[/column]"
      sec = Section.new(lev, label.gsub(/\A\{.*?\}\s?/, ""))
      until node_stack.last.level < sec.level
        node_stack.pop
      end
      node_stack.last.add_child sec
      node_stack.push sec

    when /\A=[^=]/
      label = get_label(line)
      node_stack.clear
      new_chapter = Chapter.new(label, chap)
      node_stack.push new_chapter
      roots.push new_chapter

    when %r<\A//\w+(?:\[.*?\])*\{\s*\z>
      if node_stack.empty?
        error! filename, f.lineno, 'list found before section label'
      end
      node_stack.last.add_child(list = List.new)
      beg = f.lineno
      list.add line
      while line = f.gets
        break if %r<\A//\}> =~ line
        list.add line
      end
      error! filename, beg, 'unterminated list' unless line

    when %r<\A//\w>
      # do nothing
    else
      #if node_stack.empty?
      #  error! filename, f.lineno, 'text found before section label'
      #end
      next if node_stack.empty?
      node_stack.last.add_child(par = Paragraph.new(chap))
      par.add line
      while line = f.gets
        break if /\A\s*\z/ =~ line
        par.add line
      end
    end
  end

  roots
end