diff options
Diffstat (limited to 'js/scripting-lang/web/src/ast.js')
-rw-r--r-- | js/scripting-lang/web/src/ast.js | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/js/scripting-lang/web/src/ast.js b/js/scripting-lang/web/src/ast.js new file mode 100644 index 0000000..522d026 --- /dev/null +++ b/js/scripting-lang/web/src/ast.js @@ -0,0 +1,161 @@ +// ast.js +// AST visualization tool for Baba Yaga language + +import { lexer, parser } from '../../lang.js'; + +const examples = { + simple: `x : 42;`, + + when: `result : when x is 42 then "correct" _ then "wrong";`, + + function: `factorial : n -> + when n is + 0 then 1 + _ then n * (factorial (n - 1));`, + + table: `person : {name: "Baba Yaga", age: 99, active: true}; +numbers : {1, 2, 3, 4, 5};`, + + arithmetic: `result : 5 + 3 * 2; +composed : compose @double @increment 5;`, + + complex: `classify : x y -> + when x y is + 0 0 then "both zero" + 0 _ then "x is zero" + _ 0 then "y is zero" + _ _ then "neither zero";` +}; + +// DOM elements - will be initialized when DOM is ready +let codeInput, generateBtn, examplesSelect, astOutput, tokensOutput, errorOutput, copyAstBtn, copyTokensBtn; + +// Initialize when DOM is ready +document.addEventListener('DOMContentLoaded', () => { + // Initialize DOM elements + codeInput = document.getElementById('code-input'); + generateBtn = document.getElementById('generate-btn'); + examplesSelect = document.getElementById('examples'); + astOutput = document.getElementById('ast-output'); + tokensOutput = document.getElementById('tokens-output'); + errorOutput = document.getElementById('error-output'); + copyAstBtn = document.getElementById('copy-ast-btn'); + copyTokensBtn = document.getElementById('copy-tokens-btn'); + + // Example selector functionality + examplesSelect.addEventListener('change', () => { + const selectedExample = examplesSelect.value; + if (selectedExample && examples[selectedExample]) { + codeInput.value = examples[selectedExample]; + generateAST(); + } + }); + + // Generate button click handler + generateBtn.addEventListener('click', generateAST); + + // Copy button click handlers + copyAstBtn.addEventListener('click', () => copyToClipboard(astOutput, 'AST')); + copyTokensBtn.addEventListener('click', () => copyToClipboard(tokensOutput, 'Tokens')); + + // Auto-generate on Enter key (but not in textarea) + document.addEventListener('keydown', (e) => { + if (e.key === 'Enter' && e.ctrlKey && document.activeElement !== codeInput) { + generateAST(); + } + }); + + // Initialize with a default example + codeInput.value = examples.when; + generateAST(); +}); + +// Generate AST from code +function generateAST() { + if (!codeInput) return; // DOM not ready yet + + const code = codeInput.value.trim(); + + if (!code) { + showError('Please enter some code to analyze.'); + return; + } + + try { + // Generate tokens + const tokens = lexer(code); + showTokens(tokens); + + // Generate AST + const ast = parser(tokens); + showAST(ast); + + // Clear any previous errors + showError(''); + + } catch (error) { + showError(`Parsing Error: ${error.message}`); + showAST(null); + showTokens(null); + } +} + +// Display AST in formatted JSON +function showAST(ast) { + if (!astOutput) return; // DOM not ready yet + + if (ast) { + astOutput.value = JSON.stringify(ast, null, 2); + } else { + astOutput.value = 'No AST available due to parsing error.'; + } +} + +// Display tokens in formatted JSON +function showTokens(tokens) { + if (!tokensOutput) return; // DOM not ready yet + + if (tokens) { + tokensOutput.value = JSON.stringify(tokens, null, 2); + } else { + tokensOutput.value = 'No tokens available due to parsing error.'; + } +} + +// Display error message +function showError(message) { + if (!errorOutput) return; // DOM not ready yet + + if (message) { + errorOutput.textContent = message; + errorOutput.style.display = 'block'; + } else { + errorOutput.style.display = 'none'; + } +} + +// Copy text to clipboard +async function copyToClipboard(textarea, label) { + if (!textarea || !textarea.value) { + showError(`No ${label} content to copy.`); + return; + } + + try { + await navigator.clipboard.writeText(textarea.value); + + // Show temporary success message + const originalText = errorOutput.textContent; + showError(`${label} copied to clipboard!`); + + // Clear success message after 2 seconds + setTimeout(() => { + if (errorOutput.textContent === `${label} copied to clipboard!`) { + showError(''); + } + }, 2000); + + } catch (error) { + showError(`Failed to copy ${label}: ${error.message}`); + } +} \ No newline at end of file |