function tokenize(code){
    let tokens=[],
        length=code.length,
        pos=0,
        isLetter=char=>/[a-zA-Z_]/.test(char),
        isDigit=char=>/[0-9]/.test(char),
        isOperatorChar=char=>'+-*/%=&|!<>'.includes(char);
    while(pos<length){
        let char=code[pos];
        if(char===' '||char==='\t'||char==='\r'){
            pos++;continue;
        }
        if(char==='/'&&code[pos+1]==='/'){
            while(char!=='\n'&&pos<length)
                char=code[++pos];
            continue;
        }
        if(char==='\n'){
            tokens.push({type:'newline'});
            pos++;continue;
        }
        if(';(){}.'.includes(char)){
            tokens.push({type:char});
            pos++;continue;
        }
        if(isOperatorChar(char)){
            let op=char;
            while(isOperatorChar(code[pos+1]))
                op+=code[++pos];
            tokens.push({type:'operator',value:op});
            pos++;continue;
        }
        if(isDigit(char)){
            let num=char;
            while(isDigit(code[pos+1]))
                num+=code[++pos];
            tokens.push({type:'number',value:Number(num)});
            pos++;continue;
        }
        if(isLetter(char)){
            let id=char;
            while(isLetter(code[pos+1])||isDigit(code[pos+1]))
                id+=code[++pos];
            const keywords=['int','while','if','else','print'];
            if(keywords.includes(id)){
                tokens.push({type:id});
            }else{
                tokens.push({type:'identifier',value:id});
            }
            pos++;continue;
        }
        throw new SyntaxError(`Unexpected character: ${char}`);
    }
    tokens.push({type:'EOF'});
    return tokens;
}
function parse(tokens){
    let pos=0,peek=()=>pos<tokens.length?tokens[pos]:{type:'EOF'},
        consume=expectedType=>{
        if(pos>=tokens.length)throw new SyntaxError(`Expected ${expectedType}, but reached end of input.`);
        let token=tokens[pos];
        if(token.type===expectedType){
            pos++;return token;
        }else{
            throw new SyntaxError(`Expected ${expectedType}, got ${token.type}`);
        }
    },parseProgram=()=>{
        let body=[];
        while(peek().type!=='EOF'){
            if(peek().type==='newline'){
                consume('newline');continue;
            }
            body.push(parseStatement());
        }
        return{type:'Program',body};
    },parseStatement=()=>{
        const token=peek();
        if(token.type==='EOF'){
            throw new SyntaxError("Unexpected end of input.");
        }else if(token.type==='int'){
            return parseVariableDeclaration();
        }else if(token.type==='while'){
            return parseWhileStatement();
        }else if(token.type==='if'){
            return parseIfStatement();
        }else if(token.type==='print'){
            return parsePrintStatement();
        }else if(token.type==='identifier'){
            return parseExpressionStatement();
        }else{
            throw new SyntaxError(`Unexpected token: ${token.type}`);
        }
    },parseVariableDeclaration=()=>{
        consume('int');
        let idToken=consume('identifier');
        consume(';');
        return{type:'VariableDeclaration',id:{type:'Identifier',name:idToken.value}};
    },parseWhileStatement=()=>{
        consume('while');consume('(');
        let test=parseExpression();
        consume(')');
        let body=parseBlockStatement();
        return{type:'WhileStatement',test,body};
    },parseIfStatement=()=>{
        consume('if');consume('(');
        let test=parseExpression();
        consume(')');
        let consequent=parseBlockStatement(),alternate=null;
        if(peek().type==='else'){
            consume('else');
            alternate=parseBlockStatement();
        }
        return{type:'IfStatement',test,consequent,alternate};
    },parsePrintStatement=()=>{
        consume('print');consume('(');
        let argument=parseExpression();
        consume(')');consume(';');
        return{type:'PrintStatement',argument};
    },parseExpressionStatement=()=>{
        let expression=parseAssignmentExpression();
        consume(';');
        return{type:'ExpressionStatement',expression};
    },parseBlockStatement=()=>{
        consume('{');
        let body=[];
        while(peek().type!=='}'){
            if(peek().type==='newline'){consume('newline');continue;}
            body.push(parseStatement());
        }
        consume('}');
        return{type:'BlockStatement',body};
    },parseAssignmentExpression=()=>{
        let left=parseIdentifier();
        if(peek().type==='operator'&&peek().value==='='){
            consume('operator');
            let right=parseExpression();
            return{type:'AssignmentExpression',operator:'=',left,right};
        }else{return left;}
    },parseBinaryExpression=()=>{
        let left=parseTerm();
        while(peek().type==='operator'&&['+','-','<','>','==','!=','<=','>='].includes(peek().value)){
            let operator=consume('operator').value,right=parseTerm();
            left={type:'BinaryExpression',operator,left,right};
        }
        return left;
    },parseTerm=()=>{
        let left=parseFactor();
        while(peek().type==='operator'&&['*','/'].includes(peek().value)){
            let operator=consume('operator').value,right=parseFactor();
            left={type:'BinaryExpression',operator,left,right};
        }
        return left;
    },parseExpression=parseBinaryExpression,parseFactor=()=>{
        let token=peek();
        if(token.type==='number'){
            consume('number');
            return{type:'Literal',value:token.value};
        }else if(token.type==='identifier'){
            return parseIdentifier();
        }else if(token.type==='('){
            consume('(');
            let expr=parseExpression();
            consume(')');
            return expr;
        }else{
            throw new SyntaxError(`Unexpected token in expression: ${token.type}`);
        }
    },parseIdentifier=()=>{
        let token=consume('identifier');
        return{type:'Identifier',name:token.value};
    };
    console.log(`Current position: ${pos}, Current token: ${JSON.stringify(peek())}`); //debugging
    return parseProgram();
}
function evaluate(node,environment={}){
    switch(node.type){
        case'Program':
            return evaluateProgram(node,environment);
        case'VariableDeclaration':
            return evaluateVariableDeclaration(node,environment);
        case'ExpressionStatement':
            return evaluateExpression(node.expression,environment);
        case'AssignmentExpression':
            return evaluateAssignmentExpression(node,environment);
        case'BinaryExpression':
            return evaluateBinaryExpression(node,environment);
        case'Identifier':
            return evaluateIdentifier(node,environment);
        case'Literal':
            return node.value;
        case'WhileStatement':
            return evaluateWhileStatement(node,environment);
        case'IfStatement':
            return evaluateIfStatement(node,environment);
        case'BlockStatement':
            return evaluateBlockStatement(node,environment);
        case'PrintStatement':
            return evaluatePrintStatement(node,environment);
        default:
            throw new Error(`Unknown node type: ${node.type}`);
    }
}
function evaluateProgram(node,environment){
    let result;
    for(let stmt of node.body)
        result=evaluate(stmt,environment);
    return result;
}
function evaluateVariableDeclaration(node,environment){
    let varName=node.id.name;
    if(environment.hasOwnProperty(varName)){
        throw new Error(`Variable '${varName}' is already declared.`);
    }
    environment[varName]=0;
}
function evaluateExpression(node,environment){
    return evaluate(node.expression,environment);
}
function evaluateAssignmentExpression(node,environment){
    let varName=node.left.name,
        value=evaluate(node.right,environment);
    if(!environment.hasOwnProperty(varName))
        throw new Error(`Variable '${varName}' is not declared.`);
    environment[varName]=value;
    return value;
}
function evaluateBinaryExpression(node,environment){
    let left=evaluate(node.left,environment),
        right=evaluate(node.right,environment);
    switch(node.operator){
        case'+':return left+right;
        case'-':return left-right;
        case'*':return left*right;
        case'/':return Math.floor(left/right);
        case'<':return+(left<right);
        case'>':return+(left>right);
        case'==':return+(left===right);
        case'!=':return+(left!==right);
        case'<=':return+(left<=right);
        case'>=':return+(left>=right);
        default:throw new Error(`Unsupported operator: ${node.operator}`);
    }
}
function evaluateIdentifier(node,environment){
    let varName=node.name;
    if(!environment.hasOwnProperty(varName))
        throw new Error(`Variable '${varName}' is not declared.`);
    return environment[varName];
}
function evaluateWhileStatement(node,environment){
    while(evaluate(node.test,environment))
        evaluate(node.body,environment);
}
function evaluateIfStatement(node,environment){
    if(evaluate(node.test,environment)){
        evaluate(node.consequent,environment);
    }else if(node.alternate){
        evaluate(node.alternate,environment);
    }
}
function evaluateBlockStatement(node,environment){
    for(let stmt of node.body)
        evaluate(stmt, environment);
}
function evaluatePrintStatement(node,environment){
    console.log(evaluate(node.argument,environment));
}
let code=`\
int n;n=0;
while(n<10){
    if(n==2){print(80085);}
    print(n);
    n=n+1;
}
print(0);`
try{
    let tokens=tokenize(code);
    console.log(tokens); //debugging
    let ast=parse(tokens);
    evaluate(ast);
}catch(e){
    console.error(e.message);
} It doesn't work, something's wrong with variable declaration.