Wie würden Sie Markdown analysieren? [geschlossen]


126

Bearbeiten: Ich habe kürzlich von einem Projekt namens CommonMark erfahren, das die Mehrdeutigkeiten in der ursprünglichen Markdown-Spezifikation korrekt identifiziert und behandelt. http://commonmark.org/ Es bietet hervorragende Unterstützung für die C # -Bibliothek.

Die Syntax finden Sie hier .

Die Quelle, die mit dem Download folgt, ist in Perl geschrieben , was ich nicht zu ehren beabsichtige. Es ist voller regulärer Ausdrücke und basiert auf MD5- Hashes, um bestimmten Zeichen zu entkommen. Daran stimmt einfach etwas nicht!

Ich bin dabei, einen Parser für Markdown hart zu codieren . Was ist Erfahrung damit?

Wenn Sie nichts Sinnvolles über das eigentliche Parsen von Markdown zu sagen haben, sparen Sie mir die Zeit. (Das mag hart klingen, aber ja, ich suche nach Einsicht, nicht nach einer Lösung, dh nach einer Bibliothek eines Drittanbieters.)

Um ein bisschen bei den Antworten zu helfen, sollen reguläre Ausdrücke Muster identifizieren ! NICHT eine ganze Grammatik zu analysieren. Dass die Leute dies in Betracht ziehen, ist foobar.

  • Wenn Sie an Markdown denken, basiert es im Wesentlichen auf dem Konzept der Absätze.
  • Daher könnte ein vernünftiger Ansatz darin bestehen, die Eingabe in Absätze aufzuteilen.
  • Es gibt viele Arten von Absätzen, z. B. Überschrift, Text, Liste, Blockzitat und Code.
  • Die Herausforderung besteht daher darin, diese Absätze zu identifizieren und in welchem ​​Kontext sie auftreten.

Ich werde mit einer Lösung zurück sein, sobald ich finde, dass es sich lohnt, geteilt zu werden.


2
@cletus schreibt einen Markdown-Parser, siehe cforcoding.com/search/label/markdown
Alex Angas

Am Ende habe ich das Gleiche getan. Ich versuche jedoch nicht, Markdown so zu analysieren, als wäre es eine formale Grammatik, weil dies eindeutig nicht der Fall ist. Ich habe verschiedene reguläre Ausdrücke rekursiv angewendet. Und in mehreren Durchgängen. Das hat sehr gut geklappt.
John Leidegren

@ JohnLeidegren, gibt es eine Chance, dass andere neugierige Benutzer wie ich Ihren Versuch sehen, Markdown zu analysieren?
Jmlopez

@jmlopez Entschuldigung, ich habe keinen Zugriff mehr auf diese Quelle. Wenn Sie einen Markdown-Parser benötigen, steht ein NuGet-Paket zur Verfügung, das verwendet werden kann. Die Idee ist jedoch einfach genug. Wenden Sie einfach eine Reihe von regulären Ausdrücken in Durchgängen an, beginnen Sie mit der Paritionierung der Eingabe in Absätzen und versuchen Sie dann zu identifizieren, um welche Art von Absatz es sich handelt, und so weiter. Analysieren Sie abschließend Links und Zeichenstile in den Absätzen.
John Leidegren

2
Sie sollten sich Parsedown ansehen . Es teilt Text in Zeilen auf. Dann wird untersucht, wie diese Linien beginnen und sich aufeinander beziehen.
Emanuil Rusev

Antworten:


69

Der einzige Abschlag Implementierung ich kenne, die einen tatsächlichen Parser verwendet, ist Jon MacFarleane ‚s peg-Abschlag . Sein Parser basiert auf einem Parser-Generator der Parsing Expression Grammar namens peg .


EDIT: Mauricio Fernandez hat kürzlich seinen Simple Markup Markdown Parser veröffentlicht , den er als Teil seiner OcsiBlog Weblog Engine geschrieben hat. Da der Parser in geschrieben OCaml , ist es extrem einfach und kurz (268 SLOC für den Parser , 43 SLOC für die HTML - Emitter ), noch blazingly schnell (20% schneller als Rabatt (geschrieben in der Hand optimierte C) und sixhundred mal schneller als BlueCloth ( Ruby)), obwohl es noch nicht einmal für die Leistung optimiert ist. Da es nur für den internen Gebrauch durch Mauricio selbst für sein Weblog vorgesehen ist, gibt es einige Abweichungen von der offiziellen Markdown-Spezifikation , aber Mauricio hat einen Zweig erstellt, der die meisten dieser Änderungen rückgängig macht .


1
interessant. Vielleicht werde ich versuchen, das als f # -Projekt zu
konvertieren

@ Benjol Gleiche alte Geschichte: keine Zeit: /
ShuggyCoUk

1
Terrence Parr (Co-Autor von ANTLR) hat einen für ANTLR 4 geschrieben: github.com/parrt/mini-markdown
Chris S

17

Ich habe letzte Woche eine neue parserbasierte Markdown Java-Implementierung namens pegdown veröffentlicht . pegdown verwendet einen PEG-Parser, um zunächst einen abstrakten Syntaxbaum zu erstellen, der anschließend in HTML geschrieben wird. Als solches ist es ziemlich sauber und viel einfacher zu lesen, zu warten und zu erweitern als ein auf Regex basierender Ansatz. Die PEG-Grammatik basiert auf der Implementierung "peg-markdown" von John MacFarlanes C.

Vielleicht etwas, das Sie interessiert ...


1
Dies ist jetzt offiziell veraltet
Fabich

7

Wenn ich versuchen würde, Markdown (und seine Erweiterung Markdown extra ) zu analysieren , würde ich versuchen, eine Zustandsmaschine zu verwenden und jeweils ein Zeichen zu analysieren, indem ich einige interne Strukturen, die Textbits darstellen, einmal miteinander verknüpfe Alles wird analysiert, wodurch die Ausgabe der Objekte generiert wird, die alle aneinandergereiht sind.

Grundsätzlich würde ich beim Lesen der Eingabedatei einen Mini-DOM-ähnlichen Baum erstellen.
Um eine Ausgabe zu generieren, würde ich einfach den Baum durchlaufen und HTML oder etwas anderes ausgeben (PS, LaTex, RTF, ...)

Dinge, die die Komplexität erhöhen können:

  • Die Tatsache, dass Sie HTML und Markdown mischen können, obwohl die Regel leicht zu implementieren sein könnte: Ignorieren Sie einfach alles, was zwischen zwei ausgeglichenen Tags liegt, und geben Sie es wörtlich aus.

  • URLs und Notizen können am Ende des Textes referenziert werden. Die Verwendung von Datenstrukturen für Hyperlinks könnte einfach Folgendes aufzeichnen:

    [my text to a link][linkkey]
    results in a structure like: 
        URLStructure: 
        |  InnerText : "my text to a link"
        |  Key       : "linkkey"
        |  URL       : <null>
    
  • Überschriften können mit einer Unterstreichung definiert werden, die uns zwingen könnte, eine einfache Datenstruktur für einen generischen Absatz zu verwenden und seine Eigenschaften beim Lesen der Datei zu ändern:

    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.
    

Wie auch immer, nur ein paar Gedanken.

Ich bin mir sicher, dass es viele kleine Details gibt, um die man sich kümmern muss, und ich bin mir ziemlich sicher, dass Regexes während des Prozesses nützlich sein könnten.
Schließlich sollten sie Text verarbeiten.


3

Ich würde die Syntaxspezifikation wahrscheinlich oft genug lesen, um sie zu kennen und ein Gefühl dafür zu bekommen, wie man sie analysiert.

Das Lesen des vorhandenen Parser-Codes ist natürlich brillant, sowohl um zu sehen, was die Hauptursache für Komplexität zu sein scheint, als auch um spezielle clevere Tricks zu verwenden. Die Verwendung von MD5-Prüfsummen scheint etwas seltsam, aber ich habe den Code nicht genug studiert, um zu verstehen, warum er ausgeführt wird. Ein Kommentar in einer Routine namens _EscapeSpecialChars()Staaten:

Wir ersetzen jedes dieser Zeichen durch den entsprechenden MD5-Prüfsummenwert. Dies ist wahrscheinlich übertrieben, sollte aber verhindern, dass wir versehentlich mit den Fluchtwerten kollidieren.

Das Ersetzen eines einzelnen Zeichens durch ein vollständiges MD5 scheint extravagant, ist aber vielleicht wirklich sinnvoll.

Natürlich wäre es klug, eine "echte" Syntax zu erstellen, damit ein Tool wie Flex aus dem Regex-Sumpf herauskommt.


Das MD5-Ding stört mich immer noch, auch die übermäßige Manipulation von Strings muss langsamer sein als jeder anständige Parser, den Sie selbst schreiben könnten.
John Leidegren

2
Flex ist wirklich nur die Hälfte des Parsers; Sobald Sie die Eingabe getoken haben, müssen Sie bestimmen, was die Token bedeuten. Dafür ist ein Parser-Generator gedacht. Es gibt viele von ihnen. ("Parser Combinator", "Recursive-Descent" und "LALR (1)" sind Schlüsselwörter für Google.)
Jrockway

1
@jrockway: das stimmt natürlich, ich schätze ich zuckte die Achseln und dachte "aber wenn er sich über Flex liest, wird er Bison automatisch finden". :) Vielen Dank.
Entspannen Sie am

2

Wenn Perl nicht Ihr Ding ist, gibt es Markdown-Implementierungen in mindestens 10 anderen Sprachen . Sie sind wahrscheinlich nicht alle zu 100% kompatibel, liegen aber eher nahe beieinander.



1

Wenn Sie eine Programmiersprache verwenden, die mehr als drei andere Benutzer hat, sollten Sie in der Lage sein, eine Bibliothek zu finden, um sie für Sie zu analysieren. Ein schnelles Google-ing enthüllt Bibliotheken für CL, Haskell, Python, JavaScript, Ruby und so weiter. Es ist sehr unwahrscheinlich, dass Sie dieses Rad neu erfinden müssen.

Wenn Sie es wirklich von Grund auf neu schreiben müssen, empfehle ich, einen geeigneten Parser zu schreiben. Mit dieser Technik müssen Sie mit MD5-Hashes nicht entkommen. (Ich bin damit einverstanden, dass es Zeit ist, Ihr Design zu überdenken, wenn Sie so etwas tun müssen.)


Ich bin bereit für die Herausforderung. Ich habe mir Bibliotheken angesehen, aber sie sind einfach schrecklich. Hässlich und dumm. Ich denke darüber nach, den Parser in F # zu schreiben, weil ich ein F # -Projekt brauche, aber ich werde es wahrscheinlich in C # tun.
John Leidegren

Hoffentlich hat F # eine Bibliothek wie Parsec; Wenn ja, wird dies ein lustiges Projekt sein;)
Jrockway

0

Es gibt Bibliotheken in einer Reihe von Sprachen, einschließlich PHP, Ruby, Java, C #, Javascript. Ich würde vorschlagen, einige davon nach Ideen zu durchsuchen.

Es hängt davon ab, welche Sprache Sie verwenden möchten. Für die beste Implementierung gibt es idiomatische und nicht idiomatische Möglichkeiten.

Regexes funktionieren in Perl, weil Perl und Regex beste Freunde sind.


1
Regex und Perl sind beste Freunde, weil es jemand gesagt hat. Diese Tatsache ist nicht wahrer als ihre historische Abstammung, dass sie so verwendet wurde. Ich habe keine Verwendung für so etwas wie Perl.
John Leidegren

7
Dann benutze es nicht. Lerne auch Ironie.
Garrow

0

Markdown ist eine JAWL (nur eine andere Wiki-Sprache)

Es gibt viele Open-Source-Wikis, in denen Sie den Code des Parsers überprüfen können. Die meisten verwenden REGEX

Schauen Sie sich das Screwturn-Wiki an, es hat eine interessante Multi-Pass-Formatierer-Pipeline, eine sehr schöne Technik - siehe /core/Formatter.cs und /core/FormatterPipeline.cs

Am besten ist es, ein bestehendes Projekt zu verwenden / daran teilzunehmen. Diese Art von Dingen ist immer viel schwieriger als sie erscheinen


0

Hier finden Sie eine JavaScript-Implementierung von Markdown. Es stützt sich auch stark auf reguläre Ausdrücke, da dies nur der schnellste und einfachste Weg ist, den Text zu analysieren.

Aber es schont den MD5-Teil.

Ich kann nicht direkt bei der Codierung der Analyse helfen, aber vielleicht kann dieser Link Ihnen auf die eine oder andere Weise helfen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.