diff --git a/.rubocop.yml b/.rubocop.yml index a98f8c2c1..931b5ef09 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -2,6 +2,7 @@ AllCops: Exclude: - lib/lineinput.rb - lib/uuid.rb + - lib/review/compiler.rb DisplayCopNames: true inherit_from: .rubocop_todo.yml @@ -49,6 +50,10 @@ Style/OpMethod: Style/VariableName: Enabled: true +# Configuration parameters: CountComments. +Metrics/ClassLength: + Max: 4500 + Style/ConditionalAssignment: Enabled: false diff --git a/Gemfile b/Gemfile index 2fae854ea..20fec56ca 100644 --- a/Gemfile +++ b/Gemfile @@ -3,3 +3,4 @@ source 'https://rubygems.org' # Specify your gem's dependencies in review.gemspec gemspec +gem "json" diff --git a/Rakefile b/Rakefile index bbaac0002..2983b8697 100644 --- a/Rakefile +++ b/Rakefile @@ -1,3 +1,5 @@ +require 'fileutils' + begin require 'bundler' Bundler::GemHelper.install_tasks @@ -20,6 +22,11 @@ task :rubocop do end end +task :kpeg do + FileUtils.rm_f "lib/review/compiler.rb" + sh "kpeg -s lib/review/review.kpeg -o lib/review/compiler.rb" +end + Rake::TestTask.new("test") do |t| t.libs << "test" t.test_files = Dir.glob("test/**/test_*.rb") diff --git a/bin/review-catalog-converter b/bin/review-catalog-converter-peg similarity index 100% rename from bin/review-catalog-converter rename to bin/review-catalog-converter-peg diff --git a/bin/review-check b/bin/review-check-peg similarity index 100% rename from bin/review-check rename to bin/review-check-peg diff --git a/bin/review-checkdep b/bin/review-checkdep-peg similarity index 100% rename from bin/review-checkdep rename to bin/review-checkdep-peg diff --git a/bin/review-compile b/bin/review-compile-peg similarity index 98% rename from bin/review-compile rename to bin/review-compile-peg index 6b3de8ec3..57f97a6a3 100755 --- a/bin/review-compile +++ b/bin/review-compile-peg @@ -107,7 +107,7 @@ def _main exit 1 end - begin +## begin loader = ReVIEW::YAMLLoader.new if config["yaml"] config.deep_merge!(loader.load_file(config["yaml"])) @@ -166,11 +166,11 @@ def _main else raise "must not happen: #{mode}" end - rescue ReVIEW::ApplicationError => err - raise if $DEBUG - error err.message - exit 1 - end +# rescue ReVIEW::ApplicationError => err +# raise if $DEBUG +# error err.message +# exit 1 +# end end def error(msg) diff --git a/bin/review-epubmaker b/bin/review-epubmaker-peg similarity index 100% rename from bin/review-epubmaker rename to bin/review-epubmaker-peg diff --git a/bin/review-index b/bin/review-index-peg similarity index 100% rename from bin/review-index rename to bin/review-index-peg diff --git a/bin/review-init b/bin/review-init-peg similarity index 100% rename from bin/review-init rename to bin/review-init-peg diff --git a/bin/review-pdfmaker b/bin/review-pdfmaker-peg similarity index 100% rename from bin/review-pdfmaker rename to bin/review-pdfmaker-peg diff --git a/bin/review-preproc b/bin/review-preproc-peg similarity index 100% rename from bin/review-preproc rename to bin/review-preproc-peg diff --git a/bin/review-validate b/bin/review-validate-peg similarity index 100% rename from bin/review-validate rename to bin/review-validate-peg diff --git a/bin/review-vol b/bin/review-vol-peg similarity index 100% rename from bin/review-vol rename to bin/review-vol-peg diff --git a/lib/lineinput.rb b/lib/lineinput.rb index 73932ee8c..80da99f3e 100644 --- a/lib/lineinput.rb +++ b/lib/lineinput.rb @@ -58,36 +58,6 @@ def next? peek() ? true : false end - def skip_blank_lines - n = 0 - while line = gets() - unless line.strip.empty? - ungets line - return n - end - n += 1 - end - n - end - - def gets_if(re) - line = gets() - if not line or not (re =~ line) - ungets line - return nil - end - line - end - - def gets_unless(re) - line = gets() - if not line or re =~ line - ungets line - return nil - end - line - end - def each while line = gets() yield line @@ -144,12 +114,4 @@ def until_terminator(re) nil end - def getblock(term_re) - buf = [] - until_terminator(term_re) do |line| - buf.push line - end - buf - end - end diff --git a/lib/review/book/index.rb b/lib/review/book/index.rb index 081a660d9..d62259147 100644 --- a/lib/review/book/index.rb +++ b/lib/review/book/index.rb @@ -92,10 +92,14 @@ def item_type end def number(id) - chapter = @index.fetch(id) - chapter.format_number + chapter = @index.fetch(id, nil) + if chapter + return chapter.format_number + else + return "#{I18n.t("part", chapter.number)}" + end rescue # part - "#{I18n.t("part", chapter.number)}" + raise "invalid number error: id:#{id}, capter:#{chapter}" end def title(id) diff --git a/lib/review/builder.rb b/lib/review/builder.rb index 7da04f0d0..57bfe2c25 100644 --- a/lib/review/builder.rb +++ b/lib/review/builder.rb @@ -22,6 +22,9 @@ class Builder CAPTION_TITLES = %w(note memo tip info warning important caution notice) + attr_accessor :output + attr_accessor :ast + def pre_paragraph nil end @@ -43,6 +46,7 @@ def bind(compiler, chapter, location) @compiler = compiler @chapter = chapter @location = location + @ast = nil @output = StringIO.new @book = @chapter.book if @chapter.present? @tabwidth = nil @@ -64,11 +68,11 @@ def result alias_method :raw_result, :result def print(*s) - @output.print(*s) + raise NotImplementedError, "XXX: `print` method is obsoleted. Do not use it." end def puts(*s) - @output.puts(*s) + raise NotImplementedError, "XXX: `puts` method is obsoleted. Do not use it." end def target_name @@ -83,27 +87,33 @@ def headline_prefix(level) end private :headline_prefix - def list(lines, id, caption, lang = nil) + def list(lines, id, caption = nil, lang = nil) + buf = "" begin - list_header id, caption, lang + buf << list_header(id, caption, lang) rescue KeyError error "no such list: #{id}" end - list_body id, lines, lang + buf << list_body(id, lines, lang) + buf end - def listnum(lines, id, caption, lang = nil) + def listnum(lines, id, caption = nil, lang = nil) + buf = "" begin - list_header id, caption, lang + buf << list_header(id, caption, lang) rescue KeyError error "no such list: #{id}" end - listnum_body lines, lang + buf << listnum_body(lines, lang) + buf end - def source(lines, caption, lang = nil) - source_header caption - source_body lines, lang + def source(lines, caption = nil) + buf = "" + buf << source_header(caption) + buf << source_body(lines, lang) + buf end def image(lines, id, caption, metric = nil) @@ -116,6 +126,7 @@ def image(lines, id, caption, metric = nil) end def table(lines, id = nil, caption = nil) + buf = "" rows = [] sepidx = nil lines.each_with_index do |line, idx| @@ -130,26 +141,27 @@ def table(lines, id = nil, caption = nil) rows = adjust_n_cols(rows) begin - table_header id, caption unless caption.nil? + buf << table_header(id, caption) unless caption.nil? rescue KeyError error "no such table: #{id}" end - return if rows.empty? - table_begin rows.first.size + return buf if rows.empty? + buf << table_begin(rows.first.size) if sepidx sepidx.times do - tr rows.shift.map {|s| th(s) } + buf << tr(rows.shift.map {|s| th(s) }) end rows.each do |cols| - tr cols.map {|s| td(s) } + buf << tr(cols.map {|s| td(s) }) end else rows.each do |cols| h, *cs = *cols - tr [th(h)] + cs.map {|s| td(s) } + buf << tr([th(h)] + cs.map {|s| td(s) }) end end - table_end + buf << table_end + buf end def adjust_n_cols(rows) @@ -178,12 +190,12 @@ def adjust_n_cols(rows) # footnote_end #end - def compile_inline(s) - @compiler.text(s) - end +# def compile_inline(s) +# @compiler.text(s) +# end def inline_chapref(id) - compile_inline @book.chapter_index.display_string(id) + @book.chapter_index.display_string(id) rescue KeyError error "unknown chapter: #{id}" nofunc_text("[UnknownChapter:#{id}]") @@ -197,7 +209,7 @@ def inline_chap(id) end def inline_title(id) - compile_inline @book.chapter_index.title(id) + @book.chapter_index.title(id) rescue KeyError error "unknown chapter: #{id}" nofunc_text("[UnknownChapter:#{id}]") @@ -217,8 +229,14 @@ def inline_img(id) nofunc_text("[UnknownImage:#{id}]") end - def inline_imgref(id) - img = inline_img(id) + def node_inline_img(node) + id = node[0].to_raw + inline_img(id) + end + + def node_inline_imgref(node) + id = node[0].to_raw + img = node_inline_img(node) if @chapter.image(id).caption "#{img}#{I18n.t('image_quote', @chapter.image(id).caption)}" @@ -245,22 +263,17 @@ def inline_bou(str) text(str) end - def inline_ruby(arg) - base, *ruby = *arg.scan(/(?:(?:(?:\\\\)*\\,)|[^,\\]+)+/) - base = base.gsub(/\\,/, ",") if base - ruby = ruby.join(",").gsub(/\\,/, ",") if ruby + def inline_ruby(base, ruby) compile_ruby(base, ruby) end - def inline_kw(arg) - word, alt = *arg.split(',', 2) + def inline_kw(word, alt = nil) compile_kw(word, alt) end - def inline_href(arg) - url, label = *arg.scan(/(?:(?:(?:\\\\)*\\,)|[^,\\]+)+/).map(&:lstrip) - url = url.gsub(/\\,/, ",").strip - label = label.gsub(/\\,/, ",").strip if label + def inline_href(url, label = nil) + url = url.strip + label = label.strip if label compile_href(url, label) end @@ -269,15 +282,18 @@ def text(str) end def bibpaper(lines, id, caption) - bibpaper_header id, caption + buf = "" + buf << bibpaper_header(id, caption) unless lines.empty? - puts "" - bibpaper_bibpaper id, caption, lines + buf << "\n" + buf << bibpaper_bibpaper(id, caption, lines) end - puts "" + buf << "\n" + buf end - def inline_hd(id) + def node_inline_hd(nodelist) + id = nodelist[0].to_raw m = /\A([^|]+)\|(.+)/.match(id) if m && m[1] chapter = @book.contents.detect{|chap| chap.id == m[1]} @@ -318,12 +334,12 @@ def raw(str) builders = matched[1].split(/,/).map{|i| i.gsub(/\s/, '') } c = target_name if builders.include?(c) - print matched[2].gsub("\\n", "\n") + matched[2].gsub("\\n", "\n") else "" end else - print str.gsub("\\n", "\n") + str.gsub("\\n", "\n") end end @@ -332,7 +348,7 @@ def warn(msg) end def error(msg) - raise ApplicationError, "#{@location}: error: #{msg}" + raise ApplicationError, "error: #{msg} at #{@compiler.show_pos} \n (#{@compiler.failure_oneline})" end def handle_metric(str) @@ -418,8 +434,9 @@ def image_ext raise NotImplementedError end + ### XXX def inline_include(file_name) - compile_inline File.read(file_name) + File.read(file_name) end def include(file_name) @@ -433,6 +450,7 @@ def ul_item_begin(lines) end def ul_item_end + "" end def inline_raw(args) diff --git a/lib/review/compiler.rb b/lib/review/compiler.rb index e51b4e123..67f2d5dea 100644 --- a/lib/review/compiler.rb +++ b/lib/review/compiler.rb @@ -1,51 +1,405 @@ -# encoding: utf-8 -# -# Copyright (c) 2002-2007 Minero Aoki -# Copyright (c) 2009-2016 Minero Aoki, Kenshi Muto -# -# This program is free software. -# You can distribute or modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# +# coding: UTF-8 +class ReVIEW::Compiler + # :stopdoc: -require 'review/extentions' -require 'review/preprocessor' -require 'review/exception' -require 'strscan' + # This is distinct from setup_parser so that a standalone parser + # can redefine #initialize and still have access to the proper + # parser setup code. + def initialize(str, debug=false) + setup_parser(str, debug) + end + + + + # Prepares for parsing +str+. If you define a custom initialize you must + # call this method before #parse + def setup_parser(str, debug=false) + set_string str, 0 + @memoizations = Hash.new { |h,k| h[k] = {} } + @result = nil + @failed_rule = nil + @failing_rule_offset = -1 + + setup_foreign_grammar + end + + attr_reader :string + attr_reader :failing_rule_offset + attr_accessor :result, :pos + + def current_column(target=pos) + if c = string.rindex("\n", target-1) + return target - c - 1 + end + + target + 1 + end + + def current_line(target=pos) + if @sizes_memo.respond_to?(:bsearch) + offset = @sizes_memo.bsearch{|line, cur_offset| cur_offset >= target} + if offset + return offset[0] + end + else + @sizes_memo.each do |line, cur_offset| + if cur_offset >= target + return cur_offset + end + end + end + + -1 + end + + def lines + @lines_memo + end + + + + def get_text(start) + @string[start..@pos-1] + end + + # Sets the string and current parsing position for the parser. + def set_string string, pos + @string = string.freeze + @pos = pos + @sizes_memo = [] + if string + @string_size = string.size + @lines_memo = string.lines + cur_offset = cur_line = 0 + @lines_memo.each do |line| + cur_line += 1 + cur_offset += line.size + @sizes_memo << [cur_line, cur_offset] + end + else + @string_size = 0 + @lines_memo = [] + end + end + + def show_pos + width = 10 + if @pos < width + "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")" + else + "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")" + end + end + + def failure_info + l = current_line @failing_rule_offset + c = current_column @failing_rule_offset + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'" + else + "line #{l}, column #{c}: failed rule '#{@failed_rule}'" + end + end + + def failure_caret + l = current_line @failing_rule_offset + c = current_column @failing_rule_offset + + line = lines[l-1] + "#{line}\n#{' ' * (c - 1)}^" + end + + def failure_character + l = current_line @failing_rule_offset + c = current_column @failing_rule_offset + lines[l-1][c-1, 1] + end + + def failure_oneline + l = current_line @failing_rule_offset + c = current_column @failing_rule_offset + + char = lines[l-1][c-1, 1] + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'" + else + "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'" + end + end + + class ParseError < RuntimeError + end + + def raise_error + raise ParseError, failure_oneline + end + + def show_error(io=STDOUT) + error_pos = @failing_rule_offset + line_no = current_line(error_pos) + col_no = current_column(error_pos) + + io.puts "On line #{line_no}, column #{col_no}:" + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')" + else + io.puts "Failed to match rule '#{@failed_rule}'" + end + + io.puts "Got: #{string[error_pos,1].inspect}" + line = lines[line_no-1] + io.puts "=> #{line}" + io.print(" " * (col_no + 3)) + io.puts "^" + end -module ReVIEW + def set_failed_rule(name) + if @pos > @failing_rule_offset + @failed_rule = name + @failing_rule_offset = @pos + end + end + + attr_reader :failed_rule + + def match_string(str) + len = str.size + if @string[pos,len] == str + @pos += len + return str + end + + return nil + end + + def scan(reg) + if m = reg.match(@string[@pos..-1]) + width = m.end(0) + @pos += width + return true + end + + return nil + end + + if "".respond_to? :ord + def get_byte + if @pos >= @string_size + return nil + end + + s = @string[@pos].ord + @pos += 1 + s + end + else + def get_byte + if @pos >= @string_size + return nil + end - class Location - def initialize(filename, f) - @filename = filename - @f = f + s = @string[@pos] + @pos += 1 + s + end + end + + def parse(rule=nil) + # We invoke the rules indirectly via apply + # instead of by just calling them as methods because + # if the rules use left recursion, apply needs to + # manage that. + + if !rule + apply(:_root) + else + method = rule.gsub("-","_hyphen_") + apply :"_#{method}" + end end - attr_reader :filename + class MemoEntry + def initialize(ans, pos) + @ans = ans + @pos = pos + @result = nil + @set = false + @left_rec = false + end + + attr_reader :ans, :pos, :result, :set + attr_accessor :left_rec - def lineno - @f.lineno + def move!(ans, pos, result) + @ans = ans + @pos = pos + @result = result + @set = true + @left_rec = false + end end - def string + def external_invoke(other, rule, *args) + old_pos = @pos + old_string = @string + + set_string other.string, other.pos + begin - "#{@filename}:#{@f.lineno}" - rescue - "#{@filename}:nil" + if val = __send__(rule, *args) + other.pos = @pos + other.result = @result + else + other.set_failed_rule "#{self.class}##{rule}" + end + val + ensure + set_string old_string, old_pos end end - alias_method :to_s, :string - end + def apply_with_args(rule, *args) + memo_key = [rule, args] + if m = @memoizations[memo_key][@pos] + @pos = m.pos + if !m.set + m.left_rec = true + return nil + end + + @result = m.result + + return m.ans + else + m = MemoEntry.new(nil, @pos) + @memoizations[memo_key][@pos] = m + start_pos = @pos + + ans = __send__ rule, *args + + lr = m.left_rec + + m.move! ans, @pos, @result + + # Don't bother trying to grow the left recursion + # if it's failing straight away (thus there is no seed) + if ans and lr + return grow_lr(rule, args, start_pos, m) + else + return ans + end + + return ans + end + end + + def apply(rule) + if m = @memoizations[rule][@pos] + @pos = m.pos + if !m.set + m.left_rec = true + return nil + end + + @result = m.result + + return m.ans + else + m = MemoEntry.new(nil, @pos) + @memoizations[rule][@pos] = m + start_pos = @pos + + ans = __send__ rule + + lr = m.left_rec + + m.move! ans, @pos, @result + + # Don't bother trying to grow the left recursion + # if it's failing straight away (thus there is no seed) + if ans and lr + return grow_lr(rule, nil, start_pos, m) + else + return ans + end + + return ans + end + end + + def grow_lr(rule, args, start_pos, m) + while true + @pos = start_pos + @result = m.result + + if args + ans = __send__ rule, *args + else + ans = __send__ rule + end + return nil unless ans + + break if @pos <= m.pos + + m.move! ans, @pos, @result + end + @result = m.result + @pos = m.pos + return m.ans + end + + class RuleInfo + def initialize(name, rendered) + @name = name + @rendered = rendered + end + + attr_reader :name, :rendered + end + + def self.rule_info(name, rendered) + RuleInfo.new(name, rendered) + end - class Compiler - def initialize(strategy) - @strategy = strategy + # :startdoc: + + + class Error; end + class Position + attr_accessor :pos, :line, :col + def initialize(compiler) + @pos = compiler.pos + @line = compiler.current_line + @col = compiler.current_column end + end + +# rubocop:disable all +require 'review/location' +require 'review/extentions' +require 'review/preprocessor' +require 'review/exception' +require 'review/node' + require 'lineinput' + # require 'review/compiler/literals_1_9' + # require 'review/compiler/literals_1_8' + + ## redifine Compiler.new + def initialize(strategy) + @strategy = strategy + @current_column = nil + @chapter = nil + end - attr_reader :strategy + attr_accessor :strategy def compile(chap) @chapter = chap @@ -53,11 +407,72 @@ def compile(chap) @strategy.result end + def do_compile + @strategy.bind self, @chapter, ReVIEW::Location.new(@chapter.basename, self) + setup_parser(@chapter.content) + parse() + convert_ast + end + + def convert_ast + ast = @strategy.ast + convert_column(ast) + if $DEBUG + File.open("review-dump.json","w") do |f| + f.write(ast.to_json) + end + end + @strategy.output << ast.to_doc + end + + def flush_column(new_content) + if @current_column + new_content << @current_column + @current_column = nil + end + end + + def convert_column(ast) + @column_stack = [] + content = ast.content + new_content = [] + @current_content = new_content + content.each do |elem| + if elem.kind_of?(ReVIEW::HeadlineNode) && elem.cmd && elem.cmd.to_doc == "column" + flush_column(new_content) + @current_content = [] + @current_column = ReVIEW::ColumnNode.new(elem.compiler, elem.position, elem.level, + elem.label, elem.content, @current_content) + next + elsif elem.kind_of?(ReVIEW::HeadlineNode) && elem.cmd && elem.cmd.to_doc =~ %r|^/| + cmd_name = elem.cmd.to_doc[1..-1] + if cmd_name != "column" + raise ReVIEW::CompileError, "#{cmd_name} is not opened." + end + flush_column(new_content) + @current_content = new_content + next + elsif elem.kind_of?(ReVIEW::HeadlineNode) && @current_column && elem.level <= @current_column.level + flush_column(new_content) + @current_content = new_content + end + @current_content << elem + end + flush_column(new_content) + ast.content = new_content + ast + end + + def compile_text(text) + @strategy.nofunc_text(text) + end + class SyntaxElement - def initialize(name, type, argc, &block) + def initialize(name, type, argc, esc, &block) @name = name @type = type @argc_spec = argc + @esc_patterns = esc @checker = block end @@ -65,7 +480,7 @@ def initialize(name, type, argc, &block) def check_args(args) unless @argc_spec === args.size - raise CompileError, "wrong # of parameters (block command //#{@name}, expect #{@argc_spec} but #{args.size})" + raise ReVIEW::CompileError, "wrong # of parameters (block command //#{@name}, expect #{@argc_spec} but #{args.size})" end @checker.call(*args) if @checker end @@ -79,27 +494,49 @@ def min_argc end end + def parse_args(args) + if @esc_patterns + args.map.with_index do |pattern, i| + if @esc_patterns[i] + args[i].__send__("to_#{@esc_patterns[i]}") + else + args[i].to_doc + end + end + else + args.map(&:to_doc) + end + end + def block_required? - @type == :block + @type == :block or @type == :code_block end def block_allowed? - @type == :block or @type == :optional + @type == :block or @type == :code_block or @type == :optional or @type == :optional_code_block + end + + def code_block? + @type == :code_block or @type == :optional_code_block end end SYNTAX = {} - def Compiler.defblock(name, argc, optional = false, &block) - defsyntax name, (optional ? :optional : :block), argc, &block + def self.defblock(name, argc, optional = false, esc = nil, &block) + defsyntax(name, (optional ? :optional : :block), argc, esc, &block) + end + + def self.defcodeblock(name, argc, optional = false, esc = nil, &block) + defsyntax(name, (optional ? :optional_code_block : :code_block), argc, esc, &block) end - def Compiler.defsingle(name, argc, &block) - defsyntax name, :line, argc, &block + def self.defsingle(name, argc, esc = nil, &block) + defsyntax name, :line, argc, esc, &block end - def Compiler.defsyntax(name, type, argc, &block) - SYNTAX[name] = SyntaxElement.new(name, type, argc, &block) + def self.defsyntax(name, type, argc, esc = nil, &block) + SYNTAX[name] = SyntaxElement.new(name, type, argc, esc, &block) end def syntax_defined?(name) @@ -119,32 +556,39 @@ def initialize(name) end INLINE = {} + COMPLEX_INLINE = {} - def Compiler.definline(name) + def self.definline(name) INLINE[name] = InlineSyntaxElement.new(name) end + def self.defcomplexinline(name) + COMPLEX_INLINE[name] = InlineSyntaxElement.new(name) + end + def inline_defined?(name) - INLINE.key?(name.to_sym) + INLINE.key?(name.to_sym) || COMPLEX_INLINE.key?(name.to_sym) end defblock :read, 0 defblock :lead, 0 - defblock :list, 2..3 - defblock :emlist, 0..2 - defblock :cmd, 0..1 - defblock :table, 0..2 - defblock :imgtable, 0..2 defblock :quote, 0 - defblock :image, 2..3, true - defblock :source, 0..2 - defblock :listnum, 2..3 - defblock :emlistnum, 0..2 - defblock :bibpaper, 2..3, true - defblock :doorquote, 1 + defblock :bibpaper, 2..3, true, [:raw, :doc, :doc] + defblock :doorquote, 1, false, [:doc] defblock :talk, 0 - defblock :texequation, 0 - defblock :graph, 1..3 + defblock :graph, 1..3, false, [:raw, :raw, :doc] + + defcodeblock :emlist, 0..2, false, [:doc, :raw] + defcodeblock :cmd, 0..1, false, [:doc] + defcodeblock :source, 0..2, false, [:doc, :raw] + defcodeblock :list, 2..4, false, [:raw, :doc, :raw, :raw] + defcodeblock :listnum, 2..3, false, [:raw, :doc, :raw] + defcodeblock :emlistnum, 0..2, false, [:doc, :raw] + defcodeblock :texequation, 0, false + defcodeblock :table, 0..2, false, [:raw, :doc] + defcodeblock :imgtable, 0..2, false, [:raw, :doc] + defcodeblock :image, 2..3, true, [:raw,:doc,:raw] + defcodeblock :box, 0..1, false, [:doc] defblock :address, 0 defblock :blockquote, 0 @@ -159,22 +603,21 @@ def inline_defined?(name) defblock :notice, 0..1 defblock :warning, 0..1 defblock :tip, 0..1 - defblock :box, 0..1 defblock :comment, 0..1, true - defsingle :footnote, 2 + defsingle :footnote, 2, [:raw, :doc] defsingle :noindent, 0 defsingle :linebreak, 0 defsingle :pagebreak, 0 - defsingle :indepimage, 1..3 - defsingle :numberlessimage, 1..3 + defsingle :indepimage, 1..3, [:raw, :doc, :raw] + defsingle :numberlessimage, 1..3, [:raw, :doc, :raw] defsingle :hr, 0 defsingle :parasep, 0 - defsingle :label, 1 - defsingle :raw, 1 - defsingle :tsize, 1 - defsingle :include, 1 - defsingle :olnum, 1 + defsingle :label, 1, [:raw] + defsingle :raw, 1, [:raw] + defsingle :tsize, 1, [:raw] + defsingle :include, 1, [:raw] + defsingle :olnum, 1, [:raw] definline :chapref definline :chap @@ -185,8 +628,6 @@ def inline_defined?(name) definline :list definline :table definline :fn - definline :kw - definline :ruby definline :bou definline :ami definline :b @@ -194,7 +635,6 @@ def inline_defined?(name) definline :code definline :bib definline :hd - definline :href definline :recipe definline :column definline :tcy @@ -230,330 +670,4494 @@ def inline_defined?(name) definline :include definline :tcy - private + defcomplexinline :kw + defcomplexinline :ruby + defcomplexinline :href - def do_compile - f = LineInput.new(Preprocessor::Strip.new(StringIO.new(@chapter.content))) - @strategy.bind self, @chapter, Location.new(@chapter.basename, f) - tagged_section_init - while f.next? - case f.peek - when /\A\#@/ - f.gets # Nothing to do - when /\A=+[\[\s\{]/ - compile_headline f.gets - when %r<\A\s+\*> - compile_ulist f - when %r<\A\s+\d+\.> - compile_olist f - when %r<\A\s*:\s> - compile_dlist f - when %r<\A//\}> - f.gets - error 'block end seen but not opened' - when %r<\A//[a-z]+> - name, args, lines = read_command(f) - syntax = syntax_descriptor(name) - unless syntax - error "unknown command: //#{name}" - compile_unknown_command args, lines - next - end - compile_command syntax, args, lines - when %r<\A//> - line = f.gets - warn "`//' seen but is not valid command: #{line.strip.inspect}" - if block_open?(line) - warn "skipping block..." - read_block(f) - end - else - if f.peek.strip.empty? - f.gets - next - end - compile_paragraph f - end - end - close_all_tagged_section + def compile_column(level, label, caption, content) + buf = "" + buf << @strategy.__send__("column_begin", level, label, caption) + buf << content.to_doc + buf << @strategy.__send__("column_end", level) + buf end - def compile_headline(line) - @headline_indexs ||= [@chapter.number.to_i - 1] - m = /\A(=+)(?:\[(.+?)\])?(?:\{(.+?)\})?(.*)/.match(line) - level = m[1].size - tag = m[2] - label = m[3] - caption = m[4].strip - index = level - 1 - if tag - if tag !~ /\A\// - close_current_tagged_section(level) - open_tagged_section(tag, level, label, caption) - else - open_tag = tag[1..-1] - prev_tag_info = @tagged_section.pop - unless prev_tag_info.first == open_tag - raise CompileError, "#{open_tag} is not opened." - end - close_tagged_section(*prev_tag_info) - end - else - if @headline_indexs.size > (index + 1) - @headline_indexs = @headline_indexs[0..index] - end - @headline_indexs[index] = 0 if @headline_indexs[index].nil? - @headline_indexs[index] += 1 - close_current_tagged_section(level) - @strategy.headline level, label, caption + def compile_command(name, args, lines, node) + syntax = syntax_descriptor(name) + if !syntax || (!@strategy.respond_to?(syntax.name) && !@strategy.respond_to?("node_#{syntax.name}")) + error "strategy does not support command: //#{name}" + compile_unknown_command args, lines + return end - end - - def close_current_tagged_section(level) - while @tagged_section.last and @tagged_section.last[1] >= level - close_tagged_section(* @tagged_section.pop) + begin + syntax.check_args args + rescue ReVIEW::CompileError => err + error err.message + args = ['(NoArgument)'] * syntax.min_argc end - end - - def headline(level, label, caption) - @strategy.headline level, label, caption - end - - def tagged_section_init - @tagged_section = [] - end - - def open_tagged_section(tag, level, label, caption) - mid = "#{tag}_begin" - unless @strategy.respond_to?(mid) - error "strategy does not support tagged section: #{tag}" - headline level, label, caption - return + if syntax.block_allowed? + compile_block(syntax, args, lines, node) + else + if lines + error "block is not allowed for command //#{syntax.name}; ignore" + end + compile_single(syntax, args, node) end - @tagged_section.push [tag, level] - @strategy.__send__ mid, level, label, caption end - def close_tagged_section(tag, level) - mid = "#{tag}_end" - if @strategy.respond_to?(mid) - @strategy.__send__ mid, level - else - error "strategy does not support block op: #{mid}" + def compile_headline(level, tag, label, caption) + buf = "" + @headline_indexs ||= [0] ## XXX + caption ||= "" + caption.strip! + index = level - 1 + if @headline_indexs.size > (index + 1) + @headline_indexs = @headline_indexs[0..index] end + @headline_indexs[index] = 0 if @headline_indexs[index].nil? + @headline_indexs[index] += 1 + buf << @strategy.headline(level, label, caption) + buf end - def close_all_tagged_section - until @tagged_section.empty? - close_tagged_section(* @tagged_section.pop) - end + def comment(text) + @strategy.comment(text) end - def compile_ulist(f) + def compile_ulist(content) + buf0 = "" level = 0 - f.while_match(/\A\s+\*|\A\#@/) do |line| - next if line =~ /\A\#@/ - - buf = [text(line.sub(/\*+/, '').strip)] - f.while_match(/\A\s+(?!\*)\S/) do |cont| - buf.push text(cont.strip) - end - - line =~ /\A\s+(\*+)/ - current_level = $1.size + content.each do |element| + current_level = element.level + buf = element.to_doc if level == current_level - @strategy.ul_item_end + buf0 << @strategy.ul_item_end # body - @strategy.ul_item_begin buf + buf0 << @strategy.ul_item_begin([buf]) elsif level < current_level # down level_diff = current_level - level level = current_level (1..(level_diff - 1)).to_a.reverse_each do |i| - @strategy.ul_begin {i} - @strategy.ul_item_begin [] + buf0 << @strategy.ul_begin{i} + buf0 << @strategy.ul_item_begin([]) end - @strategy.ul_begin {level} - @strategy.ul_item_begin buf + buf0 << @strategy.ul_begin{level} + buf0 << @strategy.ul_item_begin([buf]) elsif level > current_level # up level_diff = level - current_level level = current_level (1..level_diff).to_a.reverse_each do |i| - @strategy.ul_item_end - @strategy.ul_end {level + i} + buf0 << @strategy.ul_item_end + buf0 << @strategy.ul_end{level + i} end - @strategy.ul_item_end + buf0 << @strategy.ul_item_end # body - @strategy.ul_item_begin buf + buf0 <<@strategy.ul_item_begin([buf]) end end (1..level).to_a.reverse_each do |i| - @strategy.ul_item_end - @strategy.ul_end {i} + buf0 << @strategy.ul_item_end + buf0 << @strategy.ul_end{i} end + buf0 end - def compile_olist(f) - @strategy.ol_begin - f.while_match(/\A\s+\d+\.|\A\#@/) do |line| - next if line =~ /\A\#@/ - - num = line.match(/(\d+)\./)[1] - buf = [text(line.sub(/\d+\./, '').strip)] - f.while_match(/\A\s+(?!\d+\.)\S/) do |cont| - buf.push text(cont.strip) - end - @strategy.ol_item buf, num + def compile_olist(content) + buf0 = "" + buf0 << @strategy.ol_begin + content.each do |element| + ## XXX 1st arg should be String, not Array + buf0 << @strategy.ol_item(element.to_doc.split(/\n/), element.num) end - @strategy.ol_end + buf0 << @strategy.ol_end + buf0 end - def compile_dlist(f) - @strategy.dl_begin - while /\A\s*:/ =~ f.peek - @strategy.dt text(f.gets.sub(/\A\s*:/, '').strip) - @strategy.dd f.break(/\A(\S|\s*:)/).map {|line| text(line.strip) } - f.skip_blank_lines - f.skip_comment_lines + def compile_dlist(content) + buf = "" + buf << @strategy.dl_begin + content.each do |element| + buf << @strategy.dt(element.text.to_doc) + buf << @strategy.dd(element.content.map{|s| s.to_doc}) end - @strategy.dl_end + buf << @strategy.dl_end + buf end - def compile_paragraph(f) - buf = [] - f.until_match(%r<\A//|\A\#@>) do |line| - break if line.strip.empty? - buf.push text(line.sub(/^(\t+)\s*/) {|m| "" * m.size}.strip.gsub(//, "\t")) - end - @strategy.paragraph buf - end - def read_command(f) - line = f.gets - name = line.slice(/[a-z]+/).to_sym - args = parse_args(line.sub(%r<\A//[a-z]+>, '').rstrip.chomp('{'), name) - lines = block_open?(line) ? read_block(f) : nil - return name, args, lines + def compile_unknown_command(args, lines) + @strategy.unknown_command(args, lines) end - def block_open?(line) - line.rstrip[-1,1] == '{' + def compile_block(syntax, args, lines, node) + node_name = "node_#{syntax.name}".to_sym + if @strategy.respond_to?(node_name) + @strategy.__send__(node_name, node) + else + args_conv = syntax.parse_args(args) + @strategy.__send__(syntax.name, (lines || default_block(syntax)), *args_conv) + end end - def read_block(f) - head = f.lineno - buf = [] - f.until_match(%r<\A//\}>) do |line| - unless line =~ /\A\#@/ - buf.push text(line.rstrip) - end - end - unless %r<\A//\}> =~ f.peek - error "unexpected EOF (block begins at: #{head})" - return buf + def default_block(syntax) + if syntax.block_required? + error "block is required for //#{syntax.name}; use empty block" end - f.gets # discard terminator - buf + [] end - def parse_args(str, name=nil) - return [] if str.empty? - scanner = StringScanner.new(str) - words = [] - while word = scanner.scan(/(\[\]|\[.*?[^\\]\])/) - w2 = word[1..-2].gsub(/\\(.)/){ - ch = $1 - (ch == "]" or ch == "\\") ? ch : "\\" + ch - } - words << w2 - end - if !scanner.eos? - error "argument syntax error: #{scanner.rest} in #{str.inspect}" - return [] + def compile_single(syntax, args, node) + node_name = "node_#{syntax.name}".to_sym + if @strategy.respond_to?(node_name) + @strategy.__send__(node_name, node) + else + args_conv = syntax.parse_args(args) + @strategy.__send__(syntax.name, *args_conv) end - return words end - def compile_command(syntax, args, lines) - unless @strategy.respond_to?(syntax.name) - error "strategy does not support command: //#{syntax.name}" - compile_unknown_command args, lines - return + + def compile_inline(op, args) + unless inline_defined?(op) + raise ReVIEW::CompileError, "no such inline op: #{op}" end - begin - syntax.check_args args - rescue CompileError => err - error err.message - args = ['(NoArgument)'] * syntax.min_argc + if @strategy.respond_to?("node_inline_#{op}") + return @strategy.__send__("node_inline_#{op}", args) end - if syntax.block_allowed? - compile_block syntax, args, lines + unless @strategy.respond_to?("inline_#{op}") + raise "strategy does not support inline op: @<#{op}>" + end + if !args + @strategy.__send__("inline_#{op}", "") else - if lines - error "block is not allowed for command //#{syntax.name}; ignore" - end - compile_single syntax, args + @strategy.__send__("inline_#{op}", *(args.map(&:to_doc))) end +# rescue => err +# error err.message end - def compile_unknown_command(args, lines) - @strategy.unknown_command args, lines + def compile_paragraph(buf) + @strategy.paragraph buf end - def compile_block(syntax, args, lines) - @strategy.__send__(syntax.name, (lines || default_block(syntax)), *args) + def compile_raw(builders, content) + c = @strategy.class.to_s.gsub(/ReVIEW::/, '').gsub(/Builder/, '').downcase + if !builders || builders.include?(c) + content.gsub("\\n", "\n") + else + "" + end end - def default_block(syntax) - if syntax.block_required? - error "block is required for //#{syntax.name}; use empty block" - end - [] + def warn(msg) + @strategy.warn msg + end + + def error(msg) + @strategy.error msg + end + + def check_indent(s) + s.size >= @list_stack.last.size + end + + def check_nested_indent(s) + s.size >= @list_stack.last.size + 2 + end + + def check_inline_element_symbol(name) + INLINE.key?(name.to_sym) + end + + def check_complex_inline_element_symbol(name) + COMPLEX_INLINE.key?(name.to_sym) end - def compile_single(syntax, args) - @strategy.__send__(syntax.name, *args) + def position + Position.new(self) end - def text(str) - return '' if str.empty? - words = str.split(/(@<\w+>\{(?:[^\}\\]|\\.)*?\})/, -1) - words.each do |w| - error "`@' seen but is not valid inline op: #{w}" if w.scan(/@<\w+>/).size > 1 && !/\A@/.match(w) + + + + # :stopdoc: + + module ::ReVIEW + class Node; end + class BlockElementNode < Node + def initialize(compiler, position, name, args, content) + @compiler = compiler + @position = position + @name = name + @args = args + @content = content end - result = @strategy.nofunc_text(words.shift) - until words.empty? - result << compile_inline(words.shift.gsub(/\\\}/, '}')) - result << @strategy.nofunc_text(words.shift) + attr_reader :compiler + attr_reader :position + attr_reader :name + attr_reader :args + attr_reader :content + end + class BraceNode < Node + def initialize(compiler, position, content) + @compiler = compiler + @position = position + @content = content end - result - rescue => err - error err.message + attr_reader :compiler + attr_reader :position + attr_reader :content end - public :text # called from strategy - - def compile_inline(str) - op, arg = /\A@<(\w+)>\{(.*?)\}\z/.match(str).captures - unless inline_defined?(op) - raise CompileError, "no such inline op: #{op}" + class BracketArgNode < Node + def initialize(compiler, position, content) + @compiler = compiler + @position = position + @content = content end - unless @strategy.respond_to?("inline_#{op}") - raise "strategy does not support inline op: @<#{op}>" + attr_reader :compiler + attr_reader :position + attr_reader :content + end + class CodeBlockElementNode < Node + def initialize(compiler, position, name, args, content) + @compiler = compiler + @position = position + @name = name + @args = args + @content = content end - @strategy.__send__("inline_#{op}", arg) - rescue => err - error err.message - @strategy.nofunc_text(str) + attr_reader :compiler + attr_reader :position + attr_reader :name + attr_reader :args + attr_reader :content end - - def warn(msg) - @strategy.warn msg + class ColumnNode < Node + def initialize(compiler, position, level, label, caption, content) + @compiler = compiler + @position = position + @level = level + @label = label + @caption = caption + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :level + attr_reader :label + attr_reader :caption + attr_reader :content end - - def error(msg) - @strategy.error msg + class ComplexInlineElementNode < Node + def initialize(compiler, position, symbol, content) + @compiler = compiler + @position = position + @symbol = symbol + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :symbol + attr_reader :content + end + class ComplexInlineElementContentNode < Node + def initialize(compiler, position, content) + @compiler = compiler + @position = position + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :content + end + class DlistNode < Node + def initialize(compiler, position, content) + @compiler = compiler + @position = position + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :content + end + class DlistElementNode < Node + def initialize(compiler, position, text, content) + @compiler = compiler + @position = position + @text = text + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :text + attr_reader :content + end + class DocumentNode < Node + def initialize(compiler, position, content) + @compiler = compiler + @position = position + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :content + end + class HeadlineNode < Node + def initialize(compiler, position, level, cmd, label, content) + @compiler = compiler + @position = position + @level = level + @cmd = cmd + @label = label + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :level + attr_reader :cmd + attr_reader :label + attr_reader :content + end + class InlineElementNode < Node + def initialize(compiler, position, symbol, content) + @compiler = compiler + @position = position + @symbol = symbol + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :symbol + attr_reader :content + end + class InlineElementContentNode < Node + def initialize(compiler, position, content) + @compiler = compiler + @position = position + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :content + end + class NewLineNode < Node + def initialize(compiler, position, content) + @compiler = compiler + @position = position + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :content + end + class OlistNode < Node + def initialize(compiler, position, content) + @compiler = compiler + @position = position + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :content + end + class OlistElementNode < Node + def initialize(compiler, position, num, content) + @compiler = compiler + @position = position + @num = num + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :num + attr_reader :content + end + class ParagraphNode < Node + def initialize(compiler, position, content) + @compiler = compiler + @position = position + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :content + end + class RawNode < Node + def initialize(compiler, builder, position, content) + @compiler = compiler + @builder = builder + @position = position + @content = content + end + attr_reader :compiler + attr_reader :builder + attr_reader :position + attr_reader :content + end + class SinglelineCommentNode < Node + def initialize(compiler, position, content) + @compiler = compiler + @position = position + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :content end + class SinglelineContentNode < Node + def initialize(compiler, position, content) + @compiler = compiler + @position = position + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :content + end + class TextNode < Node + def initialize(compiler, position, content) + @compiler = compiler + @position = position + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :content + end + class UlistNode < Node + def initialize(compiler, position, content) + @compiler = compiler + @position = position + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :content + end + class UlistElementNode < Node + def initialize(compiler, position, level, content) + @compiler = compiler + @position = position + @level = level + @content = content + end + attr_reader :compiler + attr_reader :position + attr_reader :level + attr_reader :content + end + end + module ::ReVIEWConstruction + def block_element(compiler, position, name, args, content) + ::ReVIEW::BlockElementNode.new(compiler, position, name, args, content) + end + def brace(compiler, position, content) + ::ReVIEW::BraceNode.new(compiler, position, content) + end + def bracket_arg(compiler, position, content) + ::ReVIEW::BracketArgNode.new(compiler, position, content) + end + def code_block_element(compiler, position, name, args, content) + ::ReVIEW::CodeBlockElementNode.new(compiler, position, name, args, content) + end + def column(compiler, position, level, label, caption, content) + ::ReVIEW::ColumnNode.new(compiler, position, level, label, caption, content) + end + def complex_inline_element(compiler, position, symbol, content) + ::ReVIEW::ComplexInlineElementNode.new(compiler, position, symbol, content) + end + def complex_inline_element_content(compiler, position, content) + ::ReVIEW::ComplexInlineElementContentNode.new(compiler, position, content) + end + def dlist(compiler, position, content) + ::ReVIEW::DlistNode.new(compiler, position, content) + end + def dlist_element(compiler, position, text, content) + ::ReVIEW::DlistElementNode.new(compiler, position, text, content) + end + def document(compiler, position, content) + ::ReVIEW::DocumentNode.new(compiler, position, content) + end + def headline(compiler, position, level, cmd, label, content) + ::ReVIEW::HeadlineNode.new(compiler, position, level, cmd, label, content) + end + def inline_element(compiler, position, symbol, content) + ::ReVIEW::InlineElementNode.new(compiler, position, symbol, content) + end + def inline_element_content(compiler, position, content) + ::ReVIEW::InlineElementContentNode.new(compiler, position, content) + end + def newline(compiler, position, content) + ::ReVIEW::NewLineNode.new(compiler, position, content) + end + def olist(compiler, position, content) + ::ReVIEW::OlistNode.new(compiler, position, content) + end + def olist_element(compiler, position, num, content) + ::ReVIEW::OlistElementNode.new(compiler, position, num, content) + end + def paragraph(compiler, position, content) + ::ReVIEW::ParagraphNode.new(compiler, position, content) + end + def raw(compiler, builder, position, content) + ::ReVIEW::RawNode.new(compiler, builder, position, content) + end + def singleline_comment(compiler, position, content) + ::ReVIEW::SinglelineCommentNode.new(compiler, position, content) + end + def singleline_content(compiler, position, content) + ::ReVIEW::SinglelineContentNode.new(compiler, position, content) + end + def text(compiler, position, content) + ::ReVIEW::TextNode.new(compiler, position, content) + end + def ulist(compiler, position, content) + ::ReVIEW::UlistNode.new(compiler, position, content) + end + def ulist_element(compiler, position, level, content) + ::ReVIEW::UlistElementNode.new(compiler, position, level, content) + end + end + include ::ReVIEWConstruction + def setup_foreign_grammar; end + + # root = Start + def _root + _tmp = apply(:_Start) + set_failed_rule :_root unless _tmp + return _tmp + end + + # Start = &. { @list_stack = Array.new } Document:c { @strategy.ast = c } + def _Start + + _save = self.pos + while true # sequence + _save1 = self.pos + _tmp = get_byte + self.pos = _save1 + unless _tmp + self.pos = _save + break + end + @result = begin; @list_stack = Array.new ; end + _tmp = true + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_Document) + c = @result + unless _tmp + self.pos = _save + break + end + @result = begin; @strategy.ast = c ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_Start unless _tmp + return _tmp + end + + # Document = BOM? Block*:c {document(self, position, c)} + def _Document + + _save = self.pos + while true # sequence + _save1 = self.pos + _tmp = apply(:_BOM) + unless _tmp + _tmp = true + self.pos = _save1 + end + unless _tmp + self.pos = _save + break + end + _ary = [] + while true + _tmp = apply(:_Block) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + c = @result + unless _tmp + self.pos = _save + break + end + @result = begin; document(self, position, c); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_Document unless _tmp + return _tmp + end + + # Block = BlankLine*:c { c } (SinglelineComment:c | Headline:c | BlockElement:c | Ulist:c | Olist:c | Dlist:c | Paragraph:c) { c } + def _Block + + _save = self.pos + while true # sequence + _ary = [] + while true + _tmp = apply(:_BlankLine) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + c = @result + unless _tmp + self.pos = _save + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save + break + end + + _save2 = self.pos + while true # choice + _tmp = apply(:_SinglelineComment) + c = @result + break if _tmp + self.pos = _save2 + _tmp = apply(:_Headline) + c = @result + break if _tmp + self.pos = _save2 + _tmp = apply(:_BlockElement) + c = @result + break if _tmp + self.pos = _save2 + _tmp = apply(:_Ulist) + c = @result + break if _tmp + self.pos = _save2 + _tmp = apply(:_Olist) + c = @result + break if _tmp + self.pos = _save2 + _tmp = apply(:_Dlist) + c = @result + break if _tmp + self.pos = _save2 + _tmp = apply(:_Paragraph) + c = @result + break if _tmp + self.pos = _save2 + break + end # end choice + + unless _tmp + self.pos = _save + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_Block unless _tmp + return _tmp + end + + # BlankLine = Newline + def _BlankLine + _tmp = apply(:_Newline) + set_failed_rule :_BlankLine unless _tmp + return _tmp + end + + # SinglelineComment = "#@" < NonNewline+ > EOL {singleline_comment(self, position, text)} + def _SinglelineComment + + _save = self.pos + while true # sequence + _tmp = match_string("\#@") + unless _tmp + self.pos = _save + break + end + _text_start = self.pos + _save1 = self.pos + _tmp = apply(:_NonNewline) + if _tmp + while true + _tmp = apply(:_NonNewline) + break unless _tmp + end + _tmp = true + else + self.pos = _save1 + end + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_EOL) + unless _tmp + self.pos = _save + break + end + @result = begin; singleline_comment(self, position, text); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_SinglelineComment unless _tmp + return _tmp + end + + # Headline = HeadlinePrefix:level BracketArg?:cmd BraceArg?:label Space* SinglelineContent?:caption EOL {headline(self, position, level, cmd, label, caption)} + def _Headline + + _save = self.pos + while true # sequence + _tmp = apply(:_HeadlinePrefix) + level = @result + unless _tmp + self.pos = _save + break + end + _save1 = self.pos + _tmp = apply(:_BracketArg) + @result = nil unless _tmp + unless _tmp + _tmp = true + self.pos = _save1 + end + cmd = @result + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _tmp = apply(:_BraceArg) + @result = nil unless _tmp + unless _tmp + _tmp = true + self.pos = _save2 + end + label = @result + unless _tmp + self.pos = _save + break + end + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save + break + end + _save4 = self.pos + _tmp = apply(:_SinglelineContent) + @result = nil unless _tmp + unless _tmp + _tmp = true + self.pos = _save4 + end + caption = @result + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_EOL) + unless _tmp + self.pos = _save + break + end + @result = begin; headline(self, position, level, cmd, label, caption); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_Headline unless _tmp + return _tmp + end + + # HeadlinePrefix = < /={1,5}/ > { text.length } + def _HeadlinePrefix + + _save = self.pos + while true # sequence + _text_start = self.pos + _tmp = scan(/\A(?-mix:={1,5})/) + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save + break + end + @result = begin; text.length ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_HeadlinePrefix unless _tmp + return _tmp + end + + # Paragraph = ParagraphLine+:c {paragraph(self, position, c.flatten)} + def _Paragraph + + _save = self.pos + while true # sequence + _save1 = self.pos + _ary = [] + _tmp = apply(:_ParagraphLine) + if _tmp + _ary << @result + while true + _tmp = apply(:_ParagraphLine) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + c = @result + unless _tmp + self.pos = _save + break + end + @result = begin; paragraph(self, position, c.flatten); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_Paragraph unless _tmp + return _tmp + end + + # ParagraphLine = !Headline !SinglelineComment !BlockElement !Ulist !Olist !Dlist SinglelineContent:c Newline { c } + def _ParagraphLine + + _save = self.pos + while true # sequence + _save1 = self.pos + _tmp = apply(:_Headline) + _tmp = _tmp ? nil : true + self.pos = _save1 + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _tmp = apply(:_SinglelineComment) + _tmp = _tmp ? nil : true + self.pos = _save2 + unless _tmp + self.pos = _save + break + end + _save3 = self.pos + _tmp = apply(:_BlockElement) + _tmp = _tmp ? nil : true + self.pos = _save3 + unless _tmp + self.pos = _save + break + end + _save4 = self.pos + _tmp = apply(:_Ulist) + _tmp = _tmp ? nil : true + self.pos = _save4 + unless _tmp + self.pos = _save + break + end + _save5 = self.pos + _tmp = apply(:_Olist) + _tmp = _tmp ? nil : true + self.pos = _save5 + unless _tmp + self.pos = _save + break + end + _save6 = self.pos + _tmp = apply(:_Dlist) + _tmp = _tmp ? nil : true + self.pos = _save6 + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_SinglelineContent) + c = @result + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_Newline) + unless _tmp + self.pos = _save + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_ParagraphLine unless _tmp + return _tmp + end + + # BlockElement = ("//raw[" RawBlockBuilderSelect?:b RawBlockElementArg*:r1 "]" Space* EOL {raw(self, b, position, r1)} | !"//raw" "//" ElementName:symbol &{ syntax = syntax_descriptor(symbol); syntax && syntax.code_block? } BracketArg*:args "{" Space* Newline CodeBlockElementContents:contents "//}" Space* EOL {code_block_element(self, position, symbol, args, contents)} | !"//raw" "//" ElementName:symbol BracketArg*:args "{" Space* Newline BlockElementContents:contents "//}" Space* EOL {block_element(self, position, symbol, args, contents)} | !"//raw" "//" ElementName:symbol BracketArg*:args Space* EOL {block_element(self, position, symbol, args, nil)}) + def _BlockElement + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _tmp = match_string("//raw[") + unless _tmp + self.pos = _save1 + break + end + _save2 = self.pos + _tmp = apply(:_RawBlockBuilderSelect) + @result = nil unless _tmp + unless _tmp + _tmp = true + self.pos = _save2 + end + b = @result + unless _tmp + self.pos = _save1 + break + end + _ary = [] + while true + _tmp = apply(:_RawBlockElementArg) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + r1 = @result + unless _tmp + self.pos = _save1 + break + end + _tmp = match_string("]") + unless _tmp + self.pos = _save1 + break + end + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save1 + break + end + _tmp = apply(:_EOL) + unless _tmp + self.pos = _save1 + break + end + @result = begin; raw(self, b, position, r1); end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save5 = self.pos + while true # sequence + _save6 = self.pos + _tmp = match_string("//raw") + _tmp = _tmp ? nil : true + self.pos = _save6 + unless _tmp + self.pos = _save5 + break + end + _tmp = match_string("//") + unless _tmp + self.pos = _save5 + break + end + _tmp = apply(:_ElementName) + symbol = @result + unless _tmp + self.pos = _save5 + break + end + _save7 = self.pos + _tmp = begin; syntax = syntax_descriptor(symbol); syntax && syntax.code_block? ; end + self.pos = _save7 + unless _tmp + self.pos = _save5 + break + end + _ary = [] + while true + _tmp = apply(:_BracketArg) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + args = @result + unless _tmp + self.pos = _save5 + break + end + _tmp = match_string("{") + unless _tmp + self.pos = _save5 + break + end + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save5 + break + end + _tmp = apply(:_Newline) + unless _tmp + self.pos = _save5 + break + end + _tmp = apply(:_CodeBlockElementContents) + contents = @result + unless _tmp + self.pos = _save5 + break + end + _tmp = match_string("//}") + unless _tmp + self.pos = _save5 + break + end + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save5 + break + end + _tmp = apply(:_EOL) + unless _tmp + self.pos = _save5 + break + end + @result = begin; code_block_element(self, position, symbol, args, contents); end + _tmp = true + unless _tmp + self.pos = _save5 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save11 = self.pos + while true # sequence + _save12 = self.pos + _tmp = match_string("//raw") + _tmp = _tmp ? nil : true + self.pos = _save12 + unless _tmp + self.pos = _save11 + break + end + _tmp = match_string("//") + unless _tmp + self.pos = _save11 + break + end + _tmp = apply(:_ElementName) + symbol = @result + unless _tmp + self.pos = _save11 + break + end + _ary = [] + while true + _tmp = apply(:_BracketArg) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + args = @result + unless _tmp + self.pos = _save11 + break + end + _tmp = match_string("{") + unless _tmp + self.pos = _save11 + break + end + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save11 + break + end + _tmp = apply(:_Newline) + unless _tmp + self.pos = _save11 + break + end + _tmp = apply(:_BlockElementContents) + contents = @result + unless _tmp + self.pos = _save11 + break + end + _tmp = match_string("//}") + unless _tmp + self.pos = _save11 + break + end + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save11 + break + end + _tmp = apply(:_EOL) + unless _tmp + self.pos = _save11 + break + end + @result = begin; block_element(self, position, symbol, args, contents); end + _tmp = true + unless _tmp + self.pos = _save11 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save16 = self.pos + while true # sequence + _save17 = self.pos + _tmp = match_string("//raw") + _tmp = _tmp ? nil : true + self.pos = _save17 + unless _tmp + self.pos = _save16 + break + end + _tmp = match_string("//") + unless _tmp + self.pos = _save16 + break + end + _tmp = apply(:_ElementName) + symbol = @result + unless _tmp + self.pos = _save16 + break + end + _ary = [] + while true + _tmp = apply(:_BracketArg) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + args = @result + unless _tmp + self.pos = _save16 + break + end + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save16 + break + end + _tmp = apply(:_EOL) + unless _tmp + self.pos = _save16 + break + end + @result = begin; block_element(self, position, symbol, args, nil); end + _tmp = true + unless _tmp + self.pos = _save16 + end + break + end # end sequence + + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_BlockElement unless _tmp + return _tmp + end + + # RawBlockBuilderSelect = "|" Space* RawBlockBuilderSelectSub:c Space* "|" { c } + def _RawBlockBuilderSelect + + _save = self.pos + while true # sequence + _tmp = match_string("|") + unless _tmp + self.pos = _save + break + end + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_RawBlockBuilderSelectSub) + c = @result + unless _tmp + self.pos = _save + break + end + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save + break + end + _tmp = match_string("|") + unless _tmp + self.pos = _save + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_RawBlockBuilderSelect unless _tmp + return _tmp + end + + # RawBlockBuilderSelectSub = (< AlphanumericAscii+ >:c1 Space* "," Space* RawBlockBuilderSelectSub:c2 { [text] + c2 } | < AlphanumericAscii+ >:c1 { [text] }) + def _RawBlockBuilderSelectSub + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _text_start = self.pos + _save2 = self.pos + _tmp = apply(:_AlphanumericAscii) + if _tmp + while true + _tmp = apply(:_AlphanumericAscii) + break unless _tmp + end + _tmp = true + else + self.pos = _save2 + end + if _tmp + text = get_text(_text_start) + end + c1 = @result + unless _tmp + self.pos = _save1 + break + end + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save1 + break + end + _tmp = match_string(",") + unless _tmp + self.pos = _save1 + break + end + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save1 + break + end + _tmp = apply(:_RawBlockBuilderSelectSub) + c2 = @result + unless _tmp + self.pos = _save1 + break + end + @result = begin; [text] + c2 ; end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save5 = self.pos + while true # sequence + _text_start = self.pos + _save6 = self.pos + _tmp = apply(:_AlphanumericAscii) + if _tmp + while true + _tmp = apply(:_AlphanumericAscii) + break unless _tmp + end + _tmp = true + else + self.pos = _save6 + end + if _tmp + text = get_text(_text_start) + end + c1 = @result + unless _tmp + self.pos = _save5 + break + end + @result = begin; [text] ; end + _tmp = true + unless _tmp + self.pos = _save5 + end + break + end # end sequence + + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_RawBlockBuilderSelectSub unless _tmp + return _tmp + end + + # RawBlockElementArg = !"]" ("\\]" { "]" } | "\\n" { "\n" } | < NonNewline > { text }) + def _RawBlockElementArg + + _save = self.pos + while true # sequence + _save1 = self.pos + _tmp = match_string("]") + _tmp = _tmp ? nil : true + self.pos = _save1 + unless _tmp + self.pos = _save + break + end + + _save2 = self.pos + while true # choice + + _save3 = self.pos + while true # sequence + _tmp = match_string("\\]") + unless _tmp + self.pos = _save3 + break + end + @result = begin; "]" ; end + _tmp = true + unless _tmp + self.pos = _save3 + end + break + end # end sequence + + break if _tmp + self.pos = _save2 + + _save4 = self.pos + while true # sequence + _tmp = match_string("\\n") + unless _tmp + self.pos = _save4 + break + end + @result = begin; "\n" ; end + _tmp = true + unless _tmp + self.pos = _save4 + end + break + end # end sequence + + break if _tmp + self.pos = _save2 + + _save5 = self.pos + while true # sequence + _text_start = self.pos + _tmp = apply(:_NonNewline) + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save5 + break + end + @result = begin; text ; end + _tmp = true + unless _tmp + self.pos = _save5 + end + break + end # end sequence + + break if _tmp + self.pos = _save2 + break + end # end choice + + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_RawBlockElementArg unless _tmp + return _tmp + end + + # BracketArg = "[" BracketArgInline*:content "]" {bracket_arg(self, position, content)} + def _BracketArg + + _save = self.pos + while true # sequence + _tmp = match_string("[") + unless _tmp + self.pos = _save + break + end + _ary = [] + while true + _tmp = apply(:_BracketArgInline) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + content = @result + unless _tmp + self.pos = _save + break + end + _tmp = match_string("]") + unless _tmp + self.pos = _save + break + end + @result = begin; bracket_arg(self, position, content); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_BracketArg unless _tmp + return _tmp + end + + # BracketArgInline = (InlineElement:c { c } | "\\]" {text(self, position, "]")} | "\\\\" {text(self, position, "\\")} | < /[^\r\n\]]/ > {text(self, position, text)}) + def _BracketArgInline + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _tmp = apply(:_InlineElement) + c = @result + unless _tmp + self.pos = _save1 + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save2 = self.pos + while true # sequence + _tmp = match_string("\\]") + unless _tmp + self.pos = _save2 + break + end + @result = begin; text(self, position, "]"); end + _tmp = true + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save3 = self.pos + while true # sequence + _tmp = match_string("\\\\") + unless _tmp + self.pos = _save3 + break + end + @result = begin; text(self, position, "\\"); end + _tmp = true + unless _tmp + self.pos = _save3 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save4 = self.pos + while true # sequence + _text_start = self.pos + _tmp = scan(/\A(?-mix:[^\r\n\]])/) + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save4 + break + end + @result = begin; text(self, position, text); end + _tmp = true + unless _tmp + self.pos = _save4 + end + break + end # end sequence + + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_BracketArgInline unless _tmp + return _tmp + end + + # BraceArg = "{" < /([^\r\n}\\]|\\[^\r\n])*/ > "}" { text } + def _BraceArg + + _save = self.pos + while true # sequence + _tmp = match_string("{") + unless _tmp + self.pos = _save + break + end + _text_start = self.pos + _tmp = scan(/\A(?-mix:([^\r\n}\\]|\\[^\r\n])*)/) + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save + break + end + _tmp = match_string("}") + unless _tmp + self.pos = _save + break + end + @result = begin; text ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_BraceArg unless _tmp + return _tmp + end + + # BlockElementContents = BlockElementContent*:c { c } + def _BlockElementContents + + _save = self.pos + while true # sequence + _ary = [] + while true + _tmp = apply(:_BlockElementContent) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + c = @result + unless _tmp + self.pos = _save + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_BlockElementContents unless _tmp + return _tmp + end + + # BlockElementContent = (SinglelineComment:c { c } | BlockElement:c { c } | Ulist:c | Dlist:c | Olist:c | BlankLine:c { c } | BlockElementParagraph:c { c }) + def _BlockElementContent + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _tmp = apply(:_SinglelineComment) + c = @result + unless _tmp + self.pos = _save1 + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save2 = self.pos + while true # sequence + _tmp = apply(:_BlockElement) + c = @result + unless _tmp + self.pos = _save2 + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + break if _tmp + self.pos = _save + _tmp = apply(:_Ulist) + c = @result + break if _tmp + self.pos = _save + _tmp = apply(:_Dlist) + c = @result + break if _tmp + self.pos = _save + _tmp = apply(:_Olist) + c = @result + break if _tmp + self.pos = _save + + _save3 = self.pos + while true # sequence + _tmp = apply(:_BlankLine) + c = @result + unless _tmp + self.pos = _save3 + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save3 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save4 = self.pos + while true # sequence + _tmp = apply(:_BlockElementParagraph) + c = @result + unless _tmp + self.pos = _save4 + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save4 + end + break + end # end sequence + + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_BlockElementContent unless _tmp + return _tmp + end + + # BlockElementParagraph = BlockElementParagraphLine+:c {paragraph(self, position, c.flatten)} + def _BlockElementParagraph + + _save = self.pos + while true # sequence + _save1 = self.pos + _ary = [] + _tmp = apply(:_BlockElementParagraphLine) + if _tmp + _ary << @result + while true + _tmp = apply(:_BlockElementParagraphLine) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + c = @result + unless _tmp + self.pos = _save + break + end + @result = begin; paragraph(self, position, c.flatten); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_BlockElementParagraph unless _tmp + return _tmp + end + + # BlockElementParagraphLine = !"//}" !BlankLine !SinglelineComment !BlockElement !Ulist !Olist !Dlist SinglelineContent:c Newline { c } + def _BlockElementParagraphLine + + _save = self.pos + while true # sequence + _save1 = self.pos + _tmp = match_string("//}") + _tmp = _tmp ? nil : true + self.pos = _save1 + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _tmp = apply(:_BlankLine) + _tmp = _tmp ? nil : true + self.pos = _save2 + unless _tmp + self.pos = _save + break + end + _save3 = self.pos + _tmp = apply(:_SinglelineComment) + _tmp = _tmp ? nil : true + self.pos = _save3 + unless _tmp + self.pos = _save + break + end + _save4 = self.pos + _tmp = apply(:_BlockElement) + _tmp = _tmp ? nil : true + self.pos = _save4 + unless _tmp + self.pos = _save + break + end + _save5 = self.pos + _tmp = apply(:_Ulist) + _tmp = _tmp ? nil : true + self.pos = _save5 + unless _tmp + self.pos = _save + break + end + _save6 = self.pos + _tmp = apply(:_Olist) + _tmp = _tmp ? nil : true + self.pos = _save6 + unless _tmp + self.pos = _save + break + end + _save7 = self.pos + _tmp = apply(:_Dlist) + _tmp = _tmp ? nil : true + self.pos = _save7 + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_SinglelineContent) + c = @result + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_Newline) + unless _tmp + self.pos = _save + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_BlockElementParagraphLine unless _tmp + return _tmp + end + + # CodeBlockElementContents = CodeBlockElementContent+:c { c } + def _CodeBlockElementContents + + _save = self.pos + while true # sequence + _save1 = self.pos + _ary = [] + _tmp = apply(:_CodeBlockElementContent) + if _tmp + _ary << @result + while true + _tmp = apply(:_CodeBlockElementContent) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + c = @result + unless _tmp + self.pos = _save + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_CodeBlockElementContents unless _tmp + return _tmp + end + + # CodeBlockElementContent = (SinglelineComment:c { c } | BlankLine:c { ::ReVIEW::TextNode.new(self, position, "\n") } | !"//}" SinglelineContent:c Newline { [c, ::ReVIEW::TextNode.new(self, position, "\n")] }) + def _CodeBlockElementContent + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _tmp = apply(:_SinglelineComment) + c = @result + unless _tmp + self.pos = _save1 + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save2 = self.pos + while true # sequence + _tmp = apply(:_BlankLine) + c = @result + unless _tmp + self.pos = _save2 + break + end + @result = begin; ::ReVIEW::TextNode.new(self, position, "\n") ; end + _tmp = true + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save3 = self.pos + while true # sequence + _save4 = self.pos + _tmp = match_string("//}") + _tmp = _tmp ? nil : true + self.pos = _save4 + unless _tmp + self.pos = _save3 + break + end + _tmp = apply(:_SinglelineContent) + c = @result + unless _tmp + self.pos = _save3 + break + end + _tmp = apply(:_Newline) + unless _tmp + self.pos = _save3 + break + end + @result = begin; [c, ::ReVIEW::TextNode.new(self, position, "\n")] ; end + _tmp = true + unless _tmp + self.pos = _save3 + end + break + end # end sequence + + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_CodeBlockElementContent unless _tmp + return _tmp + end + + # Bullet = "*" + def _Bullet + _tmp = match_string("*") + set_failed_rule :_Bullet unless _tmp + return _tmp + end + + # Enumerator = < /[0-9]+/ > { num = text } "." { num.to_i } + def _Enumerator + + _save = self.pos + while true # sequence + _text_start = self.pos + _tmp = scan(/\A(?-mix:[0-9]+)/) + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save + break + end + @result = begin; num = text ; end + _tmp = true + unless _tmp + self.pos = _save + break + end + _tmp = match_string(".") + unless _tmp + self.pos = _save + break + end + @result = begin; num.to_i ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_Enumerator unless _tmp + return _tmp + end + + # Ulist = Indent+:s Bullet+:b Space+ { @list_stack.push(s) } UlistItemBlock:item { if b.size > 1 then item.level = b.size end } (UlistItem | UlistItemMore | NestedList)*:items &{ s == @list_stack.pop } {ulist(self, position, items.unshift(item))} + def _Ulist + + _save = self.pos + while true # sequence + _save1 = self.pos + _ary = [] + _tmp = apply(:_Indent) + if _tmp + _ary << @result + while true + _tmp = apply(:_Indent) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + s = @result + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _ary = [] + _tmp = apply(:_Bullet) + if _tmp + _ary << @result + while true + _tmp = apply(:_Bullet) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save2 + end + b = @result + unless _tmp + self.pos = _save + break + end + _save3 = self.pos + _tmp = apply(:_Space) + if _tmp + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + else + self.pos = _save3 + end + unless _tmp + self.pos = _save + break + end + @result = begin; @list_stack.push(s) ; end + _tmp = true + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_UlistItemBlock) + item = @result + unless _tmp + self.pos = _save + break + end + @result = begin; if b.size > 1 then item.level = b.size end ; end + _tmp = true + unless _tmp + self.pos = _save + break + end + _ary = [] + while true + + _save5 = self.pos + while true # choice + _tmp = apply(:_UlistItem) + break if _tmp + self.pos = _save5 + _tmp = apply(:_UlistItemMore) + break if _tmp + self.pos = _save5 + _tmp = apply(:_NestedList) + break if _tmp + self.pos = _save5 + break + end # end choice + + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + items = @result + unless _tmp + self.pos = _save + break + end + _save6 = self.pos + _tmp = begin; s == @list_stack.pop ; end + self.pos = _save6 + unless _tmp + self.pos = _save + break + end + @result = begin; ulist(self, position, items.unshift(item)); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_Ulist unless _tmp + return _tmp + end + + # Olist = Indent+:s Enumerator:e Space+ { @list_stack.push(s) } OlistItemBlock:item { item.num = e } (OlistItem | NestedList)*:items &{ s == @list_stack.pop } {olist(self, position, items.unshift(item))} + def _Olist + + _save = self.pos + while true # sequence + _save1 = self.pos + _ary = [] + _tmp = apply(:_Indent) + if _tmp + _ary << @result + while true + _tmp = apply(:_Indent) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + s = @result + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_Enumerator) + e = @result + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _tmp = apply(:_Space) + if _tmp + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + else + self.pos = _save2 + end + unless _tmp + self.pos = _save + break + end + @result = begin; @list_stack.push(s) ; end + _tmp = true + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_OlistItemBlock) + item = @result + unless _tmp + self.pos = _save + break + end + @result = begin; item.num = e ; end + _tmp = true + unless _tmp + self.pos = _save + break + end + _ary = [] + while true + + _save4 = self.pos + while true # choice + _tmp = apply(:_OlistItem) + break if _tmp + self.pos = _save4 + _tmp = apply(:_NestedList) + break if _tmp + self.pos = _save4 + break + end # end choice + + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + items = @result + unless _tmp + self.pos = _save + break + end + _save5 = self.pos + _tmp = begin; s == @list_stack.pop ; end + self.pos = _save5 + unless _tmp + self.pos = _save + break + end + @result = begin; olist(self, position, items.unshift(item)); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_Olist unless _tmp + return _tmp + end + + # UlistItemBlock = ListItemFirstLine:c ListItemLine*:d {ulist_element(self, position, @list_stack.size, d.unshift(c))} + def _UlistItemBlock + + _save = self.pos + while true # sequence + _tmp = apply(:_ListItemFirstLine) + c = @result + unless _tmp + self.pos = _save + break + end + _ary = [] + while true + _tmp = apply(:_ListItemLine) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + d = @result + unless _tmp + self.pos = _save + break + end + @result = begin; ulist_element(self, position, @list_stack.size, d.unshift(c)); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_UlistItemBlock unless _tmp + return _tmp + end + + # OlistItemBlock = ListItemFirstLine:c ListItemLine*:d {olist_element(self, position, 0, d.unshift(c))} + def _OlistItemBlock + + _save = self.pos + while true # sequence + _tmp = apply(:_ListItemFirstLine) + c = @result + unless _tmp + self.pos = _save + break + end + _ary = [] + while true + _tmp = apply(:_ListItemLine) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + d = @result + unless _tmp + self.pos = _save + break + end + @result = begin; olist_element(self, position, 0, d.unshift(c)); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_OlistItemBlock unless _tmp + return _tmp + end + + # ListItemFirstLine = SinglelineContent:c Newline { c } + def _ListItemFirstLine + + _save = self.pos + while true # sequence + _tmp = apply(:_SinglelineContent) + c = @result + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_Newline) + unless _tmp + self.pos = _save + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_ListItemFirstLine unless _tmp + return _tmp + end + + # ListItemLine = Indent+:s !Bullet !Enumerator !Space SinglelineContent:c &{ check_indent(s) } Newline { c } + def _ListItemLine + + _save = self.pos + while true # sequence + _save1 = self.pos + _ary = [] + _tmp = apply(:_Indent) + if _tmp + _ary << @result + while true + _tmp = apply(:_Indent) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + s = @result + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _tmp = apply(:_Bullet) + _tmp = _tmp ? nil : true + self.pos = _save2 + unless _tmp + self.pos = _save + break + end + _save3 = self.pos + _tmp = apply(:_Enumerator) + _tmp = _tmp ? nil : true + self.pos = _save3 + unless _tmp + self.pos = _save + break + end + _save4 = self.pos + _tmp = apply(:_Space) + _tmp = _tmp ? nil : true + self.pos = _save4 + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_SinglelineContent) + c = @result + unless _tmp + self.pos = _save + break + end + _save5 = self.pos + _tmp = begin; check_indent(s) ; end + self.pos = _save5 + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_Newline) + unless _tmp + self.pos = _save + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_ListItemLine unless _tmp + return _tmp + end + + # UlistItemMore = Indent+:s Bullet Bullet+:b Space+ &{ check_indent(s) } UlistItemBlock:item { item.level = b.size+1; item } + def _UlistItemMore + + _save = self.pos + while true # sequence + _save1 = self.pos + _ary = [] + _tmp = apply(:_Indent) + if _tmp + _ary << @result + while true + _tmp = apply(:_Indent) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + s = @result + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_Bullet) + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _ary = [] + _tmp = apply(:_Bullet) + if _tmp + _ary << @result + while true + _tmp = apply(:_Bullet) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save2 + end + b = @result + unless _tmp + self.pos = _save + break + end + _save3 = self.pos + _tmp = apply(:_Space) + if _tmp + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + else + self.pos = _save3 + end + unless _tmp + self.pos = _save + break + end + _save4 = self.pos + _tmp = begin; check_indent(s) ; end + self.pos = _save4 + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_UlistItemBlock) + item = @result + unless _tmp + self.pos = _save + break + end + @result = begin; item.level = b.size+1; item ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_UlistItemMore unless _tmp + return _tmp + end + + # UlistItem = Indent+:s Bullet Space+ &{ check_indent(s) } UlistItemBlock:item { item } + def _UlistItem + + _save = self.pos + while true # sequence + _save1 = self.pos + _ary = [] + _tmp = apply(:_Indent) + if _tmp + _ary << @result + while true + _tmp = apply(:_Indent) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + s = @result + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_Bullet) + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _tmp = apply(:_Space) + if _tmp + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + else + self.pos = _save2 + end + unless _tmp + self.pos = _save + break + end + _save3 = self.pos + _tmp = begin; check_indent(s) ; end + self.pos = _save3 + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_UlistItemBlock) + item = @result + unless _tmp + self.pos = _save + break + end + @result = begin; item ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_UlistItem unless _tmp + return _tmp + end + + # OlistItem = Indent+:s Enumerator:e Space+ &{ check_indent(s) } OlistItemBlock:item { item.num = e; item } + def _OlistItem + + _save = self.pos + while true # sequence + _save1 = self.pos + _ary = [] + _tmp = apply(:_Indent) + if _tmp + _ary << @result + while true + _tmp = apply(:_Indent) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + s = @result + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_Enumerator) + e = @result + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _tmp = apply(:_Space) + if _tmp + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + else + self.pos = _save2 + end + unless _tmp + self.pos = _save + break + end + _save3 = self.pos + _tmp = begin; check_indent(s) ; end + self.pos = _save3 + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_OlistItemBlock) + item = @result + unless _tmp + self.pos = _save + break + end + @result = begin; item.num = e; item ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_OlistItem unless _tmp + return _tmp + end + + # NestedList = (NestedUlist | NestedOlist) + def _NestedList + + _save = self.pos + while true # choice + _tmp = apply(:_NestedUlist) + break if _tmp + self.pos = _save + _tmp = apply(:_NestedOlist) + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_NestedList unless _tmp + return _tmp + end + + # NestedUlist = Indent+:s Bullet Space+ &{ check_nested_indent(s) } { @list_stack.push(s) } UlistItemBlock:item (UlistItem | NestedList)*:items &{ s == @list_stack.pop } {ulist(self, position, items.unshift(item))} + def _NestedUlist + + _save = self.pos + while true # sequence + _save1 = self.pos + _ary = [] + _tmp = apply(:_Indent) + if _tmp + _ary << @result + while true + _tmp = apply(:_Indent) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + s = @result + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_Bullet) + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _tmp = apply(:_Space) + if _tmp + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + else + self.pos = _save2 + end + unless _tmp + self.pos = _save + break + end + _save3 = self.pos + _tmp = begin; check_nested_indent(s) ; end + self.pos = _save3 + unless _tmp + self.pos = _save + break + end + @result = begin; @list_stack.push(s) ; end + _tmp = true + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_UlistItemBlock) + item = @result + unless _tmp + self.pos = _save + break + end + _ary = [] + while true + + _save5 = self.pos + while true # choice + _tmp = apply(:_UlistItem) + break if _tmp + self.pos = _save5 + _tmp = apply(:_NestedList) + break if _tmp + self.pos = _save5 + break + end # end choice + + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + items = @result + unless _tmp + self.pos = _save + break + end + _save6 = self.pos + _tmp = begin; s == @list_stack.pop ; end + self.pos = _save6 + unless _tmp + self.pos = _save + break + end + @result = begin; ulist(self, position, items.unshift(item)); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_NestedUlist unless _tmp + return _tmp + end + + # NestedOlist = Indent+:s Enumerator:e Space+ &{ check_nested_indent(s) } { @list_stack.push(s) } OlistItemBlock:item { item.num = e } (OlistItem | NestedList)*:items &{ s == @list_stack.pop } {olist(self, position, items.unshift(item))} + def _NestedOlist + + _save = self.pos + while true # sequence + _save1 = self.pos + _ary = [] + _tmp = apply(:_Indent) + if _tmp + _ary << @result + while true + _tmp = apply(:_Indent) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + s = @result + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_Enumerator) + e = @result + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _tmp = apply(:_Space) + if _tmp + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + else + self.pos = _save2 + end + unless _tmp + self.pos = _save + break + end + _save3 = self.pos + _tmp = begin; check_nested_indent(s) ; end + self.pos = _save3 + unless _tmp + self.pos = _save + break + end + @result = begin; @list_stack.push(s) ; end + _tmp = true + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_OlistItemBlock) + item = @result + unless _tmp + self.pos = _save + break + end + @result = begin; item.num = e ; end + _tmp = true + unless _tmp + self.pos = _save + break + end + _ary = [] + while true + + _save5 = self.pos + while true # choice + _tmp = apply(:_OlistItem) + break if _tmp + self.pos = _save5 + _tmp = apply(:_NestedList) + break if _tmp + self.pos = _save5 + break + end # end choice + + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + items = @result + unless _tmp + self.pos = _save + break + end + _save6 = self.pos + _tmp = begin; s == @list_stack.pop ; end + self.pos = _save6 + unless _tmp + self.pos = _save + break + end + @result = begin; olist(self, position, items.unshift(item)); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_NestedOlist unless _tmp + return _tmp + end + + # Dlist = (DlistElement | SinglelineComment)+:content {dlist(self, position, content)} + def _Dlist + + _save = self.pos + while true # sequence + _save1 = self.pos + _ary = [] + + _save2 = self.pos + while true # choice + _tmp = apply(:_DlistElement) + break if _tmp + self.pos = _save2 + _tmp = apply(:_SinglelineComment) + break if _tmp + self.pos = _save2 + break + end # end choice + + if _tmp + _ary << @result + while true + + _save3 = self.pos + while true # choice + _tmp = apply(:_DlistElement) + break if _tmp + self.pos = _save3 + _tmp = apply(:_SinglelineComment) + break if _tmp + self.pos = _save3 + break + end # end choice + + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + content = @result + unless _tmp + self.pos = _save + break + end + @result = begin; dlist(self, position, content); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_Dlist unless _tmp + return _tmp + end + + # DlistElement = Indent* ":" Space+ SinglelineContent:text Newline DlistElementContent+:content {dlist_element(self, position, text, content)} + def _DlistElement + + _save = self.pos + while true # sequence + while true + _tmp = apply(:_Indent) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save + break + end + _tmp = match_string(":") + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _tmp = apply(:_Space) + if _tmp + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + else + self.pos = _save2 + end + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_SinglelineContent) + text = @result + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_Newline) + unless _tmp + self.pos = _save + break + end + _save3 = self.pos + _ary = [] + _tmp = apply(:_DlistElementContent) + if _tmp + _ary << @result + while true + _tmp = apply(:_DlistElementContent) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save3 + end + content = @result + unless _tmp + self.pos = _save + break + end + @result = begin; dlist_element(self, position, text, content); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_DlistElement unless _tmp + return _tmp + end + + # DlistElementContent = (SinglelineComment:c { c } | Space+ SinglelineContent:c Newline { c }) + def _DlistElementContent + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _tmp = apply(:_SinglelineComment) + c = @result + unless _tmp + self.pos = _save1 + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save2 = self.pos + while true # sequence + _save3 = self.pos + _tmp = apply(:_Space) + if _tmp + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + else + self.pos = _save3 + end + unless _tmp + self.pos = _save2 + break + end + _tmp = apply(:_SinglelineContent) + c = @result + unless _tmp + self.pos = _save2 + break + end + _tmp = apply(:_Newline) + unless _tmp + self.pos = _save2 + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_DlistElementContent unless _tmp + return _tmp + end + + # SinglelineContent = Inline+:c {singleline_content(self, position, c)} + def _SinglelineContent + + _save = self.pos + while true # sequence + _save1 = self.pos + _ary = [] + _tmp = apply(:_Inline) + if _tmp + _ary << @result + while true + _tmp = apply(:_Inline) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + c = @result + unless _tmp + self.pos = _save + break + end + @result = begin; singleline_content(self, position, c); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_SinglelineContent unless _tmp + return _tmp + end + + # Inline = (InlineElement | NonInlineElement) + def _Inline + + _save = self.pos + while true # choice + _tmp = apply(:_InlineElement) + break if _tmp + self.pos = _save + _tmp = apply(:_NonInlineElement) + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_Inline unless _tmp + return _tmp + end + + # NonInlineElement = !InlineElement < NonNewline > {text(self, position, text)} + def _NonInlineElement + + _save = self.pos + while true # sequence + _save1 = self.pos + _tmp = apply(:_InlineElement) + _tmp = _tmp ? nil : true + self.pos = _save1 + unless _tmp + self.pos = _save + break + end + _text_start = self.pos + _tmp = apply(:_NonNewline) + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save + break + end + @result = begin; text(self, position, text); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_NonInlineElement unless _tmp + return _tmp + end + + # InlineElement = (RawInlineElement:c { c } | !RawInlineElement "@<" InlineElementSymbol:symbol ">" "{" InlineElementContents?:contents "}" {inline_element(self, position, symbol,contents)} | !RawInlineElement "@<" ComplexInlineElementSymbol:symbol ">" "{" ComplexInlineElementContents?:contents "}" {complex_inline_element(self, position, symbol,contents)}) + def _InlineElement + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _tmp = apply(:_RawInlineElement) + c = @result + unless _tmp + self.pos = _save1 + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save2 = self.pos + while true # sequence + _save3 = self.pos + _tmp = apply(:_RawInlineElement) + _tmp = _tmp ? nil : true + self.pos = _save3 + unless _tmp + self.pos = _save2 + break + end + _tmp = match_string("@<") + unless _tmp + self.pos = _save2 + break + end + _tmp = apply(:_InlineElementSymbol) + symbol = @result + unless _tmp + self.pos = _save2 + break + end + _tmp = match_string(">") + unless _tmp + self.pos = _save2 + break + end + _tmp = match_string("{") + unless _tmp + self.pos = _save2 + break + end + _save4 = self.pos + _tmp = apply(:_InlineElementContents) + @result = nil unless _tmp + unless _tmp + _tmp = true + self.pos = _save4 + end + contents = @result + unless _tmp + self.pos = _save2 + break + end + _tmp = match_string("}") + unless _tmp + self.pos = _save2 + break + end + @result = begin; inline_element(self, position, symbol,contents); end + _tmp = true + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save5 = self.pos + while true # sequence + _save6 = self.pos + _tmp = apply(:_RawInlineElement) + _tmp = _tmp ? nil : true + self.pos = _save6 + unless _tmp + self.pos = _save5 + break + end + _tmp = match_string("@<") + unless _tmp + self.pos = _save5 + break + end + _tmp = apply(:_ComplexInlineElementSymbol) + symbol = @result + unless _tmp + self.pos = _save5 + break + end + _tmp = match_string(">") + unless _tmp + self.pos = _save5 + break + end + _tmp = match_string("{") + unless _tmp + self.pos = _save5 + break + end + _save7 = self.pos + _tmp = apply(:_ComplexInlineElementContents) + @result = nil unless _tmp + unless _tmp + _tmp = true + self.pos = _save7 + end + contents = @result + unless _tmp + self.pos = _save5 + break + end + _tmp = match_string("}") + unless _tmp + self.pos = _save5 + break + end + @result = begin; complex_inline_element(self, position, symbol,contents); end + _tmp = true + unless _tmp + self.pos = _save5 + end + break + end # end sequence + + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_InlineElement unless _tmp + return _tmp + end + + # RawInlineElement = "@{" RawBlockBuilderSelect?:builders RawInlineElementContent+:c "}" {raw(self, builders, position, c)} + def _RawInlineElement + + _save = self.pos + while true # sequence + _tmp = match_string("@{") + unless _tmp + self.pos = _save + break + end + _save1 = self.pos + _tmp = apply(:_RawBlockBuilderSelect) + @result = nil unless _tmp + unless _tmp + _tmp = true + self.pos = _save1 + end + builders = @result + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _ary = [] + _tmp = apply(:_RawInlineElementContent) + if _tmp + _ary << @result + while true + _tmp = apply(:_RawInlineElementContent) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save2 + end + c = @result + unless _tmp + self.pos = _save + break + end + _tmp = match_string("}") + unless _tmp + self.pos = _save + break + end + @result = begin; raw(self, builders, position, c); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_RawInlineElement unless _tmp + return _tmp + end + + # RawInlineElementContent = ("\\}" { "}" } | < /[^\r\n\}]/ > { text }) + def _RawInlineElementContent + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _tmp = match_string("\\}") + unless _tmp + self.pos = _save1 + break + end + @result = begin; "}" ; end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save2 = self.pos + while true # sequence + _text_start = self.pos + _tmp = scan(/\A(?-mix:[^\r\n\}])/) + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save2 + break + end + @result = begin; text ; end + _tmp = true + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_RawInlineElementContent unless _tmp + return _tmp + end + + # InlineElementSymbol = < AlphanumericAscii+ >:s &{ check_inline_element_symbol(text) } { text } + def _InlineElementSymbol + + _save = self.pos + while true # sequence + _text_start = self.pos + _save1 = self.pos + _tmp = apply(:_AlphanumericAscii) + if _tmp + while true + _tmp = apply(:_AlphanumericAscii) + break unless _tmp + end + _tmp = true + else + self.pos = _save1 + end + if _tmp + text = get_text(_text_start) + end + s = @result + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _tmp = begin; check_inline_element_symbol(text) ; end + self.pos = _save2 + unless _tmp + self.pos = _save + break + end + @result = begin; text ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_InlineElementSymbol unless _tmp + return _tmp + end + + # InlineElementContents = !"}" InlineElementContentsSub:c { c } + def _InlineElementContents + + _save = self.pos + while true # sequence + _save1 = self.pos + _tmp = match_string("}") + _tmp = _tmp ? nil : true + self.pos = _save1 + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_InlineElementContentsSub) + c = @result + unless _tmp + self.pos = _save + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_InlineElementContents unless _tmp + return _tmp + end + + # InlineElementContentsSub = !"}" Space* InlineElementContent:c1 Space* { [c1] } + def _InlineElementContentsSub + + _save = self.pos + while true # sequence + _save1 = self.pos + _tmp = match_string("}") + _tmp = _tmp ? nil : true + self.pos = _save1 + unless _tmp + self.pos = _save + break + end + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_InlineElementContent) + c1 = @result + unless _tmp + self.pos = _save + break + end + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save + break + end + @result = begin; [c1] ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_InlineElementContentsSub unless _tmp + return _tmp + end + + # ComplexInlineElementSymbol = < AlphanumericAscii+ > &{ check_complex_inline_element_symbol(text) } { text } + def _ComplexInlineElementSymbol + + _save = self.pos + while true # sequence + _text_start = self.pos + _save1 = self.pos + _tmp = apply(:_AlphanumericAscii) + if _tmp + while true + _tmp = apply(:_AlphanumericAscii) + break unless _tmp + end + _tmp = true + else + self.pos = _save1 + end + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _tmp = begin; check_complex_inline_element_symbol(text) ; end + self.pos = _save2 + unless _tmp + self.pos = _save + break + end + @result = begin; text ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_ComplexInlineElementSymbol unless _tmp + return _tmp + end + + # ComplexInlineElementContents = !"}" ComplexInlineElementContentsSub:c { c } + def _ComplexInlineElementContents + + _save = self.pos + while true # sequence + _save1 = self.pos + _tmp = match_string("}") + _tmp = _tmp ? nil : true + self.pos = _save1 + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_ComplexInlineElementContentsSub) + c = @result + unless _tmp + self.pos = _save + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_ComplexInlineElementContents unless _tmp + return _tmp + end + + # ComplexInlineElementContentsSub = !"}" (Space* InlineElementContent:c1 Space* "," ComplexInlineElementContentsSub:c2 { [c1]+c2 } | Space* InlineElementContent:c1 Space* { [c1] }) + def _ComplexInlineElementContentsSub + + _save = self.pos + while true # sequence + _save1 = self.pos + _tmp = match_string("}") + _tmp = _tmp ? nil : true + self.pos = _save1 + unless _tmp + self.pos = _save + break + end + + _save2 = self.pos + while true # choice + + _save3 = self.pos + while true # sequence + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save3 + break + end + _tmp = apply(:_InlineElementContent) + c1 = @result + unless _tmp + self.pos = _save3 + break + end + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save3 + break + end + _tmp = match_string(",") + unless _tmp + self.pos = _save3 + break + end + _tmp = apply(:_ComplexInlineElementContentsSub) + c2 = @result + unless _tmp + self.pos = _save3 + break + end + @result = begin; [c1]+c2 ; end + _tmp = true + unless _tmp + self.pos = _save3 + end + break + end # end sequence + + break if _tmp + self.pos = _save2 + + _save6 = self.pos + while true # sequence + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save6 + break + end + _tmp = apply(:_InlineElementContent) + c1 = @result + unless _tmp + self.pos = _save6 + break + end + while true + _tmp = apply(:_Space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save6 + break + end + @result = begin; [c1] ; end + _tmp = true + unless _tmp + self.pos = _save6 + end + break + end # end sequence + + break if _tmp + self.pos = _save2 + break + end # end choice + + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_ComplexInlineElementContentsSub unless _tmp + return _tmp + end + + # InlineElementContent = InlineElementContentSub+:d { d } + def _InlineElementContent + + _save = self.pos + while true # sequence + _save1 = self.pos + _ary = [] + _tmp = apply(:_InlineElementContentSub) + if _tmp + _ary << @result + while true + _tmp = apply(:_InlineElementContentSub) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + d = @result + unless _tmp + self.pos = _save + break + end + @result = begin; d ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_InlineElementContent unless _tmp + return _tmp + end + + # InlineElementContentSub = (InlineElement:c { c } | !InlineElement QuotedInlineText:content {inline_element_content(self, position, content)} | !InlineElement InlineElementContentText+:content {inline_element_content(self, position, content)}) + def _InlineElementContentSub + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _tmp = apply(:_InlineElement) + c = @result + unless _tmp + self.pos = _save1 + break + end + @result = begin; c ; end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save2 = self.pos + while true # sequence + _save3 = self.pos + _tmp = apply(:_InlineElement) + _tmp = _tmp ? nil : true + self.pos = _save3 + unless _tmp + self.pos = _save2 + break + end + _tmp = apply(:_QuotedInlineText) + content = @result + unless _tmp + self.pos = _save2 + break + end + @result = begin; inline_element_content(self, position, content); end + _tmp = true + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save4 = self.pos + while true # sequence + _save5 = self.pos + _tmp = apply(:_InlineElement) + _tmp = _tmp ? nil : true + self.pos = _save5 + unless _tmp + self.pos = _save4 + break + end + _save6 = self.pos + _ary = [] + _tmp = apply(:_InlineElementContentText) + if _tmp + _ary << @result + while true + _tmp = apply(:_InlineElementContentText) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save6 + end + content = @result + unless _tmp + self.pos = _save4 + break + end + @result = begin; inline_element_content(self, position, content); end + _tmp = true + unless _tmp + self.pos = _save4 + end + break + end # end sequence + + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_InlineElementContentSub unless _tmp + return _tmp + end + + # QuotedInlineText = "\"" ("\\\"" { "\"" } | "\\\\" { "\\" } | < /[^"\r\n\\]/ > { text })+:str "\"" {text(self, position, str.join(""))} + def _QuotedInlineText + + _save = self.pos + while true # sequence + _tmp = match_string("\"") + unless _tmp + self.pos = _save + break + end + _save1 = self.pos + _ary = [] + + _save2 = self.pos + while true # choice + + _save3 = self.pos + while true # sequence + _tmp = match_string("\\\"") + unless _tmp + self.pos = _save3 + break + end + @result = begin; "\"" ; end + _tmp = true + unless _tmp + self.pos = _save3 + end + break + end # end sequence + + break if _tmp + self.pos = _save2 + + _save4 = self.pos + while true # sequence + _tmp = match_string("\\\\") + unless _tmp + self.pos = _save4 + break + end + @result = begin; "\\" ; end + _tmp = true + unless _tmp + self.pos = _save4 + end + break + end # end sequence + + break if _tmp + self.pos = _save2 + + _save5 = self.pos + while true # sequence + _text_start = self.pos + _tmp = scan(/\A(?-mix:[^"\r\n\\])/) + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save5 + break + end + @result = begin; text ; end + _tmp = true + unless _tmp + self.pos = _save5 + end + break + end # end sequence + + break if _tmp + self.pos = _save2 + break + end # end choice + + if _tmp + _ary << @result + while true + + _save6 = self.pos + while true # choice + + _save7 = self.pos + while true # sequence + _tmp = match_string("\\\"") + unless _tmp + self.pos = _save7 + break + end + @result = begin; "\"" ; end + _tmp = true + unless _tmp + self.pos = _save7 + end + break + end # end sequence + + break if _tmp + self.pos = _save6 + + _save8 = self.pos + while true # sequence + _tmp = match_string("\\\\") + unless _tmp + self.pos = _save8 + break + end + @result = begin; "\\" ; end + _tmp = true + unless _tmp + self.pos = _save8 + end + break + end # end sequence + + break if _tmp + self.pos = _save6 + + _save9 = self.pos + while true # sequence + _text_start = self.pos + _tmp = scan(/\A(?-mix:[^"\r\n\\])/) + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save9 + break + end + @result = begin; text ; end + _tmp = true + unless _tmp + self.pos = _save9 + end + break + end # end sequence + + break if _tmp + self.pos = _save6 + break + end # end choice + + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + str = @result + unless _tmp + self.pos = _save + break + end + _tmp = match_string("\"") + unless _tmp + self.pos = _save + break + end + @result = begin; text(self, position, str.join("")); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_QuotedInlineText unless _tmp + return _tmp + end + + # InlineElementContentText = ("\\}" {text(self, position, "}")} | "\\," {text(self, position, ",")} | "\\\\" {text(self, position, "\\" )} | "\\" {text(self, position, "\\" )} | !InlineElement < /[^\r\n\\},]/ > {text(self, position, text)}) + def _InlineElementContentText + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _tmp = match_string("\\}") + unless _tmp + self.pos = _save1 + break + end + @result = begin; text(self, position, "}"); end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save2 = self.pos + while true # sequence + _tmp = match_string("\\,") + unless _tmp + self.pos = _save2 + break + end + @result = begin; text(self, position, ","); end + _tmp = true + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save3 = self.pos + while true # sequence + _tmp = match_string("\\\\") + unless _tmp + self.pos = _save3 + break + end + @result = begin; text(self, position, "\\" ); end + _tmp = true + unless _tmp + self.pos = _save3 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save4 = self.pos + while true # sequence + _tmp = match_string("\\") + unless _tmp + self.pos = _save4 + break + end + @result = begin; text(self, position, "\\" ); end + _tmp = true + unless _tmp + self.pos = _save4 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save5 = self.pos + while true # sequence + _save6 = self.pos + _tmp = apply(:_InlineElement) + _tmp = _tmp ? nil : true + self.pos = _save6 + unless _tmp + self.pos = _save5 + break + end + _text_start = self.pos + _tmp = scan(/\A(?-mix:[^\r\n\\},])/) + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save5 + break + end + @result = begin; text(self, position, text); end + _tmp = true + unless _tmp + self.pos = _save5 + end + break + end # end sequence + + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_InlineElementContentText unless _tmp + return _tmp + end + + # NonNewline = /[^\r\n]/ + def _NonNewline + _tmp = scan(/\A(?-mix:[^\r\n])/) + set_failed_rule :_NonNewline unless _tmp + return _tmp + end + + # Space = /[ \t]/ + def _Space + _tmp = scan(/\A(?-mix:[ \t])/) + set_failed_rule :_Space unless _tmp + return _tmp + end + + # Indent = " " + def _Indent + _tmp = match_string(" ") + set_failed_rule :_Indent unless _tmp + return _tmp + end + + # EOL = (Newline | EOF) + def _EOL + + _save = self.pos + while true # choice + _tmp = apply(:_Newline) + break if _tmp + self.pos = _save + _tmp = apply(:_EOF) + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_EOL unless _tmp + return _tmp + end + + # EOF = !. + def _EOF + _save = self.pos + _tmp = get_byte + _tmp = _tmp ? nil : true + self.pos = _save + set_failed_rule :_EOF unless _tmp + return _tmp + end + + # ElementName = < LowerAlphabetAscii+ > { text } + def _ElementName + + _save = self.pos + while true # sequence + _text_start = self.pos + _save1 = self.pos + _tmp = apply(:_LowerAlphabetAscii) + if _tmp + while true + _tmp = apply(:_LowerAlphabetAscii) + break unless _tmp + end + _tmp = true + else + self.pos = _save1 + end + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save + break + end + @result = begin; text ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_ElementName unless _tmp + return _tmp + end + + # AlphanumericAscii = /[A-Za-z0-9]/ + def _AlphanumericAscii + _tmp = scan(/\A(?-mix:[A-Za-z0-9])/) + set_failed_rule :_AlphanumericAscii unless _tmp + return _tmp + end + + # LowerAlphabetAscii = /[a-z]/ + def _LowerAlphabetAscii + _tmp = scan(/\A(?-mix:[a-z])/) + set_failed_rule :_LowerAlphabetAscii unless _tmp + return _tmp + end + + # Digit = /[0-9]/ + def _Digit + _tmp = scan(/\A(?-mix:[0-9])/) + set_failed_rule :_Digit unless _tmp + return _tmp + end + + # BOM = "uFEFF" + def _BOM + _tmp = match_string("uFEFF") + set_failed_rule :_BOM unless _tmp + return _tmp + end + + # Newline = /\n|\r\n?|\p{Zl}|\p{Zp}/ {newline(self, position, "\n")} + def _Newline + + _save = self.pos + while true # sequence + _tmp = scan(/\A(?-mix:\n|\r\n?|\p{Zl}|\p{Zp})/) + unless _tmp + self.pos = _save + break + end + @result = begin; newline(self, position, "\n"); end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + set_failed_rule :_Newline unless _tmp + return _tmp end -end # module ReVIEW + Rules = {} + Rules[:_root] = rule_info("root", "Start") + Rules[:_Start] = rule_info("Start", "&. { @list_stack = Array.new } Document:c { @strategy.ast = c }") + Rules[:_Document] = rule_info("Document", "BOM? Block*:c {document(self, position, c)}") + Rules[:_Block] = rule_info("Block", "BlankLine*:c { c } (SinglelineComment:c | Headline:c | BlockElement:c | Ulist:c | Olist:c | Dlist:c | Paragraph:c) { c }") + Rules[:_BlankLine] = rule_info("BlankLine", "Newline") + Rules[:_SinglelineComment] = rule_info("SinglelineComment", "\"\#@\" < NonNewline+ > EOL {singleline_comment(self, position, text)}") + Rules[:_Headline] = rule_info("Headline", "HeadlinePrefix:level BracketArg?:cmd BraceArg?:label Space* SinglelineContent?:caption EOL {headline(self, position, level, cmd, label, caption)}") + Rules[:_HeadlinePrefix] = rule_info("HeadlinePrefix", "< /={1,5}/ > { text.length }") + Rules[:_Paragraph] = rule_info("Paragraph", "ParagraphLine+:c {paragraph(self, position, c.flatten)}") + Rules[:_ParagraphLine] = rule_info("ParagraphLine", "!Headline !SinglelineComment !BlockElement !Ulist !Olist !Dlist SinglelineContent:c Newline { c }") + Rules[:_BlockElement] = rule_info("BlockElement", "(\"//raw[\" RawBlockBuilderSelect?:b RawBlockElementArg*:r1 \"]\" Space* EOL {raw(self, b, position, r1)} | !\"//raw\" \"//\" ElementName:symbol &{ syntax = syntax_descriptor(symbol); syntax && syntax.code_block? } BracketArg*:args \"{\" Space* Newline CodeBlockElementContents:contents \"//}\" Space* EOL {code_block_element(self, position, symbol, args, contents)} | !\"//raw\" \"//\" ElementName:symbol BracketArg*:args \"{\" Space* Newline BlockElementContents:contents \"//}\" Space* EOL {block_element(self, position, symbol, args, contents)} | !\"//raw\" \"//\" ElementName:symbol BracketArg*:args Space* EOL {block_element(self, position, symbol, args, nil)})") + Rules[:_RawBlockBuilderSelect] = rule_info("RawBlockBuilderSelect", "\"|\" Space* RawBlockBuilderSelectSub:c Space* \"|\" { c }") + Rules[:_RawBlockBuilderSelectSub] = rule_info("RawBlockBuilderSelectSub", "(< AlphanumericAscii+ >:c1 Space* \",\" Space* RawBlockBuilderSelectSub:c2 { [text] + c2 } | < AlphanumericAscii+ >:c1 { [text] })") + Rules[:_RawBlockElementArg] = rule_info("RawBlockElementArg", "!\"]\" (\"\\\\]\" { \"]\" } | \"\\\\n\" { \"\\n\" } | < NonNewline > { text })") + Rules[:_BracketArg] = rule_info("BracketArg", "\"[\" BracketArgInline*:content \"]\" {bracket_arg(self, position, content)}") + Rules[:_BracketArgInline] = rule_info("BracketArgInline", "(InlineElement:c { c } | \"\\\\]\" {text(self, position, \"]\")} | \"\\\\\\\\\" {text(self, position, \"\\\\\")} | < /[^\\r\\n\\]]/ > {text(self, position, text)})") + Rules[:_BraceArg] = rule_info("BraceArg", "\"{\" < /([^\\r\\n}\\\\]|\\\\[^\\r\\n])*/ > \"}\" { text }") + Rules[:_BlockElementContents] = rule_info("BlockElementContents", "BlockElementContent*:c { c }") + Rules[:_BlockElementContent] = rule_info("BlockElementContent", "(SinglelineComment:c { c } | BlockElement:c { c } | Ulist:c | Dlist:c | Olist:c | BlankLine:c { c } | BlockElementParagraph:c { c })") + Rules[:_BlockElementParagraph] = rule_info("BlockElementParagraph", "BlockElementParagraphLine+:c {paragraph(self, position, c.flatten)}") + Rules[:_BlockElementParagraphLine] = rule_info("BlockElementParagraphLine", "!\"//}\" !BlankLine !SinglelineComment !BlockElement !Ulist !Olist !Dlist SinglelineContent:c Newline { c }") + Rules[:_CodeBlockElementContents] = rule_info("CodeBlockElementContents", "CodeBlockElementContent+:c { c }") + Rules[:_CodeBlockElementContent] = rule_info("CodeBlockElementContent", "(SinglelineComment:c { c } | BlankLine:c { ::ReVIEW::TextNode.new(self, position, \"\\n\") } | !\"//}\" SinglelineContent:c Newline { [c, ::ReVIEW::TextNode.new(self, position, \"\\n\")] })") + Rules[:_Bullet] = rule_info("Bullet", "\"*\"") + Rules[:_Enumerator] = rule_info("Enumerator", "< /[0-9]+/ > { num = text } \".\" { num.to_i }") + Rules[:_Ulist] = rule_info("Ulist", "Indent+:s Bullet+:b Space+ { @list_stack.push(s) } UlistItemBlock:item { if b.size > 1 then item.level = b.size end } (UlistItem | UlistItemMore | NestedList)*:items &{ s == @list_stack.pop } {ulist(self, position, items.unshift(item))}") + Rules[:_Olist] = rule_info("Olist", "Indent+:s Enumerator:e Space+ { @list_stack.push(s) } OlistItemBlock:item { item.num = e } (OlistItem | NestedList)*:items &{ s == @list_stack.pop } {olist(self, position, items.unshift(item))}") + Rules[:_UlistItemBlock] = rule_info("UlistItemBlock", "ListItemFirstLine:c ListItemLine*:d {ulist_element(self, position, @list_stack.size, d.unshift(c))}") + Rules[:_OlistItemBlock] = rule_info("OlistItemBlock", "ListItemFirstLine:c ListItemLine*:d {olist_element(self, position, 0, d.unshift(c))}") + Rules[:_ListItemFirstLine] = rule_info("ListItemFirstLine", "SinglelineContent:c Newline { c }") + Rules[:_ListItemLine] = rule_info("ListItemLine", "Indent+:s !Bullet !Enumerator !Space SinglelineContent:c &{ check_indent(s) } Newline { c }") + Rules[:_UlistItemMore] = rule_info("UlistItemMore", "Indent+:s Bullet Bullet+:b Space+ &{ check_indent(s) } UlistItemBlock:item { item.level = b.size+1; item }") + Rules[:_UlistItem] = rule_info("UlistItem", "Indent+:s Bullet Space+ &{ check_indent(s) } UlistItemBlock:item { item }") + Rules[:_OlistItem] = rule_info("OlistItem", "Indent+:s Enumerator:e Space+ &{ check_indent(s) } OlistItemBlock:item { item.num = e; item }") + Rules[:_NestedList] = rule_info("NestedList", "(NestedUlist | NestedOlist)") + Rules[:_NestedUlist] = rule_info("NestedUlist", "Indent+:s Bullet Space+ &{ check_nested_indent(s) } { @list_stack.push(s) } UlistItemBlock:item (UlistItem | NestedList)*:items &{ s == @list_stack.pop } {ulist(self, position, items.unshift(item))}") + Rules[:_NestedOlist] = rule_info("NestedOlist", "Indent+:s Enumerator:e Space+ &{ check_nested_indent(s) } { @list_stack.push(s) } OlistItemBlock:item { item.num = e } (OlistItem | NestedList)*:items &{ s == @list_stack.pop } {olist(self, position, items.unshift(item))}") + Rules[:_Dlist] = rule_info("Dlist", "(DlistElement | SinglelineComment)+:content {dlist(self, position, content)}") + Rules[:_DlistElement] = rule_info("DlistElement", "Indent* \":\" Space+ SinglelineContent:text Newline DlistElementContent+:content {dlist_element(self, position, text, content)}") + Rules[:_DlistElementContent] = rule_info("DlistElementContent", "(SinglelineComment:c { c } | Space+ SinglelineContent:c Newline { c })") + Rules[:_SinglelineContent] = rule_info("SinglelineContent", "Inline+:c {singleline_content(self, position, c)}") + Rules[:_Inline] = rule_info("Inline", "(InlineElement | NonInlineElement)") + Rules[:_NonInlineElement] = rule_info("NonInlineElement", "!InlineElement < NonNewline > {text(self, position, text)}") + Rules[:_InlineElement] = rule_info("InlineElement", "(RawInlineElement:c { c } | !RawInlineElement \"@<\" InlineElementSymbol:symbol \">\" \"{\" InlineElementContents?:contents \"}\" {inline_element(self, position, symbol,contents)} | !RawInlineElement \"@<\" ComplexInlineElementSymbol:symbol \">\" \"{\" ComplexInlineElementContents?:contents \"}\" {complex_inline_element(self, position, symbol,contents)})") + Rules[:_RawInlineElement] = rule_info("RawInlineElement", "\"@{\" RawBlockBuilderSelect?:builders RawInlineElementContent+:c \"}\" {raw(self, builders, position, c)}") + Rules[:_RawInlineElementContent] = rule_info("RawInlineElementContent", "(\"\\\\}\" { \"}\" } | < /[^\\r\\n\\}]/ > { text })") + Rules[:_InlineElementSymbol] = rule_info("InlineElementSymbol", "< AlphanumericAscii+ >:s &{ check_inline_element_symbol(text) } { text }") + Rules[:_InlineElementContents] = rule_info("InlineElementContents", "!\"}\" InlineElementContentsSub:c { c }") + Rules[:_InlineElementContentsSub] = rule_info("InlineElementContentsSub", "!\"}\" Space* InlineElementContent:c1 Space* { [c1] }") + Rules[:_ComplexInlineElementSymbol] = rule_info("ComplexInlineElementSymbol", "< AlphanumericAscii+ > &{ check_complex_inline_element_symbol(text) } { text }") + Rules[:_ComplexInlineElementContents] = rule_info("ComplexInlineElementContents", "!\"}\" ComplexInlineElementContentsSub:c { c }") + Rules[:_ComplexInlineElementContentsSub] = rule_info("ComplexInlineElementContentsSub", "!\"}\" (Space* InlineElementContent:c1 Space* \",\" ComplexInlineElementContentsSub:c2 { [c1]+c2 } | Space* InlineElementContent:c1 Space* { [c1] })") + Rules[:_InlineElementContent] = rule_info("InlineElementContent", "InlineElementContentSub+:d { d }") + Rules[:_InlineElementContentSub] = rule_info("InlineElementContentSub", "(InlineElement:c { c } | !InlineElement QuotedInlineText:content {inline_element_content(self, position, content)} | !InlineElement InlineElementContentText+:content {inline_element_content(self, position, content)})") + Rules[:_QuotedInlineText] = rule_info("QuotedInlineText", "\"\\\"\" (\"\\\\\\\"\" { \"\\\"\" } | \"\\\\\\\\\" { \"\\\\\" } | < /[^\"\\r\\n\\\\]/ > { text })+:str \"\\\"\" {text(self, position, str.join(\"\"))}") + Rules[:_InlineElementContentText] = rule_info("InlineElementContentText", "(\"\\\\}\" {text(self, position, \"}\")} | \"\\\\,\" {text(self, position, \",\")} | \"\\\\\\\\\" {text(self, position, \"\\\\\" )} | \"\\\\\" {text(self, position, \"\\\\\" )} | !InlineElement < /[^\\r\\n\\\\},]/ > {text(self, position, text)})") + Rules[:_NonNewline] = rule_info("NonNewline", "/[^\\r\\n]/") + Rules[:_Space] = rule_info("Space", "/[ \\t]/") + Rules[:_Indent] = rule_info("Indent", "\" \"") + Rules[:_EOL] = rule_info("EOL", "(Newline | EOF)") + Rules[:_EOF] = rule_info("EOF", "!.") + Rules[:_ElementName] = rule_info("ElementName", "< LowerAlphabetAscii+ > { text }") + Rules[:_AlphanumericAscii] = rule_info("AlphanumericAscii", "/[A-Za-z0-9]/") + Rules[:_LowerAlphabetAscii] = rule_info("LowerAlphabetAscii", "/[a-z]/") + Rules[:_Digit] = rule_info("Digit", "/[0-9]/") + Rules[:_BOM] = rule_info("BOM", "\"uFEFF\"") + Rules[:_Newline] = rule_info("Newline", "/\\n|\\r\\n?|\\p{Zl}|\\p{Zp}/ {newline(self, position, \"\\n\")}") + # :startdoc: +end diff --git a/lib/review/extentions.rb b/lib/review/extentions.rb index 5293a74b9..6815193c0 100644 --- a/lib/review/extentions.rb +++ b/lib/review/extentions.rb @@ -1,4 +1,5 @@ require 'review/extentions/object' require 'review/extentions/string' +require 'review/extentions/array' require 'review/extentions/hash' diff --git a/lib/review/extentions/array.rb b/lib/review/extentions/array.rb new file mode 100644 index 000000000..446bae0a8 --- /dev/null +++ b/lib/review/extentions/array.rb @@ -0,0 +1,25 @@ +class Array + + # for ReVIEW::Node + # + def to_doc + self.map(&:to_doc).join("") + end + + # for ReVIEW::Node + # + def to_raw + self.map(&:to_raw).join("") + end + + if [].map.kind_of?(Array) + # Ruby 1.8 + def map(&block) + if !block_given? + return to_enum :map + else + collect(&block) ## XXX same as original + end + end + end +end diff --git a/lib/review/htmlbuilder.rb b/lib/review/htmlbuilder.rb index 0ace2a7a3..91b885b1d 100644 --- a/lib/review/htmlbuilder.rb +++ b/lib/review/htmlbuilder.rb @@ -29,13 +29,6 @@ class HTMLBuilder < Builder Compiler.defblock(:point, 0..1) Compiler.defblock(:shoot, 0..1) - def pre_paragraph - '

' - end - def post_paragraph - '

' - end - def extname ".#{@book.config["htmlext"]}" end @@ -89,7 +82,7 @@ def result # default XHTML header/footer @error_messages = error_messages @warning_messages = warning_messages - @title = strip_html(compile_inline(@chapter.title)) + @title = strip_html(@chapter.title) @body = @output.string @language = @book.config['language'] @stylesheets = @book.config["stylesheet"] @@ -157,122 +150,132 @@ def warning_messages end def headline(level, label, caption) + buf = "" prefix, anchor = headline_prefix(level) unless prefix.nil? prefix = %Q[#{prefix}] end - puts '' if level > 1 a_id = "" unless anchor.nil? a_id = %Q[] end if caption.empty? - puts a_id unless label.nil? + buf << a_id+"\n" unless label.nil? else if label.nil? - puts %Q[#{a_id}#{prefix}#{compile_inline(caption)}] + buf << %Q[#{a_id}#{prefix}#{caption}\n] else - puts %Q[#{a_id}#{prefix}#{compile_inline(caption)}] + buf << %Q[#{a_id}#{prefix}#{caption}\n] end end + buf end def nonum_begin(level, label, caption) @nonum_counter += 1 - puts '' if level > 1 + buf = "" + buf << "\n" if level > 1 unless caption.empty? if label.nil? id = normalize_id("#{@chapter.name}_nonum#{@nonum_counter}") - puts %Q[#{compile_inline(caption)}] + buf << %Q[#{caption}\n] else - puts %Q[#{compile_inline(caption)}] + buf << %Q[#{caption}\n] end end + buf end def nonum_end(level) end def notoc_begin(level, label, caption) + buf = "" @nonum_counter += 1 - puts '' if level > 1 + buf << "\n" if level > 1 unless caption.empty? if label.nil? id = normalize_id("#{@chapter.name}_nonum#{@nonum_counter}") - puts %Q[#{compile_inline(caption)}] + buf << %Q[#{compile_inline(caption)}] else - puts %Q[#{compile_inline(caption)}] + buf << %Q[#{compile_inline(caption)}] end end + buf end def notoc_end(level) end def nodisp_begin(level, label, caption) + buf = "" @nonum_counter += 1 - puts '' if level > 1 + buf << "\n" if level > 1 unless caption.empty? if label.nil? id = normalize_id("#{@chapter.name}_nonum#{@nonum_counter}") - puts %Q[] + buf << %Q[] else - puts %Q[] + buf << %Q[] end end + buf end def nodisp_end(level) end def column_begin(level, label, caption) - puts %Q[
] + buf = %Q[
\n] @column += 1 - puts '' if level > 1 + buf << "\n" if level > 1 a_id = %Q[] if caption.empty? - puts a_id unless label.nil? + buf << a_id + "\n" unless label.nil? else if label.nil? - puts %Q[#{a_id}#{compile_inline(caption)}] + buf << %Q[#{a_id}#{caption}\n] else - puts %Q[#{a_id}#{compile_inline(caption)}] + buf << %Q[#{a_id}#{caption}\n] end end -# headline(level, label, caption) + buf end def column_end(level) - puts '
' + "
\n" end def xcolumn_begin(level, label, caption) - puts %Q[
] - headline(level, label, caption) + buf << %Q[
\n] + buf << headline(level, label, caption) + buf end def xcolumn_end(level) - puts '
' + "
\n" end def ref_begin(level, label, caption) - print %Q[
] - headline(level, label, caption) + buf << %Q[
\n] + buf << headline(level, label, caption) + buf end def ref_end(level) - puts '
' + "
\n" end def sup_begin(level, label, caption) - print %Q[
] - headline(level, label, caption) + buf << %Q[
\n] + buf << headline(level, label, caption) + buf end def sup_end(level) - puts '
' + "
\n" end def tsize(str) @@ -280,13 +283,13 @@ def tsize(str) end def captionblock(type, lines, caption) - puts %Q[
] + buf = %Q[
\n] unless caption.nil? - puts %Q[

#{compile_inline(caption)}

] + buf << %Q[

#{caption}

\n] end - blocked_lines = split_paragraph(lines) - puts blocked_lines.join("\n") - puts '
' + buf << lines.join("") + buf << "
\n" + buf end def memo(lines, caption = nil) @@ -338,12 +341,14 @@ def shoot(lines, caption = nil) end def box(lines, caption = nil) - puts %Q[
] - puts %Q[

#{compile_inline(caption)}

] unless caption.nil? - print %Q[
]
-      lines.each {|line| puts detab(line) }
-      puts '
' - puts '
' + buf = "" + buf << %Q[
\n] + buf << %Q[

#{caption}

\n] unless caption.nil? + buf << %Q[
]
+      lines.each {|line| buf << detab(line) << "\n" }
+      buf << "
\n" + buf << "
\n" + buf end def note(lines, caption = nil) @@ -351,94 +356,95 @@ def note(lines, caption = nil) end def ul_begin - puts '
    ' + "
      \n" end def ul_item(lines) - puts "
    • #{lines.join}
    • " + "
    • #{lines.map(&:to_s).join}
    • \n" end def ul_item_begin(lines) - print "
    • #{lines.join}" + "
    • #{lines.map(&:to_s).join}" end def ul_item_end - puts "
    • " + "\n" end def ul_end - puts '
    ' + "
\n" end def ol_begin if @ol_num - puts "
    " ## it's OK in HTML5, but not OK in XHTML1.1 + num = @ol_num @ol_num = nil + "
      \n" ## it's OK in HTML5, but not OK in XHTML1.1 else - puts '
        ' + "
          \n" end end def ol_item(lines, num) - puts "
        1. #{lines.join}
        2. " + "
        3. #{lines.map(&:to_s).join}
        4. \n" end def ol_end - puts '
        ' + "
      \n" end def dl_begin - puts '
      ' + "
      \n" end def dt(line) - puts "
      #{line}
      " + "
      #{line}
      \n" end def dd(lines) - puts "
      #{lines.join}
      " + "
      #{lines.join}
      \n" end def dl_end - puts '
      ' + "
      \n" end def paragraph(lines) if @noindent.nil? - puts "

      #{lines.join}

      " + "

      #{lines.join}

      \n" else - puts %Q[

      #{lines.join}

      ] @noindent = nil + %Q[

      #{lines.join}

      \n] end end def parasep - puts '
      ' + "
      \n" end def read(lines) - blocked_lines = split_paragraph(lines) - puts %Q[
      \n#{blocked_lines.join("\n")}\n
      ] + %Q[
      \n#{lines.join("")}\n
      \n] end alias_method :lead, :read def list(lines, id, caption, lang = nil) - puts %Q[
      ] + buf = %Q[
      \n] begin - list_header id, caption, lang + buf << list_header(id, caption, lang) rescue KeyError error "no such list: #{id}" end - list_body id, lines, lang - puts '
      ' + buf << list_body(id, lines, lang) + buf << "
      \n" + buf end def list_header(id, caption, lang) if get_chap.nil? - puts %Q[

      #{I18n.t("list")}#{I18n.t("format_number_header_without_chapter", [@chapter.list(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}

      ] + %Q[

      #{I18n.t("list")}#{I18n.t("format_number_header_without_chapter", [@chapter.list(id).number])}#{I18n.t("caption_prefix")}#{caption}

      \n] else - puts %Q[

      #{I18n.t("list")}#{I18n.t("format_number_header", [get_chap, @chapter.list(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}

      ] + %Q[

      #{I18n.t("list")}#{I18n.t("format_number_header", [get_chap, @chapter.list(id).number])}#{I18n.t("caption_prefix")}#{caption}

      \n] end end @@ -447,156 +453,167 @@ def list_body(id, lines, lang) class_names = ["list"] lexer = lang || File.extname(id).gsub(/\./, '') class_names.push("language-#{lexer}") unless lexer.blank? - print %Q[
      ]
      +      buf = %Q[
      ]
             body = lines.inject(''){|i, j| i + detab(j) + "\n"}
      -      puts highlight(:body => body, :lexer => lexer, :format => 'html')
      -      puts '
      ' + buf << highlight(:body => body, :lexer => lexer, :format => 'html') + buf << "
      \n" + buf end def source(lines, caption = nil, lang = nil) - puts %Q[
      ] - source_header caption - source_body caption, lines, lang - puts '
      ' + buf = %Q[
      \n] + buf << source_header(caption) + buf << source_body(caption, lines, lang) + buf << "
      \n" + buf end def source_header(caption) if caption.present? - puts %Q[

      #{compile_inline(caption)}

      ] + %Q[

      #{caption}

      \n] end end def source_body(id, lines, lang) id ||= '' - print %Q[
      ]
      +      buf = %Q[
      ]
             body = lines.inject(''){|i, j| i + detab(j) + "\n"}
             lexer = lang || File.extname(id).gsub(/\./, '')
      -      puts highlight(:body => body, :lexer => lexer, :format => 'html')
      -      puts '
      ' + buf << highlight(:body => body, :lexer => lexer, :format => 'html') + buf << "
      \n" + buf end def listnum(lines, id, caption, lang = nil) - puts %Q[
      ] + buf = %Q[
      \n] begin - list_header id, caption, lang + buf << list_header(id, caption, lang) rescue KeyError error "no such list: #{id}" end - listnum_body lines, lang - puts '
      ' + buf << listnum_body(lines, lang) + buf << "
      " + buf end def listnum_body(lines, lang) + buf = "" if highlight? body = lines.inject(''){|i, j| i + detab(j) + "\n"} lexer = lang - puts highlight(:body => body, :lexer => lexer, :format => 'html', - :options => {:linenos => 'inline', :nowrap => false}) + buf << highlight(:body => body, :lexer => lexer, :format => 'html', + :options => {:linenos => 'inline', :nowrap => false}) else class_names = ["list"] class_names.push("language-#{lang}") unless lang.blank? - print %Q[
      ]
      +        buf << %Q[
      ]
               lines.each_with_index do |line, i|
      -          puts detab((i+1).to_s.rjust(2) + ": " + line)
      +          buf << detab((i+1).to_s.rjust(2) + ": " + line) << "\n"
               end
      -        puts '
      ' + buf << '
      ' << "\n" end + buf end def emlist(lines, caption = nil, lang = nil) - puts %Q[
      ] + buf = %Q[
      \n] if caption.present? - puts %Q(

      #{compile_inline(caption)}

      ) + buf << %Q(

      #{caption}

      \n) end class_names = ["emlist"] class_names.push("language-#{lang}") unless lang.blank? - print %Q[
      ]
      +      buf << %Q[
      ]
             body = lines.inject(''){|i, j| i + detab(j) + "\n"}
             lexer = lang
      -      puts highlight(:body => body, :lexer => lexer, :format => 'html')
      -      puts '
      ' - puts '
      ' + buf << highlight(:body => body, :lexer => lexer, :format => 'html') + buf << "\n" + buf << "
      \n" + buf end def emlistnum(lines, caption = nil, lang = nil) - puts %Q[
      ] + buf = %Q[
      \n] if caption.present? - puts %Q(

      #{compile_inline(caption)}

      ) + buf << %Q(

      #{caption}

      \n) end - if highlight? body = lines.inject(''){|i, j| i + detab(j) + "\n"} lexer = lang - puts highlight(:body => body, :lexer => lexer, :format => 'html', - :options => {:linenos => 'inline', :nowrap => false}) + buf << highlight(:body => body, :lexer => lexer, :format => 'html', + :options => {:linenos => 'inline', :nowrap => false}) else class_names = ["emlist"] class_names.push("language-#{lang}") unless lang.blank? - print %Q[
      ]
      +        buf << %Q[
      ]
               lines.each_with_index do |line, i|
      -          puts detab((i+1).to_s.rjust(2) + ": " + line)
      +          buf << detab((i+1).to_s.rjust(2) + ": " + line) << "\n"
               end
      -        puts '
      ' + buf << '
      ' << "\n" end - puts '
      ' + buf << '
      ' << "\n" + buf end def cmd(lines, caption = nil) - puts %Q[
      ] + buf = %Q[
      \n] if caption.present? - puts %Q(

      #{compile_inline(caption)}

      ) + buf << %Q(

      #{caption}

      \n) end - print %Q[
      ]
      +      buf << %Q[
      ]
             body = lines.inject(''){|i, j| i + detab(j) + "\n"}
             lexer = 'shell-session'
      -      puts highlight(:body => body, :lexer => lexer, :format => 'html')
      -      puts '
      ' - puts '
      ' + buf << highlight(:body => body, :lexer => lexer, :format => 'html') + buf << "\n" + buf << "
      \n" + buf end def quotedlist(lines, css_class) - print %Q[
      ]
      +      buf = %Q[
      \n]
             lines.each do |line|
      -        puts detab(line)
      +        buf << detab(line) << "\n"
             end
      -      puts '
      ' + buf << "
      \n" end private :quotedlist def quote(lines) - blocked_lines = split_paragraph(lines) - puts "
      #{blocked_lines.join("\n")}
      " + "
      #{lines.join("")}
      \n" end def doorquote(lines, ref) - blocked_lines = split_paragraph(lines) - puts %Q[
      ] - puts "#{blocked_lines.join("\n")}" - puts %Q[

      #{ref}より

      ] - puts %Q[
      ] + buf = "" + buf << %Q[
      \n] + buf << "#{lines.join("")}\n" + buf << %Q[

      #{ref}より

      \n] + buf << %Q[
      \n] + buf end def talk(lines) - puts %Q[
      ] - blocked_lines = split_paragraph(lines) - puts "#{blocked_lines.join("\n")}" - puts '
      ' + buf = "" + buf << %Q[
      \n] + buf << "#{lines.join("\n")}\n" + buf << "
      \n" + buf end - def texequation(lines) - puts %Q[
      ] + def node_texequation(node) + buf = "" + buf << %Q[
      \n] if @book.config["mathml"] require 'math_ml' require 'math_ml/symbol/character_reference' p = MathML::LaTeX::Parser.new(:symbol=>MathML::Symbol::CharacterReference) - puts p.parse(unescape_html(lines.join("\n")), true) + buf << p.parse(node.to_raw, true).to_s << "\n" else - print '
      '
      -        puts "#{lines.join("\n")}"
      -        puts '
      ' + buf << '
      '
      +        buf << lines.join("\n") << "\n"
      +        buf << "
      \n" end - puts '
      ' + buf << "
      \n" + buf end def handle_metric(str) @@ -623,32 +640,35 @@ def result_metric(array) def image_image(id, caption, metric) metrics = parse_metric("html", metric) - puts %Q[
      ] - puts %Q[#{escape_html(compile_inline(caption))}] - image_header id, caption - puts %Q[
      ] + buf = %Q[
      \n] + buf << %Q[#{caption}\n] + buf << image_header(id, caption) + buf << %Q[
      \n] + buf end def image_dummy(id, caption, lines) - puts %Q[
      ] - puts %Q[
      ]
      +      buf = %Q[
      ] + buf << %Q[
      ]
             lines.each do |line|
      -        puts detab(line)
      +        buf << detab(line) << "\n"
             end
      -      puts %Q[
      ] - image_header id, caption - puts %Q[
      ] + buf << %Q[
      \n] + buf << image_header(id, caption) + buf << %Q[
      \n] warn "no such image: #{id}" + buf end def image_header(id, caption) - puts %Q[

      ] + buf = %Q[

      \n] if get_chap.nil? - puts %Q[#{I18n.t("image")}#{I18n.t("format_number_header_without_chapter", [@chapter.image(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}] + buf << %Q[#{I18n.t("image")}#{I18n.t("format_number_header_without_chapter", [@chapter.image(id).number])}#{I18n.t("caption_prefix")}#{caption}\n] else - puts %Q[#{I18n.t("image")}#{I18n.t("format_number_header", [get_chap, @chapter.image(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}] + buf << %Q[#{I18n.t("image")}#{I18n.t("format_number_header", [get_chap, @chapter.image(id).number])}#{I18n.t("caption_prefix")}#{caption}\n] end - puts %Q[

      ] + buf << %Q[

      \n] + buf end def table(lines, id = nil, caption = nil) @@ -666,48 +686,49 @@ def table(lines, id = nil, caption = nil) rows = adjust_n_cols(rows) if id - puts %Q[
      ] + buf = %Q[
      \n] else - puts %Q[
      ] + buf = %Q[
      \n] end begin - table_header id, caption unless caption.nil? + buf << table_header(id, caption) unless caption.nil? rescue KeyError error "no such table: #{id}" end - table_begin rows.first.size + buf << table_begin(rows.first.size) return if rows.empty? if sepidx sepidx.times do - tr rows.shift.map {|s| th(s) } + buf << tr(rows.shift.map {|s| th(s) }) end rows.each do |cols| - tr cols.map {|s| td(s) } + buf << tr(cols.map {|s| td(s) }) end else rows.each do |cols| h, *cs = *cols - tr [th(h)] + cs.map {|s| td(s) } + buf << tr([th(h)] + cs.map {|s| td(s) }) end end - table_end - puts %Q[
      ] + buf << table_end + buf << %Q[
      \n] + buf end def table_header(id, caption) if get_chap.nil? - puts %Q[

      #{I18n.t("table")}#{I18n.t("format_number_header_without_chapter", [@chapter.table(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}

      ] + %Q[

      #{I18n.t("table")}#{I18n.t("format_number_header_without_chapter", [@chapter.table(id).number])}#{I18n.t("caption_prefix")}#{caption}

      \n] else - puts %Q[

      #{I18n.t("table")}#{I18n.t("format_number_header", [get_chap, @chapter.table(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}

      ] + %Q[

      #{I18n.t("table")}#{I18n.t("format_number_header", [get_chap, @chapter.table(id).number])}#{I18n.t("caption_prefix")}#{caption}

      \n] end end def table_begin(ncols) - puts '' + "
      \n" end def tr(rows) - puts "#{rows.join}" + "#{rows.join}\n" end def th(str) @@ -719,95 +740,98 @@ def td(str) end def table_end - puts '
      ' + "\n" end def imgtable(lines, id, caption = nil, metric = nil) + buf = "" if !@chapter.image(id).bound? warn "image not bound: #{id}" - image_dummy id, caption, lines - return + return image_dummy(id, caption, lines) end - puts %Q[
      ] + buf << %Q[
      \n] begin - table_header id, caption unless caption.nil? + buf << table_header(id, caption) unless caption.nil? rescue KeyError error "no such table: #{id}" end - imgtable_image(id, caption, metric) + buf << imgtable_image(id, caption, metric) - puts %Q[
      ] + buf << %Q[
      \n] + buf end def imgtable_image(id, caption, metric) metrics = parse_metric("html", metric) - puts %Q[#{escape_html(compile_inline(caption))}] + %Q[#{escape_html(compile_inline(caption))}\n] end def comment(lines, comment = nil) lines ||= [] lines.unshift comment unless comment.blank? if @book.config["draft"] - str = lines.join("
      ") - puts %Q(
      #{str}
      ) + str = lines.map{|line| escape_html(line) }.join("
      ") + return %Q(
      #{str}
      \n) else str = lines.join("\n") - puts %Q() + return %Q(\n) end end def footnote(id, str) if @book.config["epubversion"].to_i == 3 - puts %Q(

      [*#{@chapter.footnote(id).number}] #{compile_inline(str)}

      ) + %Q(

      [*#{@chapter.footnote(id).number}] #{str}

      \n) else - puts %Q(

      [*#{@chapter.footnote(id).number}] #{compile_inline(str)}

      ) + %Q(\n) end end def indepimage(id, caption="", metric=nil) metrics = parse_metric("html", metric) caption = "" if caption.nil? - puts %Q[
      ] + buf = %Q[
      ] + "\n" begin - puts %Q[#{escape_html(compile_inline(caption))}] + buf << %Q[#{caption}\n] rescue - puts %Q[
      missing image: #{id}
      ] + buf << %Q[
      missing image: #{id}
      \n] end unless caption.empty? - puts %Q[

      ] - puts %Q[#{I18n.t("numberless_image")}#{I18n.t("caption_prefix")}#{compile_inline(caption)}] - puts %Q[

      ] + buf << %Q[

      \n] + buf << %Q[#{I18n.t("numberless_image")}#{I18n.t("caption_prefix")}#{caption}\n] + buf << %Q[

      \n] end - puts %Q[
      ] + buf << %Q[
      \n] + buf end alias_method :numberlessimage, :indepimage def hr - puts "
      " + "
      \n" end def label(id) - puts %Q() + %Q(\n) end def linebreak - puts "
      " + "
      \n" end def pagebreak - puts %Q(
      ) + %Q(
      \n) end def bpo(lines) - puts "" + buf = "\n" lines.each do |line| - puts detab(line) + buf << detab(line) + "\n" end - puts "" + buf << "\n" + buf end def noindent @@ -815,7 +839,7 @@ def noindent end def inline_labelref(idref) - %Q[「#{I18n.t("label_marker")}#{escape_html(idref)}」] + %Q[「#{I18n.t("label_marker")}#{idref}」] end alias_method :inline_ref, :inline_labelref @@ -865,9 +889,9 @@ def inline_fn(id) def compile_ruby(base, ruby) if @book.htmlversion == 5 - %Q[#{escape_html(base)}#{I18n.t("ruby_prefix")}#{escape_html(ruby)}#{I18n.t("ruby_postfix")}] + %Q[#{base}#{I18n.t("ruby_prefix")}#{ruby}#{I18n.t("ruby_postfix")}] else - %Q[#{escape_html(base)}#{I18n.t("ruby_prefix")}#{ruby}#{I18n.t("ruby_postfix")}] + %Q[#{base}#{I18n.t("ruby_prefix")}#{ruby}#{I18n.t("ruby_postfix")}] end end @@ -881,34 +905,34 @@ def compile_kw(word, alt) end def inline_i(str) - %Q(#{escape_html(str)}) + %Q(#{str}) end def inline_b(str) - %Q(#{escape_html(str)}) + %Q(#{str}) end def inline_ami(str) - %Q(#{escape_html(str)}) + %Q(#{str}) end def inline_bou(str) - %Q(#{escape_html(str)}) + %Q(#{str}) end def inline_tti(str) if @book.htmlversion == 5 - %Q(#{escape_html(str)}) + %Q(#{str}) else - %Q(#{escape_html(str)}) + %Q(#{str}) end end def inline_ttb(str) if @book.htmlversion == 5 - %Q(#{escape_html(str)}) + %Q(#{str}) else - %Q(#{escape_html(str)}) + %Q(#{str}) end end @@ -918,14 +942,14 @@ def inline_dtp(str) def inline_code(str) if @book.htmlversion == 5 - %Q(#{escape_html(str)}) + %Q(#{str}) else - %Q(#{escape_html(str)}) + %Q(#{str}) end end def inline_idx(str) - %Q(#{escape_html(str)}) + %Q(#{str}) end def inline_hidx(str) @@ -943,7 +967,7 @@ def inline_m(str) parser = MathML::LaTeX::Parser.new(:symbol => MathML::Symbol::CharacterReference) %Q[#{parser.parse(str, nil)}] else - %Q[#{escape_html(str)}] + %Q[#{str}] end end @@ -952,23 +976,24 @@ def text(str) end def bibpaper(lines, id, caption) - puts %Q[
      ] - bibpaper_header id, caption + buf = %Q[
      \n] + buf << bibpaper_header(id, caption) unless lines.empty? - bibpaper_bibpaper id, caption, lines + buf << bibpaper_bibpaper(id, caption, lines) end - puts "
      " + buf << "
      " << "\n" + buf end def bibpaper_header(id, caption) - print %Q() - print "[#{@chapter.bibpaper(id).number}]" - print %Q() - puts " #{compile_inline(caption)}" + buf = %Q() + buf << "[#{@chapter.bibpaper(id).number}]" + buf << %Q() + buf << " #{caption}" << "\n" end def bibpaper_bibpaper(id, caption, lines) - print split_paragraph(lines).join("") + lines.join("") end def inline_bib(id) @@ -978,9 +1003,9 @@ def inline_bib(id) def inline_hd_chap(chap, id) n = chap.headline_index.number(id) if chap.number and @book.config["secnolevel"] >= n.split('.').size - str = I18n.t("chapter_quote", "#{n} #{compile_inline(chap.headline(id).caption)}") + str = I18n.t("chapter_quote", "#{n} #{chap.headline(id).caption}") else - str = I18n.t("chapter_quote", compile_inline(chap.headline(id).caption)) + str = I18n.t("chapter_quote", chap.headline(id).caption) end if @book.config["chapterlink"] anchor = "h"+n.gsub(/\./, "-") @@ -1053,7 +1078,7 @@ def inline_img(id) end def inline_asis(str, tag) - %Q(<#{tag}>#{escape_html(str)}) + %Q(<#{tag}>#{str}) end def inline_abbr(str) @@ -1110,9 +1135,9 @@ def inline_sup(str) def inline_tt(str) if @book.htmlversion == 5 - %Q(#{escape_html(str)}) + %Q(#{str}) else - %Q(#{escape_html(str)}) + %Q(#{str}) end end @@ -1125,11 +1150,11 @@ def inline_ins(str) end def inline_u(str) - %Q(#{escape_html(str)}) + %Q(#{str}) end def inline_recipe(str) - %Q(「#{escape_html(str)}」) + %Q(「#{str}」) end def inline_icon(id) @@ -1146,7 +1171,7 @@ def inline_uchar(str) def inline_comment(str) if @book.config["draft"] - %Q(#{escape_html(str)}) + %Q(#{str}) else %Q() end @@ -1169,18 +1194,20 @@ def nofunc_text(str) def compile_href(url, label) if @book.config["externallink"] - %Q(#{label.nil? ? escape_html(url) : escape_html(label)}) + %Q(#{label.nil? ? url : label}) else - label.nil? ? escape_html(url) : I18n.t('external_link', [escape_html(label), escape_html(url)]) + label.nil? ? url : I18n.t('external_link', [label, url]) end end def flushright(lines) - puts split_paragraph(lines).join("\n").gsub("

      ", "

      ") + result = "" + result << lines.join("").gsub("

      ", "

      ") + result end def centering(lines) - puts split_paragraph(lines).join("\n").gsub("

      ", "

      ") + lines.join("").gsub("

      ", "

      ") end def image_ext diff --git a/lib/review/htmlutils.rb b/lib/review/htmlutils.rb index 8aef9edf2..e4d0a77c8 100644 --- a/lib/review/htmlutils.rb +++ b/lib/review/htmlutils.rb @@ -77,7 +77,7 @@ def highlight(ops) body end rescue LoadError - body + body end end diff --git a/lib/review/idgxmlbuilder.rb b/lib/review/idgxmlbuilder.rb index 28b08f5bd..e5efbc470 100644 --- a/lib/review/idgxmlbuilder.rb +++ b/lib/review/idgxmlbuilder.rb @@ -23,7 +23,10 @@ class IDGXMLBuilder < Builder [:ttbold, :hint, :maru, :keytop, :labelref, :ref, :pageref, :balloon].each {|e| Compiler.definline(e) } Compiler.defsingle(:dtp, 1) - Compiler.defblock(:insn, 0..1) + Compiler.defcodeblock(:insn, 1) + Compiler.defblock(:memo, 0..1) + Compiler.defblock(:tip, 0..1) + Compiler.defblock(:info, 0..1) Compiler.defblock(:planning, 0..1) Compiler.defblock(:best, 0..1) Compiler.defblock(:security, 0..1) @@ -36,14 +39,6 @@ class IDGXMLBuilder < Builder Compiler.defblock(:expert, 0) Compiler.defblock(:rawblock, 0) - def pre_paragraph - '

      ' - end - - def post_paragraph - '

      ' - end - def extname '.xml' end @@ -69,8 +64,14 @@ def builder_init_file @tsize = nil @texblockequation = 0 @texinlineequation = 0 - print %Q(\n) - print %Q(<#{@rootelement} xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/">) + + @output << %Q(\n) + @output << %Q(<#{@rootelement} xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/">) + if @book.config["nolf"].present? + @lf = "" + else + @lf = "\n" + end @secttags = true unless @book.config["structuredxml"].nil? end private :builder_init_file @@ -98,7 +99,7 @@ def result def warn(msg) if @no_error @warns.push [@location.filename, @location.lineno, msg] - puts "----WARNING: #{escape_html(msg)}----" + buf << "----WARNING: #{escape_html(msg)}----" << @lf else $stderr.puts "#{@location}: warning: #{msg}" end @@ -107,7 +108,7 @@ def warn(msg) def error(msg) if @no_error @errors.push [@location.filename, @location.lineno, msg] - puts "----ERROR: #{escape_html(msg)}----" + buf << "----ERROR: #{escape_html(msg)}----" << @lf else $stderr.puts "#{@location}: error: #{msg}" end @@ -138,63 +139,57 @@ def warning_messages end def headline(level, label, caption) + buf = "" case level when 1 unless @secttags.nil? - print "" if @subsubsubsection > 0 - print "" if @subsubsection > 0 - print "" if @subsection > 0 - print "" if @section > 0 + buf << "" if @subsubsubsection > 0 + buf << "" if @subsubsection > 0 + buf << "" if @subsection > 0 + buf << "" if @section > 0 end - - print %Q() unless @secttags.nil? - + buf << %Q() unless @secttags.nil? @section = 0 @subsection = 0 @subsubsection = 0 @subsubsubsection = 0 when 2 unless @secttags.nil? - print "" if @subsubsubsection > 0 - print "" if @subsubsection > 0 - print "" if @subsection > 0 - print "" if @section > 0 + buf << "" if @subsubsubsection > 0 + buf << "" if @subsubsection > 0 + buf << "" if @subsection > 0 + buf << "" if @section > 0 end @section += 1 - print %Q() unless @secttags.nil? - + buf << %Q() unless @secttags.nil? @subsection = 0 @subsubsection = 0 @subsubsubsection = 0 when 3 unless @secttags.nil? - print "" if @subsubsubsection > 0 - print "" if @subsubsection > 0 - print "" if @subsection > 0 + buf << "" if @subsubsubsection > 0 + buf << "" if @subsubsection > 0 + buf << "" if @subsection > 0 end - @subsection += 1 - print %Q() unless @secttags.nil? - + buf << %Q() unless @secttags.nil? @subsubsection = 0 @subsubsubsection = 0 when 4 unless @secttags.nil? - print "" if @subsubsubsection > 0 - print "" if @subsubsection > 0 + buf << "" if @subsubsubsection > 0 + buf << "" if @subsubsection > 0 end - @subsubsection += 1 - print %Q() unless @secttags.nil? - + buf << %Q() unless @secttags.nil? @subsubsubsection = 0 when 5 unless @secttags.nil? - print "" if @subsubsubsection > 0 + buf << "" if @subsubsubsection > 0 end @subsubsubsection += 1 - print %Q() unless @secttags.nil? + buf << %Q() unless @secttags.nil? else raise "caption level too deep or unsupported: #{level}" end @@ -202,65 +197,68 @@ def headline(level, label, caption) prefix, anchor = headline_prefix(level) label = label.nil? ? "" : " id=\"#{label}\"" - toccaption = escape_html(compile_inline(caption.gsub(/@\{.+?\}/, '')).gsub(/<[^>]+>/, '')) - puts %Q(#{prefix}#{compile_inline(caption)}) + toccaption = escape_html(caption.gsub(/@\{.+?\}/, '').gsub(/<[^>]+>/, '')) + buf << %Q(#{prefix}#{caption}) << @lf + + buf end def ul_begin level = block_given? ? yield : "" level = nil if level == 1 - puts "" + "" + @lf end def ul_item(lines) - puts %Q(
    1. #{lines.join.chomp}
    2. ) + %Q(
    3. #{lines.join.chomp}
    4. ) + @lf end def ul_item_begin(lines) - print %Q(
    5. #{lines.join.chomp}) + %Q(
    6. #{lines.join.chomp}) end def ul_item_end - puts "
    7. " + "" + @lf end def choice_single_begin - puts "" + "" + @lf end def choice_multi_begin - puts "" + "" + @lf end def choice_single_end - puts "" + "" + @lf end def choice_multi_end - puts "" + "" + @lf end def ul_end level = block_given? ? yield : "" level = nil if level == 1 - puts "" + "" + @lf end def ol_begin - puts '
        ' if !@ol_num @ol_num = 1 end + '
          ' + @lf end def ol_item(lines, num) - puts %Q(
        1. #{lines.join.chomp}
        2. ) + buf = %Q(
        3. #{lines.join.chomp}
        4. ) + @lf @ol_num += 1 + buf end def ol_end - puts '
        ' @ol_num = nil + '
      ' + @lf end def olnum(num) @@ -268,36 +266,38 @@ def olnum(num) end def dl_begin - puts '
      ' + '
      ' + @lf end def dt(line) - puts "
      #{line}
      " + "
      #{line}
      " + @lf end def dd(lines) - puts "
      #{lines.join.chomp}
      " + "
      #{lines.join.chomp}
      " + @lf end def dl_end - puts '
      ' + '
      ' + @lf end def paragraph(lines) + buf = "" if @noindent.nil? if lines[0] =~ /\A(\t+)/ - puts %Q(

      #{lines.join('').sub(/\A\t+/, "")}

      ) + buf << %Q(

      #{lines.join('').sub(/\A\t+/, "")}

      ) << @lf else - puts "

      #{lines.join}

      " + buf << "

      #{lines.join}

      " << @lf end else - puts %Q(

      #{lines.join}

      ) + buf << %Q(

      #{lines.join}

      ) << @lf @noindent = nil end + buf end def read(lines) - puts %Q[#{split_paragraph(lines).join}] + %Q[#{lines.join}] + @lf end alias_method :lead, :read @@ -326,34 +326,40 @@ def inline_list(id) end def list_header(id, caption, lang) - puts %Q[] + buf = "" + buf << %Q[] << @lf if get_chap.nil? - puts %Q[#{I18n.t("list")}#{I18n.t("format_number_without_chapter", [@chapter.list(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}] + buf << %Q[#{I18n.t("list")}#{I18n.t("format_number_without_chapter", [@chapter.list(id).number])}#{I18n.t("caption_prefix_idgxml")}#{caption}] << @lf else - puts %Q[#{I18n.t("list")}#{I18n.t("format_number", [get_chap, @chapter.list(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}] + buf << %Q[#{I18n.t("list")}#{I18n.t("format_number", [get_chap, @chapter.list(id).number])}#{I18n.t("caption_prefix_idgxml")}#{caption}] << @lf end + buf end def codelines_body(lines) + buf = "" no = 1 lines.each do |line| unless @book.config["listinfo"].nil? - print "" + buf << "" end - print detab(line) - print "\n" - print "" unless @book.config["listinfo"].nil? + buf << detab(line) + buf << "\n" + buf << "" unless @book.config["listinfo"].nil? no += 1 end + buf end def list_body(id, lines, lang) - print %Q(
      )
      -      codelines_body(lines)
      -      puts "
      " + buf = "" + buf << %Q(
      )
      +      buf << codelines_body(lines)
      +      buf << "
      " << @lf + buf end def emlist(lines, caption = nil, lang = nil) @@ -363,27 +369,30 @@ def emlist(lines, caption = nil, lang = nil) def emlistnum(lines, caption = nil, lang = nil) _lines = [] lines.each_with_index do |line, i| + line.chomp! ## new parser don't remove LF in table (code block) _lines << detab("" + (i + 1).to_s.rjust(2) + ": " + line) end quotedlist _lines, 'emlistnum', caption end def listnum_body(lines, lang) - print %Q(
      )
      +      buf = ""
      +      buf << %Q(
      )
             no = 1
             lines.each_with_index do |line, i|
               unless @book.config["listinfo"].nil?
      -          print ""
      +          buf << ""
               end
      -        print detab("" + (i + 1).to_s.rjust(2) + ": " + line)
      -        print "\n"
      -        print "" unless @book.config["listinfo"].nil?
      +        buf << detab("" + (i + 1).to_s.rjust(2) + ": " + line)
      +        buf << "\n"
      +        buf << "" unless @book.config["listinfo"].nil?
               no += 1
             end
      -      puts "
      " + buf << "
      " << @lf + buf end def cmd(lines, caption = nil) @@ -391,29 +400,30 @@ def cmd(lines, caption = nil) end def quotedlist(lines, css_class, caption) - print %Q[] - puts "#{compile_inline(caption)}" if caption.present? - print %Q[
      ]
      +      buf = ""
      +      buf << %Q[]
      +      buf << "#{caption}" + @lf if caption.present?
      +      buf << %Q[
      ]
             no = 1
             lines.each do |line|
               unless @book.config["listinfo"].nil?
      -          print ""
      +          buf << ""
               end
      -        print detab(line)
      -        print "\n"
      -        print "" unless @book.config["listinfo"].nil?
      +        buf << detab(line)
      +        buf << "\n"
      +        buf << "" unless @book.config["listinfo"].nil?
               no += 1
             end
      -      puts '
      ' + buf << '
      ' << @lf + buf end private :quotedlist def quote(lines) - blocked_lines = split_paragraph(lines) - puts "#{blocked_lines.join("")}" + "#{lines.join("")}" + @lf end def inline_table(id) @@ -425,7 +435,8 @@ def inline_table(id) end end - def inline_img(id) + def node_inline_img(node) + id = node[0].to_raw chapter, id = extract_chapter_id(id) if get_chap(chapter).nil? "#{I18n.t("image")}#{I18n.t("format_number_without_chapter", [chapter.image(id).number])}" @@ -434,10 +445,11 @@ def inline_img(id) end end - def inline_imgref(id) + def node_inline_imgref(node) + id = node[0].to_raw chapter, id = extract_chapter_id(id) if chapter.image(id).caption.blank? - inline_img(id) + node_inline_img(node) else if get_chap(chapter).nil? "#{I18n.t("image")}#{I18n.t("format_number_without_chapter", [chapter.image(id).number])}#{I18n.t('image_quote', chapter.image(id).caption)}" @@ -457,53 +469,59 @@ def result_metric(array) end def image_image(id, caption, metric=nil) + buf = "" metrics = parse_metric("idgxml", metric) - puts "" - puts %Q[] - image_header id, caption - puts "" + buf << "" << @lf + buf << %Q[] << @lf + buf << image_header(id, caption) + buf << "" << @lf + buf end def image_dummy(id, caption, lines) - puts "" - print %Q[
      ]
      +      buf << "" << @lf
      +      buf << %Q[
      ]
             lines.each do |line|
      -        print detab(line)
      -        print "\n"
      +        buf << detab(line)
      +        buf << "\n"
             end
      -      print %Q[
      ] + buf << %Q[
      ] image_header id, caption - puts "" + buf << "" << @lf warn "no such image: #{id}" + buf end def image_header(id, caption) if get_chap.nil? - puts %Q[#{I18n.t("image")}#{I18n.t("format_number_without_chapter", [@chapter.image(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}] + %Q[#{I18n.t("image")}#{I18n.t("format_number_without_chapter", [@chapter.image(id).number])}#{I18n.t("caption_prefix_idgxml")}#{caption}] + @lf else - puts %Q[#{I18n.t("image")}#{I18n.t("format_number", [get_chap, @chapter.image(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}] + %Q[#{I18n.t("image")}#{I18n.t("format_number", [get_chap, @chapter.image(id).number])}#{I18n.t("caption_prefix_idgxml")}#{caption}] + @lf end end def texequation(lines) + buf = "" @texblockequation += 1 - puts %Q[] - puts '
      '
      -      puts "#{lines.join("\n")}"
      -      puts '
      ' - puts '
      ' + buf << %Q[] << @lf + buf << '
      ' << @lf
      +      buf << "#{lines.join("\n")}" << @lf
      +      buf << '
      ' << @lf + buf << '
      ' << @lf end def table(lines, id = nil, caption = nil) + buf = "" tablewidth = nil col = 0 if @book.config["tableopt"] tablewidth = @book.config["tableopt"].split(",")[0].to_f / @book.config["pt_to_mm_unit"].to_f end - puts "" + buf << "
      " rows = [] sepidx = nil lines.each_with_index do |line, idx| + line.chomp! ## new parser don't remove LF in table (code block) if /\A[\=\-]{12}/ =~ line sepidx ||= idx next @@ -540,66 +558,71 @@ def table(lines, id = nil, caption = nil) end begin - table_header id, caption unless caption.nil? + buf << table_header(id, caption) unless caption.nil? rescue KeyError error "no such table: #{id}" end return if rows.empty? if tablewidth.nil? - print "" + buf << "" else - print %Q[] + buf << %Q[] end if sepidx sepidx.times do |y| if tablewidth.nil? - puts %Q[#{rows.shift}] + buf << %Q[#{rows.shift}] << @lf else i = 0 rows.shift.split(/\t/).each_with_index do |cell, x| - print %Q[] + buf << %Q[] i += 1 end end end end - trputs(tablewidth, rows, cellwidth, sepidx) - puts "
      #{cell.sub("DUMMYCELLSPLITTER", "")}#{cell.sub("DUMMYCELLSPLITTER", "")}
      " + buf << trputs(tablewidth, rows, cellwidth, sepidx) + buf << "" << @lf @tsize = nil + buf end def trputs(tablewidth, rows, cellwidth, sepidx) + buf = "" sepidx = 0 if sepidx.nil? if tablewidth.nil? lastline = rows.pop - rows.each {|row| puts %Q[#{row}] } - puts %Q[#{lastline}] unless lastline.nil? + rows.each {|row| buf << %Q[#{row}] } + buf << %Q[#{lastline}] + @lf unless lastline.nil? else rows.each_with_index do |row, y| i = 0 row.split(/\t/).each_with_index do |cell, x| - print %Q[#{cell.sub("DUMMYCELLSPLITTER", "")}] + buf << %Q[#{cell.sub("DUMMYCELLSPLITTER", "")}] i += 1 end end end + buf end def table_header(id, caption) + buf = "" if get_chap.nil? - puts %Q[#{I18n.t("table")}#{I18n.t("format_number_without_chapter", [@chapter.table(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}] + buf << %Q[#{I18n.t("table")}#{I18n.t("format_number_without_chapter", [@chapter.table(id).number])}#{I18n.t("caption_prefix_idgxml")}#{caption}] + @lf else - puts %Q[#{I18n.t("table")}#{I18n.t("format_number", [get_chap, @chapter.table(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}] + buf << %Q[#{I18n.t("table")}#{I18n.t("format_number", [get_chap, @chapter.table(id).number])}#{I18n.t("caption_prefix_idgxml")}#{caption}] + @lf end + buf end def table_begin(ncols) end def tr(rows) - puts %Q[#{rows.join("\t")}] + %Q[#{rows.join("\t")}] + @lf end def th(str) @@ -611,7 +634,7 @@ def td(str) end def table_end - print "" + "" end def imgtable(lines, id, caption = nil, metric = nil) @@ -628,7 +651,7 @@ def imgtable(lines, id, caption = nil, metric = nil) end def comment(str) - print %Q() + %Q() end def footnote(id, str) @@ -636,7 +659,7 @@ def footnote(id, str) end def inline_fn(id) - %Q[#{compile_inline(@chapter.footnote(id).content.strip)}] + %Q[#{@chapter.footnote(id).content.strip}] end def compile_ruby(base, ruby) @@ -646,28 +669,30 @@ def compile_ruby(base, ruby) def compile_kw(word, alt) '' + if alt - then escape_html("#{word}(#{alt.strip})") - else escape_html(word) + then + "#{word}(#{alt.strip})" + else + word end + '' + - %Q[] + + %Q[] + if alt - alt.split(/\s*,\s*/).collect! {|e| %Q[] }.join + alt.split(/\s*,\s*/).collect! {|e| %Q[] }.join else "" end end def compile_href(url, label) - %Q[#{label.nil? ? escape_html(url) : escape_html(label)}] + %Q[#{label.nil? ? url : label}] end def inline_sup(str) - %Q[#{escape_html(str)}] + %Q[#{str}] end def inline_sub(str) - %Q[#{escape_html(str)}] + %Q[#{str}] end def inline_raw(str) @@ -676,9 +701,9 @@ def inline_raw(str) def inline_hint(str) if @book.config["nolf"].nil? - %Q[\n#{escape_html(str)}] + %Q[\n#{str}] else - %Q[#{escape_html(str)}] + %Q[#{str}] end end @@ -703,41 +728,41 @@ def inline_maru(str) end def inline_idx(str) - %Q(#{escape_html(str)}) + %Q(#{str}) end def inline_hidx(str) - %Q() + %Q() end def inline_ami(str) - %Q(#{escape_html(str)}) + %Q(#{str}) end def inline_i(str) - %Q(#{escape_html(str)}) + %Q(#{str}) end def inline_b(str) - %Q(#{escape_html(str)}) + %Q(#{str}) end def inline_tt(str) - %Q(#{escape_html(str)}) + %Q(#{str}) end def inline_ttb(str) - %Q(#{escape_html(str)}) + %Q(#{str}) end alias_method :inline_ttbold, :inline_ttb def inline_tti(str) - %Q(#{escape_html(str)}) + %Q(#{str}) end def inline_u(str) - %Q(#{escape_html(str)}) + %Q(#{str}) end def inline_icon(id) @@ -750,25 +775,25 @@ def inline_icon(id) end def inline_bou(str) - %Q[#{escape_html(str)}] + %Q[#{str}] end def inline_keytop(str) - %Q[#{escape_html(str)}] + %Q[#{str}] end def inline_labelref(idref) - %Q[「#{I18n.t("label_marker")}#{escape_html(idref)}」] # FIXME:節名とタイトルも込みで要出力 + %Q[「#{I18n.t("label_marker")}#{idref}」] # FIXME:節名とタイトルも込みで要出力 end alias_method :inline_ref, :inline_labelref def inline_pageref(idref) - %Q[●●] # ページ番号を参照 + %Q[●●] # ページ番号を参照 end def inline_balloon(str) - %Q[#{escape_html(str).gsub(/@maru\[(\d+)\]/) {|m| inline_maru($1)}}] + %Q[#{str.gsub(/@maru\[(\d+)\]/) {|m| inline_maru($1)}}] end def inline_uchar(str) @@ -777,45 +802,48 @@ def inline_uchar(str) def inline_m(str) @texinlineequation += 1 - %Q[
      #{escape_html(str)}
      ] + %Q[
      #{str}
      ] end def noindent @noindent = true + "" end def linebreak # FIXME:pが閉じちゃってるので一度戻らないといけないが、難しい…。 - puts "
      " + "
      " + @lf end def pagebreak - puts "" + "" + @lf end def nonum_begin(level, label, caption) - puts %Q[#{compile_inline(caption)}] + %Q[#{caption}] + @lf end def nonum_end(level) end def circle_begin(level, label, caption) - puts %Q[•#{compile_inline(caption)}] + %Q[•#{caption}] + @lf end def circle_end(level) end def common_column_begin(type, caption) + buf = "" @column += 1 a_id = %Q[id="column-#{@column}"] - print "<#{type}column #{a_id}>" - puts %Q[#{compile_inline(caption)}] + buf << "<#{type}column #{a_id}>" + buf << %Q[#{caption}] << @lf + buf end def common_column_end(type) - puts "" + "" + @lf end def column_begin(level, label, caption) @@ -868,42 +896,43 @@ def insideout_end(level) def ref_begin(level, label, caption) if !label.nil? - puts "" + "" + @lf else - puts "" + "" + @lf end end def ref_end(level) - puts "" + "" + @lf end def sup_begin(level, label, caption) if !label.nil? - puts "" + "" + @lf else - puts "" + "" + @lf end end def sup_end(level) - puts "" + "" + @lf end def flushright(lines) - puts split_paragraph(lines).join.gsub("

      ", "

      ") + lines.join("").gsub("

      ", "

      ") + @lf end def centering(lines) - puts split_paragraph(lines).join.gsub("

      ", "

      ") + lines.join("").gsub("

      ", "

      ") + @lf end def captionblock(type, lines, caption, specialstyle = nil) - print "<#{type}>" + buf = "" + buf << "<#{type}>" style = specialstyle.nil? ? "#{type}-title" : specialstyle - puts "#{compile_inline(caption)}" unless caption.nil? - blocked_lines = split_paragraph(lines) - puts "#{blocked_lines.join}" + buf << "#{caption}" + @lf unless caption.nil? + buf << "#{lines.join}" << @lf + buf end def note(lines, caption = nil) @@ -991,8 +1020,9 @@ def expert(lines) end def syntaxblock(type, lines, caption) + buf = "" if caption.nil? - puts %Q[<#{type}>] + buf << %Q[<#{type}>] << @lf else titleopentag = %Q[caption aid:pstyle="#{type}-title"] titleclosetag = "caption" @@ -1000,22 +1030,24 @@ def syntaxblock(type, lines, caption) titleopentag = %Q[floattitle type="insn"] titleclosetag = "floattitle" end - puts %Q[<#{type}><#{titleopentag}>#{compile_inline(caption)}] + buf << %Q[<#{type}><#{titleopentag}>#{caption}] << @lf end no = 1 lines.each do |line| + line.chomp! unless @book.config["listinfo"].nil? - print %Q[] + buf << %Q[] end - print detab(line) - print "\n" - print "" unless @book.config["listinfo"].nil? + buf << detab(line) + buf << "\n" + buf << "" unless @book.config["listinfo"].nil? no += 1 end - puts "" + buf << "" << @lf + buf end def insn(lines, caption = nil) @@ -1027,38 +1059,41 @@ def box(lines, caption = nil) end def indepimage(id, caption=nil, metric=nil) + buf = "" metrics = parse_metric("idgxml", metric) - puts "" + buf << "" << @lf begin - puts %Q[] + buf << %Q[] << @lf rescue warn %Q[no such image: #{id}] end - puts %Q[#{compile_inline(caption)}] if caption.present? - puts "" + buf << %Q[#{caption}] + @lf if caption.present? + buf << "" << @lf + buf end alias_method :numberlessimage, :indepimage def label(id) # FIXME - print "


      " + "
      " end def bpo(lines) - puts %Q[#{lines.join("\n")}] + %Q[#{lines.join("\n")}] + @lf end def inline_dtp(str) @@ -1066,7 +1101,7 @@ def inline_dtp(str) end def inline_code(str) - %Q[#{escape_html(str)}] + %Q[#{str}] end def inline_br(str) @@ -1074,12 +1109,14 @@ def inline_br(str) end def rawblock(lines) + buf = "" no = 1 lines.each do |l| - print l.gsub("<", "<").gsub(">", ">").gsub(""", "\"").gsub("&", "&") - print "\n" unless lines.length == no + buf << l.gsub("<", "<").gsub(">", ">").gsub(""", "\"").gsub("&", "&") + buf << "\n" unless lines.length == no no += 1 end + buf end def text(str) @@ -1132,31 +1169,39 @@ def inline_title(id) end def source_header(caption) - puts %Q[] - puts %Q[#{compile_inline(caption)}] + buf = "" + buf << %Q[] << @lf + buf << %Q[#{caption}] << @lf + buf end def source_body(lines, lang) - puts %Q[
      ]
      -      codelines_body(lines)
      -      puts %Q[
      ] + buf = "" + buf << %Q[
      ] << @lf
      +      buf << codelines_body(lines)
      +      buf << %Q[
      ] << @lf + buf end def bibpaper(lines, id, caption) - bibpaper_header id, caption + buf = "" + buf << bibpaper_header(id, caption) unless lines.empty? - bibpaper_bibpaper id, caption, lines + buf << bibpaper_bibpaper(id, caption, lines) end - puts %Q() + buf << %Q() << @lf + buf end def bibpaper_header(id, caption) - puts %Q() - puts "[#{@chapter.bibpaper(id).number}] #{compile_inline(caption)}" + buf = "" + buf << %Q() << @lf + buf << "[#{@chapter.bibpaper(id).number}] #{caption}" << @lf + buf end def bibpaper_bibpaper(id, caption, lines) - print split_paragraph(lines).join("") + lines.join("") end def inline_bib(id) @@ -1167,15 +1212,15 @@ def inline_hd_chap(chap, id) if chap.number n = chap.headline_index.number(id) if @book.config["secnolevel"] >= n.split('.').size - return I18n.t("chapter_quote", "#{n} #{compile_inline(chap.headline(id).caption)}") + return I18n.t("chapter_quote", "#{n} #{chap.headline(id).caption}") end end - I18n.t("chapter_quote", compile_inline(chap.headline(id).caption)) + I18n.t("chapter_quote", chap.headline(id).caption) end def inline_recipe(id) # FIXME - %Q([XXX]「#{escape_html(id)}」 p.XX) + %Q([XXX]「#{id}」 p.XX) end def nofunc_text(str) diff --git a/lib/review/latexbuilder.rb b/lib/review/latexbuilder.rb index 09b2db90b..1e8d9ceab 100644 --- a/lib/review/latexbuilder.rb +++ b/lib/review/latexbuilder.rb @@ -47,23 +47,10 @@ def blank end private :blank - def print(*s) - if @blank_needed - @output.puts - @blank_needed = false - end - super - end - private :print - - def puts(*s) - if @blank_needed - @output.puts - @blank_needed = false - end - super + def blank_reset + @blank_needed = false end - private :puts + private :blank_reset HEADLINE = { 1 => 'chapter', @@ -75,6 +62,7 @@ def puts(*s) } def headline(level, label, caption) + buf = "" _, anchor = headline_prefix(level) headline_name = HEADLINE[level] if @chapter.kind_of? ReVIEW::Book::Part @@ -84,41 +72,40 @@ def headline(level, label, caption) if level > @book.config["secnolevel"] || (@chapter.number.to_s.empty? && level > 1) prefix = "*" end - blank unless @output.pos == 0 - puts macro(headline_name+prefix, compile_inline(caption)) + buf << macro(headline_name+prefix, caption) << "\n" if prefix == "*" && level <= @book.config["toclevel"].to_i - puts "\\addcontentsline{toc}{#{headline_name}}{#{compile_inline(caption)}}" + buf << "\\addcontentsline{toc}{#{headline_name}}{#{caption}}\n" end if level == 1 - puts macro('label', chapter_label) + buf << macro('label', chapter_label) << "\n" else - puts macro('label', sec_label(anchor)) + buf << macro('label', sec_label(anchor)) << "\n" end + buf rescue error "unknown level: #{level}" end def nonum_begin(level, label, caption) - blank unless @output.pos == 0 - puts macro(HEADLINE[level]+"*", compile_inline(caption)) - puts macro('addcontentsline', 'toc', HEADLINE[level], compile_inline(caption)) + "\n" + macro(HEADLINE[level]+"*", caption) + "\n" + + macro('addcontentsline', 'toc', HEADLINE[level], caption) end def nonum_end(level) end def notoc_begin(level, label, caption) - blank unless @output.pos == 0 - puts macro(HEADLINE[level]+"*", compile_inline(caption)) + "\n" + + macro(HEADLINE[level]+"*", caption) end def notoc_end(level) end def nodisp_begin(level, label, caption) - blank unless @output.pos == 0 - puts macro('clearpage') if @output.pos == 0 - puts macro('addcontentsline', 'toc', HEADLINE[level], compile_inline(caption)) + buf = "\n" + buf << macro('clearpage') if @output.pos == 0 + buf << macro('addcontentsline', 'toc', HEADLINE[level], caption) # FIXME: headings end @@ -126,115 +113,124 @@ def nodisp_end(level) end def column_begin(level, label, caption) + buf = "" blank - puts "\\begin{reviewcolumn}\n" + if @blank_needed + buf << "\n" + blank_reset + end + buf << "\\begin{reviewcolumn}\n" if label - puts "\\hypertarget{#{column_label(label)}}{}" + buf << "\\hypertarget{#{column_label(label)}}{}\n" else - puts "\\hypertarget{#{column_label(caption)}}{}" + buf << "\\hypertarget{#{column_label(caption)}}{}\n" end - puts macro('reviewcolumnhead', nil, compile_inline(caption)) + buf << macro('reviewcolumnhead', nil, caption) << "\n" if level <= @book.config["toclevel"].to_i - puts "\\addcontentsline{toc}{#{HEADLINE[level]}}{#{compile_inline(caption)}}" + buf << "\\addcontentsline{toc}{#{HEADLINE[level]}}{#{caption}}" << "\n" end + buf end def column_end(level) - puts "\\end{reviewcolumn}\n" - blank + buf = "" + buf << "\\end{reviewcolumn}\n" + buf end def captionblock(type, lines, caption) - puts "\\begin{reviewminicolumn}\n" + buf = "" + buf << "\\begin{reviewminicolumn}\n" unless caption.nil? - puts "\\reviewminicolumntitle{#{compile_inline(caption)}}\n" + buf << "\\reviewminicolumntitle{#{caption}}\n" end - blocked_lines = split_paragraph(lines) - puts blocked_lines.join("\n\n") + if lines[0].start_with?("\n") + lines[0].sub!(/\A\n/, "") + end + buf << lines.join("") - puts "\\end{reviewminicolumn}\n" + buf << "\\end{reviewminicolumn}\n" + buf end def box(lines, caption = nil) - blank + buf = "\n" if caption - puts macro('reviewboxcaption', "#{compile_inline(caption)}") + buf << macro('reviewboxcaption', "#{caption}") << "\n" end - puts '\begin{reviewbox}' + buf << '\begin{reviewbox}' << "\n" lines.each do |line| - puts detab(line) - end - puts '\end{reviewbox}' - blank + buf << detab(line) << "\n" + end< + buf << '\end{reviewbox}' << "\n" end def ul_begin - blank - puts '\begin{itemize}' + buf = "\n" + buf << '\begin{itemize}' << "\n" + buf end def ul_item(lines) str = lines.join str.sub!(/\A(\[)/){'\lbrack{}'} - puts '\item ' + str + '\item ' + str + "\n" end def ul_end - puts '\end{itemize}' - blank + '\end{itemize}' + "\n" end def ol_begin - blank - puts '\begin{enumerate}' + buf = "\n" + buf << '\begin{enumerate}' << "\n" if @ol_num - puts "\\setcounter{enumi}{#{@ol_num - 1}}" + buf << "\\setcounter{enumi}{#{@ol_num - 1}}\n" @ol_num = nil end + buf end def ol_item(lines, num) str = lines.join str.sub!(/\A(\[)/){'\lbrack{}'} - puts '\item ' + str + '\item ' + str + "\n" end def ol_end - puts '\end{enumerate}' - blank + '\end{enumerate}' + "\n" end def dl_begin - blank - puts '\begin{description}' + "\n" + '\begin{description}' + "\n" end def dt(str) str.sub!(/\[/){'\lbrack{}'} str.sub!(/\]/){'\rbrack{}'} - puts '\item[' + str + '] \mbox{} \\\\' + '\item[' + str + '] \mbox{} \\\\' + "\n" end def dd(lines) - puts lines.join + lines.join + "\n" end def dl_end - puts '\end{description}' - blank + '\end{description}' + "\n" end def paragraph(lines) - blank + buf = "\n" lines.each do |line| - puts line + buf << line end - blank + buf << "\n" + buf end def parasep - puts '\\parasep' + '\\parasep' + "\n" end def read(lines) @@ -249,67 +245,78 @@ def highlight_listings? private :highlight_listings? def emlist(lines, caption = nil, lang = nil) - blank + buf = "\n" if highlight_listings? - common_code_block_lst(nil, lines, 'reviewemlistlst', 'title', caption, lang) + buf << common_code_block_lst(nil, lines, 'reviewemlistlst', 'title', caption, lang) else - common_code_block(nil, lines, 'reviewemlist', caption, lang) do |line, idx| + buf << common_code_block(nil, lines, 'reviewemlist', caption, lang) do |line, idx| detab(line) + "\n" end end + buf end def emlistnum(lines, caption = nil, lang = nil) - blank + buf = "\n" if highlight_listings? - common_code_block_lst(nil, lines, 'reviewemlistnumlst', 'title', caption, lang) + buf << common_code_block_lst(nil, lines, 'reviewemlistnumlst', 'title', caption, lang) else - common_code_block(nil, lines, 'reviewemlist', caption, lang) do |line, idx| + buf << common_code_block(nil, lines, 'reviewemlist', caption, lang) do |line, idx| detab((idx+1).to_s.rjust(2)+": " + line) + "\n" end end + buf end ## override Builder#list - def list(lines, id, caption, lang = nil) + def list(lines, id, caption = nil, lang = nil) + buf = "" if highlight_listings? - common_code_block_lst(id, lines, 'reviewlistlst', 'caption', caption, lang) + buf << common_code_block_lst(id, lines, 'reviewlistlst', 'caption', caption, lang) else - common_code_block(id, lines, 'reviewlist', caption, lang) do |line, idx| + buf << common_code_block(id, lines, 'reviewlist', caption, lang) do |line, idx| detab(line) + "\n" end end + buf end + ## override Builder#listnum - def listnum(lines, id, caption, lang = nil) + def listnum(lines, id, caption = nil, lang = nil) + buf = "" if highlight_listings? - common_code_block_lst(id, lines, 'reviewlistnumlst', 'caption', caption, lang) + buf << common_code_block_lst(id, lines, 'reviewlistnumlst', 'caption', caption, lang) else - common_code_block(id, lines, 'reviewlist', caption, lang) do |line, idx| + buf << common_code_block(id, lines, 'reviewlist', caption, lang) do |line, idx| detab((idx+1).to_s.rjust(2)+": " + line) + "\n" end end + buf end def cmd(lines, caption = nil, lang = nil) + buf = "" if highlight_listings? - common_code_block_lst(nil, lines, 'reviewcmdlst', 'title', caption, lang) + buf << common_code_block_lst(nil, lines, 'reviewcmdlst', 'title', caption, lang) else - blank - common_code_block(nil, lines, 'reviewcmd', caption, lang) do |line, idx| + buf << "\n" + buf << common_code_block(nil, lines, 'reviewcmd', caption, lang) do |line, idx| detab(line) + "\n" end end + buf end def common_code_block(id, lines, command, caption, lang) + buf = "" if caption if command =~ /emlist/ || command =~ /cmd/ - puts macro(command + 'caption', "#{compile_inline(caption)}") + buf << macro(command + 'caption', "#{caption}") + "\n" else begin - puts macro('reviewlistcaption', "#{I18n.t("list")}#{I18n.t("format_number_header", [@chapter.number, @chapter.list(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}") + buf << "\n" + buf << macro('reviewlistcaption', "#{I18n.t("list")}#{I18n.t("format_number_header", [@chapter.number, @chapter.list(id).number])}#{I18n.t("caption_prefix")}#{caption}") + "\n" rescue KeyError error "no such list: #{id}" end @@ -319,17 +326,18 @@ def common_code_block(id, lines, command, caption, lang) lines.each_with_index do |line, idx| body.concat(yield(line, idx)) end - puts macro('begin' ,command) - print body - puts macro('end' ,command) - blank + buf << macro('begin' ,command) + "\n" + buf << body + buf << macro('end' ,command) + "\n" + buf end def common_code_block_lst(id, lines, command, title, caption, lang) - caption_str = compile_inline((caption || "")) + buf = "" + caption_str = (caption || "") if title == "title" && caption_str == "" caption_str = "\\relax" ## dummy charactor to remove lstname - print "\\vspace{-1.5em}" + buf << "\\vspace{-1.5em}" end if @book.config["highlight"] && @book.config["highlight"]["lang"] lexer = @book.config["highlight"]["lang"] # default setting @@ -338,24 +346,36 @@ def common_code_block_lst(id, lines, command, title, caption, lang) end lexer = lang if lang.present? body = lines.inject(''){|i, j| i + detab(unescape_latex(j)) + "\n"} - puts "\\begin{"+command+"}["+title+"={"+caption_str+"},language={"+ lexer+"}]" - print body - puts "\\end{"+ command + "}" - blank + buf << "\\begin{"+command+"}["+title+"={"+caption_str+"},language={"+ lexer+"}]" + "\n" + buf << body + buf << "\\end{"+ command + "}" + "\n" + buf end - def source(lines, caption, lang = nil) + def source(lines, caption = nil, lang = nil) if highlight_listings? common_code_block_lst(nil, lines, 'reviewlistlst', 'title', caption, lang) else - puts '\begin{reviewlist}' - puts macro('reviewlistcaption', compile_inline(caption)) - lines.each do |line| - puts detab(line) - end - puts '\end{reviewlist}' - puts "" + buf = "\n" + buf << '\begin{reviewlist}' << "\n" + buf << source_header(caption) + buf << source_body(lines) + buf << '\end{reviewlist}' << "\n" + buf << "\n" + buf + end + end + + def source_header(caption) + macro('reviewlistcaption', caption) + "\n" + end + + def source_body(lines) + buf = "" + lines.each do |line| + buf << detab(line) << "\n" end + buf end @@ -374,31 +394,34 @@ def result_metric(array) end def image_image(id, caption, metric) + buf = "" metrics = parse_metric("latex", metric) # image is always bound here - puts '\begin{reviewimage}' + buf << '\begin{reviewimage}' << "\n" if metrics.present? - puts "\\includegraphics[#{metrics}]{#{@chapter.image(id).path}}" + buf << "\\includegraphics[#{metrics}]{#{@chapter.image(id).path}}\n" else - puts "\\includegraphics[width=\\maxwidth]{#{@chapter.image(id).path}}" + buf << "\\includegraphics[width=\\maxwidth]{#{@chapter.image(id).path}}\n" end if caption.present? - puts macro('caption', compile_inline(caption)) + buf << macro('caption', caption) << "\n" end - puts macro('label', image_label(id)) - puts '\end{reviewimage}' + buf << macro('label', image_label(id)) << "\n" + buf << '\end{reviewimage}' << "\n" + buf end def image_dummy(id, caption, lines) - puts '\begin{reviewdummyimage}' + buf << '\begin{reviewdummyimage}' << "\n" path = @chapter.image(id).path - puts "--[[path = #{path} (#{existence(id)})]]--" + buf << "--[[path = #{path} (#{existence(id)})]]--\n" lines.each do |line| - puts detab(line.rstrip) + buf << detab(line.rstrip) << "\n" end - puts macro('label', image_label(id)) - puts compile_inline(caption) - puts '\end{reviewdummyimage}' + buf << macro('label', image_label(id)) << "\n" + buf << caption << "\n" + buf << '\end{reviewdummyimage}' << "\n" + buf end def existence(id) @@ -441,23 +464,34 @@ def column_label(id) private :column_label def indepimage(id, caption=nil, metric=nil) + buf = "" metrics = parse_metric("latex", metric) - puts '\begin{reviewimage}' + buf << '\begin{reviewimage}' << "\n" if metrics.present? - puts "\\includegraphics[#{metrics}]{#{@chapter.image(id).path}}" + buf << "\\includegraphics[#{metrics}]{#{@chapter.image(id).path}}\n" else - puts "\\includegraphics[width=\\maxwidth]{#{@chapter.image(id).path}}" + buf << "\\includegraphics[width=\\maxwidth]{#{@chapter.image(id).path}}\n" end if caption.present? - puts macro('reviewindepimagecaption', - %Q[#{I18n.t("numberless_image")}#{I18n.t("caption_prefix")}#{compile_inline(caption)}]) + buf << macro('reviewindepimagecaption', + %Q[#{I18n.t("numberless_image")}#{I18n.t("caption_prefix")}#{caption}]) << "\n" end - puts '\end{reviewimage}' + buf << '\end{reviewimage}' << "\n" + buf end alias_method :numberlessimage, :indepimage - def table(lines, id = nil, caption = nil) + def node_table(node) + id_node = node.args[0] + id = id_node ? id_node.to_raw : "" + caption_node = node.args[1] + caption = caption_node ? caption_node.to_doc : "" + lines = [] + node.content.each do |line| + lines << line.to_doc + end + buf = "" rows = [] sepidx = nil lines.each_with_index do |line, idx| @@ -472,49 +506,56 @@ def table(lines, id = nil, caption = nil) rows = adjust_n_cols(rows) begin - table_header id, caption unless caption.nil? + buf << table_header(id, caption) unless caption.nil? rescue KeyError error "no such table: #{id}" end - return if rows.empty? - table_begin rows.first.size + return buf if rows.empty? + buf << table_begin(rows.first.size) if sepidx sepidx.times do - tr rows.shift.map {|s| th(s) } + buf << tr(rows.shift.map {|s| th(s) }) end rows.each do |cols| - tr cols.map {|s| td(s) } + buf << tr(cols.map {|s| td(s) }) end else rows.each do |cols| h, *cs = *cols - tr [th(h)] + cs.map {|s| td(s) } + buf << tr([th(h)] + cs.map {|s| td(s) }) end end - table_end + buf << table_end + buf end def table_header(id, caption) + buf = "" if caption.present? @table_caption = true - puts '\begin{table}[h]' - puts macro('reviewtablecaption', compile_inline(caption)) + buf << '\begin{table}[h]' << "\n" + buf << macro('reviewtablecaption', caption) << "\n" end - puts macro('label', table_label(id)) + if id.present? + buf << macro('label', table_label(id)) << "\n" + end + buf end def table_begin(ncols) + buf = "" if @latex_tsize - puts macro('begin', 'reviewtable', @latex_tsize) + buf << macro('begin', 'reviewtable', @latex_tsize) << "\n" elsif @tsize cellwidth = @tsize.split(/\s*,\s*/) - puts macro('begin', 'reviewtable', '|'+cellwidth.collect{|i| "p{#{i}mm}"}.join('|')+'|') + buf << macro('begin', 'reviewtable', '|'+cellwidth.collect{|i| "p{#{i}mm}"}.join('|')+'|') << "\n" else - puts macro('begin', 'reviewtable', (['|'] * (ncols + 1)).join('l')) + buf << macro('begin', 'reviewtable', (['|'] * (ncols + 1)).join('l')) << "\n" end - puts '\hline' + buf << '\hline' << "\n" @tsize = nil @latex_tsize = nil + buf end def table_separator @@ -540,53 +581,59 @@ def td(s) end def tr(rows) - print rows.join(' & ') - puts ' \\\\ \hline' + buf = "" + buf << rows.join(' & ') + buf << ' \\\\ \hline' << "\n" + buf end def table_end - puts macro('end', 'reviewtable') + buf = "" + buf << macro('end', 'reviewtable') << "\n" if @table_caption - puts '\end{table}' + buf << '\end{table}' << "\n" end @table_caption = nil - blank + buf end def imgtable(lines, id, caption = nil, metric = nil) if !@chapter.image(id).bound? warn "image not bound: #{id}" - image_dummy id, caption, lines - return + return image_dummy(id, caption, lines) end + buf = "" + begin if caption.present? @table_caption = true - puts '\begin{table}[h]' - puts macro('reviewimgtablecaption', compile_inline(caption)) + buf << '\begin{table}[h]' + "\n" + buf << macro('reviewimgtablecaption', caption) + "\n" end - puts macro('label', table_label(id)) + buf << macro('label', table_label(id)) + "\n" rescue ReVIEW::KeyError error "no such table: #{id}" end - imgtable_image(id, caption, metric) + buf << imgtable_image(id, caption, metric) - puts '\end{table}' if @table_caption + buf << '\end{table}' + "\n" if @table_caption @table_caption = nil - blank + buf end def imgtable_image(id, caption, metric) metrics = parse_metric("latex", metric) # image is always bound here - puts '\begin{reviewimage}' + buf = "" + buf << '\begin{reviewimage}' + "\n" if metrics.present? - puts "\\includegraphics[#{metrics}]{#{@chapter.image(id).path}}" + buf << "\\includegraphics[#{metrics}]{#{@chapter.image(id).path}}" + "\n" else - puts "\\includegraphics[width=\\maxwidth]{#{@chapter.image(id).path}}" + buf << "\\includegraphics[width=\\maxwidth]{#{@chapter.image(id).path}}" + "\n" end - puts '\end{reviewimage}' + buf << '\end{reviewimage}' + "\n" + buf end def quote(lines) @@ -604,63 +651,73 @@ def flushright(lines) end def texequation(lines) - blank - puts macro('begin','equation*') + buf = "\n" + buf << macro('begin','equation*') << "\n" lines.each do |line| - puts unescape_latex(line) + buf << unescape_latex(line) << "\n" end - puts macro('end', 'equation*') - blank + buf << macro('end', 'equation*') << "\n" + buf << "\n" + buf end def latex_block(type, lines) - blank - puts macro('begin', type) - blocked_lines = split_paragraph(lines) - puts blocked_lines.join("\n\n") - puts macro('end', type) - blank + buf = "\n" + buf << macro('begin', type) + buf << lines.join("") + buf << macro('end', type) << "\n" + buf end private :latex_block def direct(lines, fmt) - return unless fmt == 'latex' + buf = "" + return buf unless fmt == 'latex' lines.each do |line| - puts line + buf << line << "\n" end + buf end def comment(lines, comment = nil) + buf = "" lines ||= [] lines.unshift comment unless comment.blank? if @book.config["draft"] str = lines.join("") - puts macro('pdfcomment', escape(str)) + buf << macro('pdfcomment', str) << "\n" end + buf end def hr - puts '\hrule' + '\hrule' + "\n" end def label(id) - puts macro('label', id) + macro('label', id) + "\n" + end + + def node_label(node) + id = node.args[0].to_raw + macro('label', id) + "\n" end def pagebreak - puts '\pagebreak' + '\pagebreak' + "\n" end def linebreak - puts '\\\\' + '\\\\' + "\n" end def noindent - print '\noindent' + '\noindent' end - def inline_chapref(id) - title = super + def node_inline_chapref(node) + id = node[0].to_raw + title = @book.chapter_index.display_string(id) if @book.config["chapterlink"] "\\hyperref[chap:#{id}]{#{title}}" else @@ -671,7 +728,8 @@ def inline_chapref(id) nofunc_text("[UnknownChapter:#{id}]") end - def inline_chap(id) + def node_inline_chap(node) + id = node[0].to_raw if @book.config["chapterlink"] "\\hyperref[chap:#{id}]{#{@book.chapter_index.number(id)}}" else @@ -682,8 +740,9 @@ def inline_chap(id) nofunc_text("[UnknownChapter:#{id}]") end - def inline_title(id) - title = super + def node_inline_title(node) + id = node[0].to_raw + title = @book.chapter_index.title(id) if @book.config["chapterlink"] "\\hyperref[chap:#{id}]{#{title}}" else @@ -696,33 +755,37 @@ def inline_title(id) # FIXME: use TeX native label/ref. - def inline_list(id) + def node_inline_list(node) + id = node[0].to_raw chapter, id = extract_chapter_id(id) macro('reviewlistref', "#{chapter.number}.#{chapter.list(id).number}") end - def inline_table(id) + def node_inline_table(node) + id = node[0].to_raw chapter, id = extract_chapter_id(id) macro('reviewtableref', "#{chapter.number}.#{chapter.table(id).number}", table_label(id, chapter)) end - def inline_img(id) + def node_inline_img(node) + id = node[0].to_raw chapter, id = extract_chapter_id(id) macro('reviewimageref', "#{chapter.number}.#{chapter.image(id).number}", image_label(id, chapter)) end def footnote(id, content) if @book.config["footnotetext"] - puts macro("footnotetext[#{@chapter.footnote(id).number}]", - compile_inline(content.strip)) + macro("footnotetext[#{@chapter.footnote(id).number}]", + content.strip) + "\n" end end - def inline_fn(id) + def node_inline_fn(node) + id = node[0].to_raw if @book.config["footnotetext"] macro("footnotemark[#{@chapter.footnote(id).number}]", "") else - macro('footnote', compile_inline(@chapter.footnote(id).content.strip)) + macro('footnote', @chapter.footnote(id).content.strip) end end @@ -733,12 +796,16 @@ def inline_bou(str) end def compile_ruby(base, ruby) - macro('ruby', escape(base), escape(ruby)) + macro('ruby', base, ruby) end # math - def inline_m(str) - " $#{str}$ " +# def inline_m(str) +# " $#{str}$ " +# end + + def node_inline_m(node) + " $#{node[0].to_raw}$ " end # hidden index @@ -748,7 +815,7 @@ def inline_hi(str) # index -> italic def inline_i(str) - macro('textit', escape(str)) + macro('textit', str) end # index @@ -756,14 +823,24 @@ def inline_idx(str) escape(str) + index(str) end + def node_inline_idx(nodelist) + content = nodelist[0].to_raw + escape(content) + index(content) + end + # hidden index?? def inline_hidx(str) index(str) end + def node_inline_hidx(nodelist) + content = nodelist[0].to_raw + index(content) + end + # bold def inline_b(str) - macro('textbf', escape(str)) + macro('textbf', str) end # line break @@ -778,7 +855,7 @@ def inline_dtp(str) ## @ is same as @ def inline_code(str) - macro('texttt', escape(str)) + macro('texttt', str) end def nofunc_text(str) @@ -786,44 +863,46 @@ def nofunc_text(str) end def inline_tt(str) - macro('texttt', escape(str)) + macro('texttt', str) end def inline_del(str) - macro('reviewstrike', escape(str)) + macro('reviewstrike', str) end def inline_tti(str) - macro('texttt', macro('textit', escape(str))) + macro('texttt', macro('textit', str)) end def inline_ttb(str) - macro('texttt', macro('textbf', escape(str))) + macro('texttt', macro('textbf', str)) end - def inline_bib(id) + def node_inline_bib(node) + id = node[0].to_raw macro('reviewbibref', "[#{@chapter.bibpaper(id).number}]", bib_label(id)) end def inline_hd_chap(chap, id) n = chap.headline_index.number(id) if chap.number and @book.config["secnolevel"] >= n.split('.').size - str = I18n.t("chapter_quote", "#{chap.headline_index.number(id)} #{compile_inline(chap.headline(id).caption)}") + str = I18n.t("chapter_quote", "#{chap.headline_index.number(id)} #{chap.headline(id).caption}") else - str = I18n.t("chapter_quote", compile_inline(chap.headline(id).caption)) + str = I18n.t("chapter_quote", chap.headline(id).caption) end if @book.config["chapterlink"] anchor = n.gsub(/\./, "-") - macro('reviewsecref', str, sec_label(anchor)) + macro('reviewsecref', escape(str), sec_label(anchor)) else - str + escape(str) end end - def inline_column_chap(chapter, id) + def node_inline_column(node) + id = node[0].to_raw macro('reviewcolumnref', - I18n.t("chapter_quote", compile_inline(chapter.column(id).caption)), - column_label(id)) + I18n.t("chapter_quote", compile_inline(@chapter.column(id).caption)), + column_label(id)) end def inline_raw(str) @@ -831,19 +910,19 @@ def inline_raw(str) end def inline_sub(str) - macro('textsubscript', escape(str)) + macro('textsubscript', str) end def inline_sup(str) - macro('textsuperscript', escape(str)) + macro('textsuperscript', str) end def inline_em(str) - macro('reviewem', escape(str)) + macro('reviewem', str) end def inline_strong(str) - macro('reviewstrong', escape(str)) + macro('reviewstrong', str) end def inline_u(str) @@ -851,16 +930,17 @@ def inline_u(str) end def inline_ami(str) - macro('reviewami', escape(str)) + macro('reviewami', str) end - def inline_icon(id) + def node_inline_icon(node) + id = node[0].to_raw macro('includegraphics', @chapter.image(id).path) end def inline_uchar(str) # with otf package - macro('UTF', escape(str)) + macro('UTF', str) end def inline_comment(str) @@ -871,50 +951,48 @@ def inline_comment(str) end end + def bibpaper(lines, id, caption) + buf = "" + buf << bibpaper_header(id, caption) + if lines.empty? + buf << "\n" + else + buf << "\n" + buf << bibpaper_bibpaper(id, caption, lines) + end + buf << "\n" + buf + end + def inline_tcy(str) - macro('rensuji', escape(str)) + macro('rensuji', str) end def bibpaper_header(id, caption) - puts "[#{@chapter.bibpaper(id).number}] #{compile_inline(caption)}" - puts macro('label', bib_label(id)) + "[#{@chapter.bibpaper(id).number}] #{caption}\n" + + macro('label', bib_label(id)) end def bibpaper_bibpaper(id, caption, lines) - print split_paragraph(lines).join("") - puts "" + lines.join("") end def index(str) - str.sub!(/\(\)/, '') - decl = '' - if /@\z/ =~ str - str.chop! - decl = '|IndexDecl' - end - unless /[^ -~]/ =~ str - if /\^/ =~ str - macro('index', escape_index(str.gsub(/\^/, '')) + '@' + escape_index(text(str)) + decl) - else - '\index{' + escape_index(text(str)) + decl + '}' - end - else - '\index{' + escape_index(@index_db[str]) + '@' + escape_index(text(str)) + '}' - end + "\\index{" + str + "}" end def compile_kw(word, alt) if alt - macro('reviewkw', escape(word)) + "(#{escape(alt.strip)})" + macro('reviewkw', word) + "(#{alt.strip})" else - macro('reviewkw', escape(word)) + macro('reviewkw', word) end end def compile_href(url, label) if /\A[a-z]+:/ =~ url if label - macro("href", escape_url(url), escape(label)) + macro("href", escape_url(url), label) else macro("url", escape_url(url)) end diff --git a/lib/review/location.rb b/lib/review/location.rb new file mode 100644 index 000000000..662aa3df7 --- /dev/null +++ b/lib/review/location.rb @@ -0,0 +1,24 @@ +module ReVIEW + class Location + def initialize(filename, compiler) + @filename = filename + @f = compiler + end + + attr_reader :filename + + def lineno + @f.current_line + end + + def string + begin + "#{@filename}:#{self.lineno}" + rescue + "#{@filename}:nil" + end + end + + alias_method :to_s, :string + end +end diff --git a/lib/review/markdownbuilder.rb b/lib/review/markdownbuilder.rb index 0be8399b7..fa258eb17 100644 --- a/lib/review/markdownbuilder.rb +++ b/lib/review/markdownbuilder.rb @@ -24,117 +24,152 @@ def builder_init_file end private :builder_init_file - def puts(str) + def blank_reset @blank_seen = false - super end +# def puts(str) +# @blank_seen = false +# "#{str}\n" +# end + def blank - @output.puts unless @blank_seen + buf = "" + unless @blank_seen + buf = "\n" + end @blank_seen = true + buf end def headline(level, label, caption) - blank + buf = "" + buf << blank prefix = "#" * level - puts "#{prefix} #{caption}" - blank + buf << "#{prefix} #{caption}\n" + blank_reset + buf << "\n" + buf end def quote(lines) - blank - puts split_paragraph(lines).map{|line| "> #{line}"}.join("\n> \n") - blank + buf = "" + buf << blank + buf << lines.map{|line| line.chomp!;line.chomp!;"> #{line}"}.join("\n") << "\n" + blank_reset + buf << "\n" + buf end def paragraph(lines) - puts lines.join - puts "\n" + buf = lines.join << "\n" + blank_reset + buf << "\n" + buf end def list_header(id, caption, lang) + lang ||= "" if get_chap.nil? - print %Q[リスト#{@chapter.list(id).number} #{compile_inline(caption)}\n\n] + %Q[リスト#{@chapter.list(id).number} #{compile_inline(caption)}\n\n] + "```#{lang}\n" else - print %Q[リスト#{get_chap}.#{@chapter.list(id).number} #{compile_inline(caption)}\n\n] + %Q[リスト#{get_chap}.#{@chapter.list(id).number} #{compile_inline(caption)}\n\n] + "```#{lang}\n" end - lang ||= "" - puts "```#{lang}" end def list_body(id, lines, lang) + buf = "" lines.each do |line| - puts detab(line) + buf << detab(line) << "\n" end - puts '```' + buf << '```' << "\n" + buf end def ul_begin - blank if @ul_indent == 0 + buf = "" + buf << blank if @ul_indent == 0 @ul_indent += 1 + buf end def ul_item(lines) - puts " " * (@ul_indent - 1) + "* " + "#{lines.join}" + blank_reset + " " * (@ul_indent - 1) + "* " + "#{lines.join}" + "\n" end def ul_item_begin(lines) - puts " " * (@ul_indent - 1) + "* " + "#{lines.join}" + blank_reset + " " * (@ul_indent - 1) + "* " + "#{lines.join}" + "\n" end def ul_item_end + "" end def ul_end + buf = "" @ul_indent -= 1 - blank if @ul_indent == 0 + buf << blank if @ul_indent == 0 + buf end def ol_begin - blank + buf = "" + buf << blank + buf end def ol_item(lines, num) - puts "#{num}. #{lines.join}" + buf = "" + buf << "#{num}. #{lines.join}" << "\n" + blank_reset + buf end def ol_end - blank + buf = "" + buf << blank + buf end def dl_begin - puts '
      ' + "
      \n" end def dt(line) - puts "
      #{line}
      " + "
      #{line}
      \n" end def dd(lines) - puts "
      #{lines.join}
      " + "
      #{lines.join}
      \n" end def dl_end - puts '
      ' + "
      \n" end def emlist(lines, caption = nil, lang = nil) - blank + buf = "" + buf << blank if caption - puts caption - print "\n" + buf << caption << "\n\n" end lang ||= "" - puts "```#{lang}" + buf << "```#{lang}\n" + blank_reset lines.each do |line| - puts detab(line) + buf << detab(line) << "\n" end - puts "```" - blank + buf << "```\n" + buf << blank + buf end def hr - puts "----" + buf << "----\n" + blank_reset + buf end def compile_href(url, label) @@ -168,45 +203,60 @@ def inline_tt(str) def image_image(id, caption, metric) - blank - puts "![#{compile_inline(caption)}](#{@chapter.image(id).path.sub(/\A\.\//, "")})" - blank + buf = "" + buf << blank + buf << "![#{compile_inline(caption)}](#{@chapter.image(id).path.sub(/\A\.\//, "")})" << "\n" + blank_reset + buf << blank + buf end def image_dummy(id, caption, lines) - puts lines.join + buf = "" + buf << lines.join << "\n" + blank_reset + buf end def inline_img(id) "#{I18n.t("image")}#{@chapter.image(id).number}" rescue KeyError error "unknown image: #{id}" - nofunc_text("[UnknownImage:#{id}]") + "[UnknownImage:#{id}]" end def indepimage(id, caption="", metric=nil) - blank - puts "![#{compile_inline(caption)}](#{@chapter.image(id).path.sub(/\A\.\//, "")})" - blank + buf = "" + buf << blank + buf << "![#{compile_inline(caption)}](#{@chapter.image(id).path.sub(/\A\.\//, "")})" << "\n" + blank_reset + buf << blank + buf end def pagebreak - puts "{pagebreak}" + buf = "" + buf << "{pagebreak}" << "\n" + buf end def image_ext "jpg" end - def cmd(lines) - puts "```shell-session" + def cmd(lines, caption = nil) + buf = "" + buf << "```shell-session" << "\n" + blank_reset lines.each do |line| - puts detab(line) + buf << detab(line) << "\n" end - puts "```" + buf << "```" << "\n" + buf end def table(lines, id = nil, caption = nil) + buf = "" rows = [] sepidx = nil lines.each_with_index do |line, idx| @@ -216,52 +266,58 @@ def table(lines, id = nil, caption = nil) sepidx ||= idx next end - rows.push line.strip.split(/\t+/).map {|s| s.sub(/\A\./, '') } + rows.push line.strip.split(/\t+/).map{|s| s.sub(/\A\./, '') } end rows = adjust_n_cols(rows) begin - table_header id, caption unless caption.nil? + buf << table_header(id, caption) unless caption.nil? rescue KeyError error "no such table: #{id}" end - table_begin rows.first.size - return if rows.empty? + buf << table_begin(rows.first.size) + return buf if rows.empty? if sepidx sepidx.times do - tr rows.shift.map {|s| th(s) } + buf << tr(rows.shift.map{|s| th(s) }) end - table_border rows.first.size + buf << table_border(rows.first.size) rows.each do |cols| - tr cols.map {|s| td(s) } + buf << tr(cols.map{|s| td(s) }) end else rows.each do |cols| h, *cs = *cols - tr [th(h)] + cs.map {|s| td(s) } + tr([th(h)] + cs.map {|s| td(s) }) end end - table_end + buf << table_end + buf end def table_header(id, caption) + buf = "" if get_chap.nil? - puts %Q[#{I18n.t("table")}#{I18n.t("format_number_header_without_chapter", [@chapter.table(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}] + buf << %Q[#{I18n.t("table")}#{I18n.t("format_number_header_without_chapter", [@chapter.table(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}] << "\n" else - puts %Q[#{I18n.t("table")}#{I18n.t("format_number_header", [get_chap, @chapter.table(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}] + buf << %Q[#{I18n.t("table")}#{I18n.t("format_number_header", [get_chap, @chapter.table(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}] << "\n" end - blank + blank_reset + buf << blank + buf end def table_begin(ncols) + "" end def tr(rows) - puts "|#{rows.join("|")}|" + "|#{rows.join("|")}|\n" end def table_border(ncols) - puts (0..ncols).map{"|"}.join(":--") + blank_reset + (0..ncols).map{"|"}.join(":--") + "\n" end def th(str) @@ -273,12 +329,17 @@ def td(str) end def table_end - blank + buf = "" + buf << blank + buf end def footnote(id, str) - puts "[^#{id}]: #{compile_inline(str)}" - blank + buf = "" + buf << "[^#{id}]: #{compile_inline(str)}" << "\n" + blank_reset + buf << blank + buf end def inline_fn(id) @@ -295,9 +356,9 @@ def nofunc_text(str) def compile_ruby(base, ruby) if @book.htmlversion == 5 - %Q[#{escape_html(base)}#{I18n.t("ruby_prefix")}#{escape_html(ruby)}#{I18n.t("ruby_postfix")}] + %Q[#{base}#{I18n.t("ruby_prefix")}#{ruby}#{I18n.t("ruby_postfix")}] else - %Q[#{escape_html(base)}#{I18n.t("ruby_prefix")}#{ruby}#{I18n.t("ruby_postfix")}] + %Q[#{base}#{I18n.t("ruby_prefix")}#{ruby}#{I18n.t("ruby_postfix")}] end end diff --git a/lib/review/md2inaobuilder.rb b/lib/review/md2inaobuilder.rb index 4dc290abf..6eec427fa 100644 --- a/lib/review/md2inaobuilder.rb +++ b/lib/review/md2inaobuilder.rb @@ -9,48 +9,54 @@ module ReVIEW class MD2INAOBuilder < MARKDOWNBuilder def paragraph(lines) - puts " " + lines.join - puts "\n" + ## XXX fix; do not use fullwidth space + buf = " " + lines.join << "\n" + blank_reset + buf << "\n" + buf end def list_header(id, caption, lang) lang ||= "" - puts "```#{lang}" - print %Q[●リスト#{@chapter.list(id).number}::#{compile_inline(caption)}\n\n] + buf = "```#{lang}\n" + buf << %Q[●リスト#{@chapter.list(id).number}::#{compile_inline(caption)}\n\n] + buf end def cmd(lines) # WEB+DB では使っていないらしいけど - puts "!!! cmd" + buf = "!!! cmd\n" lines.each do |line| - puts detab(line) + buf << detab(line) + "\n" end - puts "" + buf << "\n" + buf end def dl_begin - puts '
      ' + "
      \n" end def dt(line) - puts "
      #{line}
      " + "
      #{line}
      \n" end def dd(lines) - puts "
      #{lines.join}
      " + "
      #{lines.join}
      \n" end def dl_end - puts '
      ' + "
      \n" end def comment(lines, comment = nil) lines ||= [] lines.unshift comment unless comment.blank? str = lines.join("\n") - puts '' - puts str - puts '' + buf = '' + "\n" + buf << str + "\n" + buf << '' + "\n" + buf end def compile_ruby(base, ruby) diff --git a/lib/review/node.rb b/lib/review/node.rb new file mode 100644 index 000000000..2d9fe6dcd --- /dev/null +++ b/lib/review/node.rb @@ -0,0 +1,288 @@ +require 'json' + +module ReVIEW + class Node + attr_accessor :content + + def to_raw + to_s_by(:to_raw) + end + + def to_doc + to_s_by(:to_doc) + end + + def to_s_by(meth) + if content.kind_of? String + @content + elsif content.nil? + nil + elsif !content.kind_of? Array + @content.__send__(meth) + else + ##@content.map(&meth).join("") + @content.map{|o| o.__send__(meth)}.join("") + end + end + + def to_json(*args) + if content.kind_of? String + val = '"'+@content.gsub(/\"/,'\\"').gsub(/\n/,'\\n')+'"' + elsif content.nil? + val = "null" + elsif !content.kind_of? Array + val = @content.to_json + else + val = "["+@content.map(&:to_json).join(",")+"]" + end + '{"ruleName":"' + self.class.to_s.sub(/ReVIEW::/,"").sub(/Node$/,"") + '",' + + "\"offset\":#{position.pos},\"line\":#{position.line},\"column\":#{position.col}," + + '"childNodes":' + val + + '}' + end + + def inspect + self.to_json + end + + end + + class HeadlineNode < Node + + def to_doc + content_str = super + cmd = @cmd ? @cmd.to_doc : nil + label = @label + @compiler.compile_headline(@level, cmd, label, content_str) + end + + def to_json + '{"ruleName":"' + self.class.to_s.sub(/ReVIEW::/,"").sub(/Node$/,"") + '",' + + %Q|"cmd":"#{@cmd.to_json}",|+ + %Q|"label":"#{@label.to_json}",|+ + "\"offset\":#{position.pos},\"line\":#{position.line},\"column\":#{position.col}," + + '"childNodes":' + @content.to_json + '}' + end + end + + class ParagraphNode < Node + + def to_doc + #content = @content.map(&:to_doc) + content = super.split(/\n/) + @compiler.compile_paragraph(content) + end + end + + class BlockElementNode < Node + + def to_doc + # content_str = super + args = @args.map(&:to_doc) + if @content + content_lines = @content.map(&:to_doc) + else + content_lines = nil + end + @compiler.compile_command(@name, @args, content_lines, self) + end + + def parse_args(*patterns) + patterns.map.with_index do |pattern, i| + if @args[i] + @args[i].__send__("to_#{pattern}") + else + nil + end + end + end + end + + class CodeBlockElementNode < Node + + def to_doc + # content_str = super + args = @args.map(&:to_doc) + if @content + content_lines = raw_lines + else + content_lines = nil + end + @compiler.compile_command(@name, @args, content_lines, self) + end + + def parse_args(*patterns) + patterns.map.with_index do |pattern, i| + if @args[i] + @args[i].__send__("to_#{pattern}") + else + nil + end + end + end + + def raw_lines + self.content.to_doc.split(/\n/) + end + end + + + class InlineElementNode < Node + def to_raw + content_str = super + "@<#{@symbol}>{#{content_str}}" + end + + def to_doc + #content_str = super + @compiler.compile_inline(@symbol, @content) + end + + def to_json + '{"ruleName":"' + self.class.to_s.sub(/ReVIEW::/,"").sub(/Node$/,"") + '",' + + %Q|"symbol":"#{@symbol}",| + + "\"offset\":#{position.pos},\"line\":#{position.line},\"column\":#{position.col}," + + (@concat ? '"childNodes":[' + @content.map(&:to_json).join(",") + ']' : '"childNodes":[]') + '}' + end + end + + class ComplexInlineElementNode < Node + def to_raw + content_str = super + "@<#{@symbol}>{#{content_str}}" + end + + def to_doc + #content_str = super + @compiler.compile_inline(@symbol, @content) + end + + def to_json + '{"ruleName":"' + self.class.to_s.sub(/ReVIEW::/,"").sub(/Node$/,"") + '",' + + %Q|"symbol":"#{@symbol}",| + + "\"offset\":#{position.pos},\"line\":#{position.line},\"column\":#{position.col}," + + '"childNodes":[' + @content.map(&:to_json).join(",") + ']}' + end + end + + class InlineElementContentNode < Node + end + + class ComplexInlineElementContentNode < Node + end + + class TextNode < Node + + def to_raw + content_str = super + content_str.to_s + end + + def to_doc + content_str = super + @compiler.compile_text(content_str) + end + + def to_json(*args) + val = '"'+@content.gsub(/\"/,'\\"').gsub(/\n/,'\\n')+'"' + '{"ruleName":"' + self.class.to_s.sub(/ReVIEW::/,"").sub(/Node$/,"") + '",' + + "\"offset\":#{position.pos},\"line\":#{position.line},\"column\":#{position.col}," + + '"text":' + val + '}' + end + end + + class NewLineNode < Node + + def to_doc + "" + end + end + + class RawNode < Node + + def to_doc + @compiler.compile_raw(@builder, @content.join("")) + end + end + + class BracketArgNode < Node + end + + class BraceArgNode < Node + end + + class SinglelineCommentNode < Node + def to_doc + "" + end + end + + class SinglelineContentNode < Node + end + + class UlistNode < Node + def to_doc + @compiler.compile_ulist(@content) + end + end + + class UlistElementNode < Node + def level=(level) + @level = level + end + + def to_doc + @content.map(&:to_doc).join("") + end + + def concat(elem) + @content << elem + end + end + + class OlistNode < Node + def to_doc + @compiler.compile_olist(@content) + end + end + + class OlistElementNode < Node + def num=(num) + @num = num + end + + def to_doc + @content.map(&:to_doc).join("") + end + + def concat(elem) + @content << elem + end + end + + class DlistNode < Node + def to_doc + @compiler.compile_dlist(@content) + end + end + + class DlistElementNode < Node + def to_doc + @content.map(&:to_doc).join("") + end + end + + class DocumentNode < Node + end + + class ColumnNode < Node + + def to_doc + level = @level + label = @label + caption = @caption ? @caption.to_doc : nil + @compiler.compile_column(level, label, caption, @content) + end + end + +end diff --git a/lib/review/review.kpeg b/lib/review/review.kpeg new file mode 100644 index 000000000..701825f01 --- /dev/null +++ b/lib/review/review.kpeg @@ -0,0 +1,756 @@ +%% name = ReVIEW::Compiler + +%% header { +# coding: UTF-8 + +} + +%% { + class Error; end + class Position + attr_accessor :pos, :line, :col + def initialize(compiler) + @pos = compiler.pos + @line = compiler.current_line + @col = compiler.current_column + end + end + +# rubocop:disable all +require 'review/location' +require 'review/extentions' +require 'review/preprocessor' +require 'review/exception' +require 'review/node' + require 'lineinput' + # require 'review/compiler/literals_1_9' + # require 'review/compiler/literals_1_8' + + ## redifine Compiler.new + def initialize(strategy) + @strategy = strategy + @current_column = nil + @chapter = nil + end + + attr_accessor :strategy + + def compile(chap) + @chapter = chap + do_compile + @strategy.result + end + + def do_compile + @strategy.bind self, @chapter, ReVIEW::Location.new(@chapter.basename, self) + setup_parser(@chapter.content) + parse() + convert_ast + end + + def convert_ast + ast = @strategy.ast + convert_column(ast) + if $DEBUG + File.open("review-dump.json","w") do |f| + f.write(ast.to_json) + end + end + @strategy.output << ast.to_doc + end + + def flush_column(new_content) + if @current_column + new_content << @current_column + @current_column = nil + end + end + + def convert_column(ast) + @column_stack = [] + content = ast.content + new_content = [] + @current_content = new_content + content.each do |elem| + if elem.kind_of?(ReVIEW::HeadlineNode) && elem.cmd && elem.cmd.to_doc == "column" + flush_column(new_content) + @current_content = [] + @current_column = ReVIEW::ColumnNode.new(elem.compiler, elem.position, elem.level, + elem.label, elem.content, @current_content) + next + elsif elem.kind_of?(ReVIEW::HeadlineNode) && elem.cmd && elem.cmd.to_doc =~ %r|^/| + cmd_name = elem.cmd.to_doc[1..-1] + if cmd_name != "column" + raise ReVIEW::CompileError, "#{cmd_name} is not opened." + end + flush_column(new_content) + @current_content = new_content + next + elsif elem.kind_of?(ReVIEW::HeadlineNode) && @current_column && elem.level <= @current_column.level + flush_column(new_content) + @current_content = new_content + end + @current_content << elem + end + flush_column(new_content) + ast.content = new_content + ast + end + + def compile_text(text) + @strategy.nofunc_text(text) + end + + class SyntaxElement + def initialize(name, type, argc, esc, &block) + @name = name + @type = type + @argc_spec = argc + @esc_patterns = esc + @checker = block + end + + attr_reader :name + + def check_args(args) + unless @argc_spec === args.size + raise ReVIEW::CompileError, "wrong # of parameters (block command //#{@name}, expect #{@argc_spec} but #{args.size})" + end + @checker.call(*args) if @checker + end + + def min_argc + case @argc_spec + when Range then @argc_spec.begin + when Integer then @argc_spec + else + raise TypeError, "argc_spec is not Range/Integer: #{inspect()}" + end + end + + def parse_args(args) + if @esc_patterns + args.map.with_index do |pattern, i| + if @esc_patterns[i] + args[i].__send__("to_#{@esc_patterns[i]}") + else + args[i].to_doc + end + end + else + args.map(&:to_doc) + end + end + + def block_required? + @type == :block or @type == :code_block + end + + def block_allowed? + @type == :block or @type == :code_block or @type == :optional or @type == :optional_code_block + end + + def code_block? + @type == :code_block or @type == :optional_code_block + end + end + + SYNTAX = {} + + def self.defblock(name, argc, optional = false, esc = nil, &block) + defsyntax(name, (optional ? :optional : :block), argc, esc, &block) + end + + def self.defcodeblock(name, argc, optional = false, esc = nil, &block) + defsyntax(name, (optional ? :optional_code_block : :code_block), argc, esc, &block) + end + + def self.defsingle(name, argc, esc = nil, &block) + defsyntax name, :line, argc, esc, &block + end + + def self.defsyntax(name, type, argc, esc = nil, &block) + SYNTAX[name] = SyntaxElement.new(name, type, argc, esc, &block) + end + + def syntax_defined?(name) + SYNTAX.key?(name.to_sym) + end + + def syntax_descriptor(name) + SYNTAX[name.to_sym] + end + + class InlineSyntaxElement + def initialize(name) + @name = name + end + + attr_reader :name + end + + INLINE = {} + COMPLEX_INLINE = {} + + def self.definline(name) + INLINE[name] = InlineSyntaxElement.new(name) + end + + def self.defcomplexinline(name) + COMPLEX_INLINE[name] = InlineSyntaxElement.new(name) + end + + def inline_defined?(name) + INLINE.key?(name.to_sym) || COMPLEX_INLINE.key?(name.to_sym) + end + + defblock :read, 0 + defblock :lead, 0 + defblock :quote, 0 + defblock :bibpaper, 2..3, true, [:raw, :doc, :doc] + defblock :doorquote, 1, false, [:doc] + defblock :talk, 0 + defblock :graph, 1..3, false, [:raw, :raw, :doc] + + defcodeblock :emlist, 0..2, false, [:doc, :raw] + defcodeblock :cmd, 0..1, false, [:doc] + defcodeblock :source, 0..2, false, [:doc, :raw] + defcodeblock :list, 2..4, false, [:raw, :doc, :raw, :raw] + defcodeblock :listnum, 2..3, false, [:raw, :doc, :raw] + defcodeblock :emlistnum, 0..2, false, [:doc, :raw] + defcodeblock :texequation, 0, false + defcodeblock :table, 0..2, false, [:raw, :doc] + defcodeblock :imgtable, 0..2, false, [:raw, :doc] + defcodeblock :image, 2..3, true, [:raw,:doc,:raw] + defcodeblock :box, 0..1, false, [:doc] + + defblock :address, 0 + defblock :blockquote, 0 + defblock :bpo, 0 + defblock :flushright, 0 + defblock :centering, 0 + defblock :note, 0..1 + defblock :memo, 0..1 + defblock :info, 0..1 + defblock :important, 0..1 + defblock :caution, 0..1 + defblock :notice, 0..1 + defblock :warning, 0..1 + defblock :tip, 0..1 + defblock :comment, 0..1, true + + defsingle :footnote, 2, [:raw, :doc] + defsingle :noindent, 0 + defsingle :linebreak, 0 + defsingle :pagebreak, 0 + defsingle :indepimage, 1..3, [:raw, :doc, :raw] + defsingle :numberlessimage, 1..3, [:raw, :doc, :raw] + defsingle :hr, 0 + defsingle :parasep, 0 + defsingle :label, 1, [:raw] + defsingle :raw, 1, [:raw] + defsingle :tsize, 1, [:raw] + defsingle :include, 1, [:raw] + defsingle :olnum, 1, [:raw] + + definline :chapref + definline :chap + definline :title + definline :img + definline :imgref + definline :icon + definline :list + definline :table + definline :fn + definline :bou + definline :ami + definline :b + definline :dtp + definline :code + definline :bib + definline :hd + definline :recipe + definline :column + definline :tcy + + definline :abbr + definline :acronym + definline :cite + definline :dfn + definline :em + definline :kbd + definline :q + definline :samp + definline :strong + definline :var + definline :big + definline :small + definline :del + definline :ins + definline :sup + definline :sub + definline :tt + definline :i + definline :tti + definline :ttb + definline :u + definline :raw + definline :br + definline :m + definline :uchar + definline :idx + definline :hidx + definline :comment + definline :include + definline :tcy + + defcomplexinline :kw + defcomplexinline :ruby + defcomplexinline :href + + def compile_column(level, label, caption, content) + buf = "" + buf << @strategy.__send__("column_begin", level, label, caption) + buf << content.to_doc + buf << @strategy.__send__("column_end", level) + buf + end + + def compile_command(name, args, lines, node) + syntax = syntax_descriptor(name) + if !syntax || (!@strategy.respond_to?(syntax.name) && !@strategy.respond_to?("node_#{syntax.name}")) + error "strategy does not support command: //#{name}" + compile_unknown_command args, lines + return + end + begin + syntax.check_args args + rescue ReVIEW::CompileError => err + error err.message + args = ['(NoArgument)'] * syntax.min_argc + end + if syntax.block_allowed? + compile_block(syntax, args, lines, node) + else + if lines + error "block is not allowed for command //#{syntax.name}; ignore" + end + compile_single(syntax, args, node) + end + end + + def compile_headline(level, tag, label, caption) + buf = "" + @headline_indexs ||= [0] ## XXX + caption ||= "" + caption.strip! + index = level - 1 + if @headline_indexs.size > (index + 1) + @headline_indexs = @headline_indexs[0..index] + end + @headline_indexs[index] = 0 if @headline_indexs[index].nil? + @headline_indexs[index] += 1 + buf << @strategy.headline(level, label, caption) + buf + end + + def comment(text) + @strategy.comment(text) + end + + def compile_ulist(content) + buf0 = "" + level = 0 + content.each do |element| + current_level = element.level + buf = element.to_doc + if level == current_level + buf0 << @strategy.ul_item_end + # body + buf0 << @strategy.ul_item_begin([buf]) + elsif level < current_level # down + level_diff = current_level - level + level = current_level + (1..(level_diff - 1)).to_a.reverse_each do |i| + buf0 << @strategy.ul_begin{i} + buf0 << @strategy.ul_item_begin([]) + end + buf0 << @strategy.ul_begin{level} + buf0 << @strategy.ul_item_begin([buf]) + elsif level > current_level # up + level_diff = level - current_level + level = current_level + (1..level_diff).to_a.reverse_each do |i| + buf0 << @strategy.ul_item_end + buf0 << @strategy.ul_end{level + i} + end + buf0 << @strategy.ul_item_end + # body + buf0 <<@strategy.ul_item_begin([buf]) + end + end + + (1..level).to_a.reverse_each do |i| + buf0 << @strategy.ul_item_end + buf0 << @strategy.ul_end{i} + end + buf0 + end + + def compile_olist(content) + buf0 = "" + buf0 << @strategy.ol_begin + content.each do |element| + ## XXX 1st arg should be String, not Array + buf0 << @strategy.ol_item(element.to_doc.split(/\n/), element.num) + end + buf0 << @strategy.ol_end + buf0 + end + + def compile_dlist(content) + buf = "" + buf << @strategy.dl_begin + content.each do |element| + buf << @strategy.dt(element.text.to_doc) + buf << @strategy.dd(element.content.map{|s| s.to_doc}) + end + buf << @strategy.dl_end + buf + end + + + def compile_unknown_command(args, lines) + @strategy.unknown_command(args, lines) + end + + def compile_block(syntax, args, lines, node) + node_name = "node_#{syntax.name}".to_sym + if @strategy.respond_to?(node_name) + @strategy.__send__(node_name, node) + else + args_conv = syntax.parse_args(args) + @strategy.__send__(syntax.name, (lines || default_block(syntax)), *args_conv) + end + end + + def default_block(syntax) + if syntax.block_required? + error "block is required for //#{syntax.name}; use empty block" + end + [] + end + + def compile_single(syntax, args, node) + node_name = "node_#{syntax.name}".to_sym + if @strategy.respond_to?(node_name) + @strategy.__send__(node_name, node) + else + args_conv = syntax.parse_args(args) + @strategy.__send__(syntax.name, *args_conv) + end + end + + + def compile_inline(op, args) + unless inline_defined?(op) + raise ReVIEW::CompileError, "no such inline op: #{op}" + end + if @strategy.respond_to?("node_inline_#{op}") + return @strategy.__send__("node_inline_#{op}", args) + end + unless @strategy.respond_to?("inline_#{op}") + raise "strategy does not support inline op: @<#{op}>" + end + if !args + @strategy.__send__("inline_#{op}", "") + else + @strategy.__send__("inline_#{op}", *(args.map(&:to_doc))) + end +# rescue => err +# error err.message + end + + def compile_paragraph(buf) + @strategy.paragraph buf + end + + def compile_raw(builders, content) + c = @strategy.class.to_s.gsub(/ReVIEW::/, '').gsub(/Builder/, '').downcase + if !builders || builders.include?(c) + content.gsub("\\n", "\n") + else + "" + end + end + + def warn(msg) + @strategy.warn msg + end + + def error(msg) + @strategy.error msg + end + + def check_indent(s) + s.size >= @list_stack.last.size + end + + def check_nested_indent(s) + s.size >= @list_stack.last.size + 2 + end + + def check_inline_element_symbol(name) + INLINE.key?(name.to_sym) + end + + def check_complex_inline_element_symbol(name) + COMPLEX_INLINE.key?(name.to_sym) + end + + def position + Position.new(self) + end + + +} + +%% ast-location = ::ReVIEW +%% headline = ast HeadlineNode(compiler, position, level, cmd, label, content) +%% paragraph = ast ParagraphNode(compiler, position, content) +%% block_element = ast BlockElementNode(compiler, position, name, args, content) +%% code_block_element = ast CodeBlockElementNode(compiler, position, name, args, content) +%% inline_element = ast InlineElementNode(compiler, position, symbol, content) +%% inline_element_content = ast InlineElementContentNode(compiler, position, content) +%% complex_inline_element = ast ComplexInlineElementNode(compiler, position, symbol, content) +%% complex_inline_element_content = ast ComplexInlineElementContentNode(compiler, position, content) +%% text = ast TextNode(compiler, position, content) +%% raw = ast RawNode(compiler, builder, position, content) +%% brace = ast BraceNode(compiler, position, content) +%% singleline_content = ast SinglelineContentNode(compiler, position, content) +%% singleline_comment = ast SinglelineCommentNode(compiler, position, content) +%% ulist = ast UlistNode(compiler, position, content) +%% ulist_element = ast UlistElementNode(compiler, position, level, content) +%% olist = ast OlistNode(compiler, position, content) +%% olist_element = ast OlistElementNode(compiler, position, num, content) +%% dlist = ast DlistNode(compiler, position, content) +%% dlist_element = ast DlistElementNode(compiler, position, text, content) +%% bracket_arg = ast BracketArgNode(compiler, position, content) +%% document = ast DocumentNode(compiler, position, content) +%% column = ast ColumnNode(compiler, position, level, label, caption, content) +%% newline = ast NewLineNode(compiler, position, content) + +# %% dummy + +root = Start + +Start = &. { @list_stack = Array.new } Document:c { @strategy.ast = c } + +## a Document is a set of Blocks +Document = BOM? Block*:c ~document(self, position, c) + +## ignore leading blank lines +Block = BlankLine*:c { c } + ( SinglelineComment:c + | Headline:c + | BlockElement:c + | Ulist:c + | Olist:c + | Dlist:c + | Paragraph:c + ) { c } + +BlankLine = Newline + +SinglelineComment = ("#@" < NonNewline+ > EOL) ~singleline_comment(self, position, text) + +Headline = HeadlinePrefix:level BracketArg?:cmd BraceArg?:label Space* SinglelineContent?:caption EOL ~headline(self, position, level, cmd, label, caption) + +HeadlinePrefix = < /={1,5}/ > { text.length } + +Paragraph = ParagraphLine+:c ~paragraph(self, position, c.flatten) + +ParagraphLine = !Headline !SinglelineComment !BlockElement !Ulist !Olist !Dlist SinglelineContent:c Newline { c } + +# There are 3 types of Block Element: raw Block, Code Block, and Normal Block +BlockElement = ( "//raw[" RawBlockBuilderSelect?:b RawBlockElementArg*:r1 "]" Space* EOL + ~raw(self, b, position, r1) + | !"//raw" "//" ElementName:symbol &{ syntax = syntax_descriptor(symbol); syntax && syntax.code_block? } BracketArg*:args "{" Space* Newline CodeBlockElementContents:contents "//}" Space* EOL + ~code_block_element(self, position, symbol, args, contents) + | !"//raw" "//" ElementName:symbol BracketArg*:args "{" Space* Newline BlockElementContents:contents "//}" Space* EOL + ~block_element(self, position, symbol, args, contents) + | !"//raw" "//" ElementName:symbol BracketArg*:args Space* EOL ~block_element(self, position, symbol, args, nil) + ) + +RawBlockBuilderSelect = "|" Space* RawBlockBuilderSelectSub:c Space* "|" { c } + +RawBlockBuilderSelectSub = ( < AlphanumericAscii+ >:c1 Space* "," Space* RawBlockBuilderSelectSub:c2 + { [text] + c2 } + | < AlphanumericAscii+ >:c1 + { [text] } + ) + +RawBlockElementArg = !"]" ( "\\]" { "]" } + | "\\n" { "\n" } + | < NonNewline > { text } + ) + +BracketArg = "[" BracketArgInline*:content "]" ~bracket_arg(self, position, content) + +## XXX '\' (excpet '\]' and '\\' ) => '\' is ??? +BracketArgInline = ( InlineElement:c { c } + | "\\]" ~text(self, position, "]") + | "\\\\" ~text(self, position, "\\") + | < /[^\r\n\]]/ > ~text(self, position, text) + ) + +BraceArg = "{" < /([^\r\n}\\]|\\[^\r\n])*/ > "}" { text } + +## Standard BlockElement has nested blocks. Texts in content of block are parsed as Paragraph. +BlockElementContents = BlockElementContent*:c { c } + +### Headline is prohibited. +### Note: do not allow "//}" at front of Paragraph. +BlockElementContent = ( SinglelineComment:c { c } + | BlockElement:c { c } + | Ulist:c + | Dlist:c + | Olist:c + | BlankLine:c { c } + | BlockElementParagraph:c { c } + ) + +## it's like Paragraph, but it's in a block, so do not allow '//}\n' +BlockElementParagraph = BlockElementParagraphLine+:c ~paragraph(self, position, c.flatten) +BlockElementParagraphLine = !"//}" !BlankLine !SinglelineComment !BlockElement !Ulist !Olist !Dlist SinglelineContent:c Newline { c } + +## In CodeBlockElementContents, newline should no be ingored. So we use TextNode instead of NewLineNode. +CodeBlockElementContents = CodeBlockElementContent+:c { c } +CodeBlockElementContent = ( SinglelineComment:c { c } + | BlankLine:c { ::ReVIEW::TextNode.new(self, position, "\n") } + | !"//}" SinglelineContent:c Newline { [c, ::ReVIEW::TextNode.new(self, position, "\n")] } + ) + +## Ulist and Olist + +Bullet = "*" +Enumerator = < /[0-9]+/ > { num = text } "." { num.to_i } + +Ulist = Indent+:s Bullet+:b Space+ { @list_stack.push(s) } UlistItemBlock:item + { if b.size > 1 then item.level = b.size end } + (UlistItem | UlistItemMore | NestedList)*:items &{ s == @list_stack.pop } + ~ulist(self, position, items.unshift(item)) + +Olist = Indent+:s Enumerator:e Space+ { @list_stack.push(s) } OlistItemBlock:item + { item.num = e } + (OlistItem | NestedList)*:items &{ s == @list_stack.pop } + ~olist(self, position, items.unshift(item)) + +UlistItemBlock = ListItemFirstLine:c ListItemLine*:d ~ulist_element(self, position, @list_stack.size, d.unshift(c)) +OlistItemBlock = ListItemFirstLine:c ListItemLine*:d ~olist_element(self, position, 0, d.unshift(c)) + +ListItemFirstLine = SinglelineContent:c Newline { c } +ListItemLine = Indent+:s !Bullet !Enumerator !Space SinglelineContent:c &{ check_indent(s) } Newline { c } + +UlistItemMore = Indent+:s Bullet Bullet+:b Space+ &{ check_indent(s) } UlistItemBlock:item { item.level = b.size+1; item } + +UlistItem = Indent+:s Bullet Space+ &{ check_indent(s) } UlistItemBlock:item { item } +OlistItem = Indent+:s Enumerator:e Space+ &{ check_indent(s) } OlistItemBlock:item { item.num = e; item } + +## NestedList is markdown-like indented syntax. +## You can write nested Ulist and Olist with this syntax. + +NestedList = (NestedUlist | NestedOlist) + +NestedUlist = Indent+:s Bullet Space+ &{ check_nested_indent(s) } { @list_stack.push(s) } UlistItemBlock:item + (UlistItem | NestedList)*:items &{ s == @list_stack.pop } + ~ulist(self, position, items.unshift(item)) +NestedOlist = Indent+:s Enumerator:e Space+ &{ check_nested_indent(s) } { @list_stack.push(s) } OlistItemBlock:item + { item.num = e } + (OlistItem | NestedList)*:items &{ s == @list_stack.pop } + ~olist(self, position, items.unshift(item)) + +# Dlist +Dlist = (DlistElement | SinglelineComment)+:content ~dlist(self, position, content) + +DlistElement = Indent* ":" Space+ SinglelineContent:text Newline DlistElementContent+:content ~dlist_element(self, position, text, content) + +DlistElementContent = (SinglelineComment:c { c } + |Space+ SinglelineContent:c Newline { c } + ) + +SinglelineContent = Inline+:c ~singleline_content(self, position, c) + + +# Inline Element and Non Inline Element + +Inline = ( InlineElement | NonInlineElement) + +NonInlineElement = !InlineElement < NonNewline > ~text(self, position, text) + +InlineElement = ( RawInlineElement:c { c } + | !RawInlineElement "@<" InlineElementSymbol:symbol ">" "{" InlineElementContents?:contents "}" ~inline_element(self, position, symbol,contents) + | !RawInlineElement "@<" ComplexInlineElementSymbol:symbol ">" "{" ComplexInlineElementContents?:contents "}" ~complex_inline_element(self, position, symbol,contents) + ) + +RawInlineElement = "@{" RawBlockBuilderSelect?:builders RawInlineElementContent+:c "}" ~raw(self, builders, position, c) + +RawInlineElementContent = ( "\\}" { "}" } + | < /[^\r\n\}]/ > { text } + ) + +InlineElementSymbol = < AlphanumericAscii+ >:s &{ check_inline_element_symbol(text) } { text } + +InlineElementContents = !"}" InlineElementContentsSub:c { c } + +InlineElementContentsSub = !"}" Space* InlineElementContent:c1 Space* { [c1] } + +ComplexInlineElementSymbol = < AlphanumericAscii+ > &{ check_complex_inline_element_symbol(text) } { text } + +ComplexInlineElementContents = !"}" ComplexInlineElementContentsSub:c { c } + +ComplexInlineElementContentsSub = !"}" ( Space* InlineElementContent:c1 Space* "," ComplexInlineElementContentsSub:c2 { [c1]+c2 } + | Space* InlineElementContent:c1 Space* { [c1] } + ) + + +InlineElementContent = InlineElementContentSub+:d { d } + +InlineElementContentSub = ( InlineElement:c { c } + | !InlineElement QuotedInlineText:content ~inline_element_content(self, position, content) + | !InlineElement InlineElementContentText+:content ~inline_element_content(self, position, content) + ) + +## Quoted Inline Text is "..." +## In Quoted Inline Text, "\\" is "\", "\'" is "'", other characters are kept as is. +QuotedInlineText = "\"" + ( "\\\"" { "\"" } + | "\\\\" { "\\" } + | < /[^"\r\n\\]/ > { text } + )+:str "\"" ~text(self, position, str.join("")) + +## XXX '\' (excpet '\}' and '\,' and '\\' ) => '\' is OK? +InlineElementContentText = ( "\\}" ~text(self, position, "}") + | "\\," ~text(self, position, ",") + | "\\\\" ~text(self, position, "\\" ) + | "\\" ~text(self, position, "\\" ) + | !InlineElement < /[^\r\n\\},]/> ~text(self, position, text) + ) + +NonNewline = /[^\r\n]/ + +Space = /[ \t]/ + +Indent = " " + +EOL = (Newline|EOF) + +EOF = !. + +ElementName = < LowerAlphabetAscii+ > { text } + +AlphanumericAscii = /[A-Za-z0-9]/ +LowerAlphabetAscii = /[a-z]/ +Digit = /[0-9]/ +BOM = "\uFEFF" +Newline = /\n|\r\n?|\p{Zl}|\p{Zp}/ ~newline(self, position, "\n") diff --git a/lib/review/textutils.rb b/lib/review/textutils.rb index 056902b69..e621d614c 100644 --- a/lib/review/textutils.rb +++ b/lib/review/textutils.rb @@ -12,27 +12,5 @@ def detab(str, ts = 8) ' ' * len } end - - def split_paragraph(lines) - pre = pre_paragraph - post = post_paragraph - - blocked_lines = [[]] - lines.each {|element| - if element == "" - if blocked_lines.last != [] - blocked_lines << [] - end - else - blocked_lines.last << element - end - } - - if !pre.nil? and !post.nil? - blocked_lines.map!{|i| [pre] + i + [post] } - end - - blocked_lines.map{|l| l.join("")} - end end end diff --git a/lib/review/tocparser.rb b/lib/review/tocparser.rb index 40421b88a..685533f36 100644 --- a/lib/review/tocparser.rb +++ b/lib/review/tocparser.rb @@ -108,9 +108,12 @@ 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) + c = ReVIEW::Compiler.new(b) + dummy_loc = Location.new("", c) + b.bind(c, dummy_chapter, dummy_loc) + c.setup_parser(line) + c.parse("Paragraph") + c.result.to_doc end def error!(filename, lineno, msg) diff --git a/lib/review/topbuilder.rb b/lib/review/topbuilder.rb index 7e66dd778..12ca99531 100644 --- a/lib/review/topbuilder.rb +++ b/lib/review/topbuilder.rb @@ -22,7 +22,10 @@ class TOPBuilder < Builder } Compiler.defsingle(:dtp, 1) - Compiler.defblock(:insn, 1) + Compiler.defcodeblock(:insn, 1) + Compiler.defblock(:memo, 0..1) + Compiler.defblock(:tip, 0..1) + Compiler.defblock(:info, 0..1) Compiler.defblock(:planning, 0..1) Compiler.defblock(:best, 0..1) Compiler.defblock(:securty, 0..1) @@ -51,7 +54,6 @@ def builder_init_file @subsection = 0 @subsubsection = 0 @subsubsubsection = 0 - @blank_seen = true @titles = { "emlist" => "インラインリスト", @@ -99,28 +101,6 @@ def builder_init_file end private :builder_init_file - def print(s) - @blank_seen = false - super - end - private :print - - def puts(s) - @blank_seen = false - super - end - private :puts - - def blank - @output.puts unless @blank_seen - @blank_seen = true - end - private :blank - - def result - @output.string - end - def warn(msg) $stderr.puts "#{@location.filename}:#{@location.lineno}: warning: #{msg}" end @@ -134,8 +114,8 @@ def messages end def headline(level, label, caption) + buf = "" prefix = "" - blank case level when 1 if @chapter.number.to_s =~ /\A\d+\Z/ @@ -169,62 +149,67 @@ def headline(level, label, caption) raise "caption level too deep or unsupported: #{level}" end prefix = "" if (level.to_i > @book.config["secnolevel"]) - puts "■H#{level}■#{prefix}#{compile_inline(caption)}" + buf << "■H#{level}■#{prefix}#{caption}\n" + buf end def ul_begin - blank + "\n" end def ul_item(lines) - puts "●\t#{lines.join}" + "●\t#{lines.join}\n" end def ul_end - blank + "\n" end def ol_begin - blank @olitem = 0 + "\n" end def ol_item(lines, num) - puts "#{num}\t#{lines.join}" + "#{num}\t#{lines.join}\n" end def ol_end - blank @olitem = nil + "\n" end def dl_begin - blank + "\n" end def dt(line) - puts "★#{line}☆" + "★#{line}☆\n" end def dd(lines) - split_paragraph(lines).each do |paragraph| - puts "\t#{paragraph.gsub(/\n/, '')}" + buf = "" + lines.each do |paragraph| + buf << "\t#{paragraph.gsub(/\n/, '')}\n" end + buf end def dl_end - blank + "\n" end def paragraph(lines) - puts lines.join + lines.join+"\n" end def read(lines) - puts "◆→開始:#{@titles["lead"]}←◆" - puts split_paragraph(lines).join("\n") - puts "◆→終了:#{@titles["lead"]}←◆" - blank + buf = "" + buf << "◆→開始:#{@titles["lead"]}←◆\n" + buf << lines.join("\n") << "\n" + buf << "◆→終了:#{@titles["lead"]}←◆\n" + buf << "\n" + buf end alias_method :lead, :read @@ -236,44 +221,50 @@ def inline_list(id) else %Q[#{I18n.t("list")}#{I18n.t("format_number", [get_chap(chapter), @chapter.list(id).number])}] end - end def list_header(id, caption, lang) - blank - puts "◆→開始:#{@titles["list"]}←◆" + buf = "" + #buf << "\n" + buf << "◆→開始:#{@titles["list"]}←◆\n" if get_chap.nil? - puts %Q[#{I18n.t("list")}#{I18n.t("format_number_without_chapter", [@chapter.list(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}] + buf << %Q[#{I18n.t("list")}#{I18n.t("format_number_without_chapter", [@chapter.list(id).number])}#{I18n.t("caption_prefix_idgxml")}#{caption}] << "\n" else - puts %Q[#{I18n.t("list")}#{I18n.t("format_number", [get_chap, @chapter.list(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}] + buf << %Q[#{I18n.t("list")}#{I18n.t("format_number", [get_chap, @chapter.list(id).number])}#{I18n.t("caption_prefix_idgxml")}#{caption}] << "\n" end - blank + buf << "\n" + buf end def list_body(id, lines, lang) + buf = "" lines.each do |line| - puts detab(line) + buf << detab(line) << "\n" end - puts "◆→終了:#{@titles["list"]}←◆" - blank + buf << "◆→終了:#{@titles["list"]}←◆\n" + buf << "\n" + buf end def base_block(type, lines, caption = nil) - blank - puts "◆→開始:#{@titles[type]}←◆" - puts "■#{compile_inline(caption)}" unless caption.nil? - puts lines.join("\n") - puts "◆→終了:#{@titles[type]}←◆" - blank + buf = "" + buf << "\n" + buf << "◆→開始:#{@titles[type]}←◆\n" + buf << "■#{caption}\n" unless caption.nil? + buf << lines.join("") + buf << "◆→終了:#{@titles[type]}←◆\n" + buf << "\n" + buf end def base_parablock(type, lines, caption = nil) - blank - puts "◆→開始:#{@titles[type]}←◆" - puts "■#{compile_inline(caption)}" unless caption.nil? - puts split_paragraph(lines).join("\n") - puts "◆→終了:#{@titles[type]}←◆" - blank + buf = "" + buf << "◆→開始:#{@titles[type]}←◆\n" + buf << "■#{caption}\n" unless caption.nil? + buf << lines.join("") + buf << "◆→終了:#{@titles[type]}←◆\n" + buf << "\n" + buf end def emlist(lines, caption = nil, lang = nil) @@ -281,23 +272,26 @@ def emlist(lines, caption = nil, lang = nil) end def emlistnum(lines, caption = nil, lang = nil) - blank - puts "◆→開始:#{@titles["emlist"]}←◆" - puts "■#{compile_inline(caption)}" unless caption.nil? + buf = "" + buf << "◆→開始:#{@titles["emlist"]}←◆\n" + buf << "■#{caption}\n" unless caption.nil? _lines = [] lines.each_with_index do |line, i| - puts (i + 1).to_s.rjust(2) + ": #{line}" + buf << (i + 1).to_s.rjust(2) + ": #{line}\n" end - puts "◆→終了:#{@titles["emlist"]}←◆" - blank + buf << "◆→終了:#{@titles["emlist"]}←◆\n" + buf << "\n" + buf end def listnum_body(lines, lang) + buf = "" lines.each_with_index do |line, i| - puts (i + 1).to_s.rjust(2) + ": #{line}" + buf << (i + 1).to_s.rjust(2) + ": #{line}\n" end - puts "◆→終了:#{@titles["list"]}←◆" - blank + buf << "◆→終了:#{@titles["list"]}←◆\n" + buf << "\n" + buf end def cmd(lines, caption = nil) @@ -327,48 +321,57 @@ def inline_img(id) end def image(lines, id, caption, metric=nil) - blank - puts "◆→開始:#{@titles["image"]}←◆" + buf = "" + #buf << "\n" + buf << "◆→開始:#{@titles["image"]}←◆\n" if get_chap.nil? - puts "#{I18n.t("image")}#{I18n.t("format_number_without_chapter", [@chapter.image(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}" + buf << "#{I18n.t("image")}#{I18n.t("format_number_without_chapter", [@chapter.image(id).number])}#{I18n.t("caption_prefix_idgxml")}#{caption}\n" else - puts "#{I18n.t("image")}#{I18n.t("format_number", [get_chap, @chapter.image(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}" + buf << "#{I18n.t("image")}#{I18n.t("format_number", [get_chap, @chapter.image(id).number])}#{I18n.t("caption_prefix_idgxml")}#{caption}\n" end - blank + buf << "\n" if @chapter.image(id).bound? - puts "◆→#{@chapter.image(id).path}←◆" + buf << "◆→#{@chapter.image(id).path}←◆\n" else lines.each do |line| - puts line + buf << line << "\n" end end - puts "◆→終了:#{@titles["image"]}←◆" - blank + buf << "◆→終了:#{@titles["image"]}←◆\n" + buf << "\n" + buf end def texequation(lines) - puts "◆→開始:#{@titles["texequation"]}←◆" - puts "#{lines.join("\n")}" - puts "◆→終了:#{@titles["texequation"]}←◆" - blank + buf = "" + buf << "◆→開始:#{@titles["texequation"]}←◆\n" + buf << "#{lines.join("\n")}\n" + buf << "◆→終了:#{@titles["texequation"]}←◆\n" + buf << "\n" + buf end def table_header(id, caption) - blank - puts "◆→開始:#{@titles["table"]}←◆" + buf = "" + buf << "\n" + buf << "◆→開始:#{@titles["table"]}←◆\n" if get_chap.nil? - puts "#{I18n.t("table")}#{I18n.t("format_number_without_chapter", [@chapter.table(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}" + buf << "#{I18n.t("table")}#{I18n.t("format_number_without_chapter", [@chapter.table(id).number])}#{I18n.t("caption_prefix_idgxml")}#{caption}\n" else - puts "#{I18n.t("table")}#{I18n.t("format_number", [get_chap, @chapter.table(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}" + buf << "#{I18n.t("table")}#{I18n.t("format_number", [get_chap, @chapter.table(id).number])}#{I18n.t("caption_prefix_idgxml")}#{caption}\n" end - blank + buf << "\n" + buf end def table_begin(ncols) + "" end def tr(rows) - puts rows.join("\t") + buf = "" + buf << rows.join("\t") << "\n" + buf end def th(str) @@ -380,19 +383,21 @@ def td(str) end def table_end - puts "◆→終了:#{@titles["table"]}←◆" - blank + buf = "" + buf << "◆→終了:#{@titles["table"]}←◆\n" + buf << "\n" + buf end def comment(lines, comment = nil) lines ||= [] lines.unshift comment unless comment.blank? str = lines.join("") - puts "◆→DTP連絡:#{str}←◆" + "◆→DTP連絡:#{str}←◆\n" end def footnote(id, str) - puts "【注#{@chapter.footnote(id).number}】#{compile_inline(str)}" + "【注#{@chapter.footnote(id).number}】#{str}\n" end def inline_fn(id) @@ -526,25 +531,28 @@ def inline_hd_chap(chap, id) end def noindent - puts "◆→DTP連絡:次の1行インデントなし←◆" + "◆→DTP連絡:次の1行インデントなし←◆\n" end def nonum_begin(level, label, caption) - puts "■H#{level}■#{compile_inline(caption)}" + "■H#{level}■#{caption}\n" end def nonum_end(level) end def common_column_begin(type, caption) - blank - puts "◆→開始:#{@titles[type]}←◆" - puts %Q[■#{compile_inline(caption)}] + buf = "" + buf << "◆→開始:#{@titles[type]}←◆\n" + buf << %Q[■#{caption}\n] + buf end def common_column_end(type) - puts %Q[◆→終了:#{@titles[type]}←◆] - blank + buf = "" + buf << %Q[◆→終了:#{@titles[type]}←◆\n] + buf << "\n" + buf end def column_begin(level, label, caption) @@ -698,15 +706,17 @@ def warning(lines, caption = nil) alias_method :box, :insn def indepimage(id, caption=nil, metric=nil) - blank + buf = "" + buf << "\n" begin - puts "◆→画像 #{@chapter.image(id).path.sub(/\A\.\//, "")} #{metric.join(" ")}←◆" + buf << "◆→画像 #{@chapter.image(id).path.sub(/\A\.\//, "")} #{metric.join(" ")}←◆\n" rescue warn "no such image: #{id}" - puts "◆→画像 #{id}←◆" + buf << "◆→画像 #{id}←◆\n" end - puts "図 #{compile_inline(caption)}" if caption.present? - blank + buf << "図 #{caption}\n" if caption.present? + buf << "\n" + buf end alias_method :numberlessimage, :indepimage @@ -793,7 +803,7 @@ def inline_pageref(idref) end def circle_begin(level, label, caption) - puts "・\t#{caption}" + "・\t#{caption}\n" end def circle_end(level) diff --git a/lib/review/version.rb b/lib/review/version.rb index 0d8b8d473..72a8651f7 100644 --- a/lib/review/version.rb +++ b/lib/review/version.rb @@ -1,3 +1,3 @@ module ReVIEW - VERSION = "2.1.0" + VERSION = "0.3.0" end diff --git a/review.gemspec b/review.gemspec index 5b03e182c..e9146c6aa 100644 --- a/review.gemspec +++ b/review.gemspec @@ -3,17 +3,17 @@ $:.push File.expand_path("../lib", __FILE__) require "review/version" Gem::Specification.new do |gem| - gem.name = "review" + gem.name = "review-peg" gem.version = ReVIEW::VERSION gem.platform = Gem::Platform::RUBY gem.license = "LGPL" gem.authors = ["kmuto", "takahashim"] gem.email = "kmuto@debian.org" gem.homepage = "http://github.com/kmuto/review" - gem.summary = "Re:VIEW: a easy-to-use digital publishing system" - gem.description = "Re:VIEW is a digital publishing system for books and ebooks. It supports InDesign, EPUB and LaTeX." + gem.summary = "Re:VIEW peg: a easy-to-use digital publishing system (PEG version)" + gem.description = "Re:VIEW is a digital publishing system for books and ebooks. It supports InDesign, EPUB and LaTeX. This gem is experimental version with PEG grammar" gem.required_rubygems_version = Gem::Requirement.new(">= 0") if gem.respond_to? :required_rubygems_version= - gem.date = "2016-04-29" + gem.date = "2016-11-10" gem.files = `git ls-files`.split("\n") gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") @@ -26,6 +26,7 @@ Gem::Specification.new do |gem| gem.add_dependency("rubyzip") gem.add_development_dependency("rake") gem.add_development_dependency("test-unit") + gem.add_development_dependency("kpeg") gem.add_development_dependency("pygments.rb") gem.add_development_dependency("rubocop") end diff --git a/test/sample-book/src/Rakefile b/test/sample-book/src/Rakefile index 14af6d1b1..778349e4a 100644 --- a/test/sample-book/src/Rakefile +++ b/test/sample-book/src/Rakefile @@ -5,17 +5,18 @@ BOOK = "book" BOOK_PDF = BOOK+".pdf" BOOK_EPUB = BOOK+".epub" CONFIG_FILE = "config.yml" +REVIEW_COMPILE = "review-compile-peg" WEBROOT = "webroot" def build(mode, chapter) - sh "review-compile --target=#{mode} --footnotetext --stylesheet=style.css #{chapter} > tmp" + sh "#{REVIEW_COMPILE} --target=#{mode} --footnotetext --stylesheet=style.css #{chapter} > tmp" mode_ext = {"html" => "html", "latex" => "tex", "idgxml" => "xml"} FileUtils.mv "tmp", chapter.gsub(/re\z/, mode_ext[mode]) end def build_all(mode) - sh "review-compile --target=#{mode} --footnotetext --stylesheet=style.css" + sh "#{REVIEW_COMPILE} --target=#{mode} --footnotetext --stylesheet=style.css" end task :default => :html_all diff --git a/test/test_builder.rb b/test/test_builder.rb index 13d29b87e..56a6b5d1e 100644 --- a/test/test_builder.rb +++ b/test/test_builder.rb @@ -44,16 +44,6 @@ def test_result assert_equal '', b.result end - def test_print_and_puts - b = Builder.new - assert_raises(NoMethodError) do # XXX: OK? - b.print "" - end - assert_raises(NoMethodError) do # XXX: OK? - b.puts "" - end - end - def test_not_implemented_methods ex = NoMethodError # XXX: OK? [ @@ -70,26 +60,6 @@ def test_not_implemented_methods end end - def test_compile_inline - text = "abc" - assert_equal [:text, text], @b.compile_inline(text) - end - - def test_inline_ruby - def @b.compile_ruby(base,ruby) - [base,ruby] - end - str = @b.inline_ruby("foo,bar") - assert_equal str, ["foo","bar"] - str = @b.inline_ruby("foo\\,\\,,\\,bar,buz") - assert_equal str, ["foo,,",",bar,buz"] - end - - def test_compile_inline_backslash - text = "abc\\d\\#a" - assert_equal [:text, text], @b.compile_inline(text) - end - class XBuilder < Builder def list_header(id, caption) end diff --git a/test/test_catalog_converter_cmd.rb b/test/test_catalog_converter_cmd.rb index ab240ad7d..ed65f91e7 100644 --- a/test/test_catalog_converter_cmd.rb +++ b/test/test_catalog_converter_cmd.rb @@ -4,7 +4,7 @@ require 'yaml' require 'rbconfig' -load File.expand_path('../bin/review-catalog-converter', File.dirname(__FILE__)) +load File.expand_path('../bin/review-catalog-converter-peg', File.dirname(__FILE__)) class CatalogConverterCmdTest < Test::Unit::TestCase def test_parse_chaps diff --git a/test/test_compiler.rb b/test/test_compiler.rb index fd18b907c..7c84409f3 100644 --- a/test/test_compiler.rb +++ b/test/test_compiler.rb @@ -4,43 +4,90 @@ require 'review/compiler' require 'review/book' require 'review/latexbuilder' +require 'review/htmlbuilder' class CompilerTest < Test::Unit::TestCase include ReVIEW def setup - @builder = LATEXBuilder.new() - @c = Compiler.new(@builder) + @builder = HTMLBuilder.new() + @param = { + "secnolevel" => 2, # for IDGXMLBuilder, HTMLBuilder + "inencoding" => "UTF-8", + "outencoding" => "UTF-8", + "subdirmode" => nil, + "stylesheet" => nil, # for HTMLBuilder + } + @book = Book::Base.new(nil) + @book.config = @param + @compiler = ReVIEW::Compiler.new(@builder) + @chapter = Book::Chapter.new(@book, 1, '-', nil, StringIO.new) + location = Location.new(nil, nil) + @builder.bind(@compiler, @chapter, location) + + def @compiler.compile_command(name, args, lines, node) + args + end + end def test_parse_args - args = @c.__send__(:parse_args, "[foo][bar]") - assert_equal ["foo","bar"], args + args = compile_blockelem("//dummy[foo][bar]\n", false) + assert_equal ["foo","bar"], args.parse_args(:doc,:doc) end def test_parse_args_with_brace1 - args = @c.__send__(:parse_args, "[fo[\\][\\]o][bar]") - assert_equal ["fo[][]o","bar"], args + args = compile_blockelem("//dummy[fo[\\][\\]o][bar]", false) + assert_equal ["fo[][]o","bar"], args.parse_args(:doc, :doc) end def test_parse_args_with_brace2 - args = @c.__send__(:parse_args, "[f\\]o\\]o][bar]") - assert_equal ["f]o]o","bar"], args + args = compile_blockelem("//dummy[f\\]o\\]o][bar]", false) + assert_equal ["f]o]o","bar"], args.parse_args(:doc, :doc) end def test_parse_args_with_backslash - args = @c.__send__(:parse_args, "[foo][bar\\buz]") - assert_equal ["foo","bar\\buz"], args + args = compile_blockelem("//dummy[foo][bar\\buz]", false) + assert_equal ["foo","bar\\buz"], args.parse_args(:doc, :doc) end def test_parse_args_with_backslash2 - args = @c.__send__(:parse_args, "[foo][bar\\#\\[\\!]") - assert_equal ["foo","bar\\#\\[\\!"], args + args = compile_blockelem("//dummy[foo][bar\\#\\[\\!]", false) + assert_equal ["foo","bar\\#\\[\\!"], args.parse_args(:doc, :doc) end def test_parse_args_with_backslash3 - args = @c.__send__(:parse_args, "[foo][bar\\\\buz]") - assert_equal ["foo","bar\\buz"], args + args = compile_blockelem("//dummy[foo][bar\\\\buz]", false) + assert_equal ["foo","bar\\buz"], args.parse_args(:doc, :doc) + end + + def test_compile_inline + def @compiler.inline_ruby(*args) + return args + end + args = compile_inline("@{abc}",false) + assert_equal "abc", args.content[0].content.to_doc + end + + def test_inline_ruby +# def @compiler.inline_ruby(*args) +# return args +# end + args = compile_inline("@{foo,bar}",false) + assert_equal "foo", args.content[0].content[0].to_doc + assert_equal "bar", args.content[0].content[1].to_doc + args = compile_inline("@{foo\\,\\,,\\,bar\\,buz}", false) + assert_equal "foo,,", args.content[0].content[0].to_doc + assert_equal ",bar,buz", args.content[0].content[1].to_doc + end + + def test_compile_inline_backslash + def @compiler.inline_dummy(*args) + return args + end + Compiler.definline :dummy + args = compile_inline("@{abc\\d\\#a}", false) + assert_equal "abc\\d\\#a", args.content[0].content.to_doc end end diff --git a/test/test_epubmaker_cmd.rb b/test/test_epubmaker_cmd.rb index 32388f484..3e76d117c 100644 --- a/test/test_epubmaker_cmd.rb +++ b/test/test_epubmaker_cmd.rb @@ -6,7 +6,7 @@ require 'yaml' require 'rbconfig' -REVIEW_EPUBMAKER = File.expand_path('../bin/review-epubmaker', File.dirname(__FILE__)) +REVIEW_EPUBMAKER = File.expand_path('../bin/review-epubmaker-peg', File.dirname(__FILE__)) class EPUBMakerCmdTest < Test::Unit::TestCase def setup diff --git a/test/test_helper.rb b/test/test_helper.rb index 25b1ad82d..7feaa645f 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,6 +1,43 @@ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib/') require 'test/unit' + def compile_document(str, force_to_s=true) + @compiler.setup_parser(str) + @compiler.parse("Document") + if force_to_s + @compiler.result.to_doc + else + @compiler.result + end + end + + def compile_inline(str, force_to_s=true) + @compiler.setup_parser(str) + @compiler.parse("Paragraph") + if force_to_s +## @compiler.result.map(&:to_doc).join + @compiler.result.to_doc + else + @compiler.result + end + end + + def compile_blockelem(str, force_to_s=true) + @compiler.setup_parser(str) + @compiler.parse("BlockElement") + if force_to_s + @compiler.result.to_doc + else + @compiler.result + end + end + + def compile_headline(str) + @compiler.setup_parser(str) + @compiler.parse("Headline") + @compiler.result.to_doc + end + def touch_file(path) File.open(path, "w").close path @@ -16,10 +53,6 @@ def prepare_samplebook(srcdir) YAML.load(File.open(srcdir + "/config.yml")) end -def compile_inline(text) - @builder.compile_inline(text) -end - def compile_block(text) method_name = "compile_block_#{@builder.target_name}" if !self.respond_to?(method_name, true) diff --git a/test/test_htmlbuilder.rb b/test/test_htmlbuilder.rb index 869bf19c8..d159a4bc6 100644 --- a/test/test_htmlbuilder.rb +++ b/test/test_htmlbuilder.rb @@ -55,7 +55,7 @@ def on_APPENDIX? end end actual = compile_block("=={test} this is test.\n") - assert_equal %Q|\n

      A.1 this is test.

      \n|, actual + assert_equal %Q|

      A.1 this is test.

      \n|, actual end def test_headline_postdef_roman @@ -70,12 +70,8 @@ def on_APPENDIX? end end - actual = compile_block("={test} this is test.\n") - assert_equal %Q|

      付録I this is test.

      \n|, actual - actual = compile_block("=={test} this is test.\n") - assert_equal %Q|\n

      I.1 this is test.

      \n|, actual - + assert_equal %Q|

      I.1 this is test.

      \n|, actual end end end @@ -96,7 +92,7 @@ def on_APPENDIX? assert_equal %Q|

      付録A this is test.

      \n|, actual actual = compile_block("=={test} this is test.\n") - assert_equal %Q|\n

      A.1 this is test.

      \n|, actual + assert_equal %Q|

      A.1 this is test.

      \n|, actual end end end @@ -119,18 +115,18 @@ def test_headline_level1_with_inlinetag def test_headline_level2 actual = compile_block("=={test} this is test.\n") - assert_equal %Q|\n

      1.1 this is test.

      \n|, actual + assert_equal %Q|

      1.1 this is test.

      \n|, actual end def test_headline_level3 actual = compile_block("==={test} this is test.\n") - assert_equal %Q|\n

      this is test.

      \n|, actual + assert_equal %Q|

      this is test.

      \n|, actual end def test_headline_level3_with_secno @book.config["secnolevel"] = 3 actual = compile_block("==={test} this is test.\n") - assert_equal %Q|\n

      1.0.1 this is test.

      \n|, actual + assert_equal %Q|

      1.0.1 this is test.

      \n|, actual end def test_label @@ -357,7 +353,7 @@ def @chapter.image(id) def test_quote actual = compile_block("//quote{\nfoo\nbar\n\nbuz\n//}\n") - assert_equal %Q|

      foobar

      \n

      buz

      \n|, actual + assert_equal %Q|

      foobar

      \n

      buz

      \n
      \n|, actual end def test_memo @@ -518,7 +514,7 @@ def @chapter.list(id) @book.config["highlight"]["html"] = "pygments" actual = compile_block("//list[samplelist][this is @{test}<&>_]{\ntest1\ntest1.5\n\ntest@{2}\n//}\n") - assert_equal %Q|
      \n

      リスト1.1: this is test<&>_

      \n
      test1\ntest1.5\n\ntest<i>2</i>\n
      \n
      \n|, actual + assert_equal %Q|
      \n

      リスト1.1: this is test<&>_

      \n
      test1\ntest1.5\n\ntest<i>2</i>
      \n
      \n|, actual end def test_list_pygments_lang @@ -539,7 +535,7 @@ def @chapter.list(id) %Q|
      def foo(a1, a2=:test)\n| +
                        %Q|  (1..3).times{\|i\| a.include?(:foo)}\n| +
                        %Q|  return true\n| +
      -                 %Q|end\n| +
      +                 %Q|end| +
                        %Q|
      \n| + %Q|
      \n|, actual end @@ -558,7 +554,7 @@ def @chapter.list(id) @book.config["highlight"]["html"] = "pygments" actual = compile_block("//list[samplelist][this is @{test}<&>_][]{\ndef foo(a1, a2=:test)\n (1..3).times{|i| a.include?(:foo)}\n return true\nend\n\n//}\n") - assert_equal "
      \n

      リスト1.1: this is test<&>_

      \n
      def foo(a1, a2=:test)\n  (1..3).times{|i| a.include?(:foo)}\n  return true\nend\n
      \n
      \n", actual + assert_equal "
      \n

      リスト1.1: this is test<&>_

      \n
      def foo(a1, a2=:test)\n  (1..3).times{|i| a.include?(:foo)}\n  return true\nend
      \n
      \n", actual end def test_list_ext @@ -595,7 +591,7 @@ def foo(a1, a2=:test)
      EOS - assert_equal expected, actual + assert_equal expected.chomp, actual end def test_listnum_pygments_lang @@ -612,7 +608,7 @@ def @chapter.list(id) @book.config["highlight"]["html"] = "pygments" actual = compile_block("//listnum[samplelist][this is @{test}<&>_][ruby]{\ndef foo(a1, a2=:test)\n (1..3).times{|i| a.include?(:foo)}\n return true\nend\n\n//}\n") - assert_equal "
      \n

      リスト1.1: this is test<&>_

      \n
      1 def foo(a1, a2=:test)\n2   (1..3).times{|i| a.include?(:foo)}\n3   return true\n4 end\n
      \n
      \n", actual + assert_equal "
      \n

      リスト1.1: this is test<&>_

      \n
      1 def foo(a1, a2=:test)\n2   (1..3).times{|i| a.include?(:foo)}\n3   return true\n4 end\n
      ", actual end def test_listnum_pygments_lang_without_lang @@ -630,7 +626,7 @@ def @chapter.list(id) @book.config["highlight"]["lang"] = "ruby" actual = compile_block("//listnum[samplelist][this is @{test}<&>_]{\ndef foo(a1, a2=:test)\n (1..3).times{|i| a.include?(:foo)}\n return true\nend\n\n//}\n") - assert_equal "
      \n

      リスト1.1: this is test<&>_

      \n
      1 def foo(a1, a2=:test)\n2   (1..3).times{|i| a.include?(:foo)}\n3   return true\n4 end\n
      \n
      \n", actual + assert_equal "
      \n

      リスト1.1: this is test<&>_

      \n
      1 def foo(a1, a2=:test)\n2   (1..3).times{|i| a.include?(:foo)}\n3   return true\n4 end\n
      ", actual end @@ -649,7 +645,7 @@ def test_emlist_pygments_lang @book.config["highlight"] = {} @book.config["highlight"]["html"] = "pygments" actual = compile_block("//emlist[][sql]{\nSELECT COUNT(*) FROM tests WHERE tests.no > 10 AND test.name LIKE 'ABC%'\n//}\n") - assert_equal "
      \n
      SELECT COUNT(*) FROM tests WHERE tests.no > 10 AND test.name LIKE 'ABC%'\n
      \n
      \n", actual + assert_equal "
      \n
      SELECT COUNT(*) FROM tests WHERE tests.no > 10 AND test.name LIKE 'ABC%'
      \n
      \n", actual end def test_emlist_caption @@ -709,7 +705,7 @@ def test_cmd_pygments @book.config["highlight"] = {} @book.config["highlight"]["html"] = "pygments" actual = compile_block("//cmd{\nlineA\nlineB\n//}\n") - assert_equal "
      \n
      lineA\nlineB\n
      \n
      \n", actual + assert_equal "
      \n
      lineA\nlineB
      \n
      \n", actual end def test_cmd_caption @@ -748,7 +744,7 @@ def @chapter.bibpaper(id) end actual = compile_block("//bibpaper[samplebib][sample bib @{bold}]{\na\nb\n//}\n") - assert_equal %Q|
      \n[1] sample bib bold\n

      ab

      \n|, actual + assert_equal %Q|
      \n[1] sample bib bold\n

      ab

      \n
      \n|, actual end def test_bibpaper_normalized @@ -757,7 +753,7 @@ def @chapter.bibpaper(id) end actual = compile_block("//bibpaper[sample=bib][sample bib @{bold}]{\na\nb\n//}\n") - assert_equal %Q|
      \n[1] sample bib bold\n

      ab

      \n|, actual + assert_equal %Q|
      \n[1] sample bib bold\n

      ab

      \n
      \n|, actual end def test_bibpaper_with_anchor @@ -766,7 +762,7 @@ def @chapter.bibpaper(id) end actual = compile_block("//bibpaper[samplebib][sample bib @{http://example.jp}]{\na\nb\n//}\n") - assert_equal %Q|
      \n[1] sample bib http://example.jp\n

      ab

      \n|, actual + assert_equal %Q|
      \n[1] sample bib http://example.jp\n

      ab

      \n
      \n|, actual end def column_helper(review) @@ -814,7 +810,6 @@ def test_column_2

      test

      inside column

      -

      next level

      EOS @@ -850,7 +845,6 @@ def test_column_ref

      test

      inside column

      -

      next level

      this is コラム「test」.

      EOS @@ -1017,6 +1011,70 @@ def test_ul_nest5 assert_equal expected, actual end + def test_ul_in_note + src =<<-EOS +//note{ + +aaaa +bbb + + * A + * B +//} +EOS + + expected =<<-EOS +
      +

      aaaabbb

      +
        +
      • A
      • +
      • B
      • +
      +
      +EOS + actual = compile_block(src) + assert_equal expected, actual + end + + def test_ul_in_note_and_emlist + src =<<-EOS +//note{ + +aaaa +bbb + +//emlist{ +abc +ddd + * A + * B +//} + + * A + * B +//} +EOS + + expected =<<-EOS +
      +

      aaaabbb

      +
      +
      abc
      +ddd
      + * A
      + * B
      +
      +
      +
        +
      • A
      • +
      • B
      • +
      +
      +EOS + actual = compile_block(src) + assert_equal expected, actual + end + def test_ol src =<<-EOS 3. AAA @@ -1107,6 +1165,24 @@ def test_inline_fn_with_tricky_id assert_equal expected, actual end + + ## inline nesting tests + def test_href_nest + actual = compile_inline("@{http://github.com,@{G}itHub}") + assert_equal %Q|GitHub|, actual + end + + def test_inline_tti_nest + actual = compile_inline("test @{aa@{inline test}bb} test2") + assert_equal %Q|test aainline testbb test2|, actual + end + + def test_inline_ttib_nest + actual = compile_inline("test @{aa@{inline @{te}st}bb} test2") + assert_equal %Q|test aainline testbb test2|, actual + end + + def test_inline_hd book = ReVIEW::Book::Base.load book.catalog = ReVIEW::Catalog.new({"CHAPS"=>%w(ch1.re ch2.re)}) @@ -1118,7 +1194,9 @@ def test_inline_hd builder = ReVIEW::HTMLBuilder.new comp = ReVIEW::Compiler.new(builder) builder.bind(comp, chap2, nil) - hd = builder.inline_hd("ch1|test1-1") + comp.setup_parser("@{ch1|test1-1}") + comp.parse("Paragraph") + hd = comp.result.to_doc assert_equal "「1.1 test1-1」", hd end @@ -1134,7 +1212,9 @@ def test_inline_hd_for_part builder = ReVIEW::HTMLBuilder.new comp = ReVIEW::Compiler.new(builder) builder.bind(comp, chap2, nil) - hd = builder.inline_hd("part1|part1-1") + comp.setup_parser("@{part1|part1-1}") + comp.parse("Paragraph") + hd = comp.result.to_doc assert_equal "「1.1 part1-1」", hd end diff --git a/test/test_idgxmlbuilder.rb b/test/test_idgxmlbuilder.rb index f2a3f0587..b65ee863b 100644 --- a/test/test_idgxmlbuilder.rb +++ b/test/test_idgxmlbuilder.rb @@ -1,8 +1,8 @@ # encoding: utf-8 require 'test_helper' -require 'review/compiler' require 'review/book' +require 'review/compiler' require 'review/idgxmlbuilder' require 'review/i18n' @@ -189,6 +189,18 @@ def test_quote assert_equal %Q|

      foobar

      buz

      |, actual end + ## XXX block content should be escaped. + def test_note + actual = compile_block("//note[this is @{test}<&>_]{\ntest1\ntest1.5\n\ntest@{2}\n//}\n") + assert_equal %Q|this is <b>test</b><&>_

      test1test1.5

      test2

      |, actual + end + + ## XXX block content should be escaped. + def test_memo + actual = compile_block("//memo[this is @{test}<&>_]{\ntest1\ntest1.5\n\ntest@{2}\n//}\n") + assert_equal %Q|this is <b>test</b><&>_

      test1test1.5

      test2

      |, actual + end + def test_major_blocks actual = compile_block("//note{\nA\n\nB\n//}\n//note[caption]{\nA\n//}") expected = %Q(

      A

      B

      caption

      A

      ) @@ -631,5 +643,4 @@ def test_block_raw4 expected = %Q(|idgxml <>!\"\n& ) assert_equal expected.chomp, actual end - end diff --git a/test/test_latexbuilder.rb b/test/test_latexbuilder.rb index cea5adbb6..b5435c322 100644 --- a/test/test_latexbuilder.rb +++ b/test/test_latexbuilder.rb @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- require 'test_helper' -require 'review/compiler' require 'review/book' +require 'review/compiler' require 'review/latexbuilder' require 'review/i18n' @@ -288,7 +288,7 @@ def test_emlistnum_caption def test_list actual = compile_block("//list[id1][cap1]{\nfoo\nbar\n\nbuz\n//}\n") - assert_equal %Q|\\reviewlistcaption{リスト1.1: cap1}\n\\begin{reviewlist}\nfoo\nbar\n\nbuz\n\\end{reviewlist}\n|, actual + assert_equal %Q|\n\\reviewlistcaption{リスト1.1: cap1}\n\\begin{reviewlist}\nfoo\nbar\n\nbuz\n\\end{reviewlist}\n|, actual end def test_list_lst @@ -308,7 +308,7 @@ def test_list_lst_with_lang def test_listnum actual = compile_block("//listnum[test1][ruby]{\nclass Foo\n def foo\n bar\n\n buz\n end\nend\n//}\n") - assert_equal %Q|\\reviewlistcaption{リスト1.1: ruby}\n\\begin{reviewlist}\n 1: class Foo\n 2: def foo\n 3: bar\n 4: \n 5: buz\n 6: end\n 7: end\n\\end{reviewlist}\n|, actual + assert_equal %Q|\n\\reviewlistcaption{リスト1.1: ruby}\n\\begin{reviewlist}\n 1: class Foo\n 2: def foo\n 3: bar\n 4: \n 5: buz\n 6: end\n 7: end\n\\end{reviewlist}\n|, actual end def test_listnum_lst @@ -340,7 +340,7 @@ def test_centering def test_noindent actual = compile_block("//noindent\nfoo\nbar\n\nfoo2\nbar2\n") - assert_equal %Q|\\noindent\nfoo\nbar\n\nfoo2\nbar2\n|, actual + assert_equal %Q|\\noindent\nfoobar\n\nfoo2bar2\n|, actual end def test_image @@ -411,6 +411,17 @@ def @chapter.image(id) assert_equal %Q|\\begin{reviewimage}\n\\includegraphics[width=\\maxwidth]{./images/chap1-sampleimg.png}\n\\reviewindepimagecaption{図: sample photo}\n\\end{reviewimage}\n|, actual end + def test_indepimage_esc + def @chapter.image(id) + item = Book::ImageIndex::Item.new("sampleimg",1) + item.instance_eval{@path="./images/chap1-sampleimg.png"} + item + end + + actual = compile_block("//indepimage[sean_2_10][sample photo][]\n") + assert_equal %Q|\\begin{reviewimage}\n\\includegraphics[width=\\maxwidth]{./images/chap1-sampleimg.png}\n\\reviewindepimagecaption{図: sample photo}\n\\end{reviewimage}\n|, actual + end + def test_indepimage_without_caption def @chapter.image(id) item = Book::ImageIndex::Item.new("sampleimg",1) @@ -544,7 +555,6 @@ def test_column_1 \\addcontentsline{toc}{subsection}{prev column} inside prev column - \\end{reviewcolumn} \\begin{reviewcolumn} @@ -553,7 +563,6 @@ def test_column_1 \\addcontentsline{toc}{subsection}{test} inside column - \\end{reviewcolumn} EOS @config["toclevel"] = 3 @@ -575,9 +584,7 @@ def test_column_2 \\reviewcolumnhead{}{test} inside column - \\end{reviewcolumn} - \\subsection*{next level} \\label{sec:1-0-1} EOS @@ -663,7 +670,6 @@ def test_ul_nest1 \\begin{itemize} \\item AA \\end{itemize} - \\end{itemize} EOS actual = compile_block(src) @@ -686,13 +692,11 @@ def test_ul_nest3 \\begin{itemize} \\item AA \\end{itemize} - \\item BBB \\begin{itemize} \\item BB \\end{itemize} - \\end{itemize} EOS actual = compile_block(src) diff --git a/test/test_lineinput.rb b/test/test_lineinput.rb index f8c209e5d..08167ce48 100644 --- a/test/test_lineinput.rb +++ b/test/test_lineinput.rb @@ -57,6 +57,7 @@ def test_ungets assert_equal(-1, li.lineno) # XXX: OK? end +=begin def test_peek li = LineInput.new(StringIO.new) assert_equal nil, li.peek @@ -99,7 +100,7 @@ def test_gets_unless assert_equal "abc\n", li.gets_unless(/^X/) assert_equal nil, li.gets_unless(/^d/) end - +=end def test_each content = "abc\ndef\nghi" io = StringIO.new(content) @@ -118,7 +119,7 @@ def test_while_match assert_equal 2, li.lineno assert_equal "ghi", li.gets end - +=begin def test_getlines_while io = StringIO.new("abc\ndef\nghi") li = LineInput.new(io) @@ -128,7 +129,7 @@ def test_getlines_while assert_equal 2, li.lineno assert_equal "ghi", li.gets end - +=end def test_until_match io = StringIO.new("abc\ndef\nghi") li = LineInput.new(io) @@ -137,7 +138,7 @@ def test_until_match assert_equal 1, li.lineno assert_equal "def\n", li.gets end - +=begin def test_getlines_until io = StringIO.new("abc\ndef\nghi") li = LineInput.new(io) @@ -176,5 +177,6 @@ def test_until_terminator2 assert_equal ["abc\n", "def\n"], data assert_equal 3, li.lineno end +=end end diff --git a/test/test_location.rb b/test/test_location.rb index 6cd5911b4..0fcdcdf88 100644 --- a/test/test_location.rb +++ b/test/test_location.rb @@ -1,26 +1,30 @@ require 'test_helper' +require 'review/location' +require 'review/book' +require 'review/textbuilder' require 'review/compiler' class LocationTest < Test::Unit::TestCase def setup + @builder = ReVIEW::TEXTBuilder.new + dummy_book = ReVIEW::Book::Base.load + dummy_chapter = ReVIEW::Book::Chapter.new(dummy_book, 1, '-', nil, StringIO.new("a\nb\nc\n")) + @compiler = ReVIEW::Compiler.new(@builder) + @location = ReVIEW::Location.new("foo", @compiler) + @builder.bind(@compiler, dummy_chapter, @location) + @compiler.setup_parser(dummy_chapter.content) end def test_lineno - f = StringIO.new("a\nb\nc\n") - location = ReVIEW::Location.new("foo", f) - assert_equal 0, location.lineno - f.gets - assert_equal 1, location.lineno + assert_equal 1, @location.lineno end def test_string - location = ReVIEW::Location.new("foo", StringIO.new("a\nb\nc\n")) - assert_equal "foo:0", location.string + assert_equal "foo:1", @location.string end def test_to_s - location = ReVIEW::Location.new("foo", StringIO.new("a\nb\nc\n")) - assert_equal "foo:0", "#{location}" + assert_equal "foo:1", "#{@location}" end def test_to_s_nil diff --git a/test/test_markdownbuilder.rb b/test/test_markdownbuilder.rb index ba06a2ebc..03d95718b 100644 --- a/test/test_markdownbuilder.rb +++ b/test/test_markdownbuilder.rb @@ -1,8 +1,8 @@ # encoding: utf-8 require 'test_helper' -require 'review/compiler' require 'review/book' +require 'review/compiler' require 'review/markdownbuilder' require 'review/i18n' @@ -10,6 +10,7 @@ class MARKDOWNBuilderTest < Test::Unit::TestCase include ReVIEW def setup + ReVIEW::I18n.setup @builder = MARKDOWNBuilder.new() @config = { "secnolevel" => 2, # for IDGXMLBuilder, HTMLBuilder @@ -140,9 +141,9 @@ def test_table assert_equal "|testA|testB|\n|:--|:--|\n|contentA|contentB|\n\n", actual end - def test_ruby - actual = compile_block("@{謳,うた}い文句") - assert_equal "うたい文句\n\n", actual + def test_inline_ruby + actual = compile_inline("@{謳,うた}い文句") + assert_equal "うたい文句", actual end end diff --git a/test/test_md2inaobuilder.rb b/test/test_md2inaobuilder.rb index 1ee2b3cf5..1f72a292f 100644 --- a/test/test_md2inaobuilder.rb +++ b/test/test_md2inaobuilder.rb @@ -1,8 +1,8 @@ # encoding: utf-8 require 'test_helper' -require 'review/compiler' require 'review/book' +require 'review/compiler' require 'review/md2inaobuilder' require 'review/i18n' @@ -10,6 +10,7 @@ class MD2INAOBuilderTest < Test::Unit::TestCase include ReVIEW def setup + ReVIEW::I18n.setup @builder = MD2INAOBuilder.new() @config = { "secnolevel" => 2, # for IDGXMLBuilder, HTMLBuilder @@ -25,7 +26,7 @@ def setup end def test_paragraph - actual = compile_block("Hello, world!") + actual = compile_block("Hello, world!\n") assert_equal " Hello, world!\n\n", actual end @@ -59,16 +60,16 @@ def test_list def test_comment actual = compile_block("//comment{\nHello, world!\n//}\n") - assert_equal "\nHello, world!\n\n", actual + assert_equal "\n Hello, world!\n\n\n\n", actual end def test_ruby_mono - actual = compile_block("@{謳,うた}い文句") + actual = compile_block("@{謳,うた}い文句\n") assert_equal " 謳(うた)い文句\n\n", actual end def test_ruby_group - actual = compile_block("@{欠伸,あくび}が出る") + actual = compile_block("@{欠伸,あくび}が出る\n") assert_equal " 欠伸(あくび)が出る\n\n", actual end diff --git a/test/test_pdfmaker.rb b/test/test_pdfmaker.rb index 7aa86703a..9281457e8 100644 --- a/test/test_pdfmaker.rb +++ b/test/test_pdfmaker.rb @@ -34,6 +34,8 @@ def test_check_book_existed assert !File.exist?(pdf_file) end end + ensure + $stderr = STDERR end def test_check_book_none diff --git a/test/test_pdfmaker_cmd.rb b/test/test_pdfmaker_cmd.rb index 27b58c3d7..9eb52954f 100644 --- a/test/test_pdfmaker_cmd.rb +++ b/test/test_pdfmaker_cmd.rb @@ -6,7 +6,7 @@ require 'yaml' require 'rbconfig' -REVIEW_PDFMAKER = File.expand_path('../bin/review-pdfmaker', File.dirname(__FILE__)) +REVIEW_PDFMAKER = File.expand_path('../bin/review-pdfmaker-peg', File.dirname(__FILE__)) class PDFMakerCmdTest < Test::Unit::TestCase def setup diff --git a/test/test_textutils.rb b/test/test_textutils.rb index e8055e107..c34f1a17e 100644 --- a/test/test_textutils.rb +++ b/test/test_textutils.rb @@ -29,40 +29,4 @@ def test_detab_with_arg detabed = detab("\tabc\tdef", 4) assert_equal " abc def", detabed end - - def test_split_paragraph_empty_nil - ret = @tu_nil.split_paragraph([]) - assert_equal ret, [""] - end - - def test_split_paragraph_empty_p - ret = @tu_p.split_paragraph([]) - assert_equal ret, ["

      "] - end - - def test_split_paragraph_p - ret = @tu_p.split_paragraph(["abc"]) - assert_equal ["

      abc

      "], ret - ret = @tu_p.split_paragraph(["abc","def"]) - assert_equal ["

      abcdef

      "], ret - ret = @tu_p.split_paragraph(["abc","","def"]) - assert_equal ["

      abc

      ","

      def

      "], ret - ret = @tu_p.split_paragraph(["abc","","","def"]) - assert_equal ["

      abc

      ","

      def

      "], ret - ret = @tu_p.split_paragraph(["abc","","","def","ghi"]) - assert_equal ["

      abc

      ","

      defghi

      "], ret - end - - def test_split_paragraph_nil - ret = @tu_nil.split_paragraph(["abc"]) - assert_equal ["abc"], ret - ret = @tu_nil.split_paragraph(["abc","def"]) - assert_equal ["abcdef"], ret - ret = @tu_nil.split_paragraph(["abc","","def"]) - assert_equal ["abc","def"], ret - ret = @tu_nil.split_paragraph(["abc","","","def"]) - assert_equal ["abc","def"], ret - ret = @tu_nil.split_paragraph(["abc","","","def","ghi"]) - assert_equal ["abc","defghi"], ret - end end