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 } // 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. // 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{}, } 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 try to make the best of it. if api.expecting != "" { api.UnexpectedInput() } else { api.ExpectEndOfFile() } } return api.err }