/** * @throws SyntaxErrorException */ public function render() { if (!$this->_containsInterpolation($this->_text)) { return $this->_text; } $pieces = array(); $glueL = $this->_phpCtx ? '.' : '<?php echo '; $glueR = $this->_phpCtx ? '.' : ' ?>'; $encapsL = $this->_phpCtx ? '(' : ''; $encapsR = $this->_phpCtx ? ')' : ';'; $s = new StringScanner($this->_text); $quote = $s->scan(StringScanner::rQUOTE); while (!$s->eos) { trim($s->scan('/(.*?)(?<!\\\\)\\#\\{/sm')); if (!empty($s[1])) { $pieces[] = $quote . $s[1] . $quote; } trim($s->scan('/(.*?)(?<!\\\\)}/sm')); if (!empty($s[1])) { if ($this->_containsInterpolation($s[1])) { throw new SyntaxErrorException("Nesting interpolation is not allowed: " . $this->_text); } $pieces[] = $glueL; $pieces[] = $encapsL . $s[1] . $encapsR; $pieces[] = $glueR; } else { throw new SyntaxErrorException("Unclosed interpolation in: " . $this->_text); } if (!$this->_containsInterpolation($s->rest)) { $rest = trim($s->scan('/.*/sm'), " {$quote}"); if (!empty($rest)) { $pieces[] = $quote . $rest . $quote; } } } if ($this->_phpCtx) { // can't have glue on the edges if ($pieces[0] == $glueL) { array_shift($pieces); } // can't have glue on the edges if ($pieces[count($pieces) - 1] == $glueR) { array_pop($pieces); } // don't nee the parenteses if it is only one thing if (count($pieces) == 1) { $pieces[0] = s($pieces[0])->trimBalanced('(', ')'); } } return join($pieces); }
public function testUnscan() { $s = new StringScanner('test string'); $this->assertEquals('test', $s->scan('/\\w+/')); $s->unscan(); $this->assertEquals('te', $s->scan('/../')); $this->assertNull($s->scan('/\\d/')); try { $s->unscan(); # ScanError: unscan failed: previous match record not exist } catch (Exception $e) { } $this->assertNotNull($e); $s->reset(); $this->assertEquals('test ', $s->scan('/\\w+\\s/')); $this->assertEquals('st', $s->scan('/st/')); $this->assertEquals('ri', $s->scan('/ri/')); $s->unscan(); $this->assertEquals(7, $s->pos); $this->assertEquals('ri', $s->scan('/ri/')); }
function testOtag() { $sc = new StringScanner("{{foo}}{{bla}}"); $res = $sc->scan("{{"); $this->assertEqual($res, "{{"); $this->assertEqual($sc->rest(), "foo}}{{bla}}"); $res = $sc->scan("[#^\\/=!<>^{]"); $this->assertEqual($res, null); $this->assertEqual($sc->rest(), "foo}}{{bla}}"); }
/** Try to find static text. **/ public function scanText() { /* look for next opening tag. */ $text = $this->scanner->scanUntilExclusive(\StringScanner::escape($this->otag)); if ($text === null) { /* Couldn't find any otag, which means the rest is just static text. */ $text = $this->scanner->rest(); $this->scanner->clear(); } if (!empty($text)) { $prev = end($this->result); /* remove previous standalone section if found */ if ($prev[0] === ":standalone") { array_pop($this->result); } /* split text into lines, so that indentation works. */ foreach (preg_split('/(\\n)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY) as $str) { if ($str === "\n") { array_push($this->result, array(":newline")); } else { $this->addStatic($str); } } } }
private function _interpolate($str) { if (!$this->_containsInterpolation($str)) { return $str; } $nStr = ''; $s = new StringScanner($str); $quote = $s->check(StringScanner::rQUOTE); // If it doesn't starts with a quote, it CAN'T be inside php context if (empty($quote) || !s($str)->endsWith($quote)) { $int = new Interpolation($str); return $int->render(); } $int = new Interpolation($str, true); return $int->render(); }