1 if ($nextQuotePos == 1) {//Мен(возможно имеет место бог-пидорское не дописование комментария). Планировалось написать что то такое: значение менее 1 быть не может так как позиция определяется от 10ого символа, то если будет или false или значение большее или равное 1 $attrValue = ""; } else {//У атрибута есть не пустое значение(хотя если далее до конца тега будет допущена синтаксическая ошибка, то возможно это не атрибут и не его значение) $attrValue = substr($text,($shift+1),($nextQuotePos-1)); // echo "shift: ";var_dump($shift); // echo "nextQuote: ";var_dump($nextQuotePos); $shift += $nextQuotePos + 1;//Почему 1 - плюс сама кавычка, хотя открывающая кавычка не была удалена, она всё равно учтена в позиции $nextQuotePos, поэтому открывающая отдельно не плюсуется $textCodeLower = substr($textCodeLower,($nextQuotePos + 1)); } $attrAr["$attrName"] = $attrValue; //echo "ЗдесьТестируемоеЗначение:";var_dump($shift);var_dump(substr($text,($shift))); //echo "аКромеЗначенияЕщё:";var_dump($textCodeLower); //echo "ЗначениеВМассиве: \$attrValue";var_dump($attrValue);echo "\n";var_dump($attrAr); } else { //Если выполняется эта ветка, значит при попытке найти значение атрибута последовательность предположительного атрибута начинающаяся с двойной кавычки или апострофа далее по тексту нигде не закрывается аналогичной кавычкой, а значит не имеет смысла дальнейший поиск атрибутов и bb кодов, поскольку текущий тег не является корректным bb или содержит синтаксическую echo "test321";exit; } } elseif ($chr == "]") {//Сейчас предполагается что тег закончился и значение не указано, хотя можно и присвоить это значение тегу. Значение атрибута по запланированному варианту будет равно NULL как и если бы знака = не было } else {//Значение задаётся без кавычек и завершится там где появятся пробельные символы или окончание тега } //[КОНЕЦ]Убираем пробелы после равно в атрибутах } echo "test5678attr=$attrName"; } else {//Предполагается что это конце if ($chr != "]") { //Срабатывается когда символ "]" идёт после пробела или пробелов(подразумеваются пробельные символы) после значения атрибута(хотя правильно ли так утверждать если после имени атрибута не следует знака "=") а так же предположительно когда знак "]" идёт сразу после имени тега(так же без пробела или пробелов) echo "[TEXTBP1]"; $continueSearchingAttributesFlag = false; $textCodeLower = substr($textCodeLower,1); $shift++; } } else { echo "test234";var_dump($chr); //Не является блоком кода } }//Конец цикла по атрибутам if ($closingCodeTag < $shift) {echo "[ОпределениеНовойПозицииЗакрывающегоТега]"; if (($closingCodeTag = strpos($textCodeLower,"[/ncode]")) === false) { //Если закрывающего тега нет, значит это не тег(если не рассматривать самозакрывающиеся теги) и более того получается нет необходимости продолжать поиск других тегов(опять же если не рассматривать вариант с самозакрывающимися тегами) } } else { $closingCodeTag -= $shift;//Исходное значение выше было приведено для $text, если оно оказалось меньше $shift будет определёна новая позиция закрывающего тега по переменной $textCodeLower, нужно было или её приводить к позиции $shift или пересчитать значение полученное ранее к позиции относительно актуальной переменной $textCodeLower, решил чтобы потом не производить вычитание при определении значения тега привести позицию к значению относительно актуальной переменной $textCodeLower, получается что позиция в $closingCodeTag совпадает с длиной значения тега } if ($closingCodeTag !== false) { //!!!!БОГ-ПИДОР!!!!! Значение. // $value = substr($text,$shift,$closingCodeTag); $tagAr[] = array("value"=>substr($text,$shift,$closingCodeTag),"attr"=>$attrAr); $previousAr[] = substr($text,$startPosPreviousPart,$previousPartLen); $textCodeLower = substr($textCodeLower,($closingCodeTag+8)); $textLower = $textCodeLower;//Может в этой переменной и нет смысла, при этом она используется в while по тегам, поэтому использую эту строку или как вариант использовать $shift при поиске тега в while $shift += $closingCodeTag+8; echo "ЗначениеТега:";var_dump($value);echo "test9876:";var_dump($textCodeLower); echo "test5432:";var_dump(substr($text,$shift));//if ($yy == 3) {exit;} echo "\n\n=======================\n\n"; } else { //Возможно в этом условии нет необходимости, если условие сработало значит закрывающего тега нет, только эту логику возможно можно целиком реализовать выше, как только становится известно что закрывающего тега нет } //echo "BogPidor222:";var_dump(substr($text,$shift));var_dump(substr($text,$closingCodeTag)); //echo "BogPidor333.СмещениеЗакрывающегоТега:";var_dump($shift);var_dump($closingCodeTag);exit; echo "Существует"; }echo 1; //exit; var_dump($posClosingSquareBracket); var_dump($pos);var_dump($posClosingSquareBracket); //var_dump(substr($textLower,($shift+$posClosingSquareBracket+1)));//Вывод того что за пределами ] if (($chr = substr($textCodeLower,0,1)) == "]") { //Код без атрибутов } elseif ($chr == " ") { $textCodeLower = substr($textCodeLower,1);//Убрать пробел while (($chr = substr($textCodeLower,0,1)) == " ") { echo "[УбранЛишнийПробел]"; $textCodeLower = substr($textCodeLower,1); // $pos++;//Эту ли переменную нужно увеличивать } //Возможно наличие атрибутов } else { //Не является блоком кода } //exit; $checkSpace = false; while (substr($textCodeLower,0,1) ==" ") { $textCodeLower = substr($textCodeLower,1); $pos++; } } //[НАЧАЛО]Добавляем последнюю часть(после последнего тега) если она есть в массив $previousAr if ($shift > 0) {$previousAr[] = substr($text,$shift);} //[КОНЕЦ]Добавляем последнюю часть(после последнего тега) если она есть в массив echo "Массив частей:";var_dump($previousAr); echo "Массив тегов:";var_dump($tagAr); echo "ok"; Функция parseNCodeTag для парсинга тегов NCODE function parseNCodeTag($text=false,&$textPartAr=false,&$tagAr=false) {//Ранее использовалось название переменной $previousAr в которой previous переводится как "предыдущий", в входном значении функции эта переменная была переименована в, хотя внутри функции название переменной $previousAr осталось, добавлена лишь строка где добавляется ссылка на(хотя может быть и нормально что внутри функции пеерменная так называется, поскольку почти до конца функции переменная хранит предыдущие части контекста между тегами) if (($text !== false) and (gettype($text) !== "object") and ($textPartAr === array()) and ($tagAr === array())) {//Для $text возможно стоит использовать другие проверки, пока оставил этот вопрос и проверяю только что не является объектом // var_dump(strpos("123456789","6",5));exit; $textLower = strtolower($text); $yy = 0; $shift = 0; $startPosPreviousPart = false; //$endPosPreviousPart = false;//Не используется и не использовалась - закомментировал $previousAr = &$textPartAr;//Ранее присваивался пустой массив, теперь присваивается ссылка на $textPartAr, то-есть у функции другое название у входящей переменной, решил внутри функции не менять а просто сделать ссылку $tagAr = array();//По идее можно убрать это присвоение поскольку значение переменной передаётся таким в функцию, хотя возможно я эту логику позже поменяю, чтобы не присваивать перед использованием функции пустой массив переменной и как раз возможно будет использоваться эта строка, хотя и возможно в другом месте while (($pos = strpos($textLower,"[ncode")) !== false) {//Есть ли смысл определять здесь существует ли закрывающая скобка или тег, если может оказаться что они являются значением атрибута - если только проверить существую ли они хотя бы в таком варианте иначе проверку можно прекратить $startPosPreviousPart = $shift; // $endPosPreviousPart = $shift + $pos;//Или можно было к $startPosPreviousPart прибавлять. Позже закомментировал, поскольку в строке ниже стал использовать(ещё до того как применил текущую переменную) длину части, а для определения позиции последней части(после последнего тега) используется $shift $previousPartLen = $pos;//Позже решил именно длину предыдущего участка использовать а не позицию окончания $yy++; $textCodeLower = substr($textLower,($pos+6)); $shift += $pos+6;//if ($yy == 2) {echo "[YY2]";var_dump($textCodeLower);}if ($yy == 3) {echo "[YY3]";var_dump($textCodeLower);} // var_dump($textCodeLower);exit; $attrAr = array();//Ранее находилось ниже поиска ], перенесено, чтобы не использовать ниже уровня определения, а так же для того чтобы можно было определить по пустому массиву отсутствие атрибутов if ((($posClosingSquareBracket = strpos($textCodeLower,"]")) !== false) and (($closingCodeTag= strpos($textCodeLower,"[/ncode]",$posClosingSquareBracket)) !== false)) {//Если есть закрывающая скобка открывающего тега кода и конечный тег кода то можно пробовать получать атрибуты и содержание кода // var_dump($closingCodeTag);exit;//Не достаточно вписать в атрибут закрывающий тег для того чтобы по логике ниже сработало новое определение позиции закрывающего тега, поскольку определение позиции осуществляется относительно закрывающей скобки текущего тега, то есть требуется в атрибут до закрывающей скобки вписать ещё "]"(закрывающую скобку) или в предыдущие атрибуты текущего тега $closingCodeTag += $shift;//Выше позиция определяется относительно начала тега(а именно с символа после его имени), для того чтобы позицию закрывающего тега можно было использовать для проверки не был ли закрывающий тег найден внутри атрибута(хотя нужно ли это вообще) к полученной выше позиции добавляется значение $shift, поскольку переменная $textCodeLower будет изменяться и тогда как использовать позицию полученную выше, с учётом $shift позиция закрывающего тега соответствует переменной $text //echo "BogPidor800:";var_dump($closingCodeTag);var_dump(substr($text,($closingCodeTag)));echo "\$textCodeLower:";var_dump($textCodeLower);exit; //var_dump($posClosingSquareBracket);echo "xx";var_dump($textCodeLower); //Рано операцию ниже выполнял, закомментировал // $textCodeLower = substr($textCodeLower,($posClosingSquareBracket+1),($closingCodeTag-$posClosingSquareBracket-1)); // echo"test123:";var_dump("($textCodeLower)"); $continueSearchingAttributesFlag = true; while ($continueSearchingAttributesFlag) { if (($chr = substr($textCodeLower,0,1)) == "]") {//Как вариант можно было проверить позицию символа в переменной $posClosingSquareBracket на 0, при этом всё равно для условий ниже требуется символ //Срабатывается когда символ "]" идёт после значения атрибута(хотя правильно ли так утверждать если после имени атрибута не следует знака "=") без пробела или пробелов(имеются ввиду пробельные символы) а так же предположительно когда знак "]" идёт сразу после имени тега(так же без пробела или пробелов) //echo "[TEXTBP2]"; $continueSearchingAttributesFlag = false; $textCodeLower = substr($textCodeLower,1); $shift++; //Код без атрибутов } elseif ($chr == " ") { // echo "ПробелПослеNCode"; //Возможно наличие атрибутов $textCodeLower = substr($textCodeLower,1);//Убрать пробел $shift++; while ((($chr = substr($textCodeLower,0,1)) == " ") or ($chr == "\r") or ($chr == "\n")) { // echo "[УбранЛишнийПробел]"; $textCodeLower = substr($textCodeLower,1); $shift++; // $pos++;//Эту ли переменную нужно увеличивать } if ($chr != "]") { $textCodeLower = substr($textCodeLower,1); $shift++; $attrName = $chr; while (!in_array(($chr = substr($textCodeLower,0,1)),array("\n","\r","]"," ","="))) {//По идее в цикле можно было бы проверять длину разбираемой строчки, чтобы избежать зацикливания если данные закончатся, чего не должно бы быть поскольку всё равно где то должен быть символ "]", хотя тут может быть такой момент что этот символ далее может быть частью строки значения атрибута и это возможно стоит как то учесть $attrName .= $chr; $textCodeLower = substr($textCodeLower,1); $shift++; } //echo "Текущий код символа в переменной \$chr: " . ord($chr) . "!"; //[НАЧАЛО]Убираем пробелы перед = в атрибутах while (in_array($chr,array(" ","\r","\n"))) { $textCodeLower = substr($textCodeLower,1); $shift++; $chr = substr($textCodeLower,0,1); //echo "[УдранпробельныйСимволПередРавно]"; } //[КОНЕЦ]Убираем пробелы перед = в атрибутах if ($chr == "=") {//echo "[НайденоРавно]"; $textCodeLower = substr($textCodeLower,1); $shift++; //[НАЧАЛО]Убираем пробелы после равно в атрибутах while (in_array(($chr = substr($textCodeLower,0,1)),array(" ","\r","\n"))) { $textCodeLower = substr($textCodeLower,1); $shift++; // echo "[УбранПробелПослеРавно]"; } //[КОНЕЦ]Убираем пробелы после равно в атрибутах //echo "Ril:";var_dump(substr($text,($shift))); //echo "BogPid:";var_dump($textCodeLower); if (($chr == ($quoteType = "\"")) or ($chr == ($quoteType = "'"))) {//Значение атрибута в кавычках if (($nextQuotePos = strpos($textCodeLower,$quoteType,1)) !== false) { $attrValue = false;//Определил чтобы не использовать уровнем ниже, кстати можно было определить в "" и не использовать условие уровнем ниже, а сразу условие $nextQuotePos > 1 if ($nextQuotePos == 1) {//Мен(возможно имеет место бог-пидорское не дописование комментария). Планировалось написать что то такое: значение менее 1 быть не может так как позиция определяется от 10ого символа, то если будет или false или значение большее или равное 1 $attrValue = ""; } else {//У атрибута есть не пустое значение(хотя если далее до конца тега будет допущена синтаксическая ошибка, то возможно это не атрибут и не его значение) $attrValue = substr($text,($shift+1),($nextQuotePos-1)); // echo "shift: ";var_dump($shift); // echo "nextQuote: ";var_dump($nextQuotePos); $shift += $nextQuotePos + 1;//Почему 1 - плюс сама кавычка, хотя открывающая кавычка не была удалена, она всё равно учтена в позиции $nextQuotePos, поэтому открывающая отдельно не плюсуется $textCodeLower = substr($textCodeLower,($nextQuotePos + 1)); } $attrAr["$attrName"] = $attrValue; //echo "ЗдесьТестируемоеЗначение:";var_dump($shift);var_dump(substr($text,($shift))); //echo "аКромеЗначенияЕщё:";var_dump($textCodeLower); //echo "ЗначениеВМассиве: \$attrValue";var_dump($attrValue);echo "\n";var_dump($attrAr); } else { //Если выполняется эта ветка, значит при попытке найти значение атрибута последовательность предположительного атрибута начинающаяся с двойной кавычки или апострофа далее по тексту нигде не закрывается аналогичной кавычкой, а значит не имеет смысла дальнейший поиск атрибутов и bb кодов, поскольку текущий тег не является корректным bb или содержит синтаксическую echo "test321";exit; } } elseif ($chr == "]") {//Сейчас предполагается что тег закончился и значение не указано, хотя можно и присвоить это значение тегу. Значение атрибута по запланированному варианту будет равно NULL как и если бы знака = не было } else {//Значение задаётся без кавычек и завершится там где появятся пробельные символы или окончание тега } } //echo "test5678attr=$attrName"; } else {//Предполагается что это конце if ($chr != "]") { //Срабатывается когда символ "]" идёт после пробела или пробелов(подразумеваются пробельные символы) после значения атрибута(хотя правильно ли так утверждать если после имени атрибута не следует знака "=") а так же предположительно когда знак "]" идёт сразу после имени тега(так же без пробела или пробелов) echo "[TEXTBP1]"; $continueSearchingAttributesFlag = false; $textCodeLower = substr($textCodeLower,1); $shift++; } } else { echo "test234";var_dump($chr); //Не является блоком кода } }//Конец цикла по атрибутам if ($closingCodeTag < $shift) {//echo "[ОпределениеНовойПозицииЗакрывающегоТега]"; if (($closingCodeTag = strpos($textCodeLower,"[/ncode]")) === false) { //Если закрывающего тега нет, значит это не тег(если не рассматривать самозакрывающиеся теги) и более того получается нет необходимости продолжать поиск других тегов(опять же если не рассматривать вариант с самозакрывающимися тегами) } } else { $closingCodeTag -= $shift;//Исходное значение выше было приведено для $text, если оно оказалось меньше $shift будет определёна новая позиция закрывающего тега по переменной $textCodeLower, нужно было или её приводить к позиции $shift или пересчитать значение полученное ранее к позиции относительно актуальной переменной $textCodeLower, решил чтобы потом не производить вычитание при определении значения тега привести позицию к значению относительно актуальной переменной $textCodeLower, получается что позиция в $closingCodeTag совпадает с длиной значения тега } if ($closingCodeTag !== false) { //!!!!БОГ-ПИДОР!!!!! Значение. // $value = substr($text,$shift,$closingCodeTag); $tagAr[] = array("value"=>substr($text,$shift,$closingCodeTag),"attr"=>$attrAr); $previousAr[] = substr($text,$startPosPreviousPart,$previousPartLen); $textCodeLower = substr($textCodeLower,($closingCodeTag+8)); $textLower = $textCodeLower;//Может в этой переменной и нет смысла, при этом она используется в while по тегам, поэтому использую эту строку или как вариант использовать $shift при поиске тега в while $shift += $closingCodeTag+8; //echo "ЗначениеТега:";var_dump($value);echo "test9876:";var_dump($textCodeLower); //echo "test5432:";var_dump(substr($text,$shift));//if ($yy == 3) {exit;} //echo "\n\n=======================\n\n"; } else { //Возможно в этом условии нет необходимости, если условие сработало значит закрывающего тега нет, только эту логику возможно можно целиком реализовать выше, как только становится известно что закрывающего тега нет } //echo "BogPidor222:";var_dump(substr($text,$shift));var_dump(substr($text,$closingCodeTag)); //echo "BogPidor333.СмещениеЗакрывающегоТега:";var_dump($shift);var_dump($closingCodeTag);exit; // echo "Существует"; }//echo 1; //exit; //var_dump($posClosingSquareBracket); //var_dump($pos);var_dump($posClosingSquareBracket); //var_dump(substr($textLower,($shift+$posClosingSquareBracket+1)));//Вывод того что за пределами ] if (($chr = substr($textCodeLower,0,1)) == "]") { //Код без атрибутов } elseif ($chr == " ") { $textCodeLower = substr($textCodeLower,1);//Убрать пробел while (($chr = substr($textCodeLower,0,1)) == " ") { echo "[УбранЛишнийПробел]"; $textCodeLower = substr($textCodeLower,1); // $pos++;//Эту ли переменную нужно увеличивать } //Возможно наличие атрибутов } else { //Не является блоком кода } //exit; $checkSpace = false; while (substr($textCodeLower,0,1) ==" ") { $textCodeLower = substr($textCodeLower,1); $pos++; } } //[НАЧАЛО]Добавляем последнюю часть(после последнего тега) если она есть в массив $previousAr if ($shift > 0) { $previousAr[] = substr($text,$shift); return true;//Если хотя бы один тег был найден соответсвенно возвращается true } //[КОНЕЦ]Добавляем последнюю часть(после последнего тега) если она есть в массив // echo "Массив частей:";var_dump($previousAr); // echo "Массив тегов:";var_dump($tagAr); // echo "ok"; } return false; } Пример использования функции $text = "Некоторое содержание до вставки кода [NCODE name = \"Заголовок\" name2=\"x2[/ncode]y\" huuamba=\"Ямба\"]123