Html-Code Parser und Renderer
- Beta
- Open Source
Sie verwenden einen veralteten Browser (%browser%) mit Sicherheitsschwachstellen und können nicht alle Funktionen dieser Webseite nutzen.
Hier erfahren Sie, wie einfach Sie Ihren Browser aktualisieren können.
Hier erfahren Sie, wie einfach Sie Ihren Browser aktualisieren können.
Es gibt 41 Antworten in diesem Thema. Der letzte Beitrag () ist von nikeee13.
-
-
-
Der Lexer geht erstmal durch den ganzen Code durch und filtert sogenannte Tokens raus, also z.B. /, <, >, =,keyword,text,number. Diese schiebt er in eine Liste, oder ggf.auch natürlich über yield(nicht die beste performance), was automatisch eine StateMachine erzeugt und lexer werden häufig als StateMachine implementiert, das ganze selbst als StateMachine(oder auch auf andere Art, gibt ein paar Möglichkeiten) zu implementieren ist natürlich performanter, aber die Syntax ist denke ich ganz nett über eine Coroutine...
Und diese Tokens werden anschließend erst von dem parser durchgegangen und analysiert, erst dann findet also tatsächliche Syntax Analyse und DOM aufbau statt. Das ganze logisch auf diese Art zu trennen vereinfacht die logische Strukturierung, die Erweiterbarkeit(neuer HTML Standard z.B. muss eben nicht alles neu gemacht werden) und die Fehlererkennung(und Ignorierung) dürfte auch vereinfacht werden.
Das ist auch die Standardherangehensweise für die meisten Parser und Compiler. Ob dies für HTML genauso gilt wie für sonstige Sprachen kann ich dir nicht sicher sagen(weiß nicht was die Browser machen), aber ich denke es ist trotzdem sinnvoll und gehe zumindest davon aus, dass es für HTML gilt wie für alles andere halt auch^^Ich wollte auch mal ne total überflüssige Signatur:
---Leer--- -
jvbsl schrieb:
und die Fehlererkennung(und Ignorierung)
Kannst du das konkretisieren? Wie sähe das im Bezug auf HTML aus? Mir fiele da nur das Fehlen der End-Tags ein.
Lieben Dank.Und Gott alleine weiß alles am allerbesten und besser. -
-
Also die obige Implementierung hat keine Probleme mit dem Fehlen von End-Tags:
Wird erfolgreich geparst:
Vergleich das mal mit Webkit: Ist fast identisch.
jvbsl schrieb:
oder endtag ohne starttag bei Anführungszeichen
Beispiel?
jvbsl schrieb:
oder natürlich >< ohne Bedeutung
Beispiel?
Lieben Dank.Und Gott alleine weiß alles am allerbesten und besser.Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „φConst“ ()
-
Ich wollte auch mal ne total überflüssige Signatur:
---Leer--- -
-
eigt. meinte ich title statt head aber sonst prinzipiell schon. Und waren nur Dinge die mir eingefallen sind, wie die dann von jeweiligen Engines geparst werden bzw. was die "richtige" Herangehensweise ist: Keine Ahnung - schließlich ist die Syntax ansich einfach nur falsch^^Ich wollte auch mal ne total überflüssige Signatur:
---Leer--- -
Hier mal ein Tokenizer:
Spoiler anzeigen C#-Quellcode
- public class HtmlTokenizer
- {
- public StringBuilder RawHtmlSource { get; private set; }
- public List<Token> Tokens { get; private set; }
- public HtmlTokenizer(string rawHtmlSrc)
- {
- RawHtmlSource = new StringBuilder("<html>" + rawHtmlSrc + "</html>;");
- Tokens = new List<Token>();
- }
- public void Tokenize()
- {
- bool possibleTagFound = false;
- bool foundString = false;
- bool letterFound = true;
- bool endFound = false;
- Token currentToken = new Token();
- for (int i = 0; i < RawHtmlSource.Length - 1; i++)
- {
- char c = RawHtmlSource[i];
- char c1 = RawHtmlSource[i + 1];
- if (c == '"')
- foundString = !foundString;
- switch (possibleTagFound)
- {
- case true:
- currentToken.Content.Append(c);
- if (!foundString && c == '/')
- endFound = true;
- if (!foundString && char.IsLetter(c))
- letterFound = true;
- if (endFound && c == '>' && letterFound)
- currentToken.Type = Token.TokenType.EndTag;
- else if (!endFound && !foundString && letterFound && c == '>')
- currentToken.Type = Token.TokenType.BeginTag;
- if (currentToken.Type == Token.TokenType.Content || currentToken.Type == Token.TokenType.Default)
- continue;
- Tokens.Add(currentToken);
- currentToken = new Token()
- {
- Type = Token.TokenType.Content
- };
- possibleTagFound = false;
- letterFound = false;
- endFound = false;
- break;
- case false:
- currentToken.Content.Append(c);
- if (!foundString && c == '<')
- {
- if (c1 != '/' && !char.IsLetter(c1))
- continue;
- if (currentToken.Type == Token.TokenType.Content && (char.IsLetter(c1) || c1 == '/') && currentToken.Content.Length > 0)
- {
- currentToken.Content.Remove(currentToken.Content.Length - 1, 1);
- if (currentToken.Content.Length > 0)
- Tokens.Add(currentToken);
- currentToken = new Token();
- currentToken.Content.Append("<");
- }
- possibleTagFound = true;
- }
- break;
- }
- }
- if (currentToken.Content.Length > 0)
- Tokens.Add(currentToken);
- }
- }
Aufruf:
C#-Quellcode
Ergebnis:
In der Tat ist das sehr hilfreich.
So können im Quelltext auch Sonderzeichen stehen..
Dein Beispiel ergibt folgende Anordnung:
Das deckt sich mit Google Chrome:
Beachte das der Tokenizer auch "bla<><<" als Content kennzeichnet.
_Und Gott alleine weiß alles am allerbesten und besser.Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „φConst“ ()
-
Ich kenns zwar eher so, dass der lexer wirklich noch nichts HTML spezifisches großartig erkennt und das eher der Parser macht, also so in diese Richtung:
codereview.stackexchange.com/q…ml-xhtml-xml-tokenization
es werden nur <,>, /, = und ähnliches als tokens erkannt.
Aber ansonsten schon ganz nette Arbeit.Ich wollte auch mal ne total überflüssige Signatur:
---Leer--- -
-
deins ist immernoch ein Tokenizer(Lexer), der aber schon Dinge macht, die man meist gerne dem Parser überlässt.
Wie gesagt falsch ists nicht.
Nur ist der Lexer/Tokenizer meist wirklich sehr einfach und allein am Tokenizer erkennt man nicht unbedingt die Sprache.
Auch ein C Tokenizer hätte <, >, ", / als Tokens, zwar mit einer anderen Bedeutung, aber das würde dann vom Parser interpretiert werdenIch wollte auch mal ne total überflüssige Signatur:
---Leer--- -
-
-
Mir fiele ein wo man parallelisieren könnte:
Die Token-Klasse besteht aus
TokenTyp und Content.
Um additionale Informationen wie Tag-Name, Tag-Attribute und ähnliches zu extrahieren, könnte man eine Methode .ProcessToken(), im neuen Thread ausführen, die eben
den Tag prozessiert.
_Und Gott alleine weiß alles am allerbesten und besser. -
Ee gibt halt trotzdem token, die von zwei zeichen abhängig sind. Das könnte mit threading probleme machen. Für js z.b. == ist nicht dasselbe wie = =
Also was man eher parallelisiert sind unterschiedliche Dokumente. Z.b. die ganzen css und js...Ich wollte auch mal ne total überflüssige Signatur:
---Leer--- -
Hier mal ein Tokenizer + DOM-Repräsentation:
Tokenizer.zip
Funktioniert eigentlich_souverän.
ergibt:
p
__->_LOL
_____p
______->rofl
_____html
_________->TEST!<>><<<>>><<<
_Und Gott alleine weiß alles am allerbesten und besser. -
Durch die Methode
Spoiler anzeigen C#-Quellcode
- public void Analyze()
- {
- Dictionary<string, int> knownTags = new Dictionary<string, int>();
- Token endToken = null;
- for (int i = 0; i < Tokens.Count; i++)
- {
- Token currentToken = Tokens[i];
- if (currentToken.Type == Token.TokenType.Content || currentToken.Type == Token.TokenType.Default) continue;
- string name = currentToken.HtmlData.Name;
- switch (currentToken.Type)
- {
- case Token.TokenType.BeginTag:
- if (endToken != null)
- {
- Tokens.Insert(i, endToken);
- endToken = null;
- continue;
- }
- if (Declarations.UniqueTags.Contains(name))
- {
- endToken = new Token()
- {
- Type = Token.TokenType.EndTag,
- Content = new StringBuilder("</" + name + ">;"),
- HtmlData = new HtmlData(endToken)
- {
- NameBuilder = new StringBuilder(name)
- }
- };
- continue;
- }
- else if (!knownTags.ContainsKey(name))
- knownTags.Add(name, 1);
- else knownTags[name]++;
- break;
- case Token.TokenType.EndTag:
- if (endToken != null)
- if (name.Equals(endToken.HtmlData.Name))
- endToken = null;
- if (endToken != null)
- {
- Tokens.Insert(i, endToken);
- endToken = null;
- continue;
- }
- if (!knownTags.ContainsKey(name))
- {
- Tokens.RemoveAt(i);
- i--;
- continue;
- }
- if (knownTags[name] <= 0)
- {
- Tokens.RemoveAt(i);
- i--;
- }
- knownTags[name]--;
- break;
- }
- }
- }
werden nun überflüssige Tags entfernt und einige End-Tags automatisch gesetzt.
Die Eingabe
ergibt die Ausgabe:
[BEGIN]html
[BEGIN]div
[BEGIN]div
[BEGIN]p
[CONTENT]hallo
[END]p
[END]div
[END]div
[END]html
_Und Gott alleine weiß alles am allerbesten und besser. -
-1-
Die HTML-Dokumente werden nun in zwei Schritten analysiert:
Zunächst wird es in die korrespondierenden Komponenten zerlegt (id est: Start/End/Special-Tag, Content) und abschließend als DOM repräsentiert.
Funktioniert_relativ schnell und solide.
Git ist aktualisiert.
Der Tokenizer unter "Analysis"-Namespace zu finden: github.com/NET-D3v3l0p3r/HTMLR…LRenderer/Parser/Analysis
_Und Gott alleine weiß alles am allerbesten und besser.
-
Benutzer online 2
2 Besucher
-
Ähnliche Themen
-
FinnSoft - - Sonstige Problemstellungen
-
7 Benutzer haben hier geschrieben
- φConst (26)
- jvbsl (10)
- xChRoNiKx (2)
- Snickbrack (1)
- NoIde (1)
- nikeee13 (1)
- Marcel1997 (1)