...

Source file src/github.com/noirbizarre/gonja/tokens/stream.go

Documentation: github.com/noirbizarre/gonja/tokens

     1  package tokens
     2  
     3  import "fmt"
     4  
     5  type Stream struct {
     6  	it       TokenIterator
     7  	previous *Token
     8  	current  *Token
     9  	next     *Token
    10  	backup   *Token
    11  	buffer   []*Token
    12  	tokens   []*Token
    13  }
    14  
    15  type TokenIterator interface {
    16  	Next() *Token
    17  }
    18  
    19  type chanIterator struct {
    20  	input chan *Token
    21  }
    22  
    23  func ChanIterator(input chan *Token) TokenIterator {
    24  	return &chanIterator{input}
    25  }
    26  
    27  func (ci *chanIterator) Next() *Token {
    28  	return <-ci.input
    29  }
    30  
    31  type sliceIterator struct {
    32  	input []*Token
    33  	idx   int
    34  }
    35  
    36  func SliceIterator(input []*Token) TokenIterator {
    37  	length := len(input)
    38  	var last *Token
    39  	if length > 0 {
    40  		last = input[length-1]
    41  	}
    42  	if last == nil || last.Type != EOF {
    43  		input = append(input, &Token{Type: EOF})
    44  	}
    45  	return &sliceIterator{input, 0}
    46  }
    47  
    48  func (si *sliceIterator) Next() *Token {
    49  	if si.idx < len(si.input) {
    50  		tok := si.input[si.idx]
    51  		si.idx++
    52  		return tok
    53  	} else {
    54  		return nil
    55  	}
    56  }
    57  
    58  func NewStream(input interface{}) *Stream {
    59  	var it TokenIterator
    60  
    61  	switch t := input.(type) {
    62  	case chan *Token:
    63  		it = ChanIterator(t)
    64  	case []*Token:
    65  		it = SliceIterator(t)
    66  	default:
    67  		panic(fmt.Sprintf(`Unsupported stream input type "%T"`, t))
    68  	}
    69  
    70  	s := &Stream{
    71  		it:     it,
    72  		buffer: []*Token{},
    73  		tokens: []*Token{},
    74  	}
    75  	s.init()
    76  	return s
    77  }
    78  
    79  func (s *Stream) init() {
    80  	s.current = s.nonIgnored()
    81  	if !s.End() {
    82  		s.next = s.nonIgnored()
    83  	}
    84  }
    85  
    86  func (s *Stream) nonIgnored() *Token {
    87  	var tok *Token
    88  	for tok = s.it.Next(); tok.Type == Whitespace; tok = s.it.Next() {
    89  	}
    90  	return tok
    91  }
    92  
    93  func (s *Stream) consume() *Token {
    94  	s.previous = s.current
    95  	s.current = s.next
    96  	if s.backup != nil {
    97  		s.next = s.backup
    98  		s.backup = nil
    99  	} else if s.End() {
   100  		s.next = nil
   101  	} else {
   102  		s.next = s.nonIgnored()
   103  	}
   104  	return s.previous
   105  }
   106  
   107  func (s *Stream) Current() *Token {
   108  	return s.current
   109  }
   110  
   111  func (s *Stream) Next() *Token {
   112  	return s.consume()
   113  }
   114  
   115  func (s *Stream) EOF() bool {
   116  	return s.current.Type == EOF
   117  }
   118  
   119  func (s *Stream) IsError() bool {
   120  	return s.current.Type == Error
   121  }
   122  
   123  func (s *Stream) End() bool {
   124  	return s.EOF() || s.IsError()
   125  }
   126  
   127  func (s *Stream) Peek() *Token {
   128  	return s.next
   129  }
   130  
   131  func (s *Stream) Backup() {
   132  	if s.previous == nil {
   133  		panic("Can't backup")
   134  	}
   135  	s.backup = s.next
   136  	s.next = s.current
   137  	s.current = s.previous
   138  	s.previous = nil
   139  }
   140  

View as plain text