arboretum 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 42a7d24be72182eafaad9b254b40ff5738423389
4
- data.tar.gz: 5e0fc2574eb3bbc059c94dd9213dd7f7283c35d4
3
+ metadata.gz: 53ab23c0b718279ac0f58181b1b57cc75a610aa1
4
+ data.tar.gz: 964672ec600783cb39cad917b61deba000bd544f
5
5
  SHA512:
6
- metadata.gz: 44b8504954777d1d5090fd11cbeba70dcd462d47a117d9b27a1b08de0b491fa74c41062cfa76cfb1e28f709a74779d0c9023ab48922392b61e1fac92ff92a95d
7
- data.tar.gz: ee812ae2721613864054cd0d605f217bff0495e34021c0e77e2d597ca65b35763024b9f5a5d38c9b2a84fe404a523ec4e25540e3e685a25703949528fc3ef740
6
+ metadata.gz: 0f141ef672014ac90376357b7edad9335e6653d27eebd23620bdce06e4f5bc58ce8da6890c1cf6f0255de622f52b08129b88dff9932e6ff5e36b6dfe48a9c837
7
+ data.tar.gz: d1f8c0b8e694062e19ca877c1fcb3a4c1aae57eb8856615660f7f6a33d26cde5d0e37d8356f948e2ced718668ded81c52c8fead8bdb3c3ed49a3fd317cc932ec
@@ -1,3 +1,3 @@
1
- require_relative 'arboretum/xml'
1
+ require_relative 'arboretum/scandent'
2
2
  require_relative 'arboretum/doctree'
3
- require_relative 'arboretum/scandent'
3
+ require_relative 'arboretum/xml'
@@ -0,0 +1,49 @@
1
+ require 'fiber'
2
+
3
+ class ArboretumFiber
4
+ def self.ROOT_FIBER
5
+ @@ROOT_FIBER
6
+ end
7
+ def self.set_root_fiber(fiber)
8
+ @@ROOT_FIBER = fiber
9
+ end
10
+ end
11
+
12
+ ArboretumFiber.set_root_fiber(Fiber.current)
13
+
14
+ class Debtor
15
+ def initialize
16
+ @resource = nil
17
+ @locked = true
18
+ @creditors = Array.new
19
+ end
20
+ def set_resource(rsc)
21
+ @resource = rsc
22
+ end
23
+ alias_method :set, :set_resource
24
+ def resource
25
+ begin
26
+ if locked?
27
+ @creditors << Fiber.current
28
+ Fiber.yield
29
+ end
30
+ rescue FiberError
31
+ puts "Warning: Tried to yield the root Fiber on a locked resource call. Returning resource anyways..."
32
+ end
33
+ @resource
34
+ end
35
+ def resource!
36
+ @resource
37
+ end
38
+ def locked?
39
+ @locked
40
+ end
41
+ def free?
42
+ !@locked
43
+ end
44
+ def free
45
+ @locked = false
46
+ @creditors.each {|c| c.resume }
47
+ @creditors = Array.new
48
+ end
49
+ end
@@ -1,3 +1,7 @@
1
+ require 'promise'
2
+ require 'forwardable'
3
+ require 'securerandom'
4
+
1
5
  module Arboretum
2
6
  module DocTree
3
7
  module Counters
@@ -60,21 +64,21 @@ module Arboretum
60
64
  end # Counters
61
65
 
62
66
  module Elements
63
- require 'forwardable'
64
- require 'securerandom'
65
- require_relative 'scandent'
66
-
67
67
  # Tree is a representation of a tree data structure consisting of elements
68
68
  # A Tree holds only reference to the root Element of the tree
69
69
  # A tree is useful for contextual operations on elements with the root as an ancestor
70
70
  class Tree
71
71
  include Enumerable
72
72
 
73
- attr_accessor :root
73
+ attr_accessor :root, :id_cache
74
74
 
75
75
  def initialize(root=nil)
76
- @root = root # Element
77
- @listeners = [] # Array of GroupListeners
76
+ @root = root # Element
77
+ @listeners = Array.new # Array of GroupListeners
78
+
79
+ @id_cache = Hash.new # Hash: String => Element
80
+
81
+ root.update_tree_residence(self)
78
82
  end
79
83
 
80
84
  # Redefine the `each` method to iterate through all elements in the tree in depth-first order
@@ -94,6 +98,24 @@ module Arboretum
94
98
  Array.new.tap {|list| self.each {|element| list << element}}
95
99
  end
96
100
 
101
+ def id_cache_add(id, element)
102
+ @id_cache[id] = element
103
+ end
104
+
105
+ def id_cache_remove(id)
106
+ @id_cache.delete(id)
107
+ end
108
+
109
+ def id_cache_get(id)
110
+ @id_cache[id].tap {|element| yield element if block_given?}
111
+ end
112
+ alias_method :element_from_id, :id_cache_get
113
+
114
+ def element_from_id_hash(hash_id)
115
+ raise IndexError.new("Tried to get element from hash id with no hash: #{hash_id}") if !hash_id[0].eql?("#")
116
+ self.id_cache_get(hash_id[1..-1]).tap {|element| yield element if block_given?}
117
+ end
118
+
97
119
  # Find any and all elements in the tree that match a given ScandentRule string
98
120
  def scan(rule_string)
99
121
  selected = []
@@ -387,6 +409,7 @@ module Arboretum
387
409
  element = Element.create(element) if element.is_a?(Hash)
388
410
  element.graft_onto(self.parent, self.index_in_parent)
389
411
  self.graft_onto(element, index)
412
+ yield element if block_given?
390
413
  element
391
414
  end
392
415
  end
@@ -424,7 +447,7 @@ module Arboretum
424
447
  attr_writer :parent, :children, :sibling_prev, :sibling_next, :incrementers, :resetters, :library
425
448
 
426
449
  public
427
- attr_reader :parent, :children, :sibling_prev, :sibling_next, :incrementers, :resetters, :library
450
+ attr_reader :parent, :children, :sibling_prev, :sibling_next, :incrementers, :resetters, :library, :tree_residence
428
451
  attr_accessor :break_within, :history
429
452
 
430
453
  # Class method to stitch together two elements as siblings, ordered
@@ -461,7 +484,7 @@ module Arboretum
461
484
  end
462
485
  created_element = TaggedElement.new(namespace, tag, sanitary_attrs)
463
486
  if !text.nil?
464
- raise TypeError.new("Text must be a string or TextElement") if !(text.is_a?(String) or text.is_a?(TextElement))
487
+ raise TypeError.new("Text must be a String or TextElement") if !(text.is_a?(String) or text.is_a?(TextElement))
465
488
  if text.is_a?(String)
466
489
  text_child = TextElement.new(text)
467
490
  created_element.append_child(text_child)
@@ -484,6 +507,9 @@ module Arboretum
484
507
  @sibling_next = nil # Element
485
508
  @children = [] # Array of Elements
486
509
 
510
+ # Tree residence
511
+ @tree_residence = nil # Tree
512
+
487
513
  # Properties, references, and counters
488
514
  @break_within = false # Boolean
489
515
  @incrementers = Hash.new # Hash with key: Symbol (name), value: Incrementer
@@ -535,7 +561,7 @@ module Arboretum
535
561
  alias_method :unshift, :prepend_child
536
562
 
537
563
  # Insert an element as a child at a specified index it this element's children
538
- def insert_child(*elements)
564
+ def insert_child(*elements, index)
539
565
  placed = Array.new
540
566
  elements.each do |element|
541
567
  if !element.nil?
@@ -659,19 +685,15 @@ module Arboretum
659
685
  # Add an element to a category in this element's library
660
686
  def lib_add(other, category)
661
687
  raise TypeError.new("Cannot create a record for a non-element") if !other.is_a?(Element) and !other.is_a?(ElementGroup)
688
+ category = category.to_sym if !category.is_a?(Symbol)
662
689
  if @library.has_key?(category)
663
- record = @library[category]
664
- if record.is_a?(Element) and other.is_a?(Element)
665
- @library[category] = ElementGroup.new([record, other])
666
- elsif record.is_a?(ElementGroup) and other.is_a?(Element)
690
+ if other.is_a?(Element)
667
691
  @library[category] << other
668
- elsif record.is_a?(Element) and other.is_a?(ElementGroup)
669
- @library[category] = ElementGroup.new([record]) + other
670
- elsif record.is_a?(ElementGroup) and other.is_a?(ElementGroup)
671
- @library[category] = record + other
692
+ else
693
+ @library[category] = @library[category] + other
672
694
  end
673
695
  else
674
- @library[category] = other
696
+ @library[category] = ElementGroup.new([other])
675
697
  end
676
698
 
677
699
  end
@@ -680,6 +702,7 @@ module Arboretum
680
702
 
681
703
  # Get record from the given category in this element's library
682
704
  def lib_get(category)
705
+ category = category.to_sym if !category.is_a?(Symbol)
683
706
  @library[category]
684
707
  end
685
708
  alias_method :[], :lib_get
@@ -697,6 +720,11 @@ module Arboretum
697
720
  element_copy
698
721
  end
699
722
 
723
+ def update_tree_residence(update_tree)
724
+ @tree_residence = update_tree
725
+ @children.each {|child| child.update_tree_residence(update_tree)}
726
+ end
727
+
700
728
  # Detach from current parent/siblings
701
729
  def detach
702
730
  Element.stitch!(@sibling_prev, @sibling_next)
@@ -705,6 +733,8 @@ module Arboretum
705
733
  end
706
734
  alias_method :prune, :detach
707
735
  alias_method :delete, :detach
736
+ alias_method :clear, :detach
737
+ alias_method :remove, :detach
708
738
 
709
739
  # Graft onto another element of the tree at any index of its children
710
740
  # By default, it will graft as the last element of the other element's children
@@ -730,6 +760,8 @@ module Arboretum
730
760
  next_child = graft_parent.children[index]
731
761
  Element.stitch!(self, next_child)
732
762
 
763
+ self.update_tree_residence(graft_parent.tree_residence) if !self.tree_residence.eql?(graft_parent.tree_residence)
764
+
733
765
  # Graft group at index
734
766
  graft_parent.children.insert(index, self)
735
767
  end
@@ -747,6 +779,8 @@ module Arboretum
747
779
  Element.stitch!(nil, self)
748
780
  Element.stitch!(self, next_child)
749
781
 
782
+ self.update_tree_residence(graft_parent.tree_residence) if !self.tree_residence.eql?(graft_parent.tree_residence)
783
+
750
784
  # Insert graft group at the beginning of parent children
751
785
  graft_parent.children.insert(0, self)
752
786
  end
@@ -763,6 +797,8 @@ module Arboretum
763
797
  Element.stitch!(previous_child, self)
764
798
  Element.stitch!(self, nil)
765
799
 
800
+ self.update_tree_residence(graft_parent.tree_residence) if !self.tree_residence.eql?(graft_parent.tree_residence)
801
+
766
802
  # Push graft group onto parent children
767
803
  graft_parent.children.push(self)
768
804
  end
@@ -850,18 +886,18 @@ module Arboretum
850
886
  end
851
887
 
852
888
  # Finds elements in relation to this one that fit a ScandentRule string
853
- def find(rule_string)
889
+ def find(rule_string, silent: false)
854
890
  rule = Arboretum::Scandent::Parser.parse_rule_string(rule_string, :PATH_LOCATOR)
855
891
  selected = rule.locate(self) {|found_element| yield found_element if block_given?}
856
- puts "--Warning: Rule #{rule} did not match any elements!--" if selected.empty?
892
+ puts "--Warning: Rule #{rule} did not match any elements!--" if selected.empty? and !silent
857
893
  ElementGroup.new(selected)
858
894
  end
859
895
  alias_method :locate, :find
860
896
 
861
897
  # Finds up to `n` elements in relation to this one that fit a ScandentRule string
862
- def find_first_n(rule_string, limit)
898
+ def find_first_n(rule_string, limit, silent: false)
863
899
  if limit.zero?
864
- puts "--Warning: Rule #{rule} was given limit '0'. Returning nil...--" if selected.empty?
900
+ puts "--Warning: Rule #{rule} was given limit '0'. Returning nil...--" if selected.empty? and !silent
865
901
  return nil
866
902
  end
867
903
  selected = []
@@ -871,14 +907,14 @@ module Arboretum
871
907
  yield found_element if block_given?
872
908
  selected << found_element
873
909
  end
874
- puts "--Warning: Rule #{rule} did not match any elements!--" if selected.empty?
910
+ puts "--Warning: Rule #{rule} on #{self.to_s} did not match any elements!--" if selected.empty? and !silent
875
911
  ElementGroup.new(selected)
876
912
  end
877
913
  alias_method :locate_first_n, :find_first_n
878
914
 
879
915
  # Find the first element in relation to this one that fits a ScandentRule string
880
- def find_first(rule_string)
881
- self.find_first_n(rule_string, 1) {|found_element| yield found_element if block_given?}.first
916
+ def find_first(rule_string, silent: false)
917
+ self.find_first_n(rule_string, 1, :silent => silent) {|found_element| yield found_element if block_given?}.first
882
918
  end
883
919
  alias_method :locate_first, :find_first
884
920
 
@@ -970,7 +1006,6 @@ module Arboretum
970
1006
  class TaggedElement < Element
971
1007
  @@unpaired_tags = [:'DOCTYPE', :'!DOCTYPE', :'area', :'base', :'br', :'col', :'command', :'embed', :'hr', :'img',
972
1008
  :'input', :'keygen', :'link', :'meta', :'param', :'source', :'track', :'wbr']
973
- @@need_valid_xml = true
974
1009
 
975
1010
  attr_accessor :namespace, :tag, :attrs
976
1011
 
@@ -980,7 +1015,7 @@ module Arboretum
980
1015
  # Element tag and attributes
981
1016
  @namespace = namespace # Symbol
982
1017
  @tag = tag # Symbol
983
- @attrs = attrs # Hash with key: Symbol, String: Array of Strings
1018
+ @attrs = attrs # Hash: Symbol => Array of Strings
984
1019
  end
985
1020
 
986
1021
  def self.paired?(tag)
@@ -994,6 +1029,15 @@ module Arboretum
994
1029
  element_copy
995
1030
  end
996
1031
 
1032
+ def update_tree_residence(update_tree)
1033
+ # Update old and new tree id cache
1034
+ if self.has_attr?(:id)
1035
+ self.tree_residence&.id_cache_remove(self.attr_value_str(:id))
1036
+ update_tree&.id_cache_add(self.attr_value_str(:id), self)
1037
+ end
1038
+ super(update_tree)
1039
+ end
1040
+
997
1041
  # Returns the id of this element, or an auto-assigned one if none exists
998
1042
  def ref
999
1043
  if !self.has_attr?(:id) or self.attr_value_str(:id).nil?
@@ -1005,6 +1049,7 @@ module Arboretum
1005
1049
  end
1006
1050
  end
1007
1051
 
1052
+ # Returns the '#'-prefixed id of this element, or an auto-assigned one if none exists
1008
1053
  def href
1009
1054
  "#" << self.ref
1010
1055
  end
@@ -1018,6 +1063,10 @@ module Arboretum
1018
1063
 
1019
1064
  def del_attr(attr_name)
1020
1065
  attr_name = attr_name.to_sym if !attr_name.is_a?(Symbol)
1066
+
1067
+ # Update tree id cache
1068
+ self.tree_residence&.id_cache_remove(self.attr_value_str(:id)) if attr_name.eql?(:id)
1069
+
1021
1070
  self.attrs.delete(attr_name)
1022
1071
  end
1023
1072
 
@@ -1029,7 +1078,13 @@ module Arboretum
1029
1078
  raise TypeError.new("Attribute value must be a String or Array of Strings") if !attr_value.is_a?(Array)
1030
1079
  attr_value.each{|sub_val| raise TypeError.new("Each attribute value in an array must be a String") if !sub_val.is_a?(String)}
1031
1080
 
1081
+ # Update tree id cache
1082
+ self.tree_residence&.id_cache_remove(self.attr_value_str(:id)) if attr_name.eql?(:id)
1083
+
1032
1084
  self.attrs[attr_name] = attr_value
1085
+
1086
+ # Update tree id cache
1087
+ self.tree_residence&.id_cache_add(self.attr_value_str(:id), self) if attr_name.eql?(:id)
1033
1088
  end
1034
1089
 
1035
1090
  def del_attr_value(attr_name, attr_value)
@@ -1040,7 +1095,13 @@ module Arboretum
1040
1095
  raise TypeError.new("Attribute value must be a String or Array of Strings") if !attr_value.is_a?(Array)
1041
1096
  attr_value.each{|sub_val| raise TypeError.new("Each attribute value in an array must be a String") if !sub_val.is_a?(String)}
1042
1097
 
1098
+ # Update tree id cache
1099
+ self.tree_residence&.id_cache_remove(self.attr_value_str(:id)) if attr_name.eql?(:id)
1100
+
1043
1101
  self.attrs[attr_name].delete_if {|sub_val| attr_value.include?(sub_val)}
1102
+
1103
+ # Update tree id cache
1104
+ self.tree_residence&.id_cache_add(self.attr_value_str(:id), self) if (attr_name.eql?(:id) and !self.attr_value_str.nil?)
1044
1105
  end
1045
1106
 
1046
1107
  def add_attr_value(attr_name, attr_value)
@@ -1055,6 +1116,8 @@ module Arboretum
1055
1116
  else
1056
1117
  self.attrs[attr_name] = attr_value
1057
1118
  end
1119
+ # Update tree id cache
1120
+ self.tree_residence&.id_cache_add(self.attr_value_str(:id), self) if attr_name.eql?(:id)
1058
1121
  end
1059
1122
 
1060
1123
  def set_tag(new_tag)
@@ -1112,9 +1175,7 @@ module Arboretum
1112
1175
  values.each do |v|
1113
1176
  element_string << "#{v.gsub('&','&amp;').gsub('<', '&lt;').gsub('>','&gt;')} "
1114
1177
  end
1115
- if not values.empty?
1116
- element_string = element_string[0..-2]
1117
- end
1178
+ element_string = element_string.chop unless values.empty?
1118
1179
  element_string << "\""
1119
1180
  end
1120
1181
  # Close the tag if document must have valid xml
@@ -1135,21 +1196,11 @@ module Arboretum
1135
1196
  self.attrs.each do |key, values|
1136
1197
  element_string << " #{key}"
1137
1198
  element_string << "=\""
1138
- values.each do |v|
1139
- element_string << "#{v} "
1140
- end
1141
- if not values.empty?
1142
- element_string = element_string[0..-2]
1143
- end
1199
+ values.each {|v| element_string << "#{v} "}
1200
+ element_string = element_string.chop unless values.empty?
1144
1201
  element_string << "\""
1145
1202
  end
1146
- # Close the tag if document must have xml/xhtml
1147
- if self.paired? or not @@need_valid_xml
1148
- element_string << ">"
1149
- else
1150
- element_string << " />"
1151
- end
1152
- element_string
1203
+ element_string << (self.paired? ? ">" : "/>")
1153
1204
  end
1154
1205
 
1155
1206
  def to_s_close
@@ -1283,10 +1334,17 @@ module Arboretum
1283
1334
  @group
1284
1335
  end
1285
1336
 
1337
+ def only
1338
+ raise IndexError.new("Element is not the only in its group") if not @group.length == 1
1339
+ @group.first
1340
+ end
1341
+
1286
1342
  def text_string
1287
- full_string = ''
1288
- @group.each {|element| full_string << element.text_string}
1289
- full_string
1343
+ String.new.tap{|full_string| @group.each {|element| full_string << element.text_string} }
1344
+ end
1345
+
1346
+ def text_elements
1347
+ Array.new.tap{|full_list| @group.each {|element| full_list << element.text_elements} }
1290
1348
  end
1291
1349
 
1292
1350
  def +(other)
@@ -36,7 +36,7 @@ module Arboretum
36
36
  def to_s
37
37
  rule_str = ''
38
38
  @paths.each do |path|
39
- rule_str << ', ' if !rule_str.empty?
39
+ rule_str << ', ' unless rule_str.empty?
40
40
  rule_str << path.to_s
41
41
  end
42
42
  rule_str
@@ -226,8 +226,8 @@ module Arboretum
226
226
  !@attrs[:matches].empty? or
227
227
  (element_ref == :ELEMENT_ROOT and !element.parent.nil?)
228
228
  end
229
- @pseudo_exps.each do |psuedo_name, pseudo_arg|
230
- return false if !PseudoElements.match(element, pseudo_name, pseudo_arg)
229
+ @pseudo_exps.each do |pseudo_name, pseudo_arg|
230
+ return false if !PseudoClasses.match(element, pseudo_name, pseudo_arg)
231
231
  end
232
232
  @valid_rules.each do |rule|
233
233
  return false if !rule.valid_on?(element)
@@ -361,9 +361,18 @@ module Arboretum
361
361
  end
362
362
  end
363
363
 
364
- class PseudoElements
364
+ class PseudoClasses
365
+ # Call a pseudo class function
365
366
  def self.match(element, pseudo_name, pseudo_arg)
366
- PseudoElements.public_send(:pseudo_name, element, pseudo_arg)
367
+ PseudoClasses.public_send(pseudo_name.to_sym, element, pseudo_arg)
368
+ end
369
+
370
+ # Pseudo class functions start here
371
+ def self.header(element, pseudo_arg)
372
+ (element.is_a?(Arboretum::DocTree::Elements::TaggedElement) and !(/h\d+/.match(element.tag.to_s).nil?))
373
+ end
374
+ def self.not(element, pseudo_arg)
375
+ !element.matches_rule?(pseudo_arg)
367
376
  end
368
377
  end
369
378
 
@@ -372,14 +381,14 @@ module Arboretum
372
381
  # ScandentRules can then be matched to Elements in a DocTree
373
382
  class Parser
374
383
  @@actions = {
375
- :T_SLASH => :ACTION_CHILD,
376
- :T_SLASH2 => :ACTION_DESCENDANT,
377
- :T_SLASHDOT2 => :ACTION_PARENT,
378
- :T_SLASHDOT3 => :ACTION_ANCESTOR,
379
- :T_SLASHGT => :ACTION_FOLLOWING_SIBLING,
380
- :T_SLASHGT2 => :ACTION_FOLLOWING,
381
- :T_SLASHLT => :ACTION_PRECEDING_SIBLING,
382
- :T_SLASHLT2 => :ACTION_PRECEDING
384
+ :T_SLASH => :ACTION_CHILD,
385
+ :T_SLASH2 => :ACTION_DESCENDANT,
386
+ :T_SLASHDOT2 => :ACTION_PARENT,
387
+ :T_SLASHDOT3 => :ACTION_ANCESTOR,
388
+ :T_SLASHGT => :ACTION_FOLLOWING_SIBLING,
389
+ :T_SLASHGT2 => :ACTION_FOLLOWING,
390
+ :T_SLASHLT => :ACTION_PRECEDING_SIBLING,
391
+ :T_SLASHLT2 => :ACTION_PRECEDING
383
392
  }
384
393
 
385
394
  # Parse a Scandent string by giving it to the Tokenizer and then parsing the results
@@ -444,6 +453,7 @@ module Arboretum
444
453
  raise ParseException.new("Unknown step type")
445
454
  end
446
455
 
456
+ # Initialize all of the components that a step uses to match an element
447
457
  element_ref = []
448
458
  tag = []
449
459
  namespace = []
@@ -457,124 +467,103 @@ module Arboretum
457
467
  pseudo_exps = []
458
468
  valid_rules = []
459
469
 
460
- index = 0
470
+ # Walk through the tokens of this step one at a time to parse grammar
471
+ index = -1
461
472
  state = :STATE_ROOT_PATH
462
- while index < step_tokens.length
463
- # Consume current token and increment
464
- index_token = step_tokens[index]
465
- index += 1
473
+ while (index + 1) < step_tokens.length
474
+ # Consume next token
475
+ index_token = step_tokens[index+=1]
466
476
 
467
477
  case index_token[0]
468
478
  when :T_PCT
469
- following_token = step_tokens[index]
470
- index += 1
471
- raise InvalidExpressionException.new if following_token[0] != :LITERAL_IDENT
472
- tag << following_token[1]
479
+ next_token = step_tokens[index+=1]
480
+ raise InvalidExpressionException.new if next_token[0] != :LITERAL_IDENT
481
+ tag << next_token[1]
473
482
  when :T_AT
474
- following_token = step_tokens[index]
475
- index += 1
476
- raise InvalidExpressionException.new if following_token[0] != :LITERAL_IDENT
477
- namespace << following_token[1]
483
+ next_token = step_tokens[index+=1]
484
+ raise InvalidExpressionException.new if next_token[0] != :LITERAL_IDENT
485
+ namespace << next_token[1]
478
486
  when :T_PND
479
- following_token = step_tokens[index]
480
- index += 1
481
- raise InvalidExpressionException.new if following_token[0] != :LITERAL_IDENT
482
- id << following_token[1]
487
+ next_token = step_tokens[index+=1]
488
+ raise InvalidExpressionException.new if next_token[0] != :LITERAL_IDENT
489
+ id << next_token[1]
483
490
  when :T_COLON
484
- following_token = step_tokens[index]
485
- index += 1
486
- raise InvalidExpressionException.new if following_token[0] != :LITERAL_IDENT
487
- pseudo_name = following_token[1].to_sym
491
+ next_token = step_tokens[index+=1]
492
+ raise InvalidExpressionException.new if next_token[0] != :LITERAL_IDENT
493
+ pseudo_name = next_token[1].to_sym
488
494
  arg_tokens = []
489
495
 
490
- following_token = step_tokens[index]
491
- if following_token[0] == :T_LPAREN
492
- index += 1 # To consume the LPAREN
493
- following_token = step_tokens[index]
494
- index += 1
495
- until following_token[0] == :T_RPAREN or index > step_tokens.length
496
- arg_tokens << following_token
497
- following_token = step_tokens[index]
498
- index += 1
496
+ next_token = step_tokens[index+=1]
497
+ if next_token[0] == :T_LPAREN
498
+ next_token = step_tokens[index+=1]
499
+ until next_token[0] == :T_RPAREN or index > step_tokens.length
500
+ arg_tokens << next_token
501
+ next_token = step_tokens[index+=1]
499
502
  end
500
503
  raise InvalidExpressionException.new if index > step_tokens.length # Undesirable exit condition to above loop
501
- index += 1 # To consume the RPAREN
502
504
  end
503
505
  pseudo_exps << [pseudo_name, Parser.parse_arg(arg_tokens)]
504
- when :T_ASTERISK # Adds no restrictions, so do nothing
506
+ when :T_ASTERISK
507
+ # Adds no restrictions, so do nothing
505
508
  when :T_TILDE
506
509
  element_ref << :ELEMENT_ROOT
507
510
  when :T_DOT
508
511
  element_ref << :ELEMENT_SELF
509
512
  when :T_LBRAK
510
- following_token = step_tokens[index]
511
- index += 1
512
- raise InvalidExpressionException.new if following_token[0] != :LITERAL_IDENT
513
- attr_name = following_token[1].to_sym
513
+ next_token = step_tokens[index+=1]
514
+ raise InvalidExpressionException.new if next_token[0] != :LITERAL_IDENT
515
+ attr_name = next_token[1].to_sym
514
516
  attr_value = nil
515
517
  operation = nil
516
518
 
517
- following_token = step_tokens[index]
518
- index += 1
519
- case following_token[0]
519
+ next_token = step_tokens[index+=1]
520
+ case next_token[0]
520
521
  when :T_EQL
521
522
  operation = :contains
522
523
 
523
- following_token = step_tokens[index]
524
- index += 1
525
- raise InvalidExpressionException.new("Expected a string after '='") if ![:T_DQUOTE, :T_SQUOTE].include?(following_token[0])
526
- string_limiter = following_token[0]
524
+ next_token = step_tokens[index+=1]
525
+ raise InvalidExpressionException.new("Expected a string after '='") if ![:T_DQUOTE, :T_SQUOTE].include?(next_token[0])
526
+ string_limiter = next_token[0]
527
527
 
528
- following_token = step_tokens[index]
529
- index += 1
530
- raise InvalidExpressionException.new if not [:LITERAL_IDENT, :LITERAL_STRING, :LITERAL_INT, :LITERAL_FLOAT].include?(following_token[0])
531
- attr_value = following_token[1]
528
+ next_token = step_tokens[index+=1]
529
+ raise InvalidExpressionException.new if not [:LITERAL_IDENT, :LITERAL_STRING, :LITERAL_INT, :LITERAL_FLOAT].include?(next_token[0])
530
+ attr_value = next_token[1]
532
531
 
533
- following_token = step_tokens[index]
534
- index += 1
535
- raise InvalidExpressionException.new if following_token[0] != string_limiter
532
+ next_token = step_tokens[index+=1]
533
+ raise InvalidExpressionException.new if next_token[0] != string_limiter
536
534
 
537
- following_token = step_tokens[index]
538
- index += 1
539
- raise InvalidExpressionException.new if following_token[0] != :T_RBRAK
535
+ next_token = step_tokens[index+=1]
536
+ raise InvalidExpressionException.new if next_token[0] != :T_RBRAK
540
537
  when :T_EQL2
541
538
  operation = :equals
542
- following_token = step_tokens[index]
543
- index += 1
544
- raise InvalidExpressionException.new if ![:T_DQUOTE, :T_SQUOTE].include?(following_token[0])
545
- string_limiter = following_token[0]
546
-
547
- following_token = step_tokens[index]
548
- index += 1
549
- raise InvalidExpressionException.new if not [:LITERAL_IDENT, :LITERAL_STRING, :LITERAL_INT, :LITERAL_FLOAT].include?(following_token[0])
550
- attr_value = following_token[1].split
551
-
552
- following_token = step_tokens[index]
553
- index += 1
554
- raise InvalidExpressionException.new if following_token[0] != string_limiter
555
-
556
- following_token = step_tokens[index]
557
- index += 1
558
- raise InvalidExpressionException.new if following_token[0] != :T_RBRAK
539
+ next_token = step_tokens[index+=1]
540
+ raise InvalidExpressionException.new if ![:T_DQUOTE, :T_SQUOTE].include?(next_token[0])
541
+ string_limiter = next_token[0]
542
+
543
+ next_token = step_tokens[index+=1]
544
+ raise InvalidExpressionException.new if not [:LITERAL_IDENT, :LITERAL_STRING, :LITERAL_INT, :LITERAL_FLOAT].include?(next_token[0])
545
+ attr_value = next_token[1].split
546
+
547
+ next_token = step_tokens[index+=1]
548
+ raise InvalidExpressionException.new if next_token[0] != string_limiter
549
+
550
+ next_token = step_tokens[index+=1]
551
+ raise InvalidExpressionException.new if next_token[0] != :T_RBRAK
559
552
  when :T_TILDE_EQL
560
553
  operation = :matches
561
554
 
562
- following_token = step_tokens[index]
563
- index += 1
564
- raise InvalidExpressionException.new if following_token[0] != :T_VBARSLASH
555
+ next_token = step_tokens[index+=1]
556
+ raise InvalidExpressionException.new if next_token[0] != :T_VBARSLASH
565
557
 
566
- following_token = step_tokens[index]
567
- index += 1
568
- raise InvalidExpressionException.new if not [:LITERAL_IDENT, :LITERAL_STRING, :LITERAL_INT, :LITERAL_FLOAT].include?(following_token[0])
569
- attr_value = Regexp.new(following_token[1])
558
+ next_token = step_tokens[index+=1]
559
+ raise InvalidExpressionException.new if not [:LITERAL_IDENT, :LITERAL_STRING, :LITERAL_INT, :LITERAL_FLOAT].include?(next_token[0])
560
+ attr_value = Regexp.new(next_token[1])
570
561
 
571
- following_token = step_tokens[index]
572
- index += 1
573
- raise InvalidExpressionException.new if following_token[0] != :T_SLASHVBAR
562
+ next_token = step_tokens[index+=1]
563
+ raise InvalidExpressionException.new if next_token[0] != :T_SLASHVBAR
574
564
 
575
- following_token = step_tokens[index]
576
- index += 1
577
- raise InvalidExpressionException.new if following_token[0] != :T_RBRAK
565
+ next_token = step_tokens[index+=1]
566
+ raise InvalidExpressionException.new if next_token[0] != :T_RBRAK
578
567
  when :T_RBRAK
579
568
  operation = nil
580
569
  else
@@ -588,18 +577,17 @@ module Arboretum
588
577
  when :T_LBRACE
589
578
  equilibrium = 1
590
579
  reformed_path_string = ''
591
- following_token = step_tokens[index]
592
- index += 1
593
- until (following_token[0] == :T_RBRACE and equilibrium.zero?) or index > step_tokens.length
594
- reformed_path_string << following_token[1]
595
- following_token = step_tokens[index]
596
- index += 1
597
- equilibrium += 1 if following_token[0] == :T_LBRACE
598
- equilibrium -= 1 if following_token[0] == :T_RBRACE
580
+ next_token = step_tokens[index+=1]
581
+ until (next_token[0] == :T_RBRACE and equilibrium.zero?) or index > step_tokens.length
582
+ reformed_path_string << next_token[1]
583
+ next_token = step_tokens[index+=1]
584
+ equilibrium += 1 if next_token[0] == :T_LBRACE
585
+ equilibrium -= 1 if next_token[0] == :T_RBRACE
599
586
  end
600
587
  raise InvalidExpressionException.new("Could not find matching R_BRACE in #{reformed_path_string}") if index > step_tokens.length # Undesirable exit condition to above loop
601
588
  valid_rules << Parser.parse_rule_string(reformed_path_string, :PATH_LOCATOR)
602
589
  when :T_SLASH, :T_SLASH2, :T_SLASHDOT2, :T_SLASHDOT3, :T_SLASHGT, :T_SLASHGT2, :T_SLASHLT, :T_SLASHLT2
590
+ # Do nothing since the action has already been determined
603
591
  else
604
592
  raise ParseException.new("Consumed unexpected token: #{index_token}")
605
593
  end
@@ -1,9 +1,8 @@
1
+ require 'ox'
2
+
1
3
  module Arboretum
2
4
  module XML
3
5
  module IO
4
- require 'ox'
5
- require_relative 'doctree'
6
-
7
6
  class XMLParseException < StandardError
8
7
  def initialize(msg="An error occurred while parsing XML")
9
8
  super(msg)
@@ -87,7 +86,7 @@ module Arboretum
87
86
 
88
87
  # Add TaggedElement to tree
89
88
  opened_element = TaggedElement.new(element_ns, element_tag)
90
- @open_elements.last.append_child(opened_element)
89
+ opened_element.graft_last_onto(@open_elements.last)
91
90
 
92
91
  # Open the element if paired
93
92
  @open_elements.push(opened_element)
@@ -101,7 +100,7 @@ module Arboretum
101
100
  def comment(str)
102
101
  # Add CommentElement to tree
103
102
  comment_element = CommentElement.new(str)
104
- @open_elements.last.append_child(comment_element)
103
+ comment_element.graft_last_onto(@open_elements.last)
105
104
  # Do not open the element (no children)
106
105
  end
107
106
  def text(str)
@@ -111,13 +110,13 @@ module Arboretum
111
110
 
112
111
  # Add TextElement to tree
113
112
  text_element = TextElement.new(str)
114
- @open_elements.last.append_child(text_element)
113
+ text_element.graft_last_onto(@open_elements.last)
115
114
  # Do not open the element (no children)
116
115
 
117
116
  elsif @style == :preserve
118
117
  # Add TextElement to tree
119
118
  text_element = TextElement.new(str)
120
- @open_elements.last.append_child(text_element)
119
+ text_element.graft_last_onto(@open_elements.last)
121
120
  # Do not open the element (no children)
122
121
  end
123
122
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arboretum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - tomjw64
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-26 00:00:00.000000000 Z
11
+ date: 2017-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ox
@@ -37,6 +37,7 @@ extensions: []
37
37
  extra_rdoc_files: []
38
38
  files:
39
39
  - lib/arboretum.rb
40
+ - lib/arboretum/debtor.rb
40
41
  - lib/arboretum/doctree.rb
41
42
  - lib/arboretum/scandent.rb
42
43
  - lib/arboretum/xml.rb