0

我刚刚开始研究一种叫做 XScript 的编程语言。它的设计使我可以从 Java 应用程序运行它,也可以通过 Java 应用程序对其重新编程。这个想法是为了让我可以在游戏中创建虚拟计算机或随着时间的推移自行开发的程序。到目前为止,我有以下代码。我知道由于专有软件的原因可能需要更改名称,但现在还好。

人工主类:

import com.x.lang.XLoader;


public class Main {
    public static void main(String[] args) {
        XLoader xl = new XLoader();

        xl.exec("/Users/Nathan/Desktop/XScript/test.xls");
    }
}

XLoader(加载并执行 XScript):

package com.x.lang;

import java.io.File;

import com.x.lang.object.XObject;

public class XLoader {
    XObject xo;
    public String fileLocation;

    public void exec(String fl) {
        fileLocation = fl;

        XObject xo = new XObject(new File(fileLocation));
        xo.exec();
    }
}

存储语言键功能的 XCommandHub:

package com.x.lang;

import com.x.lang.keyword.Print;
import com.x.lang.keyword.Set;
import com.x.lang.object.XCommand;
import com.x.lang.object.XObject;

public class XCommandHub {
    public XCommand xc[] = new XCommand[2];

    public XCommandHub(XObject x) {
            xc[0] = new Print(x);
        xc[1] = new Set(x);
    }
    public XCommand getCommand(String s) {
        for (int i = 0; i < 2; i++) {
            if (xc[i].getCommandName() == s) {
                return xc[i];
            }
        }
        return null;
    }
}

定义关键字的 XCommand 类:

package com.x.lang.object;

public abstract class XCommand {
    private String commandName;
    public XObject xobject;

    public XCommand (String cn, XObject x) {
        commandName = cn;
        commandName += ": ";
        xobject = x;
    }
    public abstract void exec(XVar xv);

    public String getCommandName() {
        return commandName;
    }
}

定义所有变量的 XVar 类:

package com.x.lang.object;

public class XVar {
    private String var1;
    public String name;

    public XVar(String s) {
        var1 = s;
    }
    public String getStringValue() {
        if (this.var1 != null) {
            return var1;
        }
        return " ";
    }
    public int getIntValue() {
        if (this.var1 != null) {
            return Integer.parseInt(var1);
        }
        return 0;
    }
    public void setName(String s) {
        name = s;
    }
}

XObject 类实际执行命令:

package com.x.lang.object;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

import com.x.lang.XCommandHub;

public class XObject {
    public XVar xvars[] = new XVar[150];
    public int varCount = 0;
    public File f;
    XCommandHub x;

    public XObject (File file) {
            f = file;
        x = new XCommandHub(this);
    }
    public void addVar(XVar var, String name) {
        xvars[varCount] = var;
        xvars[varCount].setName(name);
        varCount++;
    }
    public XVar getVar(String varName) {
        for (int i = 0; i < varCount; i++) {
            if (xvars[i].name == varName) {
                return xvars[i];
            }
        }
        return null;
    }
    public void exec() {
        try (BufferedReader br = new BufferedReader(new FileReader(f))) {
            String sCurrentLine;

            while ((sCurrentLine = br.readLine()) != null) {
                for (int i = 0; i < 2; i++) {
                    if (sCurrentLine.startsWith(x.xc[i].getCommandName()))
                    try {
                        x.getCommand(x.xc[i].getCommandName()).exec(new XVar(sCurrentLine.split(": ")[1]));
                    } catch (ArrayIndexOutOfBoundsException e) {
                        x.getCommand(x.xc[i].getCommandName()).exec(new XVar(" "));
                    }
                }
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}

定义我到目前为止编写的命令的两个类:

package com.x.lang.keyword;

import com.x.lang.object.XCommand;
import com.x.lang.object.XObject;
import com.x.lang.object.XVar;

public class Print extends XCommand {
    public Print(XObject x) {
        super("print", x);
    }
    @Override
    public void exec(XVar xv) {
        if (xv.getStringValue().startsWith("%")) {
            try {
                System.out.println(xobject.getVar(xv.getStringValue().substring(1)).getStringValue());
            } catch (NullPointerException e) {
                System.out.println(xv.getStringValue());
            }
        }
        else {
            System.out.println(xv.getStringValue());
        }
    }
}


package com.x.lang.keyword;

import com.x.lang.object.XCommand;
import com.x.lang.object.XObject;
import com.x.lang.object.XVar;

public class Set extends XCommand {
    public Set(XObject x) {
        super("set", x);
    }
    @Override
    public void exec(XVar xv) {
        String[] add = xv.getStringValue().split("=");
        xobject.addVar(new XVar(add[1]), add[0]);
    }
}

从我到目前为止的编程中,我试图让用户能够打印他们在代码中声明的变量。一个基本的 .xls(X 语言脚本)可能看起来像这样:

set: x=Hello StackOverflow
print: This was programmed in XScript!
print: 
print: %x

但是,当我尝试从数组中检索变量 x 时,打印类中有一个 NullPointerException。该程序返回“%x”而不是“Hello StackOverflow”,因为我故意捕获了异常,但是我不知道它是如何发生的。

谢谢医生_N

4

1 回答 1

1

您的代码将永远找不到它正在寻找的变量:

public XVar getVar(String varName) {
    for (int i = 0; i < varCount; i++) {
        if (xvars[i].name == varName) {
            return xvars[i];
        }
    }

    return null;
}

由于您使用和不使用比较字符串,因此该函数几乎总是会返回。比较引用(内存地址),并且您要比较的参数和字符串不太可能指向同一位置。因此,您几乎总是返回。null==.equals==null

因此,这条线总是会导致NullPointerException

System.out.println(xobject.getVar(xv.getStringValue().substring(1)).getStringValue());

这是因为您正在有效地调用getStringValue().null

我建议将其更改if为:

if(xvars[i] != null && xvars[i].name.equals(varName)) {
    ...
}
于 2013-07-11T21:31:09.003 回答