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 }