[ Index ]

PHP Cross Reference of Limb3

title

Body

[close]

/wact/src/compiler/parser/ -> WactTreeBuilder.class.php (source)

   1  <?php
   2  /*
   3   * Limb PHP Framework
   4   *
   5   * @link http://limb-project.com 
   6   * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
   7   * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
   8   */
   9  
  10  /**
  11   * Acts on the WactCompileTreeRootNode in response to events within the WactSourceFileParser
  12   *
  13   * When adding an open tag to the tree, call pushExpectedTag().  When closing
  14   * a tag, call popExpectedTag(), which ensures the tree is balanced.
  15   *
  16   * These methods do not actually add nodes to the tree, as tags and nodes
  17   * do not necessarily match up.
  18   *
  19   * To add a node to the tree, you have the following choices.  To add a node
  20   * which can have children, use pushNode().  To add a terminal node use addNode(),
  21   * or addWactTextNode().
  22   *
  23   * @package wact
  24   * @version $Id: WactTreeBuilder.class.php 5945 2007-06-06 08:31:43Z pachanga $
  25   */
  26  
  27  
  28  define ('WACT_EXPECTED_WACT_TAG',     1);
  29  define ('WACT_EXPECTED_PLAIN_TAG',    2);class WactTreeBuilder
  30  {
  31    /**

  32    * @var WactCompiler

  33    */
  34    protected $compiler;
  35  
  36    /**

  37    * Current node

  38    * @var WactCompileTreeNode

  39    * @access private

  40    */
  41    var $component;
  42  
  43    protected $property_dictionary;
  44    protected $tag_dictionary;
  45    protected $filter_dictionary;
  46  
  47    /**

  48    * Stack of tags pushed onto the tree builder, may also contain components

  49    * @see pushExpectedTag

  50    * @see popExpectedTag

  51    * @see pushCursor

  52    * @access private

  53    */
  54    protected $expected_tags = array();
  55  
  56    function __construct($compiler, $tag_dictionary, $property_dictionary, $filter_dictionary)
  57    {
  58      $this->compiler = $compiler;
  59      $this->tag_dictionary = $tag_dictionary;
  60      $this->property_dictionary = $property_dictionary;
  61      $this->filter_dictionary = $filter_dictionary;
  62    }
  63  
  64    /**

  65    * Returns the current component

  66    * @return WactCompileTreeNode

  67    * @return void

  68    */
  69    function getCursor()
  70    {
  71      return $this->cursor_node;
  72    }
  73  
  74    /**

  75    * Sets the cursor (the current working component) of the tree builder

  76    * @param WactCompileTreeNode

  77    * @return void

  78    */
  79    function setCursor($node)
  80    {
  81      $this->cursor_node = $node;
  82    }
  83  
  84    /**

  85    * Begins a component's build phase in relation to the component tree.

  86    * Adds a component to the tree, then makes that component the 'cursor'.

  87    * @param WactCompileTreeNode

  88    * @return void

  89    */
  90    function pushNode($new_node)
  91    {
  92      $this->cursor_node->addChild($new_node);
  93      $this->setCursor($new_node);
  94  
  95      return $this->cursor_node->preParse($this->compiler);
  96    }
  97  
  98    /**

  99    * Adds a component to the tree, without descending into it.

 100    * This begins and finishes the component's composition

 101    * @param WactCompileTreeNode

 102    */
 103    function addNode($child_node)
 104    {
 105      $this->cursor_node->addChild($child_node);
 106      $child_node->preParse($this->compiler);
 107    }
 108  
 109    function addWactTextNode($text)
 110    {
 111      $this->addNode(new WactTextNode(null, $text));
 112    }
 113  
 114    /**

 115    * Ends a component's build phase in relation to the tree.

 116    * Checks child server ids and moves the 'cursor' up the tree to the parent

 117    * component.

 118    */
 119    function popNode()
 120    {
 121      $this->cursor_node->checkChildrenServerIds();
 122      $this->setCursor($this->cursor_node->parent);
 123    }
 124  
 125    /**

 126    * @param string tag name

 127    * @param mixed info about the tag

 128    * @param boolean if the tag is one of the wact tags (of having wact:id or runat='server' attributes)

 129    * @return void

 130    */
 131    function _pushExpectedTag($tag, $location, $tag_kind)
 132    {
 133      array_push($this->expected_tags, array($tag, $location, $tag_kind));
 134    }
 135  
 136    function pushExpectedPlainTag($tag, $location)
 137    {
 138      $this->_pushExpectedTag($tag, $location, WACT_EXPECTED_PLAIN_TAG);
 139    }
 140  
 141    function pushExpectedWactTag($tag, $location)
 142    {
 143      $this->_pushExpectedTag($tag, $location, WACT_EXPECTED_WACT_TAG);
 144    }
 145  
 146    /**

 147    * Sets the cursor to a new position, and pushes the old cursor onto the expected tags stack.

 148    * @param WactCompileTreeNode

 149    * @return void

 150    */
 151    function pushCursor($new_position, $location)
 152    {
 153      $this->pushExpectedWactTag($this->cursor_node, $location);
 154      $this->setCursor($new_position);
 155    }
 156  
 157    /**

 158    * Tests the passed tag against what is expected.

 159    * Returns info if expected tag was a wact tag or a plain tag

 160    */
 161    protected function _popExpectedTag($pop_tag, $pop_tag_location, $pop_tag_kind)
 162    {
 163      if(!$expected_tag_info = array_pop($this->expected_tags))
 164      {
 165        throw new WactException('Lonely closing tag', array('tag' => $pop_tag,
 166                                                            'file' => $pop_tag_location->getFile(),
 167                                                            'line' => $pop_tag_location->getLine()));
 168      }
 169  
 170      // if we have a cursor on the stack, restore the current cursor to that, and

 171      // pop the stack again

 172      if (is_object($expected_tag_info[0]))
 173      {
 174         $this->cursor_node =& $expected_tag_info[0];
 175         return $this->_popExpectedTag($pop_tag, $pop_tag_location, $pop_tag_kind);
 176      }
 177  
 178      $expected_tag = $expected_tag_info[0];
 179      $expected_tag_location = $expected_tag_info[1];
 180      $expected_tag_kind = $expected_tag_info[2];
 181  
 182      // if the tag names are equal we dont care about if they are both wact tags or not

 183      if(strcasecmp($expected_tag, $pop_tag) === 0)
 184        return $expected_tag_kind;
 185  
 186      // ignore plain html tag since we dont need to balance them

 187      if($expected_tag_kind == WACT_EXPECTED_PLAIN_TAG)
 188        return $this->_popExpectedTag($pop_tag, $pop_tag_location, $pop_tag_kind);
 189  
 190      // we stops at the nearest wact tag if we poping up a plain html tag

 191      if(($expected_tag_kind == WACT_EXPECTED_WACT_TAG) && ($pop_tag_kind == WACT_EXPECTED_PLAIN_TAG))
 192      {
 193        // restore stack

 194        $this->pushExpectedWactTag($expected_tag, $expected_tag_location);
 195        return WACT_EXPECTED_PLAIN_TAG;
 196      }
 197  
 198      // if we expected a wact tag and poping up a wact tag also and the tags names are different

 199      //  => template is not balanced.

 200      throw new WactException('Unexpected closing tag',
 201                              array('file' => $pop_tag_location->getFile(),
 202                                    'tag' => $pop_tag,
 203                                    'line' => $pop_tag_location->getLine(),
 204                                    'ExpectTag' => $expected_tag,
 205                                    'ExpectTagFile' => $expected_tag_location->getFile(),
 206                                    'ExpectedTagLine' => $expected_tag_location->getLine()));
 207    }
 208  
 209    function popExpectedPlainTag($pop_tag, $pop_tag_location)
 210    {
 211      return $this->_popExpectedTag($pop_tag, $pop_tag_location, WACT_EXPECTED_PLAIN_TAG);
 212    }
 213  
 214    function popExpectedWactTag($pop_tag, $pop_tag_location)
 215    {
 216      return $this->_popExpectedTag($pop_tag, $pop_tag_location, WACT_EXPECTED_WACT_TAG);
 217    }
 218  
 219    function getExpectedTagCount()
 220    {
 221      return count($this->expected_tags);
 222    }
 223  
 224    function getExpectedTag()
 225    {
 226      // Returns the tagname of the first non-component item on the stack

 227      $item = end($this->expected_tags);
 228      while ($item && !is_string($item[0])) {
 229        $item = prev($this->expected_tags);
 230      }
 231      return $item ? $item[0] : false;
 232    }
 233  
 234    function getExpectedTagLocation()
 235    {
 236      $item = end($this->expected_tags);
 237      return $item[1];
 238    }
 239  
 240    function addProcessingInstruction($target, $instruction)
 241    {
 242      // Pass through any PI's except PHP PI's

 243      $php_targets = array('php','PHP','=','');
 244      if(in_array($target, $php_targets))
 245      {
 246        $this->addNode(new WactPHPNode(null, $instruction));
 247      }
 248      else
 249      {
 250        $php = 'echo "<?'.$target.' '; // Whitespace assumption

 251        $php.= str_replace('"','\"',$instruction);
 252        $php.= '?>\n";'; // Newline assumption

 253        $this->addNode(new WactPHPNode(null, $php));
 254      }
 255    }
 256  
 257    /**

 258    * Builds a component, adding attributes

 259    * @param WactTagInfo

 260    * @param string XML tag name of component

 261    * @param array attributes for tag

 262    * @param boolean whether the tag has contents

 263    * @return WactCompileTreeNode

 264    */
 265    function buildTagNode($tag_info, $tag, $location, $attrs, $is_empty = false, $has_closing_tag = true)
 266    {
 267      $tag_node = $this->_createTagNode($tag_info, $tag, $location);
 268  
 269      $this->_registerPropertiesInTagNode($tag_node);
 270  
 271      $tag_node->emptyClosedTag = $is_empty;
 272      $tag_node->hasClosingTag = $has_closing_tag;
 273  
 274      $this->_convertAttributesToExpressionIfRequired($tag_node, $tag_info, $attrs);
 275  
 276      $this->_addAttributesToTagNode($tag_node, $location, $attrs);
 277  
 278      return $tag_node;
 279    }
 280  
 281    protected function _createTagNode($tag_info, $tag, $location)
 282    {
 283      $class = $tag_info->TagClass;
 284      $tag_node = new $class($location, $tag, $tag_info);
 285  
 286      return $tag_node;
 287    }
 288  
 289    protected function _registerPropertiesInTagNode($tag_node)
 290    {
 291      $properties = $this->property_dictionary->getPropertyList($tag_node);
 292      foreach ($properties as $property)
 293      {
 294        $property->load();
 295        $property_class = $property->PropertyClass;
 296        $tag_node->registerProperty($property->Property, new $property_class($tag_node));
 297      }
 298    }
 299  
 300    protected function _addAttributesToTagNode($tag_node, $location, $attrs)
 301    {
 302      foreach ($attrs as $name => $value)
 303      {
 304        $attribute = new WactAttribute($name);
 305        if($value !== NULL)
 306        {
 307          $listener = new WactAttributeBlockAnalizerListener($attribute, $tag_node, $this->filter_dictionary);
 308  
 309          $analizer = new WactBlockAnalizer();
 310          $analizer->parse($value, $listener);
 311        }
 312  
 313        $tag_node->addChildAttribute($attribute);
 314      }
 315    }
 316  
 317    // this code added to support old form of DBE expressions in some attributes

 318    // like <core:optional for='var'> should actually be <core:optional

 319    protected function _convertAttributesToExpressionIfRequired($tag_node, $tag_info, &$attributes)
 320    {
 321      foreach($tag_info->getConvertAttributesToExpressions() as $name)
 322      {
 323        if(!isset($attributes[$name]))
 324          continue;
 325  
 326        $value = $attributes[$name];
 327  
 328        if(strpos($value, '{$') !== FALSE)
 329          continue;
 330  
 331        if($tag_node->isDataSource() && (strpos($value, '#') === FALSE))
 332          $attributes[$name] = '{$^' . $value . '}';
 333        else
 334          $attributes[$name] = '{$' . $value . '}';
 335      }
 336    }
 337  
 338    function addContent($text, $location)
 339    {
 340      $listener = new WactContentBlockAnalizerListener($this, $location, $this->filter_dictionary);
 341      $analizer = new WactBlockAnalizer();
 342      $analizer->parse($text, $listener);
 343    }
 344  }
 345  ?>


Generated: Sat Sep 6 04:46:52 2008 Cross-referenced by PHPXref 0.7