Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Парсинг BBcode (https://javascript.ru/forum/misc/24939-parsing-bbcode.html)

Gozar 19.01.2012 20:00

Цитата:

Сообщение от devote (Сообщение 151490)
сначала обработать не жадным методом, а на последок жадным

Первый не жадным, а в рекурсию вписать жадный. Да, думаю так будет быстрее.

poorking 19.01.2012 20:29

Цитата:

Сообщение от Gozar
[color = red\]bububu[/color] не проблема, ведь мы получаем весь BBcode и можем потом с ним делать что хотим.

Ну уж не обязательно за пользователя делать все все все, не валидные BB я б не стал парсить, и обязательно искать теги по парам? Иначе можно без циклов и рекурсии, если, конечно не считать replace c global циклом

var BB = new function () {
			
	this.tags = {
		U: "ins",
		I: "em",
		B: "strong",
		S: "del"
	}
			
	function parseAttr(attr) {
		
		//	не реализовано
		return "ATTR";
	}
		
	var BB = /(?:\[(\/)?\s*(?:((?:\\[\s\S]|[^\[\]\s\=\/])+)(?:\s*=\s*((?:(?:(?:"[^"]*")|(?:'[^']*'))|(?:\\[\s\S]|[^\[\]\s\/]))+))?)\s*\])/g;
			
	this.toHtml = function (string) {
				
		var self = this;
				
		return string.replace(BB, function (m, closed, name, attr) {
			name = name.toUpperCase();
			
			return self.tags[name] ?
				"<" + (closed || "") + self.tags[name] +
					(attr ? " " + parseAttr(attr) : "") + ">" : m;
		});
	}
		
		
}();
		
var str = "[B]bold [B]bold [B = SOME]bold [I] ITALIC FONT[/I] foo[/B] bar [/B] zot [/B] zorg";
		
alert(BB.toHtml(str))


Извиняюсь если ерунду ляпнул, голова к вечеру квадратная

nerv_ 19.01.2012 20:41

Совсем недавно мне тоже приходилось писать регу для парсинга bbcode, правда всего одного, условного, для подсветки кода. Если принимать во внимание, что писал я ее после ~ недели знакомства с regexp, то, думаю получилось приемлемо (пример, код). Решения, примененные там, считаю далеко не оптимальными)
По вопросу. Признаться, на данный момент, вряд ли я чем смогу Вам помочь и заранее извиняюсь за разведенный флуд, но не могу понять, как может это
Цитата:

Сообщение от Gozar
сначала обработать не жадным методом, а на последок жадным

работать, при вашем условии
alert(/\[B\].*?\[\/B\]/.exec("[B]aaaa [B] bbbb[/B] aaa[/B]")); // не жадно
alert(/\[B\].*\[\/B\]/.exec("[B]aaaa [B] bbbb[/B] aaa[/B]")); // жадно

Моя логика подсказывает, что в данном конкретном случае, надо "откусить кусок побольше", а уже потом "чавкать" :)
Ссыллки на гугл давать не буду, но кое-что посоветую (если не читали): 4, 5, 6 главы "Дж.Фридл - Регулярные выражения, 3-е изд.[2008]". Если не ошибаюсь, там как раз обсуждаются вопросы эффективности построения регулярных выражений.

p.s.: все это моя субъективная точка зрения, Вы, я думаю, опытнее будите в выше обозначенных вопросах, поэтому если что не так, извиняйте)

Цитата:

Сообщение от poorking
не валидные BB я б не стал парсить

Если считать валидностью наличие пары, то получается, что парсите :)

devote 19.01.2012 21:09

Вот самый лучший и качественный вариант, работает без ошибок и начинает действовать с середину, то-есть с вложенных а уж потом обрабатывает родительские теги.
var text = 'test [b=color]bold[/b] tatata [b]blah[/b] tata [code run]function(){}[/code] tar [quote]blah blah [i]ta[i]r[/i]am[/i] param[/quote]';
  
function parseBBCode( text ) {
    return text.replace( /\[(([a-z]+)(?:(?:\=|\s)([^\]]+))?)\](.*)/gi, function( all, tagAttr, tag, attr, end ) {
        var re = new RegExp( "(.*?)(\\[\\/(" + tag + ")\\]|\\[([a-z]+.*?)\\])(.*)", "i" );
        return parseBBCode( end.replace( re, function( subAll, content, tags, closeTag, openTag, subEnd ) {
            if ( openTag ) {
                return '[' + tagAttr + ']' + parseBBCode( subAll );
            } else {

                // tag - содержит имя тега BBCode
                // tagAttr - содержит и тег и его атрибут(ы)
                // attr - трибут(ы) текущего тега
                // content - собственно содержимое этого тега

                alert( [ tagAttr, content, closeTag ].join("\n") );
                return '<' + tag + '>' + content + '</' + closeTag + '>' + subEnd;
            }
        }));
    });
}
  
alert( parseBBCode( text ) );

Gozar 19.01.2012 21:30

Цитата:

Сообщение от nerv_ (Сообщение 151510)
не могу понять, как может этоработать, при вашем условии
alert(/\[B\].*?\[\/B\]/.exec("[B]aaaa [B] bbbb[/B] aaa[/B]")); // не жадно
alert(/\[B\].*\[\/B\]/.exec("[B]aaaa [B] bbbb[/B] aaa[/B]")); // жадно

Ты не можешь понять потому, что я делаю не так как ты. Приведенный тобой пример ни к чему не относится.

Я делаю почти так же как написал devote, идея та же - собственно он мне её и подсказал, но реализация чуть сложнее, проверки разные и т.д.

nerv_ 19.01.2012 22:13

Цитата:

Сообщение от Gozar
Ты не можешь понять потому, что я делаю не так как ты.

Да, Вы правы. Прогнал код devote в отладчике. Вроде в голове чуть прояснилось) Без опыта программирования на js и в частности механизма построения и использования эффективных регулярный выражений, мне фигово :) Отсюда неверные выводы.

devote 19.01.2012 22:25

nerv_,
главное научится код в голове прокручивать, тогда и вопросов меньше станет и код будешь писать хороший, продуманный...

trikadin 19.01.2012 23:21

Gozar, вы об этом и говорили, наверное... Но я повторюсь. Можно делать так, как тут. То есть в цикле убираем самые вложенные (путём замены их на нормальные теги) и цикл гоняем до тех пор, пока можем найти хоть один непреобразованный bb-код.

Gozar 20.01.2012 14:28

Цитата:

Сообщение от trikadin (Сообщение 151550)
Gozar, вы об этом и говорили, наверное... Но я повторюсь. Можно делать так, как тут. То есть в цикле убираем самые вложенные (путём замены их на нормальные теги) и цикл гоняем до тех пор, пока можем найти хоть один непреобразованный bb-код.

От цикла я давно отказался, рекурсия рулет/торт:).
Я делаю именно так как писал выше. Без всяких new RegExp.
Сначала выбираем из текста максимум, как бы горку, а потом горку просматриваем от самого вложенного(минимального).

Этого должно быть достаточно чтобы не сканить весь текст и не было багов какой-нибудь вложенности, скорость ещё не тестировал, но пока всё нормально и реги мне понятны. Нет никаких end и if, только последовательность, сначала максимум всего, затем уже минимум конкретных тегов рекурсией.

trikadin 21.01.2012 03:39

Цитата:

Сообщение от Gozar
От цикла я давно отказался, рекурсия рулет/торт.

Рекурсия памяти больше жрёт) Но в любом случае, это ваш выбор)


Часовой пояс GMT +3, время: 21:14.