115 lines
2.3 KiB
Go
115 lines
2.3 KiB
Go
package parsec
|
|
|
|
func Nil(p Pointer) (Node, Pointer) {
|
|
return nil, p
|
|
}
|
|
|
|
func Never(p Pointer) (Node, Pointer) {
|
|
return Error{p.pos, "Never matches"}, p
|
|
}
|
|
|
|
func And(parsers ...Parserish) Parser {
|
|
if len(parsers) == 0 {
|
|
return Nil
|
|
}
|
|
|
|
ps := ParsifyAll(parsers...)
|
|
|
|
return func(p Pointer) (Node, Pointer) {
|
|
var nodes = make([]Node, 0, len(ps))
|
|
var node Node
|
|
newP := p
|
|
for _, parser := range ps {
|
|
node, newP = parser(newP)
|
|
if node == nil {
|
|
continue
|
|
}
|
|
if IsError(node) {
|
|
return node, p
|
|
}
|
|
nodes = append(nodes, node)
|
|
}
|
|
return NewSequence(p.pos, nodes...), newP
|
|
}
|
|
}
|
|
|
|
func Any(parsers ...Parserish) Parser {
|
|
if len(parsers) == 0 {
|
|
return Nil
|
|
}
|
|
|
|
ps := ParsifyAll(parsers...)
|
|
|
|
return func(p Pointer) (Node, Pointer) {
|
|
errors := []Error{}
|
|
for _, parser := range ps {
|
|
node, newP := parser(p)
|
|
if err, isErr := node.(Error); isErr {
|
|
errors = append(errors, err)
|
|
continue
|
|
}
|
|
return node, newP
|
|
}
|
|
|
|
longestError := errors[0]
|
|
for _, e := range errors[1:] {
|
|
if e.pos > longestError.pos {
|
|
longestError = e
|
|
}
|
|
}
|
|
|
|
return longestError, p
|
|
}
|
|
}
|
|
|
|
func Kleene(opScan Parserish, sepScan ...Parserish) Parser {
|
|
return manyImpl(0, opScan, Never, sepScan...)
|
|
}
|
|
|
|
func KleeneUntil(opScan Parserish, untilScan Parserish, sepScan ...Parserish) Parser {
|
|
return manyImpl(0, opScan, untilScan, sepScan...)
|
|
}
|
|
|
|
func Many(opScan Parserish, sepScan ...Parserish) Parser {
|
|
return manyImpl(1, opScan, Never, sepScan...)
|
|
}
|
|
|
|
func ManyUntil(opScan Parserish, untilScan Parserish, sepScan ...Parserish) Parser {
|
|
return manyImpl(1, opScan, untilScan, sepScan...)
|
|
}
|
|
|
|
func manyImpl(min int, op Parserish, until Parserish, sep ...Parserish) Parser {
|
|
opParser := Parsify(op)
|
|
untilParser := Parsify(until)
|
|
sepParser := Nil
|
|
if len(sep) > 0 {
|
|
sepParser = Parsify(sep[0])
|
|
}
|
|
|
|
return func(p Pointer) (Node, Pointer) {
|
|
var node Node
|
|
nodes := make([]Node, 0)
|
|
newP := p
|
|
for {
|
|
if node, _ := untilParser(newP); !IsError(node) {
|
|
if len(nodes) < min {
|
|
return NewError(newP.pos, "Unexpected input"), p
|
|
}
|
|
break
|
|
}
|
|
|
|
if node, newP = opParser(newP); IsError(node) {
|
|
if len(nodes) < min {
|
|
return node, p
|
|
}
|
|
break
|
|
}
|
|
nodes = append(nodes, node)
|
|
if node, newP = sepParser(newP); IsError(node) {
|
|
break
|
|
}
|
|
}
|
|
return NewSequence(p.pos, nodes...), newP
|
|
}
|
|
}
|