176 lines
5.6 KiB
C#
176 lines
5.6 KiB
C#
// /**
|
|
// * File: Parser.cs
|
|
// * Author: haraldwolff
|
|
// *
|
|
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
|
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
|
// *
|
|
// *
|
|
// **/
|
|
using System;
|
|
using System.IO;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
namespace ln.templates.html
|
|
{
|
|
public class HtmlReader
|
|
{
|
|
public HtmlReader()
|
|
{
|
|
}
|
|
|
|
public void Read(string source) => Read(new StringReader(source));
|
|
public void Read(Stream sourceStream)
|
|
{
|
|
using (StreamReader streamReader = new StreamReader(sourceStream))
|
|
Read(streamReader);
|
|
}
|
|
|
|
public void Read(TextReader textReader)
|
|
{
|
|
while (textReader.Peek() != -1)
|
|
{
|
|
switch (textReader.Peek())
|
|
{
|
|
case '<':
|
|
ReadTag(textReader);
|
|
break;
|
|
default:
|
|
ReadText(textReader);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
public void ReadTag(TextReader textReader)
|
|
{
|
|
if (textReader.Read() != '<')
|
|
throw new FormatException("Expected <");
|
|
|
|
bool closing = false;
|
|
|
|
if (textReader.Peek()=='/')
|
|
{
|
|
textReader.Read();
|
|
closing = true;
|
|
}
|
|
|
|
if (textReader.Peek()=='!')
|
|
{
|
|
textReader.Read();
|
|
string doctype = ReadTagName(textReader);
|
|
if (!doctype.Equals("DOCTYPE"))
|
|
throw new FormatException("Expected DOCTYPE");
|
|
|
|
string type = ReadAttributeName(textReader);
|
|
DOCTYPE(type);
|
|
|
|
if (textReader.Read() != '>')
|
|
throw new FormatException("Expected >");
|
|
|
|
return;
|
|
}
|
|
string tagName = ReadTagName(textReader);
|
|
|
|
if (closing)
|
|
{
|
|
CloseTag(tagName);
|
|
}
|
|
else
|
|
{
|
|
OpenTag(tagName);
|
|
|
|
while (TestChar((char)textReader.Peek(), (ch) => !char.IsWhiteSpace(ch) && (ch != '\0') && (ch != '"') && (ch != '\'') && (ch != '>') && (ch != '/') && (ch != '=')))
|
|
{
|
|
string attributeName = ReadAttributeName(textReader);
|
|
string attributeValue = "";
|
|
if (textReader.Peek() == '=')
|
|
{
|
|
textReader.Read();
|
|
attributeValue = ReadAttributeValue(textReader);
|
|
}
|
|
Attribute(attributeName, attributeValue);
|
|
}
|
|
|
|
if (textReader.Peek()=='/')
|
|
{
|
|
textReader.Read();
|
|
CloseTag(tagName);
|
|
}
|
|
}
|
|
|
|
if (textReader.Read() != '>')
|
|
throw new FormatException("Expected >");
|
|
}
|
|
|
|
bool TestChar(char ch, Func<char, bool> condition) => condition(ch);
|
|
public string ReadToken(TextReader textReader, Func<char, bool> condition, bool clearFinalChar = false)
|
|
{
|
|
StringBuilder characters = new StringBuilder();
|
|
while (condition((char)textReader.Peek()) && textReader.Peek() != -1)
|
|
{
|
|
characters.Append((char)textReader.Read());
|
|
}
|
|
|
|
if ((textReader.Peek() != -1) && clearFinalChar)
|
|
textReader.Read();
|
|
|
|
return characters.ToString();
|
|
}
|
|
public string ReadTokenLWS(TextReader textReader, Func<char, bool> condition,bool clearFinalChar = false)
|
|
{
|
|
string token = ReadToken(textReader, condition, clearFinalChar);
|
|
ReadToken(textReader, char.IsWhiteSpace);
|
|
return token;
|
|
}
|
|
void ReadLWS(TextReader textReader) => ReadToken(textReader, char.IsWhiteSpace);
|
|
|
|
public string ReadTagName(TextReader textReader) => ReadTokenLWS(textReader, (ch) => char.IsLetterOrDigit(ch));
|
|
public string ReadAttributeName(TextReader textReader) => ReadTokenLWS(textReader, (ch) => !char.IsWhiteSpace(ch) && (ch != '\0') && (ch != '"') && (ch != '\'') && (ch != '>') && (ch != '/') && (ch != '='));
|
|
public string ReadAttributeValue(TextReader textReader)
|
|
{
|
|
switch (textReader.Peek())
|
|
{
|
|
case '"':
|
|
textReader.Read();
|
|
return ReadTokenLWS(textReader, (ch) => ch != '"', true);
|
|
case '\'':
|
|
textReader.Read();
|
|
return ReadTokenLWS(textReader, (ch)=> ch != '\'', true);
|
|
default:
|
|
return ReadTokenLWS(textReader, (ch) => !char.IsWhiteSpace(ch) && (ch != '"') && (ch != '\'') && (ch != '<') && (ch != '>') && (ch != '`'));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ReadText(TextReader textReader)
|
|
{
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
while (textReader.Peek() != '<')
|
|
stringBuilder.Append((char)textReader.Read());
|
|
|
|
Text(stringBuilder.ToString());
|
|
}
|
|
|
|
public virtual void DOCTYPE(string type)
|
|
{
|
|
}
|
|
|
|
public virtual void OpenTag(string tagName)
|
|
{
|
|
}
|
|
public virtual void CloseTag(string tagName)
|
|
{
|
|
}
|
|
public virtual void Attribute(string attributeName,string attributeValue)
|
|
{
|
|
}
|
|
public virtual void Text(string text)
|
|
{
|
|
}
|
|
|
|
|
|
}
|
|
}
|