123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- package ini
- import (
- "fmt"
- "sort"
- )
- // Visitor is an interface used by walkers that will
- // traverse an array of ASTs.
- type Visitor interface {
- VisitExpr(AST) error
- VisitStatement(AST) error
- }
- // DefaultVisitor is used to visit statements and expressions
- // and ensure that they are both of the correct format.
- // In addition, upon visiting this will build sections and populate
- // the Sections field which can be used to retrieve profile
- // configuration.
- type DefaultVisitor struct {
- scope string
- Sections Sections
- }
- // NewDefaultVisitor return a DefaultVisitor
- func NewDefaultVisitor() *DefaultVisitor {
- return &DefaultVisitor{
- Sections: Sections{
- container: map[string]Section{},
- },
- }
- }
- // VisitExpr visits expressions...
- func (v *DefaultVisitor) VisitExpr(expr AST) error {
- t := v.Sections.container[v.scope]
- if t.values == nil {
- t.values = values{}
- }
- switch expr.Kind {
- case ASTKindExprStatement:
- opExpr := expr.GetRoot()
- switch opExpr.Kind {
- case ASTKindEqualExpr:
- children := opExpr.GetChildren()
- if len(children) <= 1 {
- return NewParseError("unexpected token type")
- }
- rhs := children[1]
- if rhs.Root.Type() != TokenLit {
- return NewParseError("unexpected token type")
- }
- key := EqualExprKey(opExpr)
- v, err := newValue(rhs.Root.ValueType, rhs.Root.base, rhs.Root.Raw())
- if err != nil {
- return err
- }
- t.values[key] = v
- default:
- return NewParseError(fmt.Sprintf("unsupported expression %v", expr))
- }
- default:
- return NewParseError(fmt.Sprintf("unsupported expression %v", expr))
- }
- v.Sections.container[v.scope] = t
- return nil
- }
- // VisitStatement visits statements...
- func (v *DefaultVisitor) VisitStatement(stmt AST) error {
- switch stmt.Kind {
- case ASTKindCompletedSectionStatement:
- child := stmt.GetRoot()
- if child.Kind != ASTKindSectionStatement {
- return NewParseError(fmt.Sprintf("unsupported child statement: %T", child))
- }
- name := string(child.Root.Raw())
- v.Sections.container[name] = Section{}
- v.scope = name
- default:
- return NewParseError(fmt.Sprintf("unsupported statement: %s", stmt.Kind))
- }
- return nil
- }
- // Sections is a map of Section structures that represent
- // a configuration.
- type Sections struct {
- container map[string]Section
- }
- // GetSection will return section p. If section p does not exist,
- // false will be returned in the second parameter.
- func (t Sections) GetSection(p string) (Section, bool) {
- v, ok := t.container[p]
- return v, ok
- }
- // values represents a map of union values.
- type values map[string]Value
- // List will return a list of all sections that were successfully
- // parsed.
- func (t Sections) List() []string {
- keys := make([]string, len(t.container))
- i := 0
- for k := range t.container {
- keys[i] = k
- i++
- }
- sort.Strings(keys)
- return keys
- }
- // Section contains a name and values. This represent
- // a sectioned entry in a configuration file.
- type Section struct {
- Name string
- values values
- }
- // Has will return whether or not an entry exists in a given section
- func (t Section) Has(k string) bool {
- _, ok := t.values[k]
- return ok
- }
- // ValueType will returned what type the union is set to. If
- // k was not found, the NoneType will be returned.
- func (t Section) ValueType(k string) (ValueType, bool) {
- v, ok := t.values[k]
- return v.Type, ok
- }
- // Bool returns a bool value at k
- func (t Section) Bool(k string) bool {
- return t.values[k].BoolValue()
- }
- // Int returns an integer value at k
- func (t Section) Int(k string) int64 {
- return t.values[k].IntValue()
- }
- // Float64 returns a float value at k
- func (t Section) Float64(k string) float64 {
- return t.values[k].FloatValue()
- }
- // String returns the string value at k
- func (t Section) String(k string) string {
- _, ok := t.values[k]
- if !ok {
- return ""
- }
- return t.values[k].StringValue()
- }
|