Как бы вы пошли на parsing Markdown?

Изменить: Недавно я узнал о проекте CommonMark, который правильно идентифицирует и имеет дело с неопределенностями в исходной спецификации Markdown. http://commonmark.org/ У него отличная поддержка библиотеки C #.

Здесь вы можете найти синтаксис.

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

Я собираюсь записать код анализатора Markdown . Что такое опыт?

Если у вас нет никакого смысла говорить о фактическом parsingе Markdown, избавьте меня от времени. (Это может показаться суровым, но да, я ищу понимание, а не решение, то есть стороннюю библиотеку).

Чтобы немного помочь в ответах, регулярные выражения предназначены для идентификации шаблонов ! НЕ разбирать всю грамматику. То, что люди считают, что это так, является foobar.

  • Если вы думаете о Markdown, он основывается на концепции абзацев.
  • Таким образом, разумный подход может заключаться в разделении ввода на абзацы.
  • Существует много видов абзацев, например, заголовок, текст, список, блок-образец и код.
  • Таким образом, задача состоит в том, чтобы идентифицировать эти параграфы и в каком контексте они происходят.

Я вернусь с решением, как только я нахожу, что это достойно быть разделенным.

Единственная реализация уценки, о которой я знаю, которая использует фактический парсер, – это привязка кодов Джона МакФарлейна . Его синтаксический анализатор основан на синтаксическом анализаторе грамматики выражений Parsing Expression, называемом peg .


EDIT: Маурисио Фернандес недавно выпустил свой сингл Simple Markup Markdown , который он написал как часть своего OcsiBlog Weblog Engine. Поскольку синтаксический анализатор написан в OCaml , он чрезвычайно прост и короток (268 SLOC для синтаксического анализатора , 43 SLOC для HTML-эмиттера ), но невероятно быстро (на 20% быстрее, чем скидка (написана в ручном оптимизированном C) и в шестьсот раз быстрее чем BlueCloth ( Ruby )), несмотря на то, что он еще не оптимизирован для производительности. Поскольку он предназначен только для внутреннего использования Маурисио для его веб-журнала, есть несколько отклонений от официальной спецификации Markdown , но Mauricio создал ветку, которая возвращает большинство этих изменений .

На прошлой неделе я выпустил новую реализацию Markdown Java на основе парсера, называемую pegdown . pegdown использует парсер PEG для создания абстрактного синтаксического дерева, которое впоследствии выписывается в HTML. Таким образом, он достаточно чист и намного легче читать, поддерживать и расширять, чем подход, основанный на регулярном выражении. Грамматика ПЭГ основана на реализации Джона МакФарланеса «привязка кодов».

Может быть, что-то интересное для вас …

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

В принципе, я бы построил мини-DOM-подобное дерево, когда прочитал входной файл.
Чтобы генерировать вывод, я бы просто пересекал дерево и выводил HTML или что-то еще (PS, LaTex, RTF, …)

Вещи, которые могут увеличить сложность:

  • Тот факт, что вы можете смешивать HTML и уценку, хотя правило может быть легко реализовано: просто игнорируйте все, что находится между двумя сбалансированными тегами, и выводите его дословно.

  • URL-адреса и заметки могут иметь ссылку в нижней части текста. Использование структур данных для гиперссылок может просто записать что-то вроде:

    [my text to a link][linkkey] results in a structure like: URLStructure: | InnerText : "my text to a link" | Key : "linkkey" | URL :  
  • Заголовки могут быть определены с подчеркиванием, что может заставить нас использовать простую структуру данных для общего абзаца и изменить его свойства при чтении файла:

     ParagraphStructure: | InnerText : the current paragraph text | (beginning of line until end of line). | HeadingLevel :  or 1-4 when we can assess | that paragraph heading level, if any. 

Во всяком случае, только некоторые мысли.

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

Я бы, наверное, достаточно долго читал спецификацию синтаксиса, чтобы узнать ее, и понять, как ее разобрать.

Чтение существующего кода парсера, конечно же, блестящее, как для того, чтобы увидеть, что, по-видимому, является основным источником сложности, и если используются специальные умные трюки. Использование контрольной суммы MD5 кажется немного странным, но я недостаточно изучил этот код, чтобы понять, почему это делается. Комментарий в процедуре под названием _EscapeSpecialChars() указывает:

Мы заменяем каждый такой символ соответствующим значением контрольной суммы MD5; это, вероятно, излишний, но это должно помешать нам случайно столкнуться с эвакуационными значениями.

Замена одного символа на полный MD5 кажется экстравагантным, но, возможно, это действительно имеет смысл.

Конечно, было бы разумно подумать о создании «истинного» синтаксиса для такого инструмента, как Flex, чтобы выбраться из regex болота.

Если Perl не ваша вещь, есть реализация Markdown, по крайней мере, на 10 других языках . Они, вероятно, не все имеют 100% совместимость, но, как правило, довольно близки.

MarkdownPapers – другая реализация Java, парсер которой определен в грамматике JavaCC .

Существуют библиотеки, доступные на нескольких языках, включая php, ruby, java, c #, javascript. Я бы предложил рассмотреть некоторые из них для идей.

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

Regexes работают в perl, потому что perl и regex являются лучшими друзьями.

Если вы используете язык программирования, в котором есть более трех других пользователей, вы должны найти библиотеку для ее анализа. Быстрый Google-поиск показывает библиотеки для CL, Haskell, Python, JavaScript, Ruby и т. Д. Очень маловероятно, что вам нужно будет изобрести это колесо.

Если вам действительно нужно писать это с нуля, я рекомендую написать правильный парсер. С помощью этой техники вам не придется избегать проблем с hashами MD5. (Я согласен, что если вам нужно сделать что-то подобное, пришло время пересмотреть ваш дизайн.)

Markdown – это JAWL (просто другой язык вики)

Существует много открытых wiki-источников, которые вы можете проверить код анализатора. Большинство используют REGEX

Посмотрите виниловую вики, есть интересный многопроходный канал форматирования, очень хороший метод – см. /Core/Formatter.cs и /core/FormatterPipeline.cs

Лучше всего использовать / присоединяться к существующему проекту, такие вещи всегда намного сложнее, чем они появляются

Здесь вы можете найти JavaScript-реализацию Markdown. Он также в значительной степени зависит от регулярных выражений, поскольку это всего лишь самый быстрый и простой способ анализа текста.

Но он сохраняет часть MD5.

Я не могу напрямую помочь в кодировании синтаксического анализа, но, возможно, эта ссылка может помочь вам так или иначе.

Давайте будем гением компьютера.