/slime

Slime is an interpreter made in Java :)

Primary LanguageJavaMIT LicenseMIT

Slime

Slime is a node-based interpreter

// Create a space to store things
final Space space = new Space();

// Define the slime interpreter
final Slime slime = new Slime(space);

// Execute
slime.exec(scanner.nextLine());

// Demo tests

// print result of 1 + 1 - (7 + 5)       
slime.exec("print 1 + 1 - (7 + 5)")

Process

The process:

Lexing -  Breaking down into tokens
Parsing - Parsed the tokens
Node Creator - Create a node tree
NodeReader/processor - Read the nodes and process them into result

Variable

Asign a value to a variable (a-zA-Z) characters are allowed.

a = 'The Android Java';

The variable can be a number or a string.

// example inputs

a = 70 + (10 + 20)
        
print a is 100 // true
a = 'The number is ' + a

Print

Use the print method to print a variable or a thing.

// prints value from variable 'a' 
// with value 'The number is 100'

print a
print 50 + (1 + 1) // 52
        
// prints 2.1        
print .1 + 2

Basic Operators

Slime can understand +, -, / and * math operators, is and or boolean operator including braces.

You will have to request the interpreter line by line.


Custom methods

You can also declare your methods!

For that, you will need to create a class that extends SlimeMethods and then do change accordingly, an example:

class MyMethods extends SlimeMethods {
    public void trim(final Object text) {
        System.out.println(String.valueOf(text).trim());
    }
}

Declare a constructor as passing your own SlimeMethods instance as the second parameter.

final Space space = new Space();
final Slime slime = new Slime(space, new MyMethods());

Define

You can also define variable with your own values with slime, you just need to call define(name, expression) or define(name, value) to define a constant.

slime.define("pie", valueOf(Math.PI));
slime.defineConstant("cakes", "50")

Dynamic operators

You can also add a dynamic operator, doing additional things!
For that you have to call setOperator on Slime and pass an operator and the operator handler. This will call the handle(Object, Object) method.
You have to perform any operator and return the result.

// Dynamically adding a boolean operator `<?> is <?>`
slime.setOperator("is", new Operator() {
            @Override
            public Object handle(Object first, Object second) {
                // checks and returns if first == second
                return Objects.equals(valueOf(first), valueOf(second));
            }
        });

slime.exec("a = (70 + (10 + 20)) is 100")
slime.exec("print a"); // prints true

Function

Yeah! You can also add functions!
There are two inbuilt functions named max and min.
To access this feature, you will have to use execBlock as replacement for exec command method.

// creates a variable named cakeName 
// with the value 'Chocolate Cake!'

slime.execBlock("cakeName = 'Chocolate Cake!'");

// prints 'CHOCOLATE CAKE!'
slime.execBlock("print case(cakeName, 'upper')");

// prints 'chocolate cake!'
slime.execBlock("print case(cakeName, 'lower')");

// find the max and  in the args provided
        
// prints the number 7     
slime.execBlock("print max(PI, 7)");

// prints the number 1

slime.execBlock("print min(PI, 7, 1)")

A complicated example to define a function with by calling the method defineFunction(MethodName, Function) on Slime object.

defineFunction("case", new Function() {
                @Override
                public Object handle(ArrayList<Object> parms) {
                    if (parms.size() != 2)
                        throw new IllegalArgumentException("Expected only two parameter!");
                    final Object toCase = parms.get(1);
                    if (toCase == "true" || toCase.equals("lower"))
                        return valueOf(parms.get(0)).toLowerCase();
                    else if (toCase == "false" || toCase.equals("upper"))
                        return valueOf(parms.get(0)).toUpperCase();
                    throw new IllegalArgumentException("Not a valid argument '" + toCase + "'");
                }
            });

This was made to learn.
Feel free to fork and contribute back 🙂