package parsekit // 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 } // ParseHandler defines the type of function that must be implemented to handle // a parsing state in a Parser state machine. // // A ParseHandler function gets a ParseAPI struct as its input. This struct holds // all the internal state for the parsing state machine and provides the // interface that the ParseHandler uses to interact with the parser. type ParseHandler func(*ParseAPI) // 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 { if startHandler == nil { callerPanic(1, "parsekit.NewParser(): NewParser() called with nil input at {caller}") } return &Parser{startHandler: startHandler} } // Execute starts the parser for the provided input. // For an overview of allowed inputs, take a look at the documentation for parsekit.reader.New(). // // When an error occurs during parsing, then this error is returned, nil otherwise. func (p *Parser) Execute(input interface{}) *Error { api := &ParseAPI{ tokenAPI: NewTokenAPI(input), loopCheck: map[string]bool{}, } if api.Handle(p.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 }