lib/qed/parser.rb in qed-2.3.0 vs lib/qed/parser.rb in qed-2.4.0

- old
+ new

@@ -34,39 +34,46 @@ def parse_lines case options[:mode] when :comment parse_comment_lines else - index = -1 + index = 0 #-1 File.readlines(file).to_a.map do |line| [index += 1, line] end end end # TODO: It would be nice if we could get ther require statement for the # comment mode to be relative to an actual loadpath. def parse_comment_lines - omit = false + ruby_omit = false + rdoc_omit = false lines = [ [0, "Load #{File.basename(file)} script.\n"], [0, "\n"], [0, " require '#{file}'\n"] ] - index = 0 + index = 1 File.readlines(file).each do |l| case l + when /^=begin(?!\s+qed)/ + ruby_omit = true + when /^=end/ + ruby_omit = false when /^\s*\#\-\-\s*$/ - omit = true + rdoc_omit = true when /^\s*\#\+\+\s*$/ - omit = false - when /^\s*\#\ \-\-/ # ? - # -- skip internal comments - when /^\s*\#/ - lines << [index, l.lstrip.sub(/^\#\ ?/, '')] unless omit + rdoc_omit = false + ##when /^\s*\#\ \-\-/ # not needed just double comment + ## # -- skip internal comments + when /^\s*##/ + ## skip internal comments + when /^\s*\#/ + lines << [index, l.lstrip.sub(/^\#\ ?/, '')] unless (ruby_omit or rdoc_omit) else - lines << [index, "\n"] unless lines.last[1] == "\n" + lines << [index, "\n"] unless lines.last[1] == "\n" unless (ruby_omit or rdoc_omit) end index += 1 end lines end @@ -133,37 +140,41 @@ end =end def parse tree = [] - mode = :rem + flush = true pend = false - block = Block.new + block = Block.new(file) lines.each do |lineno, line| case line when /^\s*$/ - case mode - when :rem - pend = true unless line == 0 - block.rem << [lineno, line] - when :raw + if flush + pend = true unless lineno == 0 block.raw << [lineno, line] + else + block.raw << [lineno, line] end when /\A\s+/ - mode = :raw + if flush + tree << block.ready!(flush, tree.last) + block = Block.new(file) + end + pend = false + flush = false block.raw << [lineno, line] else - if pend || mode == :raw - pend = false - mode = :rem - tree << block.ready! - block = Block.new + if pend || !flush + tree << block.ready!(flush, tree.last) + pend = false + flush = true + block = Block.new(file) end - block.rem << [lineno, line] + block.raw << [lineno, line] end end - tree << block.ready! + tree << block.ready!(flush, tree.last) @ast = tree end # TODO: We need to preserve the indentation for the verbatim reporter. #def clean_quote(text) @@ -174,100 +185,163 @@ # text.rstrip #end # Section Block class Block - # Block commentary. - attr :rem - # Block raw code/text. attr :raw + # previous block + attr :back_step + + # next block + attr :next_step + # - def initialize - @rem = [] - @raw = [] - @has_code = true + def initialize(file) + @file = file + @raw = [] + @type = :description + @back_step = nil + @next_step = nil end # - def ready! - @commentary = rem.map{ |lineno, line| line }.join - @example = raw.map{ |lineno, line| line }.join - @has_code = false if @raw.empty? - @has_code = false if continuation? + def ready!(flush, back_step) + @flush = flush + @back_step = back_step + + @text = raw.map{ |lineno, line| line }.join + @type = parse_type + + @back_step.next_step = self if @back_step + self end # - def commentary - @commentary + def to_s + case type + when :description + text + else + text + end end # - def example - @example + def text + @text end + # + def flush? + @flush + end + # Returns an Array of prepared example text # for use in advice. def arguments - continuation? ? [example_argument] : [] + if next_step && next_step.data? + [next_step.sample_text] + else + [] + end end - # - def code? - @has_code + # What type of block is this? + def type + @type end + # + def head? ; @type == :head ; end + + # + def desc? ; @type == :desc ; end + + # + def code? ; @type == :code ; end + + # Any commentary ending in `...` or `:` will mark the following + # block as a plain text *sample* and not example code to be evaluated. + def data? ; @type == :data ; end + + # + alias_method :header?, :head? + + # + alias_method :description?, :desc? + + # First line of example text. def lineno @line ||= @raw.first.first end # def code - @example + @code ||= tweak_code end - # - def eval_code - @eval_code ||= tweak_code - end - - # - def tweak_code - code = example.dup - code.gsub!(/\n\s*\#\ ?\=\>/, '.assert == ') - code.gsub!(/\s*\#\ ?\=\>/, '.assert == ') - code - end - # Clean up the example text, removing unccesseary white lines # and triple quote brackets, but keep indention intact. - def clean_example - text = example.chomp.sub(/\A\n/,'') - if md = /\A["]{3,}(.*?)["]{3,}\Z/.match(text) - text = md[1] + def clean_text + str = text.chomp.sub(/\A\n/,'') + if md = /\A["]{3,}(.*?)["]{3,}\Z/.match(str) + str = md[1] end - text.rstrip + str.rstrip end - # When the example is raw text and passed to an adivce block, this + # When the text is sample text and passed to an adivce block, this # provides the prepared form of the example text, removing white lines, # triple quote brackets and indention. - def example_argument - text = example.tabto(0).chomp.sub(/\A\n/,'') - if md = /\A["]{3,}(.*?)["]{3,}\Z/.match(text) - text = md[1] + def sample_text + str = text.tabto(0).chomp.sub(/\A\n/,'') + if md = /\A["]{3,}(.*?)["]{3,}\Z/.match(str) + str = md[1] end - text.rstrip + str.rstrip end - # And commentary ending in `...` or `:` will mark the following - # example as plain text and not code to be evaluated. - def continuation? - /(\.\.\.|\:)\s*\Z/m =~ commentary + # TODO: object_hexid + def inspect + %[#<Block:#{object_id} "#{text[0..25]} ...">] + end + + protected + + # + def next_step=(n) + @next_step = n + end + + private + + # + def parse_type + if flush? + if /\A[=#]/ =~ text + :head + else + :desc + end + else + if back_step && /(\.\.\.|\:)\s*\Z/m =~ back_step.text.strip + :data + else + :code + end + end + end + + # + def tweak_code + code = text.dup + code.gsub!(/\n\s*\#\ ?\=\>/, '.assert = ') + code.gsub!(/\s*\#\ ?\=\>/, '.assert = ') + code end end end