diff --git a/lexer/lexer.go b/lexer/lexer.go new file mode 100644 index 0000000..2ee64ef --- /dev/null +++ b/lexer/lexer.go @@ -0,0 +1,54 @@ +// Package lexer provides basic helpers to implement parsers +package lexer + +import "io" + +// StateFn is a State Function of the parser +type StateFn func() (StateFn, error) + +// Run runs a state machine until the state function either +// returns nil or an error +func Run(fn StateFn) error { + var err error + + for fn != nil && err == nil { + fn, err = fn() + } + + return err +} + +// Accept consumes a rune from the source if it meets the condition. +// it returns true if the condition was met and false if it wasn't. +func Accept(src io.RuneScanner, cond func(r rune) bool) bool { + r, _, err := src.ReadRune() + switch { + case err != nil: + return false + case cond(r): + return true + default: + _ = src.UnreadRune() + return false + } +} + +// AcceptAll consumes runes from the source as long as they meet the +// condition. it returns true if the condition was met for at least one rune, +// and false if it wasn't. +func AcceptAll(src io.RuneScanner, cond func(r rune) bool) bool { + var accepted bool + + for { + r, _, err := src.ReadRune() + switch { + case err != nil: + return accepted + case cond(r): + accepted = true + default: + _ = src.UnreadRune() + return accepted + } + } +}