Skip to content

Instantly share code, notes, and snippets.

@LianSheng197
Created October 25, 2023 19:44
Show Gist options
  • Select an option

  • Save LianSheng197/62af1ee6930d289a353993137c4283c6 to your computer and use it in GitHub Desktop.

Select an option

Save LianSheng197/62af1ee6930d289a353993137c4283c6 to your computer and use it in GitHub Desktop.

Revisions

  1. LianSheng197 renamed this gist Oct 25, 2023. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. LianSheng197 created this gist Oct 25, 2023.
    69 changes: 69 additions & 0 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,69 @@
    function lexer(input) {
    const regex = /<\/?(title|h1|html|head|body|p)>|[^<]+/g;
    let result, tokens = [];
    while ((result = regex.exec(input)) !== null) {
    tokens.push(result[0]);
    }
    return tokens;
    }

    function parser(tokens) {
    let current = 0;

    function walk() {
    let token = tokens[current];

    if (token.startsWith("<")) {
    let tag = token.slice(1, -1);
    current++;

    let node = {
    type: 'Element',
    tagName: tag,
    children: [],
    };

    while (!tokens[current].startsWith(`</${tag}>`)) {
    node.children.push(walk());
    }

    current++;
    return node;
    } else {
    current++;
    return {
    type: 'Text',
    value: token,
    };
    }
    }

    let ast = {
    type: 'Document',
    children: [],
    };

    while (current < tokens.length) {
    ast.children.push(walk());
    }

    return ast;
    }

    function parseHTML(input) {
    let tokens = lexer(input);
    return parser(tokens);
    }

    const exampleHTML = `
    <html>
    <head>
    <title>Test</title>
    </head>
    <body>
    <h1>Hello</h1>
    <p>World</p>
    </body>
    </html>`;
    let ast = parseHTML(exampleHTML);
    console.log(JSON.stringify(ast, null, 2));