-
Notifications
You must be signed in to change notification settings - Fork 39
/
parse.go
115 lines (91 loc) · 2.01 KB
/
parse.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package gcss
import "strings"
// Special characters
const (
cr = "\r"
lf = "\n"
crlf = "\r\n"
space = " "
colon = ":"
comma = ","
openBrace = "{"
closeBrace = "}"
semicolon = ";"
ampersand = "&"
atMark = "@"
dollarMark = "$"
openParenthesis = "("
closeParenthesis = ")"
slash = "/"
doubleSlash = slash + slash
)
// parse parses the string, generates the elements
// and returns the two channels: the first one returns
// the generated elements and the last one returns
// an error when it occurs.
func parse(lines []string) (<-chan element, <-chan error) {
elemc := make(chan element, len(lines))
errc := make(chan error)
go func() {
i := 0
l := len(lines)
for i < l {
// Fetch a line.
ln := newLine(i+1, lines[i])
i++
// Ignore the empty line.
if ln.isEmpty() {
continue
}
if ln.isTopIndent() {
elem, err := newElement(ln, nil)
if err != nil {
errc <- err
return
}
if err := appendChildren(elem, lines, &i, l); err != nil {
errc <- err
return
}
elemc <- elem
}
}
close(elemc)
}()
return elemc, errc
}
// appendChildren parses the lines and appends the child elements
// to the parent element.
func appendChildren(parent element, lines []string, i *int, l int) error {
for *i < l {
// Fetch a line.
ln := newLine(*i+1, lines[*i])
// Ignore the empty line.
if ln.isEmpty() {
*i++
return nil
}
ok, err := ln.childOf(parent)
if err != nil {
return err
}
if !ok {
return nil
}
child, err := newElement(ln, parent)
if err != nil {
return err
}
parent.AppendChild(child)
*i++
if err := appendChildren(child, lines, i, l); err != nil {
return err
}
}
return nil
}
// formatLF replaces the line feed codes with LF and
// returns the result string.
func formatLF(s string) string {
return strings.Replace(strings.Replace(s, crlf, lf, -1), cr, lf, -1)
}