parse.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package ace
  2. import "strings"
  3. // ParseSource parses the source and returns the result.
  4. func ParseSource(src *source, opts *Options) (*result, error) {
  5. // Initialize the options.
  6. opts = InitializeOptions(opts)
  7. rslt := newResult(nil, nil, nil)
  8. base, err := parseBytes(src.base.data, rslt, src, opts, src.base)
  9. if err != nil {
  10. return nil, err
  11. }
  12. inner, err := parseBytes(src.inner.data, rslt, src, opts, src.inner)
  13. if err != nil {
  14. return nil, err
  15. }
  16. includes := make(map[string][]element)
  17. for _, f := range src.includes {
  18. includes[f.path], err = parseBytes(f.data, rslt, src, opts, f)
  19. if err != nil {
  20. return nil, err
  21. }
  22. }
  23. rslt.base = base
  24. rslt.inner = inner
  25. rslt.includes = includes
  26. return rslt, nil
  27. }
  28. // parseBytes parses the byte data and returns the elements.
  29. func parseBytes(data []byte, rslt *result, src *source, opts *Options, f *File) ([]element, error) {
  30. var elements []element
  31. lines := strings.Split(formatLF(string(data)), lf)
  32. i := 0
  33. l := len(lines)
  34. // Ignore the last empty line.
  35. if l > 0 && lines[l-1] == "" {
  36. l--
  37. }
  38. for i < l {
  39. // Fetch a line.
  40. ln := newLine(i+1, lines[i], opts, f)
  41. i++
  42. // Ignore the empty line.
  43. if ln.isEmpty() {
  44. continue
  45. }
  46. if ln.isTopIndent() {
  47. e, err := newElement(ln, rslt, src, nil, opts)
  48. if err != nil {
  49. return nil, err
  50. }
  51. // Append child elements to the element.
  52. if err := appendChildren(e, rslt, lines, &i, l, src, opts, f); err != nil {
  53. return nil, err
  54. }
  55. elements = append(elements, e)
  56. }
  57. }
  58. return elements, nil
  59. }
  60. // appendChildren parses the lines and appends the children to the element.
  61. func appendChildren(parent element, rslt *result, lines []string, i *int, l int, src *source, opts *Options, f *File) error {
  62. for *i < l {
  63. // Fetch a line.
  64. ln := newLine(*i+1, lines[*i], opts, f)
  65. // Check if the line is a child of the parent.
  66. ok, err := ln.childOf(parent)
  67. if err != nil {
  68. return err
  69. }
  70. if !ok {
  71. return nil
  72. }
  73. child, err := newElement(ln, rslt, src, parent, opts)
  74. if err != nil {
  75. return err
  76. }
  77. parent.AppendChild(child)
  78. *i++
  79. if child.CanHaveChildren() {
  80. if err := appendChildren(child, rslt, lines, i, l, src, opts, f); err != nil {
  81. return err
  82. }
  83. }
  84. }
  85. return nil
  86. }