library/smarty/lexer/smarty_internal_configfileparser.y
changeset 0 4869aea77e21
new file mode 100644
--- /dev/null
+++ b/library/smarty/lexer/smarty_internal_configfileparser.y
@@ -0,0 +1,362 @@
+/**
+* Smarty Internal Plugin Configfileparser
+*
+* This is the config file parser
+* 
+* 
+* @package Smarty
+* @subpackage Config
+* @author Uwe Tews
+*/
+%name TPC_
+%declare_class {
+/**
+* Smarty Internal Plugin Configfileparse
+*
+* This is the config file parser.
+* It is generated from the smarty_internal_configfileparser.y file
+* @package Smarty
+* @subpackage Compiler
+* @author Uwe Tews
+*/
+class Smarty_Internal_Configfileparser
+}
+%include_class
+{
+    /**
+     * result status
+     *
+     * @var bool
+     */
+    public $successful = true;
+    /**
+     * return value
+     *
+     * @var mixed
+     */
+    public $retvalue = 0;
+    /**
+     * @var
+     */
+    public $yymajor;
+    /**
+     * lexer object
+     *
+     * @var Smarty_Internal_Configfilelexer
+     */
+    private $lex;
+    /**
+     * internal error flag
+     *
+     * @var bool
+     */
+    private $internalError = false;
+    /**
+     * compiler object
+     *
+     * @var Smarty_Internal_Config_File_Compiler
+     */
+    public $compiler = null;
+    /**
+     * smarty object
+     *
+     * @var Smarty
+     */
+    public $smarty = null;
+    /**
+     * copy of config_overwrite property
+     *
+     * @var bool
+     */
+    private $configOverwrite = false;
+    /**
+     * copy of config_read_hidden property
+     *
+     * @var bool
+     */
+    private $configReadHidden = false;
+    /**
+     * helper map
+     *
+     * @var array
+     */
+    private static $escapes_single = Array('\\' => '\\',
+                                           '\'' => '\'');
+
+    /**
+     * constructor
+     *
+     * @param Smarty_Internal_Configfilelexer      $lex
+     * @param Smarty_Internal_Config_File_Compiler $compiler
+     */
+    function __construct(Smarty_Internal_Configfilelexer $lex, Smarty_Internal_Config_File_Compiler $compiler)
+    {
+        // set instance object
+        self::instance($this);
+        $this->lex = $lex;
+        $this->smarty = $compiler->smarty;
+        $this->compiler = $compiler;
+        $this->configOverwrite = $this->smarty->config_overwrite;
+        $this->configReadHidden = $this->smarty->config_read_hidden;
+    }
+
+    /**
+     * @param null $new_instance
+     *
+     * @return null
+     */
+    public static function &instance($new_instance = null)
+    {
+        static $instance = null;
+        if (isset($new_instance) && is_object($new_instance)) {
+            $instance = $new_instance;
+        }
+        return $instance;
+    }
+
+    /**
+     * parse optional boolean keywords
+     *
+     * @param string $str
+     *
+     * @return bool
+     */
+    private function parse_bool($str)
+    {
+        $str = strtolower($str);
+        if (in_array($str, array('on', 'yes', 'true'))) {
+            $res = true;
+        } else {
+            $res = false;
+        }
+        return $res;
+    }
+
+    /**
+     * parse single quoted string
+     *  remove outer quotes
+     *  unescape inner quotes
+     *
+     * @param string $qstr
+     *
+     * @return string
+     */
+    private static function parse_single_quoted_string($qstr)
+    {
+        $escaped_string = substr($qstr, 1, strlen($qstr) - 2); //remove outer quotes
+
+        $ss = preg_split('/(\\\\.)/', $escaped_string, - 1, PREG_SPLIT_DELIM_CAPTURE);
+
+        $str = "";
+        foreach ($ss as $s) {
+            if (strlen($s) === 2 && $s[0] === '\\') {
+                if (isset(self::$escapes_single[$s[1]])) {
+                    $s = self::$escapes_single[$s[1]];
+                }
+            }
+            $str .= $s;
+        }
+        return $str;
+    }
+
+    /**
+     * parse double quoted string
+     *
+     * @param string $qstr
+     *
+     * @return string
+     */
+    private static function parse_double_quoted_string($qstr)
+    {
+        $inner_str = substr($qstr, 1, strlen($qstr) - 2);
+        return stripcslashes($inner_str);
+    }
+
+    /**
+     * parse triple quoted string
+     *
+     * @param string $qstr
+     *
+     * @return string
+     */
+    private static function parse_tripple_double_quoted_string($qstr)
+    {
+        return stripcslashes($qstr);
+    }
+
+    /**
+     * set a config variable in target array
+     *
+     * @param array $var
+     * @param array $target_array
+     */
+    private function set_var(Array $var, Array &$target_array)
+    {
+        $key = $var["key"];
+        $value = $var["value"];
+
+        if ($this->configOverwrite || !isset($target_array['vars'][$key])) {
+            $target_array['vars'][$key] = $value;
+        } else {
+            settype($target_array['vars'][$key], 'array');
+            $target_array['vars'][$key][] = $value;
+        }
+    }
+
+    /**
+     * add config variable to global vars
+     *
+     * @param array $vars
+     */
+    private function add_global_vars(Array $vars)
+    {
+        if (!isset($this->compiler->config_data['vars'])) {
+            $this->compiler->config_data['vars'] = Array();
+        }
+        foreach ($vars as $var) {
+            $this->set_var($var, $this->compiler->config_data);
+        }
+    }
+
+    /**
+     * add config variable to section
+     *
+     * @param string $section_name
+     * @param array  $vars
+     */
+    private function add_section_vars($section_name, Array $vars)
+    {
+        if (!isset($this->compiler->config_data['sections'][$section_name]['vars'])) {
+            $this->compiler->config_data['sections'][$section_name]['vars'] = Array();
+        }
+        foreach ($vars as $var) {
+            $this->set_var($var, $this->compiler->config_data['sections'][$section_name]);
+        }
+    }
+}
+
+%token_prefix TPC_
+
+%parse_accept
+{
+    $this->successful = !$this->internalError;
+    $this->internalError = false;
+    $this->retvalue = $this->_retvalue;
+}
+
+%syntax_error
+{
+    $this->internalError = true;
+    $this->yymajor = $yymajor;
+    $this->compiler->trigger_config_file_error();
+}
+
+%stack_overflow
+{
+    $this->internalError = true;
+    $this->compiler->trigger_config_file_error("Stack overflow in configfile parser");
+}
+
+// Complete config file
+start(res) ::= global_vars sections. {
+    res = null;
+}
+
+// Global vars
+global_vars(res) ::= var_list(vl). {
+    $this->add_global_vars(vl);
+    res = null;
+}
+
+// Sections
+sections(res) ::= sections section. {
+    res = null;
+}
+
+sections(res) ::= . {
+    res = null;
+}
+
+section(res) ::= OPENB SECTION(i) CLOSEB newline var_list(vars). {
+    $this->add_section_vars(i, vars);
+    res = null;
+}
+
+section(res) ::= OPENB DOT SECTION(i) CLOSEB newline var_list(vars). {
+    if ($this->configReadHidden) {
+        $this->add_section_vars(i, vars);
+    }
+    res = null;
+}
+
+// Var list
+var_list(res) ::= var_list(vl) newline. {
+    res = vl;
+}
+
+var_list(res) ::= var_list(vl) var(v). {
+    res = array_merge(vl, Array(v));
+}
+
+var_list(res) ::= . {
+    res = Array();
+}
+
+
+// Var
+var(res) ::= ID(id) EQUAL value(v). {
+    res = Array("key" => id, "value" => v);
+}
+
+
+value(res) ::= FLOAT(i). {
+    res = (float) i;
+}
+
+value(res) ::= INT(i). {
+    res = (int) i;
+}
+
+value(res) ::= BOOL(i). {
+    res = $this->parse_bool(i);
+}
+
+value(res) ::= SINGLE_QUOTED_STRING(i). {
+    res = self::parse_single_quoted_string(i);
+}
+
+value(res) ::= DOUBLE_QUOTED_STRING(i). {
+    res = self::parse_double_quoted_string(i);
+}
+
+value(res) ::= TRIPPLE_QUOTES(i) TRIPPLE_TEXT(c) TRIPPLE_QUOTES_END(ii). {
+    res = self::parse_tripple_double_quoted_string(c);
+}
+
+value(res) ::= TRIPPLE_QUOTES(i) TRIPPLE_QUOTES_END(ii). {
+    res = '';
+}
+
+value(res) ::= NAKED_STRING(i). {
+    res = i;
+}
+
+// NOTE: this is not a valid rule
+// It is added hier to produce a usefull error message on a missing '=';
+value(res) ::= OTHER(i). {
+    res = i;
+}
+
+
+// Newline and comments
+newline(res) ::= NEWLINE. {
+    res = null;
+}
+
+newline(res) ::= COMMENTSTART NEWLINE. {
+    res = null;
+}
+
+newline(res) ::= COMMENTSTART NAKED_STRING NEWLINE. {
+    res = null;
+}