File size: 4,105 Bytes
3e53e47
 
 
 
 
 
 
 
3ff9ec7
3e53e47
 
 
 
 
 
 
3ff9ec7
3e53e47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Syntax Tree Visualization</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="overflow-scroll bg-gray-50 text-gray-900">
    <div class="container mx-auto mt-10">
        <h1 class="text-4xl font-bold mb-5">Syntax Tree Visualization</h1>
        <form class="mb-5" onsubmit="event.preventDefault(); search();">
            <input id="search-input" type="text" value="Lean" class="w-full p-2 border border-gray-300 rounded-md">
            <button class="mt-2 bg-blue-500 text-white px-4 py-2 rounded-md">Search</button>
        </form>
        <canvas id="tree-canvas" class="mx-auto border border-gray-300 rounded-md"></canvas>
        <div id="results" class="mb-5"></div>
    </div>

    <script>
        async function search() {
            console.log('search');
            const query = document.getElementById('search-input').value;
            const response = await fetch(`/search?query=${query}`);
            const data = await response.json();
            console.log(data);
            
            const resultsDiv = document.getElementById('results');
            resultsDiv.innerHTML = '';

            data.forEach((result, index) => {
                const button = document.createElement('button');
                button.innerText = result.name;
                button.className = 'block w-full text-left p-2 bg-gray-200 my-2 rounded-md';
                if (data[index].ast !== 'expression tree does not exist\n') {
                    data[index].ast = JSON.parse(data[index].ast);
                    console.log(data[index].ast);
                }
                button.onclick = () => visualizeTree(data[index].ast);
                resultsDiv.appendChild(button);
            });
            visualizeTree(data[0].ast);
        }

        const canvas = document.getElementById('tree-canvas');
        const ctx = canvas.getContext('2d');
        ctx.font = '100px Arial';

        canvas.width = Math.floor(window.innerWidth * 0.8) * 2;
        canvas.height = Math.floor(window.innerHeight * 0.8) * 2;
        canvas.style.width = Math.floor(window.innerWidth * 0.8) + 'px';
        canvas.style.height = Math.floor(window.innerHeight * 0.8) + 'px';

        function visualizeTree(tree) {
            ctx.fillStyle = 'white';            
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            const width = drawNode(tree, 10, 10);
            if (width > canvas.width) {
                canvas.width = width;
                canvas.style.width = width / 2 + 'px';
            }
            // draw again
            drawNode(tree, 10, 10);
        }
        
        const sizeX = 60;
        const sizeY = 30;

        function drawNode(node, x, y) {
            // This is recursive. Returns the width of the node.

            // if node is still an object, it is a non-leaf node
            const isLeaf = typeof node !== 'object';
            if (isLeaf) {
                // draw leaf node simply as text
                ctx.fillStyle = 'rgba(256, 0, 0, 0.1)';
                ctx.fillRect(x, y, sizeX, sizeY);

                ctx.fillStyle = 'black';
                ctx.font = '20px Arial';
                ctx.fillText(node, x, y + sizeY);
                return sizeX;
            }
            // draw non-leaf node as a black square
            ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
            ctx.fillRect(x, y, sizeX, sizeY);

            ctx.fillStyle = 'black';
            ctx.font = '20px Arial';
            ctx.fillText(node.kind, x, y + sizeY);

            // draw children
            const childY = y + sizeY;
            let childX = x;
            let totalWidth = 0;
            node.children.forEach((child, index) => {
                let width = drawNode(child, childX, childY);
                childX += width;
                totalWidth += width;
            });
            return totalWidth;
        }
    </script>
</body>
</html>