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