visitor.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. package ini
  2. import (
  3. "fmt"
  4. "sort"
  5. )
  6. // Visitor is an interface used by walkers that will
  7. // traverse an array of ASTs.
  8. type Visitor interface {
  9. VisitExpr(AST) error
  10. VisitStatement(AST) error
  11. }
  12. // DefaultVisitor is used to visit statements and expressions
  13. // and ensure that they are both of the correct format.
  14. // In addition, upon visiting this will build sections and populate
  15. // the Sections field which can be used to retrieve profile
  16. // configuration.
  17. type DefaultVisitor struct {
  18. scope string
  19. Sections Sections
  20. }
  21. // NewDefaultVisitor return a DefaultVisitor
  22. func NewDefaultVisitor() *DefaultVisitor {
  23. return &DefaultVisitor{
  24. Sections: Sections{
  25. container: map[string]Section{},
  26. },
  27. }
  28. }
  29. // VisitExpr visits expressions...
  30. func (v *DefaultVisitor) VisitExpr(expr AST) error {
  31. t := v.Sections.container[v.scope]
  32. if t.values == nil {
  33. t.values = values{}
  34. }
  35. switch expr.Kind {
  36. case ASTKindExprStatement:
  37. opExpr := expr.GetRoot()
  38. switch opExpr.Kind {
  39. case ASTKindEqualExpr:
  40. children := opExpr.GetChildren()
  41. if len(children) <= 1 {
  42. return NewParseError("unexpected token type")
  43. }
  44. rhs := children[1]
  45. if rhs.Root.Type() != TokenLit {
  46. return NewParseError("unexpected token type")
  47. }
  48. key := EqualExprKey(opExpr)
  49. v, err := newValue(rhs.Root.ValueType, rhs.Root.base, rhs.Root.Raw())
  50. if err != nil {
  51. return err
  52. }
  53. t.values[key] = v
  54. default:
  55. return NewParseError(fmt.Sprintf("unsupported expression %v", expr))
  56. }
  57. default:
  58. return NewParseError(fmt.Sprintf("unsupported expression %v", expr))
  59. }
  60. v.Sections.container[v.scope] = t
  61. return nil
  62. }
  63. // VisitStatement visits statements...
  64. func (v *DefaultVisitor) VisitStatement(stmt AST) error {
  65. switch stmt.Kind {
  66. case ASTKindCompletedSectionStatement:
  67. child := stmt.GetRoot()
  68. if child.Kind != ASTKindSectionStatement {
  69. return NewParseError(fmt.Sprintf("unsupported child statement: %T", child))
  70. }
  71. name := string(child.Root.Raw())
  72. v.Sections.container[name] = Section{}
  73. v.scope = name
  74. default:
  75. return NewParseError(fmt.Sprintf("unsupported statement: %s", stmt.Kind))
  76. }
  77. return nil
  78. }
  79. // Sections is a map of Section structures that represent
  80. // a configuration.
  81. type Sections struct {
  82. container map[string]Section
  83. }
  84. // GetSection will return section p. If section p does not exist,
  85. // false will be returned in the second parameter.
  86. func (t Sections) GetSection(p string) (Section, bool) {
  87. v, ok := t.container[p]
  88. return v, ok
  89. }
  90. // values represents a map of union values.
  91. type values map[string]Value
  92. // List will return a list of all sections that were successfully
  93. // parsed.
  94. func (t Sections) List() []string {
  95. keys := make([]string, len(t.container))
  96. i := 0
  97. for k := range t.container {
  98. keys[i] = k
  99. i++
  100. }
  101. sort.Strings(keys)
  102. return keys
  103. }
  104. // Section contains a name and values. This represent
  105. // a sectioned entry in a configuration file.
  106. type Section struct {
  107. Name string
  108. values values
  109. }
  110. // Has will return whether or not an entry exists in a given section
  111. func (t Section) Has(k string) bool {
  112. _, ok := t.values[k]
  113. return ok
  114. }
  115. // ValueType will returned what type the union is set to. If
  116. // k was not found, the NoneType will be returned.
  117. func (t Section) ValueType(k string) (ValueType, bool) {
  118. v, ok := t.values[k]
  119. return v.Type, ok
  120. }
  121. // Bool returns a bool value at k
  122. func (t Section) Bool(k string) bool {
  123. return t.values[k].BoolValue()
  124. }
  125. // Int returns an integer value at k
  126. func (t Section) Int(k string) int64 {
  127. return t.values[k].IntValue()
  128. }
  129. // Float64 returns a float value at k
  130. func (t Section) Float64(k string) float64 {
  131. return t.values[k].FloatValue()
  132. }
  133. // String returns the string value at k
  134. func (t Section) String(k string) string {
  135. _, ok := t.values[k]
  136. if !ok {
  137. return ""
  138. }
  139. return t.values[k].StringValue()
  140. }