Finish and test Token combinator

This commit is contained in:
b
2026-08-20 22:54:31 -06:00
parent 5d1f4940ce
commit 6b201fbb69
3 changed files with 52 additions and 3 deletions
+15 -2
View File
@@ -1,11 +1,15 @@
// SPDX-License-Identifier: Unlicense
package bytes
import (
"git.codemonkeysoftware.net/b/gigaparsec"
)
func Token[Out, WSOut any](whitespace gigaparsec.Parser[byte, WSOut]) func(p gigaparsec.Parser[byte, Out]) gigaparsec.Parser[byte, Out] {
mappedWS := gigaparsec.Map(whitespace, func(WSOut) struct{} { return struct{}{} })
// Token wraps a parser to discard all whitespace after the parsed input.
// whitespace is a parser that will consume non-empty whitespace.
func Token[Out any](whitespace gigaparsec.Parser[byte, struct{}]) func(p gigaparsec.Parser[byte, Out]) gigaparsec.Parser[byte, Out] {
mappedWS := gigaparsec.Map(whitespace, func(struct{}) struct{} { return struct{}{} })
var ignoreWS gigaparsec.Parser[byte, struct{}] = func(s gigaparsec.State[byte]) (gigaparsec.Result[byte, struct{}], error) {
result, err := mappedWS(s)
return result.Consume(false), err
@@ -14,3 +18,12 @@ func Token[Out, WSOut any](whitespace gigaparsec.Parser[byte, WSOut]) func(p gig
return gigaparsec.Seq(p, gigaparsec.Repeat(0, ignoreWS), func(val Out, _ []struct{}) Out { return val })
}
}
func isWhitespaceASCII(b byte) bool {
return b == ' ' || (b >= '\t' && b <= '\r')
}
// WhitespaceASCII consumes one ASCII whitespace character: space, tab, LF, CR, vertical tab, or form feed.
func WhitespaceASCII() gigaparsec.Parser[byte, struct{}] {
return gigaparsec.Map(gigaparsec.Satisfy(isWhitespaceASCII), func(byte) struct{} { return struct{}{} })
}
+37
View File
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: Unlicense
package bytes_test
import (
"fmt"
"strings"
"git.codemonkeysoftware.net/b/gigaparsec"
"git.codemonkeysoftware.net/b/gigaparsec/bytes"
)
func ExampleToken() {
ptokens := gigaparsec.Choose(
bytes.MatchString("("),
bytes.MatchString(")"),
bytes.MatchString("+"),
bytes.MatchString("-"),
bytes.Regexp(`[a-zA-Z][a-zA-Z0-9_]*`).Label("identifier"),
bytes.Regexp(`[0-9]+`).Label("number"),
)
tokenize := gigaparsec.Repeat(0, bytes.Token[string](bytes.WhitespaceASCII())(ptokens))
tokens, _ := gigaparsec.Run(tokenize, strings.NewReader("(alpha + 42) -5 "))
for _, token := range tokens {
fmt.Println(token)
}
// Output:
// (
// alpha
// +
// 42
// )
// -
// 5
}