<commit_before><?php

namespace Laiz\Template;

require_once 'Template.php';

class Parser extends Template
{
    private $tagOpened = false;
    private $attrOpend = false;
    private $behaviors = array('b' => 'nl2br',
                               'n' => 'number_format',
                               'u' => 'urlencode');
    private $plains = array('h', 'a');
    private $tagStack = array();
    public function __construct($templateDir = null, $cacheDir = null)
    {
        parent::__construct($templateDir, $cacheDir);
    }

    public function addBehavior($char, $callback, $isPlain = false)
    {
        $this->behaviors[$char] = $callback;
        if ($isPlain)
            $this->plains[] = $char;
    }
    private function parse($buf)
    {
        $length = strlen($buf);
        $ret = '';
        for ($i = 0; $i < $length;){
            $char = $buf[$i];

            if ($char === '<'){
                list($parsed, $len) = $this->parseTag(substr($buf, $i));
            }else if ($char === '{'){
                list($parsed, $len) = $this->parseVal(substr($buf, $i));
            }else{
                $parsed = $char;
                $len = 1;
            }
            $ret .= $parsed;
            $i += $len;
        }
        return $ret;
    }

    private function parseAttr($tagName, $close, $buf)
    {
        if (!preg_match("/^$close([^$close]*)$close/", $buf, $matches))
            return array($buf[0], 1);

        $val = $matches[1];
        $length = strlen($val);

        $ret = '';
        $append = null;

        for ($i = 0; $i < $length;){
            $char = $val[$i];

            if ($char === '{'){
                list($parsed, $len) = $this->parseVal(substr($val, $i));

            }else{
                $parsed = $char;
                $len = 1;
            }
            $ret .= $parsed;
            $i += $len;
        }

        return array($close . $ret . $close, $length + 2, $append);
    }

    private function pushPhp($phpcode)
    {
        $this->tagStack[count($this->tagStack)-1]['php'] =
            '<?php ' . $phpcode . "\n?>\n"
            . $this->tagStack[count($this->tagStack)-1]['php'];
    }

    private function popTag($closeTag)
    {
        $index = count($this->tagStack) - 1;
        for ($i = $index; $i >= 0; $i--){
            $tag = array_pop($this->tagStack);
            if ($tag['tag'] === $closeTag){
                if ($tag['php'])
                    return $tag['php'];
                else
                    return '';
            }
        }
        return '';
    }
    private function parseTag($buf)
    {
        if (preg_match('|^</ *([[:alnum:]]+) *>|', $buf, $matches)){
            // close tag
            $tagName = $matches[1];
            $append = $this->popTag($tagName);
            return array($matches[0] . $append, strlen($matches[0]));
        }
        if (!preg_match('/^< *([[:alnum:]]+)/', $buf, $matches))
            return array($buf[0], 1);

        $tagName = $matches[1];
        $this->tagStack[] = array('tag' => $tagName, 'php' => null);

        $length = strlen($buf);
        $ret = '';

        $loop = '/^laiz:loop="([[:alnum:].]+):([[:alnum:]_]+)(:[[:alnum:]]+)?"/';
        $if = '/^laiz:if(el)?="([[:alnum:].]+)"/';

        $php = '';
        for ($i = 0; $i < $length;){
            $char = $buf[$i];

            $sub = substr($buf, $i);
            if (preg_match($loop, $sub, $m)){

                $ite = str_replace('.', '->', $m[1]);
                if (isset($m[3])){
                    $v = ltrim($m[3], ':');
                    $php .= "<?php foreach(\$$ite as \$$m[2]=>\$$v): ?>";
                }else{
                    $php .= "<?php foreach(\$$ite as \$$m[2]): ?>";
                }
                $len = strlen($m[0]);
                $this->pushPhp('endforeach;');
                $parsed = '';

            }else if (preg_match($if, $sub, $m)){
                if ($m[1]){
                    $this->pushPhp('else:');
                }else{<commit_msg>add under score character to variable name.<commit_after><?php

namespace Laiz\Template;

require_once 'Template.php';

class Parser extends Template
{
    private $tagOpened = false;
    private $attrOpend = false;
    private $behaviors = array('b' => 'nl2br',
                               'n' => 'number_format',
                               'u' => 'urlencode');
    private $plains = array('h', 'a');
    private $tagStack = array();
    public function __construct($templateDir = null, $cacheDir = null)
    {
        parent::__construct($templateDir, $cacheDir);
    }

    public function addBehavior($char, $callback, $isPlain = false)
    {
        $this->behaviors[$char] = $callback;
        if ($isPlain)
            $this->plains[] = $char;
    }
    private function parse($buf)
    {
        $length = strlen($buf);
        $ret = '';
        for ($i = 0; $i < $length;){
            $char = $buf[$i];

            if ($char === '<'){
                list($parsed, $len) = $this->parseTag(substr($buf, $i));
            }else if ($char === '{'){
                list($parsed, $len) = $this->parseVal(substr($buf, $i));
            }else{
                $parsed = $char;
                $len = 1;
            }
            $ret .= $parsed;
            $i += $len;
        }
        return $ret;
    }

    private function parseAttr($tagName, $close, $buf)
    {
        if (!preg_match("/^$close([^$close]*)$close/", $buf, $matches))
            return array($buf[0], 1);

        $val = $matches[1];
        $length = strlen($val);

        $ret = '';
        $append = null;

        for ($i = 0; $i < $length;){
            $char = $val[$i];

            if ($char === '{'){
                list($parsed, $len) = $this->parseVal(substr($val, $i));

            }else{
                $parsed = $char;
                $len = 1;
            }
            $ret .= $parsed;
            $i += $len;
        }

        return array($close . $ret . $close, $length + 2, $append);
    }

    private function pushPhp($phpcode)
    {
        $this->tagStack[count($this->tagStack)-1]['php'] =
            '<?php ' . $phpcode . "\n?>\n"
            . $this->tagStack[count($this->tagStack)-1]['php'];
    }

    private function popTag($closeTag)
    {
        $index = count($this->tagStack) - 1;
        for ($i = $index; $i >= 0; $i--){
            $tag = array_pop($this->tagStack);
            if ($tag['tag'] === $closeTag){
                if ($tag['php'])
                    return $tag['php'];
                else
                    return '';
            }
        }
        return '';
    }
    private function parseTag($buf)
    {
        if (preg_match('|^</ *([[:alnum:]]+) *>|', $buf, $matches)){
            // close tag
            $tagName = $matches[1];
            $append = $this->popTag($tagName);
            return array($matches[0] . $append, strlen($matches[0]));
        }
        if (!preg_match('/^< *([[:alnum:]]+)/', $buf, $matches))
            return array($buf[0], 1);

        $tagName = $matches[1];
        $this->tagStack[] = array('tag' => $tagName, 'php' => null);

        $length = strlen($buf);
        $ret = '';

        $loop = '/^laiz:loop="([[:alnum:]._]+):([[:alnum:]_]+)(:[[:alnum:]_]+)?"/';
        $if = '/^laiz:if(el)?="([[:alnum:]._]+)"/';

        $php = '';
        for ($i = 0; $i < $length;){
            $char = $buf[$i];

            $sub = substr($buf, $i);
            if (preg_match($loop, $sub, $m)){

                $ite = str_replace('.', '->', $m[1]);
                if (isset($m[3])){
                    $v = ltrim($m[3], ':');
                    $php .= "<?php foreach(\$$ite as \$$m[2]=>\$$v): ?>";
                }else{
                    $php .= "<?php foreach(\$$ite as \$$m[2]): ?>";
                }
                $len = strlen($m[0]);
                $this->pushPhp('endforeach;');
                $parsed = '';

            }else if (preg_match($if, $sub, $m)){
                if ($m[1]){
                    $this->pushPhp('else:');
                }else{
{'fraction_non_alphanumeric': 0.21033757883022133, 'fraction_numerical': 0.006677383454927662, 'mean_word_length': 1.4993819530284302, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1049934', 'n_tokens_mistral': 2642, 'n_tokens_neox': 2543, 'n_words': 511}