| package ini |
| |
| // ASTKind represents different states in the parse table |
| // and the type of AST that is being constructed |
| type ASTKind int |
| |
| // ASTKind* is used in the parse table to transition between |
| // the different states |
| const ( |
| ASTKindNone = ASTKind(iota) |
| ASTKindStart |
| ASTKindExpr |
| ASTKindEqualExpr |
| ASTKindStatement |
| ASTKindSkipStatement |
| ASTKindExprStatement |
| ASTKindSectionStatement |
| ASTKindNestedSectionStatement |
| ASTKindCompletedNestedSectionStatement |
| ASTKindCommentStatement |
| ASTKindCompletedSectionStatement |
| ) |
| |
| func (k ASTKind) String() string { |
| switch k { |
| case ASTKindNone: |
| return "none" |
| case ASTKindStart: |
| return "start" |
| case ASTKindExpr: |
| return "expr" |
| case ASTKindStatement: |
| return "stmt" |
| case ASTKindSectionStatement: |
| return "section_stmt" |
| case ASTKindExprStatement: |
| return "expr_stmt" |
| case ASTKindCommentStatement: |
| return "comment" |
| case ASTKindNestedSectionStatement: |
| return "nested_section_stmt" |
| case ASTKindCompletedSectionStatement: |
| return "completed_stmt" |
| case ASTKindSkipStatement: |
| return "skip" |
| default: |
| return "" |
| } |
| } |
| |
| // AST interface allows us to determine what kind of node we |
| // are on and casting may not need to be necessary. |
| // |
| // The root is always the first node in Children |
| type AST struct { |
| Kind ASTKind |
| Root Token |
| RootToken bool |
| Children []AST |
| } |
| |
| func newAST(kind ASTKind, root AST, children ...AST) AST { |
| return AST{ |
| Kind: kind, |
| Children: append([]AST{root}, children...), |
| } |
| } |
| |
| func newASTWithRootToken(kind ASTKind, root Token, children ...AST) AST { |
| return AST{ |
| Kind: kind, |
| Root: root, |
| RootToken: true, |
| Children: children, |
| } |
| } |
| |
| // AppendChild will append to the list of children an AST has. |
| func (a *AST) AppendChild(child AST) { |
| a.Children = append(a.Children, child) |
| } |
| |
| // GetRoot will return the root AST which can be the first entry |
| // in the children list or a token. |
| func (a *AST) GetRoot() AST { |
| if a.RootToken { |
| return *a |
| } |
| |
| if len(a.Children) == 0 { |
| return AST{} |
| } |
| |
| return a.Children[0] |
| } |
| |
| // GetChildren will return the current AST's list of children |
| func (a *AST) GetChildren() []AST { |
| if len(a.Children) == 0 { |
| return []AST{} |
| } |
| |
| if a.RootToken { |
| return a.Children |
| } |
| |
| return a.Children[1:] |
| } |
| |
| // SetChildren will set and override all children of the AST. |
| func (a *AST) SetChildren(children []AST) { |
| if a.RootToken { |
| a.Children = children |
| } else { |
| a.Children = append(a.Children[:1], children...) |
| } |
| } |
| |
| // Start is used to indicate the starting state of the parse table. |
| var Start = newAST(ASTKindStart, AST{}) |