JavaInterpreter模式

本文最后更新于:1 年前

语法规则也是类

1 - 表示语法树”节点”的类

public abstract class Node {
    public abstract void parse(Context context) throws ParseException;
}

2 - 对应program的类

// <program> ::= program <command list>
public class ProgramNode extends Node{
    private Node commandListNode;

    @Override
    public void parse(Context context) throws ParseException {
        context.skipToken("program");
        commandListNode = new CommandListNode();
        commandListNode.parse(context);
    }

    @Override
    public String toString() {
        return "[program " + commandListNode + "]";
    }
}

3 - 对应command List的类

// <command list> ::= <command>* end
public class CommandListNode extends Node{
    private ArrayList<Node> list = new ArrayList<>();

    @Override
    public void parse(Context context) throws ParseException {
        while (true) {
            if (context.CurrentToken() == null) {
                throw new ParseException("Missing 'end'");
            } else if (context.CurrentToken().equals("end")) {
                context.skipToken("end");
                break;
            } else {
                Node commandNode = new CommandNode();
                commandNode.parse(context);
                list.add(commandNode);
            }
        }
    }

    @Override
    public String toString() {
        return list.toString();
    }
}

4 - 对应command的类

// <command> ::= <repeat command> | <primitive command>
public class CommandNode extends Node{
    private Node node;

    @Override
    public void parse(Context context) throws ParseException {
        if (context.CurrentToken().equals("repeat")){
            node = new RepeatCommandNode();
            node.parse(context);
        } else {
            node = new PrimitiveCommandNode();
            node.parse(context);
        }
    }

    @Override
    public String toString() {
        return node.toString();
    }
}

5 - 对应repeat command的类

// <repeat command> ::= repeat <number> <command list>
public class RepeatCommandNode extends Node{
    private int number;
    private Node commandListNode;

    @Override
    public void parse(Context context) throws ParseException {
        context.skipToken("repeat");
        number = context.currentNumber();
        context.nextToken();
        commandListNode = new CommandListNode();
        commandListNode.parse(context);
    }

    @Override
    public String toString() {
        return "[repeat " + number + " " + commandListNode + "]";
    }
}

6 - 对应primitive command的类

// <primitive command> ::= go | right | left
public class PrimitiveCommandNode extends Node{
    private String name;

    @Override
    public void parse(Context context) throws ParseException {
        name = context.CurrentToken();
        context.skipToken(name);
        if (!name.equals("go") && !name.equals("right") && !name.equals("left")) {
            throw new ParseException(name + "is undefined");
        }
    }

    @Override
    public String toString() {
        return name;
    }
}

7 - 表示语法解析上下文的类

public class Context {
    private StringTokenizer tokenizer;
    private String currentToken;

    public Context(String text) {
        tokenizer = new StringTokenizer(text);
        nextToken();
    }

    public void nextToken() {
        if (tokenizer.hasMoreElements()) {
            currentToken = tokenizer.nextToken();
        } else {
            currentToken = null;
        }
    }

    public String CurrentToken() {
        return currentToken;
    }

    public void skipToken(String token) throws ParseException {
        if (!token.equals(currentToken)) {
            throw new ParseException("Warning: " + token +
                    " is expected, but " + currentToken + " is found.");
        }
        nextToken();
    }

    public int currentNumber() throws ParseException {
        int number = 0;
        try {
            number = Integer.parseInt(currentToken);
        } catch (NumberFormatException e) {
            throw new ParseException("Warning: " + e);
        }
        return number;
    }
}

8 -表示语法解析中可能会发生的异常的类

public class ParseException extends Exception{
    public ParseException(String msg) {
        super(msg);
    }
}

9 - 测试程序行为的类

public class Main {
    public static void main(String[] args) {
        String filePath = "Program文件路径";
        try {
            BufferedReader reader = new BufferedReader(new FileReader(filePath + "Program.txt"));
            String text;
            while ((text = reader.readLine()) != null) {
                System.out.println("text =\"" + text + "\"");
                Node node = new ProgramNode();
                node.parse(new Context(text));
                System.out.println("node = " +node);
            }
            reader.close();
        } catch (IOException | ParseException e) {
            e.printStackTrace();
        }
    }
}

10 - 输出示例

text ="program end"
node = [program []]
text ="program go end"
node = [program [go]]
text ="program go right go right go right go right end"
node = [program [go, right, go, right, go, right, go, right]]
text ="program repeat 4 go right end end"
node = [program [[repeat 4 [go, right]]]]
text ="program repeat 4 repeat 3 go right go left end right end end"
node = [program [[repeat 4 [[repeat 3 [go, right, go, left]], right]]]]

11 - Program.txt

program end
program go end
program go right go right go right go right end
program repeat 4 go right end end
program repeat 4 repeat 3 go right go left end right end end

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!