Prechádzať zdrojové kódy

ADD. 支持中括号转义和变量下标

RegMs If 4 rokov pred
rodič
commit
fb9549a621
8 zmenil súbory, kde vykonal 207 pridanie a 106 odobranie
  1. 38 57
      bind.go
  2. 69 8
      in
  3. 2 4
      io.go
  4. 9 9
      list.go
  5. 3 3
      math.go
  6. BIN
      mua
  7. 12 11
      mua.go
  8. 74 14
      type.go

+ 38 - 57
bind.go

@@ -8,48 +8,6 @@ import (
 	"strings"
 )
 
-func parseFunc(s string) value {
-	if !isList(s) {
-		return value{val: s}
-	}
-	list := parseList(s)
-	if len(list) != 2 || !isList(list[0]) || !isList(list[1]) {
-		return value{val: s, list: list}
-	}
-	param := parseList(list[0])
-	for _, name := range param {
-		if !isName(`"` + name) {
-			return value{val: s, list: list}
-		}
-	}
-	local := make(environ)
-	for name, val := range env[len(env)-1] {
-		local[name] = val
-	}
-	return value{val: s, list: list, param: param, env: local}
-}
-
-func wrapFunc(val value) value {
-	if isList(val.val) && val.list == nil {
-		return parseFunc(val.val)
-	}
-	return val
-}
-
-func getFunc(name string) value {
-	if !isName(`"` + name) {
-		return value{}
-	}
-	envs := []int{len(env) - 1, len(env) - 2, 1}
-	for _, id := range envs {
-		val, ok := env[id][name]
-		if ok {
-			return val
-		}
-	}
-	return value{}
-}
-
 func assign(s string, index []string, val string) string {
 	if len(index) == 0 {
 		return val
@@ -58,28 +16,35 @@ func assign(s string, index []string, val string) string {
 	return spliceList(list, i, 1, assign(indexOfList(list, i), index[1:], val))
 }
 
-func opMake(val1, val2 value) value {
-	name, index := toNameWithIndex(val1.val)
+func setValue(s string, val value) (value, error) {
+	if !isNameWithIndex(s) {
+		return value{}, fmt.Errorf("setvalue: %s (%s)", errInvalidName, s)
+	}
+	name, index := toNameWithIndex(s)
 	_, ok := reserved[name]
 	if ok {
-		panic(fmt.Errorf("make: %s (%s)", errNameReserved, name))
+		return value{}, fmt.Errorf("setvalue: %s (%s)", errNameReserved, name)
 	}
-	val, ok := env[len(env)-1][name]
+	oldVal, ok := env[len(env)-1][name]
 	if !ok && len(index) > 0 {
-		panic(fmt.Errorf("make: %s (%s)", errNameNotFound, name))
+		return value{}, fmt.Errorf("setvalue: %s (%s)", errNameNotFound, name)
 	}
 	if len(index) > 0 {
-		if isWord(val2.val) {
-			val2.val = val2.val[1:]
+		if isWord(val.val) {
+			val.val = val.val[1:]
 		}
-		val2 = value{val: assign(val.val, index, val2.val)}
+		val = value{val: assign(oldVal.val, index, val.val)}
 	}
-	env[len(env)-1][name] = wrapFunc(val2)
-	return val2
+	val = toValue(val)
+	env[len(env)-1][name] = val
+	return val, nil
 }
 
-func opThing(val1 value) value {
-	name, index := toNameWithIndex(val1.val)
+func getValue(s string) (value, error) {
+	if !isNameWithIndex(s) {
+		return value{}, fmt.Errorf("getvalue: %s (%s)", errInvalidName, s)
+	}
+	name, index := toNameWithIndex(s)
 	envs := []int{len(env) - 1, len(env) - 2, 1}
 	for _, id := range envs {
 		val, ok := env[id][name]
@@ -101,10 +66,26 @@ func opThing(val1 value) value {
 					val = value{val: rangeOfList(list, toInt(r[0]), toInt(r[1]))}
 				}
 			}
-			return val
+			return val, nil
 		}
 	}
-	panic(fmt.Errorf("thing: %s (%s)", errNameNotFound, name))
+	return value{}, fmt.Errorf("getvalue: %s (%s)", errNameNotFound, name)
+}
+
+func opMake(val1, val2 value) value {
+	val, err := setValue(val1.val, val2)
+	if err != nil {
+		panic(err)
+	}
+	return val
+}
+
+func opThing(val1 value) value {
+	val, err := getValue(val1.val)
+	if err != nil {
+		panic(err)
+	}
+	return val
 }
 
 func opErase(val1 value) value {
@@ -160,5 +141,5 @@ func opPoAll() value {
 	for name := range env[len(env)-1] {
 		list = append(list, name)
 	}
-	return value{val: "[ " + strings.Join(list, " ") + " ]"}
+	return value{val: makeList(list)}
 }

+ 69 - 8
in

@@ -1,17 +1,36 @@
-make "fun [
+make "l []
+make "q join :l "[
+print :q[0]
+print eq "] "\]
+
+make "t print [ \[1\]\\\] [1]]
+print islist :t[0]
+print islist :t[1]
+make "x "t
+make "y "x
+print :::y
+
+make "rev_func [
   [f]
   [
-    return [
+    [
       [a b]
-      [f :a :b]
+      [f :b :a]
     ]
   ]
 ]
-make "adder fun [[x y] [add :x :y]]
-print adder 2 "3
-make "imply fun [[x y] [or not :x :y]]
-print imply "true false
-print imply true true
+make "rev_sub rev_func [[x y] [sub :x :y]]
+print rev_sub 2 5
+print rev_sub 26.5 10.3
+make "rev_ge rev_func [[x y] [or gt :x :y eq :x :y]]
+print rev_ge 3 7
+print rev_ge "abc "aBc
+print rev_ge 8 8
+make "rev_imply rev_func [[x y] [or not :x :y]]
+print rev_imply false false
+print rev_imply false true
+print rev_imply true false
+print rev_imply true true
 
 make "arr [ [ a b ] c ]
 print :arr[0]
@@ -25,9 +44,12 @@ make "arr[1] [ add :a :d ]
 print :arr
 print arr 2 3
 make "arr[0][1] [ e [ f ] ]
+make "arr join :arr [ g [ h i ] ]
 print :arr[0][1]
 print :arr[0][1][0]
 print :arr[0][1][1][0]
+make "x 1
+print :arr[x:]
 
 print word "hello "world
 print word "hello TRUE
@@ -69,7 +91,11 @@ make "reverse_list [
   [list]
   [if isempty :list [] [join reverse_list butfirst :list first :list]]
 ]
+print reverse_list []
+print reverse_list [x y z]
+print reverse_list [12 345 6 78 9 0]
 print reverse_list [a b c d [e f] g]
+print reverse_list [h [i [j k]] l m n]
 
 make "fib_wrap [
   [x]
@@ -168,3 +194,38 @@ make "test [
 ]
 test
 print :x
+
+print poall
+
+make "fun1 [
+  [x]
+  [add :x 10]
+]
+print fun1 5
+make "fun2 [
+  []
+  [
+    print fun1 5
+    make "fun1 [
+      [x]
+      [add :x 100]
+    ]
+    print fun1 5
+    export "fun1
+    make "fun1 [
+      [x]
+      [add :x 1000]
+    ]
+    print fun1 5
+    if eq fun1 5 1005 [return 0] []
+    make "fun1 [
+      [x]
+      [add :x 10000]
+    ]
+    export "fun1
+    print fun1 5
+    return 1
+  ]
+]
+print fun2
+print fun1 5

+ 2 - 4
io.go

@@ -18,7 +18,7 @@ func opRead(scanner *bufio.Scanner) value {
 }
 
 func opPrint(val1 value) value {
-	s := val1.val
+	s := escapeValue(val1.val)
 	if s != "" {
 		if s[0] == '"' {
 			fmt.Println(s[1:])
@@ -47,9 +47,7 @@ func opReadList(scanner *bufio.Scanner) value {
 			break
 		}
 		line = true
-		if s[0] == '[' || s[len(s)-1] == ']' {
-			panic(fmt.Errorf("readlist: %s, (%s)", errWordExpceted, s))
-		}
+		// todo
 		if s != "\n" {
 			list = append(list, s)
 		}

+ 9 - 9
list.go

@@ -25,8 +25,8 @@ func parseList(s string) []string {
 	return resList
 }
 
-func wrapList(list []string) []string {
-	return append(append([]string{"["}, list...), "]")
+func makeList(list []string) string {
+	return strings.Join(append(append([]string{"["}, list...), "]"), " ")
 }
 
 func indexOfList(list []string, index int) string {
@@ -43,7 +43,7 @@ func rangeOfList(list []string, index1, index2 int) string {
 	if index1 > index2 {
 		panic(fmt.Errorf("rangelist: %s", errIllegalRange))
 	}
-	return strings.Join(wrapList(list[index1:index2]), " ")
+	return makeList(list[index1:index2])
 }
 
 func spliceList(list []string, index int, cnt int, val ...string) string {
@@ -53,7 +53,7 @@ func spliceList(list []string, index int, cnt int, val ...string) string {
 	if index+cnt > len(list) {
 		cnt = len(list) - index
 	}
-	return strings.Join(wrapList(append(append(list[:index], val...), list[index+cnt:]...)), " ")
+	return makeList(append(append(list[:index], val...), list[index+cnt:]...))
 }
 
 func opWord(val1, val2 value) value {
@@ -81,7 +81,7 @@ func opSentence(val1, val2 value) value {
 	} else if isList(val2.val) {
 		list2 = parseList(val2.val)
 	}
-	return value{val: strings.Join(wrapList(append(list1, list2...)), " ")}
+	return value{val: makeList(append(list1, list2...))}
 }
 
 func opList(val1, val2 value) value {
@@ -91,7 +91,7 @@ func opList(val1, val2 value) value {
 	if isWord(val2.val) {
 		val2.val = val2.val[1:]
 	}
-	return value{val: strings.Join(wrapList([]string{val1.val, val2.val}), " ")}
+	return value{val: makeList([]string{val1.val, val2.val})}
 }
 
 func opJoin(val1, val2 value) value {
@@ -101,7 +101,7 @@ func opJoin(val1, val2 value) value {
 	if isWord(val2.val) {
 		val2.val = val2.val[1:]
 	}
-	return value{val: strings.Join(wrapList(append(parseList(val1.val), val2.val)), " ")}
+	return value{val: makeList(append(parseList(val1.val), val2.val))}
 }
 
 func opFirst(val1 value) value {
@@ -149,7 +149,7 @@ func opButFirst(val1 value) value {
 		return value{val: `"` + val1.val[2:]}
 	}
 	list1 := parseList(val1.val)
-	return value{val: strings.Join(wrapList(list1[1:]), " ")}
+	return value{val: makeList(list1[1:])}
 }
 
 func opButLast(val1 value) value {
@@ -163,5 +163,5 @@ func opButLast(val1 value) value {
 		return value{val: val1.val[:len(val1.val)-1]}
 	}
 	list1 := parseList(val1.val)
-	return value{val: strings.Join(wrapList(list1[:len(list1)-1]), " ")}
+	return value{val: makeList(list1[:len(list1)-1])}
 }

+ 3 - 3
math.go

@@ -48,7 +48,7 @@ func opEq(val1, val2 value) value {
 		return value{val: strconv.FormatBool(b1 == b2)}
 	}
 	if isWord(val1.val) && isWord(val2.val) {
-		return value{val: strconv.FormatBool(val1.val == val2.val)}
+		return value{val: strconv.FormatBool(escapeValue(val1.val) == escapeValue(val2.val))}
 	}
 	panic(fmt.Errorf("eq: %s (%s, %s)", errIllegalOperandType, val1.val, val2.val))
 }
@@ -63,7 +63,7 @@ func opGt(val1, val2 value) value {
 		return value{val: strconv.FormatBool(b1 || !b2)}
 	}
 	if isWord(val1.val) && isWord(val2.val) {
-		return value{val: strconv.FormatBool(val1.val > val2.val)}
+		return value{val: strconv.FormatBool(escapeValue(val1.val) > escapeValue(val2.val))}
 	}
 	panic(fmt.Errorf("gt: %s (%s, %s)", errIllegalOperandType, val1.val, val2.val))
 }
@@ -78,7 +78,7 @@ func opLt(val1, val2 value) value {
 		return value{val: strconv.FormatBool(!b1 || b2)}
 	}
 	if isWord(val1.val) && isWord(val2.val) {
-		return value{val: strconv.FormatBool(val1.val < val2.val)}
+		return value{val: strconv.FormatBool(escapeValue(val1.val) < escapeValue(val2.val))}
 	}
 	panic(fmt.Errorf("lt: %s (%s, %s)", errIllegalOperandType, val1.val, val2.val))
 }


+ 12 - 11
mua.go

@@ -73,7 +73,7 @@ func interpret(scanner *bufio.Scanner) (val value, returned bool) {
 		}
 		if s[0] == ':' {
 			leading := len(s) - len(strings.TrimLeft(s, ":"))
-			val := value{val: `"` + strings.TrimLeft(s, ":")}
+			val := toValue(value{val: `"` + s[leading:]})
 			for i := 0; i < leading; i++ {
 				val = opThing(val)
 			}
@@ -83,7 +83,9 @@ func interpret(scanner *bufio.Scanner) (val value, returned bool) {
 			for {
 				leading := len(s) - len(strings.TrimLeft(s, "["))
 				trailing := len(s) - len(strings.TrimRight(s, "]"))
-				s = strings.TrimRight(strings.TrimLeft(s, "["), "]")
+				escape := len(s) - len(strings.TrimRight(strings.TrimRight(s, "]"), "\\")) - trailing
+				trailing -= escape & 1
+				s = s[leading : len(s)-trailing]
 				for i := 0; i < leading; i++ {
 					list = append(list, "[")
 				}
@@ -118,13 +120,14 @@ func interpret(scanner *bufio.Scanner) (val value, returned bool) {
 		for !returned {
 			updated := false
 			for i := len(stack) - 1; i >= stackTop; i-- {
+				if !isNameWithIndex(`"` + stack[i].val) {
+					continue
+				}
 				paramCnt, ok := reserved[stack[i].val]
 				if ok {
 					if paramCnt == len(stack)-1-i {
 						for j := i + 1; j < len(stack); j++ {
-							if !isValue(stack[j].val) {
-								panic(fmt.Errorf("mua: %s (%s)", errValueExpected, stack[j].val))
-							}
+							stack[j] = toValue(stack[j])
 						}
 						switch stack[i].val {
 						case "make":
@@ -217,17 +220,15 @@ func interpret(scanner *bufio.Scanner) (val value, returned bool) {
 					}
 					break
 				}
-				val := getFunc(stack[i].val)
+				val, _ := getValue(`"` + stack[i].val)
 				if val.param != nil {
 					if len(val.param) == len(stack)-1-i {
 						for j := i + 1; j < len(stack); j++ {
-							if !isValue(stack[j].val) {
-								panic(fmt.Errorf("mua: %s (%s)", errValueExpected, stack[j].val))
-							}
+							stack[j] = toValue(stack[j])
 						}
 						local := environ{stack[i].val: val}
 						for j, name := range val.param {
-							local[name] = wrapFunc(stack[i+1+j])
+							local[name] = stack[i+1+j]
 						}
 						env = append(env, val.env, local)
 						stack[i], _ = opRun(value{val: val.list[1]})
@@ -246,7 +247,7 @@ func interpret(scanner *bufio.Scanner) (val value, returned bool) {
 	if len(stack) == stackTop {
 		stack = append(stack, value{val: "[ ]"})
 	}
-	val = wrapFunc(stack[len(stack)-1])
+	val = toValue(stack[len(stack)-1])
 	stack = stack[:stackTop]
 	return
 }

+ 74 - 14
type.go

@@ -7,9 +7,14 @@ import (
 	"strings"
 )
 
+const _name, _nameOrInt = `([A-Za-z]\w*)`, "(" + _name + `|\d+)`
+const _index = "(" + _nameOrInt + "|:|" + _nameOrInt + ":|:" + _nameOrInt + "|" + _nameOrInt + ":" + _nameOrInt + ")"
+
+var nameExp = regexp.MustCompile(`^"` + _name + "$")
+var nameWithIndexExp = regexp.MustCompile(`^"` + _name + `((\[` + _index + `])*\[` + _index + `\\])?$`)
+
 func isName(s string) bool {
-	reg := regexp.MustCompile(`^"[A-Za-z]\w*$`)
-	return reg.MatchString(s)
+	return nameExp.MatchString(s)
 }
 
 func toName(s string) string {
@@ -20,8 +25,7 @@ func toName(s string) string {
 }
 
 func isNameWithIndex(s string) bool {
-	reg := regexp.MustCompile(`^"[A-Za-z]\w*(\[(\d+|:|\d+:|:\d+|\d+:\d+)\])*$`)
-	return reg.MatchString(s)
+	return nameWithIndexExp.MatchString(s)
 }
 
 func toNameWithIndex(s string) (string, []string) {
@@ -29,10 +33,11 @@ func toNameWithIndex(s string) (string, []string) {
 		panic(fmt.Errorf("name: %s (%s)", errInvalidName, s))
 	}
 	index := strings.Split(s, "[")
-	name := index[0][1:]
-	for i := 1; i < len(index); i++ {
+	name, cnt := index[0][1:], len(index)-1
+	for i := 1; i < cnt; i++ {
 		index[i] = index[i][:len(index[i])-1]
 	}
+	index[cnt] = index[cnt][:len(index[cnt])-2]
 	return name, index[1:]
 }
 
@@ -55,15 +60,13 @@ func toNumber(s string) float64 {
 	return val
 }
 
-func isInt(s string) bool {
-	if s != "" && s[0] == '"' {
-		s = s[1:]
-	}
-	_, err := strconv.ParseInt(s, 10, 64)
-	return err == nil
-}
-
 func toInt(s string) int {
+	if isName(`"` + s) {
+		val, err := getValue(`"` + s)
+		if err == nil {
+			s = val.val
+		}
+	}
 	if s != "" && s[0] == '"' {
 		s = s[1:]
 	}
@@ -105,10 +108,67 @@ func isEmpty(s string) bool {
 	return s == `"` || s == "[ ]"
 }
 
+func parseFunc(s string) value {
+	if !isList(s) {
+		return value{val: s}
+	}
+	list := parseList(s)
+	if len(list) != 2 || !isList(list[0]) || !isList(list[1]) {
+		return value{val: s, list: list}
+	}
+	param := parseList(list[0])
+	for _, name := range param {
+		if !isName(`"` + name) {
+			return value{val: s, list: list}
+		}
+	}
+	local := make(environ)
+	for name, val := range env[len(env)-1] {
+		local[name] = val
+	}
+	return value{val: s, list: list, param: param, env: local}
+}
+
 func isValue(s string) bool {
 	return isNumber(s) || isWord(s) || isList(s) || isBool(s)
 }
 
+func toValue(val value) value {
+	if !isValue(val.val) {
+		panic(fmt.Errorf("mua: %s (%s)", errValueExpected, val.val))
+	}
+	if isWord(val.val) {
+		if val.val[1] == '[' {
+			val.val = val.val[:1] + "\\" + val.val[1:]
+		}
+		if val.val[len(val.val)-1] == ']' {
+			val.val = val.val[:len(val.val)-1]
+			escape := len(val.val) - len(strings.TrimRight(val.val, "\\"))
+			if (escape & 1) == 0 {
+				val.val += "\\"
+			}
+			val.val += "]"
+		}
+		return val
+	}
+	if isList(val.val) {
+		if val.list == nil {
+			return parseFunc(val.val)
+		}
+		return val
+	}
+	return val
+}
+
+func escapeValue(s string) string {
+	for i := 0; i < len(s); i++ {
+		if s[i] == '\\' {
+			s = s[:i] + s[i+1:]
+		}
+	}
+	return s
+}
+
 func opIsName(val1 value) value {
 	return value{val: strconv.FormatBool(isName(val1.val))}
 }