From 70f3968fb342b37cea93f185917578fd2e548a26 Mon Sep 17 00:00:00 2001 From: Alejandro Mery Date: Tue, 29 Aug 2023 00:21:36 +0000 Subject: [PATCH] basic: WIP Signed-off-by: Alejandro Mery --- README.md | 9 ++++++ basic/basic.go | 2 ++ basic/decoder.go | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ basic/types.go | 23 +++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 basic/basic.go create mode 100644 basic/decoder.go create mode 100644 basic/types.go diff --git a/README.md b/README.md index 7a27335..86a0f55 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ of stricter parsers of similar form. [godoc-lexer]: https://pkg.go.dev/asciigoat.org/core/lexer [godoc-parser-parser]: https://pkg.go.dev/asciigoat.org/ini/parser#Parser +[godoc-basic-parser]: https://pkg.go.dev/asciigoat.org/ini/basic#Decode [wikipedia-dosini]: https://en.wikipedia.org/wiki/INI_file @@ -25,6 +26,14 @@ of stricter parsers of similar form. [`asciigoat`'s lexer][godoc-lexer] to process an `INI`-style document emiting tokens and errors via callbacks. +## Basic Parser + +[`basic.Decode()`][godoc-basic-parser] provies a one-shot decoder +that returns a structured document for you to post-process. + +To allow for correct handling of repetition of section and field names downstream, it uses arrays instead of maps, and makes almost no judgment +about what section or field names are acceptable. + ## Other Implementations * [gcfg](https://pkg.go.dev/gopkg.in/gcfg.v1) diff --git a/basic/basic.go b/basic/basic.go new file mode 100644 index 0000000..6942abe --- /dev/null +++ b/basic/basic.go @@ -0,0 +1,2 @@ +// Package basic provides a basic representation of dosini-style documents +package basic diff --git a/basic/decoder.go b/basic/decoder.go new file mode 100644 index 0000000..894fdc1 --- /dev/null +++ b/basic/decoder.go @@ -0,0 +1,73 @@ +package basic + +import ( + "bytes" + "io" + "io/fs" + "log" + "strings" + + "asciigoat.org/core/lexer" + "asciigoat.org/ini/parser" +) + +type token struct { + pos lexer.Position + typ parser.TokenType + value string +} + +type decoder struct { + p *parser.Parser + out *Document + + queue []token + curSection *Section + curField *Field +} + +func (dec *decoder) OnToken(pos lexer.Position, typ parser.TokenType, value string) error { + tok := token{pos, typ, value} + + log.Printf("%s[%v]: %s %s: %q", "decoder", len(dec.queue), pos, typ, value) + + dec.queue = append(dec.queue, tok) + + return nil +} + +func (*decoder) OnError(pos lexer.Position, hint string, err error) error { + log.Printf("%s: %s %s: %s: %v", "decoder", pos, "error", hint, err) + return err +} + +// Decode ... +func Decode(r io.Reader) (*Document, error) { + var out Document + + if r == nil { + return nil, fs.ErrNotExist + } + + // parser + p := parser.NewParser(r) + // decoder + dec := decoder{p: p, out: &out} + // glue + p.OnToken = dec.OnToken + p.OnError = dec.OnError + + // Go! + err := p.Run() + return &out, err +} + +// DecodeBytes ... +func DecodeBytes(b []byte) (*Document, error) { + return Decode(bytes.NewReader(b)) +} + +// DecodeString ... +func DecodeString(s string) (*Document, error) { + return Decode(strings.NewReader(s)) +} diff --git a/basic/types.go b/basic/types.go new file mode 100644 index 0000000..daf61bd --- /dev/null +++ b/basic/types.go @@ -0,0 +1,23 @@ +package basic + +// Document ... +type Document struct { + Global []Field + + Sections []Section +} + +// Section ... +type Section struct { + Name string + Key string + HadKey bool + + Fields []Field +} + +// Field ... +type Field struct { + Key string + Value string +}