node.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * Public Domain Software
  3. *
  4. * I (Matthias Ladkau) am the author of the source code in this file.
  5. * I have placed the source code in this file in the public domain.
  6. *
  7. * For further information see: http://creativecommons.org/publicdomain/zero/1.0/
  8. */
  9. package parser
  10. import (
  11. "bytes"
  12. "fmt"
  13. "devt.de/krotik/common/stringutil"
  14. )
  15. /*
  16. ASTNode models a node in the AST
  17. */
  18. type ASTNode struct {
  19. Name string // Name of the node
  20. Token *LexToken // Lexer token of this ASTNode
  21. Children []*ASTNode // Child nodes
  22. Runtime Runtime // Runtime component for this ASTNode
  23. binding int // Binding power of this node
  24. nullDenotation func(p *parser, self *ASTNode) (*ASTNode, error) // Configure token as beginning node
  25. leftDenotation func(p *parser, self *ASTNode, left *ASTNode) (*ASTNode, error) // Configure token as left node
  26. }
  27. /*
  28. newAstNode creates an instance of this ASTNode which is connected to a concrete lexer token.
  29. */
  30. func newAstNode(name string, p *parser, t *LexToken) *ASTNode {
  31. ret := &ASTNode{name, t, make([]*ASTNode, 0, 2), nil, 0, nil, nil}
  32. if p.rp != nil {
  33. ret.Runtime = p.rp.Runtime(ret)
  34. }
  35. return ret
  36. }
  37. /*
  38. changeAstNode changes the name of a given ASTNode.
  39. */
  40. func changeAstNode(node *ASTNode, newname string, p *parser) *ASTNode {
  41. node.Name = newname
  42. node.Runtime = nil
  43. if p.rp != nil {
  44. node.Runtime = p.rp.Runtime(node)
  45. }
  46. return node
  47. }
  48. /*
  49. instane creates a new instance of this ASTNode which is connected to a concrete lexer token.
  50. */
  51. func (n *ASTNode) instance(p *parser, t *LexToken) *ASTNode {
  52. ret := &ASTNode{n.Name, t, make([]*ASTNode, 0, 2), nil, n.binding, n.nullDenotation, n.leftDenotation}
  53. if p.rp != nil {
  54. ret.Runtime = p.rp.Runtime(ret)
  55. }
  56. return ret
  57. }
  58. /*
  59. Plain returns this ASTNode and all its children as plain AST. A plain AST
  60. only contains map objects, lists and primitive types which can be serialized
  61. with JSON.
  62. */
  63. func (n *ASTNode) Plain() map[string]interface{} {
  64. ret := make(map[string]interface{})
  65. ret["name"] = n.Name
  66. lenChildren := len(n.Children)
  67. if lenChildren > 0 {
  68. children := make([]map[string]interface{}, lenChildren)
  69. for i, child := range n.Children {
  70. children[i] = child.Plain()
  71. }
  72. ret["children"] = children
  73. }
  74. if stringutil.IndexOf(n.Name, ValueNodes) != -1 {
  75. ret["value"] = n.Token.Val
  76. }
  77. return ret
  78. }
  79. /*
  80. String returns a string representation of this token.
  81. */
  82. func (n *ASTNode) String() string {
  83. var buf bytes.Buffer
  84. n.levelString(0, &buf)
  85. return buf.String()
  86. }
  87. /*
  88. levelString function to recursively print the tree.
  89. */
  90. func (n *ASTNode) levelString(indent int, buf *bytes.Buffer) {
  91. // Print current level
  92. buf.WriteString(stringutil.GenerateRollingString(" ", indent*2))
  93. if stringutil.IndexOf(n.Name, ValueNodes) != -1 {
  94. buf.WriteString(fmt.Sprintf(n.Name+": %v", n.Token.Val))
  95. } else {
  96. buf.WriteString(n.Name)
  97. }
  98. buf.WriteString("\n")
  99. // Print children
  100. for _, child := range n.Children {
  101. child.levelString(indent+1, buf)
  102. }
  103. }