BBCodeLexer

Description

Source

File: bp-forums/admin/parser.php

class BBCodeLexer {
var $token;
var $text;
var $tag;
var $state;
var $input;
var $ptr;
var $unget;
var $verbatim;
var $debug;
var $tagmarker;
var $end_tagmarker;
var $pat_main;
var $pat_comment;
var $pat_comment2;
var $pat_wiki;
function __construct($string, $tagmarker = '[') {
$regex_beginmarkers = Array( '[' => '\[', '<' => '<', '{' => '\{', '(' => '\(' );
$regex_endmarkers = Array( '[' => '\]', '<' => '>', '{' => '\}', '(' => '\)' );
$endmarkers = Array( '[' => ']', '<' => '>', '{' => '}', '(' => ')' );
if (!isset($regex_endmarkers[$tagmarker])) $tagmarker = '[';
$e = $regex_endmarkers[$tagmarker];
$b = $regex_beginmarkers[$tagmarker];
$this->tagmarker = $tagmarker;
$this->end_tagmarker = $endmarkers[$tagmarker];
$this->pat_main = "/( "
. "{$b}"
. "(?! -- | ' | !-- | {$b}{$b} )"
. "(?: [^\\n\\r{$b}{$e}] | \\\" [^\\\"\\n\\r]* \\\" | \\' [^\\'\\n\\r]* \\' )*"
. "{$e}"
. "| {$b}{$b} (?: [^{$e}\\r\\n] | {$e}[^{$e}\\r\\n] )* {$e}{$e}"
. "| {$b} (?: -- | ' ) (?: [^{$e}\\n\\r]* ) {$e}"
. "| {$b}!-- (?: [^-] | -[^-] | --[^{$e}] )* --{$e}"
. "| -----+"
. "| \\x0D\\x0A | \\x0A\\x0D | \\x0D | \\x0A"
. "| [\\x00-\\x09\\x0B-\\x0C\\x0E-\\x20]+(?=[\\x0D\\x0A{$b}]|-----|$)"
. "| (?<=[\\x0D\\x0A{$e}]|-----|^)[\\x00-\\x09\\x0B-\\x0C\\x0E-\\x20]+"
. " )/Dx";
$this->input = preg_split($this->pat_main, $string, -1, PREG_SPLIT_DELIM_CAPTURE);
$this->pat_comment = "/^ {$b} (?: -- | ' ) /Dx";
$this->pat_comment2 = "/^ {$b}!-- (?: [^-] | -[^-] | --[^{$e}] )* --{$e} $/Dx";
$this->pat_wiki = "/^ {$b}{$b} ([^\\|]*) (?:\\|(.*))? {$e}{$e} $/Dx";
$this->ptr = 0;
$this->unget = false;
$this->state = BBCODE_LEXSTATE_TEXT;
$this->verbatim = false;
$this->token = BBCODE_EOI;
$this->tag = false;
$this->text = "";
}
function BBCodeLexer($string, $tagmarker = '[') {
$this->__construct($string, $tagmarker);
}
function GuessTextLength() {
$length = 0;
$ptr = 0;
$state = BBCODE_LEXSTATE_TEXT;
while ($ptr < count($this->input)) {
$text = $this->input[$ptr++];
if ($state == BBCODE_LEXSTATE_TEXT) {
$state = BBCODE_LEXSTATE_TAG;
$length += strlen($text);
}
else {
switch (ord(substr($this->text, 0, 1))) {
case 10:
case 13:
$state = BBCODE_LEXSTATE_TEXT;
$length++;
break;
default:
$state = BBCODE_LEXSTATE_TEXT;
$length += strlen($text);
break;
case 40:
case 60:
case 91:
case 123:
$state = BBCODE_LEXSTATE_TEXT;
break;
}
}
}
return $length;
}
function NextToken() {
if ($this->unget) {
$this->unget = false;
return $this->token;
}
while (true) {
if ($this->ptr >= count($this->input)) {
$this->text = "";
$this->tag = false;
return $this->token = BBCODE_EOI;
}
$this->text = preg_replace("/[\\x00-\\x08\\x0B-\\x0C\\x0E-\\x1F]/", "",
$this->input[$this->ptr++]);
if ($this->verbatim) {
$this->tag = false;
if ($this->state == BBCODE_LEXSTATE_TEXT) {
$this->state = BBCODE_LEXSTATE_TAG;
$token_type = BBCODE_TEXT;
}
else {
$this->state = BBCODE_LEXSTATE_TEXT;
switch (ord(substr($this->text, 0, 1))) {
case 10:
case 13:
$token_type = BBCODE_NL;
break;
default:
$token_type = BBCODE_WS;
break;
case 45:
case 40:
case 60:
case 91:
case 123:
$token_type = BBCODE_TEXT;
break;
}
}
if (strlen($this->text) > 0)
return $this->token = $token_type;
}
else if ($this->state == BBCODE_LEXSTATE_TEXT) {
$this->state = BBCODE_LEXSTATE_TAG;
$this->tag = false;
if (strlen($this->text) > 0)
return $this->token = BBCODE_TEXT;
}
else {
switch (ord(substr($this->text, 0, 1))) {
case 10:
case 13:
$this->tag = false;
$this->state = BBCODE_LEXSTATE_TEXT;
return $this->token = BBCODE_NL;
case 45:
if (preg_match("/^-----/", $this->text)) {
$this->tag = Array('_name' => 'rule', '_endtag' => false, '_default' => '');
$this->state = BBCODE_LEXSTATE_TEXT;
return $this->token = BBCODE_TAG;
}
else {
$this->tag = false;
$this->state = BBCODE_LEXSTATE_TEXT;
if (strlen($this->text) > 0)
return $this->token = BBCODE_TEXT;
continue;
}
default:
$this->tag = false;
$this->state = BBCODE_LEXSTATE_TEXT;
return $this->token = BBCODE_WS;
case 40:
case 60:
case 91:
case 123:
if (preg_match($this->pat_comment, $this->text)) {
$this->state = BBCODE_LEXSTATE_TEXT;
continue;
}
if (preg_match($this->pat_comment2, $this->text)) {
$this->state = BBCODE_LEXSTATE_TEXT;
continue;
}
if (preg_match($this->pat_wiki, $this->text, $matches)) {
$this->tag = Array('_name' => 'wiki', '_endtag' => false,
'_default' => @$matches[1], 'title' => @$matches[2]);
$this->state = BBCODE_LEXSTATE_TEXT;
return $this->token = BBCODE_TAG;
}
$this->tag = $this->Internal_DecodeTag($this->text);
$this->state = BBCODE_LEXSTATE_TEXT;
return $this->token = ($this->tag['_end'] ? BBCODE_ENDTAG : BBCODE_TAG);
}
}
}
}
function UngetToken() {
if ($this->token !== BBCODE_EOI)
$this->unget = true;
}
function PeekToken() {
$result = $this->NextToken();
if ($this->token !== BBCODE_EOI)
$this->unget = true;
return $result;
}
function SaveState() {
return Array(
'token' => $this->token,
'text' => $this->text,
'tag' => $this->tag,
'state' => $this->state,
'input' => $this->input,
'ptr' => $this->ptr,
'unget' => $this->unget,
'verbatim' => $this->verbatim
);
}
function RestoreState($state) {
if (!is_array($state)) return;
$this->token = @$state['token'];
$this->text = @$state['text'];
$this->tag = @$state['tag'];
$this->state = @$state['state'];
$this->input = @$state['input'];
$this->ptr = @$state['ptr'];
$this->unget = @$state['unget'];
$this->verbatim = @$state['verbatim'];
}
function Internal_StripQuotes($string) {
if (preg_match("/^\\\"(.*)\\\"$/", $string, $matches))
return $matches[1];
else if (preg_match("/^\\'(.*)\\'$/", $string, $matches))
return $matches[1];
else return $string;
}
function Internal_ClassifyPiece($ptr, $pieces) {
if ($ptr >= count($pieces)) return -1;
$piece = $pieces[$ptr];
if ($piece == '=') return '=';
else if (preg_match("/^[\\'\\\"]/", $piece)) return '"';
else if (preg_match("/^[\\x00-\\x20]+$/", $piece)) return ' ';
else return 'A';
}
function Internal_DecodeTag($tag) {
$result = Array('_tag' => $tag, '_endtag' => '', '_name' => '',
'_hasend' => false, '_end' => false, '_default' => false);
$tag = substr($tag, 1, strlen($tag)-2);
$ch = ord(substr($tag, 0, 1));
if ($ch >= 0 && $ch <= 32) return $result;
$pieces = preg_split("/(\\\"[^\\\"]+\\\"|\\'[^\\']+\\'|=|[\\x00-\\x20]+)/",
$tag, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
$ptr = 0;
if (count($pieces) < 1) return $result;
if (@substr($pieces[$ptr], 0, 1) == '/') {
$result['_name'] = strtolower(substr($pieces[$ptr++], 1));
$result['_end'] = true;
}
else {
$result['_name'] = strtolower($pieces[$ptr++]);
$result['_end'] = false;
}
while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ')
$ptr++;
$params = Array();
if ($type != '=') {
$result['_default'] = false;
$params[] = Array('key' => '', 'value' => '');
}
else {
$ptr++;
while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ')
$ptr++;
if ($type == "\"")
$value = $this->Internal_StripQuotes($pieces[$ptr++]);
else {
$after_space = false;
$start = $ptr;
while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) != -1) {
if ($type == ' ') $after_space = true;
if ($type == '=' && $after_space) break;
$ptr++;
}
if ($type == -1) $ptr--;
if ($type == '=') {
$ptr--;
while ($ptr > $start && $this->Internal_ClassifyPiece($ptr, $pieces) == ' ')
$ptr--;
while ($ptr > $start && $this->Internal_ClassifyPiece($ptr, $pieces) != ' ')
$ptr--;
}
$value = "";
for (; $start <= $ptr; $start++) {
if ($this->Internal_ClassifyPiece($start, $pieces) == ' ')
$value .= " ";
else $value .= $this->Internal_StripQuotes($pieces[$start]);
}
$value = trim($value);
$ptr++;
}
$result['_default'] = $value;
$params[] = Array('key' => '', 'value' => $value);
}
while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) != -1) {
while ($type == ' ') {
$ptr++;
$type = $this->Internal_ClassifyPiece($ptr, $pieces);
}
if ($type == 'A' || $type == '"')
$key = strtolower($this->Internal_StripQuotes(@$pieces[$ptr++]));
else if ($type == '=') {
$ptr++;
continue;
}
else if ($type == -1) break;
while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ')
$ptr++;
if ($type != '=')
$value = $this->Internal_StripQuotes($key);
else {
$ptr++;
while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ')
$ptr++;
if ($type == '"') {
$value = $this->Internal_StripQuotes($pieces[$ptr++]);
}
else if ($type != -1) {
$value = $pieces[$ptr++];
while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) != -1
&& $type != ' ')
$value .= $pieces[$ptr++];
}
else $value = "";
}
if (substr($key, 0, 1) != '_')
$result[$key] = $value;
$params[] = Array('key' => $key, 'value' => $value);
}
$result['_params'] = $params;
return $result;
}
}

Methods

Questions?

We're always happy to help with code or other questions you might have! Search our developer docs, contact support, or connect with our sales team.