121 lines
2.5 KiB
Go
121 lines
2.5 KiB
Go
|
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{})
|