EasyLang is a compact educational scripting language whose syntax reads like English. It is optimized for clarity and teaching: you can write programs using short English phrases instead of dense punctuation.
This repository contains a minimal interpreter easy_lang.py and a test suite test.elang demonstrating language features.
- Quick start
- Language overview
- Syntax & reference (with examples)
- Variables and types
- Expressions and operators
- Printing and comments
- Input and typed read
- Control flow (if / else / else if)
- Loops (while and for)
- Functions and return
- Scoping rules
- Lists (arrays) — literals, indexing, methods, assignment
- File I/O
- Errors and debugging
- Complete examples
- Contributing and roadmap
- License
- Run the example test program shipped with this repository:
python .\easy_lang.py- Edit
test.elangor create your own.elangfile and run the interpreter.
EasyLang uses English-like keywords and phrases for common programming constructs. The interpreter currently supports:
- Primitive types:
int,float,text(string),boolean(true/false). - Arithmetic and string combination with both symbol operators and English word-forms.
- Lexical (block) scoping for blocks and functions.
- Native lists with literals, indexing, mutation, and methods (
push,pop,length). - Functions with parameter lists and local scope, including recursion.
- File I/O and typed input with validation.
Each subsection includes example snippets you can copy into test.elang.
- Declare or reassign with:
we let <name> = <expression>
Examples:
we let a = 10
we let b = 3.5
we let name = "Alice"
we let flag = true
- Numeric operators:
+,-,*,/and word-formsmul,div. - Ambiguous word-forms:
and,or,less,greatersometimes act as arithmetic or comparisons — the parser treats them as comparisons inside conditional contexts (likeif) and as arithmetic/concatenation in plain expressions.
Examples:
we let x = 5 and 2 $ 5 + 2 => 7
we let s = "Hi" and "!" $ string concatenation => "Hi!"
we let diff = x less 2 $ 5 - 2 => 3 (in expression context)
- Print:
so print <expression> - Single-line comments: begin with
$ - Multi-line comments:
$$ ... $$(not nestable)
Examples:
so print "Hello, world"
we let msg = "Value: " and 5
so print msg
$ this is a comment
$$
This is a multi-line comment
spanning lines
$$
read int <var>— read and validate integer inputread float <var>read text <var>orread <var>read boolean <var>— expectstrueorfalse
Example:
so print "Enter an integer:"
read int n
so print "You entered: " and n
- Syntax:
if <condition> then [ ... ] else [ ... ] else ifsupported.
Example:
we let score = 85
if score greater 90 then [
so print "Grade: A"
] else if score greater 80 then [
so print "Grade: B"
] else [
so print "Lower grade"
]
- While:
repeat while <condition>: do [ ... ] - For:
repeat from <var> = <start> to <end>: do [ ... ](inclusive)
Examples:
we let i = 3
repeat while i greater 0: do [
so print i
we let i = i less 1
]
repeat from j = 1 to 5: do [
so print j
]
- Define:
define name(p1, p2): do [ ... ] - Use
return <expr>inside functions to return a value. If noreturnexecutes, the function returnsnull/None.
Examples:
define add(x, y): do [
return x and y
]
we let result = add(2, 3)
so print result
define fact(n): do [
if n less 2 then [
return 1
] else [
we let sub = n less 1
we let rec = fact(sub)
return n mul rec
]
]
so print fact(5)
- Blocks and functions create inner (lexical) scopes.
we letassigns in the current innermost scope; shadowing is supported. - Loop variables and declarations inside blocks do not leak to outer scopes.
Example:
we let outer = 1
if outer equals 1 then [
we let outer = 10
so print outer $ prints 10 (inner)
]
so print outer $ prints 1 (outer unchanged)
- List literal:
[expr1, expr2, ...](elements can be mixed types or lists) - Indexing:
a[0](zero-based) - Element assignment:
a[1] = 42(must be in bounds) - Methods:
a.push(x),a.pop(),a.length()
Examples:
we let nums = [1, 2, 3]
so print nums $ [1, 2, 3]
so print nums[0] $ 1
nums.push(4)
so print nums $ [1,2,3,4]
we let last = nums.pop()
so print last $ 4
so print nums.length() $ 3
nums[1] = 42
so print nums $ [1, 42, 3]
we let nested = [1, [2,3], "hi"]
so print nested[1][0] $ 2
Note: push modifies the list in place and returns None/null. pop returns the removed element.
- Dictionary literal:
{ key: value, ... }— keys may be unquoted identifiers (treated as strings), string literals, or numeric literals. - Indexing:
d["key"]ord[identifier]— use bracket indexing for dictionary lookup. - Assignment:
d["key"] = valueupdates or creates entries. - Methods:
d.keys()→ list of keys,d.values()→ list of values,d.has(key)→ boolean,d.length()→ number of entries.
Examples:
we let person = { name: "Alice", age: 30 }
so print person
so print person["name"]
so print person["age"]
person["age"] = 31
so print person["age"]
so print person.keys()
so print person.values()
so print person.has("name")
so print person.has("email")
open "path" as <handle> for read|write|appendwriteline <handle> with <expression>— writes value and newlinereadline <handle> into <var>— reads a single line (empty string on EOF)close <handle>
Example:
open "tmp_test.txt" as fh for write
writeline fh with "Line1"
close fh
open "tmp_test.txt" as fh for read
readline fh into first
close fh
so print first
- The interpreter reports
SyntaxErrorwith token and line information where available. RuntimeErroris raised for type or semantic errors (e.g., indexing non-list, invalid input conversion).- Validation for
read intandread floatis performed at runtime and will raise an error for invalid entries.
Below are full runnable examples you can copy into test.elang to exercise features end-to-end.
- Arithmetic, strings, and boolean mixing
we let x = 5
we let y = 3
we let name = "John"
so print x and y
so print name and " Doe"
so print true and false
- Loops and accumulation
we let sum = 0
repeat from i = 1 to 5: do [
we let sum = sum and i
]
so print sum
- Lists and iteration
we let nums = [10, 20, 30]
nums.push(40)
so print nums
repeat from i = 0 to nums.length() less 1: do [
so print nums[i]
]
- Functions and recursion
define fib(n): do [
if n less 2 then [
return n
] else [
return fib(n less 1) and fib(n less 2)
]
]
so print fib(6)
- The interpreter is intentionally small and educational. Suggested improvements:
- Additional built-in list utilities and higher-order helpers
- Module/import system
- REPL mode
- More data types and standard library functions
MIT — see repository for details.