/**
  * Unknown tag handler
  *
  * @param string $tag
  * @param array $params
  * @param array $tokens
  */
 function unknown_tag($tag, $params, &$tokens)
 {
     $when_syntax_regexp = new LiquidRegexp('/' . LIQUID_QUOTED_FRAGMENT . '/');
     switch ($tag) {
         case 'when':
             // push the current nodelist onto the stack and prepare for a new one
             if ($when_syntax_regexp->match($params)) {
                 $this->push_nodelist();
                 $this->right = $when_syntax_regexp->matches[0];
                 $this->_nodelist = array();
             } else {
                 throw new LiquidException("Syntax Error in tag 'case' - Valid when condition: when [condition]");
                 // harry
             }
             break;
         case 'else':
             // push the last nodelist onto the stack and prepare to recieve the else nodes
             $this->push_nodelist();
             $this->right = null;
             $this->else_nodelist =& $this->_nodelist;
             $this->_nodelist = array();
             break;
         default:
             parent::unknown_tag($tag, $params, $tokens);
     }
 }
 /**
  * Constructor
  *
  * @param string $markup
  * @return LiquidVariable
  */
 public function __construct($markup)
 {
     $this->markup = $markup;
     $quoted_fragment_regexp = new LiquidRegexp('/\\s*(' . LIQUID_QUOTED_FRAGMENT . ')/');
     $filter_seperator_regexp = new LiquidRegexp('/' . LIQUID_FILTER_SEPARATOR . '\\s*(.*)/');
     $filter_split_regexp = new LiquidRegexp('/' . LIQUID_FILTER_SEPARATOR . '/');
     $filter_name_regexp = new LiquidRegexp('/\\s*(\\w+)/');
     $filter_argument_regexp = new LiquidRegexp('/(?:' . LIQUID_FILTER_ARGUMENT_SEPARATOR . '|' . LIQUID_ARGUMENT_SEPARATOR . ')\\s*(' . LIQUID_QUOTED_FRAGMENT . ')/');
     $quoted_fragment_regexp->match($markup);
     //$this->_name = $quoted_fragment_regexp->matches[1];
     $this->_name = isset($quoted_fragment_regexp->matches[1]) ? $quoted_fragment_regexp->matches[1] : null;
     // harry
     if ($filter_seperator_regexp->match($markup)) {
         $filters = $filter_split_regexp->split($filter_seperator_regexp->matches[1]);
         foreach ($filters as $filter) {
             $filter_name_regexp->match($filter);
             $filtername = $filter_name_regexp->matches[1];
             $filter_argument_regexp->match_all($filter);
             //$matches = array_flatten($filter_argument_regexp->matches[1]);
             $matches = Liquid::array_flatten($filter_argument_regexp->matches[1]);
             $this->filters[] = array($filtername, $matches);
         }
     } else {
         $this->filters = array();
     }
 }
 /**
  * Constructor
  *
  * @param string $markup
  * @param array $tokens
  * @param LiquidFileSystem $file_system
  * @return AssignLiquidTag
  */
 public function __construct($markup, &$tokens, &$file_system)
 {
     $syntax_regexp = new LiquidRegexp('/(\\w+)\\s*=\\s*(' . LIQUID_QUOTED_FRAGMENT . '+)/');
     $filter_seperator_regexp = new LiquidRegexp('/' . LIQUID_FILTER_SEPARATOR . '\\s*(.*)/');
     $filter_split_regexp = new LiquidRegexp('/' . LIQUID_FILTER_SEPARATOR . '/');
     $filter_name_regexp = new LiquidRegexp('/\\s*(\\w+)/');
     $filter_argument_regexp = new LiquidRegexp('/(?:' . LIQUID_FILTER_ARGUMENT_SEPARATOR . '|' . LIQUID_ARGUMENT_SEPARATOR . ')\\s*(' . LIQUID_QUOTED_FRAGMENT . ')/');
     $this->filters = array();
     if ($filter_seperator_regexp->match($markup)) {
         $filters = $filter_split_regexp->split($filter_seperator_regexp->matches[1]);
         foreach ($filters as $filter) {
             $filter_name_regexp->match($filter);
             $filtername = $filter_name_regexp->matches[1];
             $filter_argument_regexp->match_all($filter);
             $matches = Liquid::array_flatten($filter_argument_regexp->matches[1]);
             array_push($this->filters, array($filtername, $matches));
         }
     }
     if ($syntax_regexp->match($markup)) {
         $this->_to = $syntax_regexp->matches[1];
         $this->_from = $syntax_regexp->matches[2];
     } else {
         throw new LiquidException("Syntax Error in 'assign' - Valid syntax: assign [var] = [source]");
     }
 }
 /**
  * Constructor
  *
  * @param string $markup
  * @param array $tokens
  * @param LiquidFileSystem $file_system
  * @return AssignLiquidTag
  */
 public function __construct($markup, &$tokens, &$file_system)
 {
     $syntax = new LiquidRegexp("/(" . LIQUID_ALLOWED_VARIABLE_CHARS . "+)/");
     if ($syntax->match($markup)) {
         $this->_toDecrement = $syntax->matches[0];
     } else {
         throw new LiquidException("Syntax Error in 'decrement' - Valid syntax: decrement [var]");
     }
 }
Example #5
0
 /**
  * Extracts tag attributes from a markup string
  *
  * @param string $markup
  */
 public function extract_attributes($markup)
 {
     $this->attributes = array();
     $attribute_regexp = new LiquidRegexp(LIQUID_TAG_ATTRIBUTES);
     $matches = $attribute_regexp->scan($markup);
     foreach ($matches as $match) {
         $this->attributes[$match[0]] = $match[1];
     }
 }
 /**
  * Constructor
  *
  * @param string $markup
  * @param Array $tokens
  * @param LiquidFileSystem $fileSystem
  * @return CaptureLiquidTag
  */
 public function __construct($markup, &$tokens, &$fileSystem)
 {
     $syntaxRegexp = new LiquidRegexp('/(\\w+)/');
     if ($syntaxRegexp->match($markup)) {
         $this->_block = $syntaxRegexp->matches[1];
         parent::__construct($markup, $tokens, $fileSystem);
     } else {
         throw new LiquidException("Syntax Error in 'block' - Valid syntax: block [name]");
     }
 }
 /**
  * Constructor
  *
  * @param string $markup
  * @param Array $tokens
  * @param LiquidFileSystem $file_system
  * @return CaptureLiquidTag
  */
 public function __construct($markup, &$tokens, &$file_system)
 {
     $syntax_regexp = new LiquidRegexp('/(\\w+)/');
     if ($syntax_regexp->match($markup)) {
         $this->_to = $syntax_regexp->matches[1];
         parent::__construct($markup, $tokens, $file_system);
     } else {
         throw new LiquidException("Syntax Error in 'capture' - Valid syntax: assign [var] = [source]");
         // harry
     }
 }
 /**
  * Constructor
  *
  * @param string $markup
  * @param array $tokens
  * @param LiquidFileSystem $file_system
  * @return AssignLiquidTag
  */
 public function __construct($markup, &$tokens, &$file_system)
 {
     //$syntax_regexp = new LiquidRegexp('/(\w+)\s*=\s*('.LIQUID_ALLOWED_VARIABLE_CHARS.'+)/');
     $syntax_regexp = new LiquidRegexp('/(\\w+)\\s*=\\s*(' . LIQUID_QUOTED_FRAGMENT . '+)/');
     if ($syntax_regexp->match($markup)) {
         $this->_to = $syntax_regexp->matches[1];
         $this->_from = $syntax_regexp->matches[2];
     } else {
         throw new LiquidException("Syntax Error in 'assign' - Valid syntax: assign [var] = [source]");
     }
 }
 /**
  * Constructor
  *
  * @param string $markup
  * @param array $tokens
  * @param LiquidFileSystem $file_system
  * @return TableRowLiquidTag
  */
 public function __construct($markup, &$tokens, &$file_system)
 {
     parent::__construct($markup, $tokens, $file_system);
     $syntax = new LiquidRegexp("/(\\w+)\\s+in\\s+(" . LIQUID_ALLOWED_VARIABLE_CHARS . "+)/");
     if ($syntax->match($markup)) {
         $this->variable_name = $syntax->matches[1];
         $this->collection_name = $syntax->matches[2];
         $this->extract_attributes($markup);
     } else {
         throw new LiquidException("Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3");
     }
 }
Example #10
0
 /**
  * Constructor
  *
  * @param string $markup
  * @param array $tokens
  * @param LiquidFileSystem $file_system
  * @return TableRowLiquidTag
  */
 function TableRowLiquidTag($markup, &$tokens, &$file_system)
 {
     parent::LiquidTag($markup, $tokens, $file_system);
     $syntax = new LiquidRegexp("/(\\w+)\\s+in\\s+(" . LIQUID_ALLOWED_VARIABLE_CHARS . "+)/");
     if ($syntax->match($markup)) {
         $this->variable_name = $syntax->matches[1];
         $this->collection_name = $syntax->matches[2];
         $this->extract_attributes($markup);
     } else {
         trigger_error("Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3", E_USER_ERROR);
     }
 }
 /**
  * Render the tag
  *
  * @param LiquidContext $context
  */
 public function render(&$context)
 {
     $context->push();
     $logicalRegex = new LiquidRegexp('/\\s+(and|or)\\s+/');
     $conditionalRegex = new LiquidRegexp('/(' . LIQUID_QUOTED_FRAGMENT . ')\\s*([=!<>a-z_]+)?\\s*(' . LIQUID_QUOTED_FRAGMENT . ')?/');
     $result = '';
     foreach ($this->_blocks as $i => $block) {
         if ($block[0] == 'else') {
             $result = $this->render_all($block[2], $context);
             break;
         }
         if ($block[0] == 'if' || $block[0] == 'elsif') {
             /* Extract logical operators */
             $logicalRegex->match($block[1]);
             $logicalOperators = $logicalRegex->matches;
             array_shift($logicalOperators);
             /* Extract individual conditions */
             $temp = $logicalRegex->split($block[1]);
             $conditions = array();
             foreach ($temp as $condition) {
                 if ($conditionalRegex->match($condition)) {
                     $left = isset($conditionalRegex->matches[1]) ? $conditionalRegex->matches[1] : null;
                     $operator = isset($conditionalRegex->matches[2]) ? $conditionalRegex->matches[2] : null;
                     $right = isset($conditionalRegex->matches[3]) ? $conditionalRegex->matches[3] : null;
                     array_push($conditions, array('left' => $left, 'operator' => $operator, 'right' => $right));
                 } else {
                     throw new LiquidException("Syntax Error in tag 'if' - Valid syntax: if [condition]");
                 }
             }
             if (count($logicalOperators)) {
                 /* If statement contains and/or */
                 $display = true;
                 foreach ($logicalOperators as $k => $logicalOperator) {
                     if ($logicalOperator == 'and') {
                         $display = $this->interpret_condition($conditions[$k]['left'], $conditions[$k]['right'], $conditions[$k]['operator'], $context) && $this->interpret_condition($conditions[$k + 1]['left'], $conditions[$k + 1]['right'], $conditions[$k + 1]['operator'], $context);
                     } else {
                         $display = $this->interpret_condition($conditions[$k]['left'], $conditions[$k]['right'], $conditions[$k]['operator'], $context) || $this->interpret_condition($conditions[$k + 1]['left'], $conditions[$k + 1]['right'], $conditions[$k + 1]['operator'], $context);
                     }
                 }
             } else {
                 /* If statement is a single condition */
                 $display = $this->interpret_condition($conditions[0]['left'], $conditions[0]['right'], $conditions[0]['operator'], $context);
             }
             if ($display) {
                 $result = $this->render_all($block[2], $context);
                 break;
             }
         }
     }
     $context->pop();
     return $result;
 }
 /**
  * Constructor
  *
  * @param string $markup
  * @param array $tokens
  * @param LiquidFileSystem $fileSystem
  * @return ForLiquidTag
  */
 public function __construct($markup, &$tokens, &$fileSystem)
 {
     parent::__construct($markup, $tokens, $fileSystem);
     $syntaxRegexp = new LiquidRegexp('/(\\w+)\\s+in\\s+(' . LIQUID_ALLOWED_VARIABLE_CHARS . '+)/');
     if ($syntaxRegexp->match($markup)) {
         $this->_variableName = $syntaxRegexp->matches[1];
         $this->_collectionName = $syntaxRegexp->matches[2];
         $this->_name = $syntaxRegexp->matches[1] . '-' . $syntaxRegexp->matches[2];
         $this->extractAttributes($markup);
     } else {
         throw new LiquidException("Syntax Error in 'for loop' - Valid syntax: for [item] in [collection]");
     }
 }
 /**
  * Constructor
  *
  * @param string $markup
  * @param array $tokens
  * @param LiquidFileSystem $fileSystem
  * @return ForLiquidTag
  */
 public function __construct($markup, &$tokens, &$fileSystem)
 {
     parent::__construct($markup, $tokens, $fileSystem);
     $syntax = new LiquidRegexp('/(' . LIQUID_ALLOWED_VARIABLE_CHARS . '+)\\s+by\\s+(\\w+)/');
     if ($syntax->match($markup)) {
         $this->_collectionName = $syntax->matches[1];
         $this->_numberItems = $syntax->matches[2];
         $this->_currentPage = is_numeric($_GET['page']) ? $_GET['page'] : 1;
         $this->_currentOffset = ($this->_currentPage - 1) * $this->_numberItems;
         $this->extractAttributes($markup);
     } else {
         throw new LiquidException("Syntax Error - Valid syntax: paginate [collection] by [items]");
     }
 }
 /**
  * Constructor
  *
  * @param string $markup
  * @param array $tokens
  * @param LiquidFileSystem $fileSystem
  * @return IncludeLiquidTag
  */
 public function __construct($markup, &$tokens, &$fileSystem)
 {
     $regex = new LiquidRegexp('/("[^"]+"|\'[^\']+\')(\\s+(with|for)\\s+(' . LIQUID_QUOTED_FRAGMENT . '+))?/');
     if ($regex->match($markup)) {
         $this->_templateName = substr($regex->matches[1], 1, strlen($regex->matches[1]) - 2);
         if (isset($regex->matches[1])) {
             $this->_collection = isset($regex->matches[3]) ? $regex->matches[3] == "for" : null;
             $this->_variable = isset($regex->matches[4]) ? $regex->matches[4] : null;
         }
         $this->extractAttributes($markup);
     } else {
         throw new LiquidException("Error in tag 'include' - Valid syntax: include '[template]' (with|for) [object|collection]");
     }
     parent::__construct($markup, $tokens, $fileSystem);
 }
 /**
  * Resolves a given path to a full template file path, making sure it's valid
  *
  * @param string $templatePath
  * @return string
  */
 public function fullPath($templatePath)
 {
     $nameRegex = LIQUID_INCLUDE_ALLOW_EXT ? new LiquidRegexp('/^[^.\\/][a-zA-Z0-9_\\.\\/]+$/') : new LiquidRegexp('/^[^.\\/][a-zA-Z0-9_\\/]+$/');
     if (!$nameRegex->match($templatePath)) {
         throw new LiquidException("Illegal template name '{$templatePath}'");
     }
     if (strpos($templatePath, '/') !== false) {
         //LIQUID_INCLUDE_ALLOW_EXT
         $fullPath = LIQUID_INCLUDE_ALLOW_EXT ? $this->_root . dirname($templatePath) . '/' . basename($templatePath) : $this->_root . dirname($templatePath) . '/' . LIQUID_INCLUDE_PREFIX . basename($templatePath) . '.' . LIQUID_INCLUDE_SUFFIX;
     } else {
         $fullPath = LIQUID_INCLUDE_ALLOW_EXT ? $this->_root . $templatePath : $this->_root . LIQUID_INCLUDE_PREFIX . $templatePath . '.' . LIQUID_INCLUDE_SUFFIX;
     }
     $rootRegex = new LiquidRegexp('/' . preg_quote(realpath($this->_root), '/') . '/');
     if (!$rootRegex->match(realpath($fullPath))) {
         throw new LiquidException("Illegal template path '" . realpath($fullPath) . "'");
     }
     return $fullPath;
 }
 /**
  * Extract variables from a string of markup
  * 
  * @param string $markup
  * @return array;
  */
 private function _variablesFromString($markup)
 {
     $regexp = new LiquidRegexp('/\\s*(' . LIQUID_QUOTED_FRAGMENT . ')\\s*/');
     $parts = explode(',', $markup);
     $result = array();
     foreach ($parts as $part) {
         $regexp->match($part);
         if ($regexp->matches[1]) {
             $result[] = $regexp->matches[1];
         }
     }
     return $result;
 }
Example #17
0
 /**
  * Constructor
  *
  * @param string $markup
  * @return LiquidVariable
  */
 function LiquidVariable($markup)
 {
     $this->markup = $markup;
     $quoted_fragment_regexp = new LiquidRegexp('/\\s*(' . LIQUID_QUOTED_FRAGMENT . ')/');
     $filter_seperator_regexp = new LiquidRegexp('/' . LIQUID_FILTER_SEPERATOR . '\\s*(.*)/');
     $filter_split_regexp = new LiquidRegexp('/' . LIQUID_FILTER_SEPERATOR . '/');
     $filter_name_regexp = new LiquidRegexp('/\\s*(\\w+)/');
     $filter_argument_regexp = new LiquidRegexp('/(?:' . LIQUID_FILTER_ARGUMENT_SEPERATOR . '|' . LIQUID_ARGUMENT_SPERATOR . ')\\s*(' . LIQUID_QUOTED_FRAGMENT . ')/');
     $quoted_fragment_regexp->match($markup);
     $this->name = $quoted_fragment_regexp->matches[1];
     if ($filter_seperator_regexp->match($markup)) {
         $filters = $filter_split_regexp->split($filter_seperator_regexp->matches[1]);
         foreach ($filters as $filter) {
             $filter_name_regexp->match($filter);
             $filtername = $filter_name_regexp->matches[1];
             $filter_argument_regexp->match_all($filter);
             $matches = array_flatten($filter_argument_regexp->matches[1]);
             $this->filters[] = array($filtername, $matches);
         }
     } else {
         $this->filters = array();
     }
 }
 /**
  * Constructor
  *
  * @param string $markup
  * @param array $tokens
  * @param LiquidFileSystem $file_system
  * @return ForLiquidTag
  */
 public function __construct($markup, &$tokens, &$file_system)
 {
     parent::__construct($markup, $tokens, $file_system);
     $syntax_regexp = new LiquidRegexp('/(\\w+)\\s+in\\s+(' . LIQUID_ALLOWED_VARIABLE_CHARS . '+)/');
     if ($syntax_regexp->match($markup)) {
         $this->_variableName = $syntax_regexp->matches[1];
         $this->_collectionName = $syntax_regexp->matches[2];
         $this->_name = $syntax_regexp->matches[1] . '-' . $syntax_regexp->matches[2];
         $this->extractAttributes($markup);
     } else {
         $syntax_regexp = new LiquidRegexp('/(\\w+)\\s+in\\s+\\((\\d|' . LIQUID_ALLOWED_VARIABLE_CHARS . '+)\\s*..\\s*(\\d|' . LIQUID_ALLOWED_VARIABLE_CHARS . '+)\\)/');
         if ($syntax_regexp->match($markup)) {
             $this->_type = 'digit';
             $this->_variableName = $syntax_regexp->matches[1];
             $this->_start = $syntax_regexp->matches[2];
             $this->_collectionName = $syntax_regexp->matches[3];
             $this->_name = $syntax_regexp->matches[1] . '-digit';
             $this->extractAttributes($markup);
         } else {
             throw new LiquidException("Syntax Error in 'for loop' - Valid syntax: for [item] in [collection] OR for [int] in ([start]..[end])");
         }
     }
 }
Example #19
0
 /**
  * Constructor
  *
  * @param string $markup
  * @param array $tokens
  * @param LiquidFileSystem $file_system
  * @return IncludeLiquidTag
  */
 function IncludeLiquidTag($markup, &$tokens, &$file_system)
 {
     $regex = new LiquidRegexp('/("[^"]+"|\'[^\']+\')(\\s+(with|for)\\s+(' . LIQUID_QUOTED_FRAGMENT . '+))?/');
     if ($regex->match($markup)) {
         $this->template_name = substr($regex->matches[1], 1, strlen($regex->matches[1]) - 2);
         if (isset($regex->matches[1])) {
             $this->collection = $regex->matches[3] == "for";
             $this->variable = $regex->matches[4];
         }
         $this->extract_attributes($markup);
     } else {
         trigger_error("Error in tag 'include' - Valid syntax: include '[template]' (with|for) [object|collection]", E_USER_ERROR);
     }
     parent::LiquidTag($markup, $tokens, $file_system);
 }
Example #20
0
 function test_quoted_words_in_the_middle()
 {
     $this->assertEqual(array('arg1', 'arg2', '"arg 3"', 'arg4'), $this->regexp->scan('arg1 arg2 "arg 3" arg4   '));
 }
 /**
  * Create a variable for the given token
  *
  * @param string $token
  * @return LiquidVariable
  */
 function create_variable($token)
 {
     $variable_regexp = new LiquidRegexp('/^' . LIQUID_VARIABLE_START . '(.*)' . LIQUID_VARIABLE_END . '$/');
     if ($variable_regexp->match($token)) {
         return new LiquidVariable($variable_regexp->matches[1]);
     }
     throw new LiquidException("Variable {$token} was not properly terminated");
 }
 /**
  * Parses the tokens
  *
  * @param array $tokens
  */
 public function parse(&$tokens)
 {
     if (!isset($this->_fileSystem)) {
         throw new LiquidException("No file system");
     }
     // read the source of the template and create a new sub document
     $source = $this->_fileSystem->readTemplateFile($this->_templateName);
     // tokens in this new document
     $maintokens = LiquidTemplate::tokenize($source);
     $eRegexp = new LiquidRegexp('/^' . LIQUID_TAG_START . '\\s*extends (.*)?' . LIQUID_TAG_END . '$/');
     foreach ($maintokens as $maintoken) {
         if ($eRegexp->match($maintoken)) {
             $m = $eRegexp->matches[1];
             break;
         }
     }
     if (isset($m)) {
         $rest = array_merge($maintokens, $tokens);
     } else {
         $childtokens = $this->_findBlocks($tokens);
         $blockstartRegexp = new LiquidRegexp('/^' . LIQUID_TAG_START . '\\s*block (\\w+)\\s*(.*)?' . LIQUID_TAG_END . '$/');
         $blockendRegexp = new LiquidRegexp('/^' . LIQUID_TAG_START . '\\s*endblock\\s*?' . LIQUID_TAG_END . '$/');
         $b = array();
         $name = null;
         $rest = array();
         $aufzeichnen = false;
         for ($i = 0; $i < count($maintokens); $i++) {
             if ($blockstartRegexp->match($maintokens[$i])) {
                 $name = $blockstartRegexp->matches[1];
                 if (isset($childtokens[$name])) {
                     $aufzeichnen = true;
                     array_push($rest, $maintokens[$i]);
                     foreach ($childtokens[$name] as $item) {
                         array_push($rest, $item);
                     }
                 }
             }
             if (!$aufzeichnen) {
                 array_push($rest, $maintokens[$i]);
             }
             if ($blockendRegexp->match($maintokens[$i]) && $aufzeichnen === true) {
                 $aufzeichnen = false;
                 array_push($rest, $maintokens[$i]);
             }
         }
     }
     $this->_hash = md5($source);
     $cache = LiquidTemplate::getCache();
     if (isset($cache)) {
         if (($this->_document = $cache->read($this->_hash)) != false && $this->_document->checkIncludes() != true) {
         } else {
             $this->_document = new LiquidDocument($rest, $this->_fileSystem);
             $cache->write($this->_hash, $this->_document);
         }
     } else {
         $this->_document = new LiquidDocument($rest, $this->_fileSystem);
     }
 }
Example #23
0
 /**
  * Resolves a given path to a full template file path, making sure it's valid
  *
  * @param string $template_path
  * @return string
  */
 function full_path($template_path)
 {
     $name_regex = new LiquidRegexp('/^[^.\\/][a-zA-Z0-9_\\/]+$/');
     if (!$name_regex->match($template_path)) {
         trigger_error("Illegal template name '{$template_path}'", E_USER_ERROR);
         return false;
     }
     if (strpos($template_path, '/') !== false) {
         $full_path = $this->root . dirname($template_path) . '/' . "_" . basename($template_path) . ".liquid";
     } else {
         $full_path = $this->root . "_" . $template_path . ".liquid";
     }
     $root_regex = new LiquidRegexp(realpath($root));
     if (!$root_regex->match(realpath($full_path))) {
         trigger_error("Illegal template path '" . realpath($full_path) . "'", E_USER_ERROR);
     } else {
         return $full_path;
     }
 }