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