diff options
Diffstat (limited to 'include/smarty/lexer/smarty_internal_configfileparser.y')
-rw-r--r-- | include/smarty/lexer/smarty_internal_configfileparser.y | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/include/smarty/lexer/smarty_internal_configfileparser.y b/include/smarty/lexer/smarty_internal_configfileparser.y new file mode 100644 index 000000000..ac961772d --- /dev/null +++ b/include/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; +} |