ast.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Abstract Syntax Tree
  2. package ast
  3. import (
  4. "fmt"
  5. "strings"
  6. )
  7. import . "src.eruta.nl/beoran/ll1/common"
  8. // Species is the kind of Ast node it is. It also has some methods on it.
  9. type Species interface {
  10. Self() Species
  11. String() string
  12. }
  13. // BasicSpecies is a basic implementation of a species.
  14. type BasicSpecies struct {
  15. Name string
  16. }
  17. func (bs BasicSpecies) Self() Species {
  18. return bs
  19. }
  20. func (bs BasicSpecies) String() string {
  21. return bs.Name
  22. }
  23. func MakeSpecies(name string) Species {
  24. return BasicSpecies{Name: name}
  25. }
  26. // Astro is an abstract syntax tree that is read only
  27. type Astro interface {
  28. Value
  29. Species
  30. Parent() Ast
  31. Children() []Ast
  32. Token() Token
  33. }
  34. // Ast is an abstract syntax tree with read/write capabilities
  35. type Ast interface {
  36. Astro
  37. SetParent(Ast)
  38. AppendChild(child Ast) Ast
  39. }
  40. // BasicAst is a basic implementation of an AST.
  41. type BasicAst struct {
  42. Species
  43. parent Ast
  44. children []Ast
  45. token Token
  46. }
  47. func (ast BasicAst) Value() Value {
  48. return ast.token.Value()
  49. }
  50. func AppendChild(parent Ast, child Ast) Ast {
  51. basicParent := parent.(*BasicAst)
  52. return basicParent.AppendChild(child)
  53. }
  54. func New(kind Species, parent Ast, children []Ast, token Token) *BasicAst {
  55. ast := &BasicAst{Species: kind, parent: parent, token: token}
  56. return ast.AppendChildren(children...)
  57. }
  58. func (ast *BasicAst) AppendChildren(children ...Ast) *BasicAst {
  59. for _, child := range children {
  60. ast.AppendChild(child)
  61. }
  62. return ast
  63. }
  64. func (ast *BasicAst) AppendChild(child Ast) Ast {
  65. child.SetParent(ast)
  66. ast.children = append(ast.children, child)
  67. return ast
  68. }
  69. func NewChild(ast Ast, spec Species, token Token) Ast {
  70. child := New(spec, ast, make([]Ast, 0), token)
  71. ast.AppendChild(child)
  72. return child
  73. }
  74. func (ast BasicAst) IsKind(Species Species) bool {
  75. return ast.Species == Species
  76. }
  77. func (ast BasicAst) IsError() bool {
  78. return ast.token.Kind() == ErrorKind
  79. }
  80. func (ast BasicAst) IsNone() bool {
  81. return ast.Species == nil
  82. }
  83. func (ast BasicAst) Token() Token {
  84. return ast.token
  85. }
  86. func (ast BasicAst) Parent() Ast {
  87. return ast.parent
  88. }
  89. func (ast BasicAst) Children() []Ast {
  90. return ast.children
  91. }
  92. func (ast BasicAst) Self() Species {
  93. return ast.Species
  94. }
  95. func (ast *BasicAst) SetParent(parent Ast) {
  96. ast.parent = parent
  97. }
  98. func (ast BasicAst) Child(index int) Ast {
  99. count := len(ast.children)
  100. if index < 0 || index > count {
  101. return nil
  102. }
  103. return ast.children[index]
  104. }
  105. func Walk(ast Astro, walker func(node Astro) Astro) Astro {
  106. if found := walker(ast); found != nil {
  107. return found
  108. }
  109. for _, child := range ast.Children() {
  110. if found := Walk(child, walker); found != nil {
  111. return found
  112. }
  113. }
  114. return nil
  115. }
  116. func (ast BasicAst) String() string {
  117. return fmt.Sprintf("Ast %s: %s", ast.Species.String(), ast.token.Value().String())
  118. }
  119. func Display(ast Astro) {
  120. Walk(ast, func(node Astro) Astro {
  121. depth := Depth(node)
  122. fmt.Printf("%s", strings.Repeat("--", depth))
  123. if node != nil {
  124. fmt.Printf("Ast: %s\n", node.String())
  125. } else {
  126. fmt.Printf("Ast: nil node\n")
  127. }
  128. return nil
  129. })
  130. }
  131. func Dump(ast Astro) string {
  132. result := ""
  133. Walk(ast, func(node Astro) Astro {
  134. depth := Depth(node)
  135. result += fmt.Sprintf("%s", strings.Repeat("--", depth))
  136. if node != nil {
  137. result += fmt.Sprintf("Ast: %s\n", node.String())
  138. } else {
  139. result += fmt.Sprintf("Ast: nil node\n")
  140. }
  141. return nil
  142. })
  143. return result
  144. }
  145. func Depth(ast Astro) int {
  146. var depth int = 0
  147. parent := ast.Parent()
  148. for parent != nil {
  149. depth++
  150. parent = parent.Parent()
  151. }
  152. return depth
  153. }
  154. func CountChildren(ast Astro) int {
  155. return len(ast.Children())
  156. }
  157. func IsError(ast Astro) bool {
  158. return ast.Token().Kind() == ErrorKind
  159. }
  160. func Errors(ast Astro) []Astro {
  161. res := make([]Astro, 0)
  162. Walk(ast, func(node Astro) Astro {
  163. if node != nil && IsError(ast) {
  164. res = append(res, node)
  165. }
  166. return nil
  167. })
  168. return res
  169. }
  170. func EmptyAstArray() []Ast {
  171. return make([]Ast, 0)
  172. }
  173. func NewEmptyAst(species Species) *BasicAst {
  174. return NewAstWithToken(species, nil)
  175. }
  176. func NewAstNone() *BasicAst {
  177. return NewEmptyAst(nil)
  178. }
  179. func NewAstWithToken(Species Species, token Token) *BasicAst {
  180. return New(Species, nil, EmptyAstArray(), token)
  181. }
  182. // If AST has errors, return it as a merged error, otherwise returns nil
  183. func MergeErrors(ast Ast) error {
  184. errlist := Errors(ast)
  185. if len(errlist) < 1 {
  186. return nil
  187. }
  188. sep := ""
  189. res := ""
  190. for _, err := range errlist {
  191. res = fmt.Sprintf("%s%s%s", res, sep, err)
  192. sep = "\n"
  193. }
  194. return fmt.Errorf("%s", res)
  195. }