Skip to content

Instantly share code, notes, and snippets.

@thomasvrgn
Created October 11, 2020 15:26
Show Gist options
  • Select an option

  • Save thomasvrgn/9b3f50f0002446c6f894cdf168574222 to your computer and use it in GitHub Desktop.

Select an option

Save thomasvrgn/9b3f50f0002446c6f894cdf168574222 to your computer and use it in GitHub Desktop.
Python like parser written in Typescript
const code: string = `
if test = "brut":
print "yay"
if message = "Hello":
print "World"
else:
print "brush"
set "test"
else:
print "hobo"
print "Hello world"
`;
const formated: string[] = code
.split(/\r?\n/g)
.filter((x: string) => x.trim().length > 0);
type type = 'Program' | 'Node' | 'Block';
type state = -1 | 0 | 1 | 2;
interface AST {
type: type,
raw: string,
line: number,
tabs: number,
children: AST[],
parent?: AST,
}
const ast: AST = {
type: 'Program',
raw: '',
line: -1,
tabs: -1,
children: [],
};
let tabSize: number;
let oldTabSize: number = -1;
function getSizeTabs(line: string): number {
if (!tabSize) return 0;
const matched: string[] = line.match(/^\s+/) || [''];
return matched[0].length / tabSize;
}
function getParent(ast: AST, iterations: number): AST {
if (iterations === 0) return ast;
else {
if (!ast.parent) return ast;
return getParent(ast.parent, iterations - 1);
}
}
function parse(code: string[], index: number, ast: AST): typeof parse | null {
const line: string = code[index];
if (!line) return null;
if (!tabSize || tabSize === 0) {
const matched: string[] = line.match(/^\s+/) || [''];
tabSize = matched[0].length;
}
const tabs: number = getSizeTabs(line);
let state: state = -1;
if (oldTabSize > tabs) state = 0
else if (oldTabSize === tabs) state = 2;
else if (oldTabSize < tabs) state = 1;
const parentsNumber: number = Math.abs(tabs - oldTabSize);
oldTabSize = tabs;
const trimLine: string = line.trim();
if (state === 0) ast = getParent(ast, parentsNumber);
if (trimLine.endsWith(':')) {
ast.children.push({
type: 'Node',
raw: trimLine,
line: index,
tabs: tabs,
children: [],
parent: ast,
});
return parse(code, index + 1, ast.children.slice(-1)[0]);
}
ast.children.push({
type: 'Block',
raw: trimLine,
line: index,
tabs: tabs,
children: [],
parent: ast,
});
return parse(code, index + 1, ast);
}
parse(formated, 0, ast);
function printAST(ast: AST) {
if (!ast) return;
for (const child of ast.children) {
const tabs: string = new Array(child.tabs).fill(' '.repeat(tabSize)).join('');
if (child.raw.endsWith(':')) console.log(tabs + child.raw.slice(0, child.raw.length - 1) + ' {');
else console.log(tabs + child.raw);
printAST(child);
if (child.raw.endsWith(':')) console.log(tabs + '}');
}
}
printAST(ast);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment