helper.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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/datautil"
  14. "devt.de/krotik/common/stringutil"
  15. )
  16. // AST Nodes
  17. // =========
  18. /*
  19. ASTNode models a node in the AST
  20. */
  21. type ASTNode struct {
  22. Name string // Name of the node
  23. Token *LexToken // Lexer token of this ASTNode
  24. Children []*ASTNode // Child nodes
  25. Runtime Runtime // Runtime component for this ASTNode
  26. binding int // Binding power of this node
  27. nullDenotation func(p *parser, self *ASTNode) (*ASTNode, error) // Configure token as beginning node
  28. leftDenotation func(p *parser, self *ASTNode, left *ASTNode) (*ASTNode, error) // Configure token as left node
  29. }
  30. /*
  31. Create a new instance of this ASTNode which is connected to a concrete lexer token.
  32. */
  33. func (n *ASTNode) instance(p *parser, t *LexToken) *ASTNode {
  34. ret := &ASTNode{n.Name, t, make([]*ASTNode, 0, 2), nil, n.binding, n.nullDenotation, n.leftDenotation}
  35. if p.rp != nil {
  36. ret.Runtime = p.rp.Runtime(ret)
  37. }
  38. return ret
  39. }
  40. /*
  41. String returns a string representation of this token.
  42. */
  43. func (n *ASTNode) String() string {
  44. var buf bytes.Buffer
  45. n.levelString(0, &buf)
  46. return buf.String()
  47. }
  48. /*
  49. levelString function to recursively print the tree.
  50. */
  51. func (n *ASTNode) levelString(indent int, buf *bytes.Buffer) {
  52. // Print current level
  53. buf.WriteString(stringutil.GenerateRollingString(" ", indent*2))
  54. if n.Name == NodeCOMMENT {
  55. buf.WriteString(fmt.Sprintf("%v: %20v", n.Name, n.Token.Val))
  56. } else if n.Name == NodeSTRING {
  57. buf.WriteString(fmt.Sprintf("%v: '%v'", n.Name, n.Token.Val))
  58. } else if n.Name == NodeNUMBER {
  59. buf.WriteString(fmt.Sprintf("%v: %v", n.Name, n.Token.Val))
  60. } else if n.Name == NodeIDENTIFIER {
  61. buf.WriteString(fmt.Sprintf("%v: %v", n.Name, n.Token.Val))
  62. } else {
  63. buf.WriteString(n.Name)
  64. }
  65. buf.WriteString("\n")
  66. // Print children
  67. for _, child := range n.Children {
  68. child.levelString(indent+1, buf)
  69. }
  70. }
  71. // Look ahead buffer
  72. // =================
  73. /*
  74. ASTNode models a node in the AST
  75. */
  76. type LABuffer struct {
  77. tokens chan LexToken
  78. buffer *datautil.RingBuffer
  79. }
  80. /*
  81. Create a new instance of this ASTNode which is connected to a concrete lexer token.
  82. */
  83. func NewLABuffer(c chan LexToken, size int) *LABuffer {
  84. if size < 1 {
  85. size = 1
  86. }
  87. ret := &LABuffer{c, datautil.NewRingBuffer(size)}
  88. v, more := <-ret.tokens
  89. ret.buffer.Add(v)
  90. for ret.buffer.Size() < size && more && v.ID != TokenEOF {
  91. v, more = <-ret.tokens
  92. ret.buffer.Add(v)
  93. }
  94. return ret
  95. }
  96. /*
  97. Next returns the next item.
  98. */
  99. func (b *LABuffer) Next() (LexToken, bool) {
  100. ret := b.buffer.Poll()
  101. if v, more := <-b.tokens; more {
  102. b.buffer.Add(v)
  103. }
  104. if ret == nil {
  105. return LexToken{ID: TokenEOF}, false
  106. }
  107. return ret.(LexToken), true
  108. }
  109. /*
  110. Peek looks inside the buffer starting with 0 as the next item.
  111. */
  112. func (b *LABuffer) Peek(pos int) (LexToken, bool) {
  113. if pos >= b.buffer.Size() {
  114. return LexToken{ID: TokenEOF}, false
  115. }
  116. return b.buffer.Get(pos).(LexToken), true
  117. }