helper.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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. "strconv"
  14. "devt.de/krotik/common/datautil"
  15. "devt.de/krotik/common/stringutil"
  16. )
  17. // AST Nodes
  18. // =========
  19. /*
  20. ASTNode models a node in the AST
  21. */
  22. type ASTNode struct {
  23. Name string // Name of the node
  24. Token *LexToken // Lexer token of this ASTNode
  25. Meta []*LexToken // Meta data for this ASTNode (e.g. comments)
  26. Children []*ASTNode // Child nodes
  27. Runtime Runtime // Runtime component for this ASTNode
  28. binding int // Binding power of this node
  29. nullDenotation func(p *parser, self *ASTNode) (*ASTNode, error) // Configure token as beginning node
  30. leftDenotation func(p *parser, self *ASTNode, left *ASTNode) (*ASTNode, error) // Configure token as left node
  31. }
  32. /*
  33. Create a new instance of this ASTNode which is connected to a concrete lexer token.
  34. */
  35. func (n *ASTNode) instance(p *parser, t *LexToken) *ASTNode {
  36. ret := &ASTNode{n.Name, t, nil, make([]*ASTNode, 0, 2), nil, n.binding, n.nullDenotation, n.leftDenotation}
  37. if p.rp != nil {
  38. ret.Runtime = p.rp.Runtime(ret)
  39. }
  40. return ret
  41. }
  42. /*
  43. Equal checks if this AST data equals another AST data. Returns also a message describing
  44. what is the found difference.
  45. */
  46. func (n *ASTNode) Equals(other *ASTNode, ignoreTokenPosition bool) (bool, string) {
  47. return n.equalsPath(n.Name, other, ignoreTokenPosition)
  48. }
  49. /*
  50. equalsPath checks if this AST data equals another AST data while preserving the search path.
  51. Returns also a message describing what is the found difference.
  52. */
  53. func (n *ASTNode) equalsPath(path string, other *ASTNode, ignoreTokenPosition bool) (bool, string) {
  54. var res = true
  55. var msg = ""
  56. if n.Name != other.Name {
  57. res = false
  58. msg = fmt.Sprintf("Name is different %v vs %v\n", n.Name, other.Name)
  59. }
  60. if ok, tokenMSG := n.Token.Equals(*other.Token, ignoreTokenPosition); !ok {
  61. res = false
  62. msg += fmt.Sprintf("Token is different:\n%v\n", tokenMSG)
  63. }
  64. if len(n.Children) != len(other.Children) {
  65. res = false
  66. msg = fmt.Sprintf("Number of children is different %v vs %v\n",
  67. len(n.Children), len(other.Children))
  68. } else {
  69. for i, child := range n.Children {
  70. // Check for different in children
  71. if ok, childMSG := child.equalsPath(fmt.Sprintf("%v > %v", path, child.Name),
  72. other.Children[i], ignoreTokenPosition); !ok {
  73. return ok, childMSG
  74. }
  75. }
  76. }
  77. if msg != "" {
  78. var buf bytes.Buffer
  79. buf.WriteString("AST Nodes:\n")
  80. n.levelString(0, &buf, 1)
  81. buf.WriteString("vs\n")
  82. other.levelString(0, &buf, 1)
  83. msg = fmt.Sprintf("Path to difference: %v\n\n%v\n%v", path, msg, buf.String())
  84. }
  85. return res, msg
  86. }
  87. /*
  88. String returns a string representation of this token.
  89. */
  90. func (n *ASTNode) String() string {
  91. var buf bytes.Buffer
  92. n.levelString(0, &buf, -1)
  93. return buf.String()
  94. }
  95. /*
  96. levelString function to recursively print the tree.
  97. */
  98. func (n *ASTNode) levelString(indent int, buf *bytes.Buffer, printChildren int) {
  99. // Print current level
  100. buf.WriteString(stringutil.GenerateRollingString(" ", indent*2))
  101. if n.Name == NodeSTRING {
  102. buf.WriteString(fmt.Sprintf("%v: '%v'", n.Name, n.Token.Val))
  103. } else if n.Name == NodeNUMBER {
  104. buf.WriteString(fmt.Sprintf("%v: %v", n.Name, n.Token.Val))
  105. } else if n.Name == NodeIDENTIFIER {
  106. buf.WriteString(fmt.Sprintf("%v: %v", n.Name, n.Token.Val))
  107. } else {
  108. buf.WriteString(n.Name)
  109. }
  110. if len(n.Meta) > 0 {
  111. buf.WriteString(" # ")
  112. for i, c := range n.Meta {
  113. buf.WriteString(c.Val)
  114. if i < len(n.Meta)-1 {
  115. buf.WriteString(" ")
  116. }
  117. }
  118. }
  119. buf.WriteString("\n")
  120. if printChildren == -1 || printChildren > 0 {
  121. if printChildren != -1 {
  122. printChildren--
  123. }
  124. // Print children
  125. for _, child := range n.Children {
  126. child.levelString(indent+1, buf, printChildren)
  127. }
  128. }
  129. }
  130. /*
  131. ToJSON returns this ASTNode and all its children as a JSON object.
  132. */
  133. func (n *ASTNode) ToJSONObject() map[string]interface{} {
  134. ret := make(map[string]interface{})
  135. ret["name"] = n.Name
  136. lenChildren := len(n.Children)
  137. if lenChildren > 0 {
  138. children := make([]map[string]interface{}, lenChildren)
  139. for i, child := range n.Children {
  140. children[i] = child.ToJSONObject()
  141. }
  142. ret["children"] = children
  143. }
  144. // The value is what the lexer found in the source
  145. if n.Token != nil {
  146. ret["id"] = n.Token.ID
  147. if n.Token.Val != "" {
  148. ret["value"] = n.Token.Val
  149. }
  150. ret["identifier"] = n.Token.Identifier
  151. ret["pos"] = n.Token.Pos
  152. ret["line"] = n.Token.Lline
  153. ret["linepos"] = n.Token.Lpos
  154. }
  155. return ret
  156. }
  157. /*
  158. ASTFromPlain creates an AST from a JSON Object.
  159. The following nested map structure is expected:
  160. {
  161. name : <name of node>
  162. // Optional node information
  163. value : <value of node>
  164. children : [ <child nodes> ]
  165. // Optional token information
  166. id : <token id>
  167. }
  168. */
  169. func ASTFromJSONObject(jsonAST map[string]interface{}) (*ASTNode, error) {
  170. var astChildren []*ASTNode
  171. var nodeID LexTokenID = TokenANY
  172. var pos, line, linepos int
  173. name, ok := jsonAST["name"]
  174. if !ok {
  175. return nil, fmt.Errorf("Found json ast node without a name: %v", jsonAST)
  176. }
  177. if nodeIDString, ok := jsonAST["id"]; ok {
  178. if nodeIDInt, err := strconv.Atoi(fmt.Sprint(nodeIDString)); err == nil && IsValidTokenID(nodeIDInt) {
  179. nodeID = LexTokenID(nodeIDInt)
  180. }
  181. }
  182. value, ok := jsonAST["value"]
  183. if !ok {
  184. value = ""
  185. }
  186. identifier, ok := jsonAST["identifier"]
  187. if !ok {
  188. identifier = false
  189. }
  190. if posString, ok := jsonAST["pos"]; ok {
  191. pos, _ = strconv.Atoi(fmt.Sprint(posString))
  192. } else {
  193. pos = 0
  194. }
  195. if lineString, ok := jsonAST["line"]; ok {
  196. line, _ = strconv.Atoi(fmt.Sprint(lineString))
  197. } else {
  198. line = 0
  199. }
  200. if lineposString, ok := jsonAST["linepos"]; ok {
  201. linepos, _ = strconv.Atoi(fmt.Sprint(lineposString))
  202. } else {
  203. linepos = 0
  204. }
  205. // Create children
  206. if children, ok := jsonAST["children"]; ok {
  207. if ic, ok := children.([]interface{}); ok {
  208. // Do a list conversion if necessary - this is necessary when we parse
  209. // JSON with map[string]interface{}
  210. childrenList := make([]map[string]interface{}, len(ic))
  211. for i := range ic {
  212. childrenList[i] = ic[i].(map[string]interface{})
  213. }
  214. children = childrenList
  215. }
  216. for _, child := range children.([]map[string]interface{}) {
  217. astChild, err := ASTFromJSONObject(child)
  218. if err != nil {
  219. return nil, err
  220. }
  221. astChildren = append(astChildren, astChild)
  222. }
  223. }
  224. token := &LexToken{
  225. nodeID, // ID
  226. pos, // Pos
  227. fmt.Sprint(value), // Val
  228. identifier == true, // Identifier
  229. line, // Lline
  230. linepos, // Lpos
  231. }
  232. return &ASTNode{fmt.Sprint(name), token, nil, astChildren, nil, 0, nil, nil}, nil
  233. }
  234. // Look ahead buffer
  235. // =================
  236. /*
  237. ASTNode models a node in the AST
  238. */
  239. type LABuffer struct {
  240. tokens chan LexToken
  241. buffer *datautil.RingBuffer
  242. }
  243. /*
  244. Create a new instance of this ASTNode which is connected to a concrete lexer token.
  245. */
  246. func NewLABuffer(c chan LexToken, size int) *LABuffer {
  247. if size < 1 {
  248. size = 1
  249. }
  250. ret := &LABuffer{c, datautil.NewRingBuffer(size)}
  251. v, more := <-ret.tokens
  252. ret.buffer.Add(v)
  253. for ret.buffer.Size() < size && more && v.ID != TokenEOF {
  254. v, more = <-ret.tokens
  255. ret.buffer.Add(v)
  256. }
  257. return ret
  258. }
  259. /*
  260. Next returns the next item.
  261. */
  262. func (b *LABuffer) Next() (LexToken, bool) {
  263. ret := b.buffer.Poll()
  264. if v, more := <-b.tokens; more {
  265. b.buffer.Add(v)
  266. }
  267. if ret == nil {
  268. return LexToken{ID: TokenEOF}, false
  269. }
  270. return ret.(LexToken), true
  271. }
  272. /*
  273. Peek looks inside the buffer starting with 0 as the next item.
  274. */
  275. func (b *LABuffer) Peek(pos int) (LexToken, bool) {
  276. if pos >= b.buffer.Size() {
  277. return LexToken{ID: TokenEOF}, false
  278. }
  279. return b.buffer.Get(pos).(LexToken), true
  280. }