8 // Visitor is an interface used by walkers that will
9 // traverse an array of ASTs.
10 type Visitor interface {
12 VisitStatement(AST) error
15 // DefaultVisitor is used to visit statements and expressions
16 // and ensure that they are both of the correct format.
17 // In addition, upon visiting this will build sections and populate
18 // the Sections field which can be used to retrieve profile
20 type DefaultVisitor struct {
25 // NewDefaultVisitor return a DefaultVisitor
26 func NewDefaultVisitor() *DefaultVisitor {
27 return &DefaultVisitor{
29 container: map[string]Section{},
34 // VisitExpr visits expressions...
35 func (v *DefaultVisitor) VisitExpr(expr AST) error {
36 t := v.Sections.container[v.scope]
42 case ASTKindExprStatement:
43 opExpr := expr.GetRoot()
45 case ASTKindEqualExpr:
46 children := opExpr.GetChildren()
47 if len(children) <= 1 {
48 return NewParseError("unexpected token type")
53 if rhs.Root.Type() != TokenLit {
54 return NewParseError("unexpected token type")
57 key := EqualExprKey(opExpr)
58 v, err := newValue(rhs.Root.ValueType, rhs.Root.base, rhs.Root.Raw())
65 return NewParseError(fmt.Sprintf("unsupported expression %v", expr))
68 return NewParseError(fmt.Sprintf("unsupported expression %v", expr))
71 v.Sections.container[v.scope] = t
75 // VisitStatement visits statements...
76 func (v *DefaultVisitor) VisitStatement(stmt AST) error {
78 case ASTKindCompletedSectionStatement:
79 child := stmt.GetRoot()
80 if child.Kind != ASTKindSectionStatement {
81 return NewParseError(fmt.Sprintf("unsupported child statement: %T", child))
84 name := string(child.Root.Raw())
85 v.Sections.container[name] = Section{}
88 return NewParseError(fmt.Sprintf("unsupported statement: %s", stmt.Kind))
94 // Sections is a map of Section structures that represent
96 type Sections struct {
97 container map[string]Section
100 // GetSection will return section p. If section p does not exist,
101 // false will be returned in the second parameter.
102 func (t Sections) GetSection(p string) (Section, bool) {
103 v, ok := t.container[p]
107 // values represents a map of union values.
108 type values map[string]Value
110 // List will return a list of all sections that were successfully
112 func (t Sections) List() []string {
113 keys := make([]string, len(t.container))
115 for k := range t.container {
124 // Section contains a name and values. This represent
125 // a sectioned entry in a configuration file.
126 type Section struct {
131 // Has will return whether or not an entry exists in a given section
132 func (t Section) Has(k string) bool {
137 // ValueType will returned what type the union is set to. If
138 // k was not found, the NoneType will be returned.
139 func (t Section) ValueType(k string) (ValueType, bool) {
144 // Bool returns a bool value at k
145 func (t Section) Bool(k string) bool {
146 return t.values[k].BoolValue()
149 // Int returns an integer value at k
150 func (t Section) Int(k string) int64 {
151 return t.values[k].IntValue()
154 // Float64 returns a float value at k
155 func (t Section) Float64(k string) float64 {
156 return t.values[k].FloatValue()
159 // String returns the string value at k
160 func (t Section) String(k string) string {
165 return t.values[k].StringValue()