package main import ( "fmt" "strings" ) func parseList(s string) []string { if !isList(s) { panic(fmt.Errorf("parselist: %s (%s)", errListExpected, s)) } list, bracketCnt, start, resList := strings.Split(s, " "), 0, 1, []string{} for i := 1; i < len(list)-1; i++ { if list[i] == "[" { bracketCnt++ } if list[i] == "]" { bracketCnt-- } if bracketCnt == 0 { resList = append(resList, strings.Join(list[start:i+1], " ")) start = i + 1 } } return resList } func makeList(list []string) string { return strings.Join(append(append([]string{"["}, list...), "]"), " ") } func indexOfList(list []string, index int) string { if index < 0 || index >= len(list) { panic(fmt.Errorf("indexoflist: %s", errIndexOutOfBound)) } return list[index] } func rangeOfList(list []string, index1, index2 int) string { if index1 < 0 || index1 > len(list) || index2 < 0 || index2 > len(list) { panic(fmt.Errorf("rangeoflist: %s", errIndexOutOfBound)) } if index1 > index2 { panic(fmt.Errorf("rangelist: %s", errIllegalRange)) } return makeList(list[index1:index2]) } func spliceList(list []string, index int, cnt int, val ...string) string { if index < 0 || index > len(list) { panic(fmt.Errorf("splicelist: %s", errIndexOutOfBound)) } if index+cnt > len(list) { cnt = len(list) - index } return makeList(append(append(list[:index], val...), list[index+cnt:]...)) } func opWord(val1, val2 value) value { if !isWord(val1.val) { panic(fmt.Errorf("word: %s (%s)", errWordExpceted, val1.val)) } if isWord(val2.val) { return value{val: val1.val + val2.val[1:]} } if isNumber(val2.val) || isBool(val2.val) { return value{val: val1.val + val2.val} } panic(fmt.Errorf("word: %s (%s)", errWordExpceted, val2.val)) } func opSentence(val1, val2 value) value { list1, list2 := []string{val1.val}, []string{val2.val} if isWord(val1.val) { list1 = []string{val1.val[1:]} } else if isList(val1.val) { list1 = parseList(val1.val) } if isWord(val2.val) { list2 = []string{val2.val[1:]} } else if isList(val2.val) { list2 = parseList(val2.val) } return value{val: makeList(append(list1, list2...))} } func opList(val1, val2 value) value { if isWord(val1.val) { val1.val = val1.val[1:] } if isWord(val2.val) { val2.val = val2.val[1:] } return value{val: makeList([]string{val1.val, val2.val})} } func opJoin(val1, val2 value) value { if !isList(val1.val) { panic(fmt.Errorf("join: %s (%s)", errListExpected, val1.val)) } if isWord(val2.val) { val2.val = val2.val[1:] } return value{val: makeList(append(parseList(val1.val), val2.val))} } func opFirst(val1 value) value { if !isWord(val1.val) && !isList(val1.val) { panic(fmt.Errorf("first: %s (%s)", errWordOrListExpected, val1.val)) } if isEmpty(val1.val) { panic(fmt.Errorf("first: %s (%s)", errEmptyWordOrList, val1.val)) } if isWord(val1.val) { return value{val: val1.val[:2]} } list1 := parseList(val1.val) if !isList(list1[0]) { list1[0] = `"` + list1[0] } return value{val: list1[0]} } func opLast(val1 value) value { if !isWord(val1.val) && !isList(val1.val) { panic(fmt.Errorf("last: %s (%s)", errWordOrListExpected, val1.val)) } if isEmpty(val1.val) { panic(fmt.Errorf("last: %s (%s)", errEmptyWordOrList, val1.val)) } if isWord(val1.val) { return value{val: `"` + val1.val[len(val1.val)-1:]} } list1 := parseList(val1.val) if !isList(list1[len(list1)-1]) { list1[len(list1)-1] = `"` + list1[len(list1)-1] } return value{val: list1[len(list1)-1]} } func opButFirst(val1 value) value { if !isWord(val1.val) && !isList(val1.val) { panic(fmt.Errorf("butfirst: %s (%s)", errWordOrListExpected, val1.val)) } if isEmpty(val1.val) { panic(fmt.Errorf("butfirst: %s (%s)", errEmptyWordOrList, val1.val)) } if isWord(val1.val) { return value{val: `"` + val1.val[2:]} } list1 := parseList(val1.val) return value{val: makeList(list1[1:])} } func opButLast(val1 value) value { if !isWord(val1.val) && !isList(val1.val) { panic(fmt.Errorf("butlast: %s (%s)", errWordOrListExpected, val1.val)) } if isEmpty(val1.val) { panic(fmt.Errorf("butlast: %s (%s)", errEmptyWordOrList, val1.val)) } if isWord(val1.val) { return value{val: val1.val[:len(val1.val)-1]} } list1 := parseList(val1.val) return value{val: makeList(list1[:len(list1)-1])} }