aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/homemade/scl/scanner.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/homemade/scl/scanner.go')
-rw-r--r--vendor/github.com/homemade/scl/scanner.go121
1 files changed, 121 insertions, 0 deletions
diff --git a/vendor/github.com/homemade/scl/scanner.go b/vendor/github.com/homemade/scl/scanner.go
new file mode 100644
index 0000000..7dddf59
--- /dev/null
+++ b/vendor/github.com/homemade/scl/scanner.go
@@ -0,0 +1,121 @@
+package scl
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "strings"
+)
+
+type scannerTree []*scannerLine
+
+type scanner struct {
+ file string
+ reader io.Reader
+ lines scannerTree
+}
+
+func newScanner(reader io.Reader, filename ...string) *scanner {
+
+ file := "<no file>"
+
+ if len(filename) > 0 {
+ file = filename[0]
+ }
+
+ s := scanner{
+ file: file,
+ reader: reader,
+ lines: make(scannerTree, 0),
+ }
+
+ return &s
+}
+
+func (s *scanner) scan() (lines scannerTree, err error) {
+
+ // Split to lines
+ scanner := bufio.NewScanner(s.reader)
+ scanner.Split(bufio.ScanLines)
+
+ lineNumber := 0
+ rawLines := make(scannerTree, 0)
+
+ heredoc := ""
+ heredocContent := ""
+ heredocLine := 0
+
+ for scanner.Scan() {
+ lineNumber++
+
+ if heredoc != "" {
+ heredocContent += "\n" + scanner.Text()
+
+ if strings.TrimSpace(scanner.Text()) == heredoc {
+ // HCL requires heredocs to be terminated with a newline
+ rawLines = append(rawLines, newLine(s.file, lineNumber, 0, heredocContent+"\n"))
+ heredoc = ""
+ heredocContent = ""
+ }
+
+ continue
+ }
+
+ text := strings.TrimRight(scanner.Text(), " \t{}")
+
+ if text == "" {
+ continue
+ }
+
+ if matches := heredocMatcher.FindAllStringSubmatch(text, -1); matches != nil {
+ heredoc = matches[0][1]
+ heredocContent = text
+ heredocLine = lineNumber
+ continue
+ }
+
+ rawLines = append(rawLines, newLine(s.file, lineNumber, 0, text))
+ }
+
+ if heredoc != "" {
+ return lines, fmt.Errorf("Heredoc '%s' (started line %d) not terminated", heredoc, heredocLine)
+ }
+
+ // Make sure the first line has no indent
+ if len(rawLines) > 0 {
+ index := 0
+ s.indentLines(&index, rawLines, &lines, rawLines[0].content.indent())
+ }
+
+ return
+}
+
+func (s *scanner) indentLines(index *int, input scannerTree, output *scannerTree, indent int) {
+
+ // Ends when there are no more lines
+ if *index >= len(input) {
+ return
+ }
+
+ var lineToAdd *scannerLine
+
+ for ; *index < len(input); *index++ {
+
+ lineIndent := input[*index].content.indent()
+
+ if lineIndent == indent {
+ lineToAdd = input[*index].branch()
+ *output = append(*output, lineToAdd)
+
+ } else if lineIndent > indent {
+ s.indentLines(index, input, &lineToAdd.children, lineIndent)
+
+ } else if lineIndent < indent {
+ *index--
+ return
+ }
+
+ }
+
+ return
+}