Пример #1
0
func (ls *libstore) deletelist() {
	now := time.Now()
	// ls.mutex.Lock()
	// // fmt.Println("deleteinvalid")
	// defer ls.mutex.Unlock()

	for key, list := range ls.keyValudhistory {
		ls.initiateKeyValueMutex(key)
		ls.keyValueMutex[key].Lock()
		for list.Len() > 0 {
			e := list.Front()
			if e.Value.(time.Time).Add(time.Duration(storagerpc.QueryCacheSeconds)*time.Second).After(now) && list.Len() <= storagerpc.QueryCacheThresh {
				break
			}
			list.Remove(list.Front())
		}
		ls.keyValueMutex[key].Unlock()
	}

	for key, list := range ls.keyListhistory {
		ls.initiateKeyListMutex(key)
		ls.keyListMutex[key].Lock()
		for list.Len() > 0 {
			e := list.Front()
			if e.Value.(time.Time).Add(time.Duration(storagerpc.QueryCacheSeconds)*time.Second).After(now) && list.Len() <= storagerpc.QueryCacheThresh {
				break
			}
			list.Remove(list.Front())
		}
		ls.keyListMutex[key].Unlock()
	}
}
Пример #2
0
func expandClass(regex []int) string {
	list := New()
	list.Init()
	nextEscape := false
	escaped := false
	var toDelete *Element
	for reg_index := 0; reg_index < len(regex); reg_index++ {
		escaped = nextEscape
		nextEscape = false
		switch regex[reg_index] {
		case '\\':
			if escaped {
				escaped = false
				list.PushBack(int('\\'))
				toDelete = nil
			} else {
				nextEscape = true
				toDelete = list.PushBack(int('\\'))
			}
			break
		case '-':
			if escaped {
				escaped = false
				list.PushBack(int('-'))
				toDelete.Value = Delete
			} else {
				if reg_index > 0 && reg_index < len(regex)-1 {
					start := regex[reg_index-1]
					end := uint8(regex[reg_index+1])
					for char := uint8(start + 1); char < end; char++ {
						list.PushBack(int(char))
					}
				} else {
					//ERROR
					fmt.Println("invalid character class")
				}
			}
			break
		default:
			list.PushBack(regex[reg_index])
			break
		}
	}
	for e := list.Front(); e != nil; e = e.Next() {
		if e.Value.(int) == Delete {
			list.Remove(e)
		}
	}
	out := string(list.Remove(list.Front()).(int))
	for e := list.Front(); e != nil; e = e.Next() {
		out += string('|')
		out += string(e.Value.(int))
	}
	return out
}
Пример #3
0
// Commit causes all requests that have been queued for the transaction
// to be sent to the request channel for processing. Calls the commit
// function (commitFunc) in order for each request that is part of the
// transaction.
func (txs *txStore) Commit(tx string, commitFunc func(f *frame.Frame) error) error {
	if list, ok := txs.transactions[tx]; ok {
		for element := list.Front(); element != nil; element = list.Front() {
			err := commitFunc(list.Remove(element).(*frame.Frame))
			if err != nil {
				return err
			}
		}
		delete(txs.transactions, tx)
		return nil
	}
	return txUnknown
}
func PrintDepartures(airport string, data *FlightData) {
	list := data.Departures[airport]
	for cursor := list.Front(); cursor != nil; cursor = cursor.Next() {
		f := cursor.Value.(Flight)
		fmt.Println(f.From, f.To, f.Cost)
	}
}
Пример #5
0
// Reads a list of ASN1Cert types from |r|
func readASN1CertList(r io.Reader, totalLenBytes int, elementLenBytes int) ([]ASN1Cert, error) {
	listBytes, err := readVarBytes(r, totalLenBytes)
	if err != nil {
		return []ASN1Cert{}, err
	}
	list := list.New()
	listReader := bytes.NewReader(listBytes)
	var entry []byte
	for err == nil {
		entry, err = readVarBytes(listReader, elementLenBytes)
		if err != nil {
			if err != io.EOF {
				return []ASN1Cert{}, err
			}
		} else {
			list.PushBack(entry)
		}
	}
	ret := make([]ASN1Cert, list.Len())
	i := 0
	for e := list.Front(); e != nil; e = e.Next() {
		ret[i] = e.Value.([]byte)
		i++
	}
	return ret, nil
}
Пример #6
0
// locate returns the node on which the item at the logical index should reside.
// If the index lands on a slice node, the offset is the physical index relative
// to the slice. If the index lands on a value node, then the offset is
// meaningless and set to 0.
func (s *GapSlice) locate(i int) (elem *list.Element, offset int) {
	if i < 0 || i >= s.size {
		return nil, 0
	}

	remaining := i
	list := s.list
	for e := list.Front(); e != nil; e = e.Next() {
		switch value := e.Value.(type) {
		case gapSliceChunk:
			if chunkSize := len(value); remaining < chunkSize {
				return e, remaining
			} else {
				remaining -= chunkSize
			}
		default:
			if remaining == 0 {
				return e, 0
			} else {
				remaining -= 1
			}
		}
	}

	panic(Errorf("could not find element for index %d in GapSlice", i))
}
Пример #7
0
func (ss *storageServer) GetList(args *storagerpc.GetArgs, reply *storagerpc.GetListReply) error {
	if !ss.isInServerRange(args.Key) {
		reply.Status = storagerpc.WrongServer
		return nil
	}

	//get the lock for current key
	ss.mutex.Lock()
	lock, exist := ss.lockMap[args.Key]
	if !exist {
		lock = new(sync.Mutex)
		ss.lockMap[args.Key] = lock
	}
	ss.mutex.Unlock()

	//Lock current key we are going to work on
	lock.Lock()

	//process lease request
	grantLease := false
	if args.WantLease {
		//add to lease map
		var libServerList *list.List
		libServerList, exist := ss.leaseMap[args.Key]
		if !exist {
			libServerList = new(list.List)
		}
		leaseRecord := LeaseRecord{args.HostPort, time.Now()}
		libServerList.PushBack(leaseRecord)
		ss.leaseMap[args.Key] = libServerList
		grantLease = true
	}
	reply.Lease = storagerpc.Lease{grantLease, storagerpc.LeaseSeconds}

	//retrieve list
	list, exist := ss.keyListMap[args.Key]
	if !exist {
		reply.Status = storagerpc.KeyNotFound
	} else {
		//convert list format from "map" to "[]string"
		listSize := list.Len()
		replyList := make([]string, listSize)

		i := 0
		for e := list.Front(); e != nil; e = e.Next() {
			val := (e.Value).(string)
			replyList[i] = val
			i = i + 1
		}

		reply.Value = replyList
		reply.Status = storagerpc.OK
	}

	lock.Unlock()
	return nil
}
Пример #8
0
func (stack *Stack) Top() []byte {
	list := (*list.List)(stack)
	el := list.Front()
	if el == nil {
		return nil
	}
	val, ok := el.Value.([]byte)
	if !ok {
		panic("Why is it not a byte array?")
	}
	return val
}
Пример #9
0
func (h *hashMap) Get(key Value) (Value, error) {
	index := h.getIndex(key)
	if h.data[index] == nil {
		return nil, fmt.Errorf("not found")
	}
	list := h.data[index]
	for e := list.Front(); e != nil; e = e.Next() {
		if i := e.Value.(*item); i.key.Get() == key.Get() {
			return i.value, nil
		}
	}
	return nil, fmt.Errorf("not found")
}
Пример #10
0
func IsBST(root *TreeNode) bool {
	list := list.New()
	createOrderedArray(root, list)

	prev := list.Front()
	for e := prev.Next(); e != nil; e = e.Next() {
		if prev.Value.(int) > e.Value.(int) {
			return false
		}
		prev = e
	}

	return true
}
Пример #11
0
func MatchAll(m *Matcher, text string) []Match {
	list := list.New()
	ch := m.Match(text)
	for n := range ch {
		list.PushBack(n)
	}
	all := make([]Match, list.Len())
	idx := 0
	for e := list.Front(); e != nil; e = e.Next() {
		all[idx] = e.Value.(Match)
		idx++
	}
	return all
}
Пример #12
0
// GoString formats this GapSlice as a space-separated list of nodes surrounded
// by parentheses. Value nodes are represented by the GoString format of the
// value itself, while slice nodes are presented as a space-separated list of
// values in GoString format surrounded by square brackets.
func (s *GapSlice) GoString() string {
	list := s.list
	b := bytes.NewBufferString("(")
	for e := list.Front(); e != nil; e = e.Next() {
		if chunk, isChunk := e.Value.(gapSliceChunk); isChunk {
			b.WriteString(fmt.Sprintf("%v", chunk))
		} else {
			b.WriteString(fmt.Sprintf("%#v", e.Value))
		}
		if e != list.Back() {
			b.WriteRune(' ')
		}
	}
	b.WriteRune(')')
	return b.String()
}
Пример #13
0
// Remove a service definition from the list. If a service has been removed,
// return true. Different connections cannot remove services they did not add.
func (l *serviceList) Remove(service *ServiceDef) bool {
	list := (*list.List)(l)
	for iter := list.Front(); iter != nil; iter = iter.Next() {
		e := iter.Value.(*ServiceDef)
		res := service.compare(e)
		if res > 0 {
			continue
		} else if res == 0 && e.connId == service.connId {
			list.Remove(iter)
			return true
		}
		// Did not find the service.
		break
	}
	return false
}
Пример #14
0
func daythirteen() {
	file, _ := os.Open("input-day13")
	list := list.New()
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		text := scanner.Text()
		list.PushFront(text)
	}
	arr := make([]string, list.Len())
	count := 0
	for e := list.Front(); e != nil; e = e.Next() {
		arr[count] = e.Value.(string)
		count++
	}
	fmt.Printf("Best = %d\n", ProcSeatingArray(arr, 0))
	fmt.Printf("Best = %d\n", ProcSeatingArray(arr, 1))
}
Пример #15
0
func toArray(values interface{}) ([]interface{}, os.Error) {

	// vector to array
	if vector, ok := values.(*vector.Vector); ok {
		return toArray(*vector)
	}

	result := new(vector.Vector)

	// list to array
	if list, ok := values.(*list.List); ok {
		for e := list.Front(); e != nil; e = e.Next() {
			result.Push(e.Value)
		}
		return *result, nil
	}

	switch v := reflect.ValueOf(values); v.Kind() {

	// array to array (copy)
	case reflect.Array, reflect.Slice:
		arr := v
		for i := 0; i < arr.Len(); i++ {
			obj := arr.Index(i).Interface()
			result.Push(obj)
		}

	// channel to array
	case reflect.Chan:
		ch := v
		for {
			if x, ok := ch.Recv(); ok {
				obj := x.Interface()
				result.Push(obj)
			} else {
				break
			}
		}

	// unknown type
	default:
		return nil, Errorf("type error: expected a collection type, but was “%v” of type “%T”", values, values)
	}
	return *result, nil
}
Пример #16
0
// Walk iterates through this GapSlice, calling walkFn for each item visited by
// Walk.
//
// If walkFun returns an error, the iteration is immediately halted, and in turn,
// that error is returned by Walk.
func (s *GapSlice) Walk(walkFn GapSliceWalkFunc) error {
	list := s.list
	for e := list.Front(); e != nil; e = e.Next() {
		switch value := e.Value.(type) {
		case gapSliceChunk:
			for _, v := range value {
				if err := walkFn(v); err != nil {
					return err
				}
			}
		default:
			if err := walkFn(value); err != nil {
				return nil
			}
		}
	}
	return nil
}
Пример #17
0
func reconstructPath(came_from map[Coord]Coord, current_node Coord) []*Move {
	list := list.New()
	for present := true; present; _, present = came_from[current_node] {
		next_node := came_from[current_node]
		list.PushFront(findMove(current_node, next_node))

		current_node = next_node
	}

	// Convert to a list and return
	rtn := make([]*Move, list.Len())
	i := 0
	for e := list.Front(); e != nil; e = e.Next() {
		move := e.Value.(Move)
		rtn[i] = &move
		i++
	}
	return rtn
}
Пример #18
0
// Add a new service definition to the list. If the definition is added or
// updated, return true.
func (l *serviceList) Add(service *ServiceDef) bool {
	list := (*list.List)(l)
	for iter := list.Front(); iter != nil; iter = iter.Next() {
		e := iter.Value.(*ServiceDef)
		res := service.compare(e)
		if res > 0 {
			continue
		} else if res < 0 {
			list.InsertBefore(service, iter)
			return true
		} else if e.connId == service.connId {
			// Replace the definition if it is from the same connection.
			iter.Value = service
			return true
		}
		// Equal entries but from a different connection.
		return false
	}
	list.PushBack(service)
	return true
}
Пример #19
0
//查看某状态的任务
func taskView(w http.ResponseWriter, r *http.Request) {

	status := r.FormValue("status")

	reg := regexp.MustCompile(status_requ)
	if reg.MatchString(status) == false {
		io.WriteString(w, "need param status, status must be 0-new task ,1-success,2-can not get rdb,3-parse fatal, 4-get remote redis password error or 5-task is running!")
		return
	}

	int_stat, _ := strconv.ParseInt(status, 10, 32)

	mark, list := dbutil.FetchTask(int(int_stat))

	if mark == 1 {
		var listHtml string = "<body><ol>"
		for e := list.Front(); e != nil; e = e.Next() {
			task, ok := e.Value.(dbutil.Task)
			if ok {
				//获取task信息
				host := task.Host
				port := task.Port
				filterLength := task.FilterLength
				filterKey := task.FilterKey
				taskId := task.TaskId
				createTime := task.CreateTime
				listHtml += "<li>" + "host:" + host + ";port:" + port + ";filterLength:" + strconv.FormatInt(int64(filterLength), 10) + ";filterKey:" + filterKey + ";taskId:" + taskId + ";create_time:" + createTime + "</li>"
			} else {
				//task的类型不正确
				return
			}
		}
		listHtml = listHtml + "</ol></body>"
		io.WriteString(w, listHtml)
	} else {
		io.WriteString(w, "error occure !")
		logs.Log("error occure in taskView!")
	}
}
Пример #20
0
//根据taskId查看某一个task
func task(w http.ResponseWriter, r *http.Request) {

	taskId := r.FormValue("taskId")

	mark, list := dbutil.FetchTaskById(taskId)
	if list.Len() == 0 {
		io.WriteString(w, "without this task !")
		return
	}

	if mark == 1 {
		var listHtml string = "<body><ol>"
		for e := list.Front(); e != nil; e = e.Next() {
			task, ok := e.Value.(dbutil.Task)
			if ok {
				//获取task信息
				host := task.Host
				port := task.Port
				filterLength := task.FilterLength
				filterKey := task.FilterKey
				taskId := task.TaskId
				priority := task.Priority
				status := task.Status
				createTime := task.CreateTime
				listHtml += "<li>" + "host:" + host + ";port:" + port + ";filterLength:" + strconv.FormatInt(int64(filterLength), 10) + ";filter_key:" + filterKey + ";taskId:" + taskId +
					";priority:" + strconv.FormatInt(int64(priority), 10) + ";status:" + strconv.FormatInt(int64(status), 10) + ";create_time:" + createTime + "</li>"
			} else {
				//task的类型不正确
				return
			}
			listHtml = listHtml + "</ol></body>"
		}
		io.WriteString(w, listHtml)
	} else {
		io.WriteString(w, "error occure !")
		logs.Log("error occure in taskView!")
	}
}
Пример #21
0
// String formats this GapSlice as a space-separated list of items surrounded
// by parentheses.
func (s *GapSlice) String() string {
	list := s.list
	b := bytes.NewBufferString("(")
	for e := list.Front(); e != nil; e = e.Next() {
		switch v := e.Value.(type) {
		case gapSliceChunk:
			last := len(v) - 1
			for i, item := range v {
				b.WriteString(fmt.Sprintf("%v", item))
				if i != last {
					b.WriteRune(' ')
				}
			}
		default:
			b.WriteString(fmt.Sprintf("%v", v))
		}
		if e != list.Back() {
			b.WriteRune(' ')
		}
	}
	b.WriteRune(')')
	return b.String()
}
Пример #22
0
func (t *Tree) Compile(file string) {
	_package, state, name, counts :=
		"", "", "", [TypeLast]uint{}
	for element := t.Front(); element != nil; element = element.Next() {
		node := element.Value.(Node)
		switch node.GetType() {
		case TypePackage:
			_package = node.(Token).String()
		case TypePeg:
			peg := node.(Fix)
			name = peg.String()
			state = peg.GetNode().(Token).String()
		case TypeRule:
			rule := node.(*rule)
			t.rules[rule.String()] = rule
		}
	}

	join([]func(){
		func() {
			var countTypes func(node Node)
			countTypes = func(node Node) {
				t := node.GetType()
				counts[t]++
				switch t {
				case TypeRule:
					countTypes(node.(Rule).GetExpression())
				case TypeAlternate, TypeUnorderedAlternate, TypeSequence:
					for element := node.(List).Front(); element != nil; element = element.Next() {
						countTypes(element.Value.(Node))
					}
				case TypePeekFor, TypePeekNot, TypeQuery, TypeStar, TypePlus:
					countTypes(node.(Fix).GetNode())
				}
			}
			for _, rule := range t.rules {
				countTypes(rule)
			}
		},
		func() {
			var countRules func(node Node)
			ruleReached := make([]bool, len(t.rules))
			countRules = func(node Node) {
				switch node.GetType() {
				case TypeRule:
					rule := node.(Rule)
					name, id := rule.String(), rule.GetId()
					if count, ok := t.rulesCount[name]; ok {
						t.rulesCount[name] = count + 1
					} else {
						t.rulesCount[name] = 1
					}
					if ruleReached[id] {
						return
					}
					ruleReached[id] = true
					countRules(rule.GetExpression())
				case TypeName:
					countRules(t.rules[node.String()])
				case TypeAlternate, TypeUnorderedAlternate, TypeSequence:
					for element := node.(List).Front(); element != nil; element = element.Next() {
						countRules(element.Value.(Node))
					}
				case TypePeekFor, TypePeekNot, TypeQuery, TypeStar, TypePlus:
					countRules(node.(Fix).GetNode())
				}
			}
			for element := t.Front(); element != nil; element = element.Next() {
				node := element.Value.(Node)
				if node.GetType() == TypeRule {
					countRules(node.(*rule))
					break
				}
			}
		},
		func() {
			var checkRecursion func(node Node) bool
			ruleReached := make([]bool, len(t.rules))
			checkRecursion = func(node Node) bool {
				switch node.GetType() {
				case TypeRule:
					rule := node.(Rule)
					id := rule.GetId()
					if ruleReached[id] {
						fmt.Fprintf(os.Stderr, "possible infinite left recursion in rule '%v'\n", node)
						return false
					}
					ruleReached[id] = true
					consumes := checkRecursion(rule.GetExpression())
					ruleReached[id] = false
					return consumes
				case TypeAlternate:
					for element := node.(List).Front(); element != nil; element = element.Next() {
						if !checkRecursion(element.Value.(Node)) {
							return false
						}
					}
					return true
				case TypeSequence:
					for element := node.(List).Front(); element != nil; element = element.Next() {
						if checkRecursion(element.Value.(Node)) {
							return true
						}
					}
				case TypeName:
					return checkRecursion(t.rules[node.String()])
				case TypePlus:
					return checkRecursion(node.(Fix).GetNode())
				case TypeCharacter, TypeString:
					return len(node.String()) > 0
				case TypeDot, TypeClass:
					return true
				}
				return false
			}
			for _, rule := range t.rules {
				checkRecursion(rule)
			}
		}})

	if t._switch {
		var optimizeAlternates func(node Node) (consumes, eof, peek bool, class *characterClass)
		cache := make([]struct {
			reached, consumes, eof, peek bool
			class                        *characterClass
		}, len(t.rules))
		optimizeAlternates = func(node Node) (consumes, eof, peek bool, class *characterClass) {
			switch node.GetType() {
			case TypeRule:
				rule := node.(Rule)
				cache := &cache[rule.GetId()]
				if cache.reached {
					consumes, eof, peek, class = cache.consumes, cache.eof, cache.peek, cache.class
					return
				}
				cache.reached = true
				consumes, eof, peek, class = optimizeAlternates(rule.GetExpression())
				cache.consumes, cache.eof, cache.peek, cache.class = consumes, eof, peek, class
			case TypeName:
				consumes, eof, peek, class = optimizeAlternates(t.rules[node.String()])
			case TypeDot:
				consumes, class = true, new(characterClass)
				for index, _ := range *class {
					class[index] = 0xff
				}
			case TypeString, TypeCharacter:
				consumes, class = true, new(characterClass)
				b := node.String()[0]
				if b == '\\' {
					b = node.String()[1]
					switch b {
					case 'a':
						b = '\a' /* bel */
					case 'b':
						b = '\b' /* bs */
					case 'f':
						b = '\f' /* ff */
					case 'n':
						b = '\n' /* nl */
					case 'r':
						b = '\r' /* cr */
					case 't':
						b = '\t' /* ht */
					case 'v':
						b = '\v' /* vt */
					}
				}
				class.add(b)
			case TypeClass:
				consumes, class = true, t.classes[node.String()]
			case TypeAlternate:
				consumes, peek, class = true, true, new(characterClass)
				alternate := node.(List)
				mconsumes, meof, mpeek, properties, c :=
					consumes, eof, peek, make([]struct {
						intersects bool
						class      *characterClass
					}, alternate.Len()), 0
				for element := alternate.Front(); element != nil; element = element.Next() {
					mconsumes, meof, mpeek, properties[c].class = optimizeAlternates(element.Value.(Node))
					consumes, eof, peek = consumes && mconsumes, eof || meof, peek && mpeek
					if properties[c].class != nil {
						class.union(properties[c].class)
					}
					c++
				}
				if eof {
					break
				}
				intersections := 2
			compare:
				for ai, a := range properties[0 : len(properties)-1] {
					for _, b := range properties[ai+1:] {
						for i, v := range *a.class {
							if (b.class[i] & v) != 0 {
								intersections++
								properties[ai].intersects = true
								continue compare
							}
						}
					}
				}
				if intersections < len(properties) {
					c, unordered, ordered, max :=
						0, &nodeList{Type: TypeUnorderedAlternate}, &nodeList{Type: TypeAlternate}, 0
					for element := alternate.Front(); element != nil; element = element.Next() {
						if properties[c].intersects {
							ordered.PushBack(element.Value)
						} else {
							class := &token{Type: TypeClass, string: properties[c].class.String(), class: properties[c].class}
							sequence, predicate :=
								&nodeList{Type: TypeSequence}, &fix{Type: TypePeekFor, node: class}
							sequence.PushBack(predicate)
							sequence.PushBack(element.Value)
							length := properties[c].class.len()
							if length > max {
								unordered.PushBack(sequence)
								max = length
							} else {
								unordered.PushFront(sequence)
							}
						}
						c++
					}
					alternate.Init()
					if ordered.Len() == 0 {
						alternate.SetType(TypeUnorderedAlternate)
						for element := unordered.Front(); element != nil; element = element.Next() {
							alternate.PushBack(element.Value)
						}
					} else {
						for element := ordered.Front(); element != nil; element = element.Next() {
							alternate.PushBack(element.Value)
						}
						alternate.PushBack(unordered)
					}
				}
			case TypeSequence:
				sequence := node.(List)
				meof, classes, c, element :=
					eof, make([]struct {
						peek  bool
						class *characterClass
					}, sequence.Len()), 0, sequence.Front()
				for ; !consumes && element != nil; element, c = element.Next(), c+1 {
					consumes, meof, classes[c].peek, classes[c].class = optimizeAlternates(element.Value.(Node))
					eof, peek = eof || meof, peek || classes[c].peek
				}
				eof, peek, class = !consumes && eof, !consumes && peek, new(characterClass)
				for c--; c >= 0; c-- {
					if classes[c].class != nil {
						if classes[c].peek {
							class.intersection(classes[c].class)
						} else {
							class.union(classes[c].class)
						}
					}
				}
				for ; element != nil; element = element.Next() {
					optimizeAlternates(element.Value.(Node))
				}
			case TypePeekNot:
				peek = true
				_, eof, _, class = optimizeAlternates(node.(Fix).GetNode())
				eof = !eof
				class = class.copy()
				class.complement()
			case TypePeekFor:
				peek = true
				fallthrough
			case TypeQuery, TypeStar:
				_, eof, _, class = optimizeAlternates(node.(Fix).GetNode())
			case TypePlus:
				consumes, eof, peek, class = optimizeAlternates(node.(Fix).GetNode())
			}
			return
		}
		for element := t.Front(); element != nil; element = element.Next() {
			node := element.Value.(Node)
			if node.GetType() == TypeRule {
				optimizeAlternates(node.(*rule))
				break
			}
		}
	}

	out, error := os.Open(file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
	if error != nil {
		fmt.Printf("%v: %v\n", file, error)
		return
	}
	defer out.Close()
	print := func(format string, a ...interface{}) { fmt.Fprintf(out, format, a...) }
	printSave := func(n uint) { print("\n   position%d := position", n) }
	printRestore := func(n uint) { print("   position = position%d", n) }

	print(
		`package %v
import "fmt"
type %v struct {%v
 Buffer string
 Min, Max int
 rules [%d]func() bool
}
func (p *%v) Parse() bool {
 if p.rules[0]() {
  return true
 }
 return false
}
func (p *%v) PrintError() {
 line := 1
 character := 0
 for i, c := range p.Buffer[0:] {
  if c == '\n' {
   line++
   character = 0
  } else {
   character++
  }
  if i == p.Min {
   if p.Min != p.Max {
    fmt.Printf("parse error after line %%v character %%v\n", line, character)
   } else {break}
  } else if i == p.Max {break}
 }
 fmt.Printf("parse error: unexpected ")
 if p.Max >= len(p.Buffer) {
  fmt.Printf("end of file found\n")
 } else {
  fmt.Printf("'%%c' at line %%v character %%v\n", p.Buffer[p.Max], line, character)
 }
}
func (p *%v) Init() {
 var position int`, _package, name, state, len(t.rules), name, name, name)

	hasActions := t.actions.Len() != 0
	if hasActions {
		bits := 0
		for length := t.actions.Len(); length != 0; length >>= 1 {
			bits++
		}
		switch {
		case bits < 8:
			bits = 8
		case bits < 16:
			bits = 16
		case bits < 32:
			bits = 32
		case bits < 64:
			bits = 64
		}
		print("\n actions := [...]func(buffer string, begin, end int) {\n")
		for i := t.actions.Front(); i != nil; i = i.Next() {
			a := i.Value.(Action)
			print("  /* %v %v */\n", a.GetId(), a.GetRule())
			print("  func(buffer string, begin, end int) {\n")
			print("   %v\n", a)
			print("  },\n")
		}
		print(
			` }
 var thunkPosition, begin, end int
 thunks := make([]struct {action uint%d; begin, end int}, 32)
 do := func(action uint%d) {
  if thunkPosition == len(thunks) {
   newThunks := make([]struct {action uint%d; begin, end int}, 2 * len(thunks))
   copy(newThunks, thunks)
   thunks = newThunks
  }
  thunks[thunkPosition].action = action
  thunks[thunkPosition].begin = begin
  thunks[thunkPosition].end = end
  thunkPosition++
 }`, bits, bits, bits)
		if counts[TypeCommit] > 0 {
			print(
				`
 commit := func(thunkPosition0 int) bool {
  if thunkPosition0 == 0 {
   for thunk := 0; thunk < thunkPosition; thunk++ {
    actions[thunks[thunk].action](p.Buffer, thunks[thunk].begin, thunks[thunk].end)
   }
   p.Min = position
   thunkPosition = 0
   return true
  }
  return false
 }`)
		}
		printSave = func(n uint) { print("\n   position%d,  thunkPosition%d := position, thunkPosition", n, n) }
		printRestore = func(n uint) { print("   position, thunkPosition = position%d, thunkPosition%d", n, n) }
	}

	if counts[TypeDot] > 0 {
		print(
			`
 matchDot := func() bool {
  if position < len(p.Buffer) {
   position++
   return true
  } else if position >= p.Max {
   p.Max = position
  }
  return false
 }`)
	}
	if counts[TypeCharacter] > 0 {
		print(
			`
 matchChar := func(c byte) bool {
  if (position < len(p.Buffer)) && (p.Buffer[position] == c) {
   position++
   return true
  } else if position >= p.Max {
   p.Max = position
  }
  return false
 }`)
	}
	if counts[TypeString] > 0 {
		print(
			`
 matchString := func(s string) bool {
  length := len(s)
  next := position + length
  if (next <= len(p.Buffer)) && (p.Buffer[position:next] == s) {
   position = next
   return true
  } else if position >= p.Max {
   p.Max = position
  }
  return false
 }`)
	}

	classes := make(map[string]uint)
	if len(t.classes) != 0 {
		print("\n classes := [...][32]uint8 {\n")
		var index uint
		for className, classBitmap := range t.classes {
			classes[className] = index
			print("  [32]uint8{")
			for _, b := range *classBitmap {
				print("%d, ", b)
			}
			print("},\n")
			index++
		}
		print(
			` }
 matchClass := func(class uint) bool {
  if (position < len(p.Buffer)) &&
     ((classes[class][p.Buffer[position] >> 3] & (1 << (p.Buffer[position] & 7))) != 0) {
   position++
   return true
  } else if position >= p.Max {
   p.Max = position
  }
  return false
 }`)
	}

	var printRule func(node Node)
	var compile func(expression Node, ko uint)
	var label uint
	printBegin := func() { print("\n   {") }
	printEnd := func() { print("\n   }") }
	printLabel := func(n uint) { print("\n   l%d:\t", n) }
	printJump := func(n uint) { print("\n   goto l%d", n) }
	printRule = func(node Node) {
		switch node.GetType() {
		case TypeRule:
			print("%v <- ", node)
			expression := node.(Rule).GetExpression()
			if expression != nil {
				printRule(expression)
			}
		case TypeDot:
			print(".")
		case TypeName:
			print("%v", node)
		case TypeCharacter,
			TypeString:
			print("'%v'", node)
		case TypeClass:
			print("[%v]", node)
		case TypePredicate:
			print("&{%v}", node)
		case TypeAction:
			print("{%v}", node)
		case TypeCommit:
			print("commit")
		case TypeBegin:
			print("<")
		case TypeEnd:
			print(">")
		case TypeAlternate:
			print("(")
			list := node.(List)
			element := list.Front()
			printRule(element.Value.(Node))
			for element = element.Next(); element != nil; element = element.Next() {
				print(" / ")
				printRule(element.Value.(Node))
			}
			if list.GetLastIsEmpty() {
				print(" /")
			}
			print(")")
		case TypeUnorderedAlternate:
			print("(")
			element := node.(List).Front()
			printRule(element.Value.(Node))
			for element = element.Next(); element != nil; element = element.Next() {
				print(" | ")
				printRule(element.Value.(Node))
			}
			print(")")
		case TypeSequence:
			print("(")
			element := node.(List).Front()
			printRule(element.Value.(Node))
			for element = element.Next(); element != nil; element = element.Next() {
				print(" ")
				printRule(element.Value.(Node))
			}
			print(")")
		case TypePeekFor:
			print("&")
			printRule(node.(Fix).GetNode())
		case TypePeekNot:
			print("!")
			printRule(node.(Fix).GetNode())
		case TypeQuery:
			printRule(node.(Fix).GetNode())
			print("?")
		case TypeStar:
			printRule(node.(Fix).GetNode())
			print("*")
		case TypePlus:
			printRule(node.(Fix).GetNode())
			print("+")
		default:
			fmt.Fprintf(os.Stderr, "illegal node type: %v\n", node.GetType())
		}
	}
	compile = func(node Node, ko uint) {
		switch node.GetType() {
		case TypeRule:
			fmt.Fprintf(os.Stderr, "internal error #1 (%v)\n", node)
		case TypeDot:
			print("\n   if !matchDot() {goto l%d}", ko)
		case TypeName:
			name := node.String()
			rule := t.rules[name]
			if t.inline && t.rulesCount[name] == 1 {
				compile(rule.GetExpression(), ko)
				return
			}
			print("\n   if !p.rules[%d]() {goto l%d}", rule.GetId(), ko)
		case TypeCharacter:
			print("\n   if !matchChar('%v') {goto l%d}", node, ko)
		case TypeString:
			print("\n   if !matchString(\"%v\") {goto l%d}", node, ko)
		case TypeClass:
			print("\n   if !matchClass(%d) {goto l%d}", classes[node.String()], ko)
		case TypePredicate:
			print("\n   if !(%v) {goto l%d}", node, ko)
		case TypeAction:
			print("\n   do(%d)", node.(Action).GetId())
		case TypeCommit:
			print("\n   if !(commit(thunkPosition0)) {goto l%d}", ko)
		case TypeBegin:
			if hasActions {
				print("\n   begin = position")
			}
		case TypeEnd:
			if hasActions {
				print("\n   end = position")
			}
		case TypeAlternate:
			list := node.(List)
			ok := label
			label++
			printBegin()
			element := list.Front()
			if element.Next() != nil || list.GetLastIsEmpty() {
				printSave(ok)
			}
			for element.Next() != nil {
				next := label
				label++
				compile(element.Value.(Node), next)
				printJump(ok)
				printLabel(next)
				printRestore(ok)
				element = element.Next()
			}
			if list.GetLastIsEmpty() {
				done := label
				label++
				compile(element.Value.(Node), done)
				printJump(ok)
				printLabel(done)
				printRestore(ok)
			} else {
				compile(element.Value.(Node), ko)
			}
			printEnd()
			printLabel(ok)
		case TypeUnorderedAlternate:
			list := node.(List)
			done, ok := ko, label
			label++
			printBegin()
			if list.GetLastIsEmpty() {
				done = label
				label++
				printSave(ok)
			}
			print("\n   if position == len(p.Buffer) {goto l%d}", done)
			print("\n   switch p.Buffer[position] {")
			element := list.Front()
			for ; element.Next() != nil; element = element.Next() {
				sequence := element.Value.(List).Front()
				class := sequence.Value.(Fix).GetNode().(Token).GetClass()
				sequence = sequence.Next()
				print("\n   case")
				comma := false
				for d := 0; d < 256; d++ {
					if class.has(uint8(d)) {
						if comma {
							print(",")
						}
						s := ""
						switch uint8(d) {
						case '\a':
							s = `\a` /* bel */
						case '\b':
							s = `\b` /* bs */
						case '\f':
							s = `\f` /* ff */
						case '\n':
							s = `\n` /* nl */
						case '\r':
							s = `\r` /* cr */
						case '\t':
							s = `\t` /* ht */
						case '\v':
							s = `\v` /* vt */
						case '\'':
							s = `\'` /* ' */
						default:
							s = fmt.Sprintf("%c", d)
						}
						print(" '%s'", s)
						comma = true
					}
				}
				print(":")
				compile(sequence.Value.(Node), done)
			}
			print("\n   default:")
			compile(element.Value.(List).Front().Next().Value.(Node), done)
			print("\n   }")
			if list.GetLastIsEmpty() {
				printJump(ok)
				printLabel(done)
				printRestore(ok)
			}
			printEnd()
			printLabel(ok)
		case TypeSequence:
			for element := node.(List).Front(); element != nil; element = element.Next() {
				compile(element.Value.(Node), ko)
			}
		case TypePeekFor:
			ok := label
			label++
			printBegin()
			printSave(ok)
			compile(node.(Fix).GetNode(), ko)
			printRestore(ok)
			printEnd()
		case TypePeekNot:
			ok := label
			label++
			printBegin()
			printSave(ok)
			compile(node.(Fix).GetNode(), ok)
			printJump(ko)
			printLabel(ok)
			printRestore(ok)
			printEnd()
		case TypeQuery:
			qko := label
			label++
			qok := label
			label++
			printBegin()
			printSave(qko)
			compile(node.(Fix).GetNode(), qko)
			printJump(qok)
			printLabel(qko)
			printRestore(qko)
			printEnd()
			printLabel(qok)
		case TypeStar:
			again := label
			label++
			out := label
			label++
			printLabel(again)
			printBegin()
			printSave(out)
			compile(node.(Fix).GetNode(), out)
			printJump(again)
			printLabel(out)
			printRestore(out)
			printEnd()
		case TypePlus:
			again := label
			label++
			out := label
			label++
			compile(node.(Fix).GetNode(), ko)
			printLabel(again)
			printBegin()
			printSave(out)
			compile(node.(Fix).GetNode(), out)
			printJump(again)
			printLabel(out)
			printRestore(out)
			printEnd()
		default:
			fmt.Fprintf(os.Stderr, "illegal node type: %v\n", node.GetType())
		}
	}

	print("\n p.rules = [...]func() bool {")
	for element := t.Front(); element != nil; element = element.Next() {
		node := element.Value.(Node)
		if node.GetType() != TypeRule {
			continue
		}
		rule := node.(*rule)
		expression := rule.GetExpression()
		if expression == nil {
			fmt.Fprintf(os.Stderr, "rule '%v' used but not defined\n", rule)
			print("\n  nil,")
			continue
		}
		ko := label
		label++
		print("\n  /* %v ", rule.GetId())
		printRule(rule)
		print(" */")
		if count, ok := t.rulesCount[rule.String()]; !ok {
			fmt.Fprintf(os.Stderr, "rule '%v' defined but not used\n", rule)
			print("\n  nil,")
			continue
		} else if t.inline && count == 1 && ko != 0 {
			print("\n  nil,")
			continue
		}
		print("\n  func() bool {")
		if !expression.GetType().IsSafe() {
			printSave(0)
		}
		compile(expression, ko)
		print("\n   return true")
		if !expression.GetType().IsSafe() {
			printLabel(ko)
			printRestore(0)
			print("\n   return false")
		}
		print("\n  },")
	}
	print("\n }")
	print("\n}\n")
}
Пример #23
0
func (ls *libstore) GetList(key string) ([]string, error) {
	now := time.Now()
	ls.initiateKeyListMutex(key)
	ls.keyListMutex[key].Lock()
	defer ls.keyListMutex[key].Unlock()

	value, ok := ls.keylist[key]

	if ok {
		validUntil := value.lease.startFrom.Add(time.Duration(value.lease.validSeconds) * time.Second)

		if now.After(validUntil) {
			delete(ls.keylist, key)
			ok = !ok
		}
	}
	list, list_ok := ls.keyListhistory[key]
	if list_ok {
		for list.Len() > 0 {
			e := list.Front()
			pretime := e.Value.(time.Time)
			judgetime := pretime.Add(time.Duration(storagerpc.QueryCacheSeconds) * time.Second)
			if judgetime.After(now) && list.Len() <= storagerpc.QueryCacheThresh {
				break
			}
			list.Remove(list.Front())
		}

		list.PushBack(now) // do not know wether count cache or not
	}
	if ok { //use cache
		return value.list, nil
	} else { // use the storage

		want := false
		if ls.mode == Always {
			want = true
		}
		if ls.mode == Normal && list_ok && ls.keyListhistory[key].Len() >= storagerpc.QueryCacheThresh {
			want = true
		}

		args := &storagerpc.GetArgs{
			Key:       key,
			WantLease: want,
			HostPort:  ls.myHostPort,
		}
		reply := &storagerpc.GetListReply{}

		server := ls.Findshashring(key)
		client, ok := ls.clientmap[server]
		if !ok {

			clienttemp, err := rpc.DialHTTP("tcp", server)
			if err != nil {
				return nil, errors.New("meet error when DialHTTP")
			}
			ls.clientmap[server] = clienttemp
			client = clienttemp
		}

		err := client.Call("StorageServer.GetList", args, &reply)
		if err != nil {

			return nil, errors.New("error when libstore call get to storageserver")
		}

		if reply.Status == storagerpc.OK {
			if reply.Lease.Granted == true { // update cache
				ls.keylist[key] = &listlib{
					list: reply.Value,
					lease: leasetype{
						startFrom:    now,
						validSeconds: reply.Lease.ValidSeconds,
					},
				}
			}
		} else if reply.Status == storagerpc.KeyNotFound {
			return make([]string, 0), nil
		} else {
			return nil, errors.New("reply not ready getlist: " + string(reply.Status))
		}
		return reply.Value, nil
	}
}
Пример #24
0
Файл: peg.go Проект: wrepo/peg
func (t *Tree) Compile(out io.Writer, optiFlags string) {
	counts := [TypeLast]uint{}
	nvar := 0

	O := parseOptiFlags(optiFlags)

	for element := t.Front(); element != nil; element = element.Next() {
		node := element.Value.(Node)
		switch node.GetType() {
		case TypeRule:
			rule := node.(*rule)
			t.rules[rule.String()] = rule
			nvar += len(rule.variables)
		}
	}
	for name, r := range t.rules {
		if r.name == "" {
			r := &rule{name: name, id: t.ruleId}
			t.ruleId++
			t.rules[name] = r
			t.PushBack(r)
		}
	}

	join([]func(){
		func() {
			var countTypes func(node Node)
			countTypes = func(node Node) {
				t := node.GetType()
				counts[t]++
				switch t {
				case TypeRule:
					countTypes(node.(Rule).GetExpression())
				case TypeAlternate, TypeUnorderedAlternate, TypeSequence:
					for element := node.(List).Front(); element != nil; element = element.Next() {
						countTypes(element.Value.(Node))
					}
				case TypePeekFor, TypePeekNot, TypeQuery, TypeStar, TypePlus:
					countTypes(node.(List).Front().Value.(Node))
				}
			}
			for _, rule := range t.rules {
				countTypes(rule)
			}
		},
		func() {
			var countRules func(node Node)
			ruleReached := make([]bool, len(t.rules))
			countRules = func(node Node) {
				switch node.GetType() {
				case TypeRule:
					rule := node.(Rule)
					name, id := rule.String(), rule.GetId()
					if count, ok := t.rulesCount[name]; ok {
						t.rulesCount[name] = count + 1
					} else {
						t.rulesCount[name] = 1
					}
					if ruleReached[id] {
						return
					}
					ruleReached[id] = true
					countRules(rule.GetExpression())
				case TypeName:
					countRules(t.rules[node.String()])
				case TypeAlternate, TypeUnorderedAlternate, TypeSequence:
					for element := node.(List).Front(); element != nil; element = element.Next() {
						countRules(element.Value.(Node))
					}
				case TypePeekFor, TypePeekNot, TypeQuery, TypeStar, TypePlus:
					countRules(node.(List).Front().Value.(Node))
				}
			}
			for element := t.Front(); element != nil; element = element.Next() {
				node := element.Value.(Node)
				if node.GetType() == TypeRule {
					countRules(node.(*rule))
					break
				}
			}
		},
		func() {
			var checkRecursion func(node Node) bool
			ruleReached := make([]bool, len(t.rules))
			checkRecursion = func(node Node) bool {
				switch node.GetType() {
				case TypeRule:
					rule := node.(Rule)
					id := rule.GetId()
					if ruleReached[id] {
						fmt.Fprintf(os.Stderr, "possible infinite left recursion in rule '%v'\n", node)
						return false
					}
					ruleReached[id] = true
					consumes := checkRecursion(rule.GetExpression())
					ruleReached[id] = false
					return consumes
				case TypeAlternate:
					for element := node.(List).Front(); element != nil; element = element.Next() {
						if !checkRecursion(element.Value.(Node)) {
							return false
						}
					}
					return true
				case TypeSequence:
					for element := node.(List).Front(); element != nil; element = element.Next() {
						if checkRecursion(element.Value.(Node)) {
							return true
						}
					}
				case TypeName:
					return checkRecursion(t.rules[node.String()])
				case TypePlus:
					return checkRecursion(node.(List).Front().Value.(Node))
				case TypeCharacter, TypeString:
					return len(node.String()) > 0
				case TypeDot, TypeClass:
					return true
				}
				return false
			}
			for _, rule := range t.rules {
				checkRecursion(rule)
			}
		}})

	var inlineLeafes func(node Node) Node
	inlineLeafes = func(node Node) (ret Node) {
		ret = node
		switch node.GetType() {
		case TypeRule:
			rule := node.(Rule)
			switch x := rule.GetExpression(); x.GetType() {
			case TypeCharacter, TypeDot, TypeClass, TypeString:
				ret = x
			case TypePlus, TypeStar, TypeQuery, TypePeekNot, TypePeekFor:
				switch x.(List).Front().Value.(Node).GetType() {
				case TypeCharacter, TypeDot, TypeClass, TypeString:
					ret = x
				}
			}
		case TypeName:
			r := t.rules[node.String()]
			x := inlineLeafes(r)
			if r != x {
				stats.inlineLeafs++
				ret = x
			}
		case TypeSequence, TypeAlternate:
			for el := node.(List).Front(); el != nil; el = el.Next() {
				el.Value = inlineLeafes(el.Value.(Node))
			}
		case TypePlus, TypeStar, TypeQuery, TypePeekNot, TypePeekFor:
			v := &node.(List).Front().Value
			*v = inlineLeafes((*v).(Node))
		}
		return
	}
	if O.inlineLeafs {
		for _, rule := range t.rules {
			inlineLeafes(rule.GetExpression())
		}
	}

	if t._switch {
		var optimizeAlternates func(node Node) (consumes, eof, peek bool, class *characterClass)
		cache := make([]struct {
			reached, consumes, eof, peek bool
			class                        *characterClass
		}, len(t.rules))
		optimizeAlternates = func(node Node) (consumes, eof, peek bool, class *characterClass) {
			switch node.GetType() {
			case TypeRule:
				rule := node.(Rule)
				if t.switchExcl != nil && t.switchExcl[rule.String()] {
					return
				}
				cache := &cache[rule.GetId()]
				if cache.reached {
					consumes, eof, peek, class = cache.consumes, cache.eof, cache.peek, cache.class
					if class == nil {
						class = anyChar
					}
					return
				}
				cache.reached = true
				consumes, eof, peek, class = optimizeAlternates(rule.GetExpression())
				cache.consumes, cache.eof, cache.peek, cache.class = consumes, eof, peek, class
			case TypeName:
				consumes, eof, peek, class = optimizeAlternates(t.rules[node.String()])
			case TypeDot:
				consumes, class = true, new(characterClass)
				for index, _ := range *class {
					class[index] = 0xff
				}
			case TypeString, TypeCharacter:
				if node.String() == "" {
					consumes, class = true, anyChar
					return
				}
				consumes, class = true, new(characterClass)
				b := node.String()[0]
				if b == '\\' {
					b = node.String()[1]
					switch b {
					case 'a':
						b = '\a' /* bel */
					case 'b':
						b = '\b' /* bs */
					case 'f':
						b = '\f' /* ff */
					case 'n':
						b = '\n' /* nl */
					case 'r':
						b = '\r' /* cr */
					case 't':
						b = '\t' /* ht */
					case 'v':
						b = '\v' /* vt */
					default:
						if s := node.String(); len(s) == 4 {
							b = (s[1]-'0')*64 + (s[2]-'0')*8 + s[3] - '0'
						}
					}
				}
				class.add(b)
			case TypeClass:
				consumes, class = true, t.Classes[node.String()].Class
			case TypeAlternate:
				consumes, peek, class = true, true, new(characterClass)
				alternate := node.(List)
				mconsumes, meof, mpeek, properties, c :=
					consumes, eof, peek, make([]struct {
						intersects bool
						class      *characterClass
					}, alternate.Len()), 0
				empty := false
				for element := alternate.Front(); element != nil; element = element.Next() {
					mconsumes, meof, mpeek, properties[c].class = optimizeAlternates(element.Value.(Node))
					consumes, eof, peek = consumes && mconsumes, eof || meof, peek && mpeek
					if properties[c].class != nil {
						class.union(properties[c].class)
						if properties[c].class.len() == 0 {
							empty = true
						}
					}
					c++
				}
				if eof {
					break
				}
				intersections := 0
			compare:
				for ai, a := range properties[0 : len(properties)-1] {
					for _, b := range properties[ai+1:] {
						for i, v := range *a.class {
							if (b.class[i] & v) != 0 {
								intersections++
								properties[ai].intersects = true
								continue compare
							}
						}
					}
				}
				if empty {
					class = new(characterClass)
					consumes = false
					break
				}
				if intersections < len(properties) && len(properties) >= 2 {
					c, unordered, ordered, max :=
						0, &nodeList{Type: TypeUnorderedAlternate}, &nodeList{Type: TypeAlternate}, 0
					for element := alternate.Front(); element != nil; element = element.Next() {
						if properties[c].intersects {
							ordered.PushBack(element.Value)
						} else {
							class := &token{Type: TypeClass, string: properties[c].class.String(), class: properties[c].class}

							sequence, predicate, length :=
								&nodeList{Type: TypeSequence}, &nodeList{Type: TypePeekFor}, properties[c].class.len()
							predicate.PushBack(class)
							sequence.PushBack(predicate)
							sequence.PushBack(element.Value)

							if element.Value.(Node).GetType() == TypeString && element.Value.(Node).String() == "" {
								unordered.PushBack(sequence)
							} else if element.Value.(Node).GetType() == TypeNil {
								unordered.PushBack(sequence)
							} else if length > max {
								unordered.PushBack(sequence)
								max = length
							} else {
								unordered.PushFront(sequence)
							}
						}
						c++
					}
					alternate.Init()
					if ordered.Len() == 0 {
						alternate.SetType(TypeUnorderedAlternate)
						for element := unordered.Front(); element != nil; element = element.Next() {
							alternate.PushBack(element.Value)
						}
					} else {
						for element := ordered.Front(); element != nil; element = element.Next() {
							alternate.PushBack(element.Value)
						}
						if unordered.Len() == 1 {
							alternate.PushBack(unordered.Front().Value.(List).Front().Next().Value)
						} else {
							alternate.PushBack(unordered)
						}
					}
				}
			case TypeSequence:
				sequence := node.(List)
				meof, classes, c, element :=
					eof, make([]struct {
						peek  bool
						class *characterClass
					}, sequence.Len()), 0, sequence.Front()
				for ; !consumes && element != nil; element, c = element.Next(), c+1 {
					consumes, meof, classes[c].peek, classes[c].class = optimizeAlternates(element.Value.(Node))
					eof, peek = eof || meof, peek || classes[c].peek
				}
				eof, peek, class = !consumes && eof, !consumes && peek, new(characterClass)
				for c--; c >= 0; c-- {
					if classes[c].class != nil {
						if classes[c].peek {
							class.intersection(classes[c].class)
						} else {
							class.union(classes[c].class)
						}
					}
				}
				for ; element != nil; element = element.Next() {
					optimizeAlternates(element.Value.(Node))
				}
			case TypePeekNot:
				peek = true
				// might be buggy
				_, eof, _, _ = optimizeAlternates(node.(List).Front().Value.(Node))
				class = new(characterClass)
				eof = !eof
				class = class.copy()
				class.complement()
			case TypePeekFor:
				peek = true
				fallthrough
			case TypeQuery, TypeStar:
				_, eof, _, class = optimizeAlternates(node.(List).Front().Value.(Node))
			case TypePlus:
				consumes, eof, peek, class = optimizeAlternates(node.(List).Front().Value.(Node))
			case TypeAction, TypeNil:
				class = new(characterClass)
			}
			return
		}
		for element := t.Front(); element != nil; element = element.Next() {
			node := element.Value.(Node)
			if node.GetType() == TypeRule {
				optimizeAlternates(node.(*rule))
				break
			}
		}
	}

	w := newWriter(out)
	w.elimRestore = O.elimRestore
	print := func(format string, a ...interface{}) {
		if !w.dryRun {
			fmt.Fprintf(w, format, a...)
		}
	}

	var printRule func(node Node)
	var compile func(expression Node, ko *label) (chgFlags, chgFlags)
	printRule = func(node Node) {
		switch node.GetType() {
		case TypeRule:
			print("%v <- ", node)
			expression := node.(Rule).GetExpression()
			if expression != nilNode {
				printRule(expression)
			}
		case TypeDot:
			print(".")
		case TypeName:
			print("%v", node)
		case TypeCharacter,
			TypeString:
			print("'%v'", node)
		case TypeClass:
			print("[%v]", node)
		case TypePredicate:
			print("&{%v}", node)
		case TypeAction:
			print("{%v}", node)
		case TypeCommit:
			print("commit")
		case TypeBegin:
			print("<")
		case TypeEnd:
			print(">")
		case TypeAlternate:
			print("(")
			list := node.(List)
			element := list.Front()
			printRule(element.Value.(Node))
			for element = element.Next(); element != nil; element = element.Next() {
				print(" / ")
				printRule(element.Value.(Node))
			}
			print(")")
		case TypeUnorderedAlternate:
			print("(")
			element := node.(List).Front()
			printRule(element.Value.(Node))
			for element = element.Next(); element != nil; element = element.Next() {
				print(" | ")
				printRule(element.Value.(Node))
			}
			print(")")
		case TypeSequence:
			print("(")
			element := node.(List).Front()
			printRule(element.Value.(Node))
			for element = element.Next(); element != nil; element = element.Next() {
				print(" ")
				printRule(element.Value.(Node))
			}
			print(")")
		case TypePeekFor:
			print("&")
			printRule(node.(List).Front().Value.(Node))
		case TypePeekNot:
			print("!")
			printRule(node.(List).Front().Value.(Node))
		case TypeQuery:
			printRule(node.(List).Front().Value.(Node))
			print("?")
		case TypeStar:
			printRule(node.(List).Front().Value.(Node))
			print("*")
		case TypePlus:
			printRule(node.(List).Front().Value.(Node))
			print("+")
		default:
			fmt.Fprintf(os.Stderr, "illegal node type: %v\n", node.GetType())
		}
	}
	compileExpression := func(rule *rule, ko *label) (cko, c*k chgFlags) {
		nvar := len(rule.variables)
		if nvar > 0 {
			w.lnPrint("doarg(yyPush, %d)", nvar)
		}
		cko, c*k = compile(rule.GetExpression(), ko)
		if nvar > 0 {
			w.lnPrint("doarg(yyPop, %d)", nvar)
			cko.thPos = true
			c*k.thPos = true
		}
		return
	}
	canCompilePeek := func(node Node, jumpIfTrue bool, label *label) bool {
		if !O.peek {
			return false
		}
		switch node.GetType() {
		case TypeDot:
			label.cJump(jumpIfTrue, "(position < len(p.Buffer))")
			stats.Peek.Dot++
		case TypeCharacter:
			label.cJump(jumpIfTrue, "peekChar('%v')", node)
			stats.Peek.Char++
		case TypeClass:
			label.cJump(jumpIfTrue, "peekClass(%d)", t.Classes[node.String()].Index)
			stats.Peek.Class++
		case TypePredicate:
			label.cJump(jumpIfTrue, "(%v)", node)
		default:
			return false
		}
		return true
	}
	compile = func(node Node, ko *label) (chgko, chgok chgFlags) {
		updateFlags := func(cko, c*k chgFlags) (chgFlags, chgFlags) {
			chgko, chgok = updateChgFlags(chgko, chgok, cko, c*k)
			return chgko, chgok
		}
		switch node.GetType() {
		case TypeRule:
			fmt.Fprintf(os.Stderr, "internal error #1 (%v)\n", node)
		case TypeDot:
			ko.cJump(false, "matchDot()")
			stats.Match.Dot++
			chgok.pos = true
		case TypeName:
			varp := node.(*name).varp
			name := node.String()
			rule := t.rules[name]
			if t.inline && t.rulesCount[name] == 1 {
				chgko, chgok = compileExpression(rule, ko)
			} else {
				ko.cJump(false, "p.rules[rule%s]()", rule.GoString())
				if len(rule.variables) != 0 || rule.hasActions {
					chgok.thPos = true
				}
				chgok.pos = true // safe guess
			}
			if varp != nil {
				w.lnPrint("doarg(yySet, %d)", varp.offset)
				chgok.thPos = true
			}
		case TypeCharacter:
			ko.cJump(false, "matchChar('%v')", node)
			stats.Match.Char++
			chgok.pos = true
		case TypeString:
			if s := node.String(); s != "" {
				ko.cJump(false, "matchString(\"%s\")", s)
				stats.Match.String++
				chgok.pos = true
			}
		case TypeClass:
			ko.cJump(false, "matchClass(%d)", t.Classes[node.String()].Index)
			chgok.pos = true
		case TypePredicate:
			ko.cJump(false, "(%v)", node)
		case TypeAction:
			w.lnPrint("do(%d)", node.(Action).GetId())
			chgok.thPos = true
		case TypeCommit:
			ko.cJump(false, "(commit(thunkPosition0))")
			chgko.thPos = true
		case TypeBegin:
			if t.Actions != nil {
				w.lnPrint("begin = position")
			}
		case TypeEnd:
			if t.Actions != nil {
				w.lnPrint("end = position")
			}
		case TypeAlternate:
			list := node.(List)
			ok := w.newLabel()
			element := list.Front()
			if ok.unsafe() {
				w.begin()
				ok.save()
			}
			var next *label
			for element.Next() != nil {
				next = w.newLabel()
				cko, _ := updateFlags(compile(element.Value.(Node), next))
				ok.jump()
				if next.used {
					ok.lrestore(next, cko.pos, cko.thPos)
				}
				element = element.Next()
			}
			if next == nil || next.used {
				updateFlags(compile(element.Value.(Node), ko))
			}
			if ok.unsafe() {
				w.end()
			}
			if ok.used {
				ok.label()
			}
		case TypeUnorderedAlternate:
			list := node.(List)
			done, ok := ko, w.newLabel()
			w.begin()
			done.cJump(true, "position == len(p.Buffer)")
			w.lnPrint("switch p.Buffer[position] {")
			element := list.Front()
			for ; element != nil; element = element.Next() {
				sequence := element.Value.(List).Front()
				class := sequence.Value.(List).Front().Value.(Node).(Token).GetClass()
				node := sequence.Next().Value.(Node)

				if element.Next() == nil {
					if class.len() > 2 {
						w.lnPrint("default:")
						w.indent++
						updateFlags(compile(node, done))
						w.indent--
						break
					}
				}

				w.lnPrint("case")
				comma := false
				for d := 0; d < 256; d++ {
					if class.has(uint8(d)) {
						if comma {
							print(",")
						}
						s := ""
						switch uint8(d) {
						case '\a':
							s = `\a` /* bel */
						case '\b':
							s = `\b` /* bs */
						case '\f':
							s = `\f` /* ff */
						case '\n':
							s = `\n` /* nl */
						case '\r':
							s = `\r` /* cr */
						case '\t':
							s = `\t` /* ht */
						case '\v':
							s = `\v` /* vt */
						case '\\':
							s = `\\` /* \ */
						case '\'':
							s = `\'` /* ' */
						default:
							switch {
							case d >= 0 && d < 32 || d >= 0x80:
								s = fmt.Sprintf("\\%03o", d)
							default:
								s = fmt.Sprintf("%c", d)
							}
						}
						print(" '%s'", s)
						comma = true
					}
				}
				print(":")
				w.indent++
				if O.unorderedFirstItem {
					updateFlags(compileOptFirst(w, node, done, compile))
				} else {
					updateFlags(compile(node, done))
				}
				w.lnPrint("break")
				w.indent--
				if element.Next() == nil {
					w.lnPrint("default:")
					w.indent++
					done.jump()
					w.indent--
				}
			}
			w.lnPrint("}")
			w.end()
			if ok.used {
				ok.label()
			}
		case TypeSequence:
			var cs []string
			var peek Type
			var element0 = node.(List).Front()

			if O.seqPeekNot {
				for el := element0; el != nil; el = el.Next() {
					sub := el.Value.(Node)
					switch typ := sub.GetType(); typ {
					case TypePeekNot:
						switch child := sub.(List).Front().Value.(Node); child.GetType() {
						case TypeCharacter:
							cs = append(cs, "'"+child.String()+"'")
							continue
						}
					case TypeDot:
						if len(cs) > 0 {
							peek = typ
							element0 = el.Next()
						}
					default:
						if len(cs) > 1 {
							peek = typ
							element0 = el
						}
					}
					break
				}
			}

			if peek != 0 {
				stats.seqIfNot++
				ko.cJump(true, "position == len(p.Buffer)")
				w.lnPrint("switch p.Buffer[position] {")

				w.lnPrint("case %s:", strings.Join(cs, ", "))
				w.indent++
				ko.jump()
				w.indent--
				w.lnPrint("default:")
				w.indent++
				if peek == TypeDot {
					w.lnPrint("position++")
					chgok.pos = true
				}
			}
			for element := element0; element != nil; element = element.Next() {
				cko, c*k := compile(element.Value.(Node), ko)
				if element.Next() == nil {
					if chgok.pos {
						cko.pos = true
					}
					if chgok.thPos {
						cko.thPos = true
					}
				}
				updateFlags(cko, c*k)
			}
			if peek != 0 {
				w.indent--
				w.lnPrint("}")
			}
		case TypePeekFor:
			sub := node.(List).Front().Value.(Node)
			if canCompilePeek(sub, false, ko) {
				return
			}
			l := w.newLabel()
			l.saveBlock()
			cko, c*k := compile(sub, ko)
			l.lrestore(nil, c*k.pos, c*k.thPos)
			chgko = cko
		case TypePeekNot:
			sub := node.(List).Front().Value.(Node)
			if canCompilePeek(sub, true, ko) {
				return
			}
			ok := w.newLabel()
			ok.saveBlock()
			cko, c*k := compile(sub, ok)
			ko.jump()
			if ok.used {
				ok.restore(cko.pos, cko.thPos)
			}
			chgko = c*k
		case TypeQuery:
			sub := node.(List).Front().Value.(Node)
			switch sub.GetType() {
			case TypeCharacter:
				w.lnPrint("matchChar('%v')", sub)
				chgok.pos = true
				return
			case TypeDot:
				w.lnPrint("matchDot()")
				chgok.pos = true
				return
			}
			qko := w.newLabel()
			qok := w.newLabel()
			qko.saveBlock()
			cko, c*k := compile(sub, qko)
			if qko.unsafe() {
				qok.jump()
			}
			if qko.used {
				qko.restore(cko.pos, cko.thPos)
			}
			if qko.unsafe() {
				qok.label()
			}
			chgok = c*k
		case TypeStar:
			again := w.newLabel()
			out := w.newLabel()
			again.label()
			out.saveBlock()
			cko, c*k := compile(node.(List).Front().Value.(Node), out)
			again.jump()
			out.restore(cko.pos, cko.thPos)
			chgok = c*k
		case TypePlus:
			again := w.newLabel()
			out := w.newLabel()
			updateFlags(compile(node.(List).Front().Value.(Node), ko))
			again.label()
			out.saveBlock()
			cko, _ := compile(node.(List).Front().Value.(Node), out)
			again.jump()
			if out.used {
				out.restore(cko.pos, cko.thPos)
			}
		case TypeNil:
		default:
			fmt.Fprintf(os.Stderr, "illegal node type: %v\n", node.GetType())
		}
		return
	}

	// dry compilation
	// figure out which items need to restore position resp. thunkPosition,
	// storing into w.saveFlags
	w.setDry(true)
	for element := t.Front(); element != nil; element = element.Next() {
		node := element.Value.(Node)
		if node.GetType() != TypeRule {
			continue
		}
		rule := node.(*rule)
		expression := rule.GetExpression()
		if expression == nilNode {
			continue
		}
		ko := w.newLabel()
		ko.sid = 0
		if count, ok := t.rulesCount[rule.String()]; !ok {
		} else if t.inline && count == 1 && ko.id != 0 {
			continue
		}
		ko.save()
		cko, _ := compileExpression(rule, ko)
		if ko.used {
			ko.restore(cko.pos, cko.thPos)
		}
	}
	w.setDry(false)
	if Verbose {
		log.Printf("%+v\n", stats)
	}
	tpl := template.New("parser")
	tpl.Funcs(template.FuncMap{
		"len":      itemLength,
		"def":      func(key string) string { return t.defines[key] },
		"id":	func(identifier string) string {
			if t.defines["noexport"] != "" {
				return identifier
			}
			return strings.Title(identifier)
		},
		"stats":    func() *statValues { return &stats },
		"nvar":     func() int { return nvar },
		"numRules": func() int { return len(t.rules) },
		"sortedRules": func() (r []*rule) {
			for el := t.Front(); el != nil; el = el.Next() {
				node := el.Value.(Node)
				if node.GetType() != TypeRule {
					continue
				}
				r = append(r, node.(*rule))
			}
			return
		},
		"hasCommit": func() bool { return counts[TypeCommit] > 0 },
		"actionBits": func() (bits int) {
			for n := len(t.Actions); n != 0; n >>= 1 {
				bits++
			}
			switch {
			case bits < 8:
				bits = 8
			case bits < 16:
				bits = 16
			case bits < 32:
				bits = 32
			case bits < 64:
				bits = 64
			}
			return
		},
	})
	if _, err := tpl.Parse(parserTemplate); err != nil {
		log.Fatal(err)
	}
	if err := tpl.Execute(w, t); err != nil {
		log.Fatal(err)
	}

	/* now for the real compile pass */
	for element := t.Front(); element != nil; element = element.Next() {
		node := element.Value.(Node)
		if node.GetType() != TypeRule {
			continue
		}
		rule := node.(*rule)
		expression := rule.GetExpression()
		if expression == nilNode {
			fmt.Fprintf(os.Stderr, "rule '%v' used but not defined\n", rule)
			w.lnPrint("nil,")
			continue
		}
		ko := w.newLabel()
		ko.sid = 0
		w.lnPrint("/* %v ", rule.GetId())
		printRule(rule)
		print(" */")
		if count, ok := t.rulesCount[rule.String()]; !ok {
			fmt.Fprintf(os.Stderr, "rule '%v' defined but not used\n", rule)
		} else if t.inline && count == 1 && ko.id != 0 {
			w.lnPrint("nil,")
			continue
		}
		w.lnPrint("func() bool {")
		w.indent++
		ko.save()
		cko, _ := compileExpression(rule, ko)
		w.lnPrint("return true")
		if ko.used {
			ko.restore(cko.pos, cko.thPos)
			w.lnPrint("return false")
		}
		w.indent--
		w.lnPrint("},")
	}
	print("\n\t}")
	print("\n}\n")

	for _, s := range t.trailers {
		print("%s", s)
	}
}
Пример #25
0
// The command module takes as input a map, and runs that command.
//
// Parameters in the input map are:
//   :command, a list or vector, giving the command to run. Required.
//   :env, a map of names to values; if specified, these are added to the environment when running the command; optional
//   :input, a string to pass to the command's stdin; optional
func (this Command) Exec(input types.Value) (output types.Value, err error) {
	var command []string
	var commandMap types.Map
	if m, ok := input.(types.Map); ok {
		commandMap = m
	} else {
		err = errors.New("input must be a map")
		return
	}

	var commandEntry = commandMap[types.Keyword("command")]
	if commandEntry == nil {
		err = errors.New("require at least :command in input")
		return
	} else if l, ok := commandEntry.(*types.List); ok {
		var list = (*list.List)(l)
		command = make([]string, list.Len())
		var i = 0
		for e := list.Front(); e != nil; e = e.Next() {
			if elem, ok := e.Value.(types.String); ok {
				command[i] = string(elem)
				i++
			} else {
				err = errors.New(":command must be a list of strings")
				return
			}
		}
	} else if v, ok := commandEntry.(types.Vector); ok {
		var vect = ([]types.Value)(v)
		command = make([]string, len(vect))
		for i, e := range vect {
			if elem, ok := e.(types.String); ok {
				command[i] = string(elem)
			} else {
				err = errors.New(":command must be a vector of strings")
				return
			}
		}
	} else {
		err = errors.New("expected a list or vector as :command")
		return
	}
	var cmd = exec.Command(command[0], command[1:]...)

	var envEntry = commandMap[types.Keyword("env")]
	if envEntry != nil {
		if e, ok := envEntry.(types.Map); ok {
			var env = make([]string, len(e))
			var i = 0
			for k := range e {
				v := e[k]
				if kk, ok := k.(types.String); ok && len(kk) > 0 {
					if vv, ok := v.(types.String); ok && len(vv) > 0 {
						env[i] = fmt.Sprint(string(kk), "=", string(vv))
					} else {
						err = errors.New(":env values must be nonempty strings")
						return
					}
				} else {
					err = errors.New(":env keys must be nonempty strings")
					return
				}
				i++
			}
			cmd.Env = env
		} else {
			err = errors.New(":env must be a map if specified")
			return
		}
	}

	var stdinEntry = commandMap[types.Keyword("input")]
	if stdinEntry != nil {
		if stdin, ok := stdinEntry.(types.String); ok {
			cmd.Stdin = strings.NewReader(string(stdin))
		} else {
			err = errors.New(":input must be a string if specified")
			return
		}
	}

	var stderr = new(bytes.Buffer)
	var stdout = new(bytes.Buffer)
	cmd.Stderr = stderr
	cmd.Stdout = stdout
	err = cmd.Run()
	if err != nil {
		output = types.Map{
			types.Keyword("success"):     types.Bool(false),
			types.Keyword("err"):         types.String(stderr.String()),
			types.Keyword("out"):         types.String(stdout.String()),
			types.Keyword("system-time"): types.Float(cmd.ProcessState.SystemTime().Seconds()),
			types.Keyword("user-time"):   types.Float(cmd.ProcessState.UserTime().Seconds()),
		}
		return
	}

	output = types.Map{
		types.Keyword("success"):     types.Bool(true),
		types.Keyword("err"):         types.String(stderr.String()),
		types.Keyword("out"):         types.String(stdout.String()),
		types.Keyword("system-time"): types.Float(cmd.ProcessState.SystemTime().Seconds()),
		types.Keyword("user-time"):   types.Float(cmd.ProcessState.UserTime().Seconds()),
	}
	return
}