From 27ca07b8a0d911ce0af70e6cd6e45344f40e45a2 Mon Sep 17 00:00:00 2001 From: Alejandro Mery Date: Wed, 30 Aug 2023 02:26:04 +0100 Subject: [PATCH] parser: introduce parsing callbacks Signed-off-by: Alejandro Mery --- parser/lexer.go | 2 ++ parser/parser.go | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/parser/lexer.go b/parser/lexer.go index b1a4a3e..2db36e9 100644 --- a/parser/lexer.go +++ b/parser/lexer.go @@ -8,6 +8,8 @@ import ( // Run parses the source func (p *Parser) Run() error { + p.setDefaults() + p.pos.Reset() return lexer.Run(p.lexStart) } diff --git a/parser/parser.go b/parser/parser.go index 723e589..0edfb1a 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -12,6 +12,56 @@ type Parser struct { src *lexer.Reader pos lexer.Position + + // OnSection is called after a [section] is parsed. + // Returning an error will abort the process. + OnSection func(pos lexer.Position, name, subname string, hasSubname bool) error + + // OnField is called after a `key = value` entry is parsed + // Returning an error will abort the process. + OnField func(pos lexer.Position, key, value string) error + + // OnComment is called after a comment is parsed + // Returning an error will abort the process. + OnComment func(pos lexer.Position, comment string) error + + // OnError is called after each parsing error, which you are allowed to + // override. + // OnError is called for EOF as well, but this error isn't returned as such by + // Parser.Run(). The caller will receive (nil, nil) instead indicating the + // processes terminated correctly. + OnError func(pos lexer.Position, content string, err error) error +} + +func defaultOnSection(_ lexer.Position, _, _ string, _ bool) error { return nil } +func defaultOnField(_ lexer.Position, _, _ string) error { return nil } +func defaultOnComment(_ lexer.Position, _ string) error { return nil } + +func defaultOnError(pos lexer.Position, content string, err error) error { + return &lexer.Error{ + Line: pos.Line, + Column: pos.Column, + Content: content, + Err: err, + } +} + +func (p *Parser) setDefaults() { + if p.OnSection == nil { + p.OnSection = defaultOnSection + } + + if p.OnField == nil { + p.OnField = defaultOnField + } + + if p.OnComment == nil { + p.OnComment = defaultOnComment + } + + if p.OnError == nil { + p.OnError = defaultOnError + } } // NewParser creates a dosini-style parser using