2018-11-18 18:08:18 +00:00
|
|
|
package bash
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"io"
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Decoder implements parser.Decoder
|
|
|
|
type Decoder struct{ reader io.Reader }
|
|
|
|
|
|
|
|
// Decode is the main function of the parser.Decoder interface
|
|
|
|
func (d *Decoder) Decode(v interface{}) error {
|
|
|
|
|
|
|
|
// check 'v'
|
|
|
|
if v == nil {
|
|
|
|
return ErrNullReceiver
|
|
|
|
}
|
|
|
|
vcast, ok := v.(*File)
|
|
|
|
if !ok {
|
|
|
|
return ErrInvalidReceiver
|
|
|
|
}
|
|
|
|
vcast.Lines = make([]*Line, 0)
|
|
|
|
|
|
|
|
r := bufio.NewReader(d.reader)
|
|
|
|
n := -1 // line number
|
|
|
|
|
|
|
|
// regexes
|
|
|
|
reAssign := regexp.MustCompile(`(?m)^(\s*)([A-Za-z0-9_]+)=([^;]+);?\s*(#.+)?$`)
|
|
|
|
eof := false
|
|
|
|
|
|
|
|
for {
|
|
|
|
n++
|
|
|
|
if eof {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
l := &Line{Type: ANY}
|
|
|
|
|
|
|
|
// 1. read line
|
|
|
|
line, err := r.ReadString('\n')
|
|
|
|
if err == io.EOF {
|
|
|
|
if len(line) > 0 {
|
|
|
|
eof = true
|
|
|
|
} else {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
} else if err != nil {
|
|
|
|
return &LineError{n, err}
|
|
|
|
}
|
|
|
|
line = strings.Trim(line, "\r\n")
|
|
|
|
|
|
|
|
// 2. ignore empty
|
|
|
|
if len(strings.Trim(line, " \t\r\n")) < 1 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// 3. assignment
|
|
|
|
match := reAssign.FindStringSubmatch(line)
|
|
|
|
if match != nil {
|
|
|
|
l.Type = ASSIGNMENT
|
|
|
|
l.Components = match[1:]
|
2018-11-18 20:50:02 +00:00
|
|
|
} else {
|
|
|
|
l.Components = []string{line}
|
2018-11-18 18:08:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 4. add to file
|
|
|
|
vcast.Lines = append(vcast.Lines, l)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|