Skip to content

Instantly share code, notes, and snippets.

@beberlei
Created September 10, 2009 19:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save beberlei/184744 to your computer and use it in GitHub Desktop.
Save beberlei/184744 to your computer and use it in GitHub Desktop.
<?php
class Zend_Reflection_DocblockParserTest extends PHPUnit_Framework_TestCase
{
public function testTokenizesimpleDocBlock()
{
$input = "hello world this is a description
@param string \$foo
@return int";
$t = new Zend_Reflection_DocblockTokenizer();
$tokens = $t->tokenize($input);
$parser = new Zend_Reflection_DocblockParser();
$parser->parse($tokens);
var_dump($parser);
}
}
class Zend_Reflection_DocblockParser
{
private $_ast = array();
public function parse(array &$tokens)
{
while(count($tokens) > 0) {
$token = array_shift($tokens);
switch($token['type']) {
case 'tag':
$this->_parseTag($token, $tokens);
break;
case 'text':
case 'linebreak':
case 'whitespace':
$this->_parseText($token, $tokens);
break;
}
}
}
protected function _parseText($token, array &$tokens)
{
$content = $token['content'];
while(count($tokens) > 0) {
$token = array_shift($tokens);
if($token['type'] != "tag") {
$content .= $token['content'];
} else {
array_unshift($tokens, $token);
break;
}
}
$this->_ast[] = array('text', $content);
}
protected function _parseTag($token, array &$tokens)
{
switch($token['content']) {
case '@param':
$this->_removeNextWhitespace($tokens);
$type = array_shift($tokens);
if($type['type'] !== 'text') {
throw new Exception("Param expects a type as first argument.");
}
$typeContent = $type['content'];
$this->_removeNextWhitespace($tokens);
$variable = array_shift($tokens);
if($variable['type'] != "text") {
throw new Exception("@param expects a variable as second argument.");
}
$variableContent = $variable['content'];
$this->_ast[] = array('param', $typeContent, $variableContent);
break;
case '@return':
$this->_removeNextWhitespace($tokens);
$type = array_shift($tokens);
if($type['type'] !== 'text') {
throw new Exception("Param expects a type as first argument.");
}
$typeContent = $type['content'];
$this->_ast[] = array('return', $typeContent);
break;
default:
break;
}
}
protected function _removeNextWhitespace(array &$tokens)
{
$wsToken = array_shift($tokens);
var_dump($wsToken);
if($wsToken['type'] !== "whitespace") {
throw new Exception("A whitespace was expected!");
}
}
}
class Zend_Reflection_DocblockTokenizer
{
const TOKEN_TAG = '/^(@[a-zA-Z]{1,})/';
const TOKEN_TEXT = '/^([^@_\s\r\n]{1,})/';
const TOKEN_LINEBREAK = '/^([\r\n]+)/';
const TOKEN_WHITESPACE = '/^([\s]{1,})/';
public function tokenize($string)
{
$tokens = array("tag" => self::TOKEN_TAG, "text" => self::TOKEN_TEXT, "linebreak" => self::TOKEN_LINEBREAK, "whitespace" => self::TOKEN_WHITESPACE);
$scanned = array();
while(strlen($string) > 0) {
foreach($tokens AS $type => $token) {
if(preg_match($token, $string, $match)) {
$scanned[] = array(
'type' => $type,
'content' => $match[0],
);
$string = substr($string, strlen($match[0]));
}
}
}
return $scanned;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment