(r io.Reader, location string, expansionDepth int)
| 349 | } |
| 350 | |
| 351 | func readTree(r io.Reader, location string, expansionDepth int) (nodes []Node, snips map[string][]Node, macros map[string][]string, err error) { |
| 352 | ctx := parseContext{ |
| 353 | Dispenser: lexer.NewDispenser(location, r), |
| 354 | snippets: make(map[string][]Node), |
| 355 | macros: map[string][]string{}, |
| 356 | nesting: -1, |
| 357 | fileLocation: location, |
| 358 | } |
| 359 | |
| 360 | root := Node{} |
| 361 | root.File = location |
| 362 | root.Line = 1 |
| 363 | // Before parsing starts the lexer's cursor points to the non-existent |
| 364 | // token before the first one. From readNodes viewpoint this is opening |
| 365 | // brace so we don't break any requirements here. |
| 366 | // |
| 367 | // For the same reason we use -1 as a starting nesting. So readNodes |
| 368 | // will see this as it is reading block at nesting level 0. |
| 369 | root.Children, err = ctx.readNodes() |
| 370 | if err != nil { |
| 371 | return root.Children, ctx.snippets, ctx.macros, err |
| 372 | } |
| 373 | |
| 374 | // There is no need to check ctx.nesting < 0 because it is checked by readNodes. |
| 375 | if ctx.nesting > 0 { |
| 376 | return root.Children, ctx.snippets, ctx.macros, ctx.Err("unexpected EOF when looking for }") |
| 377 | } |
| 378 | |
| 379 | root, err = ctx.expandImports(root, expansionDepth) |
| 380 | if err != nil { |
| 381 | return root.Children, ctx.snippets, ctx.macros, err |
| 382 | } |
| 383 | |
| 384 | return root.Children, ctx.snippets, ctx.macros, nil |
| 385 | } |
| 386 | |
| 387 | func Read(r io.Reader, location string) (nodes []Node, err error) { |
| 388 | nodes, _, _, err = readTree(r, location, 0) |
no test coverage detected