Konloch Software

KonScript - Scripting Parser

Published 07/07/2012

📝 This project is from 2012, I’ve chosen to keep it here as a reminder of my progress and growth.

This is KonScript, a basic script parser created for performing fundamental logical operations. I developed it long before I had any formal knowledge of programming languages or design principles. I’ve chosen to keep it here as a reminder of my progress and growth.

The original goal of this project was to develop a domain-specific language that could execute various Java functions in order, with different parameters based on the script. Today, I would use DSLBuilder to achieve the same goal.

Functions (“outcall” Operators)

To extend KScript you’ll have to add your own “outcall” operators to create your own functions.

  • print<object val>
    Prints a message to the console.
  • memory<object val>
    Clears the memory cache and resets it to the new value.
  • store<memory index> <object val>
    Stores the value into the specified memory index.
  • goto<goto line>
    Goes to the specified line.
  • ifeq<object val> <object val> <goto line> <goto line>
    Checks if the first value equals the second value. If so, goes to the first goto line; if not, goes to the second goto line.
  • ifne<object val> <object val> <goto line> <goto line>
    Checks if the first value is not equal to the second value. If so, goes to the first goto line; if not, goes to the second goto line.
  • ifgt<object val> <object val> <goto line> <goto line>
    Checks if the first value is greater than the second value. If so, goes to the first goto line; if not, goes to the second goto line.
  • iflt<object val> <object val> <goto line> <goto line>
    Checks if the first value is less than the second value. If so, goes to the first goto line; if not, goes to the second goto line.

Operators

  • memory<address>
    Loads a value from the specified memory address.
  • +
    Adds to the existing string (requires a check for integer values).

  • Converts strings to integers and performs subtraction.
  • ++
    Converts strings to integers and performs addition.

KonScript Source Code

public class KonScript {
	/*
	 * Used for parsing then executing scripts
	 */
	public static void runScript(String fileName) throws Exception {
		loadScript(fileName);
		doScript();
	}
	
	/*
	 * This is the actual script, it contains all of the content for the script to be ran
	 */
	private static ArrayList<String> script;
	
	/*
	* This is used as the virtual memory for the script, it allows loading to/from memory
	*/
	private static ArrayList<String> memory;
	
	/*
	 * This method loads the script into the array
	 */
	private static void loadScript(String fileName) throws Exception {
		script = new ArrayList<String>();
			
		BufferedReader reader = new BufferedReader(new FileReader(fileName));
		String contents;
		while ((contents = reader.readLine()) != null) {
			script.add(contents);
		}
		reader.close();
	}

	/*
	 * All of the actual logic behind the scripting language is here
	 * 
	 * Functions are handled here
	 */
	private static void doScript() {
		if(!script.isEmpty()) {
			for(int line = 0; line < script.size(); line++) {
				if(script.get(line).startsWith("#")) {
					continue;
				}
				
				String[] argument = script.get(line).split("\t");
				if(argument[0].equals("end")) {
					break;
				}
				
				if(argument[0].startsWith("memory")) {
					int limit = Integer.parseInt(argument[1]);
					memory = new ArrayList<String>(limit);
					for(int i = 0; i < limit; i++) {
						memory.add("");
					}
				}
				
				if(argument[0].startsWith("print")) {
					System.out.println(parseOperators(argument[1]));
				}
				
				if(argument[0].startsWith("store")) {
					memory.set(Integer.parseInt(argument[1]), parseOperators(argument[2]));
				}
				
				if(argument[0].startsWith("goto")) {
					line = Integer.parseInt(argument[1]) -2;
				}
				
				if(argument[0].startsWith("ifeq")) {
					if(parseOperators(argument[1]).equals(parseOperators(argument[2]))) {
						line = Integer.parseInt(argument[3]) -2;
					} else {
						line = Integer.parseInt(argument[4]) -2;
					}
				}
				
				if(argument[0].startsWith("ifne")) {
					if(!parseOperators(argument[1]).equals(parseOperators(argument[2]))) {
						line = Integer.parseInt(argument[3]) -2;
					} else {
						line = Integer.parseInt(argument[4]) -2;
					}
				}
				
				if(argument[0].startsWith("ifgt")) {
					if(Integer.parseInt(parseOperators(argument[1])) > Integer.parseInt((parseOperators(argument[2])))) {
						line = Integer.parseInt(argument[3]) -2;
					} else {
						line = Integer.parseInt(argument[4]) -2;
					}
				}
				
				if(argument[0].startsWith("iflt")) {
					if(Integer.parseInt(parseOperators(argument[1])) < Integer.parseInt((parseOperators(argument[2])))) {
						line = Integer.parseInt(argument[3]) -2;
					} else {
						line = Integer.parseInt(argument[4]) -2;
					}
				}
			}
		} else {
			System.out.println("[ERROR]: Script is empty");
		}
	}

	/*
	 * This is used to parse operators
	 */
	private static String parseOperators(String value) {
		StringTokenizer st = new StringTokenizer(value,"_");
		
		String finalValue = ""; //acts as the buffer
		
		int flag = 0;
		
		while (st.hasMoreTokens()) {
			String currentToken = st.nextToken();
		    
			/* Pre-Defined Value */
			if(currentToken.startsWith("\"")) {
				 currentToken = currentToken.substring(1,currentToken.length()-1);
			} else {
				/* Outcall Operators */
				if(currentToken.startsWith("memory")) {
					currentToken = memory.get(Integer.parseInt(currentToken.substring("memory".length())));
				} else if(currentToken.startsWith("times")) {
					currentToken = "" + (int) (System.currentTimeMillis() / 1000) % 60 ;
				} else
				
				/* Operators */
				if(currentToken.equals("+")) {
				} else if(currentToken.equals("--")) {
				} else if(currentToken.equals("++")) {
				} else {
					throw new RuntimeException("Cannot find that operator");
				}
			}
			
			/* Operator Flags */
			if(flag == 1) {
				finalValue += currentToken;
				flag = 0;
			} else if(flag == 2) {
				finalValue = ""+(Integer.parseInt(finalValue) - Integer.parseInt(currentToken));
				flag = 0;
			} else if(flag == 3) {
				finalValue = ""+ (Integer.parseInt(finalValue) + Integer.parseInt(currentToken));
				flag = 0;
			}
			
			/* Operators */
			else if(currentToken.equals("+")) {
				flag = 1;
			} else if(currentToken.equals("--")) {
				flag = 2;
			} else if(currentToken.equals("++")) {
				flag = 3;
			} else {
				finalValue += currentToken;
			}
		}
		
		return finalValue;
	}
}

Hello World.ks

A simple Hello World

print	"Hello World"

Hello World From Memory.ks

A more complicated Hello World

memory	1
store	0	"Hello World"
print	memory0

Hello World Delayed.ks

Waits 5 seconds and prints “Hello World”

memory	1

store	0	times

ifgt	times_--_memory0	"5"	11	10
print	"Hello World"
end

for.ks

This is meant to show-case the two operations of addition inside a for loop using String concatenation and Integer addition.

memory	1

#append to a String
store	0	memory0_+_"1"
print	memory0
ifeq	memory0	"1111111"	11	13
print	"Memory reached: "_+_memory0
goto	15
goto	8

#add to an Integer
memory	1
store	0	"0"
store	0	memory0_++_"1"
print	memory0
ifeq	memory0	"5"	20	22
print	"Memory reached: "_+_memory0
end
goto	17