Source for file parser.php
Documentation is available at parser.php
* LODEL - Logiciel d'Edition ELectronique.
* Copyright (c) 2001-2002, Ghislain Picard, Marin Dacos
* Copyright (c) 2003, Ghislain Picard, Marin Dacos, Luc Santeramo, Nicolas Nutten, Anne Gentil-Beccot
* Copyright (c) 2004, Ghislain Picard, Marin Dacos, Luc Santeramo, Anne Gentil-Beccot, Bruno Cénou
* Copyright (c) 2005, Ghislain Picard, Marin Dacos, Luc Santeramo, Gautier Poupeau, Jean Lamy, Bruno Cénou
* Copyright (c) 2006, Marin Dacos, Luc Santeramo, Bruno Cénou, Jean Lamy, Mikaël Cixous, Sophie Malafosse
* Home page: http://www.lodel.org
* E-Mail: lodel@lodel.org
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* @author Ghislain Picard
* @copyright 2005, Ghislain Picard, Marin Dacos, Luc Santeramo, Gautier Poupeau, Jean Lamy, Bruno Cénou
* @copyright 2006, Marin Dacos, Luc Santeramo, Bruno Cénou, Jean Lamy, Mikaël Cixous, Sophie Malafosse
* @licence http://www.gnu.org/copyleft/gpl.html
function parse($in, $out)
$parser->parse($in, $out);
var $isphp = false; // the parser produce a code which produce either html, either php. In the latter, a sequence must be written at the beginning to inform the cache system.
function errmsg($msg, $ind = 0)
// Ŕ REVOIR : déterminer le numéro de ligne dans le template
//$line = "line ".$this->linearr[$ind];
//die("LODELSCRIPT ERROR line $line (".$this->infilename."): $msg");
die("LODELSCRIPT ERROR in file ". $this->infilename. " : $msg");
function parse_loop_extra(& $tables, & $tablesinselect, & $extrainselect, & $selectparts)
$this->commands = array ("USE", "MACRO", "FUNC", "LOOP", "IF", "LET", "ELSE", "DO", "DOFIRST", "DOLAST", "BEFORE", "AFTER", "ALTERNATIVE", "ESCAPE", "CONTENT", "SWITCH", "CASE");
$this->codepieces = array ('sqlfetchassoc' => "mysql_fetch_assoc(%s)", 'sqlquery' => "mysql_query(%s)", 'sqlerror' => "or mymysql_error(%s,%s)", 'sqlfree' => "mysql_free_result(%s)", 'sqlnumrows' => "mysql_num_rows(%s)");
function parse($in, $out)
$this->errmsg("Unable to read file $in");
$file .= fread($fp, 1024);
$this->_split_file($contents); // split the contents into commands
$this->errmsg("this file contains more closing tags than opening tags");
$contents = join("", $this->arr); // recompose the file
unset ($this->arr); // save memory now.
$this->parse_after($contents); // user defined parse function
// remove <DEFMACRO>.*?</DEFMACRO>
$contents = preg_replace("/<DEF(MACRO|FUNC)\b[^>]*>.*?<\/DEF(MACRO|FUNC)>\s*\n?/s", "", $contents);
#die("::".$this->refresh);
$code = '<'. '?php if ($GLOBALS[cachedfile] && !$dontcheckrefresh) { $cachetime=filemtime($GLOBALS[cachedfile].".php"); ';
// refresh period in second
$code .= ' if($cachetime+'. $this->refresh. '<time()) return "refresh"; ';
$code .= '$now = time(); $date = getdate($now);';
foreach ($refreshtimes as $refreshtime) {
$code .= '$refreshtime=mktime('. intval($refreshtime[0]). ','. intval($refreshtime[1]). ','. intval($refreshtime[2]). ',$date[mon],$date[mday],$date[year]);';
$code .= 'if ($cachetime<$refreshtime && $now>$refreshtime) return "refresh"; ';
$contents = '<'. '?php echo \''. quote_code($code). '\'; ?>
} elseif ($this->isphp) {
$contents = '<?php if ($GLOBALS[cachedfile]) echo \'<?php #--# ?>\'; ?>'. $contents; // this is use to check if the output is a must be evaluated as a php or a raw file.
// clean the open/close php tags
$contents = preg_replace(array ('/\?><\?(php\b)?/', '/<\?php[\s\n]*\?>/'), array ("", ""), $contents);
require_once TOINCLUDE. 'utf8.php'; // conversion des caracteres
@unlink($out); // detruit avant d'ecrire.
$fp = fopen($out, "w") or $this->errmsg("cannot write file $out");
if ($GLOBALS['filemask'])
// parenthesis syntaxe [(
// look for the name of the variable now
if ($text {$i} < 'A' || $text {$i} > 'Z')
continue; // not a variable
while (($text {$i} >= 'A' && $text {$i} <= 'Z') || ($text {$i} >= '0' &&
$text {$i} <= '9') || $text {$i} == "_" || $text {$i} == ".") {
if ($text {$i} == ":") { // a lang
while ($text {$i} >= 'A' && $text {$i} < 'Z') {
$pipefunction = '|multilingue("'. $lang. '")';
if ($text {$i} == "|") { // have a pipe function
// look for the end of the variable
$mustparse = true; // potentially a new variable
$pipefunction .= $text {$i};
$i -- ; // comes back to the bracket.
if ($para && $pipefunction {strlen($pipefunction) - 1 } == ")") {
$pipefunction = substr($pipefunction, 0, - 1);
// look for a proper end of the variable
if ($para && $text {$i} == ")" && $text {$i + 1} == "]") {
} elseif (!$para && $text {$i} = "]") {
continue; // not a variable
// build the variable code
$i = $startvar + strlen($varcode); // move the counter
} // while there are some variable
if ($variable === false) { // has the variable being processed ?
if ($pipefunction) { // traitement particulier ?
//echo $pipefunction."<br />";
$array = preg_split('/(?=\|[a-z]*[^\'|^\"]+)/',$pipefunction);
foreach($array as $fct) {
//foreach (explode("|", $pipefunction) as $fct) {
#foreach (preg_split ('/(?<!")(\|)(?!")/', $pipefunction) as $fct) {
// note that explode is a little bit radical. It should be more advanced parser
if ($fct == "false" || $fct == "true" || $fct == "else") {
if ($fct == "elsefunction") {
if (preg_match("/^([A-Za-z][A-Za-z_0-9]*)\((.*?)\)$/", $fct, $result)) {
} elseif (preg_match("/^([A-Za-z][A-Za-z_0-9]*)$/", $fct)) {
$this->errmsg("The name of the pipe function \"$fct\" is invalid");
//$variable = $fct. '('. $variable.$args. ')';
//si la variable est contenue dans les arguments :
$variable = "$fct($variable$args)";
// traitement normal, php espace
$testcode = ' echo '. $variable. ';';
$code = '<'. '?php '. $testcode. ' ?'. '>';
$code = '".'. $variable. '."';
$testcode = ' echo "'. $code. '";';
// unable to test the code....
// must use the PEAR::PHP_Parser
switch ($this->arr[$this->ind]) {
$this->charset = $attrs['CHARSET'] ? $attrs['CHARSET'] : "iso-8859-1";
if ($attrs['MACROFILE']) {
$macrofilename = $attrs['MACROFILE'];
} elseif ($GLOBALS['sharedir'] && file_exists($siteroot. $GLOBALS['sharedir']. "/macros/". $macrofilename)) {
$contents = file_get_contents($siteroot. $GLOBALS['sharedir']. "/macros/". $macrofilename);
} elseif (file_exists($GLOBALS['home']. "../tpl/". $macrofilename)) {
$this->errmsg("the macro file \"$macrofilename\" doesn't exist");
} elseif ($attrs['TEMPLATEFILE']) {
$this->arr[$this->ind] = '<?php insert_template($context,"'. basename($attrs['TEMPLATEFILE']). '"); ?>';
if ($this->arr[$this->ind]{0} == '/') {
if ($this->arr[$this->ind + 1])
$this->errmsg("The closing tag ". $this->arr[$this->ind]. " is malformed");
$methodname = 'parse_'. $this->arr[$this->ind];
#call_user_func(array(&$this,$methodname));
|