We are basically making a transpiler in which we convert our own language to a C++ file to compile it.
- Clone the repository
git clone https://github.com/garv-iitr/kk_lang.git- Run
./run_ide.sh- Open localhost
http://localhost:5000The keyword khel_shuru is equivalent to
#include <iostream>
using namespace std;
int main(){The keyword khel_khatam is equivalent to
return 0;
}Syntax:
khel_shuru
khel_khatam
The keyword aelaan_karo is equivalent to
cout << (expression) << endl;Syntax:
khel_shuru
aelaan_karo ("Hello World");
aelaan_karo (10);
khel_khatam
Note
Brackets are a must
khiladi is a keyword which is used to declare a type of vairiable in runtime
khiladi loosely relates to auto in cpp
Syntax:
khel_shuru
khiladi x = 10;
aelaan_karo (x);
khiladi y = "Hello";
khel_khatam
Note
Initialization at the time of declaration is necessary
The syntax of assignment after an operation is exactly same as of cpp for example
x=x+10;
is used in cpp as well as kkl (khel khatam lang)
Syntax:
khel_shuru
khiladi x = 10;
x = x + 1;
khel_khatam
The syntax of faisla and nahi_toh is exactly same as of if-else in cpp
Syntax:
khel_shuru
khiladi x = 3;
khiladi y = 1;
faisla (x==y){
aelaan_karo (“Are Equal”)
}
nahi_toh {
aelaan_karo (“Not Equal”)
}
khel_khatam
Note
Brackets for the expressions are a must
Syntax, yet again, matches with cpp completely
Syntax:
khel_shuru
khiladi counter = 1;
khelte_raho (counter <= 5) {
aelaan_karo("Round number:");
aelaan_karo(counter);
counter = counter + 1;
}
khel_khatam
In this step we have made tokens of each word. We had already created a grammar of our language in which we created tokens.
Now we traverse through the code and assign tokens to each word and store both of them in a list.
This is the most complex and important step for our project.
In this we create an Abstract Syntax Tree (AST) which store the node of all the steps. This AST helps us in keeping tracks of branching.
The AST structure is very complex.
From the AST obtained from the previous step, we make the code to be written in a C++ file by traversing this list and creating functions for each process eg. Print, assignment, variable declare etc.
At the end we receive a cpp file of this.
So AST, originally a tree is defined I defined as a nested lists of lists in the code.
Initially, starts with the root node. Every new list represents a new branch in the original tree.
For what we have implemented till now, the branching can only occur at if condition and the root node.
khel_shuru
khiladi x = 10;
aelaan_karo (x);
x = x + 1;
khel_khatam
[(Token(“START”), 'khel_shuru'), [(Token(“VAR_DECL”), 'khiladi'), [(Token(“ID”), 'x'), (Token(“NUMBER”),'10')]],[(Token(“PRINT”),'aelaan_karo'), (Token(“EXPRESSION”), '(x)')], [(Token(“ASSIGN”), '='), [(Token(“ID”), 'x'), [(Token(“PLUS”), '+'), [(Token(“ID”), 'x'), (Token(“NUMBER”), '1')]]]]]All these token are originally tuple which contains 2 values but only the token is shown here.
[(Token("PRINT"), 'aelaan_karo'), [Token("ID"), '(x)']]
[(Token("VAR_DECL"), 'khiladi'), [(Token("ID"), 'x'), (Token("NUMBER"), '10')]]
[(Token("ASSIGN"), '='), [(Token("ID"), 'x'), [(Token("PLUS"), '+'), [(Token("ID"), 'x'), (Token("NUMBER"), '1')]]]]
[(Token("IF"), "faisla"), [(Token("EXPRESSION"), '(x==10)')], [(Token("TRUE"), <Statements>)], [(Token("FALSE"), <Statements>)]]
[(Token("WHILE"), "khelte_raho"), [(Token("EXPRESSION"), "(n<10)")], [<statements>]]
These are the list created.
For implementation purposes, we built a Flask-based compiler server that safely executes "KhelKhatam" code by transpiling it to C++, compiling it with g++, and running it inside a Docker container.
- API Endpoint: Created a
/compileendpoint that accepts.txtcode. - Sandboxing: It spins up a Docker container (
khelkhatam-runner) for every request to isolate user code execution. - Security & Stability: Implemented
flask_limiter(50 requests/min) and error handling for timeouts (10s limit) and compilation failures. - CORS: Manually handled CORS headers to allow the frontend to communicate with the server.
- Purpose: Implemented an AST to represent the logical structure of the source code after parsing.
- Structure: The AST is represented as nested lists, where each list corresponds to a node or a branch in the syntax tree.
- Branching Support: Handles control flow constructs such as
if-else,while, and nested loops
- We thought about how to create the AST on our own so that we really challenging.
- Nesting of loops was very difficult to implement. As managing the pointer while nesting is difficult.
- CORS (Cross-Origin Resource Sharing)
-
Issue: Browsers block requests from one Origin (e.g., frontend on port
8000) to another (backend on port5000) for security reasons. Even withflask-cors, we faced persistent preflight errors. -
Fix: We moved to a Single Origin Architecture. Instead of running two separate servers, we configured Flask (
app.py) to serve the HTML/JS static files itself. Now, everything lives on localhost:5000, so "Cross-Origin" rules no longer apply.
- It can print.
- We can declare and store a value of variable.
- We can assign a value to a variable.
- We can use loops and nested loops.
- We can use while loop in this.
- We have color-coded the Editor which also has auto-recommendation.
It cannot do all the things that are not mentioned above.