1package ini
2
3// ASTKind represents different states in the parse table
4// and the type of AST that is being constructed
5type ASTKind int
6
7// ASTKind* is used in the parse table to transition between
8// the different states
9const (
10	ASTKindNone = ASTKind(iota)
11	ASTKindStart
12	ASTKindExpr
13	ASTKindEqualExpr
14	ASTKindStatement
15	ASTKindSkipStatement
16	ASTKindExprStatement
17	ASTKindSectionStatement
18	ASTKindNestedSectionStatement
19	ASTKindCompletedNestedSectionStatement
20	ASTKindCommentStatement
21	ASTKindCompletedSectionStatement
22)
23
24func (k ASTKind) String() string {
25	switch k {
26	case ASTKindNone:
27		return "none"
28	case ASTKindStart:
29		return "start"
30	case ASTKindExpr:
31		return "expr"
32	case ASTKindStatement:
33		return "stmt"
34	case ASTKindSectionStatement:
35		return "section_stmt"
36	case ASTKindExprStatement:
37		return "expr_stmt"
38	case ASTKindCommentStatement:
39		return "comment"
40	case ASTKindNestedSectionStatement:
41		return "nested_section_stmt"
42	case ASTKindCompletedSectionStatement:
43		return "completed_stmt"
44	case ASTKindSkipStatement:
45		return "skip"
46	default:
47		return ""
48	}
49}
50
51// AST interface allows us to determine what kind of node we
52// are on and casting may not need to be necessary.
53//
54// The root is always the first node in Children
55type AST struct {
56	Kind      ASTKind
57	Root      Token
58	RootToken bool
59	Children  []AST
60}
61
62func newAST(kind ASTKind, root AST, children ...AST) AST {
63	return AST{
64		Kind:     kind,
65		Children: append([]AST{root}, children...),
66	}
67}
68
69func newASTWithRootToken(kind ASTKind, root Token, children ...AST) AST {
70	return AST{
71		Kind:      kind,
72		Root:      root,
73		RootToken: true,
74		Children:  children,
75	}
76}
77
78// AppendChild will append to the list of children an AST has.
79func (a *AST) AppendChild(child AST) {
80	a.Children = append(a.Children, child)
81}
82
83// GetRoot will return the root AST which can be the first entry
84// in the children list or a token.
85func (a *AST) GetRoot() AST {
86	if a.RootToken {
87		return *a
88	}
89
90	if len(a.Children) == 0 {
91		return AST{}
92	}
93
94	return a.Children[0]
95}
96
97// GetChildren will return the current AST's list of children
98func (a *AST) GetChildren() []AST {
99	if len(a.Children) == 0 {
100		return []AST{}
101	}
102
103	if a.RootToken {
104		return a.Children
105	}
106
107	return a.Children[1:]
108}
109
110// SetChildren will set and override all children of the AST.
111func (a *AST) SetChildren(children []AST) {
112	if a.RootToken {
113		a.Children = children
114	} else {
115		a.Children = append(a.Children[:1], children...)
116	}
117}
118
119// Start is used to indicate the starting state of the parse table.
120var Start = newAST(ASTKindStart, AST{})
121