Как бы вы проанализировали Markdown? [закрыто]


126

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

Вы можете найти синтаксис здесь .

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

Я собираюсь жестко запрограммировать парсер для Markdown . Какой опыт с этим?

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

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

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

Я вернусь с решением, как только найду, что им стоит поделиться.


2
@cletus пишет синтаксический анализатор уценки, см. cforcoding.com/search/label/markdown
Алекс Ангас,

В итоге я сделал то же самое. Однако я не пытаюсь анализировать разметку, как если бы это была формальная грамматика, потому что это явно не так. Я применял различные регулярные выражения рекурсивно. И за несколько проходов. Это очень хорошо сработало.
Джон Лейдегрен,

@JohnLeidegren, есть ли шанс, что другие любопытные пользователи, такие как я, увидят вашу попытку разобрать уценку?
jmlopez

@jmlopez Извините, у меня больше нет доступа к этому источнику, если вам нужен синтаксический анализатор уценки, есть пакет NuGet, который можно использовать. Идея достаточно проста: просто примените серию регулярных выражений в проходах, начните с разбиения ввода на абзацы, затем попытайтесь определить, что это за абзац, и так далее. Наконец, проанализируйте ссылки и стили символов в самих абзацах.
Джон Лейдегрен

2
Вы должны посмотреть Parsedown . Он разбивает текст на строки. Затем он смотрит, как эти строки начинаются и соотносятся друг с другом.
Эмануил Русев

Ответы:


69

Только уценка реализацией я знаю, что использует фактический анализатор, является Jon MacFarleane «s колышек-уценка . Его синтаксический анализатор основан на генераторе синтаксического анализатора грамматики выражений синтаксического анализа, называемом peg .


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


1
интересный. возможно, я попробую преобразовать это как проект f #
ShuggyCoUk

@Benjol Та же старая история: нет времени: /
ShuggyCoUk

1
Терренс Парр (соавтор ANTLR) написал один для ANTLR 4: github.com/parrt/mini-markdown
Chris S

17

На прошлой неделе я выпустил новую реализацию Java Markdown, основанную на синтаксическом анализаторе, которая называется pegdown . pegdown использует синтаксический анализатор PEG для первого построения абстрактного синтаксического дерева, которое впоследствии записывается в HTML. Таким образом, он довольно чистый и его намного проще читать, поддерживать и расширять, чем подход, основанный на регулярных выражениях. Грамматика PEG основана на реализации C John MacFarlanes "peg-markdown".

Может быть, вам что-то интересно ...


1
Теперь это официально не рекомендуется
Fabich

7

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

По сути, я бы построил дерево в стиле mini-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       : <null>
    
  • Заголовки могут быть определены с подчеркиванием, что может заставить нас использовать простую структуру данных для общего абзаца и изменять его свойства по мере чтения файла:

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

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

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


3

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

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

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

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

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


Эта штука с MD5 все еще беспокоит меня, а также чрезмерное манипулирование строками должно быть медленнее, чем любой настоящий приличный парсер, который вы могли бы написать самостоятельно.
Джон Лейдегрен 03

2
Flex - это только половина парсера; после токенизации ввода необходимо определить, что означают токены. Для этого и нужен генератор парсеров. Их очень много. («Комбинатор синтаксического анализатора», «рекурсивный спуск» и «LALR (1)» - ключевые слова для
поиска

1
@jrockway: это правда, конечно, я пожал плечами и подумал: «но если он прочтет Flex, он найдет Bison автоматически». :) Спасибо.
расслабьтесь



1

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

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


Я готов принять вызов. Я смотрел библиотеки, но они просто ужасные. Уродливо и глупо. Я подумываю написать парсер на F #, потому что мне нужен проект на F #, но я, вероятно, сделаю это на C #.
Джон Лейдегрен, 03

Надеюсь, в F # есть библиотека вроде Parsec; если так, то это будет забавный проект;)
jrockway 03

0

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

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

Регулярные выражения работают в Perl, потому что perl и regex - лучшие друзья.


1
Regex и perl - лучшие друзья, потому что кто-то так сказал. В этом факте нет больше правды, чем его историческая родословная, то, что он использовался таким образом. Мне не нужны что-то вроде perl.
Джон Лейдегрен, 03

7
Тогда не используйте это ... Кроме того, научитесь иронии.
garrow 03

0

Markdown - это JAWL (просто еще один язык вики)

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

Ознакомьтесь с вики-страницей Screwturn, у нее есть интересный конвейер многопроходного форматирования, очень хорошая техника - см. /Core/Formatter.cs и /core/FormatterPipeline.cs

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


0

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

Но это не касается части MD5.

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.