[limb-svn] r4162 - in 3.x/packages/wact/trunk/framework/template/compiler: . filter parser property tags

svn at limb-project.com svn at limb-project.com
Mon Oct 16 10:51:27 MSD 2006


Author: serega
Date: 2006-10-16 10:51:26 +0400 (Mon, 16 Oct 2006)
New Revision: 4162

Added:
   3.x/packages/wact/trunk/framework/template/compiler/CompilerArtifactDictionary.class.php
   3.x/packages/wact/trunk/framework/template/compiler/compile_tree_node/
   3.x/packages/wact/trunk/framework/template/compiler/parser/HTMLParser.class.php
   3.x/packages/wact/trunk/framework/template/compiler/parser/SourceFileParser.class.php
   3.x/packages/wact/trunk/framework/template/compiler/parser/WactBaseParsingState.class.php
   3.x/packages/wact/trunk/framework/template/compiler/parser/WactComponentParsingState.class.php
   3.x/packages/wact/trunk/framework/template/compiler/parser/WactLiteralParsingState.class.php
   3.x/packages/wact/trunk/framework/template/compiler/parser/WactNodeBuilder.class.php
   3.x/packages/wact/trunk/framework/template/compiler/parser/WactSourceLocation.class.php
   3.x/packages/wact/trunk/framework/template/compiler/parser/WactTreeBuilder.class.php
Removed:
   3.x/packages/wact/trunk/framework/template/compiler/HTMLParser.class.php
   3.x/packages/wact/trunk/framework/template/compiler/SourceFileParser.class.php
   3.x/packages/wact/trunk/framework/template/compiler/WactBaseParsingState.class.php
   3.x/packages/wact/trunk/framework/template/compiler/WactComponentParsingState.class.php
   3.x/packages/wact/trunk/framework/template/compiler/WactLiteralParsingState.class.php
   3.x/packages/wact/trunk/framework/template/compiler/WactNodeBuilder.class.php
   3.x/packages/wact/trunk/framework/template/compiler/WactSourceLocation.class.php
   3.x/packages/wact/trunk/framework/template/compiler/WactTreeBuilder.class.php
   3.x/packages/wact/trunk/framework/template/compiler/common/
Modified:
   3.x/packages/wact/trunk/framework/template/compiler/filter/dictionary.inc.php
   3.x/packages/wact/trunk/framework/template/compiler/property/dictionary.inc.php
   3.x/packages/wact/trunk/framework/template/compiler/tags/tagdictionary.inc.php
   3.x/packages/wact/trunk/framework/template/compiler/templatecompiler.inc.php
Log:
-- -- WACT package clean up and refactoring



Added: 3.x/packages/wact/trunk/framework/template/compiler/CompilerArtifactDictionary.class.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/CompilerArtifactDictionary.class.php	                        (rev 0)
+++ 3.x/packages/wact/trunk/framework/template/compiler/CompilerArtifactDictionary.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -0,0 +1,54 @@
+<?php
+class CompilerArtifactDictionary
+{
+  protected $search_paths = array();
+  protected $config;
+
+  function __construct($config = null) {
+    $this->config = $config;
+  }
+
+  function _createArtifactsExtractor($file){}
+
+  function setConfig($config) {
+    $this->config = $config;
+  }
+
+  function _prepareSearchPaths() {
+    $paths = array();
+
+    foreach($this->config->getScanDirectories() as $dir) {
+      foreach($this->_getThisAndImmediateDirectories($dir) as $item)
+        $paths[] = $item;
+    }
+    $this->search_paths = $paths;
+  }
+
+  function _getThisAndImmediateDirectories($dir)
+  {
+    $dirs = array($dir);
+    foreach(glob("$dir/*") as $item) {
+      if($item{0} != '.' && is_dir($item))
+        $dirs[] = $item;
+    }
+    return $dirs;
+  }
+
+  function extractItems($scandir, $extension) {
+    require_once WACT_ROOT . '/template/annotation/parser.inc.php';
+    $parser = new WactClassAnnotationParser();
+
+    foreach(glob("$scandir/*$extension") as $file) {
+      $extractor = $this->_createArtifactsExtractor($file);
+      $parser->process($extractor, file_get_contents($file));
+    }
+  }
+
+  function buildDictionary($extension) {
+    $this->_prepareSearchPaths();
+
+    foreach ($this->search_paths as $path)
+      $this->extractItems($path, $extension);
+  }
+}
+?>
\ No newline at end of file

Deleted: 3.x/packages/wact/trunk/framework/template/compiler/HTMLParser.class.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/HTMLParser.class.php	2006-10-16 06:38:46 UTC (rev 4161)
+++ 3.x/packages/wact/trunk/framework/template/compiler/HTMLParser.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -1,380 +0,0 @@
-<?php
-//--------------------------------------------------------------------------------
-// Copyright 2003 Procata, Inc.
-// Released under the LGPL license (http://www.gnu.org/copyleft/lesser.html)
-//--------------------------------------------------------------------------------
-
-/**
-* HTML/XHTML/XML parser
-* fast parser robustly handles malformed input.
-* All events are triggered by valid markup.
-* If markup is invalid, it is treated as data event.
-* @access protected
-* @abstract
-*/
-class HTMLParser
-{
-    var $publicId;
-    var $Observer;
-    /**
-    * XML document being parsed
-    * @var string
-    * @access private
-    */
-    var $rawtext;
-    /**
-    * Position in XML document relative to start (0)
-    * @var int
-    * @access private
-    */
-    var $position;
-    /**
-    * Length of the XML document in characters
-    * @var int
-    * @access private
-    */
-    var $length;
-
-    /**
-    * @var Observer event handler
-    * @access protected
-    */
-    function HTMLParser(&$Observer) {
-        $this->Observer =& $Observer;
-    }
-
-    /*
-    * Calculates the line number from the byte index
-    * @return int the current line number
-    * @access private
-    */
-    function getLineNumber() {
-        return 1 + substr_count(substr($this->rawtext, 0, $this->position), "\n");
-    }
-
-    function getPublicId() {
-        return $this->publicId;
-    }
-
-    /*
-    * Calculates the column number from the byte index
-    * @return int the current line number
-    * @access private
-    */
-    function getColumnNumber() {
-        // Not implemented yet.
-    }
-
-    /**
-    * Moves the position forward past any whitespace characters
-    * @access protected
-    * @return void
-    */
-    function ignoreWhitespace() {
-        while ($this->position < $this->length &&
-            strpos(" \n\r\t", $this->rawtext{$this->position}) !== FALSE) {
-            $this->position++;
-        }
-    }
-
-    /**
-    * Begins the parsing operation, setting up any decorators, depending on
-    * parse options invoking _parse() to execute parsing
-    * @param string XML document to parse
-    * @access protected
-    * @return void
-    */
-    function parse($data, $publicId = NULL) {
-        $this->rawtext = $data;
-        $this->length = strlen($data);
-        $this->position = 0;
-        $this->publicId = $publicId;
-
-        $this->Observer->setDocumentLocator($this);
-
-        do {
-            $start = $this->position;
-            $this->position = strpos($this->rawtext, '<', $start);
-            if ($this->position === FALSE) {
-                if ($start < $this->length) {
-                    $this->Observer->characters(substr($this->rawtext, $start));
-                }
-                return;
-            }
-
-            if ($this->position > $start) {
-                $this->Observer->characters(substr($this->rawtext, $start, $this->position - $start));
-            }
-
-            $this->position += 1;   // ignore '<' character
-            if ($this->position >= $this->length) {
-                $this->Observer->unexpectedEOF('<');
-                return;
-            }
-
-            $element_pos = $this->position;
-            $this->position += 1;
-
-            switch($this->rawtext{$element_pos}) {
-            case '/':
-                $start = $this->position;
-                while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
-                    $this->position++;
-                }
-                if ($this->position >= $this->length) {
-                    $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
-                    return;
-                }
-
-                $tag = substr($this->rawtext, $start, $this->position - $start);
-
-                $this->Observer->endElement($tag);
-                $this->position += 1;   // ignore '>' string
-                break;
-            case '?':
-                $start = $this->position;
-                while ($this->position < $this->length && strpos(" \n\r\t", $this->rawtext{$this->position}) === FALSE) {
-                    $this->position++;
-                }
-                if ($this->position >= $this->length) {
-                    $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
-                    return;
-                }
-
-                $target = substr($this->rawtext, $start, $this->position - $start);
-
-                $this->ignoreWhitespace();
-
-                $start = $this->position;
-                $this->position = strpos($this->rawtext, '?>', $start);
-                if ($this->position === FALSE) {
-                    $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
-                    return;
-                }
-
-                $this->Observer->processingInstruction($target,
-                    substr($this->rawtext, $start, $this->position - $start));
-
-                $this->position += 2;   // ignore '? >' string
-                break;
-            case '%':
-                if ($this->position >= $this->length) {
-                    $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
-                    return;
-                }
-
-                $start = $this->position;
-                $this->position = strpos($this->rawtext, '%>', $start);
-                if ($this->position === FALSE) {
-                    $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
-                    return;
-                }
-
-                $this->Observer->jasp(substr($this->rawtext, $start, $this->position - $start));
-
-        /* changed to multi line comment per request on list
-        http://sourceforge.net/mailarchive/forum.php?thread_id=5925242&forum_id=35579
-        ignore '%>' string
-        */
-                $this->position += 2;
-                break;
-            case '!':
-                if ($this->position >= $this->length) {
-                    $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
-                    return;
-                }
-
-                $start = $this->position;
-                if (substr($this->rawtext, $start, 2) == "--") {
-                    $this->position = strpos($this->rawtext, '-->', $start);
-                    if ($this->position === FALSE) {
-                        $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
-                        return;
-                    }
-                    $this->Observer->comment(
-                        substr($this->rawtext, $start + 2, $this->position - $start - 2));
-                    $this->position += 3;
-                } else if (strcasecmp(substr($this->rawtext, $start, 7), 'DOCTYPE') == 0) {
-                    while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
-                        $this->position++;
-                    }
-                    if ($this->position >= $this->length) {
-                        $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
-                        return;
-                    }
-                    $this->Observer->doctype(
-                        substr($this->rawtext, $start, $this->position - $start));
-                    $this->position += 1;
-                } else if (substr($this->rawtext, $start, 7) == '[CDATA[') {
-                    $this->position = strpos($this->rawtext, ']]>', $start + 7);
-                    if ($this->position === FALSE) {
-                        $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
-                        return;
-                    }
-                    $this->Observer->cdata(
-                        substr($this->rawtext, $start + 7 , $this->position - $start - 7));
-                    $this->position += 3;
-                } else {
-                    while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
-                        $this->position++;
-                    }
-                    if ($this->position >= $this->length) {
-                        $this->Observer->unexpectedEOF(
-                            substr($this->rawtext, $element_pos - 1));
-                        return;
-                    }
-                    $this->position += 1;
-                    $this->Observer->escape(
-                        substr($this->rawtext, $start, $this->position - $start));
-                }
-                break;
-            default:
-                while ($this->position < $this->length && strpos("/> \n\r\t", $this->rawtext{$this->position}) === FALSE) {
-                    $this->position++;
-                }
-                if ($this->position >= $this->length) {
-                    $this->Observer->unexpectedEOF(
-                        substr($this->rawtext, $element_pos - 1));
-                    return;
-                }
-
-                $tag = substr($this->rawtext, $element_pos, $this->position - $element_pos);
-                $Attributes = array();
-
-                $this->ignoreWhitespace();
-
-                while ( $this->position < $this->length &&
-                        $this->rawtext{$this->position} != '/' &&
-                        $this->rawtext{$this->position} != '>') {
-
-                    $start = $this->position;
-                    while ($this->position < $this->length && strpos("/>= \n\r\t", $this->rawtext{$this->position}) === FALSE) {
-                        $this->position++;
-                    }
-                    if ($this->position >= $this->length) {
-                        $this->Observer->unexpectedEOF(
-                            substr($this->rawtext, $element_pos - 1));
-                        return;
-                    }
-
-                    $attributename = substr($this->rawtext, $start, $this->position - $start);
-                    $attributevalue = NULL;
-
-                    $this->ignoreWhitespace();
-                    if ($this->position >= $this->length) {
-                        $this->Observer->unexpectedEOF(
-                            substr($this->rawtext, $element_pos - 1));
-                        return;
-                    }
-
-                    if ( $this->rawtext{$this->position} == '=') {
-                        $this->position++;
-                        $this->ignoreWhitespace();
-                        if ($this->position >= $this->length) {
-                            $this->Observer->unexpectedEOF(
-                                substr($this->rawtext, $element_pos - 1));
-                            return;
-                        }
-
-                        $quote = $this->rawtext{$this->position};
-                        if ($quote == '"' || $quote == "'") {
-                            $start = $this->position + 1;
-                            $this->position = strpos($this->rawtext, $quote, $start);
-                            if ($this->position === FALSE) {
-                                $this->Observer->unexpectedEOF(
-                                    substr($this->rawtext, $element_pos - 1));
-                                return;
-                            }
-                            $attributevalue = substr($this->rawtext, $start, $this->position - $start);
-
-                            $this->position++;
-                            if ($this->position >= $this->length) {
-                                $this->Observer->unexpectedEOF(
-                                    substr($this->rawtext, $element_pos - 1));
-                                return;
-                            }
-
-                            if (strpos("/> \n\r\t", $this->rawtext{$this->position}) === FALSE) {
-                                $this->Observer->invalidAttributeSyntax();
-                            }
-
-                        } else {
-                            $start = $this->position;
-                            while ($this->position < $this->length && strpos("/> \n\r\t", $this->rawtext{$this->position}) === FALSE) {
-                                $this->position++;
-                            }
-                            if ($this->position >= $this->length) {
-                                $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
-                                return;
-                            }
-                            $attributevalue = substr($this->rawtext, $start, $this->position - $start);
-                        }
-                    }
-
-                    $Attributes[$attributename] = $attributevalue;
-
-                    $this->ignoreWhitespace();
-                }
-
-                if ($this->position >= $this->length) {
-                    $this->Observer->unexpectedEOF(
-                        substr($this->rawtext, $element_pos - 1));
-                    return;
-                }
-
-                if ($this->rawtext{$this->position} == '/') {
-                    $this->position += 1;
-                    if ($this->position >= $this->length) {
-                        $this->Observer->unexpectedEOF(
-                            substr($this->rawtext, $element_pos - 1));
-                        return;
-                    }
-
-                    if ($this->rawtext{$this->position} != '>') {
-                        $start = $this->position;
-                        while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
-                            $this->position++;
-                        }
-                        if ($this->position >= $this->length) {
-                            $this->Observer->invalidEntitySyntax(
-                                substr($this->rawtext, $element_pos - 1));
-                            break;
-                        }
-
-                        $this->Observer->invalidEntitySyntax(
-                            substr($this->rawtext, $element_pos - 1, $this->position - $element_pos + 2));
-                        $this->position += 1;
-                        break;
-                    }
-
-                    $this->Observer->emptyElement($tag, $Attributes);
-                } else {
-                    $this->Observer->startElement($tag, $Attributes);
-                }
-                $this->position += 1;
-
-                /*
-                removed due to bug #1000806
-                see http://www.w3.org/TR/REC-html40/appendix/notes.html#notes-specifying-data
-                if (strcasecmp($tag, 'script') == 0 || strcasecmp($tag, 'style') == 0) {
-                    $start = $this->position;
-                    $this->position = strpos($this->rawtext, '</', $start);
-                    if ($this->position == FALSE) {
-                        $this->Observer->unexpectedEOF(
-                            substr($this->rawtext, $start));
-                        return;
-                    }
-
-                    $this->Observer->characters(
-                        substr($this->rawtext, $start, $this->position - $start));
-
-                }
-                */
-
-                break;
-            }
-        } while ($this->position < $this->length);
-    }
-
-}
-?>

Deleted: 3.x/packages/wact/trunk/framework/template/compiler/SourceFileParser.class.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/SourceFileParser.class.php	2006-10-16 06:38:46 UTC (rev 4161)
+++ 3.x/packages/wact/trunk/framework/template/compiler/SourceFileParser.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -1,315 +0,0 @@
-<?php
-//--------------------------------------------------------------------------------
-// Copyright 2003 Procata, Inc.
-// Released under the LGPL license (http://www.gnu.org/copyleft/lesser.html)
-//--------------------------------------------------------------------------------
-/**
-* @package WACT_TEMPLATE
-* @version $Id: SourceFileParser.class.php,v 1.114 2006/01/04 04:57:05 ian_w_white Exp $
-*/
-//--------------------------------------------------------------------------------
-/**
-* Define compile component states which determine parse behaviour
-*/
-define('PARSER_REQUIRE_PARSING', TRUE);
-define('PARSER_FORBID_PARSING', FALSE);
-define('PARSER_ALLOW_PARSING', NULL);
-
-//--------------------------------------------------------------------------------
-/**
-* Includes
-*/
-require_once WACT_ROOT . '/template/compiler/WactNodeBuilder.class.php';
-require_once WACT_ROOT . '/template/compiler/WactTreeBuilder.class.php';
-require_once WACT_ROOT . '/template/compiler/WactLiteralParsingState.class.php';
-require_once WACT_ROOT . '/template/compiler/WactComponentParsingState.class.php';
-require_once WACT_ROOT . '/template/compiler/HtmlParser.class.php';
-
-//--------------------------------------------------------------------------------
-/**
-* The source template parser is the core of the WACT template engine
-* @see http://wact.sourceforge.net/index.php/SourceFileParser
-* @access public
-* @package WACT_TEMPLATE
-*/
-class SourceFileParser implements ParserListener
-{
-  /**
-  * Path and filename of source template
-  * @var string
-  * @access private
-  */
-  var $SourceFile;
-  /**
-  * Initial instance of WactComponentParsingState
-  * @var WactComponentParsingState
-  * @access private
-  */
-  var $ComponentParsingState;
-  /**
-  * Initial instance of WactLiteralParsingState
-  * @var WactLiteralParsingState
-  * @access private
-  */
-  var $LiteralParsingState;
-  /**
-  * The current active state
-  * @var WactBaseParsingState subclass
-  * @access public
-  */
-  var $State;
-
-  protected $config;
-
-  /**
-   * Template locator
-   * @var WactLocator
-   */
-  protected $locator;
-
-  function __construct($sourcefile, $TreeBuilder, $config, $locator)
-  {
-    $this->SourceFile = $sourcefile;
-    $this->TreeBuilder = $TreeBuilder;
-    $this->config = $config;
-    $this->locator = $locator;
-  }
-
-  function getSourceFile()
-  {
-    return $this->SourceFile;
-  }
-
-  /**
-  * Creates Build a filter chain
-  * @return HTMLParser
-  * @access protected
-  */
-  function &buildFilterChain($saxfilters) {
-      $Chain =& $this;
-
-      // Build a filter chain
-      if ( !empty($saxfilters) ) {
-          foreach (explode(':', $saxfilters) as $saxfilter) {
-              $saxfilterfile = strtolower($saxfilter).'saxfilter.inc.php';
-              $saxfilterclass = $saxfilter . 'SaxFilter';
-              if ( !include_once WACT_ROOT . '/template/compiler/saxfilters/'.$saxfilterfile ) {
-                  throw new WactException('compiler', 'SAXFILTER_NOTFOUND', array(
-                      'path' => WACT_ROOT . '/template/compiler/saxfilters/'.$saxfilterfile,
-                      'name' => ucfirst($saxfilter)));
-              } else {
-                  $NewFilter =& new $saxfilterclass();
-                  $NewFilter->setChildSaxFilter($Chain);
-                  $Chain =& $NewFilter;
-              }
-          }
-      }
-
-      return $Chain;
-  }
-
-  /**
-  * Used to parse the source template.
-  * Initially invoked by the CompileTemplate function,
-  * the first component argument being a ComponentTree.
-  * Uses the TagDictionary to spot compiler components
-  * @see CompileTemplate
-  * @see ComponentTree
-  * @param object compile time component
-  * @return void
-  * @access protected
-  */
-  function parse($ComponentRoot)
-  {
-    $TagDictionary = WactDictionaryHolder ::instance()->getTagDictionary();
-
-    $NodeBuilder =& new WactNodeBuilder();
-
-    $tagCountBeforeParse = $this->TreeBuilder->getExpectedTagCount();
-
-    $this->TreeBuilder->setCursor($ComponentRoot);
-
-    $this->ComponentParsingState = new WactComponentParsingState($this, $this->TreeBuilder, $NodeBuilder, $TagDictionary);
-    $this->LiteralParsingState = new WactLiteralParsingState($this, $this->TreeBuilder);
-    $this->changeToComponentParsingState();
-
-    $Chain =& $this->buildFilterChain($this->config->getSaxFilters());
-    $parser = new HTMLParser($Chain);
-    $template = $this->locator->readTemplateFile($this->SourceFile);
-    $parser->parse($template, $this->SourceFile);
-
-    if ($tagCountBeforeParse != $this->TreeBuilder->getExpectedTagCount()) {
-        throw new WactException('compiler', 'MISSINGCLOSE', array(
-        'tag' => $this->TreeBuilder->getExpectedTag(),
-          'file' => $ComponentRoot->SourceLocation->file,
-          'line' => $ComponentRoot->SourceLocation->line));
-    }
-  }
-
-
-  /**
-  * Switch to component parsing state
-  * @return void
-  * @access public
-  */
-  function changeToComponentParsingState() {
-      $this->State = $this->ComponentParsingState;
-  }
-
-  /**
-  * Switch to literal parsing state
-  * @param string tag name marking the literal component
-  * @return void
-  * @access public
-  */
-  function changeToLiteralParsingState($tag) {
-      $this->State = $this->LiteralParsingState;
-      $this->State->setLiteralTag($tag);
-  }
-
-  /**
-  * Document Locator Handler
-  * @param Locator
-  * @return void
-  * @access private
-  */
-  function setDocumentLocator($locator) {
-      $this->LiteralParsingState->setDocumentLocator($locator);
-      $this->ComponentParsingState->setDocumentLocator($locator);
-  }
-
-  /**
-  * Sax Open Handler
-  * @param string tag name
-  * @param array attributes
-  * @return void
-  * @access private
-  */
-  function startElement($tag, $attrs) {
-      $this->State->startElement($tag, $attrs);
-  }
-
-  /**
-  * Sax Close Handler
-  * @param string tag name
-  * @return void
-  * @access private
-  */
-  function endElement($tag) {
-      $this->State->endElement($tag);
-  }
-
-  /**
-  * Sax Open Handler
-  * @param string tag name
-  * @param array attributes
-  * @return void
-  * @access private
-  */
-  function emptyElement($tag, $attrs) {
-      $this->State->emptyElement($tag, $attrs);
-  }
-
-  /**
-  * Sax Data Handler
-  * @param string text content in tag
-  * @return void
-  * @access private
-  */
-  function characters($text) {
-      $this->State->characters($text);
-  }
-
-  /**
-  * Sax CDATA Handler
-  * @param string text content in tag
-  * @return void
-  * @access private
-  */
-  function cdata($text) {
-      $this->State->cdata($text);
-  }
-
-  /**
-  * Sax Processing Instruction Handler
-  * @param string target processor (e.g. php)
-  * @param string text content in PI
-  * @return void
-  * @access private
-  */
-  function processingInstruction($target, $instruction) {
-      $this->State->processingInstruction($target, $instruction);
-  }
-
-  /**
-  * Sax XML Escape Handler
-  * @param string text content in escape
-  * @return void
-  * @access private
-  */
-  function escape($text) {
-      $this->State->escape($text);
-  }
-
-  /**
-  * Sax XML Comment Handler
-  * @param string text content in comment
-  * @return void
-  * @access private
-  */
-  function comment($text) {
-      $this->State->comment($text);
-  }
-
-  /**
-  * Sax XML doctype Handler
-  * @param string text content in doctype
-  * @return void
-  * @access private
-  */
-  function doctype($text) {
-      $this->State->doctype($text);
-  }
-
-  /**
-  * Sax JSP / ASP markup Handler
-  * @param string text content in JASP tags
-  * @return void
-  * @access private
-  */
-  function jasp($text) {
-      $this->State->jasp($text);
-  }
-
-  /**
-  * Sax EOF Handler
-  * @param string text content in tag
-  * @return void
-  * @access private
-  */
-  function unexpectedEOF($text) {
-      $this->State->unexpectedEOF($text);
-  }
-
-  /**
-  * Sax Entity syntax Error Handler
-  * @param string text content in tag
-  * @return void
-  * @access private
-  */
-  function invalidEntitySyntax($text) {
-      $this->State->invalidEntitySyntax($text);
-  }
-
-  /**
-  * Sax Attribute syntax Error Handler
-  * @param string text content in tag
-  * @return void
-  * @access private
-  */
-  function invalidAttributeSyntax() {
-      $this->State->invalidAttributeSyntax();
-  }
-}
-
-?>

Deleted: 3.x/packages/wact/trunk/framework/template/compiler/WactBaseParsingState.class.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/WactBaseParsingState.class.php	2006-10-16 06:38:46 UTC (rev 4161)
+++ 3.x/packages/wact/trunk/framework/template/compiler/WactBaseParsingState.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -1,65 +0,0 @@
-<?php
-/**
-* Base state handler for the SourceFileParser. Handles plain text
-*/
-abstract class WactBaseParsingState
-{
-  /**
-  * Instance of SourceFileParser
-  * @var SourceFileParser
-  * @access private
-  */
-  var $Parser;
-
-  /**
-  * Used to locate position within document
-  * @access private
-  */
-  var $Locator;
-
-  /**
-  * Instance of WactTreeBuilder
-  * @var WactTreeBuilder
-  * @access private
-  */
-  var $TreeBuilder;
-
-  function __construct($Parser, $TreeBuilder)
-  {
-    $this->Parser = $Parser;
-    $this->TreeBuilder = $TreeBuilder;
-  }
-
-  function setDocumentLocator($locator)
-  {
-    $this->Locator = $locator;
-    $this->TreeBuilder->setDocumentLocator($locator);
-  }
-
-  function getAttributeString($attrs)
-  {
-      $attrib_str = '';
-      foreach ( $attrs as $key => $value ) {
-          $attrib_str .= ' ' . $key;
-          if (!is_null($value)) {
-              if (strpos($value, '"') === FALSE) {
-                  $attrib_str .= '="' . $value . '"';
-              } else {
-                  $attrib_str .= '=\'' . $value . '\'';
-              }
-          }
-      }
-      return $attrib_str;
-  }
-
-  /**
-  * Attribute syntax Error Handler
-  */
-  function invalidAttributeSyntax()
-  {
-    throw new WactException('compiler', 'INVALID_ATTRIBUTE_SYNTAX', array(
-        'file' => $this->Locator->getPublicId(),
-        'line' => $this->Locator->getLineNumber()));
-  }
-}
-?>
\ No newline at end of file

Deleted: 3.x/packages/wact/trunk/framework/template/compiler/WactComponentParsingState.class.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/WactComponentParsingState.class.php	2006-10-16 06:38:46 UTC (rev 4161)
+++ 3.x/packages/wact/trunk/framework/template/compiler/WactComponentParsingState.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -1,278 +0,0 @@
-<?php
-require_once(WACT_ROOT . '/template/compiler/parser/ParserListener.interface.php');
-require_once(WACT_ROOT . '/template/compiler/WactBaseParsingState.class.php');
-
-define ('PARSER_TAG_IS_COMPONENT', 	1);
-define ('PARSER_TAG_IS_PLAIN', 		2);
-
-class WactComponentParsingState extends WactBaseParsingState implements ParserListener
-{
-    /**
-    * Instance of TagDictionary
-    * @var TagDictionary
-    * @access private
-    */
-    var $TagDictionary;
-
-    /**
-    * Instance of Node Builder
-    * @access private
-    */
-    var $NodeBuilder;
-
-    /**
-    * @param SourceFileParser
-    * @access public
-    */
-    function __construct($Parser, $TreeBuilder, $NodeBuilder, $TagDictionary)
-    {
-      parent :: __construct($Parser, $TreeBuilder);
-      $this->TagDictionary = $TagDictionary;
-      $this->NodeBuilder = $NodeBuilder;
-    }
-
-    /**
-    * @param Locator
-    * @access protected
-    */
-    function setDocumentLocator($locator)
-    {
-      parent::setDocumentLocator($locator);
-
-      $this->NodeBuilder->setDocumentLocator($locator);
-    }
-
-    /**
-  * Builds an attribute string based on passed array of attributes
-  * @param array
-  * @return string
-  * @access protected
-  */
-    function getAttributeString($attrs) {
-        $attrib_str = '';
-        foreach ( $attrs as $key => $value ) {
-            if (strcasecmp($key, PARSER_TRIGGER_ATTR_NAME) == 0 ) {
-                continue;
-            }
-
-            $attrib_str .= ' ' . $key;
-            if (!is_null($value)) {
-                if (strpos($value, '"') === FALSE) {
-                    $attrib_str .= '="' . $value . '"';
-                } else {
-                    $attrib_str .= '=\'' . $value . '\'';
-                }
-            }
-        }
-        return $attrib_str;
-    }
-
-    /**
-    * Handle opening tags
-    * @param string tag name
-    * @param array tag attributes
-    * @access public
-    */
-    function startElement($tag, $attrs)
-    {
-      $lower_attributes = $this->checkAttributes($attrs);
-
-      $TagInfo =& $this->TagDictionary->findComponent($tag, $lower_attributes, FALSE, $this->TreeBuilder->getCursor());
-
-      if (is_object($TagInfo))
-      {
-        $TagInfo->load();
-
-        // If a closing tag not forbidden then expect a closing tag
-        if ( $TagInfo->EndTag != ENDTAG_FORBIDDEN )
-          $this->TreeBuilder->pushExpectedTag($tag, PARSER_TAG_IS_COMPONENT, $this->_getPositionInfo());
-
-        $component =& $this->NodeBuilder->buildTagNode($TagInfo, $tag, $attrs, FALSE);
-        if ( $this->TreeBuilder->pushNode($component) == PARSER_FORBID_PARSING)
-          $this->Parser->changeToLiteralParsingState($tag);
-
-        // Cleanup for components that have no closing tag
-        if ( $TagInfo->EndTag == ENDTAG_FORBIDDEN )
-        {
-          $this->TreeBuilder->popNode(FALSE);
-          $this->Parser->changeToComponentParsingState();
-        }
-      }
-      else
-      {
-        $this->TreeBuilder->pushExpectedTag($tag, PARSER_TAG_IS_PLAIN, $this->_getPositionInfo());
-        $this->NodeBuilder->addContent($this->TreeBuilder, '<' . $tag . $this->getAttributeString($attrs) . '>');
-      }
-    }
-
-    /**
-    * Handle closing tags
-    * @param string tag name
-    * @access public
-    */
-    function endElement($tag)
-    {
-      $TagInfo =& $this->TagDictionary->getTagInfo($tag);
-      if (is_object($TagInfo))
-      {
-        if ($TagInfo->EndTag == ENDTAG_FORBIDDEN)
-        {
-              throw new WactException('compiler', 'UNEXPECTEDCLOSE2', array(
-                  'tag' => $TagInfo->Tag,
-                  'file' => $this->Locator->getPublicId(),
-                  'line' => $this->Locator->getLineNumber()));
-        }
-      }
-
-      if ($this->TreeBuilder->popExpectedTag($tag, $this->_getPositionInfo()) == PARSER_TAG_IS_COMPONENT)
-        $this->TreeBuilder->popNode(TRUE);
-      else
-        $this->TreeBuilder->addTextNode('</' . $tag .'>');
-    }
-
-    function _getPositionInfo()
-    {
-      return array('line' => $this->Locator->getLineNumber(),
-                   'file' => $this->Parser->getSourceFile());
-    }
-
-    /**
-    * Handle empty tags
-    * @param string tag name
-    * @param array tag attributes
-    * @access public
-    */
-    function emptyElement($tag, $attrs)
-    {
-      $lower_attributes = $this->checkAttributes($attrs);
-
-        $TagInfo =& $this->TagDictionary->findComponent($tag, $lower_attributes, TRUE, $this->TreeBuilder->getCursor());
-        if (is_object($TagInfo)) {
-            $TagInfo->load();
-
-            $component =& $this->NodeBuilder->buildTagNode($TagInfo, $tag, $attrs, TRUE);
-            if ( $this->TreeBuilder->pushNode($component) == PARSER_FORBID_PARSING) {
-                $this->Parser->changeToLiteralParsingState($tag);
-      }
-
-      // Cleanup for components that have no closing tag
-            if ( $TagInfo->EndTag == ENDTAG_FORBIDDEN ) {
-                $this->Parser->changeToComponentParsingState();
-                $this->TreeBuilder->popNode(FALSE);
-            } else {
-                $this->TreeBuilder->popNode(TRUE);
-            }
-
-        } else {
-            $this->NodeBuilder->addContent($this->TreeBuilder,
-                '<' . $tag . $this->getAttributeString($attrs) . ' />');
-    }
-    }
-
-  /**
-  * Transforms attributes so keys are lowercase, and checks for
-  * illegal DBEs
-  * @param array
-  * @return array
-  * @access protected
-  */
-  function checkAttributes($attrs) {
-    $lower_attributes = array_change_key_case($attrs, CASE_LOWER);
-        if ( isset($lower_attributes[PARSER_TRIGGER_ATTR_NAME]) &&
-                strpos($lower_attributes[PARSER_TRIGGER_ATTR_NAME], '{$') !== FALSE) {
-            throw new WactException('compiler', 'ILLEGALVARREFINATTR', array(
-                'attribute' => $lower_attributes[PARSER_TRIGGER_ATTR_NAME],
-                'file' => $this->Locator->getPublicId(),
-                'line' => $this->Locator->getLineNumber()));
-        }
-    return $lower_attributes;
-  }
-
-    /**
-    * Handle tag content
-    * @param string tag content
-    * @access public
-    */
-    function characters($text) {
-        $this->NodeBuilder->addContent($this->TreeBuilder, $text);
-    }
-
-    /**
-    * Handle tag content
-    * @param string tag content
-    * @access public
-    */
-    function cdata($text) {
-        $this->NodeBuilder->addContent($this->TreeBuilder, '<![CDATA[' . $text . ']]>');
-    }
-
-    /**
-    * Handle processing instructions
-    * @param string target processor
-    * @param string instruction
-    * @access public
-    */
-    function processingInstruction($target, $instruction) {
-        $this->NodeBuilder->addProcessingInstruction($this->TreeBuilder, $target, $instruction);
-    }
-
-    /**
-    * Handle JSP / ASP markup
-    * @param string content
-    * @access public
-    */
-    function jasp($text) {
-        // Name of method is not good in this case
-        $this->NodeBuilder->addContent($this->TreeBuilder, '<%' . $text . '%>');
-    }
-
-    /**
-    * Handle XML escape sequences
-    * @param string content of escape
-    * @access public
-    */
-    function escape($text) {
-        $this->NodeBuilder->addContent($this->TreeBuilder, '<!' . $text . '>');
-    }
-
-    /**
-    * Handle doctype
-    * @param string content of doctype
-    * @access public
-    */
-    function doctype($text) {
-        $this->NodeBuilder->addContent($this->TreeBuilder, '<!' . $text . '>');
-    }
-
-    /**
-    * Handle XML comments
-    * @param string content of comment
-    * @access public
-    */
-    function comment($text) {
-        // Name of method is not good in this case
-        $this->NodeBuilder->addContent($this->TreeBuilder, '<!--' . $text . '-->');
-    }
-
-    /**
-    * Handle EOF Error
-    * @param string tag content
-    * @access public
-    */
-    function unexpectedEOF($text) {
-        // Ignore the error and treat the rest of the file like data
-        $this->NodeBuilder->addContent($this->TreeBuilder, $text);
-    }
-
-    /**
-    * Entity syntax Error Handler
-    * @param string tag content
-    * @access public
-    */
-    function invalidEntitySyntax($text) {
-        // Ignore the error and treat the rest of the file like data
-        $this->NodeBuilder->addContent($this->TreeBuilder, $text);
-    }
-
-}
-?>
\ No newline at end of file

Deleted: 3.x/packages/wact/trunk/framework/template/compiler/WactLiteralParsingState.class.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/WactLiteralParsingState.class.php	2006-10-16 06:38:46 UTC (rev 4161)
+++ 3.x/packages/wact/trunk/framework/template/compiler/WactLiteralParsingState.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -1,88 +0,0 @@
-<?php
-require_once(WACT_ROOT . '/template/compiler/parser/ParserListener.interface.php');
-require_once(WACT_ROOT . '/template/compiler/WactBaseParsingState.class.php');
-
-class WactLiteralParsingState extends WactBaseParsingState  implements ParserListener
-{
-  protected $literal_tag;
-
-  function setLiteralTag($tag)
-  {
-    $this->literal_tag = $tag;
-  }
-
-  function getLiteralTag()
-  {
-    return $this->literal_tag;
-  }
-
-  function startElement($tag, $attrs)
-  {
-    $this->TreeBuilder->addTextNode('<' . $tag . $this->getAttributeString($attrs) . '>');
-  }
-
-  function endElement($tag)
-  {
-    if ($this->literal_tag == $tag)
-    {
-      $this->TreeBuilder->popExpectedTag($tag);
-      $this->TreeBuilder->popNode(TRUE);
-      $this->Parser->changeToComponentParsingState();
-    }
-    else
-      $this->TreeBuilder->addTextNode('</' . $tag . '>');
-  }
-
-  function emptyElement($tag, $attrs)
-  {
-      $this->TreeBuilder->addTextNode('<' . $tag . $this->getAttributeString($attrs) . ' />');
-  }
-
-  function characters($text)
-  {
-    $this->TreeBuilder->addTextNode($text);
-  }
-
-  function cdata($text)
-  {
-    $this->TreeBuilder->addTextNode('<![CDATA[' . $text . ']]>');
-  }
-
-  function processingInstruction($target, $instruction)
-  {
-    $this->TreeBuilder->addTextNode('<?' . $target . ' ' . $instruction . '?>');
-  }
-
-  function jasp($text)
-  {
-    $this->TreeBuilder->addTextNode('<%' .  $text . '%>');
-  }
-
-  function escape($text)
-  {
-    $this->TreeBuilder->addTextNode('<!' . $text . '>');
-  }
-
-  function comment($text)
-  {
-    $this->TreeBuilder->addTextNode('<!--' . $text . '-->');
-  }
-
-  function doctype($text)
-  {
-    $this->TreeBuilder->addTextNode('<!' . $text . '>');
-  }
-
-  function unexpectedEOF($text)
-  {
-    // Ignore the error and treat the rest of the file like data
-    $this->TreeBuilder->addTextNode($text);
-  }
-
-  function invalidEntitySyntax($text)
-  {
-    // Ignore the error and treat the rest of the file like data
-    $this->TreeBuilder->addTextNode($text);
-  }
-}
-?>
\ No newline at end of file

Deleted: 3.x/packages/wact/trunk/framework/template/compiler/WactNodeBuilder.class.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/WactNodeBuilder.class.php	2006-10-16 06:38:46 UTC (rev 4161)
+++ 3.x/packages/wact/trunk/framework/template/compiler/WactNodeBuilder.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -1,220 +0,0 @@
-<?php
-/**
-* Responsible for building nodes of the component tree.
-* WactTreeBuilder is responsible for the tree structure.
-*/
-class WactNodeBuilder
-{
-  const BEFORE_CONTENT = 1;
-  const EXPRESSION = 2;
-  const AFTER_CONTENT = 5;
-
-  protected $variable_reference_pattern;
-
-  var $locator;
-
-  function __construct()
-  {
-    $this->variableReferencePattern =
-      // start at the beginning
-      '/^' .
-      // Pick up the portion of the string before the variable reference
-      '((?s).*?)' .
-      // Beginning of a variable reference
-      preg_quote('{$', '/') .
-      // Collect the entire variable reference into one subexpression
-      '(' .
-          // capture the contents of one or more fragments.
-          '(' .
-              // Anything thats not a quote or the end of the variable
-              // reference can be in a fragment
-              '[^"\'}]+' .
-              // OR
-              '|' .
-              // A string inside quotes is also a fragment
-              '(\'|").*?\4' .
-          ')+' .
-      ')' .
-      // end of a variable reference
-      preg_quote('}', '/') .
-      // Pick up the portion of the string after the variable reference
-      // This portion may contain additional references; we only match
-      // one at a time.
-      '((?s).*)' .
-      // Match until the end of the string
-      '$/';
-  }
-
-  function setDocumentLocator($locator)
-  {
-    $this->locator = $locator;
-  }
-
-  /**
-  * Builds a component, adding attributes
-  * @param TagInfo
-  * @param string XML tag name of component
-  * @param array attributes for tag
-  * @param boolean whether the tag has contents
-  * @return CompilerComponent
-  * @access public
-  */
-  function buildTagNode($TagInfo, $tag, $attrs, $isEmpty)
-  {
-    $component = $this->_initTagNode($TagInfo, $tag);
-    $component->emptyClosedTag = $isEmpty;
-    $this->addAttributesToComponent($component, $attrs);
-    return $component;
-  }
-
-  /**
-  * Builds content node(s), adding it (them) to the component tree.
-  * A single piece of content may actually be a mix of terminal nodes
-  * (TextNodes and Expressions)
-  * @param WactTreeBuilder
-  * @param string content of tag
-  * @return void
-  * @access public
-  */
-  function addContent(&$TreeBuilder, $text) {
-      // if there is no expression (common case), shortcut this process
-      if (strpos($text, '{$') === FALSE) {
-          $TreeBuilder->addTextNode($text);
-          return;
-      }
-
-      while (preg_match($this->variableReferencePattern, $text, $match)) {
-          if (strlen($match[self :: BEFORE_CONTENT]) > 0) {
-              $TreeBuilder->addTextNode($match[self :: BEFORE_CONTENT]);
-          }
-
-          $expression =& new OutputExpression($match[self :: EXPRESSION]);
-          $expression->SourceLocation =& new WactSourceLocation(
-              $this->locator->getPublicId(),
-              $this->locator->getLineNumber());
-
-          $TreeBuilder->addNode($expression);
-
-          $text = $match[self :: AFTER_CONTENT];
-      }
-      if (strlen($text) > 0) {
-          $TreeBuilder->addTextNode($text);
-      }
-  }
-
-  /**
-  * Builds XML processing instructions and adds them to the component tree.
-  * PHP instructions are ignored.
-  * @param WactTreeBuilder
-  * @param string target processor
-  * @param string instruction
-  * @return void
-  * @access public
-  */
-  function addProcessingInstruction(&$TreeBuilder, $target, $instruction) {
-      // we can optimize here by not loading PHP node until we need it
-      // It will probably be rarely used in templates.
-      require_once WACT_ROOT . '/template/compiler/PHPNode.class.php';
-
-      // Pass through any PI's except PHP PI's
-      $php_targets = array('php','PHP','=','');
-      if(in_array($target, $php_targets))
-      {
-        $TreeBuilder->addNode(new PHPNode($instruction));
-      }
-      else
-      {
-        $php = 'echo "<?'.$target.' '; // Whitespace assumption
-        $php.= str_replace('"','\"',$instruction);
-        $php.= '?>\n";'; // Newline assumption
-        $TreeBuilder->addNode(new PHPNode($php));
-      }
-  }
-
-  /**
-  * Create a new tag component
-  * @param TagInfo
-  * @param string XML tag name of component
-  * @return void
-  * @access private
-  */
-  protected function _initTagNode(&$TagInfo, $tag) {
-      $class = $TagInfo->TagClass;
-      $component =& new $class();
-      $component->SourceLocation =& new WactSourceLocation(
-          $this->locator->getPublicId(),
-          $this->locator->getLineNumber());
-      $component->tag = $tag;
-      $component->TagInfo =& $TagInfo;
-      $dict = WactDictionaryHolder :: instance()->getPropertyDictionary();;
-      $properties = $dict->getPropertyList($tag);
-      foreach ($properties as $property) {
-          $property->load();
-          $PropertyClass = $property->PropertyClass;
-          $component->registerProperty(
-              $property->Property, new $PropertyClass($component));
-      }
-      return $component;
-  }
-
-  /**
-  * Create AttributeNodes or ArtributeVariableReferences to a component
-  * @param CompilerCOmponent
-  * @param array attributes found in tag
-  * @return void
-  * @access private
-  */
-  function addAttributesToComponent(&$component, $attrs) {
-      foreach ( $attrs as $name => $value ) {
-          // if there is no expression (common case), shortcut this process
-          if (strpos($value, '{$') === FALSE) {
-              $attribute =& new AttributeNode($name, $value);
-          } else {
-              if (preg_match($this->variableReferencePattern, $value, $match)) {
-                  if (strlen($match[self :: AFTER_CONTENT]) == 0 &&
-                      strlen($match[self :: BEFORE_CONTENT]) == 0) {
-                      $attribute =& new AttributeExpression(
-                          $name, $match[self :: EXPRESSION], $component);
-                  } else {
-                      $attribute =& $this->createCompoundAttribute(
-                          $component, $name, $value);
-                  }
-              } else {
-                  $attribute =& new AttributeNode($name, $value);
-              }
-          }
-
-          $component->addChildAttribute($attribute);
-      }
-  }
-
-  /**
-  * Creates a compound attribute
-  * @param CompilerComponent component to which the attribute belongs
-  * @param string name
-  * @param string value
-  * @return CompoundAttribute
-  * @access private
-  */
-  function &createCompoundAttribute(&$component, $name, $value) {
-      $attribute =& new CompoundAttribute($name);
-
-      while (preg_match($this->variableReferencePattern, $value, $match)) {
-          if (strlen($match[self :: BEFORE_CONTENT]) > 0) {
-              $attribute->addAttributeFragment(
-                  new AttributeNode($name, $match[self :: BEFORE_CONTENT]));
-          }
-
-          $attribute->addAttributeFragment(new AttributeExpression($name,
-              $match[self :: EXPRESSION], $component));
-
-          $value = $match[self :: AFTER_CONTENT];
-      }
-      if (strlen($value) > 0) {
-          $attribute->addAttributeFragment(new AttributeNode($name, $value));
-      }
-
-      return $attribute;
-  }
-}
-?>
\ No newline at end of file

Deleted: 3.x/packages/wact/trunk/framework/template/compiler/WactSourceLocation.class.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/WactSourceLocation.class.php	2006-10-16 06:38:46 UTC (rev 4161)
+++ 3.x/packages/wact/trunk/framework/template/compiler/WactSourceLocation.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -1,13 +0,0 @@
-<?php
-class WactSourceLocation
-{
-  public $file;
-  public $line;
-
-  function __construct($file, $line)
-  {
-    $this->file = $file;
-    $this->line = $line;
-  }
-}
-?>
\ No newline at end of file

Deleted: 3.x/packages/wact/trunk/framework/template/compiler/WactTreeBuilder.class.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/WactTreeBuilder.class.php	2006-10-16 06:38:46 UTC (rev 4161)
+++ 3.x/packages/wact/trunk/framework/template/compiler/WactTreeBuilder.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -1,242 +0,0 @@
-<?php
-/**
-* Acts on the ComponentTree in response to events within the SourceFileParser
-*
-* When adding an open tag to the tree, call pushExpectedTag().  When closing
-* a tag, call popExpectedTag(), which ensures the tree is balanced.
-*
-* These methods do not actually add nodes to the tree, as tags and nodes
-* do not necessarily match up.
-*
-* To add a node to the tree, you have the following choices.  To add a node
-* which can have children, use pushNode().  To add a terminal node use addNode(),
-* or addTextNode().
-*
-*/
-class WactTreeBuilder
-{
-    /**
-    * Current Component
-    * @var CompilerComponent
-    * @access private
-    */
-    var $component;
-
-    /**
-    * Used to locate position within document
-    * @access private
-    */
-    var $locator;
-
-    /**
-    * Stack of tags pushed onto the tree builder, may also contain components
-  * @see pushExpectedTag
-  * @see popExpectedTag
-  * @see pushCursor
-    * @var array of array($tagname, $info) or array($Component)
-    * @access private
-    */
-    var $expectedTags = array();
-
-    /**
-    * Sets the Document Locator
-    * @access public
-    */
-    function setDocumentLocator(&$locator) {
-        $this->locator =& $locator;
-    }
-
-    /**
-    * Returns the current component
-    * @return CompilerComponent
-    * @access public
-    */
-    function &getCursor() {
-        return $this->component;
-    }
-
-  /**
-  * Sets the cursor (the current working component) of the tree builder
-  * @param CompilerComponent
-  * @return void
-  * @access public
-  */
-    function setCursor(&$component) {
-        $this->component =& $component;
-    }
-
-  /**
-  * Begins a component's build phase in relation to the component tree.
-  * Adds a component to the tree, then makes that component the 'cursor'.
-  * Return the result of the component's preParse() method which is the
-  * parsing instruction PARSER_FORBID_PARSING or PARSER_REQUIRE_PARSING.
-  * @param CompilerComponent
-  * @return void
-  * @access public
-  */
-  function pushNode(&$newComponent)
-  {
-    $this->component->addChild($newComponent);
-    $this->setCursor($newComponent);
-
-    // scheduled for removal from component: taginfo to contain nesting level info
-    $this->component->CheckNestingLevel();
-
-    return $this->component->preParse($this);
-  }
-
-  /**
-  * Adds a component to the tree, without descending into it.
-  * This begins and finishes the component's composition
-  * @param CompilerComponent
-  * @return void
-  * @access public
-  */
-  function addNode(&$childComponent)
-  {
-    $childComponent->preParse($this);
-    $this->component->addChild($childComponent);
-  }
-
-  /**
-  * Helper method to add a TextNode, given plain text
-  * @param string text to create node for
-  * @return void
-  * @access public
-  */
-  function addTextNode($text)
-  {
-    $this->addNode(new TextNode($text));
-  }
-
-  /**
-  * Ends a component's build phase in relation to the tree.
-  * Checks child server ids and moves the 'cursor' up the tree to the parent
-  * component.
-  * @param boolean whether current component has a closing tag
-  * @return void
-  * @access public
-  */
-  function popNode($hasClosingTag)
-  {
-    $this->component->hasClosingTag = $hasClosingTag;
-    $this->checkServerIds();
-    $this->setCursor($this->component->parent);
-  }
-
-  /**
-  * Expects the passed tag.  Optionally $info may be passed which is info
-  * about that tag.  The parser state that calls TreeBuilder may use this info
-  * to differentiate, say, plain vs. component tags.
-  * @param string tag name
-  * @param mixed info about the tag
-  * @return void
-  * @access public
-  */
-  function pushExpectedTag($tag, $info = null, $position_info = array())
-  {
-    array_push($this->expectedTags, array($tag, $info, $position_info));
-  }
-
-  /**
-  * Sets the cursor to a new position, and pushes the old cursor onto the
-  * expected tags stack.
-  * @see popExpectedTag
-  * @param CompilerComponent
-  * @return void
-  * @access public
-  */
-  function pushCursor(&$newPosition)
-  {
-    // use of array() is to preserve reference from array_pop()
-    array_push($this->expectedTags, array(&$this->component));
-    $this->setCursor($newPosition);
-  }
-
-  /**
-  * Tests the passed tag against what is expected.  Returns any info that
-  * was kept about the expected tag.
-  * If the item in the tag stack is a component, then the cursor is
-  * restored to that, and popExpectedTag is called again.
-  * @param string tag name
-  * @return mixed info
-  * @access public
-  */
-  function popExpectedTag($tag, $position_info = array())
-  {
-    $expectedTagItem = array_pop($this->expectedTags);
-
-    // if we have a component on the stack, restore the cursor to that, and
-    // pop the stack again
-    if (is_object($expectedTagItem[0]))
-    {
-       $this->component =& $expectedTagItem[0];
-       return $this->popExpectedTag($tag, $position_info);
-    }
-
-    $expectedTag = $expectedTagItem[0];
-    $info = $expectedTagItem[1];
-
-    if (strcasecmp($expectedTag, $tag) !== 0)
-    {
-      if(isset($expectedTagItem[2]['line']))
-        $line = $expectedTagItem[2]['line'];
-      else
-        $line = '';
-
-      throw new WactException('compiler', 'UNEXPECTEDCLOSE', array('file' => $position_info['file'],
-                                                          'tag' => $tag,
-                                                          'line' => $position_info['line'],
-                                                          'ExpectTag' => $expectedTag,
-                                                          'ExpectedTagLine' => $line)
-                                                          );
-    }
-
-    return $info;
-  }
-
-  /**
-  * Return the size of the expected tags stack
-  * @return bool
-  * @access public
-  */
-  function getExpectedTagCount() {
-    return count($this->expectedTags);
-  }
-
-  /**
-  * Returns the current expected tag
-  * @return mixed string or false
-  * @access public
-  */
-  function getExpectedTag() {
-    // Returns the tagname of the first non-component item on the stack
-    $item = end($this->expectedTags);
-    while ($item && !is_string($item[0])) {
-      $item = prev($this->expectedTags);
-    }
-    return $item ? $item[0] : false;
-  }
-
-
-  /**
-  * Checks that each immediate child of the current component has a unique ID
-  * amongst its siblings.
-  * @see popNode
-  * @param object CompilerComponent
-  * @return void
-  */
-  function checkServerIds() {
-      $childServerIds = array();
-      $children = $this->component->getChildren();
-      foreach (array_keys($children) as $key) {
-          $id = $children[$key]->getServerId();
-          if (in_array($id, $childServerIds)) {
-              $children[$key]->raiseCompilerError('DUPLICATEID', $vars = array('ServerId' => $id));
-          } else {
-              $childServerIds[] = $id;
-      }
-      }
-  }
-}
-?>

Modified: 3.x/packages/wact/trunk/framework/template/compiler/filter/dictionary.inc.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/filter/dictionary.inc.php	2006-10-16 06:38:46 UTC (rev 4161)
+++ 3.x/packages/wact/trunk/framework/template/compiler/filter/dictionary.inc.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -8,8 +8,6 @@
 * @version $Id: dictionary.inc.php 2864 2006-02-28 10:20:41Z pachanga $
 */
 
-require_once WACT_ROOT . '/template/compiler/common/dictionary.inc.php';
-
 class FilterInfo
 {
   var $Name = 'capitalize';

Copied: 3.x/packages/wact/trunk/framework/template/compiler/parser/HTMLParser.class.php (from rev 4160, 3.x/packages/wact/trunk/framework/template/compiler/HTMLParser.class.php)
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/parser/HTMLParser.class.php	                        (rev 0)
+++ 3.x/packages/wact/trunk/framework/template/compiler/parser/HTMLParser.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -0,0 +1,380 @@
+<?php
+//--------------------------------------------------------------------------------
+// Copyright 2003 Procata, Inc.
+// Released under the LGPL license (http://www.gnu.org/copyleft/lesser.html)
+//--------------------------------------------------------------------------------
+
+/**
+* HTML/XHTML/XML parser
+* fast parser robustly handles malformed input.
+* All events are triggered by valid markup.
+* If markup is invalid, it is treated as data event.
+* @access protected
+* @abstract
+*/
+class HTMLParser
+{
+    var $publicId;
+    var $Observer;
+    /**
+    * XML document being parsed
+    * @var string
+    * @access private
+    */
+    var $rawtext;
+    /**
+    * Position in XML document relative to start (0)
+    * @var int
+    * @access private
+    */
+    var $position;
+    /**
+    * Length of the XML document in characters
+    * @var int
+    * @access private
+    */
+    var $length;
+
+    /**
+    * @var Observer event handler
+    * @access protected
+    */
+    function HTMLParser(&$Observer) {
+        $this->Observer =& $Observer;
+    }
+
+    /*
+    * Calculates the line number from the byte index
+    * @return int the current line number
+    * @access private
+    */
+    function getLineNumber() {
+        return 1 + substr_count(substr($this->rawtext, 0, $this->position), "\n");
+    }
+
+    function getPublicId() {
+        return $this->publicId;
+    }
+
+    /*
+    * Calculates the column number from the byte index
+    * @return int the current line number
+    * @access private
+    */
+    function getColumnNumber() {
+        // Not implemented yet.
+    }
+
+    /**
+    * Moves the position forward past any whitespace characters
+    * @access protected
+    * @return void
+    */
+    function ignoreWhitespace() {
+        while ($this->position < $this->length &&
+            strpos(" \n\r\t", $this->rawtext{$this->position}) !== FALSE) {
+            $this->position++;
+        }
+    }
+
+    /**
+    * Begins the parsing operation, setting up any decorators, depending on
+    * parse options invoking _parse() to execute parsing
+    * @param string XML document to parse
+    * @access protected
+    * @return void
+    */
+    function parse($data, $publicId = NULL) {
+        $this->rawtext = $data;
+        $this->length = strlen($data);
+        $this->position = 0;
+        $this->publicId = $publicId;
+
+        $this->Observer->setDocumentLocator($this);
+
+        do {
+            $start = $this->position;
+            $this->position = strpos($this->rawtext, '<', $start);
+            if ($this->position === FALSE) {
+                if ($start < $this->length) {
+                    $this->Observer->characters(substr($this->rawtext, $start));
+                }
+                return;
+            }
+
+            if ($this->position > $start) {
+                $this->Observer->characters(substr($this->rawtext, $start, $this->position - $start));
+            }
+
+            $this->position += 1;   // ignore '<' character
+            if ($this->position >= $this->length) {
+                $this->Observer->unexpectedEOF('<');
+                return;
+            }
+
+            $element_pos = $this->position;
+            $this->position += 1;
+
+            switch($this->rawtext{$element_pos}) {
+            case '/':
+                $start = $this->position;
+                while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
+                    $this->position++;
+                }
+                if ($this->position >= $this->length) {
+                    $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+                    return;
+                }
+
+                $tag = substr($this->rawtext, $start, $this->position - $start);
+
+                $this->Observer->endElement($tag);
+                $this->position += 1;   // ignore '>' string
+                break;
+            case '?':
+                $start = $this->position;
+                while ($this->position < $this->length && strpos(" \n\r\t", $this->rawtext{$this->position}) === FALSE) {
+                    $this->position++;
+                }
+                if ($this->position >= $this->length) {
+                    $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+                    return;
+                }
+
+                $target = substr($this->rawtext, $start, $this->position - $start);
+
+                $this->ignoreWhitespace();
+
+                $start = $this->position;
+                $this->position = strpos($this->rawtext, '?>', $start);
+                if ($this->position === FALSE) {
+                    $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+                    return;
+                }
+
+                $this->Observer->processingInstruction($target,
+                    substr($this->rawtext, $start, $this->position - $start));
+
+                $this->position += 2;   // ignore '? >' string
+                break;
+            case '%':
+                if ($this->position >= $this->length) {
+                    $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+                    return;
+                }
+
+                $start = $this->position;
+                $this->position = strpos($this->rawtext, '%>', $start);
+                if ($this->position === FALSE) {
+                    $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+                    return;
+                }
+
+                $this->Observer->jasp(substr($this->rawtext, $start, $this->position - $start));
+
+        /* changed to multi line comment per request on list
+        http://sourceforge.net/mailarchive/forum.php?thread_id=5925242&forum_id=35579
+        ignore '%>' string
+        */
+                $this->position += 2;
+                break;
+            case '!':
+                if ($this->position >= $this->length) {
+                    $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+                    return;
+                }
+
+                $start = $this->position;
+                if (substr($this->rawtext, $start, 2) == "--") {
+                    $this->position = strpos($this->rawtext, '-->', $start);
+                    if ($this->position === FALSE) {
+                        $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+                        return;
+                    }
+                    $this->Observer->comment(
+                        substr($this->rawtext, $start + 2, $this->position - $start - 2));
+                    $this->position += 3;
+                } else if (strcasecmp(substr($this->rawtext, $start, 7), 'DOCTYPE') == 0) {
+                    while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
+                        $this->position++;
+                    }
+                    if ($this->position >= $this->length) {
+                        $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+                        return;
+                    }
+                    $this->Observer->doctype(
+                        substr($this->rawtext, $start, $this->position - $start));
+                    $this->position += 1;
+                } else if (substr($this->rawtext, $start, 7) == '[CDATA[') {
+                    $this->position = strpos($this->rawtext, ']]>', $start + 7);
+                    if ($this->position === FALSE) {
+                        $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+                        return;
+                    }
+                    $this->Observer->cdata(
+                        substr($this->rawtext, $start + 7 , $this->position - $start - 7));
+                    $this->position += 3;
+                } else {
+                    while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
+                        $this->position++;
+                    }
+                    if ($this->position >= $this->length) {
+                        $this->Observer->unexpectedEOF(
+                            substr($this->rawtext, $element_pos - 1));
+                        return;
+                    }
+                    $this->position += 1;
+                    $this->Observer->escape(
+                        substr($this->rawtext, $start, $this->position - $start));
+                }
+                break;
+            default:
+                while ($this->position < $this->length && strpos("/> \n\r\t", $this->rawtext{$this->position}) === FALSE) {
+                    $this->position++;
+                }
+                if ($this->position >= $this->length) {
+                    $this->Observer->unexpectedEOF(
+                        substr($this->rawtext, $element_pos - 1));
+                    return;
+                }
+
+                $tag = substr($this->rawtext, $element_pos, $this->position - $element_pos);
+                $Attributes = array();
+
+                $this->ignoreWhitespace();
+
+                while ( $this->position < $this->length &&
+                        $this->rawtext{$this->position} != '/' &&
+                        $this->rawtext{$this->position} != '>') {
+
+                    $start = $this->position;
+                    while ($this->position < $this->length && strpos("/>= \n\r\t", $this->rawtext{$this->position}) === FALSE) {
+                        $this->position++;
+                    }
+                    if ($this->position >= $this->length) {
+                        $this->Observer->unexpectedEOF(
+                            substr($this->rawtext, $element_pos - 1));
+                        return;
+                    }
+
+                    $attributename = substr($this->rawtext, $start, $this->position - $start);
+                    $attributevalue = NULL;
+
+                    $this->ignoreWhitespace();
+                    if ($this->position >= $this->length) {
+                        $this->Observer->unexpectedEOF(
+                            substr($this->rawtext, $element_pos - 1));
+                        return;
+                    }
+
+                    if ( $this->rawtext{$this->position} == '=') {
+                        $this->position++;
+                        $this->ignoreWhitespace();
+                        if ($this->position >= $this->length) {
+                            $this->Observer->unexpectedEOF(
+                                substr($this->rawtext, $element_pos - 1));
+                            return;
+                        }
+
+                        $quote = $this->rawtext{$this->position};
+                        if ($quote == '"' || $quote == "'") {
+                            $start = $this->position + 1;
+                            $this->position = strpos($this->rawtext, $quote, $start);
+                            if ($this->position === FALSE) {
+                                $this->Observer->unexpectedEOF(
+                                    substr($this->rawtext, $element_pos - 1));
+                                return;
+                            }
+                            $attributevalue = substr($this->rawtext, $start, $this->position - $start);
+
+                            $this->position++;
+                            if ($this->position >= $this->length) {
+                                $this->Observer->unexpectedEOF(
+                                    substr($this->rawtext, $element_pos - 1));
+                                return;
+                            }
+
+                            if (strpos("/> \n\r\t", $this->rawtext{$this->position}) === FALSE) {
+                                $this->Observer->invalidAttributeSyntax();
+                            }
+
+                        } else {
+                            $start = $this->position;
+                            while ($this->position < $this->length && strpos("/> \n\r\t", $this->rawtext{$this->position}) === FALSE) {
+                                $this->position++;
+                            }
+                            if ($this->position >= $this->length) {
+                                $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+                                return;
+                            }
+                            $attributevalue = substr($this->rawtext, $start, $this->position - $start);
+                        }
+                    }
+
+                    $Attributes[$attributename] = $attributevalue;
+
+                    $this->ignoreWhitespace();
+                }
+
+                if ($this->position >= $this->length) {
+                    $this->Observer->unexpectedEOF(
+                        substr($this->rawtext, $element_pos - 1));
+                    return;
+                }
+
+                if ($this->rawtext{$this->position} == '/') {
+                    $this->position += 1;
+                    if ($this->position >= $this->length) {
+                        $this->Observer->unexpectedEOF(
+                            substr($this->rawtext, $element_pos - 1));
+                        return;
+                    }
+
+                    if ($this->rawtext{$this->position} != '>') {
+                        $start = $this->position;
+                        while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
+                            $this->position++;
+                        }
+                        if ($this->position >= $this->length) {
+                            $this->Observer->invalidEntitySyntax(
+                                substr($this->rawtext, $element_pos - 1));
+                            break;
+                        }
+
+                        $this->Observer->invalidEntitySyntax(
+                            substr($this->rawtext, $element_pos - 1, $this->position - $element_pos + 2));
+                        $this->position += 1;
+                        break;
+                    }
+
+                    $this->Observer->emptyElement($tag, $Attributes);
+                } else {
+                    $this->Observer->startElement($tag, $Attributes);
+                }
+                $this->position += 1;
+
+                /*
+                removed due to bug #1000806
+                see http://www.w3.org/TR/REC-html40/appendix/notes.html#notes-specifying-data
+                if (strcasecmp($tag, 'script') == 0 || strcasecmp($tag, 'style') == 0) {
+                    $start = $this->position;
+                    $this->position = strpos($this->rawtext, '</', $start);
+                    if ($this->position == FALSE) {
+                        $this->Observer->unexpectedEOF(
+                            substr($this->rawtext, $start));
+                        return;
+                    }
+
+                    $this->Observer->characters(
+                        substr($this->rawtext, $start, $this->position - $start));
+
+                }
+                */
+
+                break;
+            }
+        } while ($this->position < $this->length);
+    }
+
+}
+?>

Copied: 3.x/packages/wact/trunk/framework/template/compiler/parser/SourceFileParser.class.php (from rev 4161, 3.x/packages/wact/trunk/framework/template/compiler/SourceFileParser.class.php)
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/parser/SourceFileParser.class.php	                        (rev 0)
+++ 3.x/packages/wact/trunk/framework/template/compiler/parser/SourceFileParser.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -0,0 +1,315 @@
+<?php
+//--------------------------------------------------------------------------------
+// Copyright 2003 Procata, Inc.
+// Released under the LGPL license (http://www.gnu.org/copyleft/lesser.html)
+//--------------------------------------------------------------------------------
+/**
+* @package WACT_TEMPLATE
+* @version $Id: SourceFileParser.class.php,v 1.114 2006/01/04 04:57:05 ian_w_white Exp $
+*/
+//--------------------------------------------------------------------------------
+/**
+* Define compile component states which determine parse behaviour
+*/
+define('PARSER_REQUIRE_PARSING', TRUE);
+define('PARSER_FORBID_PARSING', FALSE);
+define('PARSER_ALLOW_PARSING', NULL);
+
+//--------------------------------------------------------------------------------
+/**
+* Includes
+*/
+require_once WACT_ROOT . '/template/compiler/parser/WactNodeBuilder.class.php';
+require_once WACT_ROOT . '/template/compiler/parser/WactTreeBuilder.class.php';
+require_once WACT_ROOT . '/template/compiler/parser/WactLiteralParsingState.class.php';
+require_once WACT_ROOT . '/template/compiler/parser/WactComponentParsingState.class.php';
+require_once WACT_ROOT . '/template/compiler/parser/HtmlParser.class.php';
+
+//--------------------------------------------------------------------------------
+/**
+* The source template parser is the core of the WACT template engine
+* @see http://wact.sourceforge.net/index.php/SourceFileParser
+* @access public
+* @package WACT_TEMPLATE
+*/
+class SourceFileParser implements ParserListener
+{
+  /**
+  * Path and filename of source template
+  * @var string
+  * @access private
+  */
+  var $SourceFile;
+  /**
+  * Initial instance of WactComponentParsingState
+  * @var WactComponentParsingState
+  * @access private
+  */
+  var $ComponentParsingState;
+  /**
+  * Initial instance of WactLiteralParsingState
+  * @var WactLiteralParsingState
+  * @access private
+  */
+  var $LiteralParsingState;
+  /**
+  * The current active state
+  * @var WactBaseParsingState subclass
+  * @access public
+  */
+  var $State;
+
+  protected $config;
+
+  /**
+   * Template locator
+   * @var WactLocator
+   */
+  protected $locator;
+
+  function __construct($sourcefile, $TreeBuilder, $config, $locator)
+  {
+    $this->SourceFile = $sourcefile;
+    $this->TreeBuilder = $TreeBuilder;
+    $this->config = $config;
+    $this->locator = $locator;
+  }
+
+  function getSourceFile()
+  {
+    return $this->SourceFile;
+  }
+
+  /**
+  * Creates Build a filter chain
+  * @return HTMLParser
+  * @access protected
+  */
+  function &buildFilterChain($saxfilters) {
+      $Chain =& $this;
+
+      // Build a filter chain
+      if ( !empty($saxfilters) ) {
+          foreach (explode(':', $saxfilters) as $saxfilter) {
+              $saxfilterfile = strtolower($saxfilter).'saxfilter.inc.php';
+              $saxfilterclass = $saxfilter . 'SaxFilter';
+              if ( !include_once WACT_ROOT . '/template/compiler/saxfilters/'.$saxfilterfile ) {
+                  throw new WactException('compiler', 'SAXFILTER_NOTFOUND', array(
+                      'path' => WACT_ROOT . '/template/compiler/saxfilters/'.$saxfilterfile,
+                      'name' => ucfirst($saxfilter)));
+              } else {
+                  $NewFilter =& new $saxfilterclass();
+                  $NewFilter->setChildSaxFilter($Chain);
+                  $Chain =& $NewFilter;
+              }
+          }
+      }
+
+      return $Chain;
+  }
+
+  /**
+  * Used to parse the source template.
+  * Initially invoked by the CompileTemplate function,
+  * the first component argument being a ComponentTree.
+  * Uses the TagDictionary to spot compiler components
+  * @see CompileTemplate
+  * @see ComponentTree
+  * @param object compile time component
+  * @return void
+  * @access protected
+  */
+  function parse($ComponentRoot)
+  {
+    $TagDictionary = WactDictionaryHolder ::instance()->getTagDictionary();
+
+    $NodeBuilder =& new WactNodeBuilder();
+
+    $tagCountBeforeParse = $this->TreeBuilder->getExpectedTagCount();
+
+    $this->TreeBuilder->setCursor($ComponentRoot);
+
+    $this->ComponentParsingState = new WactComponentParsingState($this, $this->TreeBuilder, $NodeBuilder, $TagDictionary);
+    $this->LiteralParsingState = new WactLiteralParsingState($this, $this->TreeBuilder);
+    $this->changeToComponentParsingState();
+
+    $Chain =& $this->buildFilterChain($this->config->getSaxFilters());
+    $parser = new HTMLParser($Chain);
+    $template = $this->locator->readTemplateFile($this->SourceFile);
+    $parser->parse($template, $this->SourceFile);
+
+    if ($tagCountBeforeParse != $this->TreeBuilder->getExpectedTagCount()) {
+        throw new WactException('compiler', 'MISSINGCLOSE', array(
+        'tag' => $this->TreeBuilder->getExpectedTag(),
+          'file' => $ComponentRoot->SourceLocation->file,
+          'line' => $ComponentRoot->SourceLocation->line));
+    }
+  }
+
+
+  /**
+  * Switch to component parsing state
+  * @return void
+  * @access public
+  */
+  function changeToComponentParsingState() {
+      $this->State = $this->ComponentParsingState;
+  }
+
+  /**
+  * Switch to literal parsing state
+  * @param string tag name marking the literal component
+  * @return void
+  * @access public
+  */
+  function changeToLiteralParsingState($tag) {
+      $this->State = $this->LiteralParsingState;
+      $this->State->setLiteralTag($tag);
+  }
+
+  /**
+  * Document Locator Handler
+  * @param Locator
+  * @return void
+  * @access private
+  */
+  function setDocumentLocator($locator) {
+      $this->LiteralParsingState->setDocumentLocator($locator);
+      $this->ComponentParsingState->setDocumentLocator($locator);
+  }
+
+  /**
+  * Sax Open Handler
+  * @param string tag name
+  * @param array attributes
+  * @return void
+  * @access private
+  */
+  function startElement($tag, $attrs) {
+      $this->State->startElement($tag, $attrs);
+  }
+
+  /**
+  * Sax Close Handler
+  * @param string tag name
+  * @return void
+  * @access private
+  */
+  function endElement($tag) {
+      $this->State->endElement($tag);
+  }
+
+  /**
+  * Sax Open Handler
+  * @param string tag name
+  * @param array attributes
+  * @return void
+  * @access private
+  */
+  function emptyElement($tag, $attrs) {
+      $this->State->emptyElement($tag, $attrs);
+  }
+
+  /**
+  * Sax Data Handler
+  * @param string text content in tag
+  * @return void
+  * @access private
+  */
+  function characters($text) {
+      $this->State->characters($text);
+  }
+
+  /**
+  * Sax CDATA Handler
+  * @param string text content in tag
+  * @return void
+  * @access private
+  */
+  function cdata($text) {
+      $this->State->cdata($text);
+  }
+
+  /**
+  * Sax Processing Instruction Handler
+  * @param string target processor (e.g. php)
+  * @param string text content in PI
+  * @return void
+  * @access private
+  */
+  function processingInstruction($target, $instruction) {
+      $this->State->processingInstruction($target, $instruction);
+  }
+
+  /**
+  * Sax XML Escape Handler
+  * @param string text content in escape
+  * @return void
+  * @access private
+  */
+  function escape($text) {
+      $this->State->escape($text);
+  }
+
+  /**
+  * Sax XML Comment Handler
+  * @param string text content in comment
+  * @return void
+  * @access private
+  */
+  function comment($text) {
+      $this->State->comment($text);
+  }
+
+  /**
+  * Sax XML doctype Handler
+  * @param string text content in doctype
+  * @return void
+  * @access private
+  */
+  function doctype($text) {
+      $this->State->doctype($text);
+  }
+
+  /**
+  * Sax JSP / ASP markup Handler
+  * @param string text content in JASP tags
+  * @return void
+  * @access private
+  */
+  function jasp($text) {
+      $this->State->jasp($text);
+  }
+
+  /**
+  * Sax EOF Handler
+  * @param string text content in tag
+  * @return void
+  * @access private
+  */
+  function unexpectedEOF($text) {
+      $this->State->unexpectedEOF($text);
+  }
+
+  /**
+  * Sax Entity syntax Error Handler
+  * @param string text content in tag
+  * @return void
+  * @access private
+  */
+  function invalidEntitySyntax($text) {
+      $this->State->invalidEntitySyntax($text);
+  }
+
+  /**
+  * Sax Attribute syntax Error Handler
+  * @param string text content in tag
+  * @return void
+  * @access private
+  */
+  function invalidAttributeSyntax() {
+      $this->State->invalidAttributeSyntax();
+  }
+}
+
+?>

Copied: 3.x/packages/wact/trunk/framework/template/compiler/parser/WactBaseParsingState.class.php (from rev 4161, 3.x/packages/wact/trunk/framework/template/compiler/WactBaseParsingState.class.php)
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/parser/WactBaseParsingState.class.php	                        (rev 0)
+++ 3.x/packages/wact/trunk/framework/template/compiler/parser/WactBaseParsingState.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -0,0 +1,65 @@
+<?php
+/**
+* Base state handler for the SourceFileParser. Handles plain text
+*/
+abstract class WactBaseParsingState
+{
+  /**
+  * Instance of SourceFileParser
+  * @var SourceFileParser
+  * @access private
+  */
+  var $Parser;
+
+  /**
+  * Used to locate position within document
+  * @access private
+  */
+  var $Locator;
+
+  /**
+  * Instance of WactTreeBuilder
+  * @var WactTreeBuilder
+  * @access private
+  */
+  var $TreeBuilder;
+
+  function __construct($Parser, $TreeBuilder)
+  {
+    $this->Parser = $Parser;
+    $this->TreeBuilder = $TreeBuilder;
+  }
+
+  function setDocumentLocator($locator)
+  {
+    $this->Locator = $locator;
+    $this->TreeBuilder->setDocumentLocator($locator);
+  }
+
+  function getAttributeString($attrs)
+  {
+      $attrib_str = '';
+      foreach ( $attrs as $key => $value ) {
+          $attrib_str .= ' ' . $key;
+          if (!is_null($value)) {
+              if (strpos($value, '"') === FALSE) {
+                  $attrib_str .= '="' . $value . '"';
+              } else {
+                  $attrib_str .= '=\'' . $value . '\'';
+              }
+          }
+      }
+      return $attrib_str;
+  }
+
+  /**
+  * Attribute syntax Error Handler
+  */
+  function invalidAttributeSyntax()
+  {
+    throw new WactException('compiler', 'INVALID_ATTRIBUTE_SYNTAX', array(
+        'file' => $this->Locator->getPublicId(),
+        'line' => $this->Locator->getLineNumber()));
+  }
+}
+?>
\ No newline at end of file

Copied: 3.x/packages/wact/trunk/framework/template/compiler/parser/WactComponentParsingState.class.php (from rev 4161, 3.x/packages/wact/trunk/framework/template/compiler/WactComponentParsingState.class.php)
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/parser/WactComponentParsingState.class.php	                        (rev 0)
+++ 3.x/packages/wact/trunk/framework/template/compiler/parser/WactComponentParsingState.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -0,0 +1,278 @@
+<?php
+require_once(WACT_ROOT . '/template/compiler/parser/ParserListener.interface.php');
+require_once(WACT_ROOT . '/template/compiler/parser/WactBaseParsingState.class.php');
+
+define ('PARSER_TAG_IS_COMPONENT', 	1);
+define ('PARSER_TAG_IS_PLAIN', 		2);
+
+class WactComponentParsingState extends WactBaseParsingState implements ParserListener
+{
+    /**
+    * Instance of TagDictionary
+    * @var TagDictionary
+    * @access private
+    */
+    var $TagDictionary;
+
+    /**
+    * Instance of Node Builder
+    * @access private
+    */
+    var $NodeBuilder;
+
+    /**
+    * @param SourceFileParser
+    * @access public
+    */
+    function __construct($Parser, $TreeBuilder, $NodeBuilder, $TagDictionary)
+    {
+      parent :: __construct($Parser, $TreeBuilder);
+      $this->TagDictionary = $TagDictionary;
+      $this->NodeBuilder = $NodeBuilder;
+    }
+
+    /**
+    * @param Locator
+    * @access protected
+    */
+    function setDocumentLocator($locator)
+    {
+      parent::setDocumentLocator($locator);
+
+      $this->NodeBuilder->setDocumentLocator($locator);
+    }
+
+    /**
+  * Builds an attribute string based on passed array of attributes
+  * @param array
+  * @return string
+  * @access protected
+  */
+    function getAttributeString($attrs) {
+        $attrib_str = '';
+        foreach ( $attrs as $key => $value ) {
+            if (strcasecmp($key, PARSER_TRIGGER_ATTR_NAME) == 0 ) {
+                continue;
+            }
+
+            $attrib_str .= ' ' . $key;
+            if (!is_null($value)) {
+                if (strpos($value, '"') === FALSE) {
+                    $attrib_str .= '="' . $value . '"';
+                } else {
+                    $attrib_str .= '=\'' . $value . '\'';
+                }
+            }
+        }
+        return $attrib_str;
+    }
+
+    /**
+    * Handle opening tags
+    * @param string tag name
+    * @param array tag attributes
+    * @access public
+    */
+    function startElement($tag, $attrs)
+    {
+      $lower_attributes = $this->checkAttributes($attrs);
+
+      $TagInfo =& $this->TagDictionary->findComponent($tag, $lower_attributes, FALSE, $this->TreeBuilder->getCursor());
+
+      if (is_object($TagInfo))
+      {
+        $TagInfo->load();
+
+        // If a closing tag not forbidden then expect a closing tag
+        if ( $TagInfo->EndTag != ENDTAG_FORBIDDEN )
+          $this->TreeBuilder->pushExpectedTag($tag, PARSER_TAG_IS_COMPONENT, $this->_getPositionInfo());
+
+        $component =& $this->NodeBuilder->buildTagNode($TagInfo, $tag, $attrs, FALSE);
+        if ( $this->TreeBuilder->pushNode($component) == PARSER_FORBID_PARSING)
+          $this->Parser->changeToLiteralParsingState($tag);
+
+        // Cleanup for components that have no closing tag
+        if ( $TagInfo->EndTag == ENDTAG_FORBIDDEN )
+        {
+          $this->TreeBuilder->popNode(FALSE);
+          $this->Parser->changeToComponentParsingState();
+        }
+      }
+      else
+      {
+        $this->TreeBuilder->pushExpectedTag($tag, PARSER_TAG_IS_PLAIN, $this->_getPositionInfo());
+        $this->NodeBuilder->addContent($this->TreeBuilder, '<' . $tag . $this->getAttributeString($attrs) . '>');
+      }
+    }
+
+    /**
+    * Handle closing tags
+    * @param string tag name
+    * @access public
+    */
+    function endElement($tag)
+    {
+      $TagInfo =& $this->TagDictionary->getTagInfo($tag);
+      if (is_object($TagInfo))
+      {
+        if ($TagInfo->EndTag == ENDTAG_FORBIDDEN)
+        {
+              throw new WactException('compiler', 'UNEXPECTEDCLOSE2', array(
+                  'tag' => $TagInfo->Tag,
+                  'file' => $this->Locator->getPublicId(),
+                  'line' => $this->Locator->getLineNumber()));
+        }
+      }
+
+      if ($this->TreeBuilder->popExpectedTag($tag, $this->_getPositionInfo()) == PARSER_TAG_IS_COMPONENT)
+        $this->TreeBuilder->popNode(TRUE);
+      else
+        $this->TreeBuilder->addTextNode('</' . $tag .'>');
+    }
+
+    function _getPositionInfo()
+    {
+      return array('line' => $this->Locator->getLineNumber(),
+                   'file' => $this->Parser->getSourceFile());
+    }
+
+    /**
+    * Handle empty tags
+    * @param string tag name
+    * @param array tag attributes
+    * @access public
+    */
+    function emptyElement($tag, $attrs)
+    {
+      $lower_attributes = $this->checkAttributes($attrs);
+
+        $TagInfo =& $this->TagDictionary->findComponent($tag, $lower_attributes, TRUE, $this->TreeBuilder->getCursor());
+        if (is_object($TagInfo)) {
+            $TagInfo->load();
+
+            $component =& $this->NodeBuilder->buildTagNode($TagInfo, $tag, $attrs, TRUE);
+            if ( $this->TreeBuilder->pushNode($component) == PARSER_FORBID_PARSING) {
+                $this->Parser->changeToLiteralParsingState($tag);
+      }
+
+      // Cleanup for components that have no closing tag
+            if ( $TagInfo->EndTag == ENDTAG_FORBIDDEN ) {
+                $this->Parser->changeToComponentParsingState();
+                $this->TreeBuilder->popNode(FALSE);
+            } else {
+                $this->TreeBuilder->popNode(TRUE);
+            }
+
+        } else {
+            $this->NodeBuilder->addContent($this->TreeBuilder,
+                '<' . $tag . $this->getAttributeString($attrs) . ' />');
+    }
+    }
+
+  /**
+  * Transforms attributes so keys are lowercase, and checks for
+  * illegal DBEs
+  * @param array
+  * @return array
+  * @access protected
+  */
+  function checkAttributes($attrs) {
+    $lower_attributes = array_change_key_case($attrs, CASE_LOWER);
+        if ( isset($lower_attributes[PARSER_TRIGGER_ATTR_NAME]) &&
+                strpos($lower_attributes[PARSER_TRIGGER_ATTR_NAME], '{$') !== FALSE) {
+            throw new WactException('compiler', 'ILLEGALVARREFINATTR', array(
+                'attribute' => $lower_attributes[PARSER_TRIGGER_ATTR_NAME],
+                'file' => $this->Locator->getPublicId(),
+                'line' => $this->Locator->getLineNumber()));
+        }
+    return $lower_attributes;
+  }
+
+    /**
+    * Handle tag content
+    * @param string tag content
+    * @access public
+    */
+    function characters($text) {
+        $this->NodeBuilder->addContent($this->TreeBuilder, $text);
+    }
+
+    /**
+    * Handle tag content
+    * @param string tag content
+    * @access public
+    */
+    function cdata($text) {
+        $this->NodeBuilder->addContent($this->TreeBuilder, '<![CDATA[' . $text . ']]>');
+    }
+
+    /**
+    * Handle processing instructions
+    * @param string target processor
+    * @param string instruction
+    * @access public
+    */
+    function processingInstruction($target, $instruction) {
+        $this->NodeBuilder->addProcessingInstruction($this->TreeBuilder, $target, $instruction);
+    }
+
+    /**
+    * Handle JSP / ASP markup
+    * @param string content
+    * @access public
+    */
+    function jasp($text) {
+        // Name of method is not good in this case
+        $this->NodeBuilder->addContent($this->TreeBuilder, '<%' . $text . '%>');
+    }
+
+    /**
+    * Handle XML escape sequences
+    * @param string content of escape
+    * @access public
+    */
+    function escape($text) {
+        $this->NodeBuilder->addContent($this->TreeBuilder, '<!' . $text . '>');
+    }
+
+    /**
+    * Handle doctype
+    * @param string content of doctype
+    * @access public
+    */
+    function doctype($text) {
+        $this->NodeBuilder->addContent($this->TreeBuilder, '<!' . $text . '>');
+    }
+
+    /**
+    * Handle XML comments
+    * @param string content of comment
+    * @access public
+    */
+    function comment($text) {
+        // Name of method is not good in this case
+        $this->NodeBuilder->addContent($this->TreeBuilder, '<!--' . $text . '-->');
+    }
+
+    /**
+    * Handle EOF Error
+    * @param string tag content
+    * @access public
+    */
+    function unexpectedEOF($text) {
+        // Ignore the error and treat the rest of the file like data
+        $this->NodeBuilder->addContent($this->TreeBuilder, $text);
+    }
+
+    /**
+    * Entity syntax Error Handler
+    * @param string tag content
+    * @access public
+    */
+    function invalidEntitySyntax($text) {
+        // Ignore the error and treat the rest of the file like data
+        $this->NodeBuilder->addContent($this->TreeBuilder, $text);
+    }
+
+}
+?>
\ No newline at end of file

Copied: 3.x/packages/wact/trunk/framework/template/compiler/parser/WactLiteralParsingState.class.php (from rev 4161, 3.x/packages/wact/trunk/framework/template/compiler/WactLiteralParsingState.class.php)
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/parser/WactLiteralParsingState.class.php	                        (rev 0)
+++ 3.x/packages/wact/trunk/framework/template/compiler/parser/WactLiteralParsingState.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -0,0 +1,88 @@
+<?php
+require_once(WACT_ROOT . '/template/compiler/parser/ParserListener.interface.php');
+require_once(WACT_ROOT . '/template/compiler/parser/WactBaseParsingState.class.php');
+
+class WactLiteralParsingState extends WactBaseParsingState  implements ParserListener
+{
+  protected $literal_tag;
+
+  function setLiteralTag($tag)
+  {
+    $this->literal_tag = $tag;
+  }
+
+  function getLiteralTag()
+  {
+    return $this->literal_tag;
+  }
+
+  function startElement($tag, $attrs)
+  {
+    $this->TreeBuilder->addTextNode('<' . $tag . $this->getAttributeString($attrs) . '>');
+  }
+
+  function endElement($tag)
+  {
+    if ($this->literal_tag == $tag)
+    {
+      $this->TreeBuilder->popExpectedTag($tag);
+      $this->TreeBuilder->popNode(TRUE);
+      $this->Parser->changeToComponentParsingState();
+    }
+    else
+      $this->TreeBuilder->addTextNode('</' . $tag . '>');
+  }
+
+  function emptyElement($tag, $attrs)
+  {
+      $this->TreeBuilder->addTextNode('<' . $tag . $this->getAttributeString($attrs) . ' />');
+  }
+
+  function characters($text)
+  {
+    $this->TreeBuilder->addTextNode($text);
+  }
+
+  function cdata($text)
+  {
+    $this->TreeBuilder->addTextNode('<![CDATA[' . $text . ']]>');
+  }
+
+  function processingInstruction($target, $instruction)
+  {
+    $this->TreeBuilder->addTextNode('<?' . $target . ' ' . $instruction . '?>');
+  }
+
+  function jasp($text)
+  {
+    $this->TreeBuilder->addTextNode('<%' .  $text . '%>');
+  }
+
+  function escape($text)
+  {
+    $this->TreeBuilder->addTextNode('<!' . $text . '>');
+  }
+
+  function comment($text)
+  {
+    $this->TreeBuilder->addTextNode('<!--' . $text . '-->');
+  }
+
+  function doctype($text)
+  {
+    $this->TreeBuilder->addTextNode('<!' . $text . '>');
+  }
+
+  function unexpectedEOF($text)
+  {
+    // Ignore the error and treat the rest of the file like data
+    $this->TreeBuilder->addTextNode($text);
+  }
+
+  function invalidEntitySyntax($text)
+  {
+    // Ignore the error and treat the rest of the file like data
+    $this->TreeBuilder->addTextNode($text);
+  }
+}
+?>
\ No newline at end of file

Copied: 3.x/packages/wact/trunk/framework/template/compiler/parser/WactNodeBuilder.class.php (from rev 4160, 3.x/packages/wact/trunk/framework/template/compiler/WactNodeBuilder.class.php)
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/parser/WactNodeBuilder.class.php	                        (rev 0)
+++ 3.x/packages/wact/trunk/framework/template/compiler/parser/WactNodeBuilder.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -0,0 +1,220 @@
+<?php
+/**
+* Responsible for building nodes of the component tree.
+* WactTreeBuilder is responsible for the tree structure.
+*/
+class WactNodeBuilder
+{
+  const BEFORE_CONTENT = 1;
+  const EXPRESSION = 2;
+  const AFTER_CONTENT = 5;
+
+  protected $variable_reference_pattern;
+
+  var $locator;
+
+  function __construct()
+  {
+    $this->variableReferencePattern =
+      // start at the beginning
+      '/^' .
+      // Pick up the portion of the string before the variable reference
+      '((?s).*?)' .
+      // Beginning of a variable reference
+      preg_quote('{$', '/') .
+      // Collect the entire variable reference into one subexpression
+      '(' .
+          // capture the contents of one or more fragments.
+          '(' .
+              // Anything thats not a quote or the end of the variable
+              // reference can be in a fragment
+              '[^"\'}]+' .
+              // OR
+              '|' .
+              // A string inside quotes is also a fragment
+              '(\'|").*?\4' .
+          ')+' .
+      ')' .
+      // end of a variable reference
+      preg_quote('}', '/') .
+      // Pick up the portion of the string after the variable reference
+      // This portion may contain additional references; we only match
+      // one at a time.
+      '((?s).*)' .
+      // Match until the end of the string
+      '$/';
+  }
+
+  function setDocumentLocator($locator)
+  {
+    $this->locator = $locator;
+  }
+
+  /**
+  * Builds a component, adding attributes
+  * @param TagInfo
+  * @param string XML tag name of component
+  * @param array attributes for tag
+  * @param boolean whether the tag has contents
+  * @return CompilerComponent
+  * @access public
+  */
+  function buildTagNode($TagInfo, $tag, $attrs, $isEmpty)
+  {
+    $component = $this->_initTagNode($TagInfo, $tag);
+    $component->emptyClosedTag = $isEmpty;
+    $this->addAttributesToComponent($component, $attrs);
+    return $component;
+  }
+
+  /**
+  * Builds content node(s), adding it (them) to the component tree.
+  * A single piece of content may actually be a mix of terminal nodes
+  * (TextNodes and Expressions)
+  * @param WactTreeBuilder
+  * @param string content of tag
+  * @return void
+  * @access public
+  */
+  function addContent(&$TreeBuilder, $text) {
+      // if there is no expression (common case), shortcut this process
+      if (strpos($text, '{$') === FALSE) {
+          $TreeBuilder->addTextNode($text);
+          return;
+      }
+
+      while (preg_match($this->variableReferencePattern, $text, $match)) {
+          if (strlen($match[self :: BEFORE_CONTENT]) > 0) {
+              $TreeBuilder->addTextNode($match[self :: BEFORE_CONTENT]);
+          }
+
+          $expression =& new OutputExpression($match[self :: EXPRESSION]);
+          $expression->SourceLocation =& new WactSourceLocation(
+              $this->locator->getPublicId(),
+              $this->locator->getLineNumber());
+
+          $TreeBuilder->addNode($expression);
+
+          $text = $match[self :: AFTER_CONTENT];
+      }
+      if (strlen($text) > 0) {
+          $TreeBuilder->addTextNode($text);
+      }
+  }
+
+  /**
+  * Builds XML processing instructions and adds them to the component tree.
+  * PHP instructions are ignored.
+  * @param WactTreeBuilder
+  * @param string target processor
+  * @param string instruction
+  * @return void
+  * @access public
+  */
+  function addProcessingInstruction(&$TreeBuilder, $target, $instruction) {
+      // we can optimize here by not loading PHP node until we need it
+      // It will probably be rarely used in templates.
+      require_once WACT_ROOT . '/template/compiler/PHPNode.class.php';
+
+      // Pass through any PI's except PHP PI's
+      $php_targets = array('php','PHP','=','');
+      if(in_array($target, $php_targets))
+      {
+        $TreeBuilder->addNode(new PHPNode($instruction));
+      }
+      else
+      {
+        $php = 'echo "<?'.$target.' '; // Whitespace assumption
+        $php.= str_replace('"','\"',$instruction);
+        $php.= '?>\n";'; // Newline assumption
+        $TreeBuilder->addNode(new PHPNode($php));
+      }
+  }
+
+  /**
+  * Create a new tag component
+  * @param TagInfo
+  * @param string XML tag name of component
+  * @return void
+  * @access private
+  */
+  protected function _initTagNode(&$TagInfo, $tag) {
+      $class = $TagInfo->TagClass;
+      $component =& new $class();
+      $component->SourceLocation =& new WactSourceLocation(
+          $this->locator->getPublicId(),
+          $this->locator->getLineNumber());
+      $component->tag = $tag;
+      $component->TagInfo =& $TagInfo;
+      $dict = WactDictionaryHolder :: instance()->getPropertyDictionary();;
+      $properties = $dict->getPropertyList($tag);
+      foreach ($properties as $property) {
+          $property->load();
+          $PropertyClass = $property->PropertyClass;
+          $component->registerProperty(
+              $property->Property, new $PropertyClass($component));
+      }
+      return $component;
+  }
+
+  /**
+  * Create AttributeNodes or ArtributeVariableReferences to a component
+  * @param CompilerCOmponent
+  * @param array attributes found in tag
+  * @return void
+  * @access private
+  */
+  function addAttributesToComponent(&$component, $attrs) {
+      foreach ( $attrs as $name => $value ) {
+          // if there is no expression (common case), shortcut this process
+          if (strpos($value, '{$') === FALSE) {
+              $attribute =& new AttributeNode($name, $value);
+          } else {
+              if (preg_match($this->variableReferencePattern, $value, $match)) {
+                  if (strlen($match[self :: AFTER_CONTENT]) == 0 &&
+                      strlen($match[self :: BEFORE_CONTENT]) == 0) {
+                      $attribute =& new AttributeExpression(
+                          $name, $match[self :: EXPRESSION], $component);
+                  } else {
+                      $attribute =& $this->createCompoundAttribute(
+                          $component, $name, $value);
+                  }
+              } else {
+                  $attribute =& new AttributeNode($name, $value);
+              }
+          }
+
+          $component->addChildAttribute($attribute);
+      }
+  }
+
+  /**
+  * Creates a compound attribute
+  * @param CompilerComponent component to which the attribute belongs
+  * @param string name
+  * @param string value
+  * @return CompoundAttribute
+  * @access private
+  */
+  function &createCompoundAttribute(&$component, $name, $value) {
+      $attribute =& new CompoundAttribute($name);
+
+      while (preg_match($this->variableReferencePattern, $value, $match)) {
+          if (strlen($match[self :: BEFORE_CONTENT]) > 0) {
+              $attribute->addAttributeFragment(
+                  new AttributeNode($name, $match[self :: BEFORE_CONTENT]));
+          }
+
+          $attribute->addAttributeFragment(new AttributeExpression($name,
+              $match[self :: EXPRESSION], $component));
+
+          $value = $match[self :: AFTER_CONTENT];
+      }
+      if (strlen($value) > 0) {
+          $attribute->addAttributeFragment(new AttributeNode($name, $value));
+      }
+
+      return $attribute;
+  }
+}
+?>
\ No newline at end of file

Copied: 3.x/packages/wact/trunk/framework/template/compiler/parser/WactSourceLocation.class.php (from rev 4160, 3.x/packages/wact/trunk/framework/template/compiler/WactSourceLocation.class.php)
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/parser/WactSourceLocation.class.php	                        (rev 0)
+++ 3.x/packages/wact/trunk/framework/template/compiler/parser/WactSourceLocation.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -0,0 +1,13 @@
+<?php
+class WactSourceLocation
+{
+  public $file;
+  public $line;
+
+  function __construct($file, $line)
+  {
+    $this->file = $file;
+    $this->line = $line;
+  }
+}
+?>
\ No newline at end of file

Copied: 3.x/packages/wact/trunk/framework/template/compiler/parser/WactTreeBuilder.class.php (from rev 4160, 3.x/packages/wact/trunk/framework/template/compiler/WactTreeBuilder.class.php)
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/parser/WactTreeBuilder.class.php	                        (rev 0)
+++ 3.x/packages/wact/trunk/framework/template/compiler/parser/WactTreeBuilder.class.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -0,0 +1,242 @@
+<?php
+/**
+* Acts on the ComponentTree in response to events within the SourceFileParser
+*
+* When adding an open tag to the tree, call pushExpectedTag().  When closing
+* a tag, call popExpectedTag(), which ensures the tree is balanced.
+*
+* These methods do not actually add nodes to the tree, as tags and nodes
+* do not necessarily match up.
+*
+* To add a node to the tree, you have the following choices.  To add a node
+* which can have children, use pushNode().  To add a terminal node use addNode(),
+* or addTextNode().
+*
+*/
+class WactTreeBuilder
+{
+    /**
+    * Current Component
+    * @var CompilerComponent
+    * @access private
+    */
+    var $component;
+
+    /**
+    * Used to locate position within document
+    * @access private
+    */
+    var $locator;
+
+    /**
+    * Stack of tags pushed onto the tree builder, may also contain components
+  * @see pushExpectedTag
+  * @see popExpectedTag
+  * @see pushCursor
+    * @var array of array($tagname, $info) or array($Component)
+    * @access private
+    */
+    var $expectedTags = array();
+
+    /**
+    * Sets the Document Locator
+    * @access public
+    */
+    function setDocumentLocator(&$locator) {
+        $this->locator =& $locator;
+    }
+
+    /**
+    * Returns the current component
+    * @return CompilerComponent
+    * @access public
+    */
+    function &getCursor() {
+        return $this->component;
+    }
+
+  /**
+  * Sets the cursor (the current working component) of the tree builder
+  * @param CompilerComponent
+  * @return void
+  * @access public
+  */
+    function setCursor(&$component) {
+        $this->component =& $component;
+    }
+
+  /**
+  * Begins a component's build phase in relation to the component tree.
+  * Adds a component to the tree, then makes that component the 'cursor'.
+  * Return the result of the component's preParse() method which is the
+  * parsing instruction PARSER_FORBID_PARSING or PARSER_REQUIRE_PARSING.
+  * @param CompilerComponent
+  * @return void
+  * @access public
+  */
+  function pushNode(&$newComponent)
+  {
+    $this->component->addChild($newComponent);
+    $this->setCursor($newComponent);
+
+    // scheduled for removal from component: taginfo to contain nesting level info
+    $this->component->CheckNestingLevel();
+
+    return $this->component->preParse($this);
+  }
+
+  /**
+  * Adds a component to the tree, without descending into it.
+  * This begins and finishes the component's composition
+  * @param CompilerComponent
+  * @return void
+  * @access public
+  */
+  function addNode(&$childComponent)
+  {
+    $childComponent->preParse($this);
+    $this->component->addChild($childComponent);
+  }
+
+  /**
+  * Helper method to add a TextNode, given plain text
+  * @param string text to create node for
+  * @return void
+  * @access public
+  */
+  function addTextNode($text)
+  {
+    $this->addNode(new TextNode($text));
+  }
+
+  /**
+  * Ends a component's build phase in relation to the tree.
+  * Checks child server ids and moves the 'cursor' up the tree to the parent
+  * component.
+  * @param boolean whether current component has a closing tag
+  * @return void
+  * @access public
+  */
+  function popNode($hasClosingTag)
+  {
+    $this->component->hasClosingTag = $hasClosingTag;
+    $this->checkServerIds();
+    $this->setCursor($this->component->parent);
+  }
+
+  /**
+  * Expects the passed tag.  Optionally $info may be passed which is info
+  * about that tag.  The parser state that calls TreeBuilder may use this info
+  * to differentiate, say, plain vs. component tags.
+  * @param string tag name
+  * @param mixed info about the tag
+  * @return void
+  * @access public
+  */
+  function pushExpectedTag($tag, $info = null, $position_info = array())
+  {
+    array_push($this->expectedTags, array($tag, $info, $position_info));
+  }
+
+  /**
+  * Sets the cursor to a new position, and pushes the old cursor onto the
+  * expected tags stack.
+  * @see popExpectedTag
+  * @param CompilerComponent
+  * @return void
+  * @access public
+  */
+  function pushCursor(&$newPosition)
+  {
+    // use of array() is to preserve reference from array_pop()
+    array_push($this->expectedTags, array(&$this->component));
+    $this->setCursor($newPosition);
+  }
+
+  /**
+  * Tests the passed tag against what is expected.  Returns any info that
+  * was kept about the expected tag.
+  * If the item in the tag stack is a component, then the cursor is
+  * restored to that, and popExpectedTag is called again.
+  * @param string tag name
+  * @return mixed info
+  * @access public
+  */
+  function popExpectedTag($tag, $position_info = array())
+  {
+    $expectedTagItem = array_pop($this->expectedTags);
+
+    // if we have a component on the stack, restore the cursor to that, and
+    // pop the stack again
+    if (is_object($expectedTagItem[0]))
+    {
+       $this->component =& $expectedTagItem[0];
+       return $this->popExpectedTag($tag, $position_info);
+    }
+
+    $expectedTag = $expectedTagItem[0];
+    $info = $expectedTagItem[1];
+
+    if (strcasecmp($expectedTag, $tag) !== 0)
+    {
+      if(isset($expectedTagItem[2]['line']))
+        $line = $expectedTagItem[2]['line'];
+      else
+        $line = '';
+
+      throw new WactException('compiler', 'UNEXPECTEDCLOSE', array('file' => $position_info['file'],
+                                                          'tag' => $tag,
+                                                          'line' => $position_info['line'],
+                                                          'ExpectTag' => $expectedTag,
+                                                          'ExpectedTagLine' => $line)
+                                                          );
+    }
+
+    return $info;
+  }
+
+  /**
+  * Return the size of the expected tags stack
+  * @return bool
+  * @access public
+  */
+  function getExpectedTagCount() {
+    return count($this->expectedTags);
+  }
+
+  /**
+  * Returns the current expected tag
+  * @return mixed string or false
+  * @access public
+  */
+  function getExpectedTag() {
+    // Returns the tagname of the first non-component item on the stack
+    $item = end($this->expectedTags);
+    while ($item && !is_string($item[0])) {
+      $item = prev($this->expectedTags);
+    }
+    return $item ? $item[0] : false;
+  }
+
+
+  /**
+  * Checks that each immediate child of the current component has a unique ID
+  * amongst its siblings.
+  * @see popNode
+  * @param object CompilerComponent
+  * @return void
+  */
+  function checkServerIds() {
+      $childServerIds = array();
+      $children = $this->component->getChildren();
+      foreach (array_keys($children) as $key) {
+          $id = $children[$key]->getServerId();
+          if (in_array($id, $childServerIds)) {
+              $children[$key]->raiseCompilerError('DUPLICATEID', $vars = array('ServerId' => $id));
+          } else {
+              $childServerIds[] = $id;
+      }
+      }
+  }
+}
+?>

Modified: 3.x/packages/wact/trunk/framework/template/compiler/property/dictionary.inc.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/property/dictionary.inc.php	2006-10-16 06:38:46 UTC (rev 4161)
+++ 3.x/packages/wact/trunk/framework/template/compiler/property/dictionary.inc.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -8,7 +8,7 @@
 * @version $Id: dictionary.inc.php 2864 2006-02-28 10:20:41Z pachanga $
 */
 
-require_once WACT_ROOT . '/template/compiler/common/dictionary.inc.php';
+require_once WACT_ROOT . '/template/compiler/CompilerArtifactDictionary.class.php';
 
 class PropertyInfo
 {

Modified: 3.x/packages/wact/trunk/framework/template/compiler/tags/tagdictionary.inc.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/tags/tagdictionary.inc.php	2006-10-16 06:38:46 UTC (rev 4161)
+++ 3.x/packages/wact/trunk/framework/template/compiler/tags/tagdictionary.inc.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -7,7 +7,7 @@
 * @package WACT_TEMPLATE
 * @version $Id: tagdictionary.inc.php,v 1.24 2005/11/05 12:55:10 ian_w_white Exp $
 */
-require_once WACT_ROOT . '/template/compiler/common/dictionary.inc.php';
+require_once WACT_ROOT . '/template/compiler/CompilerArtifactDictionary.class.php';
 
 /**
 * The tag must have a closing tag

Modified: 3.x/packages/wact/trunk/framework/template/compiler/templatecompiler.inc.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/templatecompiler.inc.php	2006-10-16 06:38:46 UTC (rev 4161)
+++ 3.x/packages/wact/trunk/framework/template/compiler/templatecompiler.inc.php	2006-10-16 06:51:26 UTC (rev 4162)
@@ -43,10 +43,10 @@
 require_once WACT_ROOT . '/template/compiler/property/constant.inc.php';
 
 require_once WACT_ROOT . '/template/compiler/parser/ParserListener.interface.php';
+require_once WACT_ROOT . '/template/compiler/parser/WactSourceLocation.class.php';
+require_once WACT_ROOT . '/template/compiler/parser/WactTreeBuilder.class.php';
+require_once WACT_ROOT . '/template/compiler/parser/SourceFileParser.class.php';
 
-require_once WACT_ROOT . '/template/compiler/WactSourceLocation.class.php';
-require_once WACT_ROOT . '/template/compiler/WactTreeBuilder.class.php';
-require_once WACT_ROOT . '/template/compiler/SourceFileParser.class.php';
 require_once WACT_ROOT . '/template/compiler/CodeWriter.class.php';
 
 /**



More information about the limb-svn mailing list