ast.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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. specname := "<no spec>"
  118. if ast.Species != nil {
  119. specname = ast.Species.String()
  120. }
  121. tokval := "<no token>"
  122. if ast.token != nil {
  123. tokval = ast.token.Text()
  124. /* if ast.token.Value() != nil {
  125. tokval = ast.token.Value().String()
  126. } */
  127. }
  128. return fmt.Sprintf("Ast %s: %s", specname, tokval)
  129. }
  130. func Display(ast Astro) {
  131. Walk(ast, func(node Astro) Astro {
  132. depth := Depth(node)
  133. fmt.Printf("%s", strings.Repeat("--", depth))
  134. if node != nil {
  135. fmt.Printf("Ast: %s\n", node.String())
  136. } else {
  137. fmt.Printf("Ast: nil node\n")
  138. }
  139. return nil
  140. })
  141. }
  142. func Dump(ast Astro) string {
  143. result := ""
  144. Walk(ast, func(node Astro) Astro {
  145. depth := Depth(node)
  146. result += fmt.Sprintf("%s", strings.Repeat("--", depth))
  147. if node != nil {
  148. result += fmt.Sprintf("Ast: %s\n", node.String())
  149. } else {
  150. result += fmt.Sprintf("Ast: nil node\n")
  151. }
  152. return nil
  153. })
  154. return result
  155. }
  156. func Depth(ast Astro) int {
  157. var depth int = 0
  158. parent := ast.Parent()
  159. for parent != nil {
  160. depth++
  161. parent = parent.Parent()
  162. }
  163. return depth
  164. }
  165. func CountChildren(ast Astro) int {
  166. return len(ast.Children())
  167. }
  168. func IsError(ast Astro) bool {
  169. return ast.Token().Kind() == ErrorKind
  170. }
  171. func Errors(ast Astro) []Astro {
  172. res := make([]Astro, 0)
  173. Walk(ast, func(node Astro) Astro {
  174. if node != nil && IsError(ast) {
  175. res = append(res, node)
  176. }
  177. return nil
  178. })
  179. return res
  180. }
  181. func EmptyAstArray() []Ast {
  182. return make([]Ast, 0)
  183. }
  184. func NewEmptyAst(species Species) *BasicAst {
  185. return NewAstWithToken(species, nil)
  186. }
  187. func NewAstNone() *BasicAst {
  188. return NewEmptyAst(nil)
  189. }
  190. func NewAstWithToken(Species Species, token Token) *BasicAst {
  191. return New(Species, nil, EmptyAstArray(), token)
  192. }
  193. // If AST has errors, return it as a merged error, otherwise returns nil
  194. func MergeErrors(ast Ast) error {
  195. errlist := Errors(ast)
  196. if len(errlist) < 1 {
  197. return nil
  198. }
  199. sep := ""
  200. res := ""
  201. for _, err := range errlist {
  202. res = fmt.Sprintf("%s%s%s", res, sep, err)
  203. sep = "\n"
  204. }
  205. return fmt.Errorf("%s", res)
  206. }