package parsekit // New takes an input string and a start state, // and initializes the parser for it. func New(input string, startState StateFn) *P { return &P{ input: input, len: len(input), nextState: startState, items: make(chan Item, 2), } } // Next retrieves the next parsed item. // When a valid item was found, then the boolean return parameter will be true. // On error or when successfully reaching the end of the input, false is returned. // When an error occurred, it will be set in the error return value, nil otherwise. func (p *P) Next() (Item, *Error, bool) { for { select { case i := <-p.items: switch { case i.Type == ItemEOF: return i, nil, false case i.Type == ItemError: p.err = &Error{i.Value, p.cursorRow, p.cursorColumn} return i, p.err, false default: p.item = i return i, nil, true } default: // When implementing a parser, it is mandatory to provide // a conscious state routing decision for every cycle. // This helps preventing bugs during implementation. if p.nextState == nil { panic("No next state was scheduled for the parser") } p.state, p.nextState = p.nextState, nil p.state(p) } } } // ToArray returns Parser items as an array (mainly intended for testing purposes) // When an error occurs during scanning, a partial result will be // returned, accompanied by the error that occurred. func (p *P) ToArray() ([]Item, *Error) { var items []Item for { item, err, more := p.Next() if !more { return items, err } items = append(items, item) } }