go-parsekit/parsekit.go

79 lines
2.5 KiB
Go

package parsekit
import (
"strings"
)
// Parser is the top-level struct that holds the configuration for a parser.
// The Parser can be instantiated using the parsekit.NewParser() method.
type Parser struct {
startHandler ParseHandler // the function that handles the very first state
}
// NewParser instantiates a new Parser.
//
// The Parser is a state machine-style recursive descent parser, in which
// ParseHandler functions are used to move the state machine forward during
// parsing. This style of parser is typically used for parsing programming
// languages and structured data formats (like json, xml, toml, etc.)
//
// To parse input data, use the method Parser.Execute().
func NewParser(startHandler ParseHandler) *Parser {
return &Parser{startHandler: startHandler}
}
// Execute starts the parser for the provided input.
// When an error occurs during parsing, then this error is returned. Nil otherwise.
func (p *Parser) Execute(input string) *Error {
api := &ParseAPI{
tokenAPI: NewTokenAPI(strings.NewReader(input)),
loopCheck: map[string]bool{},
}
api.Handle(p.startHandler)
if !api.stopped && api.err == nil {
api.UnexpectedInput()
}
return api.err
}
// Matcher is the top-level struct that holds the configuration for
// a parser that is based solely on a TokenHandler function.
// The Matcher can be instantiated using the parsekit.NewMatcher()
// method.
// TODO Rename to Tokenizer
type Matcher struct {
parser *Parser
result *Result
}
// NewMatcher instantiates a new Matcher.
//
// This is a simple wrapper around a TokenHandler function. It can be used to
// match an input string against that TokenHandler function and retrieve the
// results in a straight forward way.
//
// The 'expects' parameter is used for creating an error message in case parsed
// input does not match the TokenHandler.
// TODO Rename to NewTokenizer, and make matcher Tokeninzer, also see if we can use a Reader straight away, no ParseAPI.
func NewMatcher(tokenHandler TokenHandler, expects string) *Matcher {
matcher := &Matcher{}
matcher.parser = NewParser(func(p *ParseAPI) {
if p.On(tokenHandler).Accept() {
matcher.result = p.Result()
p.Stop()
} else {
p.Expects(expects)
p.UnexpectedInput()
}
})
return matcher
}
// Execute feeds the input to the wrapped TokenHandler function.
// It returns the TokenHandler's results. When an error occurred during parsing,
// the error will be set, nil otherwise.
func (m *Matcher) Execute(input string) (*Result, *Error) {
err := m.parser.Execute(input)
return m.result, err
}