Newer
Older
DesignCraft / src / main / java / parser / Parser.java
package parser;

import models.objectOrientedTransfer.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.*;

public class Parser {
    public TokenStream tokenStream;

    public static final String LEFT_CURLY_BRACKET = "{";
    public static final String RIGHT_CURLY_BRACKET = "}";
    public static final String LEFT_CURLY_BRACKET_REGX = "\\{";
    public static final String RIGHT_CURLY_BRACKET_REGX = "\\}";
    public static final String LEFT_SQUARE_BRACKET = "[";
    public static final String RIGHT_SQUARE_BRACKET = "]";
    public static final String LEFT_SQUARE_BRACKET_REGX = "\\[";
    public static final String RIGHT_SQUARE_BRACKET_REGX = "\\]";
    public static final String COMMA = ",";
    public static final String COLON = ":";
    public static final String DOUBLE_QUOT = "\"";

    public Parser() {
        Scanner sc = new Scanner(System.in);
        StringBuilder s = new StringBuilder();
        System.out.println("Jsonをはりつけてください");
        while (true) {
            String S = sc.nextLine();
            if (S.equals("")) {
                break;
            }
            s.append(S);
        }
        tokenStream = new TokenStream();
        tokenStream.addLine(s.toString());
    }

    public Parser(final BufferedReader reader) {
        this.tokenStream = new TokenStream();
        try {
            String line;
            while ((line = reader.readLine()) != null) {
                tokenStream.addLine(line);
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Value getValue() {
        return parseValue(tokenStream);
    }

    public Value parseValue(TokenStream tokenStream) {
        if (tokenStream.checkNext().equals(LEFT_CURLY_BRACKET)) {
            tokenStream.next();
            JsonValue jsonValue = parseJsonValue(tokenStream);
            if (tokenStream.checkNext().equals(RIGHT_CURLY_BRACKET)) {
                tokenStream.next();
                return jsonValue;
            } else {
                throw new RuntimeException(String.valueOf(tokenStream.getLine()));
            }
        } else if (tokenStream.checkNext().equals(LEFT_SQUARE_BRACKET)) {
            tokenStream.next();
            ArrayValue arrayValue = parseArrayValue(tokenStream);
            if (tokenStream.checkNext().equals(RIGHT_SQUARE_BRACKET)) {
                tokenStream.next();
                return arrayValue;
            } else {
                throw new RuntimeException(String.valueOf(tokenStream.getLine()));
            }
        } else if (tokenStream.checkNext().equals(DOUBLE_QUOT)) {
            tokenStream.next();
            StringValue stringValue = parseStringValue(tokenStream);
            if (tokenStream.checkNext().equals(DOUBLE_QUOT)) {
                tokenStream.next();
                return stringValue;
            } else {
                throw new RuntimeException(String.valueOf(tokenStream.getLine()));
            }
        } else if (Character.isDigit(tokenStream.checkNext().charAt(0))) {
            return parseIntegerValue(tokenStream);
        }
        throw new RuntimeException(String.valueOf(tokenStream.getLine()));
    }

    public JsonValue parseJsonValue(TokenStream tokenStream) {
        JsonValue jsonValue = new JsonValue();
        //要素が0
        if (tokenStream.checkNext().equals(RIGHT_CURLY_BRACKET)) {
            return jsonValue;
        }
        while (true) {
            //key
            Value keyValue = parseValue(tokenStream);
            if (!(keyValue instanceof StringValue)) {
                throw new RuntimeException(String.valueOf(tokenStream.getLine()));
            }
            expect(tokenStream, COLON);
            tokenStream.next();//COLON
            //value
            Value value = parseValue(tokenStream);
            jsonValue.setJsonValue((StringValue) keyValue, value);
            if (!tokenStream.checkNext().equals(COMMA)) {
                break;
            }
            tokenStream.next();
        }
        return jsonValue;
    }

    public ArrayValue parseArrayValue(TokenStream tokenStream) {
        ArrayValue arrayValue = new ArrayValue();
        //要素が0
        if (tokenStream.checkNext().equals(RIGHT_SQUARE_BRACKET)) {
            return arrayValue;
        }
        while (true) {
            Value value = parseValue(tokenStream);
            arrayValue.addValue(value);
            if (!tokenStream.checkNext().equals(COMMA)) {

                break;
            }
            tokenStream.next();//COMMA
        }
        return arrayValue;
    }

    public IntegerValue parseIntegerValue(TokenStream tokenStream) {
        IntegerValue integerValue = new IntegerValue();
        StringBuilder stringBuilder = new StringBuilder();
        while (Character.isDigit(tokenStream.checkNext().charAt(0))) {
            stringBuilder.append(tokenStream.next());
        }
        integerValue.setIntValue(Integer.valueOf(stringBuilder.toString()));
        return integerValue;
    }

    public StringValue parseStringValue(TokenStream tokenStream) {
        StringValue stringValue = new StringValue();
        StringBuilder stringBuilder = new StringBuilder();
        while (!tokenStream.checkNext().equals(DOUBLE_QUOT)) {
            stringBuilder.append(tokenStream.next());
        }
        stringValue.setStringValue(stringBuilder.toString());
        return stringValue;
    }

    public void expect(TokenStream tokenStream, String expect) {
        if (!tokenStream.checkNext().equals(expect)) {
            throw new RuntimeException("expect" + expect + "but" + tokenStream.checkNext() + " line" + tokenStream.getLine());
        }
    }

    public static class TokenStream {
        private ArrayList<ArrayList<Token>> tokens = new ArrayList<>();
        private ArrayList<String> lines = new ArrayList<>();
        private int line = 0;
        private int n = 0;

        public TokenStream() {
            line = 0;
            n = 0;
        }

        public void addLine(String line) {
            lines.add(line);
            line = line.trim();
            ArrayList<Token> tokenList = splitByDoubleQuotation(line);
            tokenList = splitBy(tokenList, COMMA, COMMA);
            tokenList = splitBy(tokenList, COLON, COLON);
            tokenList = splitBy(tokenList, LEFT_CURLY_BRACKET, LEFT_CURLY_BRACKET_REGX);
            tokenList = splitBy(tokenList, RIGHT_CURLY_BRACKET, RIGHT_CURLY_BRACKET_REGX);
            tokenList = splitBy(tokenList, LEFT_SQUARE_BRACKET, LEFT_SQUARE_BRACKET_REGX);
            tokenList = splitBy(tokenList, RIGHT_SQUARE_BRACKET, RIGHT_SQUARE_BRACKET_REGX);
            tokens.add(tokenList);
        }

        private ArrayList<Token> splitBy(final List<Token> tokens, final String delimiter, final String delimiterRegx) {
            ArrayList<Token> newTokens = new ArrayList<>();
            for (Token token : tokens) {
                if (token.isAtomic()) {
                    newTokens.add(token);
                } else {
                    String[] splitTokens = token.split(delimiterRegx);
                    boolean fFirstToken = true;
                    for (String t : splitTokens) {
                        if (!fFirstToken) {
                            newTokens.add(new Token(delimiter, true));
                        }
                        if (t.length() > 0) {
                            newTokens.add(new Token(t));
                        }
                        fFirstToken = false;
                    }
                    while (token.endsWith(delimiter)) {
                        newTokens.add(new Token(delimiter, true));
                        token = token.substring(0, token.length() - 1);
                    }
                }
            }
            return newTokens;
        }

        private ArrayList<Token> splitByDoubleQuotation(String line) {
            ArrayList<Token> newTokens = new ArrayList<>();
            String[] tokens = line.split(DOUBLE_QUOT);
            boolean fFirstToken = true;
            for (int i = 0; i < tokens.length; i++) {
                String token = tokens[i];
                if (!fFirstToken) {
                    newTokens.add(new Token(DOUBLE_QUOT, true));
                }
                if (!fFirstToken || token.length() > 0) {
                    if (i % 2 == 0) {
                        for (String t : token.split("[ \t]")) {
                            newTokens.add(new Token(t));
                        }
                    } else {
                        // string literal
                        newTokens.add(new Token(token, true));
                    }
                }
                fFirstToken = false;
            }
            if (line.endsWith(DOUBLE_QUOT)) {
                newTokens.add(new Token(DOUBLE_QUOT, true));
            }
            return newTokens;
        }

        public String next() {
            if (line >= tokens.size()) return null;
            while (n >= tokens.get(line).size()) {
                line++;
                n = 0;
                if (line >= tokens.size()) return null;
            }
            String token = tokens.get(line).get(n).getTokenStr();
            n++;
            return token;
        }

        public String checkNext() {
            if (line >= tokens.size()) return null;
            while (n >= tokens.get(line).size()) {
                line++;
                n = 0;
                if (line >= tokens.size()) return null;
            }
            return tokens.get(line).get(n).getTokenStr();
        }

        public boolean hasNext() {
            if (line >= tokens.size()) return false;
            while (n >= tokens.get(line).size()) {
                line++;
                n = 0;
                if (line >= tokens.size()) return false;
            }
            return true;
        }

        public int getLine() {
            return line;
        }

        public String getSourceText(int from, int to) {
            String text = "";
            for (int l = from; l <= to; l++) {
                text += lines.get(l) + "\n";
            }
            return text;
        }
    }

    public static class Token {
        String token;
        boolean isAtomic = false;

        public Token(String token) {
            this.token = token;
        }

        public Token(String token, boolean isAtomic) {
            this.token = token;
            this.isAtomic = isAtomic;
        }

        public String getTokenStr() {
            return token;
        }

        public boolean isAtomic() {
            return isAtomic;
        }

        public String[] split(String delimiterRegx) {
            return token.split(delimiterRegx);
        }

        public boolean endsWith(String delimiter) {
            return token.endsWith(delimiter);
        }

        public int length() {
            return token.length();
        }

        public Token substring(int beginIdx, int endIdx) {
            return new Token(token.substring(beginIdx, endIdx));
        }
    }
}