api_doc_builder.odin 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // This program creates the `karl2d.doc.odin` file by parsing `karl2d.odin`. It skips procedure
  2. // bodies and stops when it reaches `API_END :: true`. The resulting file is a nice overview of the
  3. // library's API surface.
  4. package karl2d_api_doc_builder
  5. import os "core:os"
  6. import vmem "core:mem/virtual"
  7. import "core:log"
  8. import "core:fmt"
  9. import "core:odin/parser"
  10. import "core:odin/ast"
  11. import "core:strings"
  12. main :: proc() {
  13. arena: vmem.Arena
  14. context.allocator = vmem.arena_allocator(&arena)
  15. context.temp_allocator = context.allocator
  16. context.logger = log.create_console_logger()
  17. pkg_ast, pkg_ast_ok := parser.parse_package_from_path(".")
  18. log.ensuref(pkg_ast_ok, "Could not generate AST for package")
  19. o, o_err := os.open("karl2d.doc.odin", os.O_CREATE | os.O_TRUNC, 0o644)
  20. log.assertf(o_err == nil, "Couldn't open karl2d.doc.odin: %v", o_err)
  21. pln :: fmt.fprintln
  22. pln(o, `// This file is purely documentational. It is generated from the contents of 'karl2d.odin'.`)
  23. pln(o, "#+build ignore")
  24. pln(o, "package karl2d")
  25. prev_line: int
  26. for n, &f in pkg_ast.files {
  27. if !strings.ends_with(n, "karl2d.odin") {
  28. continue
  29. }
  30. decl_loop: for &d in f.decls {
  31. #partial switch &dd in d.derived {
  32. case ^ast.Value_Decl:
  33. val: string
  34. for v, vi in dd.values {
  35. #partial switch vd in v.derived {
  36. case ^ast.Proc_Lit:
  37. name := f.src[dd.names[vi].pos.offset:dd.names[vi].end.offset]
  38. type := f.src[vd.type.pos.offset:vd.type.end.offset]
  39. val = fmt.tprintf("%v :: %v", name, type)
  40. }
  41. }
  42. if val == "" {
  43. val = f.src[dd.pos.offset:dd.end.offset]
  44. }
  45. if val == "API_END :: true" {
  46. break decl_loop
  47. }
  48. if dd.docs != nil {
  49. pln(o, "")
  50. pln(o, f.src[dd.docs.pos.offset:dd.docs.end.offset])
  51. } else {
  52. if prev_line != dd.pos.line - 1 {
  53. pln(o, "")
  54. }
  55. }
  56. pln(o, val)
  57. prev_line = dd.pos.line
  58. }
  59. }
  60. }
  61. os.close(o)
  62. }