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