PageRenderTime 70ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

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

http://drawshield.googlecode.com/
PHP | 242 lines | 183 code | 32 blank | 27 comment | 47 complexity | cc39f66d689447df2249c98773712477 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 get_modifier_array($type, $subtype, &$features, &$flags) {
  79. $node = null;
  80. $charge = array ();
  81. include ( 'charges/' . $type . '/' . $subtype . '.inc' );
  82. if ( array_key_exists('modifiers', $charge) )
  83. $features = $charge['modifiers'];
  84. if ( array_key_exists('flags', $charge) )
  85. $flags = $charge['flags'];
  86. }
  87. function simple_charge( $assume_num = false, $allow_arr_pos = false ) {
  88. global $dom;
  89. global $charge_list;
  90. global $pending_items;
  91. static $prefix_features = array (
  92. array ( null, '(demi|half)', 'mod', 'demi' ),
  93. array ( null, 'like', 'mod', 'like' ), // not sure whether this has any real meaning, but added as mod just in case
  94. );
  95. $specific_features = null;
  96. $flags = array();
  97. $state = save();
  98. // Look for a number
  99. if ( ($num = number()) == null) {
  100. if ( $assume_num ) {
  101. if ( is_int($assume_num) )
  102. $num = $assume_num;
  103. else
  104. $num = 1;
  105. } else {
  106. restore($state);
  107. return null;
  108. }
  109. }
  110. $node = $dom->createElement('charge');
  111. // Look for grouping words (bundle of etc.)
  112. bundle( $node );
  113. get_features(array($prefix_features, 'no_tinc'), $node);
  114. if ( (($match = either('charge')) == null) and (($match = search_match($charge_list)) == null ) ) {
  115. restore($state);
  116. return null;
  117. }
  118. // We have a charge
  119. $type = $match[2];
  120. $subtype = $match[0];
  121. $node->setAttribute('type', $type);
  122. $node->setAttribute('subtype', $subtype);
  123. $node->setAttribute('tokens',tokens());
  124. $node->setAttribute('number',"$num");
  125. $a_key = 'c:' . $subtype;
  126. // Get the set of features and flags, (if any)
  127. get_modifier_array($type,$subtype,$specific_features,$flags);
  128. // Sometimes we want to just get the next word as a string
  129. if ( array_key_exists('get_item', $flags))
  130. $node->appendChild( make_mod('item',get_tokens($flags['get_item'])));
  131. // Look for grouping words again
  132. bundle( $node );
  133. $mod_set = array ('simple_charge', 'rows', $specific_features);
  134. if ( $allow_arr_pos ) $mod_set[] = 'arr_pos';
  135. get_features ( $mod_set, $node );
  136. // Have we found a tincture yet?
  137. if ( ($tinc = get_child($node, 'tincture')) == null ) {
  138. if ( array_key_exists('always_proper', $flags) ) {
  139. $tinc = $dom->createElement('tincture');
  140. $proper = $dom->createElement('proper');
  141. $tinc->setAttribute('index','1');
  142. $tinc->setAttribute('origin','proper');
  143. $tinc->appendChild($proper);
  144. } elseif ( array_key_exists('default_colour', $flags)) {
  145. $tinc = make_colour($flags['default_colour']);
  146. $tinc->setAttribute('index','1');
  147. $tinc->setAttribute('origin','default');
  148. } elseif ( ($tinc = get_feature_tinc($node)) != null ) { // or it could be because the tincture was consumed by a feature
  149. // Don't need to do anything else
  150. } else { // Not proper, and no default
  151. $tinc = $dom->createElement('tincture');
  152. $tinc->setAttribute('origin','pending');
  153. $tinc->setAttribute('index','1');
  154. $pending_items[] = $tinc;
  155. }
  156. $node->appendChild($tinc);
  157. } else {
  158. $tinc->setAttribute('origin','given');
  159. }
  160. return $node;
  161. }
  162. function charge( $assume_num = false ) {
  163. global $dom;
  164. $on_charge = array (
  165. array ( true, 'charged with' ),
  166. array ( true, 'on each' ),
  167. array ( true, 'surmounted by' ),
  168. );
  169. $on_prefix = array (
  170. array ( true, 'on' ),
  171. );
  172. $state = save();
  173. $allow_arr_pos = true;
  174. // In case of "in chief, three whatever...
  175. $temp = $dom->createElement('charge');
  176. $arr_pos = get_features( array ( 'arr_pos', 'charge_prefix', 'no_tinc' ), $temp );
  177. if ( is_int($arr_pos) ) {
  178. $assume_num = $arr_pos;
  179. $allow_arr_pos = false;
  180. }
  181. $found_on = search_match($on_prefix);
  182. // Look for the charge itself
  183. if ( ($node = simple_charge( $assume_num, $allow_arr_pos )) == null ) {
  184. restore($state);
  185. return null;
  186. }
  187. // Copy over anything found earlier
  188. foreach ($temp->childNodes as $child )
  189. $node->appendChild($child);
  190. // Is there anything else "on" this charge?
  191. if ( $found_on or search_match($on_charge) != null ) {
  192. $on_mod = make_mod('on');
  193. if ( ($on_charge = simple_charge( true )) == null ) {
  194. $on_charge = $dom->createElement('missing');
  195. parser_message('blazon', 'Nothing for charge to go on');
  196. }
  197. $on_mod->appendChild($on_charge);
  198. $node->appendChild($on_mod);
  199. }
  200. if ( !semicolon() ) {
  201. adjacent($node);
  202. // If there is an explicit position, a following "between" is redundant (e.g. issue 173)
  203. search_match( array ( array ( null, 'between' )));
  204. }
  205. return $node;
  206. }
  207. ?>