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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
package main
import (
"fmt"
"os"
"github.com/alecthomas/kong"
"github.com/alecthomas/repr"
"github.com/alecthomas/participle/v2"
"github.com/alecthomas/participle/v2/lexer"
)
type File struct {
Entries []*Entry `@@*`
}
type Entry struct {
Type *Type ` @@`
Schema *Schema `| @@`
Enum *Enum `| @@`
Scalar string `| "scalar" @Ident`
}
type Enum struct {
Name string `"enum" @Ident`
Cases []string `"{" @Ident* "}"`
}
type Schema struct {
Fields []*Field `"schema" "{" @@* "}"`
}
type Type struct {
Name string `"type" @Ident`
Implements string `( "implements" @Ident )?`
Fields []*Field `"{" @@* "}"`
}
type Field struct {
Name string `@Ident`
Arguments []*Argument `( "(" ( @@ ( "," @@ )* )? ")" )?`
Type *TypeRef `":" @@`
Annotation string `( "@" @Ident )?`
}
type Argument struct {
Name string `@Ident`
Type *TypeRef `":" @@`
Default *Value `( "=" @@ )?`
}
type TypeRef struct {
Array *TypeRef `( "[" @@ "]"`
Type string ` | @Ident )`
NonNullable bool `@"!"?`
}
type Value struct {
Symbol string `@Ident`
}
var (
graphQLLexer = lexer.MustSimple([]lexer.SimpleRule{
{"Comment", `(?:#|//)[^\n]*\n?`},
{"Ident", `[a-zA-Z]\w*`},
{"Number", `(?:\d*\.)?\d+`},
{"Punct", `[-[!@#$%^&*()+_={}\|:;"'<,>.?/]|]`},
{"Whitespace", `[ \t\n\r]+`},
})
parser = participle.MustBuild[File](
participle.Lexer(graphQLLexer),
participle.Elide("Comment", "Whitespace"),
participle.UseLookahead(2),
)
)
var cli struct {
EBNF bool `help"Dump EBNF."`
Files []string `arg:"" optional:"" type:"existingfile" help:"GraphQL schema files to parse."`
}
func main() {
ctx := kong.Parse(&cli)
if cli.EBNF {
fmt.Println(parser.String())
ctx.Exit(0)
}
for _, file := range cli.Files {
r, err := os.Open(file)
ctx.FatalIfErrorf(err)
ast, err := parser.Parse("", r)
r.Close()
repr.Println(ast)
ctx.FatalIfErrorf(err)
}
}
|