From 6b23201a93094d52e36a4abd4e1ab32071dc766c Mon Sep 17 00:00:00 2001 From: brettlangdon Date: Tue, 16 Jun 2015 20:12:14 -0400 Subject: [PATCH] add SectionValue.Resolve --- config/section.go | 38 ++++++++++++++++++++++++++++++- parser/parser.go | 57 +++++++++-------------------------------------- 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/config/section.go b/config/section.go index 29ed987..640ffd0 100644 --- a/config/section.go +++ b/config/section.go @@ -1,6 +1,11 @@ package config -import "encoding/json" +import ( + "encoding/json" + "errors" + "fmt" + "strings" +) type SectionValue struct { Name string @@ -70,6 +75,37 @@ func (this *SectionValue) Contains(name string) bool { return ok } +func (this *SectionValue) Resolve(setting string) (ConfigValue, error) { + parts := strings.Split(setting, ".") + var reference ConfigValue + reference = this + visited := []string{} + for { + if len(parts) == 0 { + break + } + if reference.GetType() != SECTION { + name := strings.Join(visited, ".") + return nil, errors.New(fmt.Sprintf("'%s' is a %s not a SECTION", name, reference.GetType())) + } + part := parts[0] + parts = parts[1:] + section := reference.(*SectionValue) + if section.Contains(part) == false { + name := strings.Join(visited, ".") + if len(name) > 0 { + return nil, errors.New(fmt.Sprintf("'%s' does not have setting '%s'", name, part)) + } else { + return nil, errors.New(fmt.Sprintf("setting '%s' does not exist", part)) + } + } + reference = section.Get(part) + visited = append(visited, part) + } + + return reference, nil +} + func (this *SectionValue) ToJSON() ([]byte, error) { data, err := this.ToMap() if err != nil { diff --git a/parser/parser.go b/parser/parser.go index 4807672..9a0c2bd 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -7,7 +7,6 @@ import ( "os" "path/filepath" "strconv" - "strings" "github.com/brettlangdon/forge/config" "github.com/brettlangdon/forge/token" @@ -31,43 +30,25 @@ func (this *Parser) SyntaxError(msg string) error { return errors.New(msg) } -func (this *Parser) ReferenceTypeError(names []string, expected config.ConfigType, actual config.ConfigType) error { - reference := strings.Join(names, ".") - msg := fmt.Sprintf( - "Reference type error, '%s', expected type %s instead got %s", - reference, - expected, - actual, - ) - return errors.New(msg) -} - -func (this *Parser) ReferenceMissingError(names []string, searching string) error { - reference := strings.Join(names, ".") - msg := fmt.Sprintf( - "Reference missing error, '%s' does not have key '%s'", - reference, - searching, - ) - return errors.New(msg) -} - func (this *Parser) readToken() token.Token { this.cur_tok = this.tokenizer.NextToken() return this.cur_tok } func (this *Parser) parseReference(starting_section *config.SectionValue, period bool) (config.ConfigValue, error) { - names := []string{} + name := "" if period == false { - names = append(names, this.cur_tok.Literal) + name = this.cur_tok.Literal } for { this.readToken() if this.cur_tok.ID == token.PERIOD && period == false { period = true } else if period && this.cur_tok.ID == token.IDENTIFIER { - names = append(names, this.cur_tok.Literal) + if len(name) > 0 { + name += "." + } + name += this.cur_tok.Literal period = false } else if this.cur_tok.ID == token.SEMICOLON { break @@ -76,7 +57,7 @@ func (this *Parser) parseReference(starting_section *config.SectionValue, period return nil, this.SyntaxError(msg) } } - if len(names) == 0 { + if len(name) == 0 { return nil, this.SyntaxError( fmt.Sprintf("expected IDENTIFIER instead found %s", this.cur_tok.Literal), ) @@ -86,27 +67,11 @@ func (this *Parser) parseReference(starting_section *config.SectionValue, period return nil, this.SyntaxError(fmt.Sprintf("expected IDENTIFIER after PERIOD")) } - var reference config.ConfigValue - reference = starting_section - visited := []string{} - for { - if len(names) == 0 { - break - } - if reference.GetType() != config.SECTION { - return nil, this.ReferenceTypeError(visited, config.SECTION, reference.GetType()) - } - name := names[0] - names = names[1:] - section := reference.(*config.SectionValue) - if section.Contains(name) == false { - return nil, this.ReferenceMissingError(visited, name) - } - reference = section.Get(name) - visited = append(visited, name) + value, err := starting_section.Resolve(name) + if err != nil { + err = errors.New("Reference error, " + err.Error()) } - - return reference, nil + return value, err } func (this *Parser) parseSetting(name string) error {