Skip to content

Instantly share code, notes, and snippets.

@githiago-f
Created May 25, 2023 03:54
Show Gist options
  • Save githiago-f/af465b8de27c99a8b2f26b2c70e3138b to your computer and use it in GitHub Desktop.
Save githiago-f/af465b8de27c99a8b2f26b2c70e3138b to your computer and use it in GitHub Desktop.
dummy programing language processor preview
// memory registers
const vars = new Map(); // { varName: value }
// constants
const varStatement = /[^\s]\s?\=\s?[^\s]/i;
const conditionStatement = /[^\s]\s?(>=|<=|>|<|==)\s?[^\s]/;
const aritimeticStatement = /[0-9]*\s?(\*|\+|\/|\-|\%)\s?[0-9]*/;
const ifStatement = /^if\([^]+\):$/;
const whileStatement = /^while\([^]+\):$/;
const printStatement = /^print\([^]+\)/;
// interpreter functions
function interpreter(program) {
const lines = program.split(/\n/g);
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if(whileStatement.test(line)) {
const linesToJump = countNestedLines(lines[i], lines.slice(i+1));
const nextLines = lines.slice(i+1, i + 1 + linesToJump);
handleLoops(line, nextLines, linesToJump);
i += linesToJump;
}
else if (ifStatement.test(line)) {
i += handleIf(lines[i], lines.slice(i + 1));
}
else if (varStatement.test(line)) {
handleAssignment(line);
}
else if (printStatement.test(line)) {
console.log(atom(line.replace(/print\(|\)$/g, '')));
}
}
}
function aritimatics(operation) {
let [left, op, right] = operation.split(/(\*|\+|\\|\-|\%)/);
left = left.trim();
right = right.trim();
switch (op) {
case '*': return atom(left) * atom(right);
case '/': return atom(left) / atom(right);
case '-': return atom(left) - atom(right);
case '%': return atom(left) % atom(right);
case '+': return atom(left) + atom(right);
}
}
function conditions(operation) {
let [left, operator, right] = operation.split(/(>=|<=|>|<|==)/);
left = left.trim();
right = right.trim();
switch (operator) {
case '>': return atom(left) > atom(right);
case '<': return atom(left) < atom(right);
case '>=': return atom(left) >= atom(right);
case '<=': return atom(left) <= atom(right);
case '==': return atom(left) === atom(right);
}
}
function atom(val) {
if (conditionStatement.test(val)) return conditions(val);
else if (aritimeticStatement.test(val)) return aritimatics(val);
else if (!isNaN(Number(val))) return Number(val);
else if (val === 'true') return true;
else if (val === 'false') return false;
else if (val.startsWith('"') && val.endsWith('"')) return val.replace(/"/g, '');
else {
if (vars.has(val))
return vars.get(val);
throw Error(val + ' is not defined');
}
}
function handleAssignment(line) {
const [name, ...value] = line.split(/=/);
vars.set(name.trim(), atom(value.join('').trim()));
}
function countNestedLines(line, nextLines) {
function indentationCount(ln) {
if(!/^\s/.test(ln)) {
return 0;
}
return indentationCount(ln.slice(1)) + 1;
}
const spaces = indentationCount(line);
let nestedLines = 0;
for (const l of nextLines) {
const lineSpace = indentationCount(l);
if (lineSpace <= spaces) break;
nestedLines++;
}
return nestedLines;
}
function handleLoops(line, nextLines) {
const condition = () => atom(line.replace(/while\(|\)\:/g, ''));
while(condition()) {
interpreter(nextLines.join('\n'));
}
}
function handleIf(line, nextLines) {
const nestedLines = countNestedLines(line, nextLines);
const value = atom(line.trim().replace(/if\(|\)\:/g, ''));
if (value === true) return 0;
return nestedLines;
}
interpreter(`
two_pow_two = 2 * 2
x = 1
y = 2
z = x >= y
string = "Teste??"
if(x == 1):
print("x is 1")
if(x >= y):
print("should not display")
while(x <= 5):
print(x)
if(x % 2 == 0):
print(x + " is even")
x = x + 1
if(x > y):
print("HEHEHEH")
print("Test")
`);
console.table(vars);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment