import java.io.*;
import java.lang.Character;
// import java.util.HashMap;
import javax.swing.*;
public class Cog extends JFrame {
public static String[] defName = new String[1000];
public static int[] defLine = new int[1000];
public static int defCount = 0;
public static String[] varVal = new String[1000];
public static String[] varName = new String[1000];
public static int varCount = 0;
public static int curLine;
public static String[] strScript;
public static int globI = 0;
public static void main(String args[]) {
try {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("Which file to open? (Case-sensitive)\n");
FileInputStream fr = new FileInputStream(new File(br.readLine()));
DataInputStream ds = new DataInputStream(new BufferedInputStream(fr));
System.out.println(ds.available());
String tmp = "";
for (int i2 = ds.available(); i2 > 0; i2--) {
if (ds.available() != 0) {
tmp += ds.readLine() + "\n";
}
}
strScript = tmp.split("\n");
getDefs();
if (getDef("start") > -1) {
globI = getDef("start");
System.out.println("Found start on " + getDef("start"));
} else if (getDef("main") > -1) {
globI = getDef("main");
System.out.println("Found main on " + getDef("main"));
} else {
System.out.println("Failed to start");
}
for (globI = globI; globI < strScript.length; globI++) {
try {
analyzeLine(strScript[globI]);
curLine++;
} catch (Exception e2) {
e2.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void analyzeLine(String s) {
if (!s.startsWith("#")) {
if (s.trim().startsWith("@")) {
String[] tmp = s.split("=");
for (int i = 0; i < tmp.length; i++) {
String[] tmp2 = tmp[i].split("@");
if (tmp2.length > 1) {
if (tmp2[1].equalsIgnoreCase("author")) {
System.out.println("Written by " + tmp[i + 1]);
} else if (tmp2[1].equalsIgnoreCase("name")) {
System.out.println("Script name " + tmp[i + 1]);
}
}
}
/* } else if (s.trim().startsWith("def")) {
String[] tmp = s.split(" ");
for (int i = 0; i < tmp.length; i++) {
if (tmp[i].endsWith("{")) {
setDef(left(tmp[i].length() - 1, tmp[i]), curLine);
}
}
*/
} else if (s.trim().startsWith("goto")) {
String tmp = between(s.trim(), "(", ")");
globI = getDef(tmp);
} else if (s.trim().startsWith("var")) {
String[] t = s.split("var");
String[] tmp = t[1].split(";");
for (int i = 0; i < tmp.length; i++) {
String[] tmp2 = tmp[i].split("=");
for (int i2 = 0; i2 < tmp2.length - 1; i2++) {
if (tmp2[i2 + 1].contains("}")) {
setVar(tmp2[i2],
left(tmp2[i2 + 1].length() - 1, tmp2[i2 + 1]));
} else if (tmp2[i2].contains("{")) {
setVar(right(1, tmp2[i2]), tmp2[i2 + 1]);
} else {
setVar(tmp2[i2], tmp2[i2 + 1]);
}
}
}
} else if (s.trim().startsWith("log")) {
// String tmp = right(4, s.trim());
// String tmp2 = left(tmp.length() - 1, tmp);
System.out.println(between(s.trim(), "(", ")"));
} else if (s.trim().startsWith("for")) {
String tmp = between(s.trim(), "for(", ")");
String[] tmp2 = tmp.split("=");
String[] tmp3 = tmp2[1].split(":");
int intFinish = 0;
for (int i = curLine; i < strScript.length; i++) {
if (strScript[i].trim().startsWith("next")) {
intFinish = i;
}
}
int iStart = Integer.valueOf(tmp3[0].trim()).intValue();
int iEnd = Integer.valueOf(tmp3[1].trim()).intValue();
int tmpi = globI + iEnd;
int tmp2z = globI + 1;
// JOptionPane.showMessageDialog(null, Integer.toString(globI) + ":" + Integer.toString(intFinish));
curLine = globI;
for (int i = iStart; i < iEnd; i++) { // run how many times
for (int i2 = curLine + 1; i2 < intFinish; i2++) { // what to run
analyzeLine(strScript[i2]);
globI++;
curLine++;
}
// JOptionPane.showMessageDialog(null, "i: " + Integer.toString(i));
curLine = globI - iEnd;
globI = curLine;
System.out.println(i);
}
curLine = globI;
// curLine = tmp2z;
} else if (s.trim().startsWith("when")) {
String tmp = between(s.trim(), "(", ")");
System.out.println(s);
String[] tmp2 = tmp.split(";");
System.out.println("Going to " + tmp2[1] + " when " + tmp2[0]);
if (tmp.contains("=>")) {
String[] tmp3 = tmp2[0].split(">=");
if (Integer.valueOf(getVar(tmp3[0].trim())).intValue()
>= Integer.valueOf(tmp3[1].trim()).intValue()) {
globI = getDef(tmp2[1]);
}
} else if (tmp.contains("<=")) {
String[] tmp3 = tmp2[0].split("<=");
if (Integer.valueOf(getVar(tmp3[0].trim())).intValue()
<= Integer.valueOf(tmp3[1].trim()).intValue()) {
globI = getDef(tmp2[1]);
}
} else if (tmp.contains("!=")) {
String[] tmp3 = tmp2[0].split("!=");
if (Integer.valueOf(getVar(tmp3[0].trim())).intValue()
!= Integer.valueOf(tmp3[1].trim()).intValue()) {
globI = getDef(tmp2[1]);
}
} else if (tmp.contains("<")) {
String[] tmp3 = tmp2[0].split("<");
if (Integer.valueOf(getVar(tmp3[0].trim())).intValue()
< Integer.valueOf(tmp3[1].trim()).intValue()) {
globI = getDef(tmp2[1]);
}
} else if (tmp.contains(">")) {
String[] tmp3 = tmp2[0].split(">");
if (Integer.valueOf(getVar(tmp3[0].trim())).intValue()
> Integer.valueOf(tmp3[1].trim()).intValue()) {
globI = getDef(tmp2[1]);
}
} else if (tmp.contains("=")) {
String[] tmp3 = tmp2[0].split("=");
String tmo = getVar(tmp3[0].trim());
if (tmo.equals(tmp3[1].trim())) {
globI = getDef(tmp2[1]);
}
}
} else if (s.trim().startsWith("if")) {
String tmp = between(s.trim(), "(", ")");
String[] tmp2 = new String[] { tmp};
if (tmp.contains(">=")) {
tmp2 = tmp.split(">=");
} else if (tmp.contains("<=")) {
tmp2 = tmp.split("<=");
} else if (tmp.contains("!=")) {
tmp2 = tmp.split("!=");
if (tmp2[0].trim() != tmp2[1].trim()) {
System.out.println(
tmp2[0].trim() + " does not equal "
+ tmp2[1].trim());
}
} else if (tmp.contains("<")) {
tmp2 = tmp.split("<");
} else if (tmp.contains(">")) {
tmp2 = tmp.split(">");
} else if (tmp.contains("=")) {
tmp2 = tmp.split("=");
if (tmp2[1].trim().equals(getVar(tmp2[0].trim()))) {
System.out.println(
"" + tmp2[0].trim() + " equals "
+ tmp2[1].trim());
}
}
} else {
for (int i = 0; i < varCount; i++) {
if (s.trim().startsWith(varName[i])) {
String tmp = s.trim();
String[] tmp2;
if (tmp.contains("+")) {
tmp2 = tmp.split("+");
} else if (tmp.contains("-")) {
tmp2 = tmp.split("-");
} else if (tmp.contains("=")) {
tmp2 = tmp.split("=");
System.out.println(
"Now " + tmp2[0].trim() + " equals "
+ tmp2[1].trim());
}
}
}
}
}
}
public static void setDef(String dName, int dLine) {
defLine[defCount] = dLine;
defName[defCount] = dName.trim();
defCount++;
}
public static int getDef(String dName) {
for (int i = 0; i < defCount; i++) {
if (dName.equals(defName[i])) {
return defLine[i];
}
}
return -1;
}
public static void getDefs() {
for (int i = 0; i < strScript.length; i++) {
if (strScript[i].trim().startsWith("def")) {
String[] tmp = strScript[i].split(" ");
for (int i2 = 0; i2 < tmp.length; i2++) {
if (tmp[i2].endsWith("{")) {
setDef(left(tmp[i2].length() - 1, tmp[i2]), i);
}
}
}
}
}
public static void setVar(String vName, String vVal) {
/* boolean inUse = false;
for (int i = 0; i < varCount; i++) {
System.out.println(varName[i]);
if (varName[i] == vName) {
inUse = true;
}
}
if (inUse = false) {*/
varVal[varCount] = vVal.trim();
varName[varCount] = vName.trim();
varCount++;
/* } else {
System.out.println(vName + " is already defined");
}*/
}
public static String getVar(String vName) {
for (int i = 0; i < varCount; i++) {
if (vName.equals(varName[i])) {
return varVal[i];
}
}
return null;
}
public static String between(String e, String s1, String s2) {
return mid(e.indexOf(s1) + 1, e.indexOf(s2) - e.indexOf(s1) - 1, e);
}
public static String mid(int offset, int toread, String s) {
String tmp = "";
char[] ch = s.toCharArray();
for (int i = offset; i < offset + toread; i++) {
tmp = tmp + ch[i];
}
return tmp;
}
public static String left(int offset, String s) {
String tmp = "";
char[] ch = s.toCharArray();
for (int i = 0; i < offset; i++) {
tmp = tmp + ch[i];
}
return tmp;
}
public static String right(int offset, String s) {
String tmp = "";
char[] ch = s.toCharArray();
for (int i = offset; i < s.length(); i++) {
tmp = tmp + ch[i];
}
return tmp;
}
}
[THIS IS THE DEMO SCRIPT YOU SHOULD TEST WITH!]
@name=Demo
@author=PPL
var{Username = PPL;Password = Demo;invFull = true}
def start{
for(i = 0:2)
log(LOL)
log(LOOL)
log(LOOOL)
next
}
def main{
obj_rock = findObject(rockType)
if(obj_rock != null)
log(Mining...)
endif
}
Refactorings
No refactoring yet !
Chris Jester-Young
June 23, 2008, June 23, 2008 09:18, permalink
I don't have a code refactoring for you at the moment, however, it looks like you're trying to do your own language parsing, which is not easy to do by hand. A much easier way to do parsing is to use a parser generator, such as JavaCC (https://javacc.dev.java.net/), to make a parser for you.
Given the amount of time you have (surely) spent on it, I would suggest spending just a little more time on how to turn your language into a grammar that JavaCC can use. The JavaCC site has extensive documentation on how you can write this grammar. All the best!
pewpew.lazer
June 25, 2008, June 25, 2008 08:54, permalink
Thanks for the help. I have spent many months working on various types of interpreters in numerous languages. This was my first attempt at a single file interpreter, which is not meant to be very complex.
I may use JavaCC in a later project, as for now I can't. Like I said, it's to be converted into a script, to then run a simpler script using my custom language.
Again, thanks for the help though.
Mike K
June 26, 2008, June 26, 2008 20:33, permalink
Well, I guess the biggest thing I see is the a serious lack of dynamics and generics. Granted, I don't know your use case, but I think it would make your code a lot easier to read if you use generic lists/maps/sets. This way you don't have to create huge arrays (and if someone goes over your current limit, the program will not crash).
Also, I dabbled with my own language once. From that experience, I cannot recommend HIGHLY enough the help Regular Expressions were for me. Try them out if you have the time, they will greatly reduce the number of LOC (not to mention make it easier to understand and work with).
Below are the variables I would use along with some sample code. (this is just a quick edit, I'll be back for a longer explanation and more thorough review if you would like; do not expect code to work plug'n'play).
import java.io.*;
import java.lang.Character;
// import java.util.HashMap;
import javax.swing.*;
import java.util.regex;
public class Cog extends JFrame {
//public static String[] defName = new String[1000]; -- use defs
//public static int[] defLine = new int[1000]; -- use defs
public static HashMap<String,Integer> defs;
//public static int defCount = 0; -- use defs.size()
//public static String[] varVal = new String[1000]; -- use vars
//public static String[] varName = new String[1000]; -- use vars
public static Hashmap<String, String> vars; //-- vars<varName,varVal>
//public static int varCount = 0; -- use vars.size()
public static int curLine;
public static String[] strScript;
public static int globI = 0;
//replace getDef with defs.get("item");
public static void getDefs() {
for (int i = 0; i < strScript.length; i++) {
String line = strScript[i].trim();
Matcher match = Pattern.compile("def(.*){").matcher(line);
if(match.matches())
defs.put(match.group(1).trim(),i); //groups start at 1... group 0 is the whole matched expression
}
}
}
pewpew.lazer
June 26, 2008, June 26, 2008 23:14, permalink
Thanks a lot, I was definately planning on working with hashmaps, hence the "// import java.util.HashMap;".
That helps a lot, thank you :)
giann
July 4, 2008, July 04, 2008 11:35, permalink
The main problem for me is that your code is made of chained 'if else'. You need to write an automate (don't know the word in english) with states. The classic way of doing it is to use lex/yacc (which uses regexp).
pewpew.lazer
July 5, 2008, July 05, 2008 18:40, permalink
I'm not sure I understand, care to elaborate?
giann
July 5, 2008, July 05, 2008 19:02, permalink
See http://memphis.compilertools.net/interpreter.html for an example of a simple interpreter written with Lex and Yacc.
pewpew.lazer
July 5, 2008, July 05, 2008 20:32, permalink
Ah ok, I get what you mean now.
The only problem is that I can't include external files. It needs to be one single file.
I'm very interested in Lex + YACC for future projects though.
So I was trying to condense a multi file interpreter (for a custom language) into a single file to run as a script inside another program.
Hoping I could get some help cleaning it up a bit.
Sorry for lots of the debug output.