[limb-svn] r6561 - in 3.x/trunk/limb/macro: src src/compiler src/filters src/tags/core src/tags/form src/tags/list src/tags/tree tests/cases tests/cases/compiler
svn at limb-project.com
svn at limb-project.com
Mon Dec 3 14:56:55 MSK 2007
Author: serega
Date: 2007-12-03 14:56:54 +0300 (Mon, 03 Dec 2007)
New Revision: 6561
URL: http://fisheye.limb-project.com/changelog/limb/?cs=6561
Added:
3.x/trunk/limb/macro/src/compiler/
3.x/trunk/limb/macro/src/compiler/lmbMacroAnnotationParser.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroAnnotationParserListener.interface.php
3.x/trunk/limb/macro/src/compiler/lmbMacroBaseParsingState.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroBlockAnalizer.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroBlockAnalizerListener.interface.php
3.x/trunk/limb/macro/src/compiler/lmbMacroCodeWriter.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroCompiler.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroContentBlockAnalizerListener.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroExpression.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroExpressionInterface.interface.php
3.x/trunk/limb/macro/src/compiler/lmbMacroExpressionNode.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroFilter.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroFilterDictionary.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroFilterInfo.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroFilterParser.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroNode.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroOutputExpressionNode.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroParser.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroPassiveTag.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroPreprocessor.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroTag.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroTagAttribute.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroTagAttributeBlockAnalizerListener.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroTagDictionary.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroTagInfo.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroTagParsingState.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroTemplateExecutor.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroTextNode.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroTokenizer.class.php
3.x/trunk/limb/macro/src/compiler/lmbMacroTokenizerListener.interface.php
3.x/trunk/limb/macro/src/compiler/lmbMacroTreeBuilder.class.php
3.x/trunk/limb/macro/tests/cases/compiler/lmbMacroAnnotationParserTest.class.php
3.x/trunk/limb/macro/tests/cases/compiler/lmbMacroCodeWriterTest.class.php
3.x/trunk/limb/macro/tests/cases/compiler/lmbMacroFilterDictionaryTest.class.php
3.x/trunk/limb/macro/tests/cases/compiler/lmbMacroFilterParserTest.class.php
3.x/trunk/limb/macro/tests/cases/compiler/lmbMacroFiltersAcceptanceTest.class.php
3.x/trunk/limb/macro/tests/cases/compiler/lmbMacroOutputExpressionTest.class.php
3.x/trunk/limb/macro/tests/cases/compiler/lmbMacroTagAcceptanceTest.class.php
3.x/trunk/limb/macro/tests/cases/compiler/lmbMacroTagDictionaryTest.class.php
3.x/trunk/limb/macro/tests/cases/compiler/lmbMacroTagTest.class.php
3.x/trunk/limb/macro/tests/cases/compiler/lmbMacroTemplateExecutorTest.class.php
3.x/trunk/limb/macro/tests/cases/compiler/lmbMacroTemplateTest.class.php
3.x/trunk/limb/macro/tests/cases/compiler/lmbMacroTokenizerMalformedTest.class.php
3.x/trunk/limb/macro/tests/cases/compiler/lmbMacroTokenizerTest.class.php
3.x/trunk/limb/macro/tests/cases/compiler/lmbMacroTreeBuilderTest.class.php
Removed:
3.x/trunk/limb/macro/src/lmbMacroAnnotationParser.class.php
3.x/trunk/limb/macro/src/lmbMacroAnnotationParserListener.interface.php
3.x/trunk/limb/macro/src/lmbMacroBaseParsingState.class.php
3.x/trunk/limb/macro/src/lmbMacroBlockAnalizer.class.php
3.x/trunk/limb/macro/src/lmbMacroBlockAnalizerListener.interface.php
3.x/trunk/limb/macro/src/lmbMacroCodeWriter.class.php
3.x/trunk/limb/macro/src/lmbMacroCompiler.class.php
3.x/trunk/limb/macro/src/lmbMacroContentBlockAnalizerListener.class.php
3.x/trunk/limb/macro/src/lmbMacroExpression.class.php
3.x/trunk/limb/macro/src/lmbMacroExpressionInterface.interface.php
3.x/trunk/limb/macro/src/lmbMacroExpressionNode.class.php
3.x/trunk/limb/macro/src/lmbMacroFilter.class.php
3.x/trunk/limb/macro/src/lmbMacroFilterDictionary.class.php
3.x/trunk/limb/macro/src/lmbMacroFilterInfo.class.php
3.x/trunk/limb/macro/src/lmbMacroFilterParser.class.php
3.x/trunk/limb/macro/src/lmbMacroNode.class.php
3.x/trunk/limb/macro/src/lmbMacroOutputExpressionNode.class.php
3.x/trunk/limb/macro/src/lmbMacroParser.class.php
3.x/trunk/limb/macro/src/lmbMacroPassiveTag.class.php
3.x/trunk/limb/macro/src/lmbMacroPreprocessor.class.php
3.x/trunk/limb/macro/src/lmbMacroTag.class.php
3.x/trunk/limb/macro/src/lmbMacroTagAttribute.class.php
3.x/trunk/limb/macro/src/lmbMacroTagAttributeBlockAnalizerListener.class.php
3.x/trunk/limb/macro/src/lmbMacroTagDictionary.class.php
3.x/trunk/limb/macro/src/lmbMacroTagInfo.class.php
3.x/trunk/limb/macro/src/lmbMacroTagParsingState.class.php
3.x/trunk/limb/macro/src/lmbMacroTemplateExecutor.class.php
3.x/trunk/limb/macro/src/lmbMacroTextNode.class.php
3.x/trunk/limb/macro/src/lmbMacroTokenizer.class.php
3.x/trunk/limb/macro/src/lmbMacroTokenizerListener.interface.php
3.x/trunk/limb/macro/src/lmbMacroTreeBuilder.class.php
3.x/trunk/limb/macro/tests/cases/lmbMacroAnnotationParserTest.class.php
3.x/trunk/limb/macro/tests/cases/lmbMacroCodeWriterTest.class.php
3.x/trunk/limb/macro/tests/cases/lmbMacroFilterDictionaryTest.class.php
3.x/trunk/limb/macro/tests/cases/lmbMacroFilterParserTest.class.php
3.x/trunk/limb/macro/tests/cases/lmbMacroFiltersAcceptanceTest.class.php
3.x/trunk/limb/macro/tests/cases/lmbMacroOutputExpressionTest.class.php
3.x/trunk/limb/macro/tests/cases/lmbMacroTagAcceptanceTest.class.php
3.x/trunk/limb/macro/tests/cases/lmbMacroTagDictionaryTest.class.php
3.x/trunk/limb/macro/tests/cases/lmbMacroTagTest.class.php
3.x/trunk/limb/macro/tests/cases/lmbMacroTemplateExecutorTest.class.php
3.x/trunk/limb/macro/tests/cases/lmbMacroTemplateTest.class.php
3.x/trunk/limb/macro/tests/cases/lmbMacroTokenizerMalformedTest.class.php
3.x/trunk/limb/macro/tests/cases/lmbMacroTokenizerTest.class.php
3.x/trunk/limb/macro/tests/cases/lmbMacroTreeBuilderTest.class.php
Modified:
3.x/trunk/limb/macro/src/filters/date.filter.php
3.x/trunk/limb/macro/src/filters/lmbMacroPhpFunctionBasedFilter.class.php
3.x/trunk/limb/macro/src/lmbMacroTemplate.class.php
3.x/trunk/limb/macro/src/tags/core/apply.tag.php
3.x/trunk/limb/macro/src/tags/core/include.tag.php
3.x/trunk/limb/macro/src/tags/core/into.tag.php
3.x/trunk/limb/macro/src/tags/core/slot.tag.php
3.x/trunk/limb/macro/src/tags/core/template.tag.php
3.x/trunk/limb/macro/src/tags/core/wrap.tag.php
3.x/trunk/limb/macro/src/tags/form/lmbMacroRuntimeWidgetTag.class.php
3.x/trunk/limb/macro/src/tags/list/list.tag.php
3.x/trunk/limb/macro/src/tags/list/list_empty.tag.php
3.x/trunk/limb/macro/src/tags/list/list_even.tag.php
3.x/trunk/limb/macro/src/tags/list/list_fill.tag.php
3.x/trunk/limb/macro/src/tags/list/list_glue.tag.php
3.x/trunk/limb/macro/src/tags/list/list_item.tag.php
3.x/trunk/limb/macro/src/tags/list/list_odd.tag.php
3.x/trunk/limb/macro/src/tags/tree/tree.tag.php
3.x/trunk/limb/macro/src/tags/tree/tree_branch.tag.php
3.x/trunk/limb/macro/src/tags/tree/tree_item.tag.php
3.x/trunk/limb/macro/tests/cases/.setup.php
3.x/trunk/limb/macro/tests/cases/lmbBaseMacroTest.class.php
Log:
-- all compiler stuff moved to /compiler folder
-- tests restructurization
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroAnnotationParser.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroAnnotationParser.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroAnnotationParser.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroAnnotationParser.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,62 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/core/src/lmbPHPTokenizer.class.php');
+
+/**
+ * class lmbMacroAnnotationParser.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroAnnotationParser
+{
+ static function extractFromFile($file, $listener)
+ {
+ $infos = array();
+ $tokenizer = new lmbPHPTokenizer(file_get_contents($file));
+ while($token = $tokenizer->next())
+ {
+ if(!is_array($token))
+ continue;
+
+ //found class token
+ if($token[0] == T_CLASS)
+ {
+ //fetching class name
+ $token = $tokenizer->next();
+ $class = $token[1];
+
+ //now checking prev token for /**/
+ if(!is_array($prev_token) || $prev_token[0] != T_DOC_COMMENT)
+ throw new lmbMacroException('Invalid token, doc comment is expected');
+
+ //now parsing annotations
+ $annotations = self :: _extractAnnotations($prev_token[1]);
+ if(!$annotations)
+ throw new lmbMacroException("No annotations found in doc comment '{$prev_token[1]}' in file $file");
+
+ $infos[] = call_user_func_array (array($listener, 'createByAnnotations'), array($file, $class, $annotations));
+ //$infos[] = $listener->createByAnnotations($file, $class, $annotations);
+ }
+ $prev_token = $token;
+ }
+ return $infos;
+ }
+
+ static protected function _extractAnnotations($content)
+ {
+ if(!preg_match_all('~@(\S+)([^\n]+)?\n~', $content, $matches))
+ return false;
+ $annotations = array();
+ for($i=0;$i<count($matches[0]);$i++)
+ $annotations[trim($matches[1][$i])] = trim($matches[2][$i]);
+ return $annotations;
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroAnnotationParserListener.interface.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroAnnotationParserListener.interface.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroAnnotationParserListener.interface.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroAnnotationParserListener.interface.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,20 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * interface lmbMacroAnnotationParserListener.
+ *
+ * @package macro
+ * @version $Id$
+ */
+interface lmbMacroAnnotationParserListener
+{
+ function createByAnnotations($class, $file, $annotations);
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroBaseParsingState.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroBaseParsingState.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroBaseParsingState.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroBaseParsingState.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,61 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroBaseParsingState
+{
+ /**
+ * @var lmbMacroSourceFileParser
+ */
+ protected $parser;
+
+ /**
+ * @var lmbMacroTreeBuilder
+ */
+ protected $tree_builder;
+
+ protected $locator;
+
+ function __construct($parser, $tree_builder)
+ {
+ $this->parser = $parser;
+ $this->tree_builder = $tree_builder;
+ }
+
+ function setTemplateLocator($locator)
+ {
+ $this->locator = $locator;
+ }
+
+ function invalidAttributeSyntax($data)
+ {
+ throw new lmbException('Invalid attribute syntax starting from: ' . $data);
+ }
+
+ 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;
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroBlockAnalizer.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroBlockAnalizer.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroBlockAnalizer.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroBlockAnalizer.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,52 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroContentAnalizer.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroBlockAnalizer
+{
+ const BEFORE_CONTENT = 1;
+ const EXPRESSION = 2;
+ const AFTER_CONTENT = 5;
+
+ protected function _getRegexp()
+ {
+ return '/^((?s).*?)'. preg_quote('{$', '/') . '((([^"\']+["\']?[^"\']?["\'])+)?[^}]+)' . preg_quote('}', '/') . '((?s).*)$/';
+ }
+
+ function parse($text, $observer)
+ {
+ // if there is no expression (common case), shortcut this process
+ if (strpos($text, '{$') === FALSE)
+ {
+ $observer->addLiteralFragment($text);
+ return;
+ }
+
+ $regexp = $this->_getRegexp();
+
+ while (preg_match($regexp, $text, $match))
+ {
+ if (strlen($match[self :: BEFORE_CONTENT]) > 0)
+ $observer->addLiteralFragment($match[self :: BEFORE_CONTENT]);
+
+ $observer->addExpressionFragment('$' . $match[self :: EXPRESSION]);
+
+ $text = $match[self :: AFTER_CONTENT];
+ }
+
+ if (strlen($text) > 0)
+ $observer->addLiteralFragment($text);
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroBlockAnalizerListener.interface.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroBlockAnalizerListener.interface.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroBlockAnalizerListener.interface.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroBlockAnalizerListener.interface.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,21 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * interface lmbMacroBlockAnalizerListener.
+ *
+ * @package macro
+ * @version $Id$
+ */
+interface lmbMacroBlockAnalizerListener
+{
+ function addLiteralFragment($text);
+ function addExpressionFragment($text);
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroCodeWriter.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroCodeWriter.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroCodeWriter.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroCodeWriter.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,242 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroCodeWriter.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroCodeWriter
+{
+ const MODE_PHP = 1;
+ const MODE_HTML = 2;
+
+ protected $class;
+
+ protected $parent;
+
+ protected $current_mode = self :: MODE_PHP;
+
+ protected $current_method;
+
+ protected $code = '';
+
+ protected $methods = array();
+
+ protected $init_code = '';
+
+ protected $methods_stack = array();
+
+ protected $include_list = array();
+
+ protected $temp_var_name = 1;
+
+ function __construct($class, $render_func = 'render')
+ {
+ $this->class = $class;
+ $this->render_func = $render_func;
+ $this->parent = 'lmbMacroTemplateExecutor';
+ $this->registerInclude('limb/macro/src/compiler/lmbMacroTemplateExecutor.class.php');
+
+ $this->beginMethod($render_func, array('$args = array()'));
+ $this->writePHP('if($args) extract($args);');
+ $this->writePHP('$this->_init();');
+ }
+
+ function getClass()
+ {
+ return $this->class;
+ }
+
+ function getRenderMethod()
+ {
+ return 'render';
+ }
+
+ protected function switchToPHP()
+ {
+ if($this->current_mode == self :: MODE_HTML)
+ {
+ $this->current_mode = self :: MODE_PHP;
+ $this->_append('<?php ');
+ }
+ }
+
+ protected function switchToHTML($context = null)
+ {
+ if($this->current_mode == self :: MODE_PHP)
+ {
+ $this->current_mode = self :: MODE_HTML;
+ if($context === "\n")
+ $this->_append(" ?>\n");
+ else
+ $this->_append(' ?>');
+ }
+ }
+
+ function writePHP($text)
+ {
+ $this->switchToPHP();
+ $this->_append($text);
+ }
+
+ function writePHPLiteral($text, $escape_text = true)
+ {
+ $this->switchToPHP();
+
+ if($escape_text)
+ $this->_append("'" . $this->escapeLiteral($text) . "'");
+ else
+ $this->_append("'" . $text . "'");
+ }
+
+ function escapeLiteral($text)
+ {
+ $text = str_replace('\'', "\\'", $text);
+ if(substr($text, -1) == '\\')
+ $text .= '\\';
+ return $text;
+ }
+
+ function writeHTML($text)
+ {
+ $this->switchToHTML(substr($text,0,1));
+ $this->_append($text);
+ }
+
+ function writeRaw($text)
+ {
+ $this->_append($text);
+ }
+
+ function renderCode()
+ {
+ $this->endMethod();
+
+ $code = "<?php\n" .
+ //protection from self inclusion
+ "if(!class_exists('{$this->class}', false)){\n" .
+ $this->_renderIncludeList() .
+ "class {$this->class} " . ($this->parent ? "extends {$this->parent} " : '') . "{\n" .
+ (!$this->init_code ? "" :
+ "\nfunction _init() {" .
+ "\n$this->init_code\n" .
+ "}\n"
+ ) .
+ $this->_renderMethods() .
+ "\n}" .
+ "\n}";
+ return $code;
+ }
+
+ function getCode()
+ {
+ return $this->code;
+ }
+
+ function getMode()
+ {
+ return $this->current_mode;
+ }
+
+ function registerInclude($include_file)
+ {
+ if(!in_array($include_file, $this->include_list))
+ $this->include_list[] = $include_file;
+ }
+
+ function getIncludeList()
+ {
+ return $this->include_list;
+ }
+
+ function beginFunction($name, $param_list = array())
+ {
+ $this->writePHP('function ' . $name . '(' . implode(',', $param_list) .") {\n");
+ return $name;
+ }
+
+ function endFunction()
+ {
+ $this->writePHP("\n}\n");
+ }
+
+ function beginMethod($name, $param_list = array())
+ {
+ $this->methods_stack[] = array($this->current_method, $this->current_mode);
+ $this->current_method = $name;
+
+ //we don't need to switch to PHP, since methods can be declared inside PHP only
+ $this->writeRaw('function ' . $name . '(' . implode(',', $param_list) .") {\n");
+ $this->current_mode = self :: MODE_PHP;
+ return $name;
+ }
+
+ function endMethod()
+ {
+ $this->writePHP("\n}\n");
+ list($this->current_method, $this->current_mode) = array_pop($this->methods_stack);
+ }
+
+ function writeToInit($code)
+ {
+ $this->init_code .= $code;
+ }
+
+ /**
+ * Utility method, which generates a unique variable name
+ */
+ function generateTempName()
+ {
+ $var = $this->temp_var_name++;
+ if($var > 675)
+ return chr(65 + ($var/26)/26) . chr(65 + ($var/26)%26) . chr(65 + $var%26);
+ elseif($var > 26)
+ return chr(65 + ($var/26)%26) . chr(65 + $var%26);
+ else
+ return chr(64 + $var);
+ }
+
+ /**
+ * Utility method, which generates a unique variable name, prefixed with a $
+ */
+ function generateVar()
+ {
+ return '$' . $this->generateTempName();
+ }
+
+ protected function _append($code)
+ {
+ if(!$this->current_method)
+ {
+ $this->code .= $code;
+ return;
+ }
+
+ if(!isset($this->methods[$this->current_method]))
+ $this->methods[$this->current_method] = '';
+
+ $this->methods[$this->current_method] .= $code;
+ }
+
+ protected function _renderMethods()
+ {
+ return implode("\n", $this->methods);
+ }
+
+ protected function _renderIncludeList()
+ {
+ $include_code = '';
+ foreach($this->include_list as $include_file)
+ $include_code .= "require_once('$include_file');\n";
+ return $include_code;
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroCompiler.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroCompiler.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroCompiler.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroCompiler.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,109 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroCompiler.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroCompiler
+{
+ /**
+ * @var lmbMacroTreeBuilder
+ */
+ protected $tree_builder;
+
+ /**
+ * @var lmbMacroTemplateLocator
+ */
+ protected $template_locator;
+
+ /**
+ * @var lmbMacroSourceParser
+ */
+ protected $parser;
+
+ /**
+ * @var lmbMacroTagDictionary
+ */
+ protected $tag_dictionary;
+
+ /**
+ * @var lmbMacroFilterDictionary
+ */
+ protected $filter_dictionary;
+
+ function __construct($tag_dictionary, $template_locator, $filter_dictionary)
+ {
+ $this->tree_builder = new lmbMacroTreeBuilder($this);
+
+ $this->template_locator = $template_locator;
+
+ $this->tag_dictionary = $tag_dictionary;
+ $this->filter_dictionary = $filter_dictionary;
+ }
+
+ function compile($source_file, $compiled_file, $class, $render_func)
+ {
+ $root_node = new lmbMacroNode(new lmbMacroSourceLocation($source_file, ''));
+ $this->parseTemplate($source_file, $root_node);
+
+ $generated_code = $this->_generateTemplateCode($class, $render_func, $root_node);
+ self :: writeFile($compiled_file, $generated_code);
+ }
+
+ function _generateTemplateCode($class, $render_func, $root_node)
+ {
+ $code_writer = new lmbMacroCodeWriter($class, $render_func);
+ $root_node->generate($code_writer);
+ return $code_writer->renderCode();
+ }
+
+ function parseTemplate($source_file_path, $root_node)
+ {
+ $parser = new lmbMacroParser($this->tree_builder, $this->template_locator, $this->tag_dictionary);
+ $parser->parse($source_file_path, $root_node);
+ }
+
+ /**
+ * @return lmbMacroTemplateLocator
+ */
+ function getTemplateLocator()
+ {
+ return $this->template_locator;
+ }
+
+ /**
+ * @return lmbMacroTreeBuilder
+ */
+ function getTreeBuilder()
+ {
+ return $this->tree_builder;
+ }
+
+ function getTagDictionary()
+ {
+ return $this->tag_dictionary;
+ }
+
+ function getFilterDictionary()
+ {
+ return $this->filter_dictionary;
+ }
+
+ static function writeFile($file, $data)
+ {
+ $dirname = dirname($file);
+ lmbFs :: mkdir($dirname);
+
+ file_put_contents($file, $data);
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroContentBlockAnalizerListener.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroContentBlockAnalizerListener.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroContentBlockAnalizerListener.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroContentBlockAnalizerListener.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,42 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroContentBlockAnalizerListener.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroContentBlockAnalizerListener implements lmbMacroBlockAnalizerListener
+{
+ protected $tree_builder;
+ protected $location;
+
+ function __construct($tree_builder, $location)
+ {
+ $this->tree_builder = $tree_builder;
+ $this->location = $location;
+ }
+
+ function addLiteralFragment($text)
+ {
+ $this->tree_builder->addTextNode($text);
+ }
+
+ function addExpressionFragment($text)
+ {
+ $expression = new lmbMacroExpressionNode($text,
+ $this->tree_builder->getCursor(),
+ $this->tree_builder->getFilterDictionary());
+
+ $output_expression = new lmbMacroOutputExpressionNode($this->location, $expression);
+ $this->tree_builder->addNode($output_expression);
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroExpression.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroExpression.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroExpression.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroExpression.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,103 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroExpression
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroExpression implements lmbMacroExpressionInterface
+{
+ protected $tmp;
+
+ function __construct($expression_str)
+ {
+ $this->expression_str = $expression_str;
+ }
+
+ function preGenerate($code)
+ {
+ $this->tmp = $code->generateVar();
+ $var = $code->generateVar();
+
+ // simple case if expression is just a variable
+ if(strpos($this->expression_str, '.') === false)
+ {
+ $this->tmp = $this->expression_str;
+ return;
+ }
+
+ $expr = '';
+
+ $items = $this->_extractExpressionPathItems($this->expression_str);
+
+ //first item is variable itself
+ //$var = $items[0];
+ $expr .= $var . ' = ' . $items[0] . ';';
+ $code->writePHP($this->tmp . "='';");
+
+ for($i=1; $i<sizeof($items); $i++)
+ {
+ $item = $items[$i];
+ $expr .= 'if((is_array(' . $var . ') && isset(' . $var . '["' . $item . '"])) || ' .
+ '(is_object(' . $var . ') && ' . $this->tmp . '=' . $var . '->get("' . $item . '")))' .
+ '{if(is_array(' . $var . '))' . $this->tmp . ' = ' . $var . '["' . $item . '"];';
+ $var = $this->tmp;
+ }
+
+ //closing brackets
+ for($i=1; $i < sizeof($items); $i++)
+ $expr .= '}else{' . $this->tmp . '="";}';
+
+ $code->writePHP($expr);
+ }
+
+ protected function _extractExpressionPathItems($text)
+ {
+ $tokens = token_get_all('<?php ' . $text . '?>');
+ // removing first and last tokens since we just added them with the line above
+ array_shift($tokens);
+ array_pop($tokens);
+
+ $path_items = array();
+ $in_function = false;
+
+ $item = '';
+ foreach($tokens as $token)
+ {
+ if(is_scalar($token))
+ {
+ if($token == '(')
+ $in_function = true;
+ if($token == ')')
+ $in_function = false;
+ if($token == '.' && !$in_function)
+ {
+ $path_items[] = $item;
+ $item = '';
+ continue;
+ }
+
+ $item .= $token;
+ }
+ else
+ $item .= $token[1];
+ }
+
+ $path_items[] = $item;
+
+ return $path_items;
+ }
+
+ function getValue()
+ {
+ return $this->tmp;
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroExpressionInterface.interface.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroExpressionInterface.interface.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroExpressionInterface.interface.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroExpressionInterface.interface.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,20 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * interface lmbMacroExpressionInterface
+ * @package macro
+ * @version $Id$
+ */
+interface lmbMacroExpressionInterface
+{
+ function preGenerate($code);
+ function getValue();
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroExpressionNode.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroExpressionNode.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroExpressionNode.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroExpressionNode.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,104 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroExpressionNode.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroExpressionNode implements lmbMacroExpressionInterface
+{
+ protected $context;
+
+ protected $original_expression;
+ protected $expression;
+
+ protected $parsed;
+
+ protected $filter_dictionary;
+
+ function __construct($expression, $context_node, $filter_dictionary)
+ {
+ $this->original_expression = $expression;
+ $this->expression = $expression;
+ $this->context = $context_node;
+ $this->filter_dictionary = $filter_dictionary;
+
+ $this->_createParsedExpression();
+ }
+
+ protected function _createParsedExpression()
+ {
+ $pos = strpos($this->expression, "|");
+
+ if ($pos === FALSE)
+ $this->parsed = new lmbMacroExpression($this->expression);
+ else
+ {
+ $base_expression = trim(substr($this->expression, 0, $pos));
+ $filters_expression = trim(substr($this->expression, $pos + 1));
+ $this->parsed = $this->createFilterChain($filters_expression, new lmbMacroExpression($base_expression));
+ }
+ }
+
+ /**
+ * Parses an expression, building a chain of filters for it
+ */
+ function createFilterChain($expression, $base)
+ {
+ $filter_parser = new lmbMacroFilterParser($this->context);
+ $filters_specs = $filter_parser->parse($expression);
+
+ foreach($filters_specs as $filter_spec)
+ {
+ $filter_name = $filter_spec['name'];
+ $filter_info = $this->filter_dictionary->findFilterInfo($filter_name);
+
+ if (!is_object($filter_info))
+ $this->context->raise('Unknown filter', array('filter' => $filter_name));
+
+ $base = $this->_createFilter($filter_name, $base, $filter_spec['params']);
+ }
+
+ return $base;
+ }
+
+ protected function _createFilter($name, $base, $params = "")
+ {
+ $filter_info = $this->filter_dictionary->findFilterInfo($name);
+
+ if (!is_object($filter_info))
+ $this->context->raise('Unknown filter', array('filter' => $name));
+
+ $filter_info->load();
+
+ $filter_class = $filter_info->getClass();
+ $filter = new $filter_class($base);
+ if(sizeof($params))
+ $filter->setParams($params);
+ return $filter;
+ }
+
+ function getValue()
+ {
+ return $this->parsed->getValue();
+ }
+
+ function preGenerate($code_writer)
+ {
+ $this->parsed->preGenerate($code_writer);
+ }
+
+ function getFilterDictionary()
+ {
+ return $this->filter_dictionary;
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroFilter.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroFilter.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroFilter.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroFilter.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,35 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroFilter
+ * @package macro
+ * @version $Id$
+ */
+abstract class lmbMacroFilter implements lmbMacroExpressionInterface
+{
+ protected $base;
+ protected $params = array();
+
+ function __construct($base)
+ {
+ $this->base = $base;
+ }
+
+ function preGenerate($code)
+ {
+ $this->base->preGenerate($code);
+ }
+
+ function setParams($params)
+ {
+ $this->params = $params;
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroFilterDictionary.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroFilterDictionary.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroFilterDictionary.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroFilterDictionary.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,100 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroFilterDictionary.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroFilterDictionary
+{
+ protected $info = array();
+ static protected $instance;
+
+ static function instance()
+ {
+ if(self :: $instance)
+ return self :: $instance;
+
+ self :: $instance = new lmbMacroFilterDictionary();
+ return self :: $instance;
+ }
+
+ function load(lmbMacroConfig $config)
+ {
+ if(!$config->isForceScan() && $this->_loadCache($config))
+ return;
+
+ $dirs = $config->getFiltersScanDirectories();
+ foreach($dirs as $dir)
+ {
+ foreach(lmb_glob($dir . '/*.filter.php') as $file)
+ $this->registerFromFile($file);
+ }
+
+ $this->_saveCache($config);
+ }
+
+ protected function _loadCache(lmbMacroConfig $config)
+ {
+ $cache_file = $config->getCacheDir() . '/filters.cache';
+ if(!file_exists($cache_file))
+ return false;
+
+ $info = @unserialize(file_get_contents($cache_file));
+ if($info === false || !is_array($info))
+ return false;
+
+ $this->info = $info;
+
+ return true;
+ }
+
+ protected function _saveCache(lmbMacroConfig $config)
+ {
+ $cache_file = $config->getCacheDir() . '/filters.cache';
+ lmbFs :: safeWrite($cache_file, serialize($this->info));
+ }
+
+ function register($filter_info)
+ {
+ $names = array(strtolower($filter_info->getName()));
+
+ $aliases = $filter_info->getAliases();
+ if(count($aliases))
+ {
+ $aliases = array_map('strtolower', $aliases);
+ $names = array_merge($names, $aliases);
+ }
+
+ foreach($names as $filter_name)
+ {
+ if(isset($this->info[$filter_name]))
+ return;
+
+ $this->info[$filter_name] = $filter_info;
+ }
+ }
+
+ function registerFromFile($file)
+ {
+ $infos = lmbMacroAnnotationParser :: extractFromFile($file, 'lmbMacroFilterInfo');
+ foreach($infos as $info)
+ $this->register($info, $file);
+ }
+
+ function findFilterInfo($name)
+ {
+ $name = strtolower($name);
+ if(isset($this->info[$name]))
+ return $this->info[$name];
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroFilterInfo.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroFilterInfo.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroFilterInfo.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroFilterInfo.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,85 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroFilterInfo.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroFilterInfo
+{
+ protected $name = '';
+ protected $class = '';
+ protected $file;
+ protected $aliases = array();
+
+ function __construct($name, $class)
+ {
+ $this->name = $name;
+ $this->class = $class;
+ }
+
+ static function createByAnnotations($file, $class, $annotations)
+ {
+ if(!isset($annotations['filter']))
+ throw new lmbMacroException("@filter annotation is missing for class '$class'");
+
+ $filter = $annotations['filter'];
+ $info = new lmbMacroFilterInfo($filter, $class);
+
+ if(isset($annotations['aliases']))
+ {
+ $filter_aliases = explode(',' , $annotations['aliases']);
+ $filter_aliases = array_map('trim', $filter_aliases);
+ $info->setAliases($filter_aliases);
+ }
+
+ $info->setFile($file);
+
+ return $info;
+ }
+
+ function load()
+ {
+ if (!class_exists($this->class) && isset($this->file))
+ require_once $this->file;
+ }
+
+ function getName()
+ {
+ return $this->name;
+ }
+
+ function getClass()
+ {
+ return $this->class;
+ }
+
+ function setFile($file)
+ {
+ $this->file = $file;
+ }
+
+ function getFile()
+ {
+ return $this->file;
+ }
+
+ function setAliases($aliases)
+ {
+ $this->aliases = $aliases;
+ }
+
+ function getAliases()
+ {
+ return $this->aliases;
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroFilterParser.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroFilterParser.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroFilterParser.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroFilterParser.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,180 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroFilterParser.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroFilterParser
+{
+ protected $text;
+ protected $position;
+ protected $length;
+ protected $context;
+ protected $filters = array();
+
+ /**
+ * Construct this parser
+ */
+ function __construct($context)
+ {
+ $this->context = $context;
+ }
+
+ protected function getToken($pattern)
+ {
+ if (preg_match($pattern, $this->text, $match, PREG_OFFSET_CAPTURE, $this->position))
+ {
+ $this->position += strlen($match[0][0]);
+ return $match[1][0];
+ }
+ else
+ return FALSE;
+ }
+
+ function getFilters()
+ {
+ return $this->filters;
+ }
+
+ /**
+ * Parse text for expressions and emit a stream of events for expression fragments
+ */
+ function parse($text)
+ {
+ if (strlen($text) == 0)
+ return array();
+
+ $filters = array();
+
+ $this->text = $text;
+ $this->position = 0;
+
+ $filters_expressions = $this->_extractFiltersExpressions();
+
+ foreach($filters_expressions as $filter_expression)
+ {
+ $filter_spec = array();
+ $result = preg_match('/\G\s*([A-Za-z][A-Za-z0-9_.]*)/u', $filter_expression, $match, PREG_OFFSET_CAPTURE);
+
+ if(!$result)
+ $this->context->raise('Filter name expected');
+
+ $position = $match[0][1];
+ $filter_name = $match[1][0];
+ $filter_spec = array('name' => $filter_name,
+ 'expression' => $filter_expression,
+ 'params' => array());
+
+ $params_expression = substr($filter_expression, strlen($filter_name));
+ if(!$params_expression)
+ {
+ $filters[] = $filter_spec;
+ continue;
+ }
+
+ if(strlen($params_expression))
+ {
+ $params_start_position = strpos($params_expression, ':');
+ if(($params_start_position === FALSE))
+ $this->context->raise('Unexpected symbol after filter name');
+ }
+
+ $params_str = substr($params_expression, $params_start_position + 1);
+ if (strlen($params_str) == 0)
+ $this->context->raise('Filter params expected after ":" symbol');
+
+ $filter_spec['params'] = $this->_parseParams($params_str);
+ $filters[] = $filter_spec;
+ }
+
+ return $filters;
+ }
+
+ protected function _parseParams($params_string)
+ {
+ $params = array();
+
+ $length = strlen($params_string);
+ $this->position = 0;
+ $this->text = $params_string;
+
+ do
+ {
+ $token = $this->getToken('/\G("|\'|,|[^\'",]+)/u');
+ if ($token === FALSE)
+ {
+ $filters_expressions[] = $this->text;
+ break;
+ }
+
+ if ($token == '"' || $token == "'")
+ {
+ $string = $this->getToken('/\G([^' . $token . ']*' . $token . ')/u');
+
+ if ($string === FALSE)
+ $this->context->raise("Expecting a string literal in filter param");
+ }
+ elseif($token == ',')
+ {
+ $params[] = substr($this->text, 0, $this->position - 1);
+ $this->text = substr($this->text, $this->position);
+ $length = strlen($this->text);
+ $this->position = 0;
+ }
+ }
+ while($this->position < $length);
+
+ //ensures the last param added
+ $params[] = substr($this->text, 0, $this->position );
+
+ return $params;
+ }
+
+ protected function _extractFiltersExpressions()
+ {
+ $length = strlen($this->text);
+ $this->position = 0;
+
+ $filters_expressions = array();
+ do
+ {
+ $token = $this->getToken('/\G("|\'|\||[^\'"\|]+)/u');
+ if ($token === FALSE)
+ {
+ $filters_expressions[] = $this->text;
+ break;
+ }
+
+ if ($token == '"' || $token == "'")
+ {
+ $string = $this->getToken('/\G([^' . $token . ']*)' . $token . ',?/u');
+
+ if ($string === FALSE)
+ $this->context->raise("Expecting a string literal in filter param");
+ }
+ elseif($token == '|')
+ {
+ $filters_expressions[] = substr($this->text, 0, $this->position - 1);
+ $this->text = substr($this->text, $this->position);
+ $length = strlen($this->text);
+ $this->position = 0;
+ }
+ }
+ while($this->position < $length);
+
+ //ensures the last filter expression added
+ $filters_expressions[] = substr($this->text, 0, $this->position );
+
+ return $filters_expressions;
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroNode.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroNode.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroNode.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroNode.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,254 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroNode.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroNode
+{
+ protected $id;
+ protected $children = array();
+ protected $parent;
+ /**
+ * @var lmbMacroSourceLocation
+ */
+ protected $location;
+
+ function __construct($location = null)
+ {
+ if($location)
+ $this->location = $location;
+ else
+ $this->location = new lmbMacroSourceLocation();
+ }
+
+ function setParent($parent)
+ {
+ $this->parent = $parent;
+ }
+
+ function getParent()
+ {
+ return $this->parent;
+ }
+
+ function getLocationInTemplate()
+ {
+ return $this->location;
+ }
+
+ function getTemplateFile()
+ {
+ return $this->location->getFile();
+ }
+
+ function getTemplateLine()
+ {
+ return $this->location->getLine();
+ }
+
+ function getId()
+ {
+ if($this->id)
+ return $this->id;
+
+ $this->id = self :: generateNewId();
+ return $this->id;
+ }
+
+ function setId($id)
+ {
+ $this->id = $id;
+ }
+
+ static function generateNewId()
+ {
+ static $counter = 1;
+ return 'id00' . $counter++;
+ }
+
+ function raise($error, $vars = array())
+ {
+ $vars['file'] = $this->location->getFile();
+ $vars['line'] = $this->location->getLine();
+ throw new lmbMacroException($error, $vars);
+ }
+
+ function addChild($child)
+ {
+ $child->parent = $this;
+ $this->children[] = $child;
+ }
+
+ function removeChild($id)
+ {
+ foreach($this->children as $key => $child)
+ {
+ if($child->getId() == $id)
+ {
+ unset($this->children[$key]);
+ return $child;
+ }
+ }
+ }
+
+ function getChildren()
+ {
+ return $this->children;
+ }
+
+ function removeChildren()
+ {
+ foreach($this->children as $child)
+ {
+ $child->removeChildren();
+ unset($child);
+ }
+ }
+
+ function getChild($id)
+ {
+ if($child = $this->findChild($id))
+ return $child;
+ else
+ $this->raise('Could not find component', array('id' => $id));
+ }
+
+ function findChild($id)
+ {
+ foreach($this->children as $child)
+ {
+ if($child->getId() == $id)
+ return $child;
+ else
+ {
+ if($result = $child->findChild($id))
+ return $result;
+ }
+ }
+ }
+
+ /**
+ * Sometimes it is useful to find node located in another tree branch, eg:
+ * <code>
+ * {{block}}{{some_tag id='tag1'}}{{/block}}
+ * {{block}}{{some_tag id='tag2'}}{{/block}}
+ * </code>
+ * in this case we can find tag1 tag from tag2 tag using findUpChild.
+ */
+ function findUpChild($id)
+ {
+ if($child = $this->findChild($id))
+ return $child;
+
+ if($this->parent)
+ return $this->parent->findUpChild($id);
+ }
+
+
+ function findChildByClass($class)
+ {
+ foreach($this->children as $child)
+ {
+ if(is_a($child, $class))
+ return $child;
+ else
+ {
+ if($result = $child->findChildByClass($class))
+ return $result;
+ }
+ }
+ }
+
+ function findChildrenByClass($class)
+ {
+ $ret = array();
+ foreach($this->children as $child)
+ {
+ if(is_a($child, $class))
+ $ret[] = $child;
+ else
+ {
+ $more_children = $child->findChildrenByClass($class);
+ if(count($more_children))
+ $ret = array_merge($ret, $more_children);
+ }
+ }
+ return $ret;
+ }
+
+ function findImmediateChildByClass($class)
+ {
+ foreach($this->children as $child)
+ {
+ if(is_a($child, $class))
+ return $child;
+ }
+ }
+
+ function findImmediateChildrenByClass($class)
+ {
+ $result = array();
+ foreach($this->children as $child)
+ {
+ if(is_a($child, $class))
+ $result[] = $child;
+ }
+ return $result;
+ }
+
+ function findParentByClass($class)
+ {
+ $parent = $this->parent;
+
+ while($parent && !is_a($parent, $class))
+ $parent = $parent->parent;
+
+ return $parent;
+ }
+
+ function preParse(){}
+
+ function generate($code_writer)
+ {
+ foreach($this->children as $child)
+ $child->generate($code_writer);
+ }
+
+ /**
+ * Checks that each immediate child of the current component has a unique ID
+ * amongst its siblings.
+ */
+ function checkChildrenIds()
+ {
+ $child_ids = array();
+ $checked_children = array();
+ foreach($this->getChildren() as $key => $child)
+ {
+ $id = $child->getId();
+ if(in_array($id, $child_ids))
+ {
+ $duplicate_child = $checked_children[$id];
+ $child->raise('Duplicate "id" attribute',
+ array('id' => $id,
+ 'duplicate_node_file' => $duplicate_child->getTemplateFile(),
+ 'duplicate_node_line' => $duplicate_child->getTemplateLine()));
+ }
+ else
+ {
+ $child_ids[] = $id;
+ $checked_children[$id] = $child;
+ }
+ }
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroOutputExpressionNode.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroOutputExpressionNode.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroOutputExpressionNode.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroOutputExpressionNode.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,33 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroTag.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroOutputExpressionNode extends lmbMacroNode
+{
+ protected $expression;
+
+ function __construct($location, $expression)
+ {
+ $this->expression = $expression;
+
+ parent :: __construct($location);
+ }
+
+ function generate($code)
+ {
+ $this->expression->preGenerate($code);
+ $code->writePHP('echo ' . $this->expression->getValue() . ";\n");
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroParser.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroParser.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroParser.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroParser.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,147 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroParser.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroParser implements lmbMacroTokenizerListener
+{
+ protected $active_parsing_state;
+
+ protected $tag_parsing_state;
+
+ /**
+ * @var lmbMacroTreebuilder
+ */
+ protected $tree_builder;
+
+ /**
+ * @var lmbMacroTemplateLocator
+ */
+ protected $template_locator;
+
+ protected $tokenizer;
+
+ function __construct($tree_builder, $template_locator, $tag_dictionary)
+ {
+ $this->tokenizer = new lmbMacroTokenizer($this);
+ $this->preprocessor = new lmbMacroPreprocessor();
+
+ $this->tree_builder = $tree_builder;
+ $this->template_locator = $template_locator;
+
+ $this->tag_parsing_state = $this->_createTagParsingState($tag_dictionary);
+ }
+
+ function getCurrentLocation()
+ {
+ return $this->tokenizer->getCurrentLocation();
+ }
+
+ protected function _createTagParsingState($tag_dictionary)
+ {
+ return new lmbMacroTagParsingState($this, $this->tree_builder, $tag_dictionary);
+ }
+
+ /**
+ * Used to parse the source template.
+ * Initially invoked by the CompileTemplate function,
+ * the first component argument being a root node.
+ */
+ function parse($file_name, $root_node)
+ {
+ $source_file_path = $this->template_locator->locateSourceTemplate($file_name);
+
+ if(empty($source_file_path))
+ throw new lmbMacroException('Template source file not found', array('file_name' => $file_name));
+
+ $tags_before_parse = $this->tree_builder->getExpectedTagCount();
+
+ $this->tree_builder->setCursor($root_node);
+
+ $this->changeToTagParsingState();
+
+ $this->setTemplateLocator($this->template_locator);
+
+ $content = file_get_contents($source_file_path);
+
+ $this->preprocessor->process($content);
+
+ $this->tokenizer->parse($content, $source_file_path);
+
+ if($tags_before_parse != $this->tree_builder->getExpectedTagCount())
+ {
+ $location = $this->tree_builder->getExpectedTagLocation();
+ throw new lmbMacroException('Missing close tag',
+ array('tag' => $this->tree_builder->getExpectedTag(),
+ 'file' => $location->getFile(),
+ 'line' => $location->getLine()));
+ }
+ }
+
+ function getActiveParsingState()
+ {
+ return $this->active_parsing_state;
+ }
+
+ function changeToTagParsingState()
+ {
+ $this->active_parsing_state = $this->tag_parsing_state;
+ }
+
+ function setTemplateLocator($template_locator)
+ {
+ $this->tag_parsing_state->setTemplateLocator($template_locator);
+ }
+
+ function startElement($tag, $attrs)
+ {
+ $this->active_parsing_state->startElement($tag, $attrs);
+ }
+
+ function endElement($tag)
+ {
+ $this->active_parsing_state->endElement($tag);
+ }
+
+ function emptyElement($tag, $attrs)
+ {
+ $this->active_parsing_state->emptyElement($tag, $attrs);
+ }
+
+ function characters($text)
+ {
+ $this->active_parsing_state->characters($text);
+ }
+
+ function php($text)
+ {
+ $this->active_parsing_state->php($text);
+ }
+
+ function unexpectedEOF($text)
+ {
+ $this->active_parsing_state->unexpectedEOF($text);
+ }
+
+ function invalidEntitySyntax($text)
+ {
+ $this->active_parsing_state->invalidEntitySyntax($text);
+ }
+
+ function invalidAttributeSyntax($text)
+ {
+ $this->active_parsing_state->invalidAttributeSyntax($text);
+ }
+}
+
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroPassiveTag.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroPassiveTag.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroPassiveTag.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroPassiveTag.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,28 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroPassiveTag.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroPassiveTag extends lmbMacroTag
+{
+
+ function generate($code_writer)
+ {
+ }
+
+ function generateNow($code_writer)
+ {
+ parent :: generate($code_writer);
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroPreprocessor.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroPreprocessor.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroPreprocessor.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroPreprocessor.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,25 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroPreprocessor
+ *
+ * @package macro
+ * @version $Id$
+ */
+
+class lmbMacroPreprocessor
+{
+ function process(&$contents)
+ {
+ $contents = str_replace('<?=', '<?php echo ', $contents);
+ $contents = preg_replace('~<\?(?!php|=)~', '<?php ', $contents);
+ $contents = str_replace('$#', '$this->', $contents);
+ }
+}
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroTag.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroTag.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroTag.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroTag.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,228 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroTag.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroTag extends lmbMacroNode
+{
+ protected $tag;
+ protected $tag_info;
+ protected $has_closing_tag = true;
+ protected $attributes = array();
+
+ function __construct($location, $tag, $tag_info)
+ {
+ $this->tag = $tag;
+ $this->tag_info = $tag_info;
+
+ parent :: __construct($location);
+ }
+
+ function getTag()
+ {
+ return $this->tag;
+ }
+
+ function getHasClosingTag()
+ {
+ return $this->has_closing_tag;
+ }
+
+ function setHasClosingTag($flag)
+ {
+ return $this->has_closing_tag = $flag;
+ }
+
+ function getId()
+ {
+ if($this->id)
+ return $this->id;
+
+ if($id = $this->get('id'))
+ $this->id = $id;
+ else
+ $this->id = self :: generateNewId();
+
+ return $this->id;
+ }
+
+ function getEscapedId()
+ {
+ $id = $this->getId();
+ return "'" . $id . "'";
+ }
+
+ function get($name)
+ {
+ if(!array_key_exists(strtolower($name), $this->attributes))
+ return;
+
+ return $this->attributes[strtolower($name)]->getValue();
+ }
+
+ function getEscaped($name)
+ {
+ if(!$this->has($name))
+ return;
+
+ $value = $this->get($name);
+ if($this->isDynamic($name))
+ return $value;
+ else
+ return "'" . $value . "'";
+ }
+
+ /**
+ * Should be used for testing purposes only since not parses $value for any output expressions
+ */
+ function set($name, $value)
+ {
+ $this->attributes[strtolower($name)] = new lmbMacroTagAttribute($name, $value);
+ }
+
+ function add($attribute)
+ {
+ $this->attributes[strtolower($attribute->getName())] = $attribute;
+ }
+
+ function has($name)
+ {
+ return array_key_exists(strtolower($name), $this->attributes);
+ }
+
+ function hasConstant($name)
+ {
+ return $this->has($name) && !$this->attributes[strtolower($name)]->isDynamic();
+ }
+
+ function isDynamic($name)
+ {
+ return !$this->hasConstant($name);
+ }
+
+ function getConstantAttributes()
+ {
+ $res = array();
+ foreach($this->attributes as $key => $attr)
+ {
+ if(!$attr->isDynamic())
+ $res[$attr->getName()] = $attr->getValue();
+ }
+ return $res;
+ }
+
+ /**
+ * Return the value of a boolean attribute as a boolean.
+ * ATTRIBUTE=ANYTHING (true)
+ * ATTRIBUTE=(false|N|NA|NO|NONE|0) (false)
+ * ATTRIBUTE (true)
+ * (attribute unspecified) (default)
+ */
+ function getBool($name, $default = false)
+ {
+ if(!isset($this->attributes[strtolower($name)]))
+ return $default;
+
+ return self :: getBooleanValue($this->attributes[strtolower($name)]->getValue());
+ }
+
+ static function getBooleanValue($value)
+ {
+ if(!$value)
+ return $value;
+
+ switch(strtoupper($value))
+ {
+ case 'FALSE':
+ case 'N':
+ case 'NO':
+ case 'NONE':
+ case 'NA':
+ case '0':
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ function generate($code_writer)
+ {
+ $this->_preGenerataAttributes($code_writer);
+
+ $this->_generateBeforeContent($code_writer);
+
+ $this->_generateContent($code_writer);
+
+ $this->_generateAfterContent($code_writer);
+ }
+
+ // children can override this method if they need to generate some code around content in simple cases
+ // but it's recommended to override generateBeforeContent() and generateAfterContent() instead.
+ protected function _generateContent($code_writer)
+ {
+ parent :: generate($code_writer);
+ }
+
+ protected function _generateBeforeContent($code_writer)
+ {
+ }
+
+ protected function _generateAfterContent($code_writer)
+ {
+ }
+
+ protected function _preGenerataAttributes($code_writer)
+ {
+ foreach($this->attributes as $attribute)
+ $attribute->preGenerate($code_writer);
+ }
+
+ function remove($attrib)
+ {
+ unset($this->attributes[strtolower($attrib)]);
+ }
+
+ function raise($error, $vars = array())
+ {
+ $vars['tag'] = $this->tag;
+ parent :: raise($error, $vars);
+ }
+
+ function raiseRequiredAttribute($attribute_name)
+ {
+ $this->raise('Missing required attribute', array('attribute' => $attribute_name));
+ }
+
+ function preParse($compiler)
+ {
+ foreach($this->tag_info->getRequiredAttributes() as $attr_name)
+ {
+ if(!$this->has($attr_name))
+ $this->raiseRequiredAttribute($attr_name);
+ }
+
+ if($this->tag_info->isRestrictSelfNesting() && $parent = $this->findParentByClass(get_class($this)))
+ $this->raise('Tag cannot be nested within the same tag',
+ array('same_tag_file' => $parent->getTemplateFile(),
+ 'same_tag_line' => $parent->getTemplateLine()));
+
+ if(($parent_class = $this->tag_info->getParentClass()) &&
+ !$parent = $this->findParentByClass($parent_class))
+ {
+ $this->raise('Tag must be enclosed by a proper parent tag',
+ array('required_parent_tag_class' => $parent_class));
+
+ }
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroTagAttribute.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroTagAttribute.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroTagAttribute.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroTagAttribute.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,76 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * Used to store complex expressions like "{$var1}_my_{$var2}" found inside tag attributes
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroTagAttribute implements lmbMacroExpressionInterface
+{
+ protected $name;
+ protected $expressions = array();
+ protected $raw_string = '';
+
+ function __construct($name, $value = null)
+ {
+ $this->name = $name;
+
+ if($value)
+ $this->raw_string .= $value;
+ }
+
+ function getName()
+ {
+ return $this->name;
+ }
+
+ function addTextFragment($text)
+ {
+ $this->raw_string .= $text;
+ }
+
+ function addExpressionFragment($expression)
+ {
+ $this->raw_string .= '%s';
+ $this->expressions[] = $expression;
+ }
+
+ function preGenerate($code_writer)
+ {
+ foreach($this->expressions as $fragment)
+ $fragment->preGenerate($code_writer);
+ }
+
+ function isDynamic()
+ {
+ return (bool)sizeof($this->expressions) || (strpos($this->raw_string, '$') === 0);
+ }
+
+ function getValue()
+ {
+ // simple case
+ if(!sizeof($this->expressions))
+ return $this->raw_string;
+
+ $res = 'sprintf(\'' . $this->raw_string. '\',';
+
+ $separator = '';
+ foreach($this->expressions as $expressions)
+ {
+ $res .= $separator . $expressions->getValue();
+ $separator = ',';
+ }
+
+ $res .= ')';
+ return $res;
+ }
+}
+
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroTagAttributeBlockAnalizerListener.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroTagAttributeBlockAnalizerListener.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroTagAttributeBlockAnalizerListener.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroTagAttributeBlockAnalizerListener.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,39 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroTagAttributeBlockAnalizerListener.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroTagAttributeBlockAnalizerListener implements lmbMacroBlockAnalizerListener
+{
+ protected $attribute;
+ protected $tag_node;
+ protected $filter_dictionary;
+
+ function __construct($attribute, $tag_node)
+ {
+ $this->attribute = $attribute;
+ $this->tag_node = $tag_node;
+ }
+
+ function addLiteralFragment($text)
+ {
+ $this->attribute->addTextFragment($text);
+ }
+
+ function addExpressionFragment($text)
+ {
+ $expression = new lmbMacroExpression($text);
+ $this->attribute->addExpressionFragment($expression);
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroTagDictionary.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroTagDictionary.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroTagDictionary.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroTagDictionary.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,121 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroTagDictionary.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroTagDictionary
+{
+ protected $info = array();
+ static protected $instance;
+
+ static function instance()
+ {
+ if(self :: $instance)
+ return self :: $instance;
+
+ self :: $instance = new lmbMacroTagDictionary();
+ return self :: $instance;
+ }
+
+ function load(lmbMacroConfig $config)
+ {
+ if(!$config->isForceScan() && $this->_loadCache($config))
+ return;
+
+ $config_scan_dirs = $config->getTagsScanDirectories();
+ $real_scan_dirs = array();
+
+ foreach($config_scan_dirs as $dir)
+ {
+ foreach($this->_getThisAndImmediateDirectories($dir) as $item)
+ $real_scan_dirs[] = $item;
+ }
+
+ foreach($real_scan_dirs as $scan_dir)
+ {
+ foreach(lmb_glob($scan_dir . '/*.tag.php') as $file)
+ $this->registerFromFile($file);
+ }
+
+ $this->_saveCache($config);
+ }
+
+ function _getThisAndImmediateDirectories($dir)
+ {
+ $dirs = array();
+ foreach(lmb_glob("$dir/*") as $item) {
+ if($item{0} != '.' && is_dir($item))
+ $dirs[] = $item;
+ }
+
+ $dirs[] = $dir;
+
+ return $dirs;
+ }
+
+ protected function _loadCache(lmbMacroConfig $config)
+ {
+ $cache_file = $config->getCacheDir() . '/tags.cache';
+ if(!file_exists($cache_file))
+ return false;
+
+ $info = @unserialize(file_get_contents($cache_file));
+ if($info === false || !is_array($info))
+ return false;
+
+ $this->info = $info;
+
+ return true;
+ }
+
+ protected function _saveCache(lmbMacroConfig $config)
+ {
+ $cache_file = $config->getCacheDir() . '/tags.cache';
+ lmbFs :: safeWrite($cache_file, serialize($this->info));
+ }
+
+ function register($tag_info)
+ {
+ $names = array(strtolower($tag_info->getTag()));
+
+ $aliases = $tag_info->getAliases();
+ if(count($aliases))
+ {
+ $aliases = array_map('strtolower', $aliases);
+ $names = array_merge($names, $aliases);
+ }
+
+ foreach($names as $tag_name)
+ {
+ if(isset($this->info[$tag_name]))
+ return;
+
+ $this->info[$tag_name] = $tag_info;
+ }
+ }
+
+ function registerFromFile($file)
+ {
+ $infos = lmbMacroAnnotationParser :: extractFromFile($file, 'lmbMacroTagInfo');
+ foreach($infos as $info)
+ $this->register($info, $file);
+ }
+
+ function findTagInfo($tag)
+ {
+ $tag = strtolower($tag);
+ if(isset($this->info[$tag]))
+ return $this->info[$tag];
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroTagInfo.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroTagInfo.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroTagInfo.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroTagInfo.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,156 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroTagInfo.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroTagInfo
+{
+ protected $tag;
+ protected $class;
+ protected $file;
+ protected $aliases = array();
+ protected $req_attributes = array();
+ protected $parent_class;
+ protected $restrict_self_nesting = false;
+ protected $require_endtag = true;
+
+ function __construct($tag, $class, $require_endtag = true)
+ {
+ $this->tag = $tag;
+ $this->class = $class;
+ $this->require_endtag = $require_endtag;
+ }
+
+ static function createByAnnotations($file, $class, $annotations)
+ {
+ if(!isset($annotations['tag']))
+ throw new lmbMacroException("@tag annotation is missing for class '$class'");
+
+ $tag = $annotations['tag'];
+ $info = new lmbMacroTagInfo($tag, $class);
+
+ $info->setFile($file);
+
+ if(isset($annotations['forbid_end_tag']))
+ $info->setForbidEndtag(true);
+
+ if(isset($annotations['restrict_self_nesting']))
+ $info->setRestrictSelfNesting(true);
+
+ if(isset($annotations['parent_tag_class']))
+ $info->setParentClass(trim($annotations['parent_tag_class']));
+
+ if(isset($annotations['req_attributes']))
+ {
+ $req_attributes = explode(',' , $annotations['req_attributes']);
+ $req_attributes = array_map('trim', $req_attributes);
+ $info->setRequiredAttributes($req_attributes);
+ }
+
+ if(isset($annotations['aliases']))
+ {
+ $filter_aliases = explode(',' , $annotations['aliases']);
+ $filter_aliases = array_map('trim', $filter_aliases);
+ $info->setAliases($filter_aliases);
+ }
+
+ return $info;
+ }
+
+ function getTag()
+ {
+ return $this->tag;
+ }
+
+ function getClass()
+ {
+ return $this->class;
+ }
+
+ function setFile($file)
+ {
+ $this->file = $file;
+ }
+
+ function getFile()
+ {
+ return $this->file;
+ }
+
+ function setForbidEndtag($flag = true)
+ {
+ $this->require_endtag = !$flag;
+ }
+
+ function isEndtagForbidden()
+ {
+ return !$this->require_endtag;
+ }
+
+ function setRequiredAttributes($attributes)
+ {
+ $this->req_attributes = $attributes;
+ }
+
+ function getRequiredAttributes()
+ {
+ return $this->req_attributes;
+ }
+
+ function setParentClass($parent_tag_class)
+ {
+ $this->parent_class = $parent_tag_class;
+ }
+
+ function getParentClass()
+ {
+ return $this->parent_class;
+ }
+
+ function setAliases($aliases)
+ {
+ $this->aliases = $aliases;
+ }
+
+ function getAliases()
+ {
+ return $this->aliases;
+ }
+
+ function setRestrictSelfNesting($flag = true)
+ {
+ $this->restrict_self_nesting = $flag;
+ }
+
+ function isRestrictSelfNesting()
+ {
+ return $this->restrict_self_nesting;
+ }
+
+ function setForbidParsing($flag = true)
+ {
+ $this->forbid_parsing = $flag;
+ }
+
+ function isParsingForbidden()
+ {
+ return $this->forbid_parsing;
+ }
+
+ function load()
+ {
+ if(!class_exists($this->class) && isset($this->file))
+ require_once($this->file);
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroTagParsingState.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroTagParsingState.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroTagParsingState.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroTagParsingState.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,156 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroTagParsingState.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroTagParsingState extends lmbMacroBaseParsingState implements lmbMacroTokenizerListener
+{
+ protected $tag_dictionary;
+
+ function __construct(lmbMacroParser $parser, lmbMacroTreeBuilder $tree_builder, lmbMacroTagDictionary $tag_dictionary)
+ {
+ parent :: __construct($parser, $tree_builder);
+ $this->tag_dictionary = $tag_dictionary;
+ }
+
+ function startElement($tag, $attrs)
+ {
+ $location = $this->parser->getCurrentLocation();
+
+ $lower_attributes = $this->normalizeAttributes($attrs, $location);
+
+ if(!$tag_info = $this->tag_dictionary->findTagInfo($tag))
+ throw new lmbMacroException("Tag '$tag' not found in dictionary");
+
+ if($tag_info->isEndTagForbidden())
+ {
+ $tag_node = $this->buildTagNode($tag_info, $tag, $attrs);
+ $tag_node->setHasClosingTag(false);
+ $this->tree_builder->pushNode($tag_node); // for cases like {{include}} we do pushNode() and popNode() here.
+ $this->tree_builder->popNode();
+ }
+ else
+ {
+ $this->tree_builder->pushExpectedTag($tag, $location);
+ $tag_node = $this->buildTagNode($tag_info, $tag, $attrs, $self_closed_tag = false);
+ $result = $this->tree_builder->pushNode($tag_node);
+ }
+ }
+
+ function endElement($tag)
+ {
+ if(!$tag_info = $this->tag_dictionary->findTagInfo($tag))
+ throw new lmbMacroException("Tag '$tag' not found in dictionary");
+
+ $location = $this->parser->getCurrentLocation();
+
+ if($tag_info->isEndTagForbidden())
+ {
+ throw new lmbMacroException('Closing tag forbidden',
+ array('tag' => $tag_info->getTag(),
+ 'file' => $location->getFile(),
+ 'line' => $location->getLine()));
+ }
+
+ $this->tree_builder->popExpectedTag($tag, $location);
+ $this->tree_builder->popNode();
+ }
+
+ function emptyElement($tag, $attrs)
+ {
+ $location = $this->parser->getCurrentLocation();
+ $lower_attributes = $this->normalizeAttributes($attrs, $location);
+
+ if(!$tag_info = $this->tag_dictionary->findTagInfo($tag))
+ throw new lmbMacroException("Tag '$tag' not found in dictionary");
+ $tag_info->load();
+
+ $tag_node = $this->buildTagNode($tag_info, $tag, $attrs);
+ $tag_node->setHasClosingTag(false);
+ $this->tree_builder->pushNode($tag_node); // for cases like {{include}} we do pushNode() and popNode() here.
+ $this->tree_builder->popNode();
+ }
+
+ /**
+ * Builds a component, adding attributes
+ * @param lmbMacroTagInfo
+ * @param string XML tag name of component
+ * @param array attributes for tag
+ * @param boolean whether the tag has contents
+ * @return lmbMacroNode
+ */
+ function buildTagNode($tag_info, $tag, $attrs)
+ {
+ $tag_node = $this->_createTagNode($tag_info, $tag);
+ $this->_addAttributesToTagNode($tag_node, $attrs);
+ return $tag_node;
+ }
+
+ protected function _addAttributesToTagNode($tag_node, $attrs)
+ {
+ foreach($attrs as $name => $value)
+ {
+ if($value === null)
+ {
+ $location = $this->parser->getCurrentLocation();
+ throw new lmbMacroException('Attribute should have a value',
+ array('file' => $location->getFile(),
+ 'line' => $location->getLine(),
+ 'tag' => $tag_node->getTag(),
+ 'attribute' => $name));
+ }
+
+ $attribute = new lmbMacroTagAttribute($name);
+ $listener = new lmbMacroTagAttributeBlockAnalizerListener($attribute, $tag_node);
+
+ $analizer = new lmbMacroBlockAnalizer();
+ $analizer->parse($value, $listener);
+
+ $tag_node->add($attribute);
+ }
+ }
+
+ protected function _createTagNode($tag_info, $tag)
+ {
+ $class = $tag_info->getClass();
+ require_once($tag_info->getFile());
+ $tag_node = new $class($this->parser->getCurrentLocation(), $tag, $tag_info);
+ return $tag_node;
+ }
+
+ function normalizeAttributes($attrs)
+ {
+ return array_change_key_case($attrs, CASE_LOWER);
+ }
+
+ function characters($text)
+ {
+ $this->tree_builder->addContent($text, $this->parser->getCurrentLocation());
+ }
+
+ function php($text)
+ {
+ $this->tree_builder->addTextNode($text);
+ }
+
+ function unexpectedEOF($text)
+ {
+ $this->tree_builder->addTextNode($text);
+ }
+
+ function invalidEntitySyntax($text)
+ {
+ $this->tree_builder->addTextNode($text);
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroTemplateExecutor.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroTemplateExecutor.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroTemplateExecutor.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroTemplateExecutor.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,81 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroTemplateExecutor.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroTemplateExecutor
+{
+ //we add prefixes in order to avoid possible conflict
+ //since variables are added directly
+ protected $__config;
+ protected $__context;
+
+ function __construct(lmbMacroConfig $config = null, $vars = array())
+ {
+ $this->__config = $config ? $config : new lmbMacroConfig();
+ $this->setVars($vars);
+ }
+
+ //overridden in children
+ protected function _init(){}
+
+ function setVars($vars)
+ {
+ foreach($vars as $name => $value)
+ $this->$name = $value;
+ }
+
+ function set($name, $value)
+ {
+ $this->$name = $value;
+ }
+
+ function setContext(lmbMacroTemplateExecutor $context)
+ {
+ $this->__context = $context;
+ }
+
+ function __get($name)
+ {
+ //we can have parent variable context which should be consulted for all missing variables
+ //actually, it's quite a dirty hack for a deeper problem which should be addressed later
+ if($this->__context)
+ return $this->__context->$name;
+
+ //we definitely want to supress warnings, make it some sort of a NullObject?
+ return '';
+ }
+
+ function render($args = array())
+ {
+ extract($args);
+ }
+
+ function includeTemplate($file, $vars = array())
+ {
+ $template = new lmbMacroTemplate($file, $this->__config);
+ $template->setVars(get_object_vars($this));//global template vars
+ echo $template->render($vars);//local template vars
+ }
+
+ function wrapTemplate($file, $slots_handlers)
+ {
+ $template = new lmbMacroTemplate($file, $this->__config);
+ $template->setVars(get_object_vars($this));//global template vars
+ foreach($slots_handlers as $name => $handler)
+ $template->set('__slot_handler_' . $name, $handler);
+ $template->setChildExecutor($this);//from now we consider the wrapper to be a master variable context
+ echo $template->render();
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroTextNode.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroTextNode.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroTextNode.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroTextNode.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,38 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroTextNode.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroTextNode extends lmbMacroNode
+{
+ protected $contents;
+
+ function __construct($location, $text)
+ {
+ parent :: __construct($location);
+ $this->contents = $text;
+ }
+
+ function generate($code_writer)
+ {
+ $code_writer->writeHtml($this->contents);
+ parent :: generate($code_writer);
+ }
+
+ function getText()
+ {
+ return $this->contents;
+ }
+}
+
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroTokenizer.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroTokenizer.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroTokenizer.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroTokenizer.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,312 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroTokenizer.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroTokenizer
+{
+ protected $publicId;
+ protected $observer;
+ protected $rawtext;
+ protected $position;
+ protected $length;
+
+ function __construct($observer)
+ {
+ $this->observer = $observer;
+ }
+
+ function getLineNumber()
+ {
+ return 1 + substr_count(substr($this->rawtext, 0, $this->position), "\n");
+ }
+
+ function getCurrentLocation()
+ {
+ return new lmbMacroSourceLocation($this->getPublicId(), $this->getLineNumber());
+ }
+
+ function getPublicId()
+ {
+ return $this->publicId;
+ }
+
+ /**
+ * Moves the position forward past any whitespace characters
+ */
+ function ignoreWhitespace()
+ {
+ while($this->position < $this->length &&
+ strpos(" \n\r\t", $this->rawtext{$this->position}) !== false)
+ $this->position++;
+ }
+
+ protected function _parseUntilTagStart($start)
+ {
+ do
+ {
+ $php_start = strpos($this->rawtext, '<?php', $start);
+ $tag_start = strpos($this->rawtext, '{{', $start);
+
+ //no php found
+ if($php_start === false)
+ {
+ //tag candidate found
+ if($tag_start !== false)
+ {
+ //add preceding characters
+ if($tag_start > $start)
+ $this->observer->characters(substr($this->rawtext, $start, $tag_start - $start));
+ return $tag_start;
+ }
+ //no tags at all
+ else
+ {
+ //add preceding characters
+ if($start != $this->length)
+ $this->observer->characters(substr($this->rawtext, $start, $this->length - $start));
+ return null;
+ }
+ }
+ //php found
+ else
+ {
+ $php_end = strpos($this->rawtext, '?>', $start);
+ //php end found
+ if($php_end !== false)
+ {
+ //at the same time tag found and it's not inside php
+ if($tag_start !== false && $tag_start < $php_start)
+ {
+ //add preceding characters
+ if($start < $tag_start)
+ $this->observer->characters(substr($this->rawtext, $start, $tag_start - $start));
+ return $tag_start;
+ }
+ //extract php block
+ else
+ {
+ //add preceding characters
+ if($start < $php_start)
+ $this->observer->characters(substr($this->rawtext, $start, $php_start - $start));
+ $this->observer->php(substr($this->rawtext, $php_start, $php_end - $php_start + 2));
+ $start = $php_end + 2;
+ }
+ }
+ //no php end found, everything is php then
+ else
+ {
+ $this->observer->php(substr($this->rawtext, $php_start));
+ return null;
+ }
+
+ }
+ }while($start < $this->length);
+ return null;
+ }
+
+ /**
+ * Begins the parsing operation, setting up any decorators, depending on
+ * parse options invoking _parse() to execute parsing
+ */
+ function parse($data, $publicId = null)
+ {
+ $this->rawtext = $data;
+ $this->length = strlen($data);
+ $this->position = 0;
+ $this->publicId = $publicId;
+
+ do
+ {
+ $start = $this->position;
+
+ $this->position = $this->_parseUntilTagStart($start);
+ if($this->position === null)
+ return;
+
+ $this->position += 2; // ignore '{{' string
+ 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->rawtext{$this->position+1} == '}'))
+ $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 += 2; // ignore '}}' string
+ 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();
+
+ //tag attributes
+ 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;
+ }
+
+ $attribute_name = substr($this->rawtext, $start, $this->position - $start);
+ $attribute_value = null;
+
+ $this->ignoreWhitespace();
+ if($this->position >= $this->length)
+ {
+ $this->observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+
+ if($this->rawtext{$this->position} == '=')
+ {
+ $attribute_value = "";
+
+ $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;
+ }
+
+ $attribute_value = 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(substr($this->rawtext, $this->position));
+ }
+ 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;
+ }
+ $attribute_value = substr($this->rawtext, $start, $this->position - $start);
+ }
+ }
+
+ $attributes[$attribute_name] = $attribute_value;
+
+ $this->ignoreWhitespace();
+ }
+
+ if($this->position >= $this->length)
+ {
+ $this->observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+
+ //self closing tag check
+ if($this->rawtext{$this->position} == '/' && $this->rawtext{$this->position + 1} == '}')
+ {
+ $this->position += 2;
+ 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 - 2));
+ break;
+ }
+
+ $this->observer->invalidEntitySyntax(substr($this->rawtext, $element_pos - 2,
+ $this->position - $element_pos + 2));
+ $this->position += 1;
+ break;
+ }
+ $this->observer->emptyElement($tag, $attributes);
+ }
+ else
+ {
+ $this->observer->startElement($tag, $attributes);
+ //skipping }
+ $this->position += 1;
+ }
+
+ $this->position += 1;
+ break;
+ }
+ }
+ while($this->position < $this->length);
+ }
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroTokenizerListener.interface.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroTokenizerListener.interface.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroTokenizerListener.interface.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroTokenizerListener.interface.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,28 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * interface lmbMacroTokenizerListener.
+ *
+ * @package macro
+ * @version $Id$
+ */
+interface lmbMacroTokenizerListener
+{
+ function startElement($tag_name, $attrs);
+ function endElement($tag_name);
+ function emptyElement($tag_name, $attrs);
+ function characters($data);
+ function php($data);
+ function unexpectedEOF($data);
+ function invalidEntitySyntax($data);
+ function invalidAttributeSyntax($data);
+ function setTemplateLocator($locator);
+}
+
Copied: 3.x/trunk/limb/macro/src/compiler/lmbMacroTreeBuilder.class.php (from rev 6555, 3.x/trunk/limb/macro/src/lmbMacroTreeBuilder.class.php)
===================================================================
--- 3.x/trunk/limb/macro/src/compiler/lmbMacroTreeBuilder.class.php (rev 0)
+++ 3.x/trunk/limb/macro/src/compiler/lmbMacroTreeBuilder.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -0,0 +1,188 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
+ * @license LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * Acts on the root lmbMacroNode in response to events within the lmbMacroParser
+ *
+ * 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().
+ * @package macro
+ * @version $Id$
+ */
+
+class lmbMacroTreeBuilder
+{
+ protected $compiler;
+ protected $node;
+
+ protected $filter_dictionary;
+ /**
+ * Stack of tags pushed onto the tree builder
+ */
+ var $expected_tags = array();
+
+ function __construct($compiler)
+ {
+ $this->compiler = $compiler;
+ }
+
+ /**
+ * Returns the current node
+ */
+ function getCursor()
+ {
+ return $this->node;
+ }
+
+ /**
+ * Sets the cursor (the current working node) of the tree builder
+ */
+ function setCursor($node)
+ {
+ $this->node = $node;
+ }
+
+ /**
+ * Begins a node's build phase in relation to the node tree.
+ * Adds a node to the tree, then makes that node the 'cursor'.
+ */
+ function pushNode($node)
+ {
+ $this->node->addChild($node);
+ $this->setCursor($node);
+ return $this->node->preParse($this->compiler);
+ }
+
+ /**
+ * Adds a node to the tree, without descending into it.
+ * This begins and finishes the node's composition
+ */
+ function addNode($node)
+ {
+ $node->preParse($this->compiler);
+ $this->node->addChild($node);
+ }
+
+ function addTextNode($text)
+ {
+ $this->addNode(new lmbMacroTextNode(null, $text));
+ }
+
+ function addContent($text, $location)
+ {
+ $listener = new lmbMacroContentBlockAnalizerListener($this, $location, $this->filter_dictionary);
+ $analizer = new lmbMacroBlockAnalizer();
+ $analizer->parse($text, $listener);
+ }
+
+ /**
+ * Ends a node's build phase in relation to the tree.
+ * Checks child server ids and moves the 'cursor' up the tree to the parent
+ * node.
+ */
+ function popNode()
+ {
+ $this->node->checkChildrenIds();
+ $this->setCursor($this->node->getParent());
+ }
+
+ function pushExpectedTag($tag, $location = null)
+ {
+ array_push($this->expected_tags, array($tag, $location));
+ }
+
+ /**
+ * Sets the cursor to a new position, and pushes the old cursor onto the
+ * expected tags stack.
+ * @see popExpectedTag
+ */
+ function pushCursor($newPosition, $location)
+ {
+ // use of array() is to preserve reference from array_pop()
+ array_push($this->expected_tags, array($this->node, $location));
+ $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 node, then the cursor is
+ * restored to that, and popExpectedTag is called again.
+ */
+ function popExpectedTag($tag, $location)
+ {
+ if(!$expected_tag_item = array_pop($this->expected_tags))
+ {
+ throw new lmbMacroException('Lonely closing tag', array('tag' => $tag,
+ 'file' => $location->getFile(),
+ 'line' => $location->getLine()));
+ }
+
+ // if we have a node on the stack, restore the cursor to that, and
+ // pop the stack again
+ if(is_object($expected_tag_item[0]))
+ {
+ $this->node = $expected_tag_item[0];
+ return $this->popExpectedTag($tag, $location);
+ }
+
+ $expected_tag = $expected_tag_item[0];
+ $expected_location = $expected_tag_item[1];
+
+ if(strcasecmp($expected_tag, $tag) === 0)
+ return $tag;
+
+ throw new lmbMacroException('Unexpected closing tag',
+ array('file' => $location->getFile(),
+ 'tag' => $tag,
+ 'line' => $location->getLine(),
+ 'expected_tag' => $expected_tag,
+ 'expected_file' => $expected_location->getFile(),
+ 'expected_line' => $expected_location->getLine()));
+ }
+
+ /**
+ * Return the size of the expected tags stack
+ */
+ function getExpectedTagCount()
+ {
+ return count($this->expected_tags);
+ }
+
+ /**
+ * Returns the current expected tag
+ */
+ function getExpectedTag()
+ {
+ // Returns the tagname of the first non-node item on the stack
+ $item = end($this->expected_tags);
+ while($item && !is_string($item[0]))
+ $item = prev($this->expected_tags);
+ return $item ? $item[0] : false;
+ }
+
+ function getExpectedTagLocation()
+ {
+ $item = end($this->expected_tags);
+ return $item[1];
+ }
+
+ function getFilterDictionary()
+ {
+ return $this->compiler->getFilterDictionary();
+ }
+}
+
Modified: 3.x/trunk/limb/macro/src/filters/date.filter.php
===================================================================
--- 3.x/trunk/limb/macro/src/filters/date.filter.php 2007-12-03 11:44:06 UTC (rev 6560)
+++ 3.x/trunk/limb/macro/src/filters/date.filter.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -6,7 +6,6 @@
* @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
* @license LGPL http://www.gnu.org/copyleft/lesser.html
*/
-lmb_require('limb/macro/src/lmbMacroFilter.class.php');
/**
* class lmbMacroDateFilter.
Modified: 3.x/trunk/limb/macro/src/filters/lmbMacroPhpFunctionBasedFilter.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/filters/lmbMacroPhpFunctionBasedFilter.class.php 2007-12-03 11:44:06 UTC (rev 6560)
+++ 3.x/trunk/limb/macro/src/filters/lmbMacroPhpFunctionBasedFilter.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -6,7 +6,6 @@
* @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
* @license LGPL http://www.gnu.org/copyleft/lesser.html
*/
-lmb_require('limb/macro/src/lmbMacroFilter.class.php');
/**
* class lmbMacroStrToUpperFilter.
Deleted: 3.x/trunk/limb/macro/src/lmbMacroAnnotationParser.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroAnnotationParser.class.php 2007-12-03 11:44:06 UTC (rev 6560)
+++ 3.x/trunk/limb/macro/src/lmbMacroAnnotationParser.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -1,63 +0,0 @@
-<?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com
- * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
- * @license LGPL http://www.gnu.org/copyleft/lesser.html
- */
-lmb_require('limb/core/src/lmbPHPTokenizer.class.php');
-lmb_require('limb/macro/src/lmbMacroException.class.php');
-
-/**
- * class lmbMacroAnnotationParser.
- *
- * @package macro
- * @version $Id$
- */
-class lmbMacroAnnotationParser
-{
- static function extractFromFile($file, $listener)
- {
- $infos = array();
- $tokenizer = new lmbPHPTokenizer(file_get_contents($file));
- while($token = $tokenizer->next())
- {
- if(!is_array($token))
- continue;
-
- //found class token
- if($token[0] == T_CLASS)
- {
- //fetching class name
- $token = $tokenizer->next();
- $class = $token[1];
-
- //now checking prev token for /**/
- if(!is_array($prev_token) || $prev_token[0] != T_DOC_COMMENT)
- throw new lmbMacroException('Invalid token, doc comment is expected');
-
- //now parsing annotations
- $annotations = self :: _extractAnnotations($prev_token[1]);
- if(!$annotations)
- throw new lmbMacroException("No annotations found in doc comment '{$prev_token[1]}' in file $file");
-
- $infos[] = call_user_func_array (array($listener, 'createByAnnotations'), array($file, $class, $annotations));
- //$infos[] = $listener->createByAnnotations($file, $class, $annotations);
- }
- $prev_token = $token;
- }
- return $infos;
- }
-
- static protected function _extractAnnotations($content)
- {
- if(!preg_match_all('~@(\S+)([^\n]+)?\n~', $content, $matches))
- return false;
- $annotations = array();
- for($i=0;$i<count($matches[0]);$i++)
- $annotations[trim($matches[1][$i])] = trim($matches[2][$i]);
- return $annotations;
- }
-}
-
Deleted: 3.x/trunk/limb/macro/src/lmbMacroAnnotationParserListener.interface.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroAnnotationParserListener.interface.php 2007-12-03 11:44:06 UTC (rev 6560)
+++ 3.x/trunk/limb/macro/src/lmbMacroAnnotationParserListener.interface.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -1,20 +0,0 @@
-<?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com
- * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
- * @license LGPL http://www.gnu.org/copyleft/lesser.html
- */
-
-/**
- * interface lmbMacroAnnotationParserListener.
- *
- * @package macro
- * @version $Id$
- */
-interface lmbMacroAnnotationParserListener
-{
- function createByAnnotations($class, $file, $annotations);
-}
-
Deleted: 3.x/trunk/limb/macro/src/lmbMacroBaseParsingState.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroBaseParsingState.class.php 2007-12-03 11:44:06 UTC (rev 6560)
+++ 3.x/trunk/limb/macro/src/lmbMacroBaseParsingState.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -1,61 +0,0 @@
-<?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com
- * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
- * @license LGPL http://www.gnu.org/copyleft/lesser.html
- */
-
-/**
- * @package macro
- * @version $Id$
- */
-class lmbMacroBaseParsingState
-{
- /**
- * @var lmbMacroSourceFileParser
- */
- protected $parser;
-
- /**
- * @var lmbMacroTreeBuilder
- */
- protected $tree_builder;
-
- protected $locator;
-
- function __construct($parser, $tree_builder)
- {
- $this->parser = $parser;
- $this->tree_builder = $tree_builder;
- }
-
- function setTemplateLocator($locator)
- {
- $this->locator = $locator;
- }
-
- function invalidAttributeSyntax($data)
- {
- throw new lmbException('Invalid attribute syntax starting from: ' . $data);
- }
-
- 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;
- }
-}
-
Deleted: 3.x/trunk/limb/macro/src/lmbMacroBlockAnalizer.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroBlockAnalizer.class.php 2007-12-03 11:44:06 UTC (rev 6560)
+++ 3.x/trunk/limb/macro/src/lmbMacroBlockAnalizer.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -1,52 +0,0 @@
-<?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com
- * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
- * @license LGPL http://www.gnu.org/copyleft/lesser.html
- */
-
-/**
- * class lmbMacroContentAnalizer.
- *
- * @package macro
- * @version $Id$
- */
-class lmbMacroBlockAnalizer
-{
- const BEFORE_CONTENT = 1;
- const EXPRESSION = 2;
- const AFTER_CONTENT = 5;
-
- protected function _getRegexp()
- {
- return '/^((?s).*?)'. preg_quote('{$', '/') . '((([^"\']+["\']?[^"\']?["\'])+)?[^}]+)' . preg_quote('}', '/') . '((?s).*)$/';
- }
-
- function parse($text, $observer)
- {
- // if there is no expression (common case), shortcut this process
- if (strpos($text, '{$') === FALSE)
- {
- $observer->addLiteralFragment($text);
- return;
- }
-
- $regexp = $this->_getRegexp();
-
- while (preg_match($regexp, $text, $match))
- {
- if (strlen($match[self :: BEFORE_CONTENT]) > 0)
- $observer->addLiteralFragment($match[self :: BEFORE_CONTENT]);
-
- $observer->addExpressionFragment('$' . $match[self :: EXPRESSION]);
-
- $text = $match[self :: AFTER_CONTENT];
- }
-
- if (strlen($text) > 0)
- $observer->addLiteralFragment($text);
- }
-}
-
Deleted: 3.x/trunk/limb/macro/src/lmbMacroBlockAnalizerListener.interface.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroBlockAnalizerListener.interface.php 2007-12-03 11:44:06 UTC (rev 6560)
+++ 3.x/trunk/limb/macro/src/lmbMacroBlockAnalizerListener.interface.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -1,21 +0,0 @@
-<?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com
- * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
- * @license LGPL http://www.gnu.org/copyleft/lesser.html
- */
-
-/**
- * interface lmbMacroBlockAnalizerListener.
- *
- * @package macro
- * @version $Id$
- */
-interface lmbMacroBlockAnalizerListener
-{
- function addLiteralFragment($text);
- function addExpressionFragment($text);
-}
-
Deleted: 3.x/trunk/limb/macro/src/lmbMacroCodeWriter.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroCodeWriter.class.php 2007-12-03 11:44:06 UTC (rev 6560)
+++ 3.x/trunk/limb/macro/src/lmbMacroCodeWriter.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -1,242 +0,0 @@
-<?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com
- * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
- * @license LGPL http://www.gnu.org/copyleft/lesser.html
- */
-
-/**
- * class lmbMacroCodeWriter.
- *
- * @package macro
- * @version $Id$
- */
-class lmbMacroCodeWriter
-{
- const MODE_PHP = 1;
- const MODE_HTML = 2;
-
- protected $class;
-
- protected $parent;
-
- protected $current_mode = self :: MODE_PHP;
-
- protected $current_method;
-
- protected $code = '';
-
- protected $methods = array();
-
- protected $init_code = '';
-
- protected $methods_stack = array();
-
- protected $include_list = array();
-
- protected $temp_var_name = 1;
-
- function __construct($class, $render_func = 'render')
- {
- $this->class = $class;
- $this->render_func = $render_func;
- $this->parent = 'lmbMacroTemplateExecutor';
- $this->registerInclude('limb/macro/src/lmbMacroTemplateExecutor.class.php');
-
- $this->beginMethod($render_func, array('$args = array()'));
- $this->writePHP('if($args) extract($args);');
- $this->writePHP('$this->_init();');
- }
-
- function getClass()
- {
- return $this->class;
- }
-
- function getRenderMethod()
- {
- return 'render';
- }
-
- protected function switchToPHP()
- {
- if($this->current_mode == self :: MODE_HTML)
- {
- $this->current_mode = self :: MODE_PHP;
- $this->_append('<?php ');
- }
- }
-
- protected function switchToHTML($context = null)
- {
- if($this->current_mode == self :: MODE_PHP)
- {
- $this->current_mode = self :: MODE_HTML;
- if($context === "\n")
- $this->_append(" ?>\n");
- else
- $this->_append(' ?>');
- }
- }
-
- function writePHP($text)
- {
- $this->switchToPHP();
- $this->_append($text);
- }
-
- function writePHPLiteral($text, $escape_text = true)
- {
- $this->switchToPHP();
-
- if($escape_text)
- $this->_append("'" . $this->escapeLiteral($text) . "'");
- else
- $this->_append("'" . $text . "'");
- }
-
- function escapeLiteral($text)
- {
- $text = str_replace('\'', "\\'", $text);
- if(substr($text, -1) == '\\')
- $text .= '\\';
- return $text;
- }
-
- function writeHTML($text)
- {
- $this->switchToHTML(substr($text,0,1));
- $this->_append($text);
- }
-
- function writeRaw($text)
- {
- $this->_append($text);
- }
-
- function renderCode()
- {
- $this->endMethod();
-
- $code = "<?php\n" .
- //protection from self inclusion
- "if(!class_exists('{$this->class}', false)){\n" .
- $this->_renderIncludeList() .
- "class {$this->class} " . ($this->parent ? "extends {$this->parent} " : '') . "{\n" .
- (!$this->init_code ? "" :
- "\nfunction _init() {" .
- "\n$this->init_code\n" .
- "}\n"
- ) .
- $this->_renderMethods() .
- "\n}" .
- "\n}";
- return $code;
- }
-
- function getCode()
- {
- return $this->code;
- }
-
- function getMode()
- {
- return $this->current_mode;
- }
-
- function registerInclude($include_file)
- {
- if(!in_array($include_file, $this->include_list))
- $this->include_list[] = $include_file;
- }
-
- function getIncludeList()
- {
- return $this->include_list;
- }
-
- function beginFunction($name, $param_list = array())
- {
- $this->writePHP('function ' . $name . '(' . implode(',', $param_list) .") {\n");
- return $name;
- }
-
- function endFunction()
- {
- $this->writePHP("\n}\n");
- }
-
- function beginMethod($name, $param_list = array())
- {
- $this->methods_stack[] = array($this->current_method, $this->current_mode);
- $this->current_method = $name;
-
- //we don't need to switch to PHP, since methods can be declared inside PHP only
- $this->writeRaw('function ' . $name . '(' . implode(',', $param_list) .") {\n");
- $this->current_mode = self :: MODE_PHP;
- return $name;
- }
-
- function endMethod()
- {
- $this->writePHP("\n}\n");
- list($this->current_method, $this->current_mode) = array_pop($this->methods_stack);
- }
-
- function writeToInit($code)
- {
- $this->init_code .= $code;
- }
-
- /**
- * Utility method, which generates a unique variable name
- */
- function generateTempName()
- {
- $var = $this->temp_var_name++;
- if($var > 675)
- return chr(65 + ($var/26)/26) . chr(65 + ($var/26)%26) . chr(65 + $var%26);
- elseif($var > 26)
- return chr(65 + ($var/26)%26) . chr(65 + $var%26);
- else
- return chr(64 + $var);
- }
-
- /**
- * Utility method, which generates a unique variable name, prefixed with a $
- */
- function generateVar()
- {
- return '$' . $this->generateTempName();
- }
-
- protected function _append($code)
- {
- if(!$this->current_method)
- {
- $this->code .= $code;
- return;
- }
-
- if(!isset($this->methods[$this->current_method]))
- $this->methods[$this->current_method] = '';
-
- $this->methods[$this->current_method] .= $code;
- }
-
- protected function _renderMethods()
- {
- return implode("\n", $this->methods);
- }
-
- protected function _renderIncludeList()
- {
- $include_code = '';
- foreach($this->include_list as $include_file)
- $include_code .= "require_once('$include_file');\n";
- return $include_code;
- }
-}
-
Deleted: 3.x/trunk/limb/macro/src/lmbMacroCompiler.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroCompiler.class.php 2007-12-03 11:44:06 UTC (rev 6560)
+++ 3.x/trunk/limb/macro/src/lmbMacroCompiler.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -1,117 +0,0 @@
-<?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com
- * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
- * @license LGPL http://www.gnu.org/copyleft/lesser.html
- */
-
-lmb_require('limb/macro/src/lmbMacroTreeBuilder.class.php');
-lmb_require('limb/macro/src/lmbMacroNode.class.php');
-lmb_require('limb/macro/src/lmbMacroParser.class.php');
-lmb_require('limb/macro/src/lmbMacroCodeWriter.class.php');
-
-lmb_require('limb/macro/src/lmbMacroTag.class.php');
-lmb_require('limb/macro/src/lmbMacroPassiveTag.class.php');
-
-/**
- * class lmbMacroCompiler.
- *
- * @package macro
- * @version $Id$
- */
-class lmbMacroCompiler
-{
- /**
- * @var lmbMacroTreeBuilder
- */
- protected $tree_builder;
-
- /**
- * @var lmbMacroTemplateLocator
- */
- protected $template_locator;
-
- /**
- * @var lmbMacroSourceParser
- */
- protected $parser;
-
- /**
- * @var lmbMacroTagDictionary
- */
- protected $tag_dictionary;
-
- /**
- * @var lmbMacroFilterDictionary
- */
- protected $filter_dictionary;
-
- function __construct($tag_dictionary, $template_locator, $filter_dictionary)
- {
- $this->tree_builder = new lmbMacroTreeBuilder($this);
-
- $this->template_locator = $template_locator;
-
- $this->tag_dictionary = $tag_dictionary;
- $this->filter_dictionary = $filter_dictionary;
- }
-
- function compile($source_file, $compiled_file, $class, $render_func)
- {
- $root_node = new lmbMacroNode(new lmbMacroSourceLocation($source_file, ''));
- $this->parseTemplate($source_file, $root_node);
-
- $generated_code = $this->_generateTemplateCode($class, $render_func, $root_node);
- self :: writeFile($compiled_file, $generated_code);
- }
-
- function _generateTemplateCode($class, $render_func, $root_node)
- {
- $code_writer = new lmbMacroCodeWriter($class, $render_func);
- $root_node->generate($code_writer);
- return $code_writer->renderCode();
- }
-
- function parseTemplate($source_file_path, $root_node)
- {
- $parser = new lmbMacroParser($this->tree_builder, $this->template_locator, $this->tag_dictionary);
- $parser->parse($source_file_path, $root_node);
- }
-
- /**
- * @return lmbMacroTemplateLocator
- */
- function getTemplateLocator()
- {
- return $this->template_locator;
- }
-
- /**
- * @return lmbMacroTreeBuilder
- */
- function getTreeBuilder()
- {
- return $this->tree_builder;
- }
-
- function getTagDictionary()
- {
- return $this->tag_dictionary;
- }
-
- function getFilterDictionary()
- {
- return $this->filter_dictionary;
- }
-
- static function writeFile($file, $data)
- {
- $dirname = dirname($file);
- lmbFs :: mkdir($dirname);
-
- file_put_contents($file, $data);
- }
-}
-
Deleted: 3.x/trunk/limb/macro/src/lmbMacroContentBlockAnalizerListener.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroContentBlockAnalizerListener.class.php 2007-12-03 11:44:06 UTC (rev 6560)
+++ 3.x/trunk/limb/macro/src/lmbMacroContentBlockAnalizerListener.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -1,45 +0,0 @@
-<?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com
- * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
- * @license LGPL http://www.gnu.org/copyleft/lesser.html
- */
-lmb_require('limb/macro/src/lmbMacroBlockAnalizerListener.interface.php');
-lmb_require('limb/macro/src/lmbMacroOutputExpressionNode.class.php');
-lmb_require('limb/macro/src/lmbMacroExpressionNode.class.php');
-
-/**
- * class lmbMacroContentBlockAnalizerListener.
- *
- * @package macro
- * @version $Id$
- */
-class lmbMacroContentBlockAnalizerListener implements lmbMacroBlockAnalizerListener
-{
- protected $tree_builder;
- protected $location;
-
- function __construct($tree_builder, $location)
- {
- $this->tree_builder = $tree_builder;
- $this->location = $location;
- }
-
- function addLiteralFragment($text)
- {
- $this->tree_builder->addTextNode($text);
- }
-
- function addExpressionFragment($text)
- {
- $expression = new lmbMacroExpressionNode($text,
- $this->tree_builder->getCursor(),
- $this->tree_builder->getFilterDictionary());
-
- $output_expression = new lmbMacroOutputExpressionNode($this->location, $expression);
- $this->tree_builder->addNode($output_expression);
- }
-}
-
Deleted: 3.x/trunk/limb/macro/src/lmbMacroExpression.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroExpression.class.php 2007-12-03 11:44:06 UTC (rev 6560)
+++ 3.x/trunk/limb/macro/src/lmbMacroExpression.class.php 2007-12-03 11:56:54 UTC (rev 6561)
@@ -1,105 +0,0 @@
-<?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com
- * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com)
- * @license LGPL http://www.gnu.org/copyleft/lesser.html
- */
-
-lmb_require('limb/macro/src/lmbMacroExpressionInterface.interface.php');
-
-/**
- * class lmbMacroExpression
- * @package macro
- * @version $Id$
- */
-class lmbMacroExpression implements lmbMacroExpressionInterface
-{
- protected $tmp;
-
- function __construct($expression_str)
- {
- $this->expression_str = $expression_str;
- }
-
- function preGenerate($code)
- {
- $this->tmp = $code->generateVar();
- $var = $code->generateVar();
-
- // simple case if expression is just a variable
- if(strpos($this->expression_str, '.') === false)
- {
- $this->tmp = $this->expression_str;
- return;
- }
-
- $expr = '';
-
- $items = $this->_extractExpressionPathItems($this->expression_str);
-
- //first item is variable itself
- //$var = $items[0];
- $expr .= $var . ' = ' . $items[0] . ';';
- $code->writePHP($this->tmp . "='';");
-
- for($i=1; $i<sizeof($items); $i++)
- {
- $item = $items[$i];
- $expr .= 'if((is_array(' . $var . ') && isset(' . $var . '["' . $item . '"])) || ' .
- '(is_object(' . $var . ') && ' . $this->tmp . '=' . $var . '->get("' . $item . '")))' .
- '{if(is_array(' . $var . '))' . $this->tmp . ' = ' . $var . '["' . $item . '"];';
- $var = $this->tmp;
- }
-
- //closing brackets
- for($i=1; $i < sizeof($items); $i++)
- $expr .= '}else{' . $this->tmp . '="";}';
-
- $code->writePHP($expr);
- }
-
- protected function