58 lines
1.6 KiB
Go
58 lines
1.6 KiB
Go
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)
|
|
}
|
|
}
|