Як би ви пішли розбирати Маркдаун? [зачинено]


126

Редагувати: Нещодавно я дізнався про проект під назвою CommonMark, який правильно ідентифікує і вирішує неясності в оригінальній специфікації Markdown. http://commonmark.org/ Він має чудову підтримку бібліотеки C #.

Ви можете знайти синтаксис тут .

Джерело, яке випливає із завантаженням, написане на Perl , яке я не маю наміру шанувати. Він пронизаний регулярними виразами, і він покладається на хеші MD5, щоб уникнути певних символів. Щось у цьому просто не так!

Я збираюся жорстко розібрати парсер для Markdown . Який досвід з цим?

Якщо у вас немає нічого значущого сказати про фактичний розбір Маркдауна, шкодуйте мене часу. (Це може здатися суворим, але так, я шукаю розуміння, а не рішення, тобто сторонню бібліотеку).

Щоб допомогти трохи у відповідях, регулярні вирази призначені для виявлення шаблонів ! НЕ розбирати цілу граматику. Що люди вважають, що це роблять, це foobar.

  • Якщо ви думаєте про Маркдаун, він принципово ґрунтується на концепції пунктів.
  • Таким чином, розумним підходом може бути поділ даних на абзаци.
  • Існує багато видів абзаців, наприклад, заголовок, текст, список, блок-котирування та код.
  • Завдання полягає в тому, щоб визначити ці пункти та в якому контексті вони виникають.

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


2
@cletus пише аналізатор розмітки
Алекс Ангас

Я в кінці кінців робив те саме. Однак я не намагаюся розбирати відмітку, як ніби це була формальна граматика, бо це явно не так. Я застосовував різні регулярні вирази рекурсивно. І в кілька проходів. Це вийшло дуже добре.
Джон Лейдегрен

@JohnLeidegren, чи є шанс, щоб інші допитливі користувачі, такі як я, побачили вашу спробу розбору відмітки?
jmlopez

@jmlopez Вибачте, у мене більше немає доступу до цього джерела, якщо вам потрібен аналізатор розмітки, доступний пакет NuGet, який можна використовувати. Ідея досить проста, але просто застосуйте ряд регулярних виразів у пропусках, почніть з розподілу введення в абзацах, а потім спробуйте визначити, що це за абзац тощо. Нарешті, розбираємо посилання та стилі символів у самих абзацах.
Джон Лейдегрен

2
Ви повинні подивитися на Парседаун . Він розбиває текст на рядки. Потім він розглядає, як ці лінії починаються і співвідносяться один з одним.
Емануїл Русєв

Відповіді:


69

Тільки уцінка реалізацією я знаю, що використовує фактичний аналізатор, є Jon MacFarleane «s кілочок-уцінка . Його аналізатор заснований на генераторі граматичного аналізатора парсингу виразів під назвою прив’язка .


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


1
цікаво. можливо, я спробую перетворити це як проект f #
ShuggyCoUk

@Benjol Ця ж стара історія: немає часу: /
ShuggyCoUk

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

17

Минулого тижня я випустив нову реалізацію Java Markdown Java, що називається pegdown . pegdown використовує парсер PEG для спочатку побудови абстрактного дерева синтаксису, який згодом виписується в HTML. Як такий, це досить чисто і набагато простіше читати, підтримувати та розширювати, ніж підхід на основі регулярних виразів. Граматика PEG базується на застосуванні Джона МакФарланеса C "прив'язка".

Можливо, щось цікавить вас ...


1
Зараз це офіційно застаріло
Фабіч

7

Якби я намагався проаналізувати розмітку (і її розширення 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       : <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.
    

У всякому разі, лише деякі думки.

Я впевнений, що є багато дрібних деталей, про які слід подбати, і я майже впевнений, що Regexes може стати в нагоді під час процесу.
Зрештою, вони мали на меті обробляти текст.


3

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

Читання існуючого коду парсера, звичайно, геніальне, як для того, щоб побачити, що здається головним джерелом складності, і якщо використовуються якісь спеціальні хитрі хитрощі. Використання контрольної суми MD5 здається трохи дивним, але я недостатньо вивчив код, щоб зрозуміти, чому це робиться. У коментарі у рутині, що називається _EscapeSpecialChars():

Ми замінюємо кожен такий символ відповідним значенням контрольної суми MD5; це, ймовірно, перевищення, але це повинно запобігти випадковому зіткненню зі значеннями втечі.

Заміна одного символу на повний MD5 здається екстравагантною, але, можливо, це справді має сенс.

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


Ця річ MD5 все ще мене турбує, також надмірна маніпуляція з рядком повинна бути повільнішою, ніж будь-який власне гідний аналізатор, який ви могли написати самі.
Джон Лейдегрен

2
Flex насправді лише половина аналізатора; після того, як ви ввімкнули токенізований вхід, вам потрібно визначити, що означають маркери. Це те, для чого призначений генератор парсера. Їх дуже багато. ("Комбінатор парсера", "рекурсивно-спускний" та "ЛАЛР (1)" - це ключові слова для Google.)
jrockway

1
@jrockway: це правда, звичайно, я думаю, що я знизав плечима і подумав, "але якщо він прочитає на Flex, він автоматично знайде Бізона". :) Дякую.
розмотуємо



1

Якщо ви використовуєте мову програмування, яка містить більше трьох інших користувачів, ви повинні мати можливість знайти бібліотеку для її розбору. Швидкий пошук Google розкриває бібліотеки для CL, Haskell, Python, JavaScript, Ruby тощо. Навряд чи вам знадобиться винаходити це колесо.

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


Я готовий до виклику. Я подивився на бібліотеки, але вони просто жахливі. Потворний і дурний. Я розглядаю можливість написання аналізатора на F #, тому що мені потрібен проект F #, але я, мабуть, в кінцевому підсумку робити це на C #.
Джон Лейдегрен

Сподіваємось, у F # є така бібліотека, як Парсек; якщо так, це буде веселий проект;)
jrockway

0

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

Залежно від того, якою мовою ви хочете скористатися, для найкращого втілення в життя є ідіоматичні та неідіоматичні способи це зробити.

Regexes працюють у perl, тому що perl та regex - найкращі друзі.


1
Регекс і перл - найкращі друзі, тому що хтось так сказав. У цьому факту немає більше правди, ніж це історичне походження, що воно було використано таким чином. Я не маю користі для чогось типу perl.
Джон Лейдегрен

7
Тоді не використовуйте його. Також навчіться іронії.
гарро

0

Markdown - це JAWL (просто інша мова вікі)

Вікі з відкритим кодом відкрито для того, щоб ви могли вивчити код аналізатора. Більшість використовують REGEX

Перевірте вікі-винт, чи є цікавий конвертер формату багатопрохідного формату, дуже приємна техніка - див. /Core/Formatter.cs та /core/FormatterPipeline.cs

Найкраще використовувати / приєднуватися до вже існуючого проекту, такі речі завжди набагато складніше, ніж вони з'являються


0

Ось ви можете знайти JavaScript-реалізацію Markdown. Вона також сильно покладається на регулярні вирази, оскільки це лише найшвидший і найпростіший спосіб розбору тексту.

Але він забуває частину MD5.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.