Support decoding floats, scientific notation for JSON [GH-5]
This commit is contained in:
parent
b699557f16
commit
e868ca02fd
18
decoder.go
18
decoder.go
@ -48,6 +48,8 @@ func (d *decoder) decode(name string, o *hcl.Object, result reflect.Value) error
|
|||||||
switch k.Kind() {
|
switch k.Kind() {
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
return d.decodeBool(name, o, result)
|
return d.decodeBool(name, o, result)
|
||||||
|
case reflect.Float64:
|
||||||
|
return d.decodeFloat(name, o, result)
|
||||||
case reflect.Int:
|
case reflect.Int:
|
||||||
return d.decodeInt(name, o, result)
|
return d.decodeInt(name, o, result)
|
||||||
case reflect.Interface:
|
case reflect.Interface:
|
||||||
@ -65,7 +67,7 @@ func (d *decoder) decode(name string, o *hcl.Object, result reflect.Value) error
|
|||||||
return d.decodeStruct(name, o, result)
|
return d.decodeStruct(name, o, result)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"%s: unknown kind to decode into: %s", name, result.Kind())
|
"%s: unknown kind to decode into: %s", name, k.Kind())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -82,6 +84,17 @@ func (d *decoder) decodeBool(name string, o *hcl.Object, result reflect.Value) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *decoder) decodeFloat(name string, o *hcl.Object, result reflect.Value) error {
|
||||||
|
switch o.Type {
|
||||||
|
case hcl.ValueTypeFloat:
|
||||||
|
result.Set(reflect.ValueOf(o.Value.(float64)))
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("%s: unknown type %s", name, o.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (d *decoder) decodeInt(name string, o *hcl.Object, result reflect.Value) error {
|
func (d *decoder) decodeInt(name string, o *hcl.Object, result reflect.Value) error {
|
||||||
switch o.Type {
|
switch o.Type {
|
||||||
case hcl.ValueTypeInt:
|
case hcl.ValueTypeInt:
|
||||||
@ -142,6 +155,9 @@ func (d *decoder) decodeInterface(name string, o *hcl.Object, result reflect.Val
|
|||||||
case hcl.ValueTypeBool:
|
case hcl.ValueTypeBool:
|
||||||
var result bool
|
var result bool
|
||||||
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
|
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
|
||||||
|
case hcl.ValueTypeFloat:
|
||||||
|
var result float64
|
||||||
|
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
|
||||||
case hcl.ValueTypeInt:
|
case hcl.ValueTypeInt:
|
||||||
var result int
|
var result int
|
||||||
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
|
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
|
||||||
|
@ -33,6 +33,15 @@ func TestDecode_interface(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"scientific.json",
|
||||||
|
false,
|
||||||
|
map[string]interface{}{
|
||||||
|
"a": 1e-10,
|
||||||
|
"b": 1e+10,
|
||||||
|
"c": 1e10,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"terraform_heroku.hcl",
|
"terraform_heroku.hcl",
|
||||||
false,
|
false,
|
||||||
|
12
json/lex.go
12
json/lex.go
@ -43,6 +43,18 @@ func (x *jsonLex) Lex(yylval *jsonSymType) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch c {
|
switch c {
|
||||||
|
case 'e':
|
||||||
|
fallthrough
|
||||||
|
case 'E':
|
||||||
|
switch x.next() {
|
||||||
|
case '+':
|
||||||
|
return EPLUS
|
||||||
|
case '-':
|
||||||
|
return EMINUS
|
||||||
|
default:
|
||||||
|
x.backup()
|
||||||
|
return EPLUS
|
||||||
|
}
|
||||||
case '.':
|
case '.':
|
||||||
return PERIOD
|
return PERIOD
|
||||||
case '-':
|
case '-':
|
||||||
|
27
json/parse.y
27
json/parse.y
@ -22,12 +22,12 @@ import (
|
|||||||
%type <num> int
|
%type <num> int
|
||||||
%type <obj> number object pair value
|
%type <obj> number object pair value
|
||||||
%type <objlist> array elements members
|
%type <objlist> array elements members
|
||||||
%type <str> frac
|
%type <str> exp frac
|
||||||
|
|
||||||
%token <num> NUMBER
|
%token <num> NUMBER
|
||||||
%token <str> COLON COMMA IDENTIFIER EQUAL NEWLINE STRING
|
%token <str> COLON COMMA IDENTIFIER EQUAL NEWLINE STRING
|
||||||
%token <str> LEFTBRACE RIGHTBRACE LEFTBRACKET RIGHTBRACKET
|
%token <str> LEFTBRACE RIGHTBRACE LEFTBRACKET RIGHTBRACKET
|
||||||
%token <str> TRUE FALSE NULL MINUS PERIOD
|
%token <str> TRUE FALSE NULL MINUS PERIOD EPLUS EMINUS
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
@ -153,6 +153,19 @@ number:
|
|||||||
Value: f,
|
Value: f,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
| int exp
|
||||||
|
{
|
||||||
|
fs := fmt.Sprintf("%d%s", $1, $2)
|
||||||
|
f, err := strconv.ParseFloat(fs, 64)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
$$ = &hcl.Object{
|
||||||
|
Type: hcl.ValueTypeFloat,
|
||||||
|
Value: f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int:
|
int:
|
||||||
MINUS int
|
MINUS int
|
||||||
@ -164,6 +177,16 @@ int:
|
|||||||
$$ = $1
|
$$ = $1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exp:
|
||||||
|
EPLUS NUMBER
|
||||||
|
{
|
||||||
|
$$ = "e" + strconv.FormatInt(int64($2), 10)
|
||||||
|
}
|
||||||
|
| EMINUS NUMBER
|
||||||
|
{
|
||||||
|
$$ = "e-" + strconv.FormatInt(int64($2), 10)
|
||||||
|
}
|
||||||
|
|
||||||
frac:
|
frac:
|
||||||
PERIOD NUMBER
|
PERIOD NUMBER
|
||||||
{
|
{
|
||||||
|
82
json/y.go
82
json/y.go
@ -36,6 +36,8 @@ const FALSE = 57358
|
|||||||
const NULL = 57359
|
const NULL = 57359
|
||||||
const MINUS = 57360
|
const MINUS = 57360
|
||||||
const PERIOD = 57361
|
const PERIOD = 57361
|
||||||
|
const EPLUS = 57362
|
||||||
|
const EMINUS = 57363
|
||||||
|
|
||||||
var jsonToknames = []string{
|
var jsonToknames = []string{
|
||||||
"NUMBER",
|
"NUMBER",
|
||||||
@ -54,6 +56,8 @@ var jsonToknames = []string{
|
|||||||
"NULL",
|
"NULL",
|
||||||
"MINUS",
|
"MINUS",
|
||||||
"PERIOD",
|
"PERIOD",
|
||||||
|
"EPLUS",
|
||||||
|
"EMINUS",
|
||||||
}
|
}
|
||||||
var jsonStatenames = []string{}
|
var jsonStatenames = []string{}
|
||||||
|
|
||||||
@ -61,7 +65,7 @@ const jsonEofCode = 1
|
|||||||
const jsonErrCode = 2
|
const jsonErrCode = 2
|
||||||
const jsonMaxDepth = 200
|
const jsonMaxDepth = 200
|
||||||
|
|
||||||
//line parse.y:173
|
//line parse.y:196
|
||||||
|
|
||||||
//line yacctab:1
|
//line yacctab:1
|
||||||
var jsonExca = []int{
|
var jsonExca = []int{
|
||||||
@ -70,59 +74,59 @@ var jsonExca = []int{
|
|||||||
-2, 0,
|
-2, 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
const jsonNprod = 23
|
const jsonNprod = 26
|
||||||
const jsonPrivate = 57344
|
const jsonPrivate = 57344
|
||||||
|
|
||||||
var jsonTokenNames []string
|
var jsonTokenNames []string
|
||||||
var jsonStates []string
|
var jsonStates []string
|
||||||
|
|
||||||
const jsonLast = 45
|
const jsonLast = 50
|
||||||
|
|
||||||
var jsonAct = []int{
|
var jsonAct = []int{
|
||||||
|
|
||||||
12, 23, 20, 25, 23, 3, 7, 13, 3, 10,
|
12, 23, 26, 27, 28, 23, 3, 13, 3, 20,
|
||||||
21, 26, 17, 18, 19, 22, 30, 23, 22, 7,
|
21, 29, 17, 18, 19, 22, 7, 23, 5, 22,
|
||||||
1, 5, 28, 13, 3, 29, 21, 32, 17, 18,
|
7, 9, 31, 13, 3, 37, 21, 8, 17, 18,
|
||||||
19, 22, 9, 33, 6, 31, 15, 2, 8, 24,
|
19, 22, 32, 36, 6, 10, 35, 34, 38, 33,
|
||||||
4, 27, 16, 14, 11,
|
15, 2, 1, 24, 11, 25, 4, 30, 16, 14,
|
||||||
}
|
}
|
||||||
var jsonPact = []int{
|
var jsonPact = []int{
|
||||||
|
|
||||||
-6, -1000, -1000, 9, 26, -1000, -1000, 4, -1000, -4,
|
-5, -1000, -1000, 6, 15, -1000, -1000, 30, -1000, 10,
|
||||||
13, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
|
13, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
|
||||||
-16, -3, 0, -1000, -1000, 12, -1000, 21, -1000, -1000,
|
-17, -3, 1, -1000, -1000, -1000, 35, 33, 32, -1000,
|
||||||
-1000, -1000, 13, -1000,
|
19, -1000, -1000, -1000, -1000, -1000, -1000, 13, -1000,
|
||||||
}
|
}
|
||||||
var jsonPgo = []int{
|
var jsonPgo = []int{
|
||||||
|
|
||||||
0, 2, 43, 36, 34, 0, 42, 41, 40, 39,
|
0, 9, 49, 40, 34, 0, 48, 47, 46, 45,
|
||||||
20,
|
43, 42,
|
||||||
}
|
}
|
||||||
var jsonR1 = []int{
|
var jsonR1 = []int{
|
||||||
|
|
||||||
0, 10, 3, 3, 8, 8, 4, 5, 5, 5,
|
0, 11, 3, 3, 8, 8, 4, 5, 5, 5,
|
||||||
5, 5, 5, 5, 6, 6, 7, 7, 2, 2,
|
5, 5, 5, 5, 6, 6, 7, 7, 2, 2,
|
||||||
1, 1, 9,
|
2, 1, 1, 9, 9, 10,
|
||||||
}
|
}
|
||||||
var jsonR2 = []int{
|
var jsonR2 = []int{
|
||||||
|
|
||||||
0, 1, 3, 2, 1, 3, 3, 1, 1, 1,
|
0, 1, 3, 2, 1, 3, 3, 1, 1, 1,
|
||||||
1, 1, 1, 1, 2, 3, 1, 3, 1, 2,
|
1, 1, 1, 1, 2, 3, 1, 3, 1, 2,
|
||||||
2, 1, 2,
|
2, 2, 1, 2, 2, 2,
|
||||||
}
|
}
|
||||||
var jsonChk = []int{
|
var jsonChk = []int{
|
||||||
|
|
||||||
-1000, -10, -3, 11, -8, 12, -4, 10, 12, 6,
|
-1000, -11, -3, 11, -8, 12, -4, 10, 12, 6,
|
||||||
5, -4, -5, 10, -2, -3, -6, 15, 16, 17,
|
5, -4, -5, 10, -2, -3, -6, 15, 16, 17,
|
||||||
-1, 13, 18, 4, -9, 19, 14, -7, -5, -1,
|
-1, 13, 18, 4, -10, -9, 19, 20, 21, 14,
|
||||||
4, 14, 6, -5,
|
-7, -5, -1, 4, 4, 4, 14, 6, -5,
|
||||||
}
|
}
|
||||||
var jsonDef = []int{
|
var jsonDef = []int{
|
||||||
|
|
||||||
0, -2, 1, 0, 0, 3, 4, 0, 2, 0,
|
0, -2, 1, 0, 0, 3, 4, 0, 2, 0,
|
||||||
0, 5, 6, 7, 8, 9, 10, 11, 12, 13,
|
0, 5, 6, 7, 8, 9, 10, 11, 12, 13,
|
||||||
18, 0, 0, 21, 19, 0, 14, 0, 16, 20,
|
18, 0, 0, 22, 19, 20, 0, 0, 0, 14,
|
||||||
22, 15, 0, 17,
|
0, 16, 21, 25, 23, 24, 15, 0, 17,
|
||||||
}
|
}
|
||||||
var jsonTok1 = []int{
|
var jsonTok1 = []int{
|
||||||
|
|
||||||
@ -131,7 +135,7 @@ var jsonTok1 = []int{
|
|||||||
var jsonTok2 = []int{
|
var jsonTok2 = []int{
|
||||||
|
|
||||||
2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||||
12, 13, 14, 15, 16, 17, 18, 19,
|
12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
||||||
}
|
}
|
||||||
var jsonTok3 = []int{
|
var jsonTok3 = []int{
|
||||||
0,
|
0,
|
||||||
@ -489,17 +493,41 @@ jsondefault:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 20:
|
case 20:
|
||||||
//line parse.y:159
|
//line parse.y:157
|
||||||
|
{
|
||||||
|
fs := fmt.Sprintf("%d%s", jsonS[jsonpt-1].num, jsonS[jsonpt-0].str)
|
||||||
|
f, err := strconv.ParseFloat(fs, 64)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonVAL.obj = &hcl.Object{
|
||||||
|
Type: hcl.ValueTypeFloat,
|
||||||
|
Value: f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 21:
|
||||||
|
//line parse.y:172
|
||||||
{
|
{
|
||||||
jsonVAL.num = jsonS[jsonpt-0].num * -1
|
jsonVAL.num = jsonS[jsonpt-0].num * -1
|
||||||
}
|
}
|
||||||
case 21:
|
case 22:
|
||||||
//line parse.y:163
|
//line parse.y:176
|
||||||
{
|
{
|
||||||
jsonVAL.num = jsonS[jsonpt-0].num
|
jsonVAL.num = jsonS[jsonpt-0].num
|
||||||
}
|
}
|
||||||
case 22:
|
case 23:
|
||||||
//line parse.y:169
|
//line parse.y:182
|
||||||
|
{
|
||||||
|
jsonVAL.str = "e" + strconv.FormatInt(int64(jsonS[jsonpt-0].num), 10)
|
||||||
|
}
|
||||||
|
case 24:
|
||||||
|
//line parse.y:186
|
||||||
|
{
|
||||||
|
jsonVAL.str = "e-" + strconv.FormatInt(int64(jsonS[jsonpt-0].num), 10)
|
||||||
|
}
|
||||||
|
case 25:
|
||||||
|
//line parse.y:192
|
||||||
{
|
{
|
||||||
jsonVAL.str = strconv.FormatInt(int64(jsonS[jsonpt-0].num), 10)
|
jsonVAL.str = strconv.FormatInt(int64(jsonS[jsonpt-0].num), 10)
|
||||||
}
|
}
|
||||||
|
3
test-fixtures/scientific.hcl
Normal file
3
test-fixtures/scientific.hcl
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
a = 1e-10
|
||||||
|
b = 1e+10
|
||||||
|
c = 1e10
|
5
test-fixtures/scientific.json
Normal file
5
test-fixtures/scientific.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"a": 1e-10,
|
||||||
|
"b": 1e+10,
|
||||||
|
"c": 1e10
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user