66 lines
2.2 KiB
Go
66 lines
2.2 KiB
Go
package parse
|
|
|
|
import (
|
|
"git.makaay.nl/mauricem/go-parsekit/parse"
|
|
"git.makaay.nl/mauricem/go-parsekit/tokenize"
|
|
"git.makaay.nl/mauricem/go-toml/ast"
|
|
)
|
|
|
|
// Some globally useful tokenizer definitions.
|
|
var (
|
|
c, a, m, tok = tokenize.C, tokenize.A, tokenize.M, tokenize.T
|
|
|
|
// From the specs: "Whitespace means tab (0x09) or space (0x20)."
|
|
// In this package, we name this a blank, to be in line with the
|
|
// terminology as used in parsekit.
|
|
blank = a.Runes('\t', ' ')
|
|
blanks = c.OneOrMore(blank)
|
|
optionalBlanks = c.ZeroOrMore(blank)
|
|
dropBlanks = m.Drop(optionalBlanks)
|
|
|
|
// Newline means LF (0x0A) or CRLF (0x0D0A).
|
|
// This matches the default newline as defined by parsekit.
|
|
newline = a.Newline
|
|
|
|
// Whitespace is defined as blanks + newlines.
|
|
whitespace = c.OneOrMore(blank.Or(newline))
|
|
optionalWhitespace = c.ZeroOrMore(blank.Or(newline))
|
|
dropWhitespace = m.Drop(optionalWhitespace)
|
|
|
|
// A '#' hash symbol marks the rest of the line as a comment.
|
|
// All characters up to the end of the line are included in the comment.
|
|
comment = c.Seq(a.Hash, c.ZeroOrMore(c.Not(a.EndOfLine)), m.Drop(a.EndOfLine))
|
|
|
|
endOfLineOrComment = optionalBlanks.Then(a.EndOfLine.Or(comment))
|
|
whitespaceOrComment = c.OneOrMore(c.Any(blank, newline, comment))
|
|
optionalWhitespaceOrComment = c.Optional(whitespaceOrComment)
|
|
)
|
|
|
|
// parser embeds the TOML ast.Document, so it can be extended with methods
|
|
// that implement the parsing logic. This makes the ast.Document part of
|
|
// the state of the parser, making it possible to let parsing code call
|
|
// ast.Document methods directly to build the abstract syntax tree for the
|
|
// parsed TOML input.
|
|
type parser struct {
|
|
*ast.Document
|
|
}
|
|
|
|
func newParser() *parser {
|
|
doc := ast.NewDocument()
|
|
return &parser{doc}
|
|
}
|
|
|
|
// Run the TOML parser against the provided input data.
|
|
//
|
|
// For an overview of allowed inputs, take a look at the documentation for
|
|
// parsekit.read.New().
|
|
//
|
|
// This function returns a TOML ast structure and an error (or nil when
|
|
// no error occurred). When an error occurred, the TOML ast struct will
|
|
// contain the data that could be parsed up to the error.
|
|
func Run(input interface{}) (ast.Table, error) {
|
|
p := newParser()
|
|
err := parse.New(p.startDocument)(input)
|
|
return p.Root, err
|
|
}
|