@rcrsr/rill 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +187 -0
  3. package/dist/cli.d.ts +11 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +69 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/demo.d.ts +6 -0
  8. package/dist/demo.d.ts.map +1 -0
  9. package/dist/demo.js +121 -0
  10. package/dist/demo.js.map +1 -0
  11. package/dist/index.d.ts +10 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +9 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/lexer/errors.d.ts +9 -0
  16. package/dist/lexer/errors.d.ts.map +1 -0
  17. package/dist/lexer/errors.js +12 -0
  18. package/dist/lexer/errors.js.map +1 -0
  19. package/dist/lexer/helpers.d.ts +14 -0
  20. package/dist/lexer/helpers.d.ts.map +1 -0
  21. package/dist/lexer/helpers.js +30 -0
  22. package/dist/lexer/helpers.js.map +1 -0
  23. package/dist/lexer/index.d.ts +8 -0
  24. package/dist/lexer/index.d.ts.map +1 -0
  25. package/dist/lexer/index.js +8 -0
  26. package/dist/lexer/index.js.map +1 -0
  27. package/dist/lexer/operators.d.ts +11 -0
  28. package/dist/lexer/operators.d.ts.map +1 -0
  29. package/dist/lexer/operators.js +58 -0
  30. package/dist/lexer/operators.js.map +1 -0
  31. package/dist/lexer/readers.d.ts +12 -0
  32. package/dist/lexer/readers.d.ts.map +1 -0
  33. package/dist/lexer/readers.js +144 -0
  34. package/dist/lexer/readers.js.map +1 -0
  35. package/dist/lexer/state.d.ts +18 -0
  36. package/dist/lexer/state.d.ts.map +1 -0
  37. package/dist/lexer/state.js +37 -0
  38. package/dist/lexer/state.js.map +1 -0
  39. package/dist/lexer/tokenizer.d.ts +9 -0
  40. package/dist/lexer/tokenizer.d.ts.map +1 -0
  41. package/dist/lexer/tokenizer.js +100 -0
  42. package/dist/lexer/tokenizer.js.map +1 -0
  43. package/dist/lexer.d.ts +19 -0
  44. package/dist/lexer.d.ts.map +1 -0
  45. package/dist/lexer.js +344 -0
  46. package/dist/lexer.js.map +1 -0
  47. package/dist/parser/arithmetic.d.ts +16 -0
  48. package/dist/parser/arithmetic.d.ts.map +1 -0
  49. package/dist/parser/arithmetic.js +128 -0
  50. package/dist/parser/arithmetic.js.map +1 -0
  51. package/dist/parser/boolean.d.ts +15 -0
  52. package/dist/parser/boolean.d.ts.map +1 -0
  53. package/dist/parser/boolean.js +20 -0
  54. package/dist/parser/boolean.js.map +1 -0
  55. package/dist/parser/control-flow.d.ts +56 -0
  56. package/dist/parser/control-flow.d.ts.map +1 -0
  57. package/dist/parser/control-flow.js +167 -0
  58. package/dist/parser/control-flow.js.map +1 -0
  59. package/dist/parser/expressions.d.ts +23 -0
  60. package/dist/parser/expressions.d.ts.map +1 -0
  61. package/dist/parser/expressions.js +950 -0
  62. package/dist/parser/expressions.js.map +1 -0
  63. package/dist/parser/extraction.d.ts +48 -0
  64. package/dist/parser/extraction.d.ts.map +1 -0
  65. package/dist/parser/extraction.js +279 -0
  66. package/dist/parser/extraction.js.map +1 -0
  67. package/dist/parser/functions.d.ts +20 -0
  68. package/dist/parser/functions.d.ts.map +1 -0
  69. package/dist/parser/functions.js +96 -0
  70. package/dist/parser/functions.js.map +1 -0
  71. package/dist/parser/helpers.d.ts +94 -0
  72. package/dist/parser/helpers.d.ts.map +1 -0
  73. package/dist/parser/helpers.js +225 -0
  74. package/dist/parser/helpers.js.map +1 -0
  75. package/dist/parser/index.d.ts +49 -0
  76. package/dist/parser/index.d.ts.map +1 -0
  77. package/dist/parser/index.js +73 -0
  78. package/dist/parser/index.js.map +1 -0
  79. package/dist/parser/literals.d.ts +37 -0
  80. package/dist/parser/literals.d.ts.map +1 -0
  81. package/dist/parser/literals.js +373 -0
  82. package/dist/parser/literals.js.map +1 -0
  83. package/dist/parser/parser-collect.d.ts +16 -0
  84. package/dist/parser/parser-collect.d.ts.map +1 -0
  85. package/dist/parser/parser-collect.js +125 -0
  86. package/dist/parser/parser-collect.js.map +1 -0
  87. package/dist/parser/parser-control.d.ts +20 -0
  88. package/dist/parser/parser-control.d.ts.map +1 -0
  89. package/dist/parser/parser-control.js +120 -0
  90. package/dist/parser/parser-control.js.map +1 -0
  91. package/dist/parser/parser-expr.d.ts +37 -0
  92. package/dist/parser/parser-expr.d.ts.map +1 -0
  93. package/dist/parser/parser-expr.js +639 -0
  94. package/dist/parser/parser-expr.js.map +1 -0
  95. package/dist/parser/parser-extract.d.ts +17 -0
  96. package/dist/parser/parser-extract.d.ts.map +1 -0
  97. package/dist/parser/parser-extract.js +222 -0
  98. package/dist/parser/parser-extract.js.map +1 -0
  99. package/dist/parser/parser-functions.d.ts +21 -0
  100. package/dist/parser/parser-functions.d.ts.map +1 -0
  101. package/dist/parser/parser-functions.js +155 -0
  102. package/dist/parser/parser-functions.js.map +1 -0
  103. package/dist/parser/parser-literals.d.ts +22 -0
  104. package/dist/parser/parser-literals.d.ts.map +1 -0
  105. package/dist/parser/parser-literals.js +288 -0
  106. package/dist/parser/parser-literals.js.map +1 -0
  107. package/dist/parser/parser-script.d.ts +21 -0
  108. package/dist/parser/parser-script.d.ts.map +1 -0
  109. package/dist/parser/parser-script.js +174 -0
  110. package/dist/parser/parser-script.js.map +1 -0
  111. package/dist/parser/parser-variables.d.ts +20 -0
  112. package/dist/parser/parser-variables.d.ts.map +1 -0
  113. package/dist/parser/parser-variables.js +146 -0
  114. package/dist/parser/parser-variables.js.map +1 -0
  115. package/dist/parser/parser.d.ts +49 -0
  116. package/dist/parser/parser.d.ts.map +1 -0
  117. package/dist/parser/parser.js +54 -0
  118. package/dist/parser/parser.js.map +1 -0
  119. package/dist/parser/script.d.ts +14 -0
  120. package/dist/parser/script.d.ts.map +1 -0
  121. package/dist/parser/script.js +196 -0
  122. package/dist/parser/script.js.map +1 -0
  123. package/dist/parser/state.d.ts +40 -0
  124. package/dist/parser/state.d.ts.map +1 -0
  125. package/dist/parser/state.js +129 -0
  126. package/dist/parser/state.js.map +1 -0
  127. package/dist/parser/variables.d.ts +10 -0
  128. package/dist/parser/variables.d.ts.map +1 -0
  129. package/dist/parser/variables.js +215 -0
  130. package/dist/parser/variables.js.map +1 -0
  131. package/dist/runtime/ast-equals.d.ts +13 -0
  132. package/dist/runtime/ast-equals.d.ts.map +1 -0
  133. package/dist/runtime/ast-equals.js +447 -0
  134. package/dist/runtime/ast-equals.js.map +1 -0
  135. package/dist/runtime/builtins.d.ts +13 -0
  136. package/dist/runtime/builtins.d.ts.map +1 -0
  137. package/dist/runtime/builtins.js +180 -0
  138. package/dist/runtime/builtins.js.map +1 -0
  139. package/dist/runtime/callable.d.ts +88 -0
  140. package/dist/runtime/callable.d.ts.map +1 -0
  141. package/dist/runtime/callable.js +98 -0
  142. package/dist/runtime/callable.js.map +1 -0
  143. package/dist/runtime/context.d.ts +13 -0
  144. package/dist/runtime/context.d.ts.map +1 -0
  145. package/dist/runtime/context.js +73 -0
  146. package/dist/runtime/context.js.map +1 -0
  147. package/dist/runtime/core/callable.d.ts +171 -0
  148. package/dist/runtime/core/callable.d.ts.map +1 -0
  149. package/dist/runtime/core/callable.js +246 -0
  150. package/dist/runtime/core/callable.js.map +1 -0
  151. package/dist/runtime/core/context.d.ts +29 -0
  152. package/dist/runtime/core/context.d.ts.map +1 -0
  153. package/dist/runtime/core/context.js +154 -0
  154. package/dist/runtime/core/context.js.map +1 -0
  155. package/dist/runtime/core/equals.d.ts +9 -0
  156. package/dist/runtime/core/equals.d.ts.map +1 -0
  157. package/dist/runtime/core/equals.js +381 -0
  158. package/dist/runtime/core/equals.js.map +1 -0
  159. package/dist/runtime/core/eval/base.d.ts +65 -0
  160. package/dist/runtime/core/eval/base.d.ts.map +1 -0
  161. package/dist/runtime/core/eval/base.js +112 -0
  162. package/dist/runtime/core/eval/base.js.map +1 -0
  163. package/dist/runtime/core/eval/evaluator.d.ts +47 -0
  164. package/dist/runtime/core/eval/evaluator.d.ts.map +1 -0
  165. package/dist/runtime/core/eval/evaluator.js +73 -0
  166. package/dist/runtime/core/eval/evaluator.js.map +1 -0
  167. package/dist/runtime/core/eval/index.d.ts +57 -0
  168. package/dist/runtime/core/eval/index.d.ts.map +1 -0
  169. package/dist/runtime/core/eval/index.js +95 -0
  170. package/dist/runtime/core/eval/index.js.map +1 -0
  171. package/dist/runtime/core/eval/mixins/annotations.d.ts +19 -0
  172. package/dist/runtime/core/eval/mixins/annotations.d.ts.map +1 -0
  173. package/dist/runtime/core/eval/mixins/annotations.js +146 -0
  174. package/dist/runtime/core/eval/mixins/annotations.js.map +1 -0
  175. package/dist/runtime/core/eval/mixins/closures.d.ts +49 -0
  176. package/dist/runtime/core/eval/mixins/closures.d.ts.map +1 -0
  177. package/dist/runtime/core/eval/mixins/closures.js +479 -0
  178. package/dist/runtime/core/eval/mixins/closures.js.map +1 -0
  179. package/dist/runtime/core/eval/mixins/collections.d.ts +24 -0
  180. package/dist/runtime/core/eval/mixins/collections.d.ts.map +1 -0
  181. package/dist/runtime/core/eval/mixins/collections.js +466 -0
  182. package/dist/runtime/core/eval/mixins/collections.js.map +1 -0
  183. package/dist/runtime/core/eval/mixins/control-flow.d.ts +27 -0
  184. package/dist/runtime/core/eval/mixins/control-flow.d.ts.map +1 -0
  185. package/dist/runtime/core/eval/mixins/control-flow.js +369 -0
  186. package/dist/runtime/core/eval/mixins/control-flow.js.map +1 -0
  187. package/dist/runtime/core/eval/mixins/core.d.ts +24 -0
  188. package/dist/runtime/core/eval/mixins/core.d.ts.map +1 -0
  189. package/dist/runtime/core/eval/mixins/core.js +335 -0
  190. package/dist/runtime/core/eval/mixins/core.js.map +1 -0
  191. package/dist/runtime/core/eval/mixins/expressions.d.ts +19 -0
  192. package/dist/runtime/core/eval/mixins/expressions.d.ts.map +1 -0
  193. package/dist/runtime/core/eval/mixins/expressions.js +202 -0
  194. package/dist/runtime/core/eval/mixins/expressions.js.map +1 -0
  195. package/dist/runtime/core/eval/mixins/extraction.d.ts +10 -0
  196. package/dist/runtime/core/eval/mixins/extraction.d.ts.map +1 -0
  197. package/dist/runtime/core/eval/mixins/extraction.js +250 -0
  198. package/dist/runtime/core/eval/mixins/extraction.js.map +1 -0
  199. package/dist/runtime/core/eval/mixins/literals.d.ts +23 -0
  200. package/dist/runtime/core/eval/mixins/literals.d.ts.map +1 -0
  201. package/dist/runtime/core/eval/mixins/literals.js +180 -0
  202. package/dist/runtime/core/eval/mixins/literals.js.map +1 -0
  203. package/dist/runtime/core/eval/mixins/types.d.ts +20 -0
  204. package/dist/runtime/core/eval/mixins/types.d.ts.map +1 -0
  205. package/dist/runtime/core/eval/mixins/types.js +109 -0
  206. package/dist/runtime/core/eval/mixins/types.js.map +1 -0
  207. package/dist/runtime/core/eval/mixins/variables.d.ts +34 -0
  208. package/dist/runtime/core/eval/mixins/variables.d.ts.map +1 -0
  209. package/dist/runtime/core/eval/mixins/variables.js +247 -0
  210. package/dist/runtime/core/eval/mixins/variables.js.map +1 -0
  211. package/dist/runtime/core/eval/types.d.ts +41 -0
  212. package/dist/runtime/core/eval/types.d.ts.map +1 -0
  213. package/dist/runtime/core/eval/types.js +10 -0
  214. package/dist/runtime/core/eval/types.js.map +1 -0
  215. package/dist/runtime/core/evaluate.d.ts +42 -0
  216. package/dist/runtime/core/evaluate.d.ts.map +1 -0
  217. package/dist/runtime/core/evaluate.debug.js +1251 -0
  218. package/dist/runtime/core/evaluate.js +1913 -0
  219. package/dist/runtime/core/evaluate.js.map +1 -0
  220. package/dist/runtime/core/execute.d.ts +26 -0
  221. package/dist/runtime/core/execute.d.ts.map +1 -0
  222. package/dist/runtime/core/execute.js +177 -0
  223. package/dist/runtime/core/execute.js.map +1 -0
  224. package/dist/runtime/core/signals.d.ts +19 -0
  225. package/dist/runtime/core/signals.d.ts.map +1 -0
  226. package/dist/runtime/core/signals.js +26 -0
  227. package/dist/runtime/core/signals.js.map +1 -0
  228. package/dist/runtime/core/types.d.ts +177 -0
  229. package/dist/runtime/core/types.d.ts.map +1 -0
  230. package/dist/runtime/core/types.js +50 -0
  231. package/dist/runtime/core/types.js.map +1 -0
  232. package/dist/runtime/core/values.d.ts +66 -0
  233. package/dist/runtime/core/values.d.ts.map +1 -0
  234. package/dist/runtime/core/values.js +240 -0
  235. package/dist/runtime/core/values.js.map +1 -0
  236. package/dist/runtime/evaluate.d.ts +32 -0
  237. package/dist/runtime/evaluate.d.ts.map +1 -0
  238. package/dist/runtime/evaluate.js +1111 -0
  239. package/dist/runtime/evaluate.js.map +1 -0
  240. package/dist/runtime/execute.d.ts +26 -0
  241. package/dist/runtime/execute.d.ts.map +1 -0
  242. package/dist/runtime/execute.js +121 -0
  243. package/dist/runtime/execute.js.map +1 -0
  244. package/dist/runtime/ext/builtins.d.ts +16 -0
  245. package/dist/runtime/ext/builtins.d.ts.map +1 -0
  246. package/dist/runtime/ext/builtins.js +528 -0
  247. package/dist/runtime/ext/builtins.js.map +1 -0
  248. package/dist/runtime/ext/content-parser.d.ts +83 -0
  249. package/dist/runtime/ext/content-parser.d.ts.map +1 -0
  250. package/dist/runtime/ext/content-parser.js +536 -0
  251. package/dist/runtime/ext/content-parser.js.map +1 -0
  252. package/dist/runtime/index.d.ts +28 -0
  253. package/dist/runtime/index.d.ts.map +1 -0
  254. package/dist/runtime/index.js +34 -0
  255. package/dist/runtime/index.js.map +1 -0
  256. package/dist/runtime/signals.d.ts +19 -0
  257. package/dist/runtime/signals.d.ts.map +1 -0
  258. package/dist/runtime/signals.js +26 -0
  259. package/dist/runtime/signals.js.map +1 -0
  260. package/dist/runtime/types.d.ts +169 -0
  261. package/dist/runtime/types.d.ts.map +1 -0
  262. package/dist/runtime/types.js +50 -0
  263. package/dist/runtime/types.js.map +1 -0
  264. package/dist/runtime/values.d.ts +50 -0
  265. package/dist/runtime/values.d.ts.map +1 -0
  266. package/dist/runtime/values.js +209 -0
  267. package/dist/runtime/values.js.map +1 -0
  268. package/dist/runtime.d.ts +254 -0
  269. package/dist/runtime.d.ts.map +1 -0
  270. package/dist/runtime.js +2014 -0
  271. package/dist/runtime.js.map +1 -0
  272. package/dist/types.d.ts +752 -0
  273. package/dist/types.d.ts.map +1 -0
  274. package/dist/types.js +189 -0
  275. package/dist/types.js.map +1 -0
  276. package/docs/00_INDEX.md +65 -0
  277. package/docs/01_guide.md +390 -0
  278. package/docs/02_types.md +399 -0
  279. package/docs/03_variables.md +314 -0
  280. package/docs/04_operators.md +551 -0
  281. package/docs/05_control-flow.md +350 -0
  282. package/docs/06_closures.md +353 -0
  283. package/docs/07_collections.md +686 -0
  284. package/docs/08_iterators.md +330 -0
  285. package/docs/09_strings.md +205 -0
  286. package/docs/10_parsing.md +366 -0
  287. package/docs/11_reference.md +350 -0
  288. package/docs/12_examples.md +771 -0
  289. package/docs/13_modules.md +519 -0
  290. package/docs/14_host-integration.md +826 -0
  291. package/docs/15_grammar.ebnf +693 -0
  292. package/docs/16_conventions.md +696 -0
  293. package/docs/99_llm-reference.txt +300 -0
  294. package/docs/assets/logo.png +0 -0
  295. package/package.json +70 -0
@@ -0,0 +1,366 @@
1
+ # Content Parsing
2
+
3
+ Built-in functions for extracting structured data from text, optimized for LLM output.
4
+
5
+ ## Overview
6
+
7
+ | Function | Purpose |
8
+ |----------|---------|
9
+ | `parse_auto` | Auto-detect format and extract structured content |
10
+ | `parse_json` | Parse JSON with error repair |
11
+ | `parse_xml` | Extract content from XML tags |
12
+ | `parse_fence` | Extract fenced code block content |
13
+ | `parse_fences` | Extract all fenced code blocks |
14
+ | `parse_frontmatter` | Parse YAML frontmatter and body |
15
+ | `parse_checklist` | Parse markdown checkbox items |
16
+
17
+ ## Auto-Detection with `parse_auto`
18
+
19
+ Automatically detects format and extracts structured content:
20
+
21
+ ```rill
22
+ $response -> parse_auto :> $result
23
+
24
+ # $result contains:
25
+ # type: "json" | "xml" | "yaml" | "frontmatter" | "fence" | "checklist" | "text"
26
+ # data: <parsed structured data>
27
+ # raw: <original extracted content>
28
+ # confidence: <0.0-1.0 detection confidence>
29
+ # repaired: <true if error recovery applied>
30
+ ```
31
+
32
+ ### Detection Priority
33
+
34
+ | Priority | Format | Detection Signal |
35
+ |----------|--------|------------------|
36
+ | 1 | frontmatter | Starts with `---\n` |
37
+ | 2 | fence (json/yaml) | ` ```json ` or ` ```yaml ` blocks |
38
+ | 3 | fence (other) | ` ```lang ` blocks |
39
+ | 4 | xml | `<tag>...</tag>` structure |
40
+ | 5 | json | `{...}` or `[...]` with balanced braces |
41
+ | 6 | checklist | `- [ ]` or `- [x]` patterns |
42
+ | 7 | yaml | `key: value` line patterns (2+ lines) |
43
+ | 8 | text | Fallback (returns trimmed input) |
44
+
45
+ ### Examples
46
+
47
+ ```rill
48
+ "{{\"count\": 42}}" -> parse_auto
49
+ # type: "json", data: [count: 42]
50
+ ```
51
+
52
+ ```rill
53
+ "<answer>42</answer>" -> parse_auto
54
+ # type: "xml", data: [answer: "42"]
55
+ ```
56
+
57
+ ```rill
58
+ "- [ ] Todo\n- [x] Done" -> parse_auto
59
+ # type: "checklist", data: [[false, "Todo"], [true, "Done"]]
60
+
61
+ # Frontmatter
62
+ "---\ntitle: Doc\n---\nBody" -> parse_auto
63
+ # type: "frontmatter", data: [meta: [title: "Doc"], body: "Body"]
64
+ ```
65
+
66
+ ### Confidence Checking
67
+
68
+ Use confidence scores to handle ambiguous responses:
69
+
70
+ ```rill
71
+ prompt("Analyze this data") -> parse_auto :> $parsed
72
+
73
+ ($parsed.confidence < 0.8) ? {
74
+ "Low confidence parse: {$parsed.type}" -> log
75
+ # Fall back to manual handling
76
+ }
77
+ ```
78
+
79
+ ## JSON Parsing
80
+
81
+ ### `parse_json`
82
+
83
+ Parses JSON with automatic error repair for common LLM formatting issues:
84
+
85
+ ```rill
86
+ "{{\"name\": \"test\", \"count\": 42}}" -> parse_json
87
+ # Returns [name: "test", count: 42]
88
+ ```
89
+
90
+ ### Error Repair
91
+
92
+ | Error | Repair |
93
+ |-------|--------|
94
+ | Trailing commas | Removed |
95
+ | Single quotes | Converted to double quotes |
96
+ | Unquoted keys | Quoted |
97
+ | Unclosed braces | Closed (best effort) |
98
+
99
+ ### Practical Usage
100
+
101
+ ```rill
102
+ # LLM returns JSON with common errors
103
+ prompt("Return user data as JSON") -> parse_json :> $user
104
+
105
+ # Safe access with defaults
106
+ $user.name ?? "Unknown"
107
+ $user.age ?? 0
108
+ ```
109
+
110
+ ## XML Parsing
111
+
112
+ ### `parse_xml`
113
+
114
+ Extract content from XML tags. Useful for chain-of-thought prompting:
115
+
116
+ ```rill
117
+ # Extract single tag
118
+ $response -> parse_xml("thinking")
119
+ # Returns content between <thinking>...</thinking>
120
+
121
+ # Extract and parse nested content
122
+ $response -> parse_xml("answer") -> parse_json
123
+ # Extract <answer> tag, parse its content as JSON
124
+
125
+ # Extract all tags as dict
126
+ $response -> parse_xml
127
+ # Returns [tag1: "content1", tag2: "content2", ...]
128
+ ```
129
+
130
+ ### Chain-of-Thought Pattern
131
+
132
+ ```rill
133
+ prompt(<<EOF
134
+ Analyze this problem step by step.
135
+
136
+ <thinking>
137
+ Show your reasoning here
138
+ </thinking>
139
+
140
+ <answer>
141
+ Return your final answer as JSON
142
+ </answer>
143
+ EOF
144
+ ) :> $response
145
+
146
+ # Log reasoning for debugging
147
+ $response -> parse_xml("thinking") -> log
148
+
149
+ # Parse structured answer
150
+ $response -> parse_xml("answer") -> parse_json :> $result
151
+ ```
152
+
153
+ ### Tool Calling Pattern
154
+
155
+ ```rill
156
+ prompt(<<EOF
157
+ You have access to tools. To call a tool, use:
158
+ <tool>
159
+ <name>tool_name</name>
160
+ <args>{"param": "value"}</args>
161
+ </tool>
162
+ EOF
163
+ ) :> $response
164
+
165
+ $response -> parse_xml("tool") :> $tool
166
+ $tool -> parse_xml("name") :> $fn_name
167
+ $tool -> parse_xml("args") -> parse_json :> $fn_args
168
+
169
+ # Call the function dynamically
170
+ call($fn_name, $fn_args)
171
+ ```
172
+
173
+ ## Fenced Code Blocks
174
+
175
+ ### `parse_fence`
176
+
177
+ Extract content from markdown fenced code blocks:
178
+
179
+ ```rill
180
+ # Extract by language
181
+ $response -> parse_fence("json") -> parse_json
182
+ # Extracts ```json block, parses as JSON
183
+
184
+ # Extract first fence (any language)
185
+ $response -> parse_fence
186
+ # Returns content of first fenced block
187
+ ```
188
+
189
+ ### `parse_fences`
190
+
191
+ Extract all fenced code blocks:
192
+
193
+ ```rill
194
+ prompt("Show examples in Python and JavaScript") -> parse_fences -> each {
195
+ "{$.lang}:" -> log
196
+ $.content -> log
197
+ }
198
+ # Returns list of [lang: "python", content: "..."], [lang: "javascript", content: "..."]
199
+ ```
200
+
201
+ ### Practical Usage
202
+
203
+ ```rill
204
+ # ...
205
+ # Parse fenced JSON from LLM response
206
+ # prompt("Generate JSON") -> parse_fence("json") -> parse_json :> $config
207
+ # $config.host -> log
208
+ ```
209
+
210
+ ## Frontmatter Parsing
211
+
212
+ ### `parse_frontmatter`
213
+
214
+ Parse YAML frontmatter delimited by `---`:
215
+
216
+ ```rill
217
+ "---\ntitle: Hello\n---\nBody text" :> $doc
218
+ $doc -> parse_frontmatter
219
+ # Returns [meta: [title: "Hello"], body: "Body text"]
220
+ ```
221
+
222
+ Destructure into variables:
223
+
224
+ ```rill
225
+ "---\ntitle: Hello\n---\nBody text" :> $doc
226
+ $doc -> parse_frontmatter -> *<meta: $m, body: $b>
227
+ $m.title -> log
228
+ ```
229
+
230
+ ### Practical Usage
231
+
232
+ ```rill
233
+ # Parse frontmatter from document
234
+ "---\ntitle: My Doc\nstatus: draft\n---\nContent here" -> parse_frontmatter :> $doc
235
+
236
+ $doc.meta.title -> log
237
+ ($doc.meta.status ?? "") -> .eq("draft") ? { "Document is still a draft" -> log }
238
+ $doc.body -> log
239
+ ```
240
+
241
+ ## Checklist Parsing
242
+
243
+ ### `parse_checklist`
244
+
245
+ Parse markdown task list items:
246
+
247
+ ```rill
248
+ "- [ ] Buy milk\n- [x] Call mom" -> parse_checklist
249
+ # Returns [[false, "Buy milk"], [true, "Call mom"]]
250
+ ```
251
+
252
+ Each item is a tuple: `[completed: bool, text: string]`
253
+
254
+ ### Practical Usage
255
+
256
+ ```rill
257
+ "- [ ] Deploy\n- [x] Test" -> parse_checklist :> $tasks
258
+ $tasks -> .len
259
+ ```
260
+
261
+ ## Validation Patterns
262
+
263
+ ### Type Checking
264
+
265
+ ```text
266
+ app::prompt("Return JSON with status and items") -> parse_auto :> $result
267
+
268
+ ($result.type != "json") ? {
269
+ app::error("Expected JSON response, got {$result.type}")
270
+ }
271
+
272
+ $result.data -> app::process()
273
+ ```
274
+
275
+ ### Required Fields
276
+
277
+ ```text
278
+ app::prompt("Return user profile as JSON") -> parse_json :> $user
279
+
280
+ # Validate required fields exist
281
+ ($user.?name && $user.?email) ? {
282
+ app::create_account($user)
283
+ } ! {
284
+ app::error("Missing required fields")
285
+ }
286
+ ```
287
+
288
+ ### Retry on Parse Failure
289
+
290
+ ```text
291
+ ^(limit: 3) @ {
292
+ app::prompt("Generate valid JSON for a user profile")
293
+ } ? (parse_json($) -> type != "dict")
294
+
295
+ # Loop exits when valid dict is returned
296
+ parse_json($) :> $profile
297
+ ```
298
+
299
+ ## Combining Parsers
300
+
301
+ Chain parsers for complex extraction:
302
+
303
+ ```rill
304
+ # ...
305
+ # Extract JSON from a fenced block
306
+ # $response -> parse_fence("json") -> parse_json :> $data
307
+
308
+ # Extract XML answer, parse as JSON
309
+ # $response -> parse_xml("answer") -> parse_json :> $result
310
+
311
+ # Parse frontmatter, then parse body as checklist
312
+ # $doc -> parse_frontmatter :> $parsed
313
+ # $parsed.body -> parse_checklist :> $tasks
314
+ ```
315
+
316
+ ## Best Practices
317
+
318
+ 1. **Use `parse_auto` for unknown formats** — Let it detect the structure
319
+ 2. **Use specific parsers when format is known** — More predictable results
320
+ 3. **Check confidence for ambiguous content** — Handle low-confidence parses specially
321
+ 4. **Chain parsers for nested structures** — XML containing JSON, frontmatter with checklists
322
+ 5. **Validate before using** — Check type and required fields exist
323
+
324
+ ## Limitations
325
+
326
+ These parsers handle common LLM output patterns with zero external dependencies. For full-featured parsing (nested YAML, XML attributes, streaming JSON), host applications can register their own functions via `RuntimeContext`.
327
+
328
+ ### YAML Parser
329
+
330
+ The YAML parser handles **flat `key: value` format only**:
331
+
332
+ ```text
333
+ # Supported
334
+ title: My Document
335
+ count: 42
336
+ enabled: true
337
+
338
+ # NOT supported (returns raw string or fails)
339
+ nested:
340
+ child: value
341
+ items:
342
+ - one
343
+ - two
344
+ multiline: |
345
+ long text
346
+ across lines
347
+ ```
348
+
349
+ ### JSON Repair
350
+
351
+ Repairs common LLM errors but **cannot fix**:
352
+
353
+ | Repaired | Not Repaired |
354
+ |----------|--------------|
355
+ | Trailing commas | Missing commas between items |
356
+ | Single quotes on values | Malformed string escapes |
357
+ | Unquoted keys | Truncated mid-string |
358
+ | Unclosed braces | Invalid Unicode |
359
+
360
+ ### XML Parser
361
+
362
+ Extracts simple `<tag>content</tag>` but **does not support**:
363
+
364
+ - Attribute extraction (`<tag attr="val">` — attr ignored)
365
+ - Nested same-name tags (`<item><item>...</item></item>`)
366
+ - CDATA sections, namespaces, self-closing tags
@@ -0,0 +1,350 @@
1
+ # rill Core Language Specification v0.1.0
2
+
3
+ *From prompts to workflows*
4
+
5
+ rill is a pipe-based scripting language for orchestrating workflows.
6
+
7
+ > **Experimental (v0.1.0).** Active development. Breaking changes until v1.0.
8
+
9
+ ## Overview
10
+
11
+ rill is an imperative scripting language that is dynamically typed and type-safe. Types are checked at runtime, but type errors are always caught—there are no implicit conversions. Type annotations are optional, but variables lock their type on first assignment. The language is value-based: no references, all copies are deep, all comparisons are by value. Empty values are valid (empty strings, lists, dicts), but null and undefined do not exist. Control flow is singular: no exceptions, no try/catch. Data flows through pipes (`->`), not assignment.
12
+
13
+ ## Design Principles
14
+
15
+ 1. **Pipes over assignment** — Data flows via `->`. No `=` operator exists.
16
+ 2. **Pattern-driven decisions** — Check response patterns, branch accordingly.
17
+ 3. **Singular control flow** — No try/catch. Errors halt execution. Recovery requires explicit conditionals.
18
+ 4. **Value-based** — All values compare by content. No references, no object identity.
19
+ 5. **No null/undefined** — Empty values are valid, but "no value" cannot be represented.
20
+ 6. **No magic** — No truthiness, no automatic type conversions. Explicit behavior only.
21
+ 7. **Expressive and consistent** — Small syntax, coherent semantics. Every construct composes predictably.
22
+
23
+ ---
24
+
25
+ ## Quick Reference Tables
26
+
27
+ ### Operators
28
+
29
+ | Category | Operators |
30
+ |----------|-----------|
31
+ | Arithmetic | `+`, `-`, `*`, `/`, `%` |
32
+ | Comparison | `==`, `!=`, `<`, `>`, `<=`, `>=` |
33
+ | Comparison | `.eq`, `.ne`, `.lt`, `.gt`, `.le`, `.ge` methods |
34
+ | Logical | `!` (unary), `&&`, `\|\|` |
35
+ | Pipe | `->` |
36
+ | Capture | `:>` |
37
+ | Spread | `@` (sequential), `*` (tuple) |
38
+ | Extraction | `*<>` (destructure), `/<>` (slice) |
39
+ | Type | `:type` (assert), `:?type` (check) |
40
+ | Member | `.field`, `[index]` |
41
+ | Default | `?? value` |
42
+ | Existence | `.?field`, `.?field&type` |
43
+
44
+ See [Operators](04_operators.md) for detailed documentation.
45
+
46
+ ### Control Flow
47
+
48
+ | Syntax | Description |
49
+ |--------|-------------|
50
+ | `cond ? then ! else` | Conditional (if-else) |
51
+ | `$val -> ? then ! else` | Piped conditional ($ as condition) |
52
+ | `(cond) @ body` | While loop |
53
+ | `@ body ? cond` | Do-while |
54
+ | `break` / `$val -> break` | Exit loop |
55
+ | `return` / `$val -> return` | Exit block or script |
56
+
57
+ See [Control Flow](05_control-flow.md) for detailed documentation. Script-level exit functions must be host-provided.
58
+
59
+ ### Collection Operators
60
+
61
+ | Syntax | Description |
62
+ |--------|-------------|
63
+ | `-> each { body }` | Sequential iteration, all results |
64
+ | `-> each(init) { body }` | Sequential with accumulator (`$@`) |
65
+ | `-> map { body }` | Parallel iteration, all results |
66
+ | `-> filter { cond }` | Parallel filter, matching elements |
67
+ | `-> fold(init) { body }` | Sequential reduction, final result |
68
+
69
+ See [Collections](07_collections.md) for detailed documentation.
70
+
71
+ ### Types
72
+
73
+ | Type | Syntax | Example |
74
+ |------|--------|---------|
75
+ | String | `"text"` | `"hello"` |
76
+ | Number | `123`, `0.5` | `42`, `0.9` |
77
+ | Bool | `true`, `false` | `true` |
78
+ | List | `[a, b]` | `["file.ts", 42]` |
79
+ | Dict | `[k: v]` | `[output: "text", code: 0]` |
80
+ | Tuple | `*[...]` | `*[1, 2]`, `*[x: 1, y: 2]` |
81
+ | Closure | `\|\|{ }` | `\|x\|($x * 2)` |
82
+
83
+ See [Types](02_types.md) for detailed documentation.
84
+
85
+ ### Functions
86
+
87
+ | Syntax | Description |
88
+ |--------|-------------|
89
+ | `\|p: type\|{ } :> $fn` | Define and capture function |
90
+ | `\|p = default\|{ }` | Parameter with default |
91
+ | `$fn(arg)` | Call function directly |
92
+ | `arg -> $fn()` | Call function with pipe value |
93
+ | `arg -> $fn` | Pipe-style invoke |
94
+
95
+ See [Closures](06_closures.md) for detailed documentation.
96
+
97
+ ### Special Variables
98
+
99
+ | Variable | Contains | Source |
100
+ |----------|----------|--------|
101
+ | `$` | Piped value (current scope) | Grammar |
102
+ | `$ARGS` | CLI positional args (list) | Runtime |
103
+ | `$ENV.NAME` | Environment variable | Runtime |
104
+ | `$name` | Named variable | Runtime |
105
+
106
+ See [Variables](03_variables.md) for detailed documentation.
107
+
108
+ ### `$` Binding by Context
109
+
110
+ | Context | `$` contains |
111
+ |---------|--------------|
112
+ | Inline block `-> { }` | Piped value |
113
+ | Each loop `-> each { }` | Current item |
114
+ | While-loop `(cond) @ { }` | Accumulated value |
115
+ | Do-while `@ { } ? cond` | Accumulated value |
116
+ | Conditional `cond ? { }` | Tested value |
117
+ | Piped conditional `-> ? { }` | Piped value |
118
+ | Stored closure `\|x\|{ }` | N/A — use params |
119
+ | Dict closure `\|\|{ $.x }` | Dict self |
120
+
121
+ ### Property Access
122
+
123
+ | Syntax | Description |
124
+ |--------|-------------|
125
+ | `$data.field` | Literal field access |
126
+ | `$data[0]`, `$data[-1]` | Index access |
127
+ | `$data.$key` | Variable as key |
128
+ | `$data.($i + 1)` | Computed key |
129
+ | `$data.(a \|\| b)` | Alternative keys |
130
+ | `$data.field ?? default` | Default if missing |
131
+ | `$data.?field` | Existence check |
132
+
133
+ ### Parsing Functions
134
+
135
+ | Function | Description |
136
+ |----------|-------------|
137
+ | `parse_auto` | Auto-detect and extract structured content |
138
+ | `parse_json` | Parse JSON with error repair |
139
+ | `parse_xml(tag?)` | Extract content between XML tags |
140
+ | `parse_fence(lang?)` | Extract fenced code block content |
141
+ | `parse_fences` | Extract all fenced blocks as list |
142
+ | `parse_frontmatter` | Parse `---` delimited YAML frontmatter |
143
+ | `parse_checklist` | Parse `- [ ]` and `- [x]` items |
144
+
145
+ See [Parsing](10_parsing.md) for detailed documentation.
146
+
147
+ ### Core Methods
148
+
149
+ | Method | Input | Output | Description |
150
+ |--------|-------|--------|-------------|
151
+ | `.str` | Any | String | Convert to string |
152
+ | `.num` | Any | Number | Convert to number |
153
+ | `.len` | Any | Number | Length |
154
+ | `.trim` | String | String | Remove whitespace |
155
+ | `.head` | String/List | Any | First element |
156
+ | `.tail` | String/List | Any | Last element |
157
+ | `.at(idx)` | String/List | Any | Element at index |
158
+ | `.split(sep)` | String | List | Split by separator |
159
+ | `.join(sep)` | List | String | Join with separator |
160
+ | `.lines` | String | List | Split on newlines |
161
+ | `.lower` | String | String | Lowercase |
162
+ | `.upper` | String | String | Uppercase |
163
+ | `.replace(pat, repl)` | String | String | Replace first match |
164
+ | `.replace_all(pat, repl)` | String | String | Replace all matches |
165
+ | `.contains(text)` | String | Bool | Contains substring |
166
+ | `.starts_with(pre)` | String | Bool | Starts with prefix |
167
+ | `.ends_with(suf)` | String | Bool | Ends with suffix |
168
+ | `.match(regex)` | String | Dict | First match info |
169
+ | `.is_match(regex)` | String | Bool | Regex matches |
170
+ | `.empty` | Any | Bool | Is empty |
171
+ | `.keys` | Dict | List | All keys |
172
+ | `.values` | Dict | List | All values |
173
+ | `.entries` | Dict | List | Key-value pairs |
174
+
175
+ See [Strings](09_strings.md) for detailed string method documentation.
176
+
177
+ ### Global Functions
178
+
179
+ | Function | Description |
180
+ |----------|-------------|
181
+ | `type` | Returns type name of value |
182
+ | `log` | Print to console, pass through |
183
+ | `json` | Convert to JSON string |
184
+ | `identity` | Returns input unchanged |
185
+ | `range(start, end, step?)` | Generate number sequence |
186
+ | `repeat(value, count)` | Repeat value n times |
187
+ | `enumerate(collection)` | Add index to elements |
188
+
189
+ See [Iterators](08_iterators.md) for `range` and `repeat` documentation.
190
+
191
+ ---
192
+
193
+ ## Implied `$`
194
+
195
+ When constructs appear without explicit input, `$` is used implicitly:
196
+
197
+ | Written | Equivalent to |
198
+ |---------|---------------|
199
+ | `? { }` | `$ -> ? { }` |
200
+ | `.method()` | `$ -> .method()` |
201
+ | `$fn()` | `$fn($)` (when no args, no default) |
202
+
203
+ ---
204
+
205
+ ## Extraction Operators
206
+
207
+ ### Destructure `*<>`
208
+
209
+ Extract elements from lists or dicts into variables:
210
+
211
+ ```rill
212
+ [1, 2, 3] -> *<$a, $b, $c>
213
+ # $a = 1, $b = 2, $c = 3
214
+
215
+ [name: "test", count: 42] -> *<name: $n, count: $c>
216
+ # $n = "test", $c = 42
217
+ ```
218
+
219
+ ### Slice `/<>`
220
+
221
+ Extract portions using Python-style `start:stop:step`:
222
+
223
+ ```rill
224
+ [0, 1, 2, 3, 4] -> /<0:3> # [0, 1, 2]
225
+ [0, 1, 2, 3, 4] -> /<-2:> # [3, 4]
226
+ [0, 1, 2, 3, 4] -> /<::-1> # [4, 3, 2, 1, 0]
227
+ "hello" -> /<1:4> # "ell"
228
+ ```
229
+
230
+ See [Operators](04_operators.md) for detailed extraction operator documentation.
231
+
232
+ ---
233
+
234
+ ## Tuples
235
+
236
+ Tuples package values for argument unpacking:
237
+
238
+ ```rill
239
+ |a, b, c|"{$a}-{$b}-{$c}" :> $fmt
240
+ *[1, 2, 3] -> $fmt() # "1-2-3"
241
+ *[c: 3, a: 1, b: 2] -> $fmt() # "1-2-3" (named)
242
+ ```
243
+
244
+ See [Types](02_types.md) for detailed tuple documentation.
245
+
246
+ ---
247
+
248
+ ## Runtime Limits
249
+
250
+ ### Iteration Limits
251
+
252
+ Loops have a default maximum of **10,000 iterations**. Override with `^(limit: N)`:
253
+
254
+ ```rill
255
+ ^(limit: 100) 0 -> ($ < 50) @ { $ + 1 }
256
+ ```
257
+
258
+ ### Concurrency Limits
259
+
260
+ The `^(limit: N)` annotation also controls parallel concurrency in `map`:
261
+
262
+ ```text
263
+ ^(limit: 3) $items -> map { slow_process($) }
264
+ ```
265
+
266
+ See [Host Integration](14_host-integration.md) for timeout and cancellation configuration.
267
+
268
+ ---
269
+
270
+ ## Host-Provided Functions
271
+
272
+ rill is a vanilla language. The host application registers domain-specific functions via `RuntimeContext`:
273
+
274
+ ```typescript
275
+ const ctx = createRuntimeContext({
276
+ functions: {
277
+ prompt: async (args) => await callLLM(args[0]),
278
+ 'io::read': async (args) => fs.readFile(String(args[0]), 'utf-8'),
279
+ },
280
+ variables: {
281
+ config: { apiUrl: 'https://api.example.com' },
282
+ },
283
+ });
284
+ ```
285
+
286
+ Scripts call these as `prompt("text")` or `io::read("file.txt")`.
287
+
288
+ See [Host Integration](14_host-integration.md) for complete API documentation.
289
+
290
+ ---
291
+
292
+ ## Script Frontmatter
293
+
294
+ Optional YAML frontmatter between `---` markers. **Frontmatter is opaque to rill**—the host interprets it:
295
+
296
+ ```text
297
+ ---
298
+ timeout: 00:10:00
299
+ args: file: string
300
+ ---
301
+
302
+ process($file)
303
+ ```
304
+
305
+ ---
306
+
307
+ ## Script Return Values
308
+
309
+ Scripts return their last expression:
310
+
311
+ | Return | Exit Code |
312
+ |--------|-----------|
313
+ | `true` / non-empty string | 0 |
314
+ | `false` / empty string | 1 |
315
+ | `[0, "message"]` | 0 with message |
316
+ | `[1, "message"]` | 1 with message |
317
+
318
+ ---
319
+
320
+ ## Comments
321
+
322
+ Single-line comments start with `#`:
323
+
324
+ ```rill
325
+ # This is a comment
326
+ "hello" # inline comment
327
+ ```
328
+
329
+ ---
330
+
331
+ ## Grammar
332
+
333
+ The complete formal grammar is in [grammar.ebnf](15_grammar.ebnf).
334
+
335
+ ---
336
+
337
+ ## Topic Guides
338
+
339
+ For detailed documentation on specific topics:
340
+
341
+ - [Types](02_types.md) — Type system, type assertions
342
+ - [Variables](03_variables.md) — Declaration, scope, `$` binding
343
+ - [Control Flow](05_control-flow.md) — Conditionals, loops
344
+ - [Operators](04_operators.md) — All operators
345
+ - [Closures](06_closures.md) — Late binding, dict closures
346
+ - [Collections](07_collections.md) — `each`, `map`, `filter`, `fold`
347
+ - [Iterators](08_iterators.md) — `range`, `repeat`, `.first()`
348
+ - [Strings](09_strings.md) — String methods
349
+ - [Parsing](10_parsing.md) — Content parsing
350
+ - [Host Integration](14_host-integration.md) — Embedding API