79 lines
2.5 KiB
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
|
|
}
|