<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Scheme Interpreter with PDF</title>
<style>
body, html {
margin: 0;
padding: 0;
height: 100%;
font-family: Arial, sans-serif;
}
#pdf-container {
width: 100%;
height: 67%;
overflow: hidden;
}
#repl-container {
width: 100%;
height: 33%;
display: flex;
flex-direction: column;
border-top: 1px solid #ccc;
padding: 10px;
}
textarea {
flex: 1;
width: 100%;
font-family: monospace;
font-size: 16px;
padding: 10px;
}
button {
margin-top: 10px;
padding: 10px;
font-size: 16px;
}
#scheme-output {
font-family: monospace;
background-color: #f0f0f0;
padding: 10px;
margin-top: 10px;
overflow-wrap: break-word;
}
</style>
</head>
<body>
<div id="pdf-container">
<embed src="tls.pdf" type="application/pdf" width="100%" height="100%">
</div>
<div id="repl-container">
<textarea id="scheme-input" placeholder="Scheme here..."></textarea>
<div id="scheme-output"></div>
<button onclick="evaluateScheme()">Run Code</button>
</div>
<script>
// Scheme interpreter (unchanged)
function tokenizeScheme(input) {
const tokens = [];
let current = 0;
const isWhitespace = (char) => /\s/.test(char);
const isDigit = (char) => /[0-9]/.test(char);
const isParen = (char) => char === '(' || char === ')';
const isSymbolChar = (char) => /[a-zA-Z0-9\+\-\*\/\=\?\!\_]/.test(char);
while (current < input.length) {
let char = input[current];
if (isWhitespace(char)) {
current++;
continue;
}
if (isParen(char)) {
tokens.push({ type: 'paren', value: char });
current++;
continue;
}
if (isDigit(char) || (char === '-' && isDigit(input[current + 1]))) {
let number = '';
while (isDigit(char) || char === '-') {
number += char;
char = input[++current];
}
tokens.push({ type: 'number', value: number });
continue;
}
if (isSymbolChar(char)) {
let symbol = '';
while (isSymbolChar(char)) {
symbol += char;
char = input[++current];
}
tokens.push({ type: 'symbol', value: symbol });
continue;
}
throw new Error(`Unexpected character: ${char}`);
}
return tokens;
}
function parseScheme(tokens) {
let current = 0;
function walk() {
let token = tokens[current];
if (token.type === 'number') {
current++;
return { type: 'NumberLiteral', value: Number(token.value) };
}
if (token.type === 'symbol') {
current++;
return { type: 'Symbol', value: token.value };
}
if (token.type === 'paren' && token.value === '(') {
current++;
const node = { type: 'List', value: [] };
while (!(tokens[current].type === 'paren' && tokens[current].value === ')')) {
node.value.push(walk());
}
current++; // Skip closing ')'
return node;
}
throw new Error(`Unexpected token: ${token.type}`);
}
return walk();
}
const globalEnv = {
'+': (...args) => args.reduce((acc, curr) => acc + curr),
'-': (...args) => args.reduce((acc, curr) => acc - curr),
'*': (...args) => args.reduce((acc, curr) => acc * curr),
'/': (a, b) => a / b,
'eq?': (...args) => args.every((val, i, arr) => val === arr[0]),
'car': (list) => list[0],
'cdr': (list) => list.slice(1),
'cons': (a, b) => [a].concat(b),
'null?': (list) => list.length === 0,
};
function evaluate(node, env = globalEnv) {
if (node.type === 'NumberLiteral') {
return node.value;
}
if (node.type === 'Symbol') {
if (env[node.value] !== undefined) {
return env[node.value];
}
throw new Error(`Undefined symbol: ${node.value}`);
}
if (node.type === 'List') {
const [first, ...rest] = node.value;
if (first.type === 'Symbol') {
const operator = first.value;
if (operator === 'define') {
const [symbol, expr] = rest;
env[symbol.value] = evaluate(expr, env);
return;
}
if (operator === 'lambda') {
const [params, body] = rest;
return function (...args) {
const lambdaEnv = { ...env };
params.value.forEach((param, i) => {
lambdaEnv[param.value] = args[i];
});
return evaluate(body, lambdaEnv);
};
}
if (operator === 'if') {
const [test, consequent, alternate] = rest;
const condition = evaluate(test, env);
return condition ? evaluate(consequent, env) : evaluate(alternate, env);
}
}
const func = evaluate(first, env);
if (typeof func !== 'function') {
throw new Error(`Expected a function but got: ${func}`);
}
const args = rest.map(arg => evaluate(arg, env));
return func(...args);
}
throw new Error(`Unexpected node type: ${node.type}`);
}
function evalScheme(input) {
const tokens = tokenizeScheme(input);
const ast = parseScheme(tokens);
return evaluate(ast);
}
// Function to evaluate the input in the REPL
function evaluateScheme() {
const input = document.getElementById('scheme-input').value;
let output;
try {
output = evalScheme(input);
} catch (error) {
output = `Error: ${error.message}`;
}
document.getElementById('scheme-output').innerText = JSON.stringify(output, null, 2);
}
</script>
</body>
</html>