danielebarchiesi@4: setDefaultPrefixes(); danielebarchiesi@4: $this->base = $src ? $this->calcBase($src) : ARC2::getScriptURI(); danielebarchiesi@4: $this->blocks = array(); danielebarchiesi@4: $this->r = array('base' => '', 'vars' => array(), 'prefixes' => $this->prefixes); danielebarchiesi@4: do { danielebarchiesi@4: $proceed = 0; danielebarchiesi@4: if ((list($r, $v) = $this->xScriptBlock($v)) && $r) { danielebarchiesi@4: $this->blocks[] = $r; danielebarchiesi@4: $proceed = 1; danielebarchiesi@4: } danielebarchiesi@4: $this->unparsed_code = trim($v); danielebarchiesi@4: } while ($proceed); danielebarchiesi@4: if (trim($this->unparsed_code) && !$this->getErrors()) { danielebarchiesi@4: $rest = preg_replace('/[\x0a|\x0d]/i', ' ', substr($this->unparsed_code, 0, 30)); danielebarchiesi@4: $msg = trim($rest) ? 'Could not properly handle "' . $rest . '"' : 'Syntax Error'; danielebarchiesi@4: $this->addError($msg); danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: function getScriptBlocks() { danielebarchiesi@4: return $this->v('blocks', array()); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /* */ danielebarchiesi@4: danielebarchiesi@4: function xScriptBlock($v) { danielebarchiesi@4: /* comment removal */ danielebarchiesi@4: while (preg_match('/^\s*(\#[^\xd\xa]*)(.*)$/si', $v, $m)) $v = $m[2]; danielebarchiesi@4: /* BaseDecl */ danielebarchiesi@4: if ((list($sub_r, $v) = $this->xBaseDecl($v)) && $sub_r) { danielebarchiesi@4: $this->base = $sub_r; danielebarchiesi@4: } danielebarchiesi@4: /* PrefixDecl */ danielebarchiesi@4: while ((list($r, $v) = $this->xPrefixDecl($v)) && $r) { danielebarchiesi@4: $this->prefixes[$r['prefix']] = $r['uri']; danielebarchiesi@4: } danielebarchiesi@4: /* EndpointDecl */ danielebarchiesi@4: if ((list($r, $v) = $this->xEndpointDecl($v)) && $r) { danielebarchiesi@4: return array($r, $v); danielebarchiesi@4: } danielebarchiesi@4: /* Return */ danielebarchiesi@4: if ((list($r, $v) = $this->xReturn($v)) && $r) { danielebarchiesi@4: return array($r, $v); danielebarchiesi@4: } danielebarchiesi@4: /* Assignment */ danielebarchiesi@4: if ((list($r, $v) = $this->xAssignment($v)) && $r) { danielebarchiesi@4: return array($r, $v); danielebarchiesi@4: } danielebarchiesi@4: /* IFBlock */ danielebarchiesi@4: if ((list($r, $v) = $this->xIFBlock($v)) && $r) { danielebarchiesi@4: return array($r, $v); danielebarchiesi@4: } danielebarchiesi@4: /* FORBlock */ danielebarchiesi@4: if ((list($r, $v) = $this->xFORBlock($v)) && $r) { danielebarchiesi@4: return array($r, $v); danielebarchiesi@4: } danielebarchiesi@4: /* String */ danielebarchiesi@4: if ((list($r, $v) = $this->xString($v)) && $r) { danielebarchiesi@4: return array($r, $v); danielebarchiesi@4: } danielebarchiesi@4: /* FunctionCall */ danielebarchiesi@4: if ((list($r, $v) = $this->xFunctionCall($v)) && $r) { danielebarchiesi@4: return array($r, ltrim($v, ';')); danielebarchiesi@4: } danielebarchiesi@4: /* Query */ danielebarchiesi@4: $prev_r = $this->r; danielebarchiesi@4: $this->r = array('base' => '', 'vars' => array(), 'prefixes' => $this->prefixes); danielebarchiesi@4: if ((list($r, $rest) = $this->xQuery($v)) && $r) { danielebarchiesi@4: $q = $rest ? trim(substr($v, 0, -strlen($rest))) : trim($v); danielebarchiesi@4: $v = $rest; danielebarchiesi@4: $r = array_merge($this->r, array( danielebarchiesi@4: 'type' => 'query', danielebarchiesi@4: 'query_type' => $r['type'], danielebarchiesi@4: 'query' => $q, danielebarchiesi@4: //'prefixes' => $this->prefixes, danielebarchiesi@4: 'base' => $this->base, danielebarchiesi@4: //'infos' => $r danielebarchiesi@4: )); danielebarchiesi@4: return array($r, $v); danielebarchiesi@4: } danielebarchiesi@4: else { danielebarchiesi@4: $this->r = $prev_r; danielebarchiesi@4: } danielebarchiesi@4: return array(0, $v); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: function xBlockSet($v) { danielebarchiesi@4: if (!$r = $this->x("\{", $v)) return array(0, $v); danielebarchiesi@4: $blocks = array(); danielebarchiesi@4: $sub_v = $r[1]; danielebarchiesi@4: while ((list($sub_r, $sub_v) = $this->xScriptBlock($sub_v)) && $sub_r) { danielebarchiesi@4: $blocks[] = $sub_r; danielebarchiesi@4: } danielebarchiesi@4: if (!$sub_r = $this->x("\}", $sub_v)) return array(0, $v); danielebarchiesi@4: $sub_v = $sub_r[1]; danielebarchiesi@4: return array(array('type' => 'block_set', 'blocks' => $blocks), $sub_v); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /* s2 */ danielebarchiesi@4: danielebarchiesi@4: function xEndpointDecl($v) { danielebarchiesi@4: if ($r = $this->x("ENDPOINT\s+", $v)) { danielebarchiesi@4: if ((list($r, $sub_v) = $this->xIRI_REF($r[1])) && $r) { danielebarchiesi@4: $r = $this->calcURI($r, $this->base); danielebarchiesi@4: if ($sub_r = $this->x('\.', $sub_v)) { danielebarchiesi@4: $sub_v = $sub_r[1]; danielebarchiesi@4: } danielebarchiesi@4: return array( danielebarchiesi@4: array('type' => 'endpoint_decl', 'endpoint' => $r), danielebarchiesi@4: $sub_v danielebarchiesi@4: ); danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: return array(0, $v); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /* s3 */ danielebarchiesi@4: danielebarchiesi@4: function xAssignment($v) { danielebarchiesi@4: /* Var */ danielebarchiesi@4: list($r, $sub_v) = $this->xVar($v); danielebarchiesi@4: if (!$r) return array(0, $v); danielebarchiesi@4: $var = $r; danielebarchiesi@4: /* := | = */ danielebarchiesi@4: if (!$sub_r = $this->x("\:?\=", $sub_v)) return array(0, $v); danielebarchiesi@4: $sub_v = $sub_r[1]; danielebarchiesi@4: /* try String */ danielebarchiesi@4: list($r, $sub_v) = $this->xString($sub_v); danielebarchiesi@4: if ($r) return array(array('type' => 'assignment', 'var' => $var, 'sub_type' => 'string', 'string' => $r), ltrim($sub_v, '; ')); danielebarchiesi@4: /* try VarMerge */ danielebarchiesi@4: list($r, $sub_v) = $this->xVarMerge($sub_v); danielebarchiesi@4: if ($r) return array(array('type' => 'assignment', 'var' => $var, 'sub_type' => 'var_merge', 'var2' => $r[0], 'var3' => $r[1]), ltrim($sub_v, '; ')); danielebarchiesi@4: /* try Var */ danielebarchiesi@4: list($r, $sub_v) = $this->xVar($sub_v); danielebarchiesi@4: if ($r) return array(array('type' => 'assignment', 'var' => $var, 'sub_type' => 'var', 'var2' => $r), ltrim($sub_v, '; ')); danielebarchiesi@4: /* try function */ danielebarchiesi@4: list($r, $sub_v) = $this->xFunctionCall($sub_v); danielebarchiesi@4: if ($r) return array(array('type' => 'assignment', 'var' => $var, 'sub_type' => 'function_call', 'function_call' => $r), ltrim($sub_v, '; ')); danielebarchiesi@4: /* try Placeholder */ danielebarchiesi@4: list($r, $sub_v) = $this->xPlaceholder($sub_v); danielebarchiesi@4: if ($r) return array(array('type' => 'assignment', 'var' => $var, 'sub_type' => 'placeholder', 'placeholder' => $r), ltrim($sub_v, '; ')); danielebarchiesi@4: /* try query */ danielebarchiesi@4: $prev_r = $this->r; danielebarchiesi@4: $this->r = array('base' => '', 'vars' => array(), 'prefixes' => $this->prefixes); danielebarchiesi@4: list($r, $rest) = $this->xQuery($sub_v); danielebarchiesi@4: if (!$r) { danielebarchiesi@4: $this->r = $prev_r; danielebarchiesi@4: return array(0, $v); danielebarchiesi@4: } danielebarchiesi@4: else { danielebarchiesi@4: $q = $rest ? trim(substr($sub_v, 0, -strlen($rest))) : trim($sub_v); danielebarchiesi@4: return array( danielebarchiesi@4: array( danielebarchiesi@4: 'type' => 'assignment', danielebarchiesi@4: 'var' => $var, danielebarchiesi@4: 'sub_type' => 'query', danielebarchiesi@4: 'query' => array_merge($this->r, array( danielebarchiesi@4: 'type' => 'query', danielebarchiesi@4: 'query_type' => $r['type'], danielebarchiesi@4: 'query' => $q, danielebarchiesi@4: 'base' => $this->base, danielebarchiesi@4: )), danielebarchiesi@4: ), danielebarchiesi@4: ltrim($rest, '; ') danielebarchiesi@4: ); danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: function xReturn($v) { danielebarchiesi@4: if ($r = $this->x("return\s+", $v)) { danielebarchiesi@4: /* fake assignment which accepts same right-hand values */ danielebarchiesi@4: $sub_v = '$__return_value__ := ' . $r[1]; danielebarchiesi@4: if ((list($r, $sub_v) = $this->xAssignment($sub_v)) && $r) { danielebarchiesi@4: $r['type'] = 'return'; danielebarchiesi@4: return array($r, $sub_v); danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: return array(0, $v); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /* s4 'IF' BrackettedExpression '{' Script '}' ( 'ELSE' '{' Script '}')? */ danielebarchiesi@4: danielebarchiesi@4: function xIFBlock($v) { danielebarchiesi@4: if ($r = $this->x("IF\s*", $v)) { danielebarchiesi@4: if ((list($sub_r, $sub_v) = $this->xBrackettedExpression($r[1])) && $sub_r) { danielebarchiesi@4: $cond = $sub_r; danielebarchiesi@4: if ((list($sub_r, $sub_v) = $this->xBlockSet($sub_v)) && $sub_r) { danielebarchiesi@4: $blocks = $sub_r['blocks']; danielebarchiesi@4: /* else */ danielebarchiesi@4: $else_blocks = array(); danielebarchiesi@4: $rest = $sub_v; danielebarchiesi@4: if ($sub_r = $this->x("ELSE\s*", $sub_v)) { danielebarchiesi@4: if ((list($sub_r, $sub_v) = $this->xBlockSet($sub_r[1])) && $sub_r) { danielebarchiesi@4: $else_blocks = $sub_r['blocks']; danielebarchiesi@4: } danielebarchiesi@4: else { danielebarchiesi@4: $sub_v = $rest; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: return array( danielebarchiesi@4: array( danielebarchiesi@4: 'type' => 'ifblock', danielebarchiesi@4: 'condition' => $cond, danielebarchiesi@4: 'blocks' => $blocks, danielebarchiesi@4: 'else_blocks' => $else_blocks, danielebarchiesi@4: ), danielebarchiesi@4: $sub_v danielebarchiesi@4: ); danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: return array(0, $v); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /* s5 'FOR' '(' Var 'IN' Var ')' '{' Script '}' */ danielebarchiesi@4: danielebarchiesi@4: function xFORBlock($v) { danielebarchiesi@4: if ($r = $this->x("FOR\s*\(\s*[\$\?]([^\s]+)\s+IN\s+[\$\?]([^\s]+)\s*\)", $v)) {/* @@todo split into sub-patterns? */ danielebarchiesi@4: $iterator = $r[1]; danielebarchiesi@4: $set_var = $r[2]; danielebarchiesi@4: $sub_v = $r[3]; danielebarchiesi@4: if ((list($sub_r, $sub_v) = $this->xBlockSet($sub_v)) && $sub_r) { danielebarchiesi@4: return array( danielebarchiesi@4: array( danielebarchiesi@4: 'type' => 'forblock', danielebarchiesi@4: 'set' => $set_var, danielebarchiesi@4: 'iterator' => $iterator, danielebarchiesi@4: 'blocks' => $sub_r['blocks'] danielebarchiesi@4: ), danielebarchiesi@4: $sub_v danielebarchiesi@4: ); danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: return array(0, $v); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /* s6 Var '+' Var */ danielebarchiesi@4: danielebarchiesi@4: function xVarMerge($v) { danielebarchiesi@4: if ((list($sub_r, $sub_v) = $this->xVar($v)) && $sub_r) { danielebarchiesi@4: $var1 = $sub_r; danielebarchiesi@4: if ($sub_r = $this->x("\+", $sub_v)) { danielebarchiesi@4: $sub_v = $sub_r[1]; danielebarchiesi@4: if ((list($sub_r, $sub_v) = $this->xVar($sub_v)) && $sub_r) { danielebarchiesi@4: return array( danielebarchiesi@4: array($var1, $sub_r), danielebarchiesi@4: $sub_v danielebarchiesi@4: ); danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: return array(0, $v); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: }