编译原理——实现简单json解析器

一、词法分析阶段

1创建Tok类,记录Token的类型以及将每个转换为相应的字符串值。

package Lex;

/**
 * Created by think on 2017/6/8.
 */
public class TOK {
    //Tok类型
    public static final int OBJB = 0;
    public static final int OBJE = 1;
    public static final int ARRB = 2;
    public static final int ARRE = 3;
    public static final int DESC = 4;
    public static final int SPLIT = 5;
    public static final int STR = 6;
    public static final int NUM = 7;
    public static final int TRUE = 8;
    public static final int FALSE = 9;

    public static final int NULL = 10;
    public static final int BGN = 11;
    public static final int EOF = 12;


     //并存储tok类型的个数
    public static final int TOK_NUM = 13;

   //每个Tok类型对应的字符串类型
    public static final String[] CAST_STRS = { "OBJB","OBJE", "ARRB","ARRE","DESC", "SPLIT",
            "STR", "NUM","TRUE", "FALSE",  "NULL","BGN","EOF" };


   //每个Tok类型对应的实际字符串
    public static final String[] CAST_LOCAL_STRS = { "{", "}", "[", "]",
            ":", ",", "s", "n", "true","false",  "null", "开始", "结束" };
    //返回Tok类型字符串
    public static String castTokTypeStr(int type) {
        if (type < 0 || type > TOK_NUM)
            return "undefine";
        else
            return CAST_STRS[type];
    }

    //返回Tok类型实际字符串
    public static String castTokTypeLocalStr(int type) {
        if (type < 0 || type > TOK_NUM)
            return "undefine";
        else
            return CAST_LOCAL_STRS[type];
    }
}

2、创建Token类,作为词法分析的结果,有type属性和value属性,其中只有Num类型和STR类型有真正的value值,其余的只有类型。

package Lex;

/**
 * Created by think on 2017/6/8.
 */
public class Token {

    public static final Token DESC = new Token(TOK.DESC);
    public static final Token SPLIT = new Token(TOK.SPLIT);
    public static final Token ARRB= new Token(TOK.ARRB);
    public static final Token OBJB = new Token(TOK.OBJB);
    public static final Token ARRE = new Token(TOK.ARRE);
    public static final Token OBJE = new Token(TOK.OBJE);
    public static final Token FALSE = new Token(TOK.FALSE);
    public static final Token TRUE = new Token(TOK.TRUE);
    public static final Token NULL = new Token(TOK.NULL);
    public static final Token BGN = new Token(TOK.BGN);
    public static final Token EOF = new Token(TOK.EOF);

    // 从TOK类中定义的类型
    private Integer type;
    // 该tok的值
    private String value;
    //行号
    private int lineNum;
    //开始列号
    private int beginCol;
    //结束列号
    private int endCol;

    public Token(int type) {
        this.type = type;
        this.value = null;
    }

    public Token(int type, String value) {
        this.type = type;
        this.value = value;
    }

    public int getType() {
        return type;
    }
    public void setType(int type) {
        this.type = type;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public int getLineNum(){
        return lineNum;
    }
    public void setLineNum(int lineNum) {
        this.lineNum = lineNum;
    }
    public int getBeginCol() {
        return beginCol;
    }
    public int getEndCol() {
        return endCol;
    }
    public void setEndCol(int endCol){
        this.endCol=endCol;
    }
    public void setBeginCol(int beginCol) {
        this.beginCol = beginCol;
    }
    public Object getRealValue(){
        Object curValue = null;
        switch(this.getType()){
            case TOK.TRUE:
                curValue = true;
                break;
            case TOK.FALSE:
                curValue = false;
                break;
            case TOK.NULL:
                curValue = null;
                break;
            case TOK.NUM:
                if(value.indexOf('.')>=0){
                    curValue = Double.parseDouble(value);
                }else{
                    curValue = Integer.parseInt(value);
                }
                break;
            case TOK.STR:
                curValue = "\""+this.getValue()+"\"";
                break;
        }
        return curValue;
    }

    //输出被中括号括起来的token值
    public String toString() {
        if (this.type != 6&&this.type!=7) {
            return "[" + TOK.castTokTypeStr(this.type) + "]";
        } else {
            return "[" + TOK.castTokTypeStr(this.type) + ":" + this.value
                    + "]";
        }
    }
    //输出每个Token实际对应的值
    public String toLocalString() {
        if (this.type != 6&&this.type!=7) {
            return   TOK.castTokTypeLocalStr(this.type);
        } else if(this.type == 6){
            return "\""+this.value + "\"";
        }else{
            return this.value;
        }
    }
}

3、创建JsonLex类进行词法分析,其中next()用来获取下一个的tokennextchar()用于获取下一个的字符,revertchar()用于回退一个字符,其余进行词法解析。getWriteStr()用来把词法分析的json字符串按照json文件的格式进行输出。

package Lex;
import MyException.UnexpectedException;

/**
 * Created by think on 2017/6/8.
 */
public class JsonLex {
    // 当前行号
    private int lineNum = 0;
    //每个Token的开始位置
    private int startCol = 0;
    // 当前字符游标
    private int cur = -1;
    // 保存当前要解析的字符串
    private String str = null;
    // 保存当前要解析的字符串的长度
    private int len = 0;
    //private int startLine=0;
    //private int lastEndCol;


    public JsonLex(String str) {
        if (str == null)
            throw new NullPointerException("词法解析构造函数不能传递null");
        this.str = str;
        this.len = str.length();
       //this.lastEndCol=0;
        this.startCol = 0;
        this.cur = -1;
        this.lineNum = 0;
    }

    public boolean isLetterUnderline(char c) {
        return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_');
    }

    public boolean isNumLetterUnderline(char c) {
        return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
                || (c >= '0' && c <= '9') || c == '_');
    }
    public boolean isNum(char c) {
        return (c >= '0' && c <= '9');
    }

    public boolean isPunctuation(char c){
        return (c==','||c=='.'||c=='-'||c=='('||c==')');
    }

    public static boolean isSpace(char c) {
        return (c == ' ' || c == '\t' || c == '\n'||c=='\r');
    }

    private void checkEnd() throws UnexpectedException {
        if (cur >= len - 1) {
            throw generateUnexpectedException("未预期的结束,字符串未结束");
        }
    }

    public UnexpectedException generateUnexpectedException(String str) {
        return new UnexpectedException(lineNum,startCol, str);
    }
   //获取下一个字符
    private char nextChar() {
        if (cur >= len - 1) {
            return 0;
        }
        cur++;
        startCol++;
        char c = str.charAt(cur);
        if (c == '\n'||c=='\r') {
            if(str.charAt(cur+1)!='\n'&&str.charAt(cur+1)!='\r'){
            lineNum++;
            //lastEndCol=startCol;
            startCol = 0;
            }
        }
        return c;
    }

   //回退一个字符
    private int revertChar() {
        if (cur <= 0) {
            return 0;
        }
        int rcur = cur--;
        char c = str.charAt(rcur);
        if (c == '\n') {
            lineNum--;
            //startCol=lastEndCol;
        }
        return rcur;
    }

    //解析获取字符串的值
    private String getStrValue(char s) throws UnexpectedException {
        int start = cur;
        char c;
        c=nextChar();
        while (c!=0) {
            if (isNumLetterUnderline(c)||isSpace(c)||isPunctuation(c)) {
                c = nextChar();
            } else if (s == c) {
                return str.substring(start + 1, cur);
            } else {
                throw generateUnexpectedException("字符串,需要\"结尾");

            }
        }

        return null;
    }
    //解析获取数字的值
    private String getNumValue() throws UnexpectedException {
        int start = cur;
        boolean hasPoint=false;
        boolean hasE=false;
        char c;
        while ((c=nextChar())!=0) {
            if(isNum(c)){}
            else if(c=='.'){
              if(hasPoint){
                  throw generateUnexpectedException("数字错误,多余的.");
              }else {
                  hasPoint=true;
              }
          }else if(c=='e'){
              if (hasE){
                  throw generateUnexpectedException("数字错误,多余的e");
              }else{
                  hasE=true;
              }
          }else if (isLetterUnderline(c)||c==' '){
                throw generateUnexpectedException("数字错误,未知标识符");
            }else {
                return str.substring(start, revertChar());
            }


        }
        checkEnd();
        return null;
    }
    //解析获取false true,null类型的Token
    private Token getDefToken() throws UnexpectedException {
        int start = cur;
        char c;
        while ((c = nextChar()) != 0) {
            if(cur==1245){
                System.out.print(1546);
            }
            if (!isNumLetterUnderline(c)) {
                String value = str.substring(start, revertChar());
                if ("true".equals(value)) {
                    return Token.TRUE;
                } else if ("false".equals(value)) {
                    return Token.FALSE;
                } else if ("null".equals(value)) {
                    return Token.NULL;
                } else {
                   throw generateUnexpectedException("错误标识符");
                }
            }
        }
        checkEnd();
        return null;
    }
    //解析获取标点符号的Token
    public Token parseSymbol(char c) {
        switch (c) {
            case '[':
                return Token.ARRB;
            case ']':
                return Token.ARRE;
            case '{':
                return Token.OBJB;
            case '}':
                return Token.OBJE;
            case ',':
                return Token.SPLIT;
            case ':':
                return Token.DESC;
        }
        return null;
    }

    //获取下一个Token
    public Token next() throws UnexpectedException {
        if (lineNum == 0) {
            lineNum = 1;
            return Token.BGN;
        }

        char c;
        while ((c = nextChar()) != 0) {
            if (c == '\"') {
                Token tempToken = new Token(TOK.STR);
                tempToken.setLineNum(lineNum);
                tempToken.setBeginCol(startCol);
                tempToken.setValue(getStrValue(c));
                tempToken.setEndCol(startCol);
                return tempToken;
            } else if (isLetterUnderline(c)) {
                Token tempToken= getDefToken();
                tempToken.setLineNum(lineNum);
                tempToken.setBeginCol(startCol-TOK.castTokTypeStr(tempToken.getType()).length());
                tempToken.setEndCol(startCol);
                return tempToken;
            } else if (isNum(c) || c == '-') {
                Token tempToken = new Token(TOK.NUM);
                tempToken.setLineNum(lineNum);
                tempToken.setBeginCol(startCol);
                tempToken.setValue(getNumValue());
                tempToken.setEndCol(startCol);
                return tempToken;
            } else if (isSpace(c)) {
                continue;
            } else {
                Token tempToken = parseSymbol(c);
                tempToken.setLineNum(lineNum);
                tempToken.setBeginCol(startCol);
                tempToken.setEndCol(startCol);
                return tempToken;
            }
        }
        if (c == 0) {
            return Token.EOF;
        }
        return null;
    }
    //获取待解析json字符串的标准格式
    public String getWriteStr() throws UnexpectedException {
        Token tk;
        String str = "";
        int goTimes = 0;
        this.next();
        while ((tk = this.next()) != Token.EOF) {
            if (tk.toLocalString() == "{" || tk.toLocalString() == "[") {
                str = str + tk.toLocalString();
                goTimes++;
                str = str + "\r" + "\n";
                for (int i = 0; i < goTimes * 4; i++) {
                    str = str + " ";
                }

            } else if (tk.toLocalString() == ",") {
                str = str + tk.toLocalString();
                str = str + "\r" + "\n";
                for (int i = 0; i < goTimes * 4; i++) {
                    str = str + " ";
                }
            } else if (tk.toLocalString() == "}" || tk.toLocalString() == "]") {
                goTimes--;
                str = str + "\r" + "\n";
                for (int i = 0; i < goTimes * 4; i++) {
                    str = str + " ";
                }
                str = str + tk.toLocalString();
            } else {
                str = str + tk.toLocalString();
            }
        }
        return str;
    }

}

4、创建UnexpectedException进行错误抛出。

package MyException;

/**
 * Created by think on 2017/6/8.
 */
public class UnexpectedException extends Exception {

    private Integer lineNum = null;

    private Integer colNum = null;

    private String desc = null;

    private Throwable cause = null;

    public UnexpectedException() {
        super();
    }

    public UnexpectedException(Integer lineNum, Integer colNum, String message) {

        this.colNum = colNum;
        this.lineNum = lineNum;
        this.desc = message;
    }

    public String getMessage() {
        return "line:" + lineNum + ",column:" + colNum
                + "]" + desc + (cause == null ? "" : cause.toString());
    }

    public String getLocalMessage() {
        return getMessage();
    }

    public String toString() {
        return getMessage();
    }
}

    在词法分析阶段,可以完成词法错误的识别,如字符串没有用结束,数字的浮点型和科学计数法行不对,truefalsenull的拼写错误等。

二、语法分析阶段

1、根据用LR分析法进行分析,发现Json语法为LR(1)文法。

构造LALR1)项目自动机得如下图:(这个自己画一遍吧,比较复杂,画的很乱)

 

求得LALR1)分析表

状态

Action

GoTo

{

}

[

]

:

,

s

n

#

TRUE

FALSE

null

J

O

M

P

A

E

V

0

s4

 

s21

 

 

 

 

 

 

 

 

 

1

2

 

 

3

 

 

1

 

 

 

 

 

 

 

 

r0

 

 

 

 

 

 

 

 

 

 

2

 

 

 

 

 

 

 

 

r1

 

 

 

 

 

 

 

 

 

 

3

 

 

 

 

 

 

 

 

r2

 

 

 

 

 

 

 

 

 

 

4

 

s5

 

 

 

 

s11

 

 

 

 

 

 

 

6

8

 

 

 

5

 

r3

 

r3

 

r3

 

 

r3

 

 

 

 

 

 

 

 

 

 

6

 

s7

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

7

 

r4

 

r4

 

r4

 

 

r4

 

 

 

 

 

 

 

 

 

 

8

 

r5

 

 

 

s9

 

 

 

 

 

 

 

 

 

 

 

 

 

9

 

 

 

 

 

 

s11

 

 

 

 

 

 

 

10

8

 

 

 

10

 

r6

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

11

 

 

 

 

s12

 

 

 

 

 

 

 

 

 

 

 

 

 

 

12

s4

 

s21

 

 

 

s16

s17

 

s18

s19

s20

 

14

 

 

15

 

13

13

 

r7

 

 

 

r7

 

 

 

 

 

 

 

 

 

 

 

 

 

14

 

r12

 

r12

 

r12

 

 

 

 

 

 

 

 

 

 

 

 

 

15

 

r13

 

r13

 

r13

 

 

 

 

 

 

 

 

 

 

 

 

 

16

 

r14

 

r14

 

r14

 

 

 

 

 

 

 

 

 

 

 

 

 

17

 

r15

 

r15

 

r15

 

 

 

 

 

 

 

 

 

 

 

 

 

18

 

r16

 

r16

 

r16

 

 

 

 

 

 

 

 

 

 

 

 

 

19

 

r17

 

r17

 

r17

 

 

 

 

 

 

 

 

 

 

 

 

 

20

 

r18

 

r18

 

r18

 

 

 

 

 

 

 

 

 

 

 

 

 

21

S4

 

 

s22

 

 

s16

s17

 

s18

s19

s20

 

14

 

 

15

23

25

22

 

r8

 

r8

 

r8

 

 

r8

 

 

 

 

 

 

 

 

 

 

23

 

 

 

s24

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

24

 

r9

 

r9

 

r9

 

 

r9

 

 

 

 

 

 

 

 

 

 

25

 

 

 

r10

 

s26

 

 

 

 

 

 

 

 

 

 

 

 

 

26

s4

 

s21

 

 

 

s16

s17

 

s18

s19

s20

 

14

 

 

15

27

25

27

 

 

 

r11

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

test/a/true.json进行分析得

SYMBOL

INPUT

ACTION

GOTO

#

{

S4

 

#{

s

s11

 

#{s

:

s12

 

#{s:

[

s21

 

#{s:[

{

s4

 

#{s:[{

s

s11

 

#{s:[{s

:

s12

 

#{s:[{s:

s

s16

 

#{s:[{s:s

,

r14

13

#{s:[{s:v

,

r7

8

#{s:[{p

,

s9

 

#{s:[{p,

s

s11

 

#{s:[{p,s

:

S12

 

#{s:[{p,s:

s

s16

 

#{s:[{p,s:s

}

r14

13

#{s:[{p,s:v

}

r7

8

#{s:[{p,p

}

r5

10

#{s:[{p,m

}

r6

6

#{s:[{m

}

s7

 

#{s:[{m}

,

r4

14

#{s:[o

,

r12

25

#{s:[v

,

s26

 

#{s:[v,

{

S4

 

#{s:[v,{

s

s11

 

#{s:[v,{s

:

s12

 

#{s:[v,{s:

s

s16

 

#{s:[v,{s:s

,

r14

13

#{s:[v,{s:v

,

r7

8

#{s:[v,{p

,

s9

 

#{s:[v,{p,

s

s11

 

#{s:[v,{p,s

:

s12

 

#{s:[v,{p,s:

s

s16

 

#{s:[v,{p,s:s

}

R14

13

#{s:[v,{p,s:V

}

r7

 

#{s:[v,{p,p

}

r5

10

#{s:[v,{p,m

}

r6

6

#{s:[v,{m

}

s7

 

#{s:[v,{m}

]

r4

14

#{s:[v,o

]

r12

25

#{s:[v,v

]

r10

27

#{s:[v,E

]

r11

23

#{s:[E

]

s24

 

#{s:[E]

}

r9

 

#{s:A

}

 

 

 

 

 

 

2、构建StateClass类,创建inputChar数组,存放分析表的终结符和非终结符,创建stateTable数字,存放分析表的值。创建production二维数组,存放产生式,其中数组的第一个值为左部,第二个值为右部。

package Parser;

import java.util.*;

/**
 * Created by think on 2017/6/9.
 */
public class StateClass {
    //分析表中的所有终结符和非终结符
    public static final ArrayList inputChar =new ArrayList<>();
    static {
        inputChar.add("{");
        inputChar.add("}");
        inputChar.add("[");
        inputChar.add("]");
        inputChar.add(":");
        inputChar.add(",");
        inputChar.add("s");
        inputChar.add("n");
        inputChar.add("#");
        inputChar.add("true");
        inputChar.add("false");
        inputChar.add("null");
        inputChar.add("J");
        inputChar.add("O");
        inputChar.add("M");
        inputChar.add("P");
        inputChar.add("A");
        inputChar.add("E");
        inputChar.add("V");
    }

    //分析表
    public static final String stateTable[][]={
            //     {	}  [	]  :  ,	 s	n  # TRUE FALSE null J O M P A  E V
           /*0*/ {"S4","","S21","","","","","","","","","","1","2","","","3","",""},
           /*1*/ {"","","","","","","","","R0","","","","","","","","","",""},
           /*2*/ {"","","","","","","","","R1","","","","","","","","","",""},
           /*3*/ {"","","","","","","","","R2","","","","","","","","","",""},
           /*4*/ {"","S5","","","","","S11","","","","","","","","6","8","","",""},
           /*5*/ {"","R3","","R3","","R3","","","R3","","","","","","","","","",""},
           /*6*/ {"","S7","","","","","","","","","","","","","","","","",""},
           /*7*/ {"","R4","","R4","","R4","","","R4","","","","","","","","","",""},
           /*8*/ {"","R5","","","","S9","","","","","","","","","","","","",""},
           /*9*/ {"","","","","","","S11","","","","","","","","10","8","","",""},
           /*10*/ {"","R6","","","","","","","","","","","","","","","","",""},
           /*11*/ {"","","","","S12","","","","","","","","","","","","","",""},
           /*12*/  {"S4","","S21","","","","S16","S17","","S18","S19","S20","","14","","","15","","13"},
           /*13*/ {"","R7","","","","R7","","","","","","","","","","","","",""},
           /*14*/ {"","R12","","R12","","R12","","","","","","","","","","","","",""},
           /*15*/ {"","R13","","R13","","R13","","","","","","","","","","","","",""},
           /*16*/ {"","R14","","R14","","R14","","","","","","","","","","","","",""},
           /*17*/ {"","R15","","R15","","R15","","","","","","","","","","","","",""},
           /*18*/ {"","R16","","R16","","R16","","","","","","","","","","","","",""},
           /*19*/ {"","R17","","R17","","R17","","","","","","","","","","","","",""},
           /*20*/ {"","R18","","R18","","R18","","","","","","","","","","","","",""},
           /*21*/ {"S4","","","S22","","","S16","S17","","S18","S19","S20","","14","","","15","23","25"},
           /*22*/ {"","R8","","R8","","R8","","","R8","","","","","","","","","",""},
           /*23*/ {"","","","S24","","","","","","","","","","","","","","",""},
           /*24*/ {"","R9","","R9","","R9","","","R9","","","","","","","","","",""},
           /*25*/ {"","","","R10","","S26","","","","","","","","","","","","",""},
           /*26*/ {"S4","","S21","","","","S16","S17","","S18","S19","S20","","14","","","15","27","25"},
           /*27*/ {"","","","R11","","","","","","","","","","","","","","",""},
    };
    //产生式
    public static final String[][] production={
            {"S","J"},{"J","O"},{"J","A"},{"O","{}"},{"O","{M}"},{"M","P"},{"M","P,M"},
            {"P","s:V"},{"A","[]"}, {"A","[E]"},{"E","V"},{"E","V,E"},{"V","O"},{"V","A"},
            {"V","s"},{"V","n"}, {"V","t"},{"V","f"},{"V","u"}
    };
}

3、创建stateMachine类进行最终的语法分析。Parse()用于解析json字符串的每个token,如果解析成功,则返回true。在analyse()进行每个token的字符串值的解析。

package Parser;

import Lex.JsonLex;
import Lex.TOK;
import Lex.Token;
import MyException.UnexpectedException;
import java.util.Stack;

/**
 * Created by think on 2017/6/10.
 */
public class StateMachine {
    private JsonLex lex = null;
    private Integer status = null;
    //符号栈
    private Stack stateStack=new Stack<>();
    //符号栈
    private Stack symbolStack=new Stack<>();

    public StateMachine(String str){
        stateStack.push(0);
        symbolStack.push("#");
        if (str == null)
            throw new NullPointerException("语法解析构造函数不能传递null");
        lex = new JsonLex(str);
    }

    public boolean isNum(char c) {
        return (c >= '0' && c <= '9');
    }
    //解析每个Token的字符串值
    public boolean analyse(int lineNum,int colNum,String c) throws UnexpectedException {
        status = stateStack.peek();
        String tempStr= StateClass.stateTable[status][StateClass.inputChar.indexOf(c)];
        if(tempStr==""){
            throw new UnexpectedException(lineNum,colNum,"不合法标识符");
        }else if (tempStr.charAt(0)=='S'){
            stateStack.push(Integer.parseInt(tempStr.substring(1)));
            symbolStack.push(c);
            return true;
        }else if (tempStr.charAt(0)=='R'){
            int x=Integer.parseInt(tempStr.substring(1));
            int len=StateClass.production[x][1].length();
            for(int i=0;i< StateClass.production[x][1].length();i++){
                stateStack.pop();
                symbolStack.pop();
            }
            return analyse(lineNum,colNum,StateClass.production[x][0]);
        }else if(isNum(tempStr.charAt(0))){
            stateStack.push(Integer.parseInt(tempStr));
            symbolStack.push(c);
            return true;
        }else if(tempStr=="acc"){
            return true;
        }
        return false;

    }

    //解析json字符串
    public boolean parse() throws UnexpectedException {
        Token tk = null;
        tk=lex.next();
        tk=lex.next();
        Integer oldStatus = status;
        while(tk!=Token.EOF){
            String analyseStr= TOK.CAST_LOCAL_STRS[tk.getType()];
            if(analyse(tk.getLineNum(),tk.getBeginCol(),analyseStr)==false){
                System.out.print("未知错误");
                return false;
            }
            String  tempC=symbolStack.peek();
            if(tempC=="J"||tempC=="O"||tempC=="M"||tempC=="P"||tempC=="A"||tempC=="E"||tempC=="V"){
                continue;
            }
            tk=lex.next();
        }
        return true;

    }
}

三、文件读取和写入

1、创建FileIO类进行文件读取和写入。其中readFile用于读取文件内容并返回字符串,writeFile用于将字符串写入到指定文件中,如果文件不存在,则创建文件。

package FileIO;
 /**
 * Created by think on 2017/6/12.
 */
import   java.io.*;
public class FileIO {
    //从文件读取内容
     public static String readFile(String path) throws IOException{
         BufferedReader in = new BufferedReader(new FileReader( path));
         String str="";
         int c;
         while((c = in.read())!=-1)
         {
             str=str+(char)c;
         }
         in.close();
        return str;
    }
    //向文件写入内容
    public static void writeFile(String path,String str) throws IOException{
        File toFile = new File(path);
        if (!toFile.exists()) {
            toFile.createNewFile();
        }
        FileWriter fw = null;
        fw = new FileWriter(toFile);
        fw.write(str);
        fw.close();
    }
}

四、按路径得到Json元素值

1、创建Json文件,完成将json字符串解析为Maplist格式并完成按路径存取。其中maps栈用于保存所有对象maplists栈用于保存所有数组,islist栈判断是否为listkeys栈用来保存key

    方法getStructure()用于得到解析后的maplist结构,search()用于根据路径得到元素值,printSearchResult()用于打印提取的结果值。

package Json;

import FileIO.FileIO;
import Lex.JsonLex;
import Lex.TOK;
import Lex.Token;
import MyException.UnexpectedException;

import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.lang.System.exit;

/**
 * Created by think on 2017/6/13.
 */
public class Json {
    Stack maps=new Stack(); //用来表示多层的json对象
    Stack lists=new Stack(); //用来表示多层的list对象
    Stack islist=new Stack();//判断是不是list
    Stack keys=new Stack(); //用来表示多层的key
    String keytmp=null;
    Object valuetmp=null;
    public JsonLex jl;
    Token token = null;
    String nowString="";
    Object searchValue=null;
    int level;//记录提取元素是的层数
    public Json(String str)throws UnexpectedException{
        jl=new JsonLex(str);
    }
    //用于得到json字符串解析后得到的map和list结构
    public Object getStructure() throws UnexpectedException {
        while ((token = jl.next()) != Token.EOF) {
            switch (TOK.CAST_STRS[token.getType()]) {
                case "OBJB": //如果是{map进栈
                    maps.push(new HashMap());
                    islist.push(false);
                    break;
                case"DESC"://如果是:表示这是一个属性建,key进栈
                    keys.push(nowString);
                    nowString="";
                    break;
                case "ARRB"://如果是]list进栈
                    islist.push(true);
                    lists.push(new ArrayList());
                    break;
                case "SPLIT":
                    boolean listis=islist.peek();
                    if(nowString.length()>0)
                        valuetmp=nowString;
                    nowString="";
                    if(!listis){
                        keytmp=keys.pop();
                        maps.peek().put(keytmp, valuetmp);
                    }else
                        lists.peek().add(valuetmp);
                    break;
                case "ARRE":
                    islist.pop();
                    if(nowString.length()>0)
                        valuetmp=nowString;
                    nowString="";
                    lists.peek().add(valuetmp);
                    valuetmp=lists.pop();
                    break;
                case "OBJE":
                    islist.pop();
                    keytmp=keys.pop();
                    if(nowString.length()>0)
                        valuetmp=nowString;
                    nowString="";
                    maps.peek().put(keytmp, valuetmp);
                    valuetmp=maps.pop();
                    break;
                case "STR":
                    nowString=token.getValue();
                    break;
                case "NUM":
                   nowString=token.getValue();
                    break;
                case "TRUE":
                case "FALSE":
                case "NULL":
                    nowString=TOK.CAST_LOCAL_STRS[token.getType()];
                    break;
            }

        }
        return valuetmp;
    }
    //查找指定路径的元素
    public  Object search(Object object,String[] path) throws UnexpectedException{
       if(level

你可能感兴趣的:(编译原理)