2014-10-07 00:55:15 +00:00
|
|
|
package parse
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"strconv"
|
|
|
|
|
|
|
|
"github.com/mediocregopher/ginger/types"
|
|
|
|
)
|
|
|
|
|
|
|
|
//func ReadElem(r io.Reader) (types.Elem, error) {
|
|
|
|
// buf := bufio.NewReader(r)
|
|
|
|
// var err error
|
|
|
|
// for {
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
|
|
|
|
// ReadString reads in a string from the given reader. It assumes the first
|
|
|
|
// double-quote has already been read off. Ginger strings are wrapped with " and
|
|
|
|
// are allowed to have newlines literal in them. In all other respects they are
|
|
|
|
// the same as go strings.
|
2014-10-15 00:39:20 +00:00
|
|
|
func ReadString(r *bufio.Reader) (types.Str, error) {
|
2014-10-07 00:55:15 +00:00
|
|
|
str := types.Str("\"")
|
|
|
|
for {
|
2014-10-15 00:39:20 +00:00
|
|
|
piece, err := r.ReadBytes('"')
|
2014-10-07 00:55:15 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
str += types.Str(piece)
|
|
|
|
if piece[len(piece)-2] != '\\' {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret, err := strconv.Unquote(string(str))
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return types.Str(ret), nil
|
|
|
|
}
|
2014-10-15 00:13:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Returns (isNumber, isFloat). Can never return (false, true)
|
|
|
|
func whatNumber(el string) (bool, bool) {
|
|
|
|
var isFloat bool
|
|
|
|
first := el[0]
|
|
|
|
|
|
|
|
var start int
|
|
|
|
if first == '-' {
|
|
|
|
if len(el) == 1 {
|
|
|
|
return false, false
|
|
|
|
}
|
|
|
|
start = 1
|
|
|
|
}
|
|
|
|
|
|
|
|
el = el[start:]
|
|
|
|
for i := range el {
|
|
|
|
if el[i] == '.' {
|
|
|
|
isFloat = true
|
|
|
|
} else if el[i] < '0' || el[i] > '9' {
|
|
|
|
return false, false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, isFloat
|
|
|
|
}
|
|
|
|
|
|
|
|
// Given a string with no spaces and with a length >= 1, parses it into either a
|
|
|
|
// number or string.
|
|
|
|
func ParseBareElement(el string) (types.Elem, error) {
|
|
|
|
isNumber, isFloat := whatNumber(el)
|
|
|
|
if isNumber {
|
|
|
|
if isFloat {
|
|
|
|
f, err := strconv.ParseFloat(el, 64)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return types.Float(f), nil
|
|
|
|
} else {
|
|
|
|
i, err := strconv.ParseInt(el, 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return types.Int(i), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if el[0] == ':' {
|
|
|
|
return types.Str(el), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return types.Str(":"+el), nil
|
|
|
|
}
|