Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Создание облегченной разметки


Автор: Logo 15.9.2010, 13:31
Хочу сделать облегченную разметку, вроде markdown. Но, в отличии от Text::Markdown хотелось бы сделать обработку ошибок, и валидный код на выходе.
Есль примеры подобных вещей на перле, или статьи, как это можно сделать?

Автор: DurRandir 15.9.2010, 16:30
1. Написать грамматику для языка разметки. Но в этом случае ограничены возможности по коррекции неправильного ввода. Если хватает диагностики "а у вас тут тег не правильный", без коррекции, - то это оптимальный вариант. Хотя можно попытаться сделать грамматику более лёгкой и строить html по дереву разбора с коррекцией. Но не уверен в результатах такого подхода.
2. Спуститься уровнем ниже, и писать свой конечный автомат по разбору текста. В этом случае можно и вносить исправления, и выдавать любую диагностику. Минус - количество переходов между состояниями растёт очень быстро. У меня есть простой парсер bb-кодов, сделанный вручную как автомат, могу показать.

Автор: Logo 15.9.2010, 19:50
Да, достатоточно "а у вас тут тег не правильный", но только сразу найти все ошибки в тексте. И желательно сказать, почему не правильный.

Грамматики мне показались сложноватыми, кроме того, в разметке присуствует неодназначность -
Код

...текст

  block
  block

текст...


Block может быть воспринят как абзац с пробелами для удобочитаемости - абзацы разделяются пустыми строками. Но если каждая строка "абзаца" начинается с пробелных символов, то это другая синтаксическая конструкция.

Да, хотелось бы взглянуть на парсер bb-кодов.

Автор: DurRandir 15.9.2010, 23:57
А есть где-нибудь полное описание этой разметки? По ссылке в Text::Markdown на родной сайт - очень мутное описание. Отделить блок  от "блока, начинающегося с пробелов" - достаточно просто. Вот пример грамматики для разметки, содержащей только блоки из строк, возможно начинающихся с пробелов, разделённых переводами строк. Капсом выделены терминалы:

text = | block CRLF text
block = with_spaces | without_spaces
with_spaces = | SPACE line with_spaces
without_spaces = | line without_spaces
line = NO_START_SPACE_LINE CRLF

Почему неправильный - сказать сможет. Выдать сразу все ошибки - нет. Считайте, что это компилятор, работает до 1го сбоя в исходниках) Исходники парсера завтра скину.

Автор: Logo 16.9.2010, 11:11
Разметка своя, из markdown и других взяты идеи. Некоторые вещи специфичны для проекта.
Цитата

#заголовок                         // один уровень заголовков

*жирный текст*                     // правило \*\S ... \S\*
~курсивный текст~                  // правило ~\S ... \S~
{цитата}                           // <cite>цитата</cite>
[:имя картинки]                    // картинка. Имя картинки является одновременно атрибутом alt
[http://oursite.com/...]           // графическая ссылка статью из другого раздела сайта
[http://oursite.com/..., описание] // тоже, с описанием
текст ...                          // Диалог. <blockquote>Имя: <cite>Цитата</cite><br>...</blockquote>

  Автор: Цитата
  Автор: Цитата

... тест
текст ...                          // Диалог с прямой речью

  - Прямая речь
  - Прямая речь

... тест
             
абзац                              // Обивается пустыми строками

[*сноска]

Типографика:
- тире     // дефис, окруженный пробельными символами
-- тире    // пример 1999--2000

""кавычки" кавычки" => «„кавычки“ кавычки»
Кавычка (несколько кавычек), перед которой стоит символ ([{, пробелы, начало строки - открывающая. Остальные кавычки считаются закрывающими. Проверяем кавычки на корректность вложенности.

«» „“ ‘’ “” считаем uicode кавычки для проверки правильности вложенности, и корректной расстановке кавычек из ", в случае их смеси.

' => ’ // типографский апостроф. д’Артаньян

Одиночные пробелы между словами могут преобразовываться в неразрывные пробелы, в соответствии с правилами.
Из пробелов вокруг тире один преобразуется в неразрывный.

Еще:
Последовательность пробельные символы (в т. ч. перевод строки), не имеющие специального значения, описанного выше, преобразуется в один пробел.

Экранирование:
\ отменяет особое действие символа. Поставленная перед обычным символом, не имеет особого действия.
Исключение - символ перевода строки.
"текст" \ {пробелы} "\n"
В этом случае пробелы игнорируются, и \ действует на символ перевода строки.
Внутри сносок, картинок допустимы не экранированные [], при условии корректной вложенности.


Разметка ориентированна на автоматическую верстку, с минимальным участием редактора.
На счет строгости, еще окончательно не решил, пока думаю лучше сообщать о возможных ошибках, чем выводить текст как есть. Имею ввиду такие вещи, как
Цитата

текст * текст текст*
текст [текст текст]


Для упрощения конструкции вроде *жирный ~жирный курсивный* курсивный~ не допускаются, т.е. все корректно вложенное.
inline элементы (цитата, оформление текста) нельзя разрывать блочными (абзац, диалоги, заголовок).
Некоторые теги запрещены внутри других. Например нельзя вставить картинку в заголовок, цитату в имя автора в диалоге.

Автор: DurRandir 16.9.2010, 11:37
http://dur-randir.ru/bbcode.parser.rar

Ключевые куски - это lexer() и BBCode::FSM, неформальное описание автомата - в BBCode::FSM_scheme, остальное занимается генерацией html'я.

Автор: Logo 19.10.2010, 17:07
Правильно я понимаю, при разборе по грамматикам, возможным будет некоторое нарушение:
Код


      - Прямая речь *жирный
текст*
      - Прямая речь 



Одиночный превод строки не будет иметь специального значения внутри inline элементов (т.к. это необходимо в обычных абзацах). В результате включение inline элемента в блок, где перевод строки важен, будет скрывать смысл перевода строки от анализатора.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)