hcl/hcl/parse.y
2014-11-12 21:29:07 -08:00

260 lines
3.0 KiB
Plaintext

// This is the yacc input for creating the parser for HCL.
%{
package hcl
import (
"fmt"
"strconv"
)
%}
%union {
b bool
f float64
num int
str string
obj *Object
objlist []*Object
}
%type <f> float
%type <num> int
%type <objlist> list listitems objectlist
%type <obj> block number object objectitem
%type <obj> listitem
%type <str> blockId exp objectkey
%token <b> BOOL
%token <f> FLOAT
%token <num> NUMBER
%token <str> COMMA COMMAEND IDENTIFIER EQUAL NEWLINE STRING MINUS
%token <str> LEFTBRACE RIGHTBRACE LEFTBRACKET RIGHTBRACKET PERIOD
%token <str> EPLUS EMINUS
%%
top:
{
hclResult = &Object{Type: ValueTypeObject}
}
| objectlist
{
hclResult = &Object{
Type: ValueTypeObject,
Value: ObjectList($1).Flat(),
}
}
objectlist:
objectitem
{
$$ = []*Object{$1}
}
| objectlist objectitem
{
$$ = append($1, $2)
}
object:
LEFTBRACE objectlist RIGHTBRACE
{
$$ = &Object{
Type: ValueTypeObject,
Value: ObjectList($2).Flat(),
}
}
| LEFTBRACE RIGHTBRACE
{
$$ = &Object{
Type: ValueTypeObject,
}
}
objectkey:
IDENTIFIER
{
$$ = $1
}
| STRING
{
$$ = $1
}
objectitem:
objectkey EQUAL number
{
$$ = $3
$$.Key = $1
}
| objectkey EQUAL BOOL
{
$$ = &Object{
Key: $1,
Type: ValueTypeBool,
Value: $3,
}
}
| objectkey EQUAL STRING
{
$$ = &Object{
Key: $1,
Type: ValueTypeString,
Value: $3,
}
}
| objectkey EQUAL object
{
$3.Key = $1
$$ = $3
}
| objectkey EQUAL list
{
$$ = &Object{
Key: $1,
Type: ValueTypeList,
Value: $3,
}
}
| block
{
$$ = $1
}
block:
blockId object
{
$2.Key = $1
$$ = $2
}
| blockId block
{
$$ = &Object{
Key: $1,
Type: ValueTypeObject,
Value: []*Object{$2},
}
}
blockId:
IDENTIFIER
{
$$ = $1
}
| STRING
{
$$ = $1
}
list:
LEFTBRACKET listitems RIGHTBRACKET
{
$$ = $2
}
| LEFTBRACKET RIGHTBRACKET
{
$$ = nil
}
listitems:
listitem
{
$$ = []*Object{$1}
}
| listitems COMMA listitem
{
$$ = append($1, $3)
}
| listitems COMMAEND
{
$$ = $1
}
listitem:
number
{
$$ = $1
}
| STRING
{
$$ = &Object{
Type: ValueTypeString,
Value: $1,
}
}
number:
int
{
$$ = &Object{
Type: ValueTypeInt,
Value: $1,
}
}
| float
{
$$ = &Object{
Type: ValueTypeFloat,
Value: $1,
}
}
| int exp
{
fs := fmt.Sprintf("%d%s", $1, $2)
f, err := strconv.ParseFloat(fs, 64)
if err != nil {
panic(err)
}
$$ = &Object{
Type: ValueTypeFloat,
Value: f,
}
}
| float exp
{
fs := fmt.Sprintf("%f%s", $1, $2)
f, err := strconv.ParseFloat(fs, 64)
if err != nil {
panic(err)
}
$$ = &Object{
Type: ValueTypeFloat,
Value: f,
}
}
int:
MINUS int
{
$$ = $2 * -1
}
| NUMBER
{
$$ = $1
}
float:
MINUS float
{
$$ = $2 * -1
}
| FLOAT
{
$$ = $1
}
exp:
EPLUS NUMBER
{
$$ = "e" + strconv.FormatInt(int64($2), 10)
}
| EMINUS NUMBER
{
$$ = "e-" + strconv.FormatInt(int64($2), 10)
}
%%