code: func (t *tree) textOrTag(token item, until []itemType) (node ast.Node, halt bool) {
  	var seenComment = token.typ == itemComment
  	for token.typ == itemComment {
  		token = t.next() // skip any comments
  	}
  
  	// Two ways to end a list:
  	// 1. We found the until token (e.g. EOF)
  	if isOneOf(token.typ, until) {
  		return nil, true
  	}
  
  	// 2. The until token is a command, e.g. {else} {/template}
  	var token2 = t.next()
  	if token.typ == itemLeftDelim && isOneOf(token2.typ, until) {
  		return nil, true
  	}
  
  	t.backup()
  	switch token.typ {
  	case itemText:
  		var text = token.val
  		var next item
  		for {
  			next = t.next()
  			if next.typ != itemText {
  				break
  			}
  			text += next.val
  		}
  		t.backup()
  		var textvalue = rawtext(text, seenComment, next.typ == itemComment)
  		if len(textvalue) == 0 {
  			return nil, false
  		}
  		return &ast.RawTextNode{token.pos, textvalue}, false
  	case itemLeftDelim:
  		return t.beginTag(), false
  	case itemSoyDocStart:
  		return t.parseSoyDoc(token), false
  	default:
  		t.unexpected(token, "input")
  	}
  	return nil, false
  }
docs: // textOrTag reads raw text or recognizes the start of tags until the end tag.