优化词法分析
This commit is contained in:
parent
d933ff5f03
commit
8071532012
213
lexical.go
213
lexical.go
@ -21,7 +21,10 @@ import (
|
||||
//
|
||||
// Date : 20:52 2022/7/4
|
||||
func NewLexical(jsonData string) *lexical {
|
||||
return &lexical{jsonData: jsonData}
|
||||
return &lexical{
|
||||
jsonData: jsonData,
|
||||
lexicalResult: make([]*lexicalNode, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// lexical 词法解析
|
||||
@ -32,6 +35,7 @@ func NewLexical(jsonData string) *lexical {
|
||||
type lexical struct {
|
||||
jsonData string
|
||||
keyLeftRightTokenCnt int
|
||||
lexicalResult []*lexicalNode
|
||||
}
|
||||
|
||||
// Parse 解析词法
|
||||
@ -40,50 +44,64 @@ type lexical struct {
|
||||
//
|
||||
// Date : 18:11 2022/7/4
|
||||
func (l *lexical) Parse(jsonData string) ([]lexicalNode, error) {
|
||||
jsonData = strings.ReplaceAll(strings.ReplaceAll(jsonData, "\n", ""), "\t", "")
|
||||
// mt.Println(jsonData)
|
||||
if len(jsonData) < 2 {
|
||||
return nil, errors.New("input data is not json")
|
||||
}
|
||||
lexicalList := make([]lexicalNode, 0)
|
||||
tmpStr := ""
|
||||
for _, itemChar := range jsonData {
|
||||
currentChar := string(itemChar)
|
||||
preChar := "-1"
|
||||
if len(lexicalList) > 0 {
|
||||
preChar = lexicalList[len(lexicalList)-1].Val
|
||||
if len(tmpStr) == 0 && preChar == objectLeftToken && currentChar == " " {
|
||||
// 无意义的空格
|
||||
continue
|
||||
}
|
||||
if len(tmpStr) == 0 && currentChar == " " && preChar == keyLeftRightToken && l.keyLeftRightTokenCnt%2 == 0 {
|
||||
// " : 之间的空格无意义
|
||||
continue
|
||||
}
|
||||
}
|
||||
if l.inputCharIsToken(currentChar, preChar) {
|
||||
if l.inputCharIsToken(currentChar, tmpStr) {
|
||||
if currentChar == keyLeftRightToken {
|
||||
// 双引号计数
|
||||
l.keyLeftRightTokenCnt++
|
||||
}
|
||||
// 是关键词
|
||||
if len(tmpStr) > 0 {
|
||||
lexicalList = append(lexicalList, lexicalNode{
|
||||
l.lexicalResult = append(l.lexicalResult, &lexicalNode{
|
||||
Val: tmpStr,
|
||||
IsToken: false,
|
||||
})
|
||||
}
|
||||
lexicalList = append(lexicalList, lexicalNode{
|
||||
l.lexicalResult = append(l.lexicalResult, &lexicalNode{
|
||||
Val: currentChar,
|
||||
IsToken: true,
|
||||
})
|
||||
tmpStr = ""
|
||||
} else {
|
||||
// 不是关键词, 继续向后走
|
||||
if currentChar == " " {
|
||||
// 当前字符是空格, 只有在字符串内方才有效
|
||||
if l.keyLeftRightTokenCnt%2 == 0 {
|
||||
// 关键字之间的空格, 忽略即可
|
||||
continue
|
||||
}
|
||||
}
|
||||
tmpStr = tmpStr + currentChar
|
||||
}
|
||||
}
|
||||
util.JSON.ConsoleOutput(lexicalList)
|
||||
// 格式化, 去掉 \n \t 等换行符
|
||||
format := make([]*lexicalNode, 0)
|
||||
for idx, val := range l.lexicalResult {
|
||||
formatVal := strings.ReplaceAll(strings.ReplaceAll(val.Val, "\n", ""), "\t", "")
|
||||
// 说明是 \n\t 组成的
|
||||
if len(formatVal) == 0 {
|
||||
if idx == 0 {
|
||||
continue
|
||||
}
|
||||
if idx == len(l.lexicalResult)-1 {
|
||||
break
|
||||
}
|
||||
if (!l.lexicalResult[idx-1].IsToken || l.lexicalResult[idx-1].Val != keyLeftRightToken) ||
|
||||
(!l.lexicalResult[idx+1].IsToken || l.lexicalResult[idx+1].Val != keyLeftRightToken) {
|
||||
// 不是 "" 之间的 \n \t 没有实际意义
|
||||
continue
|
||||
}
|
||||
}
|
||||
format = append(format, val)
|
||||
}
|
||||
l.lexicalResult = format
|
||||
util.JSON.ConsoleOutput(l.lexicalResult)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@ -92,24 +110,151 @@ func (l *lexical) Parse(jsonData string) ([]lexicalNode, error) {
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 18:15 2022/7/4
|
||||
func (l *lexical) inputCharIsToken(inputChar string, preChar string) bool {
|
||||
if preChar == escapeCharacterToken {
|
||||
// 前一个是转义符, 当前不是关键字
|
||||
return false
|
||||
func (l *lexical) inputCharIsToken(inputChar string, tmpStr string) bool {
|
||||
if len(tmpStr) == 0 && inputChar == keyLeftRightToken {
|
||||
// 双引号关键字
|
||||
return true
|
||||
}
|
||||
tokenCharList := []string{
|
||||
listLeftToken,
|
||||
listRightToken,
|
||||
objectLeftToken,
|
||||
objectRightToken,
|
||||
keyLeftRightToken,
|
||||
kvPairSplitToken,
|
||||
escapeCharacterToken,
|
||||
}
|
||||
for _, itemChar := range tokenCharList {
|
||||
if itemChar == inputChar {
|
||||
tmpStrByte := []byte(tmpStr)
|
||||
if len(tmpStrByte) > 0 {
|
||||
// 字符串拼接过程中, 只有 " 可能是关键字
|
||||
// 判断转义符个数
|
||||
escapeCharacterTokenCnt := 0
|
||||
for i := len(tmpStrByte) - 1; i >= 0; i-- {
|
||||
if string(tmpStrByte[i]) == escapeCharacterToken {
|
||||
// 前一个是转义符
|
||||
escapeCharacterTokenCnt++
|
||||
continue
|
||||
}
|
||||
// 非连续的转义符不计数
|
||||
break
|
||||
}
|
||||
// 0 个 或者 偶数个转义符, " 是关键字
|
||||
if escapeCharacterTokenCnt%2 == 0 && inputChar == keyLeftRightToken {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
var preNode *lexicalNode
|
||||
if len(l.lexicalResult) > 0 {
|
||||
preNode = l.lexicalResult[len(l.lexicalResult)-1]
|
||||
}
|
||||
|
||||
if inputChar == colonToken && nil != preNode && preNode.Val == keyLeftRightToken && l.keyLeftRightTokenCnt > 0 && l.keyLeftRightTokenCnt%2 == 0 {
|
||||
// : 必须出现在偶数 " 之后才是关键字
|
||||
return true
|
||||
}
|
||||
|
||||
tmpStrType := l.getTpmStrType(tmpStr)
|
||||
// , 是关键字的场景
|
||||
// {"name":"zhangsan", "age":"18"}
|
||||
// [{"name":"zhangsan", "age":"18"}, {"name":"zhangsan", "age":"18"}]
|
||||
// [[],[]]
|
||||
// [1,2,3]
|
||||
// [true,false,true]
|
||||
if inputChar == commaToken && len(tmpStr) == 0 &&
|
||||
// 对应 {"name":"zhangsan", "age":"18"}
|
||||
(nil != preNode && preNode.Val == keyLeftRightToken) ||
|
||||
// 对应[{"name":"zhangsan", "age":"18"}, {"name":"zhangsan", "age":"18"}]
|
||||
(nil != preNode && preNode.Val == objectRightToken) ||
|
||||
// 对应[[],[]]
|
||||
(nil != preNode && preNode.Val == listRightToken) ||
|
||||
// 对应 [true,false,true] / [1,2,3] / [1,true,2,false]
|
||||
(nil != preNode && (preNode.Val == listLeftToken || preNode.Val == commaToken) && (tmpStrType == "number" || tmpStr == "bool")) { // 对应
|
||||
return true
|
||||
}
|
||||
|
||||
// { 可能出现的情况
|
||||
// {}
|
||||
// [{}] [{}, {}]
|
||||
// {"person": {}}
|
||||
if inputChar == objectLeftToken && len(tmpStr) == 0 &&
|
||||
(nil == preNode || // 对应 {}
|
||||
(nil != preNode && preNode.Val == listLeftToken) || // 对应 [{}]
|
||||
(nil != preNode && preNode.Val == colonToken) || // 对应 {"person": {}}
|
||||
(nil != preNode && preNode.Val == commaToken)) { // 对应 [{}, {}]
|
||||
// { 是关键字
|
||||
return true
|
||||
}
|
||||
|
||||
// } 可能出出现的情况
|
||||
// {}
|
||||
// [{}]
|
||||
// {"name":"zhangsan"}
|
||||
// {"person": {"name":"zhangsan"}}
|
||||
// {"person": {"name":"zhangsan", "age": 18}}
|
||||
// {"person": {"work":true}}
|
||||
// {"person": {"like":1}}
|
||||
if inputChar == objectRightToken && len(tmpStr) == 0 && (
|
||||
// 对应 {}, [{}]
|
||||
(nil != preNode && preNode.Val == objectLeftToken) ||
|
||||
// 对应 {"name":"zhangsan"}
|
||||
(nil != preNode && preNode.Val == keyLeftRightToken) ||
|
||||
// 对应 {"person": {"name":"zhangsan"}}
|
||||
(nil != preNode && preNode.Val == objectRightToken)) ||
|
||||
// 对应 {"person": {"work":true}} / {"person": {"like":1}}
|
||||
(nil != preNode && preNode.Val == colonToken && (tmpStr == "number" || tmpStr == "bool")) {
|
||||
// } 是关键字
|
||||
return true
|
||||
}
|
||||
|
||||
// [ 可能出现的场景
|
||||
// []
|
||||
// [[],[]]
|
||||
// "a": []
|
||||
if inputChar == listLeftToken && (nil == preNode || // 对应 []
|
||||
(nil != preNode && preNode.Val == listLeftToken) || // 对应 [[],[]]
|
||||
(nil != preNode && preNode.Val == colonToken)) { // 对应 "a": []
|
||||
// [ 是关键字
|
||||
return true
|
||||
}
|
||||
|
||||
// ] 可能出现的场景
|
||||
// []
|
||||
// [[],[]]
|
||||
// [{}, {}]
|
||||
// [1,2,3]
|
||||
// [true, false]
|
||||
// ["", "" ]
|
||||
if inputChar == listLeftToken && (
|
||||
//对应 []
|
||||
(nil != preNode && preNode.Val == listLeftToken) ||
|
||||
// 对应 [[],[]]
|
||||
(nil != preNode && preNode.Val == listRightToken) ||
|
||||
// [true, false] /
|
||||
(nil != preNode && preNode.Val == objectRightToken) ||
|
||||
// 对应 [{}, {}] / [1,2,3]
|
||||
(nil != preNode && (tmpStrType == "number" || tmpStrType == "bool")) ||
|
||||
// 对应 ["", "" ]
|
||||
(nil != preNode && preNode.Val == keyLeftRightToken)) {
|
||||
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (l *lexical) getTpmStrType(tmpStr string) string {
|
||||
var preNode *lexicalNode
|
||||
if len(l.lexicalResult) > 0 {
|
||||
preNode = l.lexicalResult[len(l.lexicalResult)-1]
|
||||
}
|
||||
|
||||
// 数字只有一个场景 {"age": 18},多以若是数字, 则 前一次解析必为关键字 :
|
||||
if nil != preNode && preNode.Val == colonToken {
|
||||
// 判断是否可转数字
|
||||
var floatVal float64
|
||||
if err := util.ConvertAssign(&floatVal, tmpStr); nil == err {
|
||||
return "number"
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否为 bool
|
||||
// bool 只有一个场景 {"work": true/false},多以若是数字, 则 前一次解析必为关键字 :
|
||||
if nil != preNode && preNode.Val == colonToken {
|
||||
// 判断是否可转数字
|
||||
var boolVal bool
|
||||
if err := util.ConvertAssign(&boolVal, tmpStr); nil == err {
|
||||
return "bool"
|
||||
}
|
||||
}
|
||||
return "string"
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
|
||||
func Test_parseLexical(t *testing.T) {
|
||||
jsonData := `{
|
||||
"name" :"zhangsan",
|
||||
"name" : "zhangsan",
|
||||
"age":"18",
|
||||
"extension":{
|
||||
"sex":"man",
|
||||
|
Loading…
Reference in New Issue
Block a user