<?php 

## makrell test file

require 'makrell.inc.php';
require 
'testik.php';

##########################################################################################
# utils

class MakrellTest extends Makrell {
    function 
parse($text) {
        
$this->parsed 1;
        return 
$text parent::parse($text);
    }
}

class 
BBParser extends PregParser
{
    function 
parse($text) {
        
$this->clip = new PregClipboard;
        
$text $this->kfun($text, array(
            
'~\[code\](.+?)\[/code\]~si' => '.code',
            
'~\[(/?(b|i|u))\]~i'         => '.tag'));
        return 
$this->clip->paste(htmlspecialchars($text));
    }
    function 
code($m) {
        return 
$this->clip->copy('<code>' htmlspecialchars($m[1]) . '</code>');
    }
    function 
tag($m) {
        return 
$this->clip->copy('<' $m[1] . '>');
    }
}


function 
fcleanup() {
    if(
is_dir('tmp'))
        foreach(
glob('tmp/*') as $funlink($f);
    foreach(
glob('*.tmp') as $funlink($f);
}

fcleanup();
@
mkdir('tmp');

function 
nows($s) {
    return 
trim(preg_replace('/\s+/'' '$s)); 
}

function 
mak($s) { 
    
$m = new MakrellParser;    
    
$s $m->parse($s);
    return 
nows($s);
}

function 
wfile($path$s) {
    
$fp fopen($path'wb');
    
fwrite($fp$s);
    
fclose($fp);
}


testik();

##########################################################################################
# PregParser 

# simple replacement

$m = new PregParser;
$m->gsub('foo''/o/''x'); # 'fxx'

$a = array('/[a-z]/''/[0-9]/');
$b = array('L''D');

$m->gsub('abc123'$a$b ); # 'LLLDDD'

function t1($x) { 
    return 
strrev($x[0]); 
}
$m->gfun('abc abd xyz''/ab./''t1'); # "cba dba xyz"

# repeated replacement

function trec($x) { 
    if(
strlen($x[1]) > 10) return '*';
    return 
"<{$x[0]}>";
}

$m->gfun('A B C''/(<*)([A-Z])(>*)/''trec');      # "<A> <B> <C>"
$m->gfun('A B C''/(<*)([A-Z])(>*)/''trec'1);   # "<A> <B> <C>"
$m->gfun('A B C''/(<*)([A-Z])(>*)/''trec'5);   # "<<<<<A>>>>> <<<<<B>>>>> <<<<<C>>>>>"
$m->gfun('A B C''/(<*)([A-Z])(>*)/''trec', -1);  # "* * *"

# ksub 

$a = array('/[a-z]/' => 'L''/[0-9]/' => 'D');
$m->ksub('abc123'$a); # 'LLLDDD'

# proof that ksub applies sequentially

$a = array('/[a-z]/' => '9''/[0-9]/' => '[$0]');
$m->ksub('abc123'$a); # "[9][9][9][1][2][3]"

# kfun 

$a = array(
    
'/[A-Z]+/' => create_function('$m''return ord($m[0]);'),
    
'/[0-9]+/' => create_function('$m''return intval($m[0])+100;'),
);
$m->kfun('A-B-C-1-2-3-D-E-F'$a); # "165-166-167-101-102-103-168-169-170"

# repeat

function trepeat($x$y 0) {
    return 
"<$x$y>";
}

$m->repeat('trepeat'1'a');      # "<a0>"
$m->repeat('trepeat'5'x''*'); # "<<<<<x*>*>*>*>*>"
$m->limit 7;
$m->repeat('trepeat', -1'y'''); # "<<<<<<<y>>>>>>>"

##########################################################################################
# PregClipboard

$m = new PregClipboard("\x07");

$t $m->cut('abc<def>ghi<jkl>xyz''/<[a-z]+>/'); 
$t strtoupper($t);
$t .= $m->copy('+++');

$m->paste($t); # "ABC<def>GHI<jkl>XYZ+++"

##########################################################################################
# MakrellParser

# a basic macro

$a = <<<TXT
foo {{bar}}
hi <foo>
TXT;

mak($a); # "hi <bar>"

# more macros

$a = <<<TXT
before {{ << }}
after {{ >> }}
mid {{ * }}
before mid after
TXT;

mak($a); # "<< * >>"

# unpaired braces

$a = <<<TXT
}}}}}
foo {{bar}}}}
hi <foo>
{{{{{
TXT;
    
mak($a); # "}}}}} }} hi <bar> {{{{{"
    
# slash is special

$a = <<<TXT
\\bar {{BAZ}}
hi <\\bar>
TXT;
    
mak($a); # "hi <BAZ>"    
    
# simple vars

$a = <<<TXT
one @str {{ [UNO @str] }}
two @a @b {{ [DUE (@a)(@b)] }}
three @a @b @c {{ [TRES (@a)(@x)(@b)] }}

one foobar 
and two abc def
and three 1 2 3
TXT;

mak($a); # "[UNO foobar ] and [DUE (abc)(def)] and [TRES (1)(@x)(2)]"

# typed vars

$a = <<<TXT
x @a:id @b:int  {{ [@a,@b] }}

x abc 12345
x ab% 12345
x abc zz

TXT;

mak($a); # "[abc,12345] x ab% 12345 x abc zz"

# bad type should be ignored

$a = <<<TXT
foo @z:zzz!{{ (@z) }}

foo abc!
TXT;

mak($a); # "(abc)"

# builtin types

$a = <<<TXT
(test @n:int)    {{<int>=<@n> }}
(test @n:string) {{<string>=<@n> }}

(test @n:alpha)  {{<alpha>=<@n> }}
(test @n:alnum)  {{<alnum>=<@n> }}
(test @n:id)     {{<id>=<@n> }}

(test @n:ns)     {{<ns>=<@n> }}
(test @n:nobr)   {{<nobr>=<@n> }}
(test @n:br)     {{<br>=<@n> }}
(test @n:any)    {{<any>=<@n> }}

(test 123)
(test "x\\"y")
(test 'z')
(test _id45)
(test ABC)
(test ABD789)
(test !#$%^)
space=(test     )
breaks=(test 


)

(test 
    1
    2
    3)
TXT;


mak($a); # "<int>=<123> <string>=<\"x\\\"y\"> <string>=<'z'> <id>=<_id45> <alpha>=<ABC> <alnum>=<ABD789> <ns>=<!#$%^> space=<nobr>=< > breaks=<br>=< > <any>=< 1 2 3>"


# priority and nested macros

$a = <<<TXT
def_@foo {{{
    macro_@foo @bar {{  @bar in @foo }}
}}}

def_xyz
macro_xyz quux
def_abc
macro_abc blah
TXT;

mak($a); # "quux in xyz blah in abc"

$a = <<<TXT
{{ both outer and inner are known }}
outer {{
    begin
    inner {{ IN }}
    end
}}
[inner]
TXT;

mak($a); # "[ IN ]"

$a = <<<TXT
{{ both outer and inner are known }}
outer {{
    begin
    inner {{ IN }}
    end
}}
[outer]
TXT;

mak($a); # "[ begin end ]"

$a = <<<TXT
{{ inner is not known, because outer is not instantiated }}
outer {{{
    begin
    inner {{ IN }}
    end
}}}
[inner]
TXT;

mak($a); # "[inner]"

$a = <<<TXT
{{ inner is known, because outer is instantiated }}
outer {{{
    begin
    inner {{ IN }}
    end
}}}
[inner] and [outer]
TXT;

mak($a); # "[ IN ] and [ begin end ]"

# command quote

$a = <<<TXT
a {{ A }}
    aa
    {{ quote aa1 }}
    aa
    {{ quote aa2 }}
TXT;

mak($a); # "A A aa1 A A aa2"

# command type

$a = <<<TXT
{{ type abc [ab]+c? }}

(test @var:abc) {{ [y @var] }}
(test @var)     {{ [n @var] }}

(test abba) (test bbac)
(test xxyy) (test abxx)
TXT;

mak($a); # "[y abba] [y bbac] [n xxyy] [n abxx]"

# command include

wfile('tmp/a.tmp', <<<TXT
AAA [[
{{ include b.tmp }}
]]
TXT
);

wfile('b.tmp', <<<TXT
BBB
TXT
);

$a = <<<TXT
begin
    beginA
    {{ include tmp/a.tmp }}
    endA
    
    beginB
    {{ include b.tmp }}
    endB
end
TXT;

mak($a); # "begin beginA AAA [[ BBB ]] endA beginB BBB endB end"

# include + quote

wfile('tmp/a.tmp', <<<TXT
<a
macro_a {{ hi }}
{{ include b.tmp }}
>
TXT
);

wfile('b.tmp', <<<TXT
[b
{{ quote macro_a }} 
]
TXT
);

$a = <<<TXT
    macro_a
    {{ include tmp/a.tmp }}
    {{ include b.tmp }}
TXT;

mak($a); # "hi <a [b macro_a ] > [b macro_a ]"

# include + priority

wfile('tmp/a.tmp', <<<TXT
<a
macro_inc {{{ 
    {
        {{ include b.tmp }}
    }
}}}
>
TXT
);

wfile('b.tmp', <<<TXT
content_b
TXT
);

$a = <<<TXT
    (macro_inc)
    {{ include tmp/a.tmp }}
TXT;

mak($a); # "( { content_b } ) <a >"

##########################################################################################
# Makrell

$m = new MakrellTest;
$m->cachedir 'tmp';
$m->set('a''A');
$m->set(array('b' => 'B''c' => 'C'));

wfile('b.tmp', <<<TXT
    puts @var:id {{ <?php echo $@var ?> }}
    [puts a]-[puts b]-[puts c]
TXT
);

touch('b.tmp'time() - 100);

$m->parsed 0;
$html $m->render('b.tmp');
$m->parsed# 1

$m->parsed 0;
$html $m->render('b.tmp');
$m->parsed# 0

trim($html); # "[ A ]-[ B ]-[ C ]"


##########################################################################################
# examples

$a = <<<TXT
compare @a to @b {{ strcmp("@b", "@a") }}
compare apples to oranges
TXT;

mak($a); # 'strcmp("oranges", "apples")'

$a = <<<TXT

<macro name="@key">@body:any</macro> {{{ 
    @key {{@body}} 
}}}


<macro name="foo">BAR</macro>

<foo!>
TXT;
    
mak($a); # "<BAR!>"

$text "
    [b]bold[/b] and [i]italic[/i]
    <script src=evil>
    [code] x = a[i] > a[b] [/code]
"
;

$b = new BBParser;
nows($b->parse($text)); # "<b>bold</b> and <i>italic</i> &lt;script src=evil&gt; <code> x = a[i] &gt; a[b] </code>"


wfile('b.tmp', <<<TXT
sayhello {{ <h1>hello_text</h1> }}
hello_text {{ base }}
TXT
);

$a = <<<TXT
{{include b.tmp}}
sayhello
TXT;
    
mak($a); # "<h1> base </h1>"

$a = <<<TXT
{{{ include b.tmp }}}
hello_text {{ deriv }}
sayhello

TXT;
    
mak($a); # "<h1> deriv </h1>"

##########################################################################################


fcleanup();
@
rmdir('tmp');

?>