helper.go 9.8 KB

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