A Go implementation of a complete programming language interpreter
YAPL (Yet Another Programming Language) is a dynamically-typed, interpreted programming language with a clean and simple syntax. This implementation provides a full-featured interpreter with lexical analysis, parsing, and execution capabilities, including control flow statements, variable scoping, and comprehensive error handling.
- Statements must end with a semicolon (
;) - Identifiers can contain letters, digits, and underscores, but cannot start with a digit
- Keywords are reserved and cannot be used as identifiers
- Case sensitivity: Lox is case-sensitive
- Whitespace is generally ignored except for separating tokens
and, break, class, else, false, for, fun, if, nil, or, print, return, super, this, true, var, while
Note: class, fun, return, super, and this are reserved for future implementation.
| Operator | Description | Example |
|---|---|---|
+ |
Addition / String concatenation | 1 + 2 or "hello" + "world" |
- |
Subtraction / Negation | 5 - 3 or -x |
* |
Multiplication | 3 * 4 |
/ |
Division | 10 / 2 |
! |
Logical NOT | !true |
== |
Equality | x == y |
!= |
Inequality | x != y |
> |
Greater than | 5 > 3 |
>= |
Greater than or equal | 5 >= 5 |
< |
Less than | 3 < 5 |
<= |
Less than or equal | 3 <= 5 |
and |
Logical AND | true and false |
or |
Logical OR | true or false |
go build./Lox script.yapl./LoxIn interactive mode, you can:
- Enter expressions and statements
- Type
clearto clear the screen - Type
exitto quit
var a = 10;
var b = 20;
print a + b; // Output: 30
print a * b; // Output: 200
var greeting = "Hello";
var name = "World";
print greeting + " " + name; // Output: Hello World
var x = true;
var y = false;
print y == x; // Output: false
print !x; // Output: false
print true and false; // Output: false
print true or false; // Output: true
var count = 0;
print count; // Output: 0
count = count + 1;
print count; // Output: 1
// If statement
var age = 18;
if (age >= 18) {
print "You are an adult";
} else {
print "You are a minor";
}
// While loop
var i = 0;
while (i < 5) {
print i;
i = i + 1;
}
// For loop (desugared to while)
for (var j = 0; j < 3; j = j + 1) {
print "Iteration: " + j;
}
// Break statement
var a = 1;
while (a < 100) {
while (a < 40) {
if (a == 39) {
break; // Breaks out of inner loop only
}
print a;
a = a + 1;
}
print "now outside";
print a;
a = a + 1;
}
var global = "I'm global";
{
var local = "I'm local";
print global; // Output: I'm global
print local; // Output: I'm local
}
print global; // Output: I'm global
// print local; // Error: Undefined variable 'local'
YAPL/
├── Token/ # Token definitions and types
├── Scanner/ # Lexical analysis (tokenization)
├── parser/ # Syntax analysis (parsing)
├── ast/ # Abstract Syntax Tree nodes
├── Interpreter/ # Expression and statement evaluation
├── environment/ # Variable environment management with scoping
├── YaplErrors/ # Error handling and reporting
├── state/ # Global interpreter state
├── printer/ # AST pretty printing utilities
├── main.go # Main interpreter entry point
├── test.lox # Example YAPL program
└── main.yapl # Additional example program
The interpreter follows a traditional pipeline architecture:
- Scanner: Converts source code into tokens
- Parser: Builds an Abstract Syntax Tree (AST) from tokens
- Interpreter: Evaluates the AST and produces results
- Token: Represents lexical units (keywords, operators, literals)
- Scanner: Implements lexical analysis with support for comments, strings, numbers, and identifiers
- Parser: Recursive descent parser with error recovery and support for all control flow statements
- AST: Tree representation of program structure with expression and statement nodes
- Interpreter: Visitor pattern implementation for expression and statement evaluation
- Environment: Manages variable storage and lookup with proper scoping support
- Error Handling: Comprehensive error reporting for lexical, parse, and runtime errors
The interpreter provides comprehensive error reporting:
- Lexical Errors: Invalid characters, unterminated strings
- Parse Errors: Syntax errors with line numbers and helpful messages
- Runtime Errors: Type mismatches, undefined variables
Error messages include:
- Line number where the error occurred
- Description of the error
- Context around the error location
This implementation represents a mature interpreter with comprehensive language features. The core functionality is complete and includes:
- Complete Expression System: All arithmetic, comparison, logical, and unary operations
- Control Flow:
if/elsestatements,whileloops,forloops (desugared to while), andbreakstatements - Variable Management: Declaration, assignment, and proper scoping with block environments
- Data Types: Numbers (float64), strings, booleans, and nil
- Error Handling: Comprehensive lexical, parse, and runtime error reporting
- Interactive Mode: REPL with clear and exit commands
- File Execution: Run YAPL programs from files
- Functions: User-defined functions with parameters and return values
- Classes and Objects: Object-oriented programming support
- Standard Library: Built-in functions for common operations
- Modules: Import/export system for code organization
- Advanced Error Recovery: Better error messages and suggestions
- Numbers: Floating-point numbers, all numbers are double, with 2-place float precision (e.g.,
42,3.14) - Strings: Text literals enclosed in double quotes (e.g.,
"hello world") - Booleans:
trueandfalse - Nil: Represents the absence of a value
- Arithmetic Operations:
- Addition:
+(supports numbers and string concatenation) - Subtraction:
- - Multiplication:
* - Division:
/
- Addition:
- Comparison Operations:
- Equality:
==,!= - Relational:
>,>=,<,<=
- Equality:
- Logical Operations:
- Logical AND:
and - Logical OR:
or - Logical NOT:
!
- Logical AND:
- Unary Operations:
- Negation:
-(for numbers) - Logical NOT:
!
- Negation:
- Grouping: Parentheses
()for expression precedence - Variable Access: Direct variable name references
- Variable Declaration:
var name = value; - Print Statement:
print expression; - Expression Statement: Any expression followed by
; - If Statement:
if (condition) statement else statement - While Loop:
while (condition) statement - For Loop:
for (initializer; condition; increment) statement - Break Statement:
break;(exits the innermost loop) - Block Statement:
{ statement1; statement2; ... }
- Declaration:
var variableName;orvar variableName = initialValue; - Assignment:
variableName = newValue; - Scope: Block-scoped variables with proper environment nesting
- Lookup: Variables are looked up in the current scope and enclosing scopes
- Syntax:
break; - Purpose: Exits the innermost loop (while or for) immediately
- Scope: Only affects the current loop level, outer loops continue normally
- Usage: Must be used inside a loop body
- Example:
var i = 0; while (i < 10) { if (i == 5) { break; // Exits the while loop when i equals 5 } print i; i = i + 1; }
- Single-line comments:
// This is a comment
- Lexical Errors: Invalid characters, unterminated strings
- Parse Errors: Syntax errors with helpful error messages
- Runtime Errors: Type errors, undefined variables