// Package parse provides tooling to build a state machine-style recursive descent parser. package parse import ( "git.makaay.nl/mauricem/go-parsekit/tokenize" ) // Func is the function signature as returned by New: a function that takes // any supported type of input, executes a parse run and returns an error // (or nil when all went right). type Func func(interface{}) error // New instantiates a new parser. // // The parser is a state machine-style recursive descent parser, in which // parse.Handler 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.) // // The startHandler argument points the parser to the parse.Handler function // that must be executed at the start of the parsing process. From there on // other parse.Handler functions can be invoked recursively to implement the // parsing process. // // This function returns a function that can be invoked to run the parser // against the provided input data. For an overview of allowed inputs, take a // look at the documentation for parsekit.read.New(). func New(startHandler Handler) Func { return new(startHandler, true) } // NewWithoutSanityChecks instantiates a new parser, which does not have // parsekit's built-in sanith checks enabled (e.g. checks for loops or // or calls to parse.API methods after an error or Stop()). // // Disabling sanity checks does improve parsing performance, but for // most use cases this is not an issue. Only disable sanity checks when // you really need the extra performance. // You can of course create a normal sanity-checked parser that is used // during development / unit testing, and an unchecked one for production. func NewWithoutSanityChecks(startHandler Handler) Func { return new(startHandler, false) } func new(startHandler Handler, sanityChecksEnabled bool) Func { if startHandler == nil { callerPanic("New", "parsekit.parse.{name}(): {name}() called with nil input at {caller}") } return func(input interface{}) error { api := &API{ tokenAPI: tokenize.NewAPI(input), loopCheck: make(map[filepos]bool), sanityChecksEnabled: sanityChecksEnabled, } if api.Handle(startHandler) { // Handle returned true, indicating that parsing could still continue. // There was no error and that the parsing has not actively been Stop()-ed. // Let's assume that we actually reached the end of the parsing successfully // and try to make the best of it. api.ExpectEndOfFile() } return api.err } }