lib/raabro.rb in raabro-1.0.5 vs lib/raabro.rb in raabro-1.1.0

- old
+ new

@@ -1,8 +1,8 @@ #-- -# Copyright (c) 2015-2015, John Mettraux, jmettraux@gmail.com +# Copyright (c) 2015-2016, John Mettraux, jmettraux@gmail.com # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell @@ -24,11 +24,11 @@ #++ module Raabro - VERSION = '1.0.5' + VERSION = '1.1.0' class Input attr_accessor :string, :offset attr_reader :options @@ -49,10 +49,15 @@ s = str_or_regex.to_s l = s.length @string[@offset, l] == s ? l : false end end + + def tring(l=-1) + + l < 0 ? @string[@offset..l] : @string[@offset, l] + end end class Tree attr_accessor :name, :input @@ -69,10 +74,21 @@ @offset = input.offset @length = 0 @children = [] end + def c0; @children[0]; end + def c1; @children[1]; end + def c2; @children[2]; end + def c3; @children[3]; end + def c4; @children[4]; end + + def empty? + + @result == 1 && @length == 0 + end + def successful_children @children.select { |c| c.result == 1 } end @@ -86,39 +102,57 @@ @input.string[@offset, @length] end def lookup(name) - name = name.to_s + name = name ? name.to_s : nil + return self if @name && name == nil return self if @name.to_s == name + sublookup(name) + end + + def sublookup(name) + @children.each { |c| if n = c.lookup(name); return n; end } + nil end def gather(name, acc=[]) - name = name.to_s + name = name ? name.to_s : nil - if @name.to_s == name + if (@name && name == nil) || (@name.to_s == name) acc << self else - @children.each { |c| c.gather(name, acc) } + subgather(name, acc) end acc end + def subgather(name, acc=[]) + + @children.each { |c| c.gather(name, acc) } + + acc + end + def to_a(opts={}) opts = Array(opts).inject({}) { |h, e| h[e] = true; h } \ unless opts.is_a?(Hash) cn = - opts[:leaves] && (@result == 1) && @children.empty? ? - string : - @children.collect { |e| e.to_a(opts) } + 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) @@ -130,10 +164,20 @@ @children.each { |c| c.to_s(depth + 1, io) } depth == 0 ? io.string : nil end + + def odd_children + + cs = []; @children.each_with_index { |c, i| cs << c if i.odd? }; cs + end + + def even_children + + cs = []; @children.each_with_index { |c, i| cs << c if i.even? }; cs + end end module ModuleMethods def _match(name, input, parter, regex_or_string) @@ -179,10 +223,14 @@ method(parser.to_sym) end def _parse(parser, input) + #p [ caller.length, parser, input.tring ] + #r = _narrow(parser).call(input) + #p [ caller.length, parser, input.tring, r.to_a(children: false) ] + #r _narrow(parser).call(input) end def seq(name, input, *parsers) @@ -238,13 +286,15 @@ r.children << cc input.offset = start if greedy - if cc.result == 1 && cc.length > (c ? c.length : -1) + if cc.result == 1 && cc.length >= (c ? c.length : -1) c.result = 0 if c c = cc + else + cc.result = 0 end else c = cc break if c.result == 1 end @@ -278,10 +328,11 @@ loop do c = _parse(parser, input) r.children << c break if c.result != 1 count += 1 + break if c.length < 1 break if max && count == max end if count >= min && (max == nil || count <= max) r.result = 1 @@ -343,27 +394,32 @@ r.result = 0 if c.result != 1 end if r.result == 1 - i = 1 - count = 0 + i = 0 loop do - i = (i + 1) % 2 - pa = i == 0 ? eltpa : seppa + add = true - c = _parse(pa, input) - r.children << c + st = i > 0 ? _parse(seppa, input) : nil + et = st == nil || st.result == 1 ? _parse(eltpa, input) : nil - break if c.result != 1 + break if st && et && st.empty? && et.result == 0 + break if st && et && st.empty? && et.empty? - count += 1 + r.children << st if st + r.children << et if et + + break if et == nil + break if et.result != 1 + + i = i + 1 end - r.result = 0 if jseq && count < 1 + r.result = 0 if jseq && i == 0 end if r.result == 1 && endpa c = _parse(endpa, input) r.children << c @@ -413,29 +469,41 @@ return nil if opts[:prune] != false && t.result != 1 t = t.children.first if t.parter == :all - return rewrite(t) if opts[:rewrite] != false && rewrite(0) == true + return rewrite(t) if opts[:rewrite] != false t end + def rewrite_(tree) + + t = tree.lookup(nil) + + t ? rewrite(t) : nil + end + def rewrite(tree) return !! methods.find { |m| m.to_s.match(/^rewrite_/) } if tree == 0 # return true when "rewrite_xxx" methods seem to have been provided send("rewrite_#{tree.name}", tree) end - end - extend ModuleMethods - def self.included(target) + def make_includable - target.instance_eval do - extend ::Raabro::ModuleMethods - extend self + def self.included(target) + + target.instance_eval do + extend ::Raabro::ModuleMethods + extend self + end + end end end + extend ModuleMethods + + make_includable end