1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
// Package main implements a parser for HashiCorp's HCL configuration syntax.
package main
import (
"fmt"
"os"
"strings"
"github.com/alecthomas/repr"
"github.com/alecthomas/participle/v2"
)
type Bool bool
func (b *Bool) Capture(v []string) error { *b = v[0] == "true"; return nil }
type Value struct {
Boolean *Bool ` @("true"|"false")`
Identifier *string `| @Ident ( @"." @Ident )*`
String *string `| @(String|Char|RawString)`
Number *float64 `| @(Float|Int)`
Array []*Value `| "[" ( @@ ","? )* "]"`
}
func (l *Value) GoString() string {
switch {
case l.Boolean != nil:
return fmt.Sprintf("%v", *l.Boolean)
case l.Identifier != nil:
return fmt.Sprintf("`%s`", *l.Identifier)
case l.String != nil:
return fmt.Sprintf("%q", *l.String)
case l.Number != nil:
return fmt.Sprintf("%v", *l.Number)
case l.Array != nil:
out := []string{}
for _, v := range l.Array {
out = append(out, v.GoString())
}
return fmt.Sprintf("[]*Value{ %s }", strings.Join(out, ", "))
}
panic("??")
}
type Entry struct {
Key string `@Ident`
Value *Value `( "=" @@`
Block *Block ` | @@ )`
}
type Block struct {
Parameters []*Value `@@*`
Entries []*Entry `"{" @@* "}"`
}
type Config struct {
Entries []*Entry `@@*`
}
var parser = participle.MustBuild[Config](participle.Unquote())
func main() {
expr, err := parser.Parse("", os.Stdin)
if err != nil {
panic(err)
}
repr.Println(expr)
}
|