summaryrefslogtreecommitdiff
path: root/buildscripts/PhpDocumentor/phpDocumentor/DocBlock
diff options
context:
space:
mode:
authorxue <>2006-06-19 18:38:29 +0000
committerxue <>2006-06-19 18:38:29 +0000
commit588727c7e2b8954ec3dbde293cf4c4d68b119f9b (patch)
treefdcc16181a20335547953ccf1550e0006c11bf28 /buildscripts/PhpDocumentor/phpDocumentor/DocBlock
parent127f78a4db3cc0fbbbb92f5b1abcfdce4a9af93b (diff)
Merge from 3.0 branch till 1185.
Diffstat (limited to 'buildscripts/PhpDocumentor/phpDocumentor/DocBlock')
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/DocBlock/Lexer.inc701
1 files changed, 701 insertions, 0 deletions
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/DocBlock/Lexer.inc b/buildscripts/PhpDocumentor/phpDocumentor/DocBlock/Lexer.inc
new file mode 100644
index 00000000..edfc896c
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/DocBlock/Lexer.inc
@@ -0,0 +1,701 @@
+<?php
+define('PHPDOC_LEXER_DESC', 1);
+define('PHPDOC_LEXER_TAGS', 2);
+define('PHPDOC_LEXER_ESCTAG', 3);
+define('PHPDOC_LEXER_INLINETAG', 4);
+define('PHPDOC_LEXER_INTERNAL', 5);
+define('PHPDOC_LEXER_INTERNALTAG', 6);
+define('PHPDOC_LEXER_SIMPLELIST', 7);
+define('PHPDOC_DOCBLOCK_TOKEN_NEWLINE', 1);
+define('PHPDOC_DOCBLOCK_TOKEN_DESC', 2);
+define('PHPDOC_DOCBLOCK_TOKEN_ESCTAGOPEN', 3);
+define('PHPDOC_DOCBLOCK_TOKEN_ESCTAGCLOSE', 4);
+define('PHPDOC_DOCBLOCK_TOKEN_TAG', 5);
+define('PHPDOC_DOCBLOCK_TOKEN_INLINETAG', 6);
+define('PHPDOC_DOCBLOCK_TOKEN_INLINETAGCLOSE', 7);
+define('PHPDOC_DOCBLOCK_TOKEN_INTERNAL', 8);
+define('PHPDOC_DOCBLOCK_TOKEN_INTERNALCLOSE', 9);
+define('PHPDOC_DOCBLOCK_TOKEN_HTMLTAG', 10);
+define('PHPDOC_DOCBLOCK_TOKEN_HTMLTAGCLOSE', 11);
+define('PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTSTART', 12);
+define('PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTEND', 13);
+define('PHPDOC_DOCBLOCK_TOKEN_UNORDEREDBULLET', 14);
+define('PHPDOC_DOCBLOCK_TOKEN_ORDEREDBULLET', 15);
+class PhpDocumentor_DocBlock_Lexer
+{
+ var $processedline;
+ var $tagStack = array();
+ var $tokens = array();
+ var $simplelist = array();
+ var $whitespace = array();
+ var $states = array(PHPDOC_LEXER_DESC);
+ function tokenName($token)
+ {
+ $this->tokens = array(
+ PHPDOC_DOCBLOCK_TOKEN_NEWLINE => 'PHPDOC_DOCBLOCK_TOKEN_NEWLINE',
+ PHPDOC_DOCBLOCK_TOKEN_DESC => 'PHPDOC_DOCBLOCK_TOKEN_DESC',
+ PHPDOC_DOCBLOCK_TOKEN_ESCTAGOPEN => 'PHPDOC_DOCBLOCK_TOKEN_ESCTAGOPEN',
+ PHPDOC_DOCBLOCK_TOKEN_ESCTAGCLOSE => 'PHPDOC_DOCBLOCK_TOKEN_ESCTAGCLOSE',
+ PHPDOC_DOCBLOCK_TOKEN_TAG => 'PHPDOC_DOCBLOCK_TOKEN_TAG',
+ PHPDOC_DOCBLOCK_TOKEN_INLINETAG => 'PHPDOC_DOCBLOCK_TOKEN_INLINETAG',
+ PHPDOC_DOCBLOCK_TOKEN_INLINETAGCLOSE => 'PHPDOC_DOCBLOCK_TOKEN_INLINETAGCLOSE',
+ PHPDOC_DOCBLOCK_TOKEN_INTERNAL => 'PHPDOC_DOCBLOCK_TOKEN_INTERNAL',
+ PHPDOC_DOCBLOCK_TOKEN_INTERNALCLOSE => 'PHPDOC_DOCBLOCK_TOKEN_INTERNALCLOSE',
+ );
+ if (in_array($token, array_keys($this->tokens))) {
+ return $this->tokens[$token];
+ }
+ return 'UNKNOWN';
+ }
+
+ function lex($comment)
+ {
+ $comment = str_replace(array("\r\n", "\r"), array("\n", "\n"), $comment);
+ $comment = explode("\n", $comment);
+ $this->tokens = array();
+ $state = PHPDOC_LEXER_DESC;
+ $this->states = array(PHPDOC_LEXER_DESC);
+ $tid = 0;
+ $token = '';
+ $esctag = false;
+ $this->exception = false;
+ list($lastline,) = each(array_reverse($comment, true));
+ foreach ($comment as $this->linenum => $line) {
+ if ($this->exception) {
+ $this->tokens = array();
+ return false;
+ }
+ $linestart = true;
+ $this->processedline = trim($line);
+ if ($this->processedline == '*/') {
+ break;
+ }
+ if (!$this->processedline) {
+ continue;
+ }
+ if (substr($this->processedline, 0, 3) == '/**') {
+ $this->processedline = substr($this->processedline, 3);
+ if (!$this->processedline) {
+ continue;
+ }
+ if (trim($this->processedline) == '*/') {
+ $this->endSimpleList();
+ break;
+ }
+ } else {
+ $this->processedline = substr($this->processedline, 1);
+ }
+ while (true) {
+ switch ($state) {
+ case PHPDOC_LEXER_INTERNALTAG :
+ $internalendpos = strpos($this->processedline, '}}');
+ case PHPDOC_LEXER_TAGS :
+ $trimline = trim($this->processedline);
+ if (strlen($trimline) && $trimline{0} == '@') {
+ if (preg_match('/^(@[^\s]+)\s/', $trimline, $matches) ||
+ preg_match('/^(@[^\s]+)$/', $trimline, $matches)) {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_TAG,
+ $matches[1]);
+ $this->processedline = substr($trimline, strpos($trimline, $matches[1]) +
+ strlen($matches[1]));
+ if (!$this->processedline) {
+ break 2;
+ }
+ continue 2; // to while(true)
+ }
+ } elseif (preg_match('/^@/', $trimline, $matches)) {
+ // throw exception for invalid tag
+ return $this->throwException('Invalid tag encountered in line number ' .
+ $this->linenum . ': "' . $line . '"', 'tag');
+ } else {
+ $tagpos = strpos($this->processedline, '<');
+ $inlinetagpos = strpos($this->processedline, '{@');
+ if (isset($internalendpos) && $internalendpos !== false) {
+ do {
+ if ($tagpos !== false && $internalendpos > $tagpos) {
+ break;
+ }
+ if ($inlinetagpos !== false && $internalendpos > $inlinetagpos) {
+ break;
+ }
+ // }} is the next important token
+ $this->appendDesc(substr($this->processedline, 0,
+ $internalendpos));
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_INTERNALCLOSE, '}}');
+ $this->processedline = substr($this->processedline, $internalendpos
+ + 2);
+ array_shift($this->states);
+ $state = PHPDOC_LEXER_TAGS;
+ continue 3; // to while(true);
+ } while (false);
+ }
+ if ($tagpos !== false && $inlinetagpos !== false) {
+ if ($tagpos > $inlinetagpos) {
+ $tagpos = false;
+ } else {
+ $inlinetagpos = false;
+ }
+ }
+ if ($tagpos !== false) {
+ continue $this->searchForHTMLTag($tagpos,
+ $state, $esctag, $linestart, $trimline);
+ }
+ if ($inlinetagpos !== false) {
+ $state = $this->searchForInlineTag($inlinetagpos, $comment);
+ $linestart = false;
+ continue 2; // to while (true)
+ }
+ if (strpos($this->processedline, '*/')) {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_DESC,
+ substr($this->processedline,
+ 0, strpos($this->processedline, '*/')));
+ return $this->tokens;
+ }
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_DESC, $this->processedline);
+ }
+ break;
+ case PHPDOC_LEXER_INTERNAL :
+ $internalendpos = strpos($this->processedline, '}}');
+ case PHPDOC_LEXER_SIMPLELIST :
+ if ($linestart && $state == PHPDOC_LEXER_SIMPLELIST) {
+ if (!$this->processSimpleList()) {
+ while (count($this->simplelist) && !$this->processSimpleList());
+ }
+ if (!count($this->simplelist)) {
+ array_shift($this->states);
+ $state = array_shift($this->states);
+ array_unshift($this->states, $state);
+ }
+ }
+ case PHPDOC_LEXER_DESC :
+ if (strpos($this->processedline, '*/')) {
+ $this->processedline = substr($this->processedline,
+ 0, strpos($this->processedline, '*/'));
+ }
+ if (!$this->processedline) {
+ if ($this->linenum != $lastline) {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_NEWLINE, "\n");
+ }
+ continue 3; // to foreach
+ }
+ $trimline = trim($this->processedline);
+ if ($linestart && $state != PHPDOC_LEXER_TAGS && $trimline{0} == '@') {
+ if ($state == PHPDOC_LEXER_INTERNAL) {
+ // throw exception
+ return $this->throwException('Cannot start tags in {@internal}} ' .
+ ' in line number ' .
+ $this->linenum . ': "' . $line . '"', 'tag');
+ }
+ $this->states = array(PHPDOC_LEXER_TAGS);
+ $state = PHPDOC_LEXER_TAGS;
+ continue 2; // to while(true)
+
+ }
+ if ($state != PHPDOC_LEXER_SIMPLELIST && $linestart && strlen($trimline) > 3 &&
+ ($trimline{0} == '-' || $trimline{0} == '*' ||
+ $trimline{0} == '#' || $trimline{0} == 'o' ||
+ $trimline{0} == '1')) {
+ if ($this->searchForSimplelist($trimline)) {
+ $state = PHPDOC_LEXER_SIMPLELIST;
+ $linestart = false;
+ continue 2; // to while(true)
+ }
+ }
+ $tagpos = strpos($this->processedline, '<');
+ $inlinetagpos = strpos($this->processedline, '{@');
+ if (isset($internalendpos) && $internalendpos !== false) {
+ do {
+ if ($tagpos !== false && $internalendpos > $tagpos) {
+ break;
+ }
+ if ($inlinetagpos !== false && $internalendpos > $inlinetagpos) {
+ break;
+ }
+ // }} is the next important token
+ $this->appendDesc(substr($this->processedline, 0, $internalendpos));
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_INTERNALCLOSE, '}}');
+ $this->processedline = substr($this->processedline, $internalendpos
+ + 2);
+ array_shift($this->states);
+ $state = PHPDOC_LEXER_DESC;
+ continue 3; // to while(true);
+ } while (false);
+ }
+ if ($tagpos !== false && $inlinetagpos !== false) {
+ if ($tagpos > $inlinetagpos) {
+ $tagpos = false;
+ } else {
+ $inlinetagpos = false;
+ }
+ }
+ if ($tagpos !== false) {
+ continue $this->searchForHTMLTag($tagpos, $state,
+ $esctag, $linestart, $trimline);
+ }
+ if ($inlinetagpos !== false) {
+ $state = $this->searchForInlineTag($inlinetagpos, $comment);
+ $linestart = false;
+ continue 2; // to while (true)
+ }
+ $this->appendDesc($this->processedline);
+ break;
+ case PHPDOC_LEXER_ESCTAG :
+ if (!$this->processedline) {
+ if ($this->linenum != $lastline) {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_NEWLINE, "\n");
+ }
+ continue 3; // to foreach
+ }
+ $endpos = strpos($this->processedline, $esctag);
+ $inlinetagpos = strpos($this->processedline, '{@');
+ if ($endpos !== false && $inlinetagpos !== false) {
+ if ($endpos > $inlinetagpos) {
+ $endpos = false;
+ } else {
+ $inlinetagpos = false;
+ }
+ }
+ if ($endpos !== false) {
+ if (strlen(substr($this->processedline, 0, $endpos))) {
+ $this->appendDesc(substr($this->processedline, 0, $endpos));
+ }
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ESCTAGCLOSE, $esctag);
+ $this->processedline = substr($this->processedline, $endpos +
+ strlen($esctag));
+ $state = $this->states[0];
+ if (count($this->states) > 1) {
+ array_shift($this->states);
+ }
+ if (!$this->processedline) {
+ break 2;
+ }
+ }
+ if ($inlinetagpos !== false) {
+ array_unshift($this->states, PHPDOC_LEXER_ESCTAG);
+ $state = $this->searchForInlineTag($inlinetagpos, $comment);
+ $linestart = false;
+ continue 2; // to while (true)
+ }
+ $this->appendDesc($this->processedline);
+ break;
+ case PHPDOC_LEXER_INLINETAG :
+ if (!$this->processedline) {
+ if ($this->linenum != $lastline) {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_NEWLINE, "\n");
+ }
+ continue 3; // to foreach
+ }
+ $endpos = strpos($this->processedline, '}');
+ if ($endpos !== false) {
+ if (strlen(substr($this->processedline, 0, $endpos))) {
+ $this->appendDesc(substr($this->processedline, 0, $endpos));
+ }
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_INLINETAGCLOSE, '}');
+ $this->processedline = substr($this->processedline, $endpos + 1); // strlen('}')
+ $state = $this->states[0];
+ if (count($this->states) > 1) {
+ array_shift($this->states);
+ }
+ if (!$this->processedline) {
+ break 2;
+ }
+ if ($state != PHPDOC_LEXER_INLINETAG && strlen($this->processedline)) {
+ $linestart = false;
+ continue 2; // to while (true)
+ }
+ }
+ $this->appendDesc($this->processedline);
+ break;
+ }
+ break;
+ }
+ if ($this->linenum != $lastline) {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_NEWLINE, "\n");
+ }
+ }
+ return $this->tokens;
+ }
+
+ function searchForSimplelist($trimline)
+ {
+ $whitespace = strpos($this->processedline, $trimline);
+ switch ($trimline{0}) {
+ case '-' :
+ case '*' :
+ case '+' :
+ case 'o' :
+ if (strlen($trimline) < 3 || $trimline{1} != ' ') {
+ return false;
+ }
+ // unordered lists
+ $this->simplelist[] = 'u' . $trimline{0};
+ $this->whitespace[] = $whitespace;
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTSTART, '');
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_UNORDEREDBULLET, $trimline{0});
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ $trimline{0}) + 2);
+ array_unshift($this->states, PHPDOC_LEXER_SIMPLELIST);
+ return true;
+ break;
+ case '#' :
+ if (strlen($trimline) < 3) {
+ return false;
+ }
+ // ordered lists
+ $this->simplelist[] = '#1';
+ $this->whitespace[] = $whitespace;
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTSTART, '');
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ORDEREDBULLET, '#');
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ '#') + 2);
+ array_unshift($this->states, PHPDOC_LEXER_SIMPLELIST);
+ return true;
+ case '1' :
+ if (strlen($trimline) < 4) {
+ return false;
+ }
+ if ($trimline{1} == ' ') {
+ $this->simplelist[] = 'O1';
+ } elseif ($trimline{1} == '.' && $trimline{2} == ' ') {
+ $this->simplelist[] = 'o1';
+ } else {
+ return false;
+ }
+ $this->whitespace[] = $whitespace;
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTSTART, '');
+ if ($trimline{1} == '.') {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ORDEREDBULLET, '1.');
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ '1.') + 3);
+ } else {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ORDEREDBULLET, '1');
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ '1') + 2);
+ }
+ array_unshift($this->states, PHPDOC_LEXER_SIMPLELIST);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @todo process multi-line elements via whitespace
+ * @todo process nested simple lists
+ */
+ function processSimpleList()
+ {
+ $trimline = trim($this->processedline);
+ $index = count($this->simplelist) - 1;
+ $whitespace = strpos($this->processedline, $trimline);
+ if ($whitespace < $this->whitespace[$index]) {
+ while (count($this->whitespace[$index]) && $whitespace < $this->whitespace[$index]) {
+ // the end of the current simplelist
+ $this->tokens = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTEND, '');
+ array_pop($this->simplelist);
+ $index--;
+ }
+ if ($index == -1) {
+ return false; // all simple lists concluded
+ }
+ }
+ if ($whitespace > $this->whitespace[$index]) {
+ // could be a multi-line element or a new list
+ if (!$this->searchForSimplelist($trimline)) {
+ // trim off the simple list whitespace if this is multi-line
+ $this->processedline = substr($this->processedline, $this->whitespace[$index] + 2);
+ }
+ return true;
+ }
+ // implied: whitespace matches exactly so this is either another
+ // bullet point or the end of the simple list
+ switch ($this->simplelist[$index]{0}) {
+ case 'u' :
+ if (strlen($trimline) < 3 || $trimline{0} != $this->simplelist[$index]{1} ||
+ $trimline{1} != ' ') {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTEND, '');
+ array_pop($this->simplelist);
+ return false;
+ }
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_UNORDEREDBULLET, $trimline{0});
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ $trimline{0}) + 2);
+ break;
+ case 'o' :
+ if (strlen($trimline) < 4 || ($trimline{0} !=
+ ($this->simplelist[$index]{1} + 1) . '') ||
+ $trimline{1} != '.' || $trimline{2} != ' ') {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTEND, '');
+ array_pop($this->simplelist);
+ return false;
+ }
+ $this->simplelist[$index] = $this->simplelist[$index]{0} .
+ ($this->simplelist[$index]{1} + 1);
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ORDEREDBULLET,
+ $this->simplelist[$index]{1} . '.');
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ $trimline{0} . '.') + 3);
+ break;
+ case 'O' :
+ if (strlen($trimline) < 3 || $trimline{0} != ($this->simplelist[$index]{1} + 1) . '' ||
+ $trimline{1} != ' ') {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTEND, '');
+ array_pop($this->simplelist);
+ return false;
+ }
+ $this->simplelist[$index] = $this->simplelist[$index]{0} .
+ ($this->simplelist[$index]{1} + 1);
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ORDEREDBULLET,
+ $this->simplelist[$index]{1});
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ $this->simplelist[$index]{1}) + 2);
+ break;
+ case '#' :
+ if (strlen($trimline) < 3 || $trimline{0} != '#' ||
+ $trimline{1} != ' ') {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTEND, '');
+ array_pop($this->simplelist);
+ return false;
+ }
+ $this->simplelist[$index] = $this->simplelist[$index]{0} .
+ ($this->simplelist[$index]{1} + 1);
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ORDEREDBULLET,
+ $this->simplelist[$index]{1});
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ '#') + 2);
+ break;
+ }
+ return true;
+ }
+
+ function searchForHTMLTag($tagpos, &$state, &$esctag, &$linestart,
+ &$trimline)
+ {
+ if (preg_match('/^<(<\/?[a-zA-Z]+ ?\/?>)>/', substr($this->processedline, $tagpos),
+ $matches)) {
+ if ($tagpos) {
+ $this->appendDesc(substr($this->processedline, 0, $tagpos));
+ }
+ $this->appendDesc($matches[1]);
+ $this->processedline = substr($this->processedline, $tagpos
+ + strlen($matches[1])
+ + 2);
+ return 2;
+ } elseif (!count($matches) &&
+ preg_match('/^<(<\/?[a-zA-Z]+ ?\/?>)>/', substr($this->processedline, $tagpos + 1),
+ $matches)) {
+ if ($tagpos) {
+ $this->appendDesc(substr($this->processedline, 0, $tagpos));
+ }
+ $this->appendDesc('<' . $matches[1]);
+ $this->processedline = substr($this->processedline, $tagpos
+ + strlen($matches[1])
+ + 3);
+ return 2;
+ } elseif (preg_match('#^(br>|br/>|br />)#',
+ substr($this->processedline, $tagpos + 1), $matches)) {
+ if ($tagpos) {
+ $this->appendDesc(substr($this->processedline, 0, $tagpos));
+ }
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_HTMLTAG, 'br');
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_HTMLTAGCLOSE, 'br');
+ $this->processedline = substr($this->processedline, $tagpos
+ + strlen($matches[1])
+ + 1);
+ return 2;
+ } elseif (preg_match('/^(b>|i>|li>|ol>|ul>|p>|pre>|var>)/',
+ substr($this->processedline, $tagpos + 1), $matches)) {
+ if ($tagpos) {
+ $this->appendDesc(substr($this->processedline, 0, $tagpos));
+ }
+ $matches = substr($matches[1], 0, strlen($matches[1]) - 1);
+ array_push($this->tagStack, $matches);
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_HTMLTAG, $matches);
+ $this->processedline = substr($this->processedline, $tagpos
+ + strlen($matches)
+ + 2);
+ return 2;
+ } elseif (preg_match('#^(/b>|/i>|/li>|/ol>|/ul>|/p>|/pre>|/var>)#',
+ substr($this->processedline, $tagpos + 1), $matches)) {
+ if ($tagpos) {
+ $this->appendDesc(substr($this->processedline, 0, $tagpos));
+ }
+ $matches = substr($matches[1], 1, strlen($matches[1]) - 2);
+ $test = array_pop($this->tagStack);
+ if ($matches != $test) {
+ // throw exception
+ $this->throwException('Invalid closing html tag encountered in line number ' .
+ $this->linenum . ': "</' . $matches . '>", expecting "</' . $test . '>"', 'htmltag');
+ return 3;
+ }
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_HTMLTAGCLOSE, $matches);
+ $this->processedline = substr($this->processedline, $tagpos
+ + strlen($matches)
+ + 3);
+ return 2;
+ } elseif (preg_match('/^(code>|pre>|kbd>|samp>)/',
+ substr($this->processedline, $tagpos + 1), $matches)) {
+ $esctag = '</' . $matches[0];
+ if ($tagpos) {
+ $this->appendDesc(substr($this->processedline, 0, $tagpos));
+ }
+ switch ($matches[0]) {
+ case 'code>' :
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ESCTAGOPEN,
+ '<code>');
+ break;
+ case 'pre>' :
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ESCTAGOPEN,
+ '<pre>');
+ break;
+ case 'kbd>' :
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ESCTAGOPEN,
+ '<kbd>');
+ break;
+ case 'samp>' :
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ESCTAGOPEN,
+ '<samp>');
+ break;
+ }
+ $this->processedline = $line = substr($this->processedline, $tagpos
+ + strlen($matches[0])
+ + 1);
+ $state = PHPDOC_LEXER_ESCTAG;
+ if (!$this->processedline) {
+ return 3; // to foreach
+ }
+ if (strpos($this->processedline, $esctag) !== false) {
+ if (!strpos($this->processedline, $esctag)) {
+ $linestart = false;
+ return 2; // to while (true)
+ }
+ if (strpos($this->processedline, $esctag)) {
+ $this->appendDesc(substr($this->processedline, 0,
+ strpos($this->processedline, $esctag)));
+ }
+ $this->processedline = $trimline =
+ substr($this->processedline, strpos($this->processedline, $esctag));
+ $linestart = false;
+ return 2; // to while(true)
+ }
+ }
+ }
+
+ function searchForInlineTag($inlinetagpos, $comment)
+ {
+ if ($inlinetagpos) {
+ $this->appendDesc(substr($this->processedline, 0, $inlinetagpos));
+ }
+ if ($inlinetagpos === strpos($this->processedline, '{@internal')) {
+ $state = array_shift($this->states);
+ array_unshift($this->states, $state);
+ if ($state == PHPDOC_LEXER_INTERNAL || $state == PHPDOC_LEXER_INTERNALTAG) {
+ // throw exception
+ return $this->throwException('cannot nest {@internal}} in line number ' .
+ $this->linenum . ': "' . $line . '"', 'internaltag');
+ }
+ $basestate = array_pop($this->states);
+ array_push($this->states, $basestate);
+ if ($basestate == PHPDOC_LEXER_DESC) {
+ $newstate = PHPDOC_LEXER_INTERNAL;
+ } else {
+ $newstate = PHPDOC_LEXER_INTERNALTAG;
+ }
+ array_unshift($this->states, $newstate);
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_INTERNAL, '{@internal');
+ $this->processedline = substr($this->processedline, $inlinetagpos + strlen('{@internal'));
+ return $newstate;
+ }
+ if (!preg_match('/^({@[^}\s]+)\s/', substr($this->processedline, $inlinetagpos), $matches)) {
+ if (!preg_match('/^({@[^}\s]+)}/', substr($this->processedline, $inlinetagpos), $matches)) {
+ if ($this->hasEndchar($comment, '}')) {
+ $matches = array(substr($this->processedline, $inlinetagpos),
+ substr($this->processedline, $inlinetagpos));
+ } else {
+ // throw exception if this does not match
+ $this->throwException('Unclosed inline tag encountered on line number ' .
+ $this->linenum . ': "' . $line . '"', 'tag');
+ return PHPDOC_LEXER_DESC;
+ }
+ } else {
+ // throw exception if this does not match
+ $this->throwException('Invalid inline tag encountered in line number ' .
+ $this->linenum . ': "' . $line . '"', 'tag');
+ return PHPDOC_LEXER_DESC;
+ }
+ }
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_INLINETAG, $matches[1]);
+ $this->processedline = substr($this->processedline, $inlinetagpos + strlen($matches[1]));
+ return PHPDOC_LEXER_INLINETAG;
+ }
+
+ function appendDesc($desc)
+ {
+ if (!strlen($desc)) {
+ return;
+ }
+ if (count($this->tokens)) {
+ $last = array_pop($this->tokens);
+ if ($last[0] == PHPDOC_DOCBLOCK_TOKEN_DESC) {
+ $last[1] .= $desc;
+ $this->tokens[] = $last;
+ } else {
+ $this->tokens[] = $last;
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_DESC, $desc);
+ }
+ } else {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_DESC, $desc);
+ }
+ }
+
+ function hasEndChar($comment, $char)
+ {
+ $linenum = $this->linenum;
+ foreach ($comment as $num => $line) {
+ if ($linenum !== false && $num <= $linenum) {
+ continue;
+ }
+ $linenum = false;
+ $processedline = trim($line);
+ if ($processedline == '*/') {
+ break;
+ }
+ if (!$processedline) {
+ continue;
+ }
+ if (substr($processedline, 0, 3) == '/**') {
+ $processedline = substr($processedline, 3);
+ if (!$processedline) {
+ continue;
+ }
+ if (trim($processedline) == '*/') {
+ break;
+ }
+ } else {
+ $processedline = substr($processedline, 1);
+ }
+ if (strpos($processedline, $char) !== false) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ function endSimpleList()
+ {
+ if (count($this->tagStack)) {
+ $this->tokens = array();
+ return $this->throwException('Error: unclosed html tags: "' .
+ implode(', ', $this->tagStack) . '"', 'simplelist');
+ }
+ while (count($this->simplelist)) {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTEND, '');
+ }
+ }
+
+ function throwException($message, $type)
+ {
+ $this->error = array($message, $this->linenum, $type);
+ $this->exception = true;
+ }
+}
+?> \ No newline at end of file