package token import ( "fmt" "git.maximhutz.com/max/lambda/pkg/iterator" ) // ParseRawToken consumes the next token from the iterator if its type matches // the expected type. // Uses [iterator.Try] for automatic backtracking on failure. func ParseRawToken[T Type](i *iterator.Iterator[Token[T]], expected T) (*Token[T], error) { return iterator.Try(i, func(i *iterator.Iterator[Token[T]]) (*Token[T], error) { if tok, err := i.Next(); err != nil { return nil, err } else if tok.Type != expected { return nil, fmt.Errorf("expected token %v, got %v'", expected.Name(), tok.Value) } else { return &tok, nil } }) } // ParseList repeatedly applies a parse function, collecting results into a // slice. // Stops when the parse function returns an error. // Returns an error if fewer than minimum results are collected. func ParseList[T Type, U any](i *iterator.Iterator[Token[T]], fn func(*iterator.Iterator[Token[T]]) (U, error), minimum int) ([]U, error) { results := []U{} for { if u, err := fn(i); err != nil { if len(results) < minimum { return nil, fmt.Errorf("expected at least '%v' items, got only '%v': %w", minimum, len(results), err) } return results, nil } else { results = append(results, u) } } }