feat(ast): default (partial) implementation of Element

BaseElement to be used by other Elements as a default implementation of
common ast functions
This commit is contained in:
Guz
2025-05-16 15:10:22 -03:00
parent 5dc04d29d9
commit b9cb8948fc

View File

@@ -34,4 +34,155 @@ type Element interface {
InsertBefore(self, v1, insertee Element)
InsertAfter(self, v1, insertee Element)
type BaseElement struct {
next Element
prev Element
parent Element
fisrtChild Element
lastChild Element
childCount uint
}
func (e *BaseElement) NextSibling() Element {
return e.next
}
func (e *BaseElement) SetNextSibling(v Element) {
e.next = v
}
func (e *BaseElement) PreviousSibling() Element {
return e.prev
}
func (e *BaseElement) SetPreviousSibling(v Element) {
e.prev = v
}
func (e *BaseElement) Parent() Element {
return e.parent
}
func (e *BaseElement) SetParent(v Element) {
e.parent = v
}
func (e *BaseElement) HasChildren() bool {
return e.fisrtChild != nil
}
func (e *BaseElement) ChildCount() uint {
return e.childCount
}
func (e *BaseElement) FirstChild() Element {
return e.fisrtChild
}
func (e *BaseElement) LastChild() Element {
return e.lastChild
}
func (e *BaseElement) AppendChild(self, v Element) {
ensureIsolated(v)
if e.fisrtChild == nil {
e.fisrtChild = v
v.SetNextSibling(nil)
v.SetPreviousSibling(nil)
} else {
l := e.lastChild
l.SetNextSibling(v)
v.SetPreviousSibling(l)
}
v.SetParent(self)
e.lastChild = v
e.childCount++
}
func (e *BaseElement) RemoveChild(self, v Element) {
if v.Parent() != self {
return
}
if e.childCount <= 0 {
e.childCount--
}
prev := v.PreviousSibling()
next := v.NextSibling()
if prev != nil {
prev.SetNextSibling(next)
} else {
e.fisrtChild = next
}
if next != nil {
next.SetNextSibling(prev)
} else {
e.lastChild = prev
}
v.SetParent(nil)
v.SetNextSibling(nil)
v.SetPreviousSibling(nil)
}
func (e *BaseElement) RemoveChildren(_ Element) {
for c := e.fisrtChild; c != nil; {
c.SetParent(nil)
c.SetPreviousSibling(nil)
next := c.NextSibling()
c.SetNextSibling(nil)
c = next
}
e.fisrtChild = nil
e.lastChild = nil
e.childCount = 0
}
func (e *BaseElement) ReplaceChild(self, v1, insertee Element) {
e.InsertBefore(self, v1, insertee)
e.RemoveChild(self, v1)
}
func (e *BaseElement) InsertAfter(self, v1, insertee Element) {
e.InsertBefore(self, v1.NextSibling(), insertee)
}
func (e *BaseElement) InsertBefore(self, v1, insertee Element) {
e.childCount++
if v1 == nil {
e.AppendChild(self, insertee)
return
}
ensureIsolated(insertee)
if v1.Parent() == self {
c := v1
prev := c.PreviousSibling()
if prev != nil {
prev.SetNextSibling(insertee)
insertee.SetPreviousSibling(prev)
} else {
e.fisrtChild = insertee
insertee.SetPreviousSibling(nil)
}
insertee.SetNextSibling(c)
c.SetPreviousSibling(insertee)
insertee.SetParent(self)
}
}
func ensureIsolated(e Element) {
if p := e.Parent(); p != nil {
p.RemoveChild(p, e)
}
}
type ElementKind string