Class: QED::Parser
Overview
The parser breaks down a demonstandum into structured object to passed thru the script evaluator.
Technically is defines it’s own markup language but for interoperability sake it is RDoc and/or Markdown.
Instance Attribute Summary collapse
-
#demo ⇒ Object
readonly
The demo to parse.
-
#mode ⇒ Object
readonly
Parser mode.
-
#steps ⇒ Object
readonly
Abstract Syntax Tree.
Instance Method Summary collapse
-
#file ⇒ Object
The demo’s file to parse.
-
#initialize(demo, options = {}) ⇒ Parser
constructor
Setup new parser instance.
-
#lines ⇒ Object
Lines of demo, prepared for parsing into steps.
-
#parse ⇒ Object
Parse demo file into steps.
-
#parse_comment_lines ⇒ Object
Parse comment lines into a format that the parse method can use.
-
#parse_lines ⇒ Object
Prepare lines for parsing into steps.
Constructor Details
#initialize(demo, options = {}) ⇒ Parser
Setup new parser instance.
24 25 26 27 28 |
# File 'lib/qed/parser.rb', line 24 def initialize(demo, ={}) @demo = demo @mode = [:mode] @steps = [] end |
Instance Attribute Details
#demo ⇒ Object (readonly)
The demo to parse.
31 32 33 |
# File 'lib/qed/parser.rb', line 31 def demo @demo end |
#mode ⇒ Object (readonly)
Parser mode.
34 35 36 |
# File 'lib/qed/parser.rb', line 34 def mode @mode end |
#steps ⇒ Object (readonly)
Abstract Syntax Tree
37 38 39 |
# File 'lib/qed/parser.rb', line 37 def steps @steps end |
Instance Method Details
#file ⇒ Object
The demo’s file to parse.
40 41 42 |
# File 'lib/qed/parser.rb', line 40 def file demo.file end |
#lines ⇒ Object
Lines of demo, prepared for parsing into steps.
45 46 47 |
# File 'lib/qed/parser.rb', line 45 def lines @lines ||= parse_lines end |
#parse ⇒ Object
Parse demo file into steps.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/qed/parser.rb', line 100 def parse steps = [] blank = false indented = false fenced = false # inside a ``` ruby/bare code fence foreign = false # inside a ``` non-ruby code fence explain = [] example = [] #Step.new(file) lines.each do |lineno, line| case line when /\A```ruby\s*$/ # ```ruby opens a ruby fence fenced = true foreign = false next when /\A```\s*$/ # bare ``` either opens or closes a fence if fenced || foreign fenced = false foreign = false next else fenced = true # bare ``` opens a ruby fence next end when /\A```\S/ # ```<language> opens a foreign fence foreign = true next else # skip lines inside foreign code fences next if foreign end if fenced # lines inside a ruby fence are treated as example code indented = true blank = false example << [lineno, line] else case line when /^\s*$/ # blank line blank = true if indented example << [lineno, line] else explain << [lineno, line] end when /\A\s+/ # indented indented = true blank = false example << [lineno, line] else if indented or blank steps << Step.new(demo, explain, example, steps.last) explain, example = [], [] end indented = false blank = false explain << [lineno, line] end end end steps << Step.new(demo, explain, example, steps.last) @steps = steps end |
#parse_comment_lines ⇒ Object
Parse comment lines into a format that the parse method can use.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/qed/parser.rb', line 66 def parse_comment_lines ruby_omit = false rdoc_omit = false lines = [ [0, "Load #{File.basename(file)} script.\n"], [0, "\n"], [0, " require '#{file}'\n"] ] 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*$/ rdoc_omit = true when /^\s*\#\+\+\s*$/ 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" unless (ruby_omit or rdoc_omit) end index += 1 end lines end |
#parse_lines ⇒ Object
Prepare lines for parsing into steps.
50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/qed/parser.rb', line 50 def parse_lines case mode when :comment parse_comment_lines else index = 0 #-1 File.readlines(file).to_a.map do |line| [index += 1, line] end end end |