MLang is a custom programming language with a unique syntax and structure, built using ANTLR4 and Java.
It supports variables, arithmetic expressions, functions, control flow (if, while), output (show), input (take()), and block scoping.
-
Variable declarations (with
let)let x > int = 5; -
Assignments
x = x + 1; -
Arithmetic expressions
x + 3 * 4; -
Comparison expressions
if (x == 0) [ ... ] -
show(...)for printing valuesshow(x); -
take()for user inputlet x > int = take(); -
if-elsecontrol flowif (x > 0) [ show(1); ] else [ show(0); ] -
whileloopswhile (x < 5) [ ... ] -
Function declarations and calls
func add(x > int, y > int) > int [ return x + y; ] let result > int = add(2, 3); -
Block scoping using square brackets
[ stmt1; stmt2; ]
- ANTLR4 Grammar (
MLang.g4) custom defined - AST Node Hierarchy:
ProgramNode,LetDeclNode,AssignStmtNode,ExprStmtNodeBinaryOpNode,IntLiteralNode,IdNode,InputExprNodeIfStmtNode,WhileStmtNode,ShowStmtNode,BlockNodeFuncDeclNode,FuncCallNode,ReturnStmtNode
- AST built via
MLangASTBuilder.javausing ANTLRMLangBaseVisitor - AST pretty-printer (
printAST) for visualization
- Interpreter implemented (
runtime/Interpreter.java) - Executes programs by visiting AST nodes:
- Variable environment management
- Expression evaluation
- Function call/return stack with local scope
- Control flow execution (
if,while) - Output to console using
show - Input from user using
take()
- Handles both integer and boolean conditions
- Place
.mltest programs inside thetests/folder. - Example:
tests/input_test.ml
let x > int = take();
show(x + 1);
From the MLANG/ root directory:
make clean
make✅ make handles ANTLR code generation, Java compilation, and execution.
To run a specific test file:
Edit TestMLang.java:
String inputCode = Files.readString(Paths.get("tests/input_test.ml"));Then rerun make.
MLANG/
├── src/
│ ├── MLang.g4 # ANTLR grammar
│ ├── MLangASTBuilder.java # AST builder
│ ├── TestMLang.java # Main driver (AST print + Interpreter run)
│ ├── ast/ # AST Node classes
│ └── runtime/ # Interpreter and Environment
├── gen/ # ANTLR-generated parser and lexer
├── bin/ # Compiled .class files
├── lib/ # antlr-4.13.1-complete.jar
├── tests/ # Test programs (.ml)
├── Makefile # Build automation
└── README.md
let num > int = take();
show(num + 1);
Program
VarDecl: num > int
InputExpr (take)
Show
BinaryOp: +
Id: num
IntLiteral: 1
take> 42
43
-
ANTLR Output Directory Problems:
Fixed by running ANTLR fromsrc/with output togen/. -
Classpath and Compilation Issues:
Used$(wildcard gen/*.java)and explicitly includedsrc/runtime/*.java. -
Variable Initialization Order:
Interpreter defines variable names before evaluating their initializers. -
Return flow handling in functions:
UsedReturnExceptionto simulate non-local returns. -
Local scope for functions:
Functions execute in isolated environments (not modifying global state). -
Input support:
Addedtake()expression for reading integers viaScanner.
- Add
floatandbooltypes fully (currently onlyintsupported) - Add support for recursion and higher-order functions
- Add
arrays,forloops, and standard library support - Improve parser error messages (currently minimal error recovery)
🧠 Author
Mudit Golchha
CS571 – Programming Languages
Binghamton University