对于“第二显示器”中的某些功能,您知道我正在创建一种新的高尔夫语言。对于一个或两个(@Quill),您已经从我那里听到了它的坚韧性。

A-Ray(即所谓的)是一种功能编程语言。示例程序看起来像:

 T0〜f“ Fizz”〜b“ Buzz” f {?=%t + 960 {p` fp`b} {?=%t30 {p`f}?=%t50 {p`b}} T + t1p“ 
”}


(注意物理换行;稍后会提到)

这永远是FizzBu​​zz。我确实知道可以轻松地进行深入了解,但这主要是为了解释A-Ray的工作原理。

在语言解释器中,它从索引0开始。

 T0〜f“ Fizz”〜b“ Buzz” f {?=%t + 960 {p`fp`b} {?=%t30 {p` f}?=%t50 {p`b}} T + t1p“ 
”}


它递归检查:


函数是什么->决定要执行哪个函数
需要多少个参数:


这是下一个自身的调用次数索引,它将执行




代码说明:

 T0函数'T'将临时变量设置为参数,在这种情况下,
为'0'

〜f“ Fizz”特殊〜函数是集合变量函数。
这会将'f'的值设置为“ Fizz”

〜b“ Buzz”与上次功能相同。

f {函数'f'意味着循环直到达到'b'。
花括号括住代码。

?=%t + 960 {?命令检查给定的布尔值是否为true。如果是
,它将执行第一个程序段。否则,它将
执行第二个。内部命令的细分:
=相等检查
%模运算符
t获取临时变量值
+ Add
9 Nine
6六(这是获取
'15'的更快方法,因为对于整数值
'15 ',需要4个字节('15')。
0零

分步执行该块:
=%t + 960加9和6
= %t'15'0模't'和15(假设t = 10)
由于10%15 = 10,则结果为10。
='10'0 10 == 0
(假)

p`fp`b在f和b内打印值,从而导致“ FizzBu​​zz”
} {
?=%t30 {检查是否'可以被3
p`f整除在f(“ Fizz”)
}中打印值在这里,多余的空间很重要。这意味着没有'else'
大小写。

?=%t50 {检查't'是否可被5整除
p`b在b内打印值(“嗡嗡声”)
}同样,请在此处留出多余的空间。
}

T + t1增量t
p“ \ n”这里的'\ n'应该替换为真正的换行符。
打印换行符。
}


整个功能列表在这里。

注意:此语言非常实用严格。一个额外的空间,您的程序可能会崩溃。程序中的所有字符都被视为一个函数(或一部分);因此,添加任何内容并不完全安全。

代码

(请忽略//TODO标志,它们在那里提醒我一些小错误,或者是否有等待执行的功能)

A_RayCode.java

package library;

import java.io.File;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.regex.Pattern;

public class A_RayCode {

    public static final String FILENAME_EXTENSTION = ".br";

    protected final String code;
    protected final InputIterator input;
    protected final StringBuilder output;
    protected final List<Object> memory;
    protected final MutableObject temporaryVariable;
    protected final Map<String, Object> variables;

    protected static final Map<String, Function<?>> functions = new HashMap<>();

    protected static Predicate<Character> isSeparator = new Predicate<Character>() {

        @Override
        public boolean test(Character c) {
            return c == ',' || c == ' ' || c == ';' || c == '\n';
        }

    };

    protected static Predicate<Character> isNumberSeparator = new Predicate<Character>() {

        @Override
        public boolean test(Character c) {
            return !Character.isDigit(c);
        }

    };

    static {
        // template
        functions.put("", new Function<Void>(new Type[] {},
                new RunnableFunction<Void>() {

                    @Override
                    public Void run(List<Object> memory, InputIterator input,
                            StringBuilder output,
                            MutableObject temporaryVariable,
                            Map<String, Object> variables, Object[] args) {
                        return null;
                    }

                }));
        functions.put("i", new Function<String>(new Type[] {},
                new RunnableFunction<String>() {

                    @Override
                    public String run(List<Object> memory, InputIterator input,
                            StringBuilder output,
                            MutableObject temporaryVariable,
                            Map<String, Object> variables, Object[] args) {
                        return input.nextCharsUntil(isSeparator);
                    }

                }));
        functions.put("I", new Function<BigInteger>(new Type[] {},
                new RunnableFunction<BigInteger>() {

                    @Override
                    public BigInteger run(List<Object> memory,
                            InputIterator input, StringBuilder output,
                            MutableObject temporaryVariable,
                            Map<String, Object> variables, Object[] args) {
                        return new BigInteger(input.nextCharsUntil(
                                isNumberSeparator));
                    }

                }));
        functions.put("s", new Function<Boolean>(new Type[] {},
                new RunnableFunction<Boolean>() {

                    @Override
                    public Boolean run(List<Object> memory, InputIterator input,
                            StringBuilder output,
                            MutableObject temporaryVariable,
                            Map<String, Object> variables, Object[] args) {
                        char result = input.next();
                        return result != '
package library;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;

public final class Function<T> {

    private final Type[] parameterTypes;
    private final RunnableFunction<T> function;

    public Function(Type[] parameterTypes, RunnableFunction<T> function) {
        this.parameterTypes = parameterTypes;
        this.function = function;
    }

    public T run(List<Object> memory, InputIterator input, StringBuilder output,
            MutableObject temporaryVariable, Map<String, Object> variables,
            Object[] args) throws LoopFlag {
        if (args.length != parameterTypes.length) {
            throw new IllegalArgumentException(); // TODO
        }
        for (int i = 0; i < args.length; i++) {
            switch (parameterTypes[i]) {
            case ARRAY:
                args[i] = toArray(args[i]);
                break;
            case BOOLEAN:
                args[i] = toBoolean(args[i]);
                break;
            case CHARACTER:
                args[i] = toChar(args[i]);
                break;
            case DECIMAL:
                args[i] = toDecimal(args[i]);
                break;
            case INTEGER:
                args[i] = toInteger(args[i]);
                break;
            case STRING:
                args[i] = toString(args[i]);
                break;
            case FUNCTION:
                args[i] = toFunction(args[i]);
                break;
            case OBJECT:
                args[i] = toObject(args[i]);
            }
        }
        return function.run(memory, input, output, temporaryVariable, variables,
                args);
    }

    public Type[] getParameterTypes() {
        return parameterTypes;
    }

    @SuppressWarnings("unchecked")
    public static int compare(Object object1, Object object2) throws LoopFlag {
        if (object1 == null) {
            if (object2 == null) {
                return 0;
            }
            return -1;
        }
        if (object2 == null) {
            return 1;
        }
        Type type1 = Type.getMatch(object1);
        Type type2 = Type.getMatch(object2);
        if (type1 == Type.FUNCTION) {
            object1 = ((A_RayCode) object1).run(0).result;
            type1 = Type.getMatch(object1);
        }
        if (type2 == Type.FUNCTION) {
            object2 = ((A_RayCode) object2).run(0).result;
            type2 = Type.getMatch(object2);
        }
        if (type1 == type2) {
            return ((Comparable<Object>) object1).compareTo(object2);
        }
        if (type1 == Type.BOOLEAN || type2 == Type.BOOLEAN) {
            boolean bool1 = toBoolean(object1);
            boolean bool2 = toBoolean(object2);
            if (bool1) {
                return bool2 ? 0 : 1;
            } else {
                return bool2 ? -1 : 0;
            }
        }
        // TODO

        return 0;
    }

    private Object toObject(Object object) throws LoopFlag {
        if (Type.getMatch(object) == Type.FUNCTION) {
            return ((A_RayCode) object).run();
        }
        return object;
    }

    @SuppressWarnings("unchecked")
    public static String toString(Object object) throws LoopFlag {
        Type type = Type.getMatch(object);
        if (type == null) {
            return null;
        }
        switch (type) {
        case ARRAY:
            List<Object> array = (List<Object>) object;
            Object value = array.get(0);
            if (Type.CHARACTER.isMatch(value) || Type.STRING.isMatch(value)) {
                StringBuilder result = new StringBuilder();
                for (Object item : array) {
                    result.append(item);
                }
                return result.toString();
            }
            return ((List<Object>) object).toString();
        case BOOLEAN:
            return Boolean.toString((boolean) object);
        case CHARACTER:
            return Character.toString((char) object);
        case DECIMAL:
            return ((BigDecimal) object).toPlainString();
        case INTEGER:
            return ((BigInteger) object).toString();
        case OBJECT:
            return object.toString();
        case STRING:
            return ((CharSequence) object).toString();
        case FUNCTION:
            return toString(((A_RayCode) object).run(0).result); // TODO
        }
        return null;
    }

    public static BigDecimal toDecimal(Object object) throws LoopFlag {
        Type type = Type.getMatch(object);
        if (type == null) {
            return null;
        }
        switch (type) {
        case ARRAY:
            return null;
        case BOOLEAN:
            return BigDecimal.ONE;
        case CHARACTER:
            return BigDecimal.valueOf((char) object);
        case DECIMAL:
            return (BigDecimal) object;
        case INTEGER:
            return new BigDecimal((BigInteger) object);
        case OBJECT:
            return null;
        case STRING:
            return new BigDecimal((String) object);
        case FUNCTION:
            return toDecimal(((A_RayCode) object).run(0).result); // TODO
        }
        return null;
    }

    public static Character toChar(Object object) throws LoopFlag {
        Type type = Type.getMatch(object);
        if (type == null) {
            return null;
        }
        switch (type) {
        case ARRAY:
            return null;
        case BOOLEAN:
            return (boolean) object ? 't' : 'f';
        case CHARACTER:
            return (char) object;
        case DECIMAL:
            return null;
        case INTEGER:
            BigInteger num = (BigInteger) object;
            return num.bitCount() > Character.SIZE ? null
                    : (char) num.intValue();
        case OBJECT:
            return null;
        case STRING:
            return ((CharSequence) object).charAt(0);
        case FUNCTION:
            return toChar(((A_RayCode) object).run(0).result); // TODO
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public static List<Object> toArray(Object object) {
        Type type = Type.getMatch(object);
        if (type == null) {
            return null;
        }
        List<Object> array = new ArrayList<>();
        switch (type) {
        case ARRAY:
            return ((List<Object>) object);
        case STRING:
            ((String) object).chars().forEach(e -> array.add((char) e));
            return array;
        default:
            array.add(object);
            return array;
        }
    }

    @SuppressWarnings("unchecked")
    public static Boolean toBoolean(Object object) throws LoopFlag {
        Type type = Type.getMatch(object);
        if (type == null) {
            return null;
        }
        switch (type) {
        case ARRAY:
            return ((List<Object>) object).size() != 0;
        case BOOLEAN:
            return (boolean) object;
        case CHARACTER:
            return (char) object != '
package library;

import java.util.List;
import java.util.Map;

public interface RunnableFunction<T> {

    public T run(List<Object> memory, InputIterator input, StringBuilder output,
            MutableObject temporaryVariable, Map<String, Object> variables,
            Object[] args) throws LoopFlag;

}
'; case DECIMAL: return !((BigDecimal) object).equals(BigDecimal.ZERO); case INTEGER: return !((BigInteger) object).equals(BigInteger.ZERO); case OBJECT: return object != null; case STRING: return ((CharSequence) object).length() != 0; case FUNCTION: return toBoolean(((A_RayCode) object).run(0).result); // TODO } return null; } @SuppressWarnings("unchecked") public static BigInteger toInteger(Object object) throws LoopFlag { Type type = Type.getMatch(object); if (type == null) { return null; } switch (type) { case ARRAY: return BigInteger.valueOf(((List<Object>) object).size()); case BOOLEAN: return (boolean) object ? BigInteger.ONE : BigInteger.ZERO; case CHARACTER: return BigInteger.valueOf((char) object); case DECIMAL: return ((BigDecimal) object).toBigInteger(); case INTEGER: return (BigInteger) object; case OBJECT: return null; case STRING: return new BigInteger((String) object); case FUNCTION: return toInteger(((A_RayCode) object).run(0).result); // TODO } return null; } public static A_RayCode toFunction(Object object) { if (Type.getMatch(object) == Type.FUNCTION) { return (A_RayCode) object; } return new A_RayCode("", "") { @Override protected FunctionResult run(int index) { return new FunctionResult(object, 1); } }; } @SuppressWarnings("unchecked") public static Object copy(Object object) { Type type = Type.getMatch(object); if (type == null) { return null; } else if (type == Type.ARRAY) { return new ArrayList<>(((List<Object>) object)); } return object; } }
'; } })); functions.put("S", new Function<Boolean>(new Type[] {}, new RunnableFunction<Boolean>() { @Override public Boolean run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { String result = input.nextCharsUntil(isSeparator .negate()); return !result.isEmpty(); } })); functions.put("p", new Function<Boolean>(new Type[] { Type.OBJECT }, new RunnableFunction<Boolean>() { @Override public Boolean run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { output.append(Function.toString(args[0])); return true; } })); functions.put("c", new Function<Character>(new Type[] {}, new RunnableFunction<Character>() { @Override public Character run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return input.next(); } })); functions.put("C", new Function<BigInteger>(new Type[] {}, new RunnableFunction<BigInteger>() { @Override public BigInteger run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return BigInteger.valueOf(input.next()); } })); functions.put("r", new Function<String>(new Type[] {}, new RunnableFunction<String>() { @Override public String run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return input.nextChars(input.getNumRemaining()); } })); functions.put("d", new Function<List<Object>>(new Type[] { Type.STRING }, new RunnableFunction<List<Object>>() { @Override public List<Object> run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { List<Object> result = new ArrayList<>(); new ArrayList<String>(args[0].toString().split( "(,| |;|\n)+")).stream().forEach(e -> result .add(e)); return result; } })); functions.put("a", new Function<List<Object>>(new Type[] { Type.ARRAY, Type.OBJECT }, new RunnableFunction<List<Object>>() { @Override public List<Object> run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { List<Object> result = Function.toArray(args[0]); result.add(args[1]); return result; } })); functions.put("A", new Function<List<Object>>(new Type[] { Type.ARRAY, Type.OBJECT, Type.INTEGER }, new RunnableFunction<List<Object>>() { @Override public List<Object> run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { List<Object> result = Function.toArray(args[0]); result.add(((BigInteger) args[2]).intValue(), args[1]); return result; } })); functions.put("g", new Function<Object>(new Type[] { Type.ARRAY, Type.INTEGER }, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { List<Object> result = Function.toArray(args[0]); return result.get(Function.toInteger(args[1]) .intValue()); } })); functions.put("G", new Function<Object>(new Type[] { Type.ARRAY, Type.INTEGER, Type.OBJECT }, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { List<Object> result = Function.toArray(args[0]); return result.set(Function.toInteger(args[1]) .intValue(), args[2]); } })); functions.put("f", new Function<Boolean>(new Type[] { Type.FUNCTION }, new RunnableFunction<Boolean>() { @Override public Boolean run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { boolean result = false; LoopCode code = new LoopCode(((A_RayCode) args[0]).code, memory, input, output, temporaryVariable, variables); boolean keepRunning = true; while (keepRunning) { try { keepRunning = (boolean) code.run().result; } catch (LoopFlag e) { if (e.getAction() == Action.BREAK) { keepRunning = false; } } result = true; } return result; } })); functions.put("F", new Function<Boolean>(new Type[] { Type.ARRAY, Type.FUNCTION }, new RunnableFunction<Boolean>() { @Override public Boolean run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { boolean result = false; IteratorCode code = new IteratorCode(Function.toArray( args[0]), ((A_RayCode) args[0]).code, memory, input, output, temporaryVariable, variables); boolean keepRunning = true; while (keepRunning) { try { keepRunning = (boolean) code.run().result; } catch (LoopFlag e) { if (e.getAction() == Action.BREAK) { keepRunning = false; } } result = true; } return result; } })); functions.put("?", new Function<Boolean>(new Type[] { Type.BOOLEAN, Type.FUNCTION, Type.FUNCTION }, new RunnableFunction<Boolean>() { @Override public Boolean run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { boolean result = Function.toBoolean(args[0]); A_RayCode code = (A_RayCode) (result ? args[1] : args[2]); code.run(); return result; } })); functions.put(" ", new Function<A_RayCode>(new Type[] {}, new RunnableFunction<A_RayCode>() { @Override public A_RayCode run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return new A_RayCode("", memory, input, output, temporaryVariable, variables); } })); functions.put("e", new Function<List<Object>>(new Type[] {}, new RunnableFunction<List<Object>>() { @Override public List<Object> run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return memory; } })); functions.put("E", new Function<List<Object>>(new Type[] { Type.ARRAY }, new RunnableFunction<List<Object>>() { @Override public List<Object> run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { List<Object> result = new ArrayList<>(memory); memory.clear(); memory.addAll(Function.toArray(args[0])); return result; } })); functions.put("l", new Function<BigInteger>(new Type[] { Type.ARRAY }, new RunnableFunction<BigInteger>() { @Override public BigInteger run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return BigInteger.valueOf(Function.toArray(args[0]) .size()); } })); functions.put("t", new Function<Object>(new Type[] {}, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return temporaryVariable.getValue(); } })); functions.put("T", new Function<Object>(new Type[] { Type.OBJECT }, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { Object result = temporaryVariable.getValue(); temporaryVariable.setValue(args[0]); return result == null ? new Object() : result; } })); functions.put(":", new Function<List<Object>>(new Type[] { Type.ARRAY, Type.INTEGER }, new RunnableFunction<List<Object>>() { @Override public List<Object> run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { int length = Function.toInteger(args[1]).intValue(); List<Object> result = new ArrayList<>(); getAllPerms(Function.toArray(args[0]), result, new ArrayList<>(), length, 0, 0); return result; } private void getAllPerms(List<Object> array, List<Object> fullList, List<Object> currentList, int requiredLength, int currentLength, int index) { if (requiredLength == currentLength) { fullList.add(new ArrayList<>(currentList)); currentList.remove(currentLength - 1); return; } for (int i = index, max = array.size() - (requiredLength - currentLength); i <= max; i++) { Object object = array.get(i); currentList.add(object); getAllPerms(array, fullList, currentList, requiredLength, currentLength + 1, i + 1); } if (currentLength > 0) { currentList.remove(currentLength - 1); } } })); final Comparator<Object> comparator = new Comparator<Object>() { @Override public int compare(Object object1, Object object2) { try { return Function.compare(object1, object2); } catch (LoopFlag e) { // TODO catch return 0; } } }; functions.put("m", new Function<Object>(new Type[] { Type.ARRAY }, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { List<Object> array = Function.toArray(args[0]); return Collections.min(array, comparator); } })); functions.put("M", new Function<Object>(new Type[] { Type.ARRAY }, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { List<Object> array = Function.toArray(args[0]); return Collections.max(array, comparator); } })); functions.put("b", new Function<Object>(new Type[] {}, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { throw new LoopFlag(Action.BREAK); } })); functions.put("B", new Function<Object>(new Type[] {}, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { throw new LoopFlag(Action.CONTINUE); } })); functions.put("R", new Function<Boolean>(new Type[] { Type.STRING, Type.STRING }, new RunnableFunction<Boolean>() { @Override public Boolean run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { return Function.toString(args[1]).matches(Function .toString(args[0])); } })); functions.put("u", new Function<List<Object>>(new Type[] { Type.INTEGER }, new RunnableFunction<List<Object>>() { @Override public List<Object> run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { BigInteger to = Function.toInteger(args[0]); List<Object> result = new ArrayList<>(to.intValue()); while (!to.equals(BigInteger.ONE)) { to = to.subtract(BigInteger.ONE); result.add(0, to); } return result; } })); functions.put("U", new Function<List<Object>>(new Type[] { Type.INTEGER, Type.INTEGER }, new RunnableFunction<List<Object>>() { @Override public List<Object> run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { BigInteger from = Function.toInteger(args[0]); BigInteger to = Function.toInteger(args[1]); List<Object> result = new ArrayList<>(); while (!from.equals(to)) { result.add(0, to); from = from.add(BigInteger.ONE); } return result; } })); functions.put("L", new Function<List<Object>>(new Type[] { Type.INTEGER, Type.OBJECT }, new RunnableFunction<List<Object>>() { @Override public List<Object> run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { int size = Function.toInteger(args[0]).intValue(); List<Object> list = new ArrayList<>(size); for (; size > 0; size--) { list.add(Function.copy(args[1])); } return list; } })); functions.put("N", new Function<Object>(new Type[] {}, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return null; } })); final BigInteger TWO = BigInteger.valueOf(2L); final BigInteger THREE = BigInteger.valueOf(3L); final BigInteger FOUR = BigInteger.valueOf(4L); final BigInteger FIVE = BigInteger.valueOf(5L); final BigInteger SIX = BigInteger.valueOf(6L); final BigInteger SEVEN = BigInteger.valueOf(7L); final BigInteger EIGHT = BigInteger.valueOf(8L); final BigInteger NINE = BigInteger.valueOf(9L); functions.put("0", new Function<BigInteger>(new Type[] {}, new RunnableFunction<BigInteger>() { @Override public BigInteger run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return BigInteger.ZERO; } })); functions.put("1", new Function<BigInteger>(new Type[] {}, new RunnableFunction<BigInteger>() { @Override public BigInteger run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return BigInteger.ONE; } })); functions.put("2", new Function<BigInteger>(new Type[] {}, new RunnableFunction<BigInteger>() { @Override public BigInteger run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return TWO; } })); functions.put("3", new Function<BigInteger>(new Type[] {}, new RunnableFunction<BigInteger>() { @Override public BigInteger run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return THREE; } })); functions.put("4", new Function<BigInteger>(new Type[] {}, new RunnableFunction<BigInteger>() { @Override public BigInteger run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return FOUR; } })); functions.put("5", new Function<BigInteger>(new Type[] {}, new RunnableFunction<BigInteger>() { @Override public BigInteger run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return FIVE; } })); functions.put("6", new Function<BigInteger>(new Type[] {}, new RunnableFunction<BigInteger>() { @Override public BigInteger run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return SIX; } })); functions.put("7", new Function<BigInteger>(new Type[] {}, new RunnableFunction<BigInteger>() { @Override public BigInteger run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return SEVEN; } })); functions.put("8", new Function<BigInteger>(new Type[] {}, new RunnableFunction<BigInteger>() { @Override public BigInteger run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return EIGHT; } })); functions.put("9", new Function<BigInteger>(new Type[] {}, new RunnableFunction<BigInteger>() { @Override public BigInteger run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return NINE; } })); functions.put("+", new Function<Object>(new Type[] { Type.OBJECT, Type.OBJECT }, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { Type type1 = Type.getMatch(args[0]); Type type2 = Type.getMatch(args[1]); if ((type1 == Type.DECIMAL || type1 == Type.INTEGER) && (type2 == Type.DECIMAL || type2 == Type.INTEGER)) { return addNumbers(args[0], type1, args[1], type2); } else if (type1 == Type.ARRAY) { return append(Function.toArray(args[0]), args[1]); } else if (type2 == Type.ARRAY) { return append(Function.toArray(args[1]), args[0]); } else if (type1 == Type.STRING || type2 == Type.STRING) { return concat(args[0], args[1], type2); } return concat(args[0], args[1], type2); } private Object append(List<Object> list, Object object) { list.add(object); return list; } private Object addNumbers(Object number1, Type type1, Object number2, Type type2) { return toBigDecimal(number1, type1).add(toBigDecimal( number2, type2)); } private BigDecimal toBigDecimal(Object number, Type type) { return type == Type.INTEGER ? new BigDecimal( (BigInteger) number) : (BigDecimal) number; } private String concat(Object object1, Object object2, Type type2) throws LoopFlag { return Function.toString(object1) + Function.toString( object2); } })); functions.put("-", new Function<Object>(new Type[] { Type.OBJECT, Type.OBJECT }, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { Type type1 = Type.getMatch(args[0]); Type type2 = Type.getMatch(args[1]); if ((type1 == Type.DECIMAL || type1 == Type.INTEGER) && (type2 == Type.DECIMAL || type2 == Type.INTEGER)) { return subtractNumbers(args[0], type1, args[1], type2); } else if (type1 == Type.ARRAY) { return remove(Function.toArray(args[0]), Function .toInteger(args[1])); } else if (type1 == Type.STRING && type2 == Type.CHARACTER) { return Function.toString(args[0]).replaceAll(Pattern .quote(Function.toString(args[1])), ""); } return null; } private List<Object> remove(List<Object> list, BigInteger index) { list.remove(index.intValue()); return list; } private Object subtractNumbers(Object number1, Type type1, Object number2, Type type2) { return toBigDecimal(number1, type1).subtract( toBigDecimal(number2, type2)); } private BigDecimal toBigDecimal(Object number, Type type) { return type == Type.INTEGER ? new BigDecimal( (BigInteger) number) : (BigDecimal) number; } })); functions.put("*", new Function<Object>(new Type[] { Type.OBJECT, Type.OBJECT }, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { Type type1 = Type.getMatch(args[0]); Type type2 = Type.getMatch(args[1]); if ((type1 == Type.DECIMAL || type1 == Type.INTEGER) && (type2 == Type.DECIMAL || type2 == Type.INTEGER)) { return multiplyNumbers(args[0], type1, args[1], type2); } return null; } private Object multiplyNumbers(Object number1, Type type1, Object number2, Type type2) { return toBigDecimal(number1, type1).multiply( toBigDecimal(number2, type2)); } private BigDecimal toBigDecimal(Object number, Type type) { return type == Type.INTEGER ? new BigDecimal( (BigInteger) number) : (BigDecimal) number; } })); functions.put("/", new Function<Object>(new Type[] { Type.OBJECT, Type.OBJECT }, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { Type type1 = Type.getMatch(args[0]); Type type2 = Type.getMatch(args[1]); if ((type1 == Type.DECIMAL || type1 == Type.INTEGER) && (type2 == Type.DECIMAL || type2 == Type.INTEGER)) { return divideNumbers(args[0], type1, args[1], type2); } return null; } private Object divideNumbers(Object number1, Type type1, Object number2, Type type2) { return toBigDecimal(number1, type1).divide(toBigDecimal( number2, type2)); } private BigDecimal toBigDecimal(Object number, Type type) { return type == Type.INTEGER ? new BigDecimal( (BigInteger) number) : (BigDecimal) number; } })); functions.put("^", new Function<Object>(new Type[] { Type.OBJECT, Type.OBJECT }, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { Type type1 = Type.getMatch(args[0]); Type type2 = Type.getMatch(args[1]); if ((type1 == Type.DECIMAL || type1 == Type.INTEGER) && (type2 == Type.DECIMAL || type2 == Type.INTEGER)) { return pow(args[0], type1, args[1], type2); } return null; } private Object pow(Object number1, Type type1, Object number2, Type type2) { return toBigDecimal(number1, type1).pow(toBigDecimal( number2, type2).intValue()); } private BigDecimal toBigDecimal(Object number, Type type) { return type == Type.INTEGER ? new BigDecimal( (BigInteger) number) : (BigDecimal) number; } })); functions.put("%", new Function<Object>(new Type[] { Type.OBJECT, Type.OBJECT }, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { Type type1 = Type.getMatch(args[0]); Type type2 = Type.getMatch(args[1]); if ((type1 == Type.DECIMAL || type1 == Type.INTEGER) && (type2 == Type.DECIMAL || type2 == Type.INTEGER)) { return mod(args[0], type1, args[1], type2); } return null; } private Object mod(Object number1, Type type1, Object number2, Type type2) { return toBigDecimal(number1, type1).remainder( toBigDecimal(number2, type2)); } private BigDecimal toBigDecimal(Object number, Type type) { return type == Type.INTEGER ? new BigDecimal( (BigInteger) number) : (BigDecimal) number; } })); functions.put("=", new Function<Boolean>(new Type[] { Type.OBJECT, Type.OBJECT }, new RunnableFunction<Boolean>() { @Override public Boolean run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { return Function.toString(args[0]).equals(Function .toString(args[1])); } })); functions.put("<", new Function<Boolean>(new Type[] { Type.OBJECT, Type.OBJECT }, new RunnableFunction<Boolean>() { @Override public Boolean run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { return Function.compare(args[0], args[1]) < 0; } })); functions.put(">", new Function<Boolean>(new Type[] { Type.OBJECT, Type.OBJECT }, new RunnableFunction<Boolean>() { @Override public Boolean run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { return Function.compare(args[0], args[1]) > 0; } })); functions.put("&", new Function<Object>(new Type[] { Type.OBJECT, Type.OBJECT }, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { Type type1 = Type.getMatch(args[0]); Type type2 = Type.getMatch(args[1]); if (type1 == Type.INTEGER && type2 == Type.INTEGER) { return Function.toInteger(args[0]).and(Function .toInteger(args[1])); } return Function.toBoolean(args[0]) && Function .toBoolean(args[1]); } })); functions.put("|", new Function<Object>(new Type[] { Type.OBJECT, Type.OBJECT }, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { Type type1 = Type.getMatch(args[0]); Type type2 = Type.getMatch(args[1]); if (type1 == Type.INTEGER && type2 == Type.INTEGER) { return Function.toInteger(args[0]).or(Function .toInteger(args[1])); } return Function.toBoolean(args[0]) || Function .toBoolean(args[1]); } })); functions.put("!", new Function<Object>(new Type[] { Type.OBJECT }, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) throws LoopFlag { Type type1 = Type.getMatch(args[0]); Type type2 = Type.getMatch(args[1]); if (type1 == Type.INTEGER && type2 == Type.INTEGER) { return Function.toInteger(args[0]).not(); } return !Function.toBoolean(args[0]); } })); // TODO add built-ins } public A_RayCode(String code, File input) { this(code, new ArrayList<>(), new InputIterator(input), new StringBuilder(), new MutableObject(null), new HashMap<>()); } public A_RayCode(String code, String input) { this(code, new ArrayList<>(), new InputIterator(input), new StringBuilder(), new MutableObject(null), new HashMap<>()); } protected A_RayCode(String code, List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables) { this.code = code; this.input = input; this.output = output; this.memory = memory; this.temporaryVariable = temporaryVariable; this.variables = variables; } public String runAndGetOutput() { input.reset(); output.delete(0, output.length()); memory.clear(); try { run(); } catch (LoopFlag e) { return "Loop flag not resolved\n"; } return output.toString(); } @Override public String toString() { return code; } protected FunctionResult run() throws LoopFlag { // run FunctionResult value = new FunctionResult(null, 0); FunctionResult previous = null; do { previous = value; value = run(value.currentIndex); } while (value.result != null); return previous; } protected FunctionResult run(int index) throws LoopFlag { if (index >= code.length()) { return new FunctionResult(null, index); } char c = code.charAt(index); String functionName = Character.toString(c); int endIndex = index; final String functionCode; Function<?> function; switch (c) { case '$': endIndex = code.indexOf('$', ++index); functionName = code.substring(index, endIndex); break; case '#': endIndex = code.indexOf('{', ++index); functionName = code.substring(index, endIndex); functionCode = code.substring(endIndex + 1, endIndex = indexOfMatchingClose(endIndex, '}')); function = new Function<Object>(new Type[] {}, new RunnableFunction<Object>() { @Override public Object run(List<Object> memory, InputIterator input, StringBuilder output, MutableObject temporaryVariable, Map<String, Object> variables, Object[] args) { return new A_RayCode(functionCode, memory, input, output, temporaryVariable, variables); } }); functions.put(functionName, function); return new FunctionResult(function.run(memory, input, output, temporaryVariable, variables, new Object[] {}), endIndex + 1); case ',': case '{': return new FunctionResult(new A_RayCode(code.substring(index + 1, endIndex = indexOfMatchingCloseBrace(index++)), memory, input, output, temporaryVariable, variables), endIndex + (code.charAt(endIndex) == ',' ? 0 : 1)); case '`': case '~': String name = Character.toString(code.charAt(index++)); if (name.charAt(0) == '"') { endIndex = code.indexOf('"', ++index); name = code.substring(index, endIndex++); } if (c == '`') { return new FunctionResult(variables.get(name), endIndex); } FunctionResult result = run(endIndex); index = result.currentIndex; Object value = result.result; variables.put(name, value); return new FunctionResult(true, index); case '"': endIndex = code.indexOf('"', ++index); return new FunctionResult(code.substring(index, endIndex), endIndex + 1); case '\'': endIndex = code.indexOf('\'', ++index); try { return new FunctionResult(new BigDecimal(code.substring(index, endIndex)), endIndex + 1); } catch (NumberFormatException e) { return new FunctionResult(null, endIndex + 1); } case '[': endIndex = indexOfMatchingClose(index, ']'); return new FunctionResult(createNewArray(code.substring(index + 1, endIndex++)), endIndex); } index = endIndex; function = functions.get(functionName); int numOfArguments = function.getParameterTypes().length; Object[] args = new Object[numOfArguments]; index++; for (int i = 0; i < numOfArguments; i++) { FunctionResult argResult = run(index); args[i] = argResult.result; index = argResult.currentIndex; } return new FunctionResult(function.run(memory, input, output, temporaryVariable, variables, args), index); } private List<Object> createNewArray(String substring) throws LoopFlag { String[] array = substring.split(","); List<Object> result = new ArrayList<>(); for (String string : array) { result.add(new A_RayCode(string, memory, input, output, temporaryVariable, variables).run().result); } return result; } private int indexOfMatchingClose(int index, char close) { char open = code.charAt(index); for (int i = index + 1, count = 1; i < code.length(); i++) { if (code.charAt(i) == open) { count++; } else if (code.charAt(i) == close) { count--; } if (count == 0) { return i; } } return -1; // TODO error } private int indexOfMatchingCloseBrace(int index) { return Math.min(indexOfMatchingClose(index, ','), indexOfMatchingClose( index, '}')); } protected static class FunctionResult { protected final Object result; protected final int currentIndex; protected FunctionResult(Object result, int currentIndex) { this.result = result; this.currentIndex = currentIndex; } } }


Function.java

package library;

public enum Action {
    BREAK, CONTINUE
}


RunnableFunction.java

package library;

import java.io.File;
import java.util.Iterator;
import java.util.function.Predicate;

public class InputIterator implements Iterator<Character> {

    private final String input;
    private final int length;
    private int index = 0;

    public InputIterator(File input) {
        this(FileUtils.readAll(input));
    }

    public InputIterator(String input) {
        this.input = input;
        this.length = this.input.length();
    }

    @Override
    public boolean hasNext() {
        return length >= index;
    }

    @Override
    public Character next() {
        return index >= length ? '
package library;

import java.util.List;
import java.util.Map;

public class IteratorCode extends LoopCode {

    public IteratorCode(List<Object> array, String code, List<Object> memory,
            InputIterator input, StringBuilder output,
            MutableObject temporaryVariable, Map<String, Object> variables) {
        super(code, memory, input, output, temporaryVariable, variables);
        functions.put(LoopCode.X, new Function<Object>(new Type[] {},
                new RunnableFunction<Object>() {

                    @Override
                    public Object run(List<Object> memory, InputIterator input,
                            StringBuilder output,
                            MutableObject temporaryVariable,
                            Map<String, Object> variables, Object[] args) {
                        return array.get(count.intValue());
                    }

                }));
    }

}
' : input.charAt(index++); } public String nextChars(int numOfChars) { if (index + numOfChars > length) { numOfChars = length - index; } String result = input.substring(index, index + numOfChars); index += numOfChars; return result; } public String nextCharsUntil(Predicate<Character> predicate) { if (!hasNext()) { return ""; } int endIndex = index; while (endIndex < length && !predicate.test(input.charAt(endIndex))) { endIndex++; } String result = input.substring(index, endIndex); index = endIndex; while (index != length && predicate.test(input.charAt(index))) { index++; } return result; } public int getNumRemaining() { return length - index; } public void reset() { index = 0; } }


Action.java

package library;

import java.math.BigInteger;
import java.util.List;
import java.util.Map;

public class LoopCode extends A_RayCode {

    protected static final String X = "x";

    protected BigInteger count = BigInteger.ZERO;
    protected boolean out = false;

    private final Function<?> oldXFunction;

    public LoopCode(String code, List<Object> memory, InputIterator input,
            StringBuilder output, MutableObject temporaryVariable,
            Map<String, Object> variables) {
        super(code, memory, input, output, temporaryVariable, variables);
        oldXFunction = functions.get(X);
        functions.put(X, new Function<BigInteger>(new Type[] {},
                new RunnableFunction<BigInteger>() {

                    @Override
                    public BigInteger run(List<Object> memory,
                            InputIterator input, StringBuilder output,
                            MutableObject temporaryVariable,
                            Map<String, Object> variables, Object[] args) {
                        return count;
                    }

                }));
    }

    @Override
    public FunctionResult run() throws LoopFlag {
        // run
        FunctionResult value = new FunctionResult(null, 0);
        do {
            value = run(value.currentIndex);
        } while (value.result != null);
        count = count.add(BigInteger.ONE);
        if (out) {
            functions.put(X, oldXFunction);
        }
        return new FunctionResult(!out, value.currentIndex);
    }

    @Override
    protected FunctionResult run(int index) throws LoopFlag {
        if (index >= code.length()) {
            return new FunctionResult(null, index);
        }
        switch (code.charAt(index)) {
        case 'b':
            out = true;
        case 'B':
            index = code.length();
        }
        return super.run(index); // TODO args
    }

}


InputIterator.java

package library;

public class LoopFlag extends Exception {

    private static final long serialVersionUID = 2275239478370374878L;

    private final Action action;

    public LoopFlag(Action action) {
        this.action = action;
    }

    public Action getAction() {
        return action;
    }

}


IteratorCode.java

package library;

import java.math.BigDecimal;
import java.math.BigInteger;

public enum Type {

    INTEGER(BigInteger.class), DECIMAL(BigDecimal.class), STRING(
            CharSequence.class), CHARACTER(Character.class), BOOLEAN(
                    Boolean.class), ARRAY(ArrayList.class), FUNCTION(
                            A_RayCode.class), OBJECT(Object.class);

    private final Class<?> c;

    private <T> Type(Class<T> c) {
        this.c = c;
    }

    public boolean isMatch(Object object) {
        switch (this) {
        case ARRAY:
        case BOOLEAN:
        case CHARACTER:
        case DECIMAL:
        case INTEGER:
        case STRING:
        case FUNCTION:
        case OBJECT:
            return c.isInstance(object);
        }
        return false;
    }

    public Class<?> getClassOfType() {
        return c;
    }

    public static Type getMatch(Object object) {
        for (Type type : Type.values()) {
            if (type.isMatch(object)) {
                return type;
            }
        }
        return OBJECT;
    }

}


LoopCode.java

q4312078q

LoopFlag.java

q4312078q

Type.java

q4312078q

剩余的库类和GUI类在GitHub上可用(对于一个帖子来说太多了)。

关注点:


我的结构好吗?
我是否没有发现小错误?
还有其他什么吗?


评论

你现在是我们之一。

编写好代码以帮助编写坏代码?

据我了解,您正在为功能语言实现解释器。我知道了吗?

@oopexpert是的。

我认为这是您的语言只能解析一位数字的错误(或至少是一项功能)

#1 楼

匿名类

在HashMap中注册对象(函数)及其字符表示是可以的。我在这里所缺少的是具有函数名称的结构。我会将匿名类解析为命名类。

避免静态初始化程序

由于解析本身是一件复杂的事情,因此您应该使它周围的事情尽可能简单。当加载相应的类时,静态初始化程序在控件之外执行。我并不是说永远不要使用静态初始化器。但是在业务环境中,您应该依赖对象中的构造函数和方法作为执行代码的主要方式。

多个解析概念

您将遵循不同的解析概念和解析遍布各处(继承,不同的方法和语义上不同的类)。


在匿名函数中,您解析参数:“ input.nextCharsUntil(Predicate)”
在内部“ A_RayCode.run(int index)”方法,您正在解析方括号中的内容
在LoopCode中,您将在调用super之前在覆盖的方法“ run(int index)”中进行解析。

我希望尽可能少地分析概念。通过一个通用的解析概念来协调您的解析。我建议在这里使用一种策略模式。

较长的函数名称

您的概念不考虑名称具有多个字符的函数。引入此类功能后,您将不得不考虑所有问题。即使这种人工语言似乎具有很短的函数名(我猜至少有一个),在现实世界中解析也可能是一个严重的问题。您已关闭以进行扩展。

职责

解析职责是分开的,正如我提到的,您有不同的解析概念。此外,您还混合了解析和执行。

我建议准备将已解析的参数提供给函数,而不要让函数本身解析其参数。

单独考虑以下问题:


解析
解释
执行

当前您无法执行函数无需解析。去耦以不同的方式提供帮助,例如进行测试或重新使用。

解析的示例结构

我仅提供一个解析示例,因为这通常是最复杂的问题。

    functions.put("C", new Function<BigInteger>(new Type[] {},
            new RunnableFunction<BigInteger>() {

                @Override
                public BigInteger run(List<Object> memory,
                        InputIterator input, StringBuilder output,
                        MutableObject temporaryVariable,
                        Map<String, Object> variables, Object[] args) {
                    return BigInteger.valueOf(input.next() /*parsing*/) /*execution*/;
                }

            }));


该解析器搜索数字并返回它们。空格分隔数字,因为允许空格多次出现。如果输入字母数字字符,则计算机将进入“错误状态”。

本示例使用状态模式来协调解析。这对应于应该在之前创建的状态图(如UML状态机)。

解释

解释器将由解析器中的新语义元素通知并决定何时将函数和参数放在一起,以便它们可以执行。这可以通过标准的侦听器模式来完成。解释器在解析器处注册为侦听器,因此它将获取可用的功能和参数(正确解析)。
在提供的解析器示例中,我们必须通知侦听器是否可以确定新的数字:

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;

public class NumberParser {


    public static void main(String[] args) {

        List<BigInteger> parse = new NumberParser("   10   22  32  ").parse();

        for (BigInteger bigInteger : parse) {
            System.out.println(bigInteger);
        }

    }


    private List<BigInteger> numbers;


    private final StringBuffer stringToParse;
    private final StringBuffer buffer;


    private State state;


    public NumberParser(String string) {
        this.stringToParse = new StringBuffer(string);
        this.buffer = new StringBuffer();
        this.setState(new Unknown());
    }


    private boolean hasCurrentChar() {
        return this.stringToParse.length() > 0;
    }


    private char removeCurrentChar() {
        if (hasCurrentChar()) {
            char ch = this.stringToParse.charAt(0);
            this.stringToParse.deleteCharAt(0);
            return ch;
        } else {
            throw new NoSuchElementException();
        }
    }

    private char currentChar() {
        if (this.stringToParse.length() > 0) {
            return this.stringToParse.charAt(0);
        } else {
            throw new NoSuchElementException();
        }
    }


    private void clearBuffer() {
        buffer.setLength(0);
    }


    private void recognizeNumber() {
        numbers.add(new BigInteger(buffer.toString()));
        clearBuffer();
    }


    public List<BigInteger> parse() {

        if (numbers == null) {

            this.numbers = new ArrayList<>();

            while (!(getState() instanceof End)) {
                getState().parse();
            }

        }

        return this.numbers;

    }


    private State getState() {
        return state;
    }


    private void setState(State state) {
        System.out.println(state.getStateInfo());
        this.state = state;
    }


    private interface State {
        public String getStateInfo();
        public void parse();
    }


    private interface End extends State {
    }


    private class Error implements End {

        @Override
        public String getStateInfo() {
            return "Something went wrong ...";
        }

        @Override
        public void parse() {
        }

    }


    private class NoMoreChars implements End {

        @Override
        public String getStateInfo() {
            return "No chars left.";
        }

        @Override
        public void parse() {
        }

    }


    private class RemoveWhiteSpaces implements State {

        @Override
        public String getStateInfo() {
            return "Removing white spaces.";
        }

        @Override
        public void parse() {

            if (hasCurrentChar()) {

                if (Character.isWhitespace(currentChar())) {
                    removeCurrentChar();
                } else {
                    setState(new Unknown());
                }

            } else {
                setState(new NoMoreChars());
            }

        }

    }


    private class Number implements State {

        @Override
        public String getStateInfo() {
            return "Parse digits.";
        }

        @Override
        public void parse() {

            if (hasCurrentChar()) {

                if (Character.isDigit(currentChar())) {
                    buffer.append(currentChar());
                    removeCurrentChar();
                } else {
                    recognizeNumber();
                    setState(new Unknown());
                }

            } else {
                recognizeNumber();
                setState(new NoMoreChars());
            }

        }

    }


    private class Unknown implements State {

        @Override
        public String getStateInfo() {
            return "Search ...";
        }

        @Override
        public void parse() {

            if (hasCurrentChar()) {

                if (Character.isWhitespace(currentChar())) {
                    setState(new RemoveWhiteSpaces());
                } else if (Character.isDigit(currentChar())){
                    setState(new Number());
                } else {
                    setState(new Error());
                }

            } else {
                setState(new NoMoreChars());
            }

        }

    }

}