123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- package ace
- import "strings"
- // ParseSource parses the source and returns the result.
- func ParseSource(src *source, opts *Options) (*result, error) {
- // Initialize the options.
- opts = InitializeOptions(opts)
- rslt := newResult(nil, nil, nil)
- base, err := parseBytes(src.base.data, rslt, src, opts, src.base)
- if err != nil {
- return nil, err
- }
- inner, err := parseBytes(src.inner.data, rslt, src, opts, src.inner)
- if err != nil {
- return nil, err
- }
- includes := make(map[string][]element)
- for _, f := range src.includes {
- includes[f.path], err = parseBytes(f.data, rslt, src, opts, f)
- if err != nil {
- return nil, err
- }
- }
- rslt.base = base
- rslt.inner = inner
- rslt.includes = includes
- return rslt, nil
- }
- // parseBytes parses the byte data and returns the elements.
- func parseBytes(data []byte, rslt *result, src *source, opts *Options, f *File) ([]element, error) {
- var elements []element
- lines := strings.Split(formatLF(string(data)), lf)
- i := 0
- l := len(lines)
- // Ignore the last empty line.
- if l > 0 && lines[l-1] == "" {
- l--
- }
- for i < l {
- // Fetch a line.
- ln := newLine(i+1, lines[i], opts, f)
- i++
- // Ignore the empty line.
- if ln.isEmpty() {
- continue
- }
- if ln.isTopIndent() {
- e, err := newElement(ln, rslt, src, nil, opts)
- if err != nil {
- return nil, err
- }
- // Append child elements to the element.
- if err := appendChildren(e, rslt, lines, &i, l, src, opts, f); err != nil {
- return nil, err
- }
- elements = append(elements, e)
- }
- }
- return elements, nil
- }
- // appendChildren parses the lines and appends the children to the element.
- func appendChildren(parent element, rslt *result, lines []string, i *int, l int, src *source, opts *Options, f *File) error {
- for *i < l {
- // Fetch a line.
- ln := newLine(*i+1, lines[*i], opts, f)
- // Check if the line is a child of the parent.
- ok, err := ln.childOf(parent)
- if err != nil {
- return err
- }
- if !ok {
- return nil
- }
- child, err := newElement(ln, rslt, src, parent, opts)
- if err != nil {
- return err
- }
- parent.AppendChild(child)
- *i++
- if child.CanHaveChildren() {
- if err := appendChildren(child, rslt, lines, i, l, src, opts, f); err != nil {
- return err
- }
- }
- }
- return nil
- }
|