class Raabro::Tree
def c0; @children[0]; end
def c0; @children[0]; end
def c1; @children[1]; end
def c1; @children[1]; end
def c2; @children[2]; end
def c2; @children[2]; end
def c3; @children[3]; end
def c3; @children[3]; end
def c4; @children[4]; end
def c4; @children[4]; end
def clast; @children.last; end
def clast; @children.last; end
def empty?
def empty? @result == 1 && @length == 0 end
def even_children
def even_children cs = []; @children.each_with_index { |c, i| cs << c if i.even? }; cs end
def extract_error
def extract_error bro.pp(self, colors: true) err_tree, stack = lookup_error || lookup_all_error line, column = line_and_column(err_tree.offset) err_message = if stack path = stack .compact.reverse.take(3).reverse .collect(&:inspect).join('/') "parsing failed .../#{path}" else "parsing failed, not all input was consumed" end visual = visual(line, column) [ line, column, err_tree.offset, err_message, visual ] end
def gather(name=nil, acc=[])
def gather(name=nil, acc=[]) name = name ? name.to_s : nil if (@name && name == nil) || (@name.to_s == name) acc << self else subgather(name, acc) end acc end
def initialize(name, parter, input)
def initialize(name, parter, input) @result = 0 @name = name @parter = parter @input = input @offset = input.offset @length = 0 @children = [] end
def line_and_column(offset)
def line_and_column(offset) line = 1 column = 0 (0..offset).each do |off| column += 1 next unless @input.at(off) == "\n" line += 1 column = 0 end [ line, column ] end
def lookup(name=nil)
def lookup(name=nil) name = name ? name.to_s : nil return self if @name && name == nil return self if @name.to_s == name sublookup(name) end
def lookup_all_error
consuming all the input)
words lookup the point up until which the parser stopped (not
Not "lookup all errors" but "lookup all error", in other
def lookup_all_error nt "lae(): "; Raabro.pp(self, colors: true) @children.each { |c| return [ c, nil ] if c.result == 0 } @children.reverse.each { |c| es = c.lookup_all_error; return es if es } nil end
def lookup_error(stack=[])
def lookup_error(stack=[]) nt "le(): "; Raabro.pp(self, colors: true) return nil if @result != 0 return [ self, stack ] if @children.empty? @children.each { |c| es = c.lookup_error(stack.dup.push(self.name)) return es if es } nil end
def nonstring(l=7)
def nonstring(l=7) @input.string[@offset, l] end
def odd_children
def odd_children cs = []; @children.each_with_index { |c, i| cs << c if i.odd? }; cs end
def prune!
def prune! @children = successful_children end
def string
def string @input.string[@offset, @length] end
def subgather(name=nil, acc=[])
def subgather(name=nil, acc=[]) @children.each { |c| c.gather(name, acc) } acc end
def sublookup(name=nil)
def sublookup(name=nil) @children.each { |c| if n = c.lookup(name); return n; end } nil end
def successful_children
def successful_children @children.select { |c| c.result == 1 } end
def to_a(opts={})
def to_a(opts={}) opts = Array(opts).inject({}) { |h, e| h[e] = true; h } \ unless opts.is_a?(Hash) cn = if opts[:leaves] && (@result == 1) && @children.empty? string elsif opts[:children] != false @children.collect { |e| e.to_a(opts) } else @children.length end [ @name, @result, @offset, @length, @note, @parter, cn ] end
def to_s(depth=0, io=StringIO.new)
def to_s(depth=0, io=StringIO.new) io.print "\n" if depth > 0 io.print ' ' * depth io.print "#{@result} #{@name.inspect} #{@offset},#{@length}" io.print result == 1 && children.size == 0 ? ' ' + string.inspect : '' @children.each { |c| c.to_s(depth + 1, io) } depth == 0 ? io.string : nil end
def visual(line, column)
def visual(line, column) @input.string.split("\n")[line - 1] + "\n" + ' ' * (column - 1) + '^---' end