/g,">"),r+=`${o}`):"whitespace"===e?r+=n:"error"===e?(o=n.replace(//g,">"),r+=`${o}`):(o=n.replace(//g,">"),r+=o)}!r.trim()&&e.trim()?(t=e.replace(//g,">"),r=`${t}`):r.trim()||e.trim()||(r="/* Code visualization will appear here */"),a.innerHTML=r}function h(e){if(g.selectAll("*").remove(),c.textContent="",e&&e.name){"TranslationUnit"!==e.name||e.children&&0!==e.children.length||(c.textContent="Input parsed as empty or contains only comments/whitespace.");var r=50
e.y).y(e=>e.x)),t.selectAll(".node").data(r.descendants()).enter().append("g").attr("class",e=>"node"+(e.children?" node--internal":" node--leaf")).attr("transform",e=>`translate(${e.y},${e.x})`)),e=(o.append("circle").attr("r",5).attr("fill",e=>(e=e.data.name)?(e=String(e).toLowerCase()).startsWith("func:")?"var(--ast-color-function)":e.startsWith("for")||e.startsWith("while")||e.startsWith("do")?"var(--ast-color-loop)":e.startsWith("if")||e.startsWith("switch")?"var(--ast-color-conditional)":e.startsWith("declare")||e.startsWith("declaration")||e.startsWith("param:")?"var(--ast-color-declaration)":e.startsWith("id:")?"var(--ast-color-identifier)":e.startsWith("const:")||e.startsWith("stringliteral")||e.startsWith("characterliteral")?"var(--ast-color-literal)":e.startsWith("op:")||e.includes("expression")?"var(--ast-color-operator)":e.startsWith("call:")?"var(--ast-color-call)":e.startsWith("return")?"var(--ast-color-return)":e.includes("struct")||e.includes("union")?"var(--ast-color-struct-union)":e.includes("type")?"var(--ast-color-type)":"var(--ast-color-default)":"var(--ast-color-default)"),o.append("text").attr("dy",".35em").attr("x",e=>e.children?-12:12).style("text-anchor",e=>e.children?"end":"start").text(e=>e.data.name),d3.zoom().scaleExtent([.3,5]).on("zoom",e=>{t.attr("transform",e.transform)}));g.call(e).on("dblclick.zoom",null)}else c.textContent="No AST data to display."}function y(e,t,r){t=new Blob([t],{type:r}),r=URL.createObjectURL(t),t=document.createElement("a");t.href=r,t.download=e,document.body.appendChild(t),t.click(),document.body.removeChild(t),URL.revokeObjectURL(r)}function f(o){if(l.disabled=!0,s.disabled=!0,i=null,"undefined"==typeof cparse){c.textContent="Error: cparse.js library not found. Cannot generate AST.",c.style.color="red";try{m(o),n.textContent="Tokenized code, but AST generation failed (cparse.js missing)."}catch(e){console.error("Tokenization Error:",e),n.textContent="Error during tokenization.",a.innerHTML=`Error processing code: ${e.message}`}}else n.textContent="Processing...",c.textContent="Parsing code with cparse.js...",g.selectAll("*").remove(),setTimeout(()=>{let e=null,t=null,r=null;try{m(o);try{e=cparse(o),i=e,console.log("CPARSE Raw AST:",e),c.textContent="Transforming AST for visualization..."}catch(e){console.error("CPARSE Parsing Error:",e),r=e,c.textContent="Parser Error: "+e.message,c.style.color="red",i=null}if(e&&!r)try{t=(t=function t(e){if(!e||"object"!=typeof e)return{name:String(e)};let r=e.type||"Node",o=[];for(var n in"Identifier"===e.type?r="ID: "+e.name:"Constant"===e.type?r="Const: "+e.value:"BinaryExpression"===e.type?r="Op: "+e.operator:"UnaryExpression"===e.type?r=`Op: ${e.operator} (unary)`:"FunctionDefinition"===e.type?r="Func: "+(e.declarator?.declarator?.name||"unnamed"):"Declaration"===e.type?r="Declare":"IfStatement"===e.type?r="if":"ForStatement"===e.type?r="for":"WhileStatement"===e.type?r="while":"ReturnStatement"===e.type?r="return":"CallExpression"===e.type&&(r="Call: "+(e.callee?.name||"?")),e)"type"!==n&&"loc"!==n&&e.hasOwnProperty(n)&&(n=e[n],Array.isArray(n)?n.forEach(e=>{(e=t(e))&&o.push(e)}):n&&"object"==typeof n&&(n=t(n))&&o.push(n));return"Node"===r&&0===o.length&&Object.keys(e).length<=2?null:{name:r,children:0Error: ${e.message}`,c.textContent="An unexpected error occurred.",c.style.color="red",g.selectAll("*").remove(),i=null,l.disabled=!0,s.disabled=!0}setTimeout(()=>{"Code visualized."===n.textContent&&(n.textContent=""),"AST rendered successfully."===c.textContent&&(c.textContent="")},4e3)},50)}l.addEventListener("click",function(){if(i)try{y("ast.json",JSON.stringify(i,null,2),"application/json")}catch(e){console.error("Error creating JSON for download:",e),alert("Failed to generate JSON data for download.")}else alert("No AST data available to download.")}),s.addEventListener("click",function(){let d=g.node();if(d&&d.childNodes.length&&!g.select("g").empty())try{var e=d.cloneNode(!0),t=d3.select(e);let l=window.getComputedStyle(d);var r=window.getComputedStyle(p);let o=l.getPropertyValue("--ast-link-stroke").trim(),s=l.getPropertyValue("--ast-text-color").trim(),i=l.getPropertyValue("--ast-node-stroke").trim();var n=r.getPropertyValue("--ast-bg").trim()||"#ffffff",a=(t.selectAll(".node").each(function(){var t=d3.select(this),r=t.select("circle"),e=t.select("text");if(!r.empty()){var o=r.attr("fill");let e=l.getPropertyValue("--ast-color-default").trim();o&&o.startsWith("var(")?(a=o.match(/--[\w-]+/))&&a[0]&&((n=l.getPropertyValue(a[0]).trim())?e=n:console.warn(`CSS variable ${a[0]} did not resolve.`)):o&&(e=o);var n=document.querySelector(`#${d.id} g[transform="${t.attr("transform")}"] circle`),a=(n?window.getComputedStyle(n):l).getPropertyValue("stroke-width");r.attr("style",`fill: ${e}; stroke: ${i}; stroke-width: ${a||"1px"};`),r.attr("fill",null)}e.empty()||(a=(n=(o=document.querySelector(`#${d.id} g[transform="${t.attr("transform")}"] text`))?window.getComputedStyle(o):l).getPropertyValue("font-family")||"sans-serif",r=n.getPropertyValue("font-size")||"10px",t=n.getPropertyValue("text-anchor")||"start",e.attr("style",`fill: ${s}; font-family: ${a}; font-size: ${r}; text-anchor: ${t};`))}),t.selectAll(".link").each(function(){var e=d3.select(this),t=document.querySelector(`#${d.id} path[d="${e.attr("d")}"]`),t=t?window.getComputedStyle(t):l,r=t.getPropertyValue("stroke-width")||"1.5px",t=t.getPropertyValue("stroke-opacity")||"0.6";e.attr("style",`stroke: ${o}; stroke-width: ${r}; stroke-opacity: ${t}; fill: none;`)}),e.getAttribute("width")),c=e.getAttribute("height"),u=(a&&c||console.warn("SVG width/height not set, background rect might not display correctly."),document.createElementNS("http://www.w3.org/2000/svg","rect")),m=(u.setAttribute("width",a||"100%"),u.setAttribute("height",c||"100%"),u.setAttribute("fill",n),e.insertBefore(u,e.firstChild),e.getAttribute("xmlns")||e.setAttribute("xmlns","http://www.w3.org/2000/svg"),(new XMLSerializer).serializeToString(e));y("ast.svg",m,"image/svg+xml")}catch(e){console.error("Error creating SVG for download:",e),alert("Failed to generate SVG data for download. Check console for details: "+e.message)}else alert("No SVG visualization available to download (AST might be empty or not rendered).")}),e.addEventListener("change",e=>{let t=e.target.files[0];var r;t&&((r=new FileReader).onload=e=>{e=e.target.result;f(o.value=e),n.textContent=`File "${t.name}" loaded.`},r.onerror=()=>{n.textContent=`Error reading file "${t.name}".`,a.innerHTML="/* Error loading file */",c.textContent="Error loading file.",g.selectAll("*").remove()},r.readAsText(t)),e.target.value=null});let r;function v(e){var t;"system"===e?(document.documentElement.removeAttribute("data-theme"),localStorage.removeItem("theme"),t=window.matchMedia("(prefers-color-scheme: dark)").matches,console.log(`Theme set to System (${t?"Dark":"Light"} detected)`)):(document.documentElement.setAttribute("data-theme",e),localStorage.setItem("theme",e)),console.log("Theme applied: "+e)}o.addEventListener("input",()=>{clearTimeout(r),r=setTimeout(()=>{f(o.value)},400)}),t.addEventListener("change",e=>{v(e.target.value)});e=localStorage.getItem("theme"),v(t.value=e||"system"),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{"system"===t.value&&v("system")}),e=`// Example C Code (Preprocessor directives like #include might not be handled by cparse.js)
int main() {
int i = 0;
for (i = 0; i < 5; i++) {
printf("Hello: %d\\n", i);
}
return 0;
}
`;o.value=e,l.disabled=!0,s.disabled=!0,f(e),n.textContent=""})