Monkey
Interpreter with support for class, linq, sql, net, http, fmt, json and A realtime syntax highlighting REPL.
Install / Use
/learn @haifenghuang/MonkeyREADME
Deprecation Notice
This project is no longer being maintained. All the contents have been moved to magpie.
Monkey Programming Language
Chinese version: 中文
Table of Contents
- Monkey Programming Language
- Summary
- Overview
- Installation
- Basic use
- Language Tour
- Comments
- Data Types
- Constants(Literal)
- Variables
- Reserved keywords
- Type conversion
- qw(Quote word) keyword
- enum keyword
- Meta-Operators
- Control flow
- using statement
- User Defined Operator
- Integer
- Float
- Decimal
- Array
- String
- Hash
- Tuple
- class
- Standard input/output/error
- Error Handling of standard library
- About defer keyword
- Concatenation of different types
- Comprehensions
- grep and map
- Function
- Pipe Operator
- Spawn and channel
- Use go language modules
- Standard module introduction
- About regular expression
- Useful Utilities
- Document generator
- Syntax Highlight
- Future Plans
- License
Summary
Monkey is a toy language interpreter, written in Go. It has C-style syntax, and is largely inspired by Ruby, Python, Perl and c# It support the normal control flow, functional programming and object oriented programming. It also has a REPL with realtime syntax highlighter.
This is a sample program using monkey language:
//Declare annotation class
//Note: In the body, you must use property, not method.
class @MinMaxValidator {
property MinLength
property MaxLength default 10 //Same as 'property MaxLength = 10'
}
//This is a marker annotation
class @NoSpaceValidator {}
class @DepartmentValidator {
property Department
}
//The 'Request' class
class Request {
@MinMaxValidator(MinLength=1)
property FirstName; //getter and setter are implicit. It is equal to 'property FirstName { get; set; }'
@NoSpaceValidator
property LastName;
@DepartmentValidator(Department=["Department of Education", "Department of Labors"])
property Dept;
}
//This class is responsible for processing the annotation.
class RequestHandler {
static fn handle(o) {
props = o.getProperties()
for p in props {
annos = p.getAnnotations()
for anno in annos {
if anno.instanceOf(MinMaxValidator) {
//p.value is the property real value.
if len(p.value) > anno.MaxLength || len(p.value) < anno.MinLength {
printf("Property '%s' is not valid!\n", p.name)
}
} elseif anno.instanceOf(NoSpaceValidator) {
for c in p.value {
if c == " " || c == "\t" {
printf("Property '%s' is not valid!\n", p.name)
break
}
}
} elseif anno.instanceOf(DepartmentValidator) {
found = false
for d in anno.Department {
if p.value == d {
found = true
}
}
if !found {
printf("Property '%s' is not valid!\n", p.name)
}
}
}
}
}
}
class RequestMain {
static fn main() {
request = new Request()
request.FirstName = "Haifeng123456789"
request.LastName = "Huang "
request.Dept = "Department of Labors"
RequestHandler.handle(request)
}
}
RequestMain.main()
Below is the result:
Property 'FirstName' not valid!
Property 'LastName' not valid!
Below is the REPL with real time syntax highlight:

Below is the html document generated using the mdoc tool:

Overview
This project is based on mayoms's project monkey with some bug fixes and a lot of new features including:
- Added simple class support(Indexer, operator overloading, property, static method/property/field and class annotation)
- Modified string module(which can correctly handle utf8 character encoding)
- Added
filemodule(with some new methods). - Added
math,time,sort,os,log,net,http,filepath,fmt,sync,list,csv,regexp,template, etc... sql(db) module(which can correctly handing null values)flagmodule(for handling command line options)jsonmodule(for json marshaling and unmarshaling)linqmodule(Code come from linq with some modifications)decimalmodule(Code come from decimal with some minor modifications)- Regular expression literal support(partially like perls)
- channel support(like golang's channel)
- more operator support(&&, ||, &, |, ^, +=, -=, ?:, ??, etc.)
- utf8 support(e.g. you could use utf8 character as variable name)
- more flow control support(e.g. try/catch/finally, for-in, case, c-like for loop)
- defer support
- spawn support(goroutine)
- enum support
usingsupport(like C#'susing)- pipe operator support(see demo for help)
- function with default value and variadic parameters
- list comprehension and hash comprehension support
- user defined operator support
- Using method of Go Package(
RegisterFunctionsandRegisterVars)
There are a number of tasks to complete, as well as a number of bugs. The purpose of this project was to dive deeper into Go, as well as get a better understanding of how programming languages work. It has been successful in those goals. There may or may not be continued work - I do plan on untangling a few messy spots, and there are a few features I'd like to see implemented. This will happen as time and interest allows.
Installation
Just download the repository and run ./run.sh
Basic use
To access the REPL, simply run the following:
~ » monkey
Monkey programming language REPL
>>
or, to run a program:
monkey path/to/file
Language Tour
Comments
Monkey support two kinds of single line comment and also block comment.
// this is a single line comment
# this is another single line comment
/* This is a
block comment.
*/
Data Types
Monkey supports 9 basic data types: String, Int, UInt, Float, Bool, Array, Hash, Tuple and Nil
s1 = "hello, 黄" # strings are UTF-8 encoded
s2 = `hello, "world"` # raw string
i = 10 # int
u = 10u # uint
f = 10.0 # float
b = true # bool
a = [1, "2"] # array
h = {"a": 1, "b": 2} # hash
t = (1,2,3) # tuple
n = nil
Constants(Literal)
In monkey, there are mainly eleven types of constants(Literals).
- Integer
- UInteger
- Float
- String
- Regular expression
- Array
- Hash
- Tuple
- Nil
- Boolean
- Function
// Integer literals
i1 = 10
i2 = 20_000_000 //for more readable
i3 = 0x80 // hex
i4 = 0b10101 // binary
i5 = 0o127 // octal
// Unsigned Integer literals
ui1 = 10u
ui2 = 20_000_000u //for more readable
ui3 = 0x80u // hex
ui4 = 0b10101u // binary
ui5 = 0o127u // octal
// Float literals
f1 = 10.25
f2 = 1.02E3
f3 = 123_456.789_012 //for more readable
// String literals
s1 = "123"
s2 = "Hello world"
// Regular expression literals
r = /\d+/.match("12")
if (r) { prinln("regex matched!") }
// Array literals
a = [1+2, 3, 4, "5", 3]
// Hash literals
h = { "a": 1, "b": 2, "c": 2}
//Tuple literals
t = (1, 2+3, "Hello", 5)
// Nil literal
n = nil
// Boolean literals
t = true
f = false
// Function literals
let f1 = add(x, y) { return x + y }
println(f1(1,2))
//fat-arrow function literals
let f2 = (x, y) => x + y
println(f2(1,2))
Variables
Variables in Monkey could start with the keyword let, or nothing with the
form variable=value.
let a, b, c = 1, "hello world", [1,2,3]
d = 4
e = 5
姓 = "黄"
You can also use Destructuring assignment.
Note, the left-hand side must be included using the '()'.
//righ-hand side is an array
let (d,e,f) = [1,5,8]
//d=1, e=5, f=8
//right-hand side is a tuple
let (g, h, i) = (10, 20, "hhf")
//g=10, h=20, i=hhf
//righ-hand side is a hash
let (j, k, l) = {"j": 50, "l": "good"}
//j=50, k=nil, l=good
Note however, if you do not use the keyword let, you could not do mult
