|
| 1 | +// nolint: golint, dupl |
| 2 | +package main |
| 3 | + |
| 4 | +import ( |
| 5 | + "os" |
| 6 | + |
| 7 | + "github.com/alecthomas/kong" |
| 8 | + |
| 9 | + "github.com/alecthomas/participle/v2" |
| 10 | + "github.com/alecthomas/participle/v2/lexer" |
| 11 | +) |
| 12 | + |
| 13 | +var ( |
| 14 | + jsonLexer = lexer.MustSimple([]lexer.SimpleRule{ |
| 15 | + {Name: "Comment", Pattern: `\/\/[^\n]*`}, |
| 16 | + {Name: "String", Pattern: `"(\\"|[^"])*"`}, |
| 17 | + {Name: "Number", Pattern: `[-+]?(\d*\.)?\d+`}, |
| 18 | + {Name: "Punct", Pattern: `[-[!@#$%^&*()+_={}\|:;"'<,>.?/]|]`}, |
| 19 | + {Name: "Null", Pattern: "null"}, |
| 20 | + {Name: "True", Pattern: "true"}, |
| 21 | + {Name: "False", Pattern: "false"}, |
| 22 | + {Name: "EOL", Pattern: `[\n\r]+`}, |
| 23 | + {Name: "Whitespace", Pattern: `[ \t]+`}, |
| 24 | + }) |
| 25 | + |
| 26 | + jsonParser = participle.MustBuild[Json]( |
| 27 | + participle.Lexer(jsonLexer), |
| 28 | + participle.Unquote("String"), |
| 29 | + participle.Elide("Whitespace", "EOL"), |
| 30 | + participle.UseLookahead(2), |
| 31 | + ) |
| 32 | + |
| 33 | + cli struct { |
| 34 | + File string `arg:"" type:"existingfile" help:"File to parse."` |
| 35 | + } |
| 36 | +) |
| 37 | + |
| 38 | +// Parse a Json string. |
| 39 | +func Parse(data []byte) (*Json, error) { |
| 40 | + json, err := jsonParser.ParseBytes("", data) |
| 41 | + if err != nil { |
| 42 | + return nil, err |
| 43 | + } |
| 44 | + return json, nil |
| 45 | +} |
| 46 | + |
| 47 | +type Json struct { |
| 48 | + Pos lexer.Position |
| 49 | + |
| 50 | + Object *Object `parser:"@@ |"` |
| 51 | + Array *Array `parser:"@@ |"` |
| 52 | + Number *string `parser:"@Number |"` |
| 53 | + String *string `parser:"@String |"` |
| 54 | + False *string `parser:"@False |"` |
| 55 | + True *string `parser:"@True |"` |
| 56 | + Null *string `parser:"@Null"` |
| 57 | +} |
| 58 | + |
| 59 | +type Object struct { |
| 60 | + Pos lexer.Position |
| 61 | + |
| 62 | + Pairs []*Pair `parser:"'{' @@ (',' @@)* '}'"` |
| 63 | +} |
| 64 | + |
| 65 | +type Pair struct { |
| 66 | + Pos lexer.Position |
| 67 | + |
| 68 | + Key string `parser:"@String ':'"` |
| 69 | + Value *Json `parser:"@@"` |
| 70 | +} |
| 71 | + |
| 72 | +type Array struct { |
| 73 | + Pos lexer.Position |
| 74 | + |
| 75 | + Items []*Json `parser:"'[' @@ (',' @@)* ']'"` |
| 76 | +} |
| 77 | + |
| 78 | +func main() { |
| 79 | + ctx := kong.Parse(&cli) |
| 80 | + data, err := os.ReadFile(cli.File) |
| 81 | + ctx.FatalIfErrorf(err) |
| 82 | + |
| 83 | + res, err := Parse(data) |
| 84 | + ctx.FatalIfErrorf(err) |
| 85 | + ctx.Printf("res is: %v", res) |
| 86 | +} |
0 commit comments