Module: Markup

Defined in:
lib/rsyntaxtree/markup_parser.rb

Class Method Summary collapse

Class Method Details

.deepest_charpos(cause, best = 0) ⇒ Object

Largest charpos anywhere in a parse-failure cause tree: the position the parser actually reached before giving up.



218
219
220
221
222
223
# File 'lib/rsyntaxtree/markup_parser.rb', line 218

def deepest_charpos(cause, best = 0)
  pos = cause.respond_to?(:pos) && cause.pos ? cause.pos.charpos : 0
  best = [best, pos].max
  cause.children&.each { |child| best = deepest_charpos(child, best) }
  best
end

.parse(txt) ⇒ Object



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/rsyntaxtree/markup_parser.rb', line 225

def parse(txt)
  begin
    parsed = @parser.parse(txt)
  rescue Parslet::ParseFailed => e
    # The cause is kept: the deepest node of the failure tree is where the
    # parse actually got stuck, which is what structured errors report.
    return { status: :error, text: txt, charpos: deepest_charpos(e.parse_failure_cause) }
  end

  applied = @evaluator.apply(parsed)
  # A label holding a single named part (a whole-label matrix, nothing
  # else) comes back as one hash, not a one-element array.
  applied = [applied] unless applied.is_a?(Array)

  results = { enclosure: :none, triangle: false, paths: [], contents: [], color: nil, region: false, region_color: nil }
  applied.each do |h|
    # Region shade (whole-subtree background). '%' sets it on; an optional
    # color right after '%' overrides the default shade color.
    if h[:region]
      results[:region] = true
      region_color = h[:region][:region_color]
      results[:region_color] = region_color[:color_value].to_s if region_color && region_color[:color_value]
    end
    if h[:enclosure]
      results[:enclosure] = case h[:enclosure].to_s
                            when '###'
                              :brectangle
                            when '##'
                              :rectangle
                            when '#'
                              :brackets
                            else
                              :none
                            end
    end
    results[:triangle] = h[:triangle].to_s == '^' if h[:triangle]
    results[:paths] = h[:paths] if h[:paths]
    # Handle color specification
    if h[:color] && h[:color][:color_value]
      color_value = h[:color][:color_value].to_s
      # Prepend # if it's a hex color without it (parser captures just the hex part after #)
      results[:color] = color_value
    end
    results[:contents] << h if h[:type] == :text || h[:type] == :border || h[:type] == :bborder
    # A label that is one whole matrix arrives under its own key in the
    # top-level hash; the matrix element becomes the label's only line.
    results[:contents] << { type: :text, elements: [h[:whole_label_matrix]] } if h[:whole_label_matrix]
  end
  { status: :success, results: results }
end