TODO:
-	iBlock: Listen/Felder:
	<table>
	<tr><th><+$ head1 / $+></th><th><+$ head2 / $+></th></tr>
	<+@ rows @+>
		<tr><td><+$ field1 / $+></td><td><+$ field2 $+>default2<+$ / $+></td><+@ / @+></tr>
	<+@ / @+>
	</table>
	==>
	prepare mit & UND +@ und +$.
	?? +@ und +$ bauen einen parallelen baum auf, der auf die einzelnen template-elemente zeigt.
	my $iblocktemplate = {
		fields => {
			head1 => $tagnode,
			head2 => $tagnode,
		},
		lists => {
			rows => {
				node => $tagnode,
				fields => {
					field1 => $tagnode,
					field2 => $tagnode,
				},
			}
		}
	}
	
	<& iblock src="..." &>
		<$ head1 $>a<$ / $>
		<$ head2 $>b<$ / $>
		<@ rows @>
			<$ field1 $>c<$ / $>
			<$ field2 $>d<$ / $>
		<@ / @>
	<& / &>
	==>
	my $iblock_data = {
		fields => {
			head1 => $tagnode,
			head2 => $tagnode
		},
		lists => {
			rows => [
				{ field1 => $tagnode, field2 => $tagnode },
				{ field1 => $tagnode, field2 => $tagnode },
				{ field1 => $tagnode },
				...
			]
		}
	};

-	iBlock: Listen in Listen?!
	<table>
	<+@ rows @+>
		<tr>
			<+@ columns @+><td><+$ field / $+></td><+@ / @+>
		</tr>
	<+@ / @+>
	</table>
	
	==>
	prepare mit & UND +@ und +$.
	+@ und +$ bauen einen parallelen baum auf, der auf die einzelnen template-elemente zeigt.
	my $iblocktemplate = {
		fields => undef,
		lists => {
			rows => {
				node => $tagnode,
				fields => undef,
				lists => {
					columns => {
						fields => {
							field => $tagnode
						},
						lists => undef
					}
				}
			}
		}
	}
	
	<& iblock src="..." &>
		<@ rows @>
			<@ columns @>
				<$ field $>a<$ / $>
				<$ field $>b<$ / $>
			<@ / @>
			<@ columns @>
				<$ field $>c<$ / $>
				<$ field $>d<$ / $>
			<@ / @>
		<@ / @>
	<& / &>
	
	==> generische form
	my $iblock_data = {
		fields => {
			field1 => 'value1',
			field2 => 'value2'
		},
		lists => {
			rows => [
				{
					fields => { line => $number },
					lists => {
						columns => [
							{ fields => {field1 => $tagnode, field2 => $tagnode} },
							{ fields => {field1 => $tagnode, field2 => $tagnode} }
						]
					}
				}
				...
			]
		}
	}
	
Vorgehensweise:========================================
Page compilation:
-	Cache vorhanden (im RAM oder auf Platte)?
	-	Prfung auf gltigen Cache:
		Jedes Plugin, das statischen Inhalt zurckgibt, kann eine Bedingung ein die gecachte Datei einfgen, die erfllt sein muss, damit der Cache noch aktuell ist.
		Z.B. Datei-Datum nicht neuer als XY, neuester Eintrag in einer SQL-Tabelle nicht neuer als XY, etc.
	-	Cache teilweise dynamischer Datei (.ihtml.prepared)
		-> Vorbereiteten Baum laden und execute'n (Execute, Display)
	-	Kein Cache:
		-> Datei lesen, Prepare, Cache, Execute, Display
		
Prepare (Parser):
	-	Aufruf: iBlock::Compiler->prepare($input, $actions)
		-	$input: Baum (Hashref) oder String (Scalarref)
		-	$actions: Hashref mit den zu bercksichtigenden Tags und den damit verknpften Aktionen:
			{
				'&' => 'iBlock::Handlers::Plugin'-obj,
				'~' => 'iBlock::Handlers::Shortcut'-obj,
			}
			Soll bei einem bestimmten Tag-Typ keine Aktion ausgefhrt werden, so weist man dem Hash-Key den Wert "undef" zu.
			Andernfalls wird $obj->handle() ausgefhrt.
	
	->	Strings werden in einen Baum mit einem Knoten transformiert.
	
	Innerhalb des Eingabebaumes verfhrt der Parser folgendermaen:
	-	Alle Nodes bis auf den Typ plaintext (p) werden bersprungen, da sie schon Ergebnis vorherigen Parsens sind.
	-	Kommentare (type: c) werden grundstzlich bersprungen und nicht bearbeitet.
	-	Jeder plaintext Node wird entsprechend einer (festen) regexp (z.B. /(<!--|-->|<&|&>)/) in Tokens (Tags) gesplittet.	Der plaintext Node wird entfernt.
	-	Die Tokens werden auf Relevanz hin berprft. Relevante Tokens knnen z.B. Plugin Tags sein (<& &>).
		-	Wird ein ffnendes Comment Tag gefunden, werden alle Tokens bis zum Ende des Comments zu einem Comment Node zusammengefasst
		-	Wird ein Tag-Start (<&) gefunden, so muss geprft werden, ob alle Tokens bis zum Tag-Ende (&>) statisch (plaintext) sind
			Falls ja, so werden diese Tokens zusammengefasst und das Tag wird geparst und in einen entsprechenden Hash umgewandelt.
			Falls nein, wird ein vorlufiges Tag erstellt, das noch nicht geparst wird, und das als die noch zu parsenden Tokens als Unterbaum speichert.
			Die Tokens nach dem Tag-Ende werden dann wie bei einem vollstndig geparsten Tag als Child-Nodes angehangen.
		-	Wurde ein ffnendes, vollstndig geparstes Tag gefunden, wird es an aktueller Position in aktueller Ebene eingefgt. Alle folgenden Tokens sind nun Child-Nodes dieses Tags.
		-	Wird ein schlieendes Tag gefunden, springt der Parser eine Ebene hher im Baum und prft, ob das Tag vollstndig geparst wurde.
			Falls ja fhrt er die mit dem Tag verknpfte Prepare-Funktion aus: $handler->prepare().
			Der auszufhrenden Funktion wird eine Referenz auf einen Baum bergeben, die auf den Tag-Node selbst zeigt.
			Die Funktion kann direkte Vernderungen an dem Baum und an dem Tag-Node vornehmen. Wenn die Funktion lediglich Vernderungen direkt im Baum
			vorgenommen hat, gibt sie "undef" zurck. Ansonsten, wenn sie z.B. mehrere Nodes zurckgibt, oder den Node lschen mchte, gibt sie eine Referenz
			auf ein Array mit den Nodes zurck, die an Stelle des Funktions-Nodes eingesetzt werden sollen bzw. eine Referenz auf eine leere Liste.
		-	Die Funktion kann die Child-Nodes auch nur teilweise bearbeiten. Die vollstndige Bearbeitung muss erst beim Execute'n geschehen.
			Eine teilweise Bearbeitung ist immer dann der Fall, wenn sich noch dynamische Inhalte unterhalb des Nodes befinden.
		-	Nachdem eine Funktion ausgefhrt wurde, wird berprft, ob sie dynamische Inhalte zurckgegeben hat, also ob das dynamic-Tag nach der Ausfhrung
			im Node selbst oder in einem Node der Rckgabeliste gesetzt wird. Der Parent-Node wird dann ggf. auch dynamisch. $parent->{dynamic} ||= $child->{dynamic};
		-	Wurden statische Inhalte zurckgegeben, wird geprft, ob Geschwister vor diesem Node auch statisch und gleichen Typs sind, ggf. Zusammenfassung.
		-	Sprung hinter den bearbeiteten Node/hinter die Rckgabeliste.
	-	Sind alle Nodes dieser Ebene verarbeitet worden, so ist das Parsen/Preparen abgeschlossen.

Execute:
	Beim Execute'n wird der durch das Prepare'n entstandene Baum durchlaufen und die Funktions-Tags werden Bottom-up ausgefhrt.
	(1) Je Knoten auf aktueller Ebene:
		(1.1) Node ist dynamischen Typs (Tag). Ausfhren des Handlers (z.B. Plugin-Handler). Das entsprechende Plugin muss ausgefhrt werden ($plugin->handle()):
			(1.1.1) Hat der aktuelle Knoten Kinder?
				-Ja: Springe zunchst eine Ebene tiefer und bearbeite die dortigen Knoten ("Rekursion"), gehe dort zu (1.1).
					Das Plugin kann den Inhalt des Nodes komplett verndern.
			(1.1.2)
				-	Es mssen statische Elemente (c/p) zurckgegeben werden. Jegliche dynamischen Elemente/Plugins werden gezwungen, ihre Funktion auszufhren und
					statischen Inhalt zurckzugeben.
					Dynamische Plugins wie z.b. &embperl, &date, &embperl_mysql, &env, &param, &sql mssen nun ausgefhrt werden und statischen Inhalt zurckgeben.
					Dieser statische Inhalt kann je nach plugin (z.B. bei &embperl, &forum) nochmals auf Sonderfunktionen (Plugins, ...) geparst werden (->prepare).
					Nach dem prepare wird (1.1.2) erneut durchgefhrt.
				-	Nachdem statischer Inhalt (ggf. auch mehrere Nodes) zurckgegeben wurden, muss geprft werden, ob vor dem ersten zurckgegebenen Node ein Node
					gleichen Typs (c/p) existiert. Ggf. Zusammenfassung.
				-	Sprung hinter die Liste zurckgegebener Nodes. Fahre bei (1.1.1) fort.
	(2) Nachdem alle Leaf-Nodes bearbeitet wurden, springt man eine Ebene hher und setzt dort die Bearbeitung bei (1.1.2) fort (Rekursionsrcksprung).

Vorgehensweise (konkret bei <& iBlock &>):=============
Prepare (P) / Execute (E)
	(E) Kann eigentlich nur auftreten, wenn im Prepare-Durchlauf noch dynamische Elemente (Funktionen) im Baum geblieben sind.
		Da Execute rekursiv bottom-up ausgefhrt wird, sollte der Tag-Node nur noch statische Child-Nodes haben, die sich jedoch ber mehrere Ebenen erstrecken
		knnen, da im Prepare-Durchlauf schon vorlufig auf $/@ geparst wurde.
	(E) Nur statische Nodes. Gehe zu "(P) - Nein:"
	(P/E) Beinhaltet der Knoten dynamische Child-Nodes?
		-	Ja:
			-	Es kann noch kein Field-H0ash erstellt werden.
				Subtree (Hauptdatei) wurde so weit wie mglich geparst, jedoch sind noch dynamische Elemente vorhanden.
				Keine weitere Bearbeitung fr den prepare-Durchlauf mglich. exit sub.
		-	Nein:
			-	Durchlaufe den Baum und erstelle einen Field-Hash. Der Baum kann nun gelscht werden.
			-	Der Subtree (Hauptdatei) war statisch und wurde vollstndig geparst. Es existiert ein Field-Hash. Nun muss die .iblock-Datei bearbeitet werden.
			-	Geforderte .iBlock-Datei laden und verarbeiten:
				-	Existiert ein aktueller Cache (.iblock.prepared) fr die geforderte .iBlock-Datei?
					-Ja:
						-	Baum Laden.
					-Nein:
						-	Geforderte .iBlock-Datei laden.
						-	->prepare(&,~,+$,+@).
						-	collect_fields anwenden und parallelen Baum erzeugen, der auf die +$- und +@-Tags zeigt. Diesen Baum im root-Node der iBlock-Datei speichern.
						-	Speichern in .iblock.prepared.
				-	Falls Template-Fields vorhanden sind, Ersetzung der Template-Fields (+$, +@) mit den Werten aus dem Field-Hash.
				-	Die iBlock-Substitution wurde durchgefhrt. Ersetzung des Tags im Baum durch den bearbeiteten .iblock-Baum.
					Dieser kann statisch aber auch teilweise dynamisch sein.

