PageRenderTime 38ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/2.4/tags/parser/charge.inc

http://drawshield.googlecode.com/
PHP | 233 lines | 175 code | 31 blank | 27 comment | 48 complexity | c5d3a67d1fe95a155389b797b40dfb4c MD5 | raw file
  1. <?php /* Copyright 2010 Karl R. Wilcox
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License. */
  11. function adjacent(&$node, $found_between = false) {
  12. global $dom;
  13. static $adjacent_charge = array (
  14. array ( true, 'between', 'between' ),
  15. array ( true, 'within', 'within' ),
  16. array ( true, 'above', 'above' ),
  17. array ( true, 'below', 'below' ),
  18. array ( true, 'with', 'below' ),
  19. );
  20. // Does this charge go "between/above/below" some others?
  21. if ( $found_between )
  22. $position = 'between';
  23. elseif (( $match = search_match($adjacent_charge)) != null )
  24. $position = $match[2];
  25. else
  26. return;
  27. $adj_mod = make_mod($position);
  28. if ( $position == 'within' ) { // could be charge or ordinary
  29. if ( (($adj_charge = charge()) == null) and (($adj_charge = ordinary()) == null) ){
  30. $adj_charge = $dom->createElement('missing');
  31. parser_message('blazon', 'Nothing to go within');
  32. }
  33. } else { // 'between' can only be a charge
  34. if ( ($adj_charge = charge()) == null ) {
  35. $adj_charge = $dom->createElement('missing');
  36. parser_message('blazon', 'Nothing to go between');
  37. }
  38. }
  39. $adj_mod->appendChild ( $adj_charge);
  40. $node->appendChild($adj_mod);
  41. // keep looking for more of the same
  42. while ( !semicolon() and andd() and (($adj_charge = charge()) != null ) ) {
  43. $adj_mod = make_mod($position);
  44. $adj_mod->appendChild($adj_charge);
  45. $node->appendChild($adj_mod);
  46. }
  47. }
  48. function bundle ( &$node ) {
  49. static $bundle_words = array (
  50. array ( 'bundle', '(sheaf|sheave|bundle|tuft)s?', 3 ),
  51. array ( 'bundle', 'pair', 2), // just to demonstrate different defaults really....
  52. );
  53. static $of_words = array (
  54. array ( true, 'of', ),
  55. );
  56. if ( ($match = search_match($bundle_words)) != null ) {
  57. $num = 0;
  58. if ( search_match($of_words) != null ) $num = number();
  59. if ( $num < 1) $num = $match[2];
  60. $node->appendChild( make_mod ( $match[0], "$num" ));
  61. }
  62. }
  63. function demi() {
  64. $prefix_words = array (
  65. array ( null, 'demi|half' ),
  66. );
  67. return search_match($prefix_words);
  68. }
  69. function get_feature_tinc($node) {
  70. foreach ( $node->childNodes as $child ) {
  71. if ( $child->nodeName == 'feature' ) {
  72. if ( ($tinc = get_child($child, 'tincture')) != null )
  73. return deep_copy($tinc);
  74. }
  75. }
  76. return null;
  77. }
  78. function simple_charge( $assume_num = false, $allow_arr_pos = false ) {
  79. global $dom;
  80. global $flag_list;
  81. global $charge_list;
  82. global $modifier_list;
  83. global $pending_items;
  84. $specific_features = null;
  85. $flags = array();
  86. $state = save();
  87. // Look for a number
  88. if ( ($num = number()) == null) {
  89. if ( $assume_num ) {
  90. if ( is_int($assume_num) )
  91. $num = $assume_num;
  92. else
  93. $num = 1;
  94. } else {
  95. restore($state);
  96. return null;
  97. }
  98. }
  99. $node = $dom->createElement('charge');
  100. // Look for grouping words (bundle of etc.)
  101. bundle( $node );
  102. if ( demi() ) $node->appendChild(make_mod('demi'));
  103. if ( (($match = either('charge')) == null) and (($match = search_match($charge_list)) == null ) ) {
  104. restore($state);
  105. return null;
  106. }
  107. // We have a charge
  108. $type = $match[2];
  109. $subtype = $match[0];
  110. $node->setAttribute('type', $type);
  111. $node->setAttribute('subtype', $subtype);
  112. $node->setAttribute('tokens',tokens());
  113. $node->setAttribute('number',"$num");
  114. $a_key = 'c:' . $subtype;
  115. // Get the set of features and flags, (if any)
  116. if ( array_key_exists($a_key, $modifier_list ))
  117. $specific_features = $modifier_list[$a_key];
  118. if ( array_key_exists($a_key, $flag_list ))
  119. $flags = $flag_list[$a_key];
  120. // Sometimes we want to just get the next word as a string
  121. if ( array_key_exists('get_item', $flags))
  122. $node->appendChild( make_mod('item',get_tokens($flags['get_item'])));
  123. // Look for grouping words again
  124. bundle( $node );
  125. $mod_set = array ('simple_charge', 'rows', $specific_features);
  126. if ( $allow_arr_pos ) $mod_set[] = 'arr_pos';
  127. get_features ( $mod_set, $node );
  128. // Have we found a tincture yet?
  129. if ( ($tinc = get_child($node, 'tincture')) == null ) {
  130. if ( array_key_exists('always_proper', $flags) ) {
  131. $tinc = $dom->createElement('tincture');
  132. $proper = $dom->createElement('proper');
  133. $tinc->setAttribute('index','1');
  134. $tinc->setAttribute('origin','proper');
  135. $tinc->appendChild($proper);
  136. } elseif ( array_key_exists('default_colour', $flags)) {
  137. $tinc = make_colour($flags['default_colour']);
  138. $tinc->setAttribute('index','1');
  139. $tinc->setAttribute('origin','default');
  140. } elseif ( ($tinc = get_feature_tinc($node)) != null ) { // or it could be because the tincture was consumed by a feature
  141. // Don't need to do anything else
  142. } else { // Not proper, and no default
  143. $tinc = $dom->createElement('tincture');
  144. $tinc->setAttribute('origin','pending');
  145. $tinc->setAttribute('index','1');
  146. $pending_items[] = $tinc;
  147. }
  148. $node->appendChild($tinc);
  149. } else {
  150. $tinc->setAttribute('origin','given');
  151. }
  152. return $node;
  153. }
  154. function charge( $assume_num = false ) {
  155. global $dom;
  156. $on_charge = array (
  157. array ( true, 'charged with' ),
  158. array ( true, 'on each' ),
  159. array ( true, 'surmounted by' ),
  160. );
  161. $on_prefix = array (
  162. array ( true, 'on' ),
  163. );
  164. $state = save();
  165. $allow_arr_pos = true;
  166. // In case of "in chief, three whatever...
  167. $temp = $dom->createElement('charge');
  168. $arr_pos = get_features( array ( 'arr_pos', 'charge_prefix'), $temp );
  169. if ( is_int($arr_pos) ) {
  170. $assume_num = $arr_pos;
  171. $allow_arr_pos = false;
  172. }
  173. $found_on = search_match($on_prefix);
  174. // Look for the charge itself
  175. if ( ($node = simple_charge( $assume_num, $allow_arr_pos )) == null ) {
  176. restore($state);
  177. return null;
  178. }
  179. // Copy over anything found earlier
  180. foreach ($temp->childNodes as $child )
  181. $node->appendChild($child);
  182. // Is there anything else "on" this charge?
  183. if ( $found_on or search_match($on_charge) != null ) {
  184. $on_mod = make_mod('on');
  185. if ( ($on_charge = simple_charge( true )) == null ) {
  186. $on_charge = $dom->createElement('missing');
  187. parser_message('blazon', 'Nothing for charge to go on');
  188. }
  189. $on_mod->appendChild($on_charge);
  190. $node->appendChild($on_mod);
  191. }
  192. if ( !semicolon() ) {
  193. adjacent($node);
  194. // If there is an explicit position, a following "between" is redundant (e.g. issue 173)
  195. search_match( array ( array ( null, 'between' )));
  196. }
  197. return $node;
  198. }
  199. ?>