Beispiel #1
0
func evalSubscript(ec *evalCtx, left, right Value, lp, rp parse.Pos) Value {
	var sub string
	if s, ok := right.(str); ok {
		sub = string(s)
	} else {
		ec.errorf(rp, "right operand of subscript must be of type string")
	}

	switch left.(type) {
	case *table:
		t := left.(*table)
		// TODO(xiaq): An index is considered a list index if it can be parsed
		// as an unsigned integer; otherwise it is a dict index. This is
		// somewhat subtle.
		idx, err := strconv.ParseUint(sub, 10, 0)
		if err == nil {
			if idx < uint64(len(t.List)) {
				return t.List[idx]
			}
			ec.errorf(rp, "index out of range")
		}
		if v, ok := t.Dict[sub]; ok {
			return v
		}
		ec.errorf(rp, "nonexistent key %q", sub)
		return nil
	case str:
		invalidIndex := "invalid index, must be integer or integer:integer"

		ss := strings.Split(sub, ":")
		if len(ss) > 2 {
			ec.errorf(rp, invalidIndex)
		}
		idx := make([]int, len(ss))
		for i, s := range ss {
			n, err := strconv.ParseInt(s, 10, 0)
			if err != nil {
				ec.errorf(rp, invalidIndex)
			}
			idx[i] = int(n)
		}

		var s string
		var e error
		if len(idx) == 1 {
			var r rune
			r, e = strutil.NthRune(toString(left), idx[0])
			s = string(r)
		} else {
			s, e = strutil.SubstringByRune(toString(left), idx[0], idx[1])
		}
		if e != nil {
			ec.errorf(rp, "%v", e)
		}
		return str(s)
	default:
		ec.errorf(lp, "left operand of subscript must be of type string, env, table or any")
		return nil
	}
}
Beispiel #2
0
func (s String) Index(idx Value) Value {
	i := intIndex(idx)
	r, err := strutil.NthRune(string(s), i)
	maybeThrow(err)
	return String(string(r))
}