diff --git a/hcl/token/token.go b/hcl/token/token.go index 3b7581a..26291d0 100644 --- a/hcl/token/token.go +++ b/hcl/token/token.go @@ -103,3 +103,40 @@ func (t Type) IsOperator() bool { return operator_beg < t && t < operator_end } func (t Token) String() string { return fmt.Sprintf("%s %s %s", t.Pos.String(), t.Type.String(), t.Text) } + +// Value returns the properly typed value for this token. The type of +// the returned interface{} is guaranteed based on the Type field. +// +// This can only be called for literal types. If it is called for any other +// type, this will panic. +func (t Token) Value() interface{} { + switch t.Type { + case BOOL: + if t.Text == "true" { + return true + } else if t.Text == "false" { + return false + } + + panic("unknown bool value: " + t.Text) + case FLOAT: + v, err := strconv.ParseFloat(t.Text, 64) + if err != nil { + panic(err) + } + + return float64(v) + case NUMBER: + v, err := strconv.ParseInt(t.Text, 0, 64) + if err != nil { + panic(err) + } + + return int64(v) + case STRING: + // It is wrapped in quotes always + return t.Text[1 : len(t.Text)-1] + default: + panic(fmt.Sprintf("unimplemented Value for type: %s", t.Type)) + } +} diff --git a/hcl/token/token_test.go b/hcl/token/token_test.go index 796945c..8876ed1 100644 --- a/hcl/token/token_test.go +++ b/hcl/token/token_test.go @@ -1,6 +1,9 @@ package token -import "testing" +import ( + "reflect" + "testing" +) func TestTypeString(t *testing.T) { var tokens = []struct { @@ -34,3 +37,23 @@ func TestTypeString(t *testing.T) { } } + +func TestTokenValue(t *testing.T) { + var tokens = []struct { + tt Token + v interface{} + }{ + {Token{Type: BOOL, Text: `true`}, true}, + {Token{Type: BOOL, Text: `false`}, false}, + {Token{Type: FLOAT, Text: `3.14`}, float64(3.14)}, + {Token{Type: NUMBER, Text: `42`}, int64(42)}, + {Token{Type: STRING, Text: `"foo"`}, "foo"}, + } + + for _, token := range tokens { + if val := token.tt.Value(); !reflect.DeepEqual(val, token.v) { + t.Errorf("want: %v got:%v\n", token.v, val) + } + } + +}