Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

1

16.06.2016, 22:19

HTML zu Markdown Compiler, Leerzeichen zwischen Strings und Elementen einfügen

Moin,

ich bastel gerade einen HTML <-> Markdown Compiler (in beide Richtungen). Dabei bin ich jetzt auf ein Problem von HTML -> Md gestoßen für das mir gerade keine Lösung einfällt. Und zwar zerlege ich die Eingabe in Tokens, Beispiel:

Quellcode

1
2
Hello <e>World</e>!
Hello <e>happy</e> World!


Wird zu (kommasepariert, whitespace um strings und Zeilenumbrüche werden entfernt):

Quellcode

1
2
Hello,<,e,>,World,<,/,e,>,!,
Hello,<,e,>,happy,<,/,e,>,World!


Wie ihr seht steht hier in der ersten Zeile das ! allein, in der zweiten nicht.
Problem: wie füge ich jetzt entsprechend Leerzeichen ein, so dass dort folgendes herauskommt:

Quellcode

1
2
Hello *World*!
Hello *happy* World!


Ich kann weder für <e... noch für </e... einfach ein Leerzeichen einfügen, dann hätte das ! eines welches dort nicht hingehört. Nur für eines der beiden einfügen geht auch nicht, dann würde das "happy" links oder rechts mit am Wort kleben.
Fällt jemanden von euch eine Möglichkeit ein hier richtig zu unterscheiden?

Das ganze Ding gibt es auf GitHub. Relevant ist vor allem die ParseBlock() Funktion in der compiler Datei. An den Tokens kann ich auch erkennen ob es sich um ein Element oder um einen string handelt, falls das irgendwie hilft hier (wird für den tokenizer sowieso benötigt). Unter test findet ihr die Dateien mit denen ich teste. Alle Go Dateien mit _test.go am Ende sind Unit Tests.

Ich baue das ganze weil ich nichts finden konnte was beide Richtungen kann, ich Spaß daran habe und weil ich einen modularen Parser brauche (um mit speziellen Elementen erweitern zu können, für die Plattform die ich schon mal im offtopic gezeigt habe).

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

2

16.06.2016, 22:40

Ist World! ein zusammenhängendes Token? Oder sind das später zwei, einmal der Bezeichner/das Wort World und einmal !?
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

3

16.06.2016, 22:43

Wenn ein Element, also <irgendwas> oder <irgendwas /> oder </irgendwas>, dazwischen ist sind es zwei, sonst eins. Im tokenizer siehst du oben alle Delimiter. Bei der aktuellen (falschen) Lösung sieht es entweder so:

Hello World !

oder so

Hellohappy World!

oder so

Hello happyWorld!

aus. Ich will aber beide Fälle können.

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

4

16.06.2016, 22:47

Wären es immer zwei wäre es einfacher. Wenn alles von [a-zA-Z] ein Token ist und alle anderen Zeichen separate Token hast du eine optimale (und semantisch korrekte) Trennung und (soweit ich das sehe) würde das dein Problem lösen.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

5

16.06.2016, 22:48

Verstehe ich nicht ganz. Ich will ja kein Leerzeichen zwischen "Wort" und "!" haben, aber zwischen "Wort" und "weiteres Wort" schon.

Edit

Ja doch ich glaub ich habs gerade verstanden. Du willst also quasi in "Wort", "noch eins", "!" zerlegen und semantisch zwischen Worten und Sonderzeichen unterscheiden? Das könnte schwierig werden wenn man z.B. sowas hat: "P!nk" und daraus "P! ink" wird.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »DeKugelschieber« (16.06.2016, 22:55)


Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

6

16.06.2016, 22:56

Ich stelle mir die optimalen Lexeme wie folgt vor:
Hello <e>World</e>!
produziert den folgenden Token-Stream:
[Token::Identifier("Hello"), Token::OpenTag('e'), Token::Identifier("World"), Token::CloseTag('e'), Token::Mark('!')]

und

Hello <e>happy</e> World!
diesen
[Token::Identifier("Hello"), Token::OpenTag('e'), Token::Identifier("happy"), Token::CloseTag('e'), Token::Identifier("World"), Token::Mark('!')]

Dann kannst du Open- und CloseTags sowie deren dazwischenliegenden Token im nächsten Schritt als Expressions zusammenfassen und somit validieren und dann entsprechend ersetzen.

edit: Wobei dass dein eigentliches Problem nicht löst. Bin echt durch heute.. Du willst ja eig. die vorherigen Leerzeichen so wieder herstellen wie sie waren. Also wäre es das passendste wenn du die nicht filterst sondern so bei behältst (also auch als eigenes Token).

edit2:

Zitat

Ja doch ich glaub ich habs gerade verstanden. Du willst also quasi in "Wort", "noch eins", "!" zerlegen und semantisch zwischen Worten und Sonderzeichen unterscheiden? Das könnte schwierig werden wenn man z.B. sowas hat: "P!nk" und daraus "P! ink" wird.

Genau, siehe meinen ersten edit. Das wäre IMO das einfachste.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

7

16.06.2016, 23:04

Nicht unbedingt wieder herstellen, da ich dem HTML Code nicht wirklich vertraue(n kann). Zwar muss ich natürlich ein paar Grundannahmen machen und dann auch "falsch" parsen wenn man Quatsch reinwirft, aber whitespaces beizubehalten... hmm. Ich glaube ich habs vor ein paar Tagen wegen irgend einem anderen Problem rausgenommen. Muss ich mal testen.

Compiler für Programmiersprachen sind einfacher, da ist nicht alles so "weich" :D

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

8

16.06.2016, 23:08

Leerzeichen außerhalb von Tags sollten Ok sein. Tabs oder anderweitig multiple nacheinander auftretende Leerzeichen könntest du ja in einen Leerzeichen zusammenfassen.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

9

16.06.2016, 23:23

Ja aber was mache ich mit sowas: Hello <b>happy</b>World!
Jeder Browser bekommt das hin. Aber wie?

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

10

16.06.2016, 23:52

Was ist damit? Das produziert die Ausgabe: Hello happyWorld!
Daraus würde folgender Token-Stream resultieren: [Token::Identifier("Hello"), Token::Space, Token::OpenTag('b'), Token::Identifier("happy"), Token::CloseTag('b'), Token::Identifier("World!")] und damit folgender Markdown: Hello **happy**World!
Wenn du darauf hinaus willst, dass da kein Leerzeichen vor World! ist, dann könntest du einfach vor jedem Token::Identifier ein Token::Space inserten, sofern keines da ist.

edit: Btw.: einfacher (aber möglicherweise nicht effizienter) ginge es per RegEx (hier in PHP):

Quellcode

1
2
$str = 'Hello <b>happy</b>World!';
print preg_replace('#<b>(.+?)<\/b>#i', '**\1**', $str);

Für den allgemeinen Fall könntest du dir eine Ersetzungstabelle der Form ['b' => '**', ...] anlegen und dann einfach mit einem solchen Pattern loslegen: <([a-z]+)>(.+?)<\/\1>
Hier mal dargestellt: https://regex101.com/r/kZ4sG4/1
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Architekt« (16.06.2016, 23:59)


Werbeanzeige