helper.go 9.8 KB

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