llguidance 1.1.2__tar.gz → 1.3.0__tar.gz

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 (196) hide show
  1. llguidance-1.3.0/.github/workflows/code-coverage.yml +126 -0
  2. {llguidance-1.1.2 → llguidance-1.3.0}/.github/workflows/rust.yml +1 -1
  3. {llguidance-1.1.2 → llguidance-1.3.0}/CHANGELOG.md +14 -0
  4. {llguidance-1.1.2 → llguidance-1.3.0}/Cargo.lock +8 -8
  5. {llguidance-1.1.2 → llguidance-1.3.0}/Cargo.toml +3 -0
  6. {llguidance-1.1.2 → llguidance-1.3.0}/PKG-INFO +1 -1
  7. {llguidance-1.1.2 → llguidance-1.3.0}/docs/json_schema.md +22 -2
  8. {llguidance-1.1.2 → llguidance-1.3.0}/docs/syntax.md +1 -1
  9. {llguidance-1.1.2 → llguidance-1.3.0}/parser/Cargo.toml +2 -1
  10. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/api.rs +10 -0
  11. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/grammar.rs +1 -1
  12. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/parser.rs +5 -6
  13. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/perf.rs +1 -1
  14. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/regexvec.rs +1 -1
  15. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/grammar_builder.rs +3 -0
  16. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/compiler.rs +49 -25
  17. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/numeric.rs +1 -1
  18. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lark/lexer.rs +1 -1
  19. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/logging.rs +2 -2
  20. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/matcher.rs +1 -2
  21. {llguidance-1.1.2 → llguidance-1.3.0}/pyproject.toml +1 -1
  22. {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/_lib.pyi +34 -3
  23. {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/numpy.py +14 -0
  24. {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/torch.py +11 -0
  25. {llguidance-1.1.2 → llguidance-1.3.0}/python/torch_tests/test_matcher.py +149 -2
  26. {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/Cargo.toml +2 -1
  27. {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/src/llinterpreter.rs +2 -2
  28. {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/src/llmatcher.rs +113 -4
  29. {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/src/py.rs +3 -11
  30. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/common_lark_utils/mod.rs +7 -0
  31. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_json_primitives.rs +13 -7
  32. llguidance-1.3.0/sample_parser/tests/test_json_schema_combinations.rs +372 -0
  33. llguidance-1.3.0/sample_parser/tests/test_json_string_format.rs +141 -0
  34. llguidance-1.3.0/sample_parser/tests/test_json_x_guidance.rs +81 -0
  35. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_lark.rs +16 -0
  36. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_ll.rs +9 -0
  37. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_raw_parser.rs +26 -0
  38. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/Cargo.toml +2 -1
  39. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/src/bytes.rs +1 -1
  40. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/src/svob.rs +1 -1
  41. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/src/toktree.rs +1 -1
  42. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_hf_downloader/Cargo.toml +2 -1
  43. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_hf_tokenizers/Cargo.toml +2 -1
  44. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_tiktoken/Cargo.toml +2 -1
  45. llguidance-1.1.2/.github/workflows/code-coverage.yml +0 -62
  46. llguidance-1.1.2/sample_parser/tests/test_json_schema_combinations.rs +0 -154
  47. {llguidance-1.1.2 → llguidance-1.3.0}/.github/workflows/wheels.yml +0 -0
  48. {llguidance-1.1.2 → llguidance-1.3.0}/.gitignore +0 -0
  49. {llguidance-1.1.2 → llguidance-1.3.0}/CODE_OF_CONDUCT.md +0 -0
  50. {llguidance-1.1.2 → llguidance-1.3.0}/LICENSE +0 -0
  51. {llguidance-1.1.2 → llguidance-1.3.0}/README.md +0 -0
  52. {llguidance-1.1.2 → llguidance-1.3.0}/SECURITY.md +0 -0
  53. {llguidance-1.1.2 → llguidance-1.3.0}/SUPPORT.md +0 -0
  54. {llguidance-1.1.2 → llguidance-1.3.0}/c_sample/Makefile +0 -0
  55. {llguidance-1.1.2 → llguidance-1.3.0}/c_sample/README.md +0 -0
  56. {llguidance-1.1.2 → llguidance-1.3.0}/c_sample/c_sample.cpp +0 -0
  57. {llguidance-1.1.2 → llguidance-1.3.0}/docs/de_recursing.md +0 -0
  58. {llguidance-1.1.2 → llguidance-1.3.0}/docs/fast_forward.md +0 -0
  59. {llguidance-1.1.2 → llguidance-1.3.0}/docs/mask_plot.png +0 -0
  60. {llguidance-1.1.2 → llguidance-1.3.0}/docs/optimizations.md +0 -0
  61. {llguidance-1.1.2 → llguidance-1.3.0}/docs/parametric.md +0 -0
  62. {llguidance-1.1.2 → llguidance-1.3.0}/docs/special_tokens.md +0 -0
  63. {llguidance-1.1.2 → llguidance-1.3.0}/docs/toktrie.md +0 -0
  64. {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/Cargo.toml +0 -0
  65. {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/expected_maskbench.json +0 -0
  66. {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/jstats.sh +0 -0
  67. {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/scripts/split-stats.sh +0 -0
  68. {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/scripts/split_plot.py +0 -0
  69. {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/src/json_stats.rs +0 -0
  70. {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/src/lib.rs +0 -0
  71. {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/src/stats.rs +0 -0
  72. {llguidance-1.1.2 → llguidance-1.3.0}/parser/LICENSE +0 -0
  73. {llguidance-1.1.2 → llguidance-1.3.0}/parser/README.md +0 -0
  74. {llguidance-1.1.2 → llguidance-1.3.0}/parser/build.rs +0 -0
  75. {llguidance-1.1.2 → llguidance-1.3.0}/parser/cbindgen.toml +0 -0
  76. {llguidance-1.1.2 → llguidance-1.3.0}/parser/grammars/character.json +0 -0
  77. {llguidance-1.1.2 → llguidance-1.3.0}/parser/grammars/json.json +0 -0
  78. {llguidance-1.1.2 → llguidance-1.3.0}/parser/llguidance.h +0 -0
  79. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/constraint.rs +0 -0
  80. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/from_guidance.rs +0 -0
  81. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/lexer.rs +0 -0
  82. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/lexerspec.rs +0 -0
  83. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/mod.rs +0 -0
  84. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/slicer.rs +0 -0
  85. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/factory.rs +0 -0
  86. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/ffi.rs +0 -0
  87. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/ffi_par.rs +0 -0
  88. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/hashcons.rs +0 -0
  89. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/README.md +0 -0
  90. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/context_ref.rs +0 -0
  91. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/context_simple/context.rs +0 -0
  92. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/context_simple/draft.rs +0 -0
  93. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/context_simple/mod.rs +0 -0
  94. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/formats.rs +0 -0
  95. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/mod.rs +0 -0
  96. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/schema.rs +0 -0
  97. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/shared_context.rs +0 -0
  98. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json_validation.rs +0 -0
  99. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lark/README.md +0 -0
  100. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lark/ast.rs +0 -0
  101. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lark/common.rs +0 -0
  102. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lark/compiler.rs +0 -0
  103. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lark/mod.rs +0 -0
  104. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lark/parser.rs +0 -0
  105. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lib.rs +0 -0
  106. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/output.rs +0 -0
  107. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/panic_utils.rs +0 -0
  108. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/regex_rewrite.rs +0 -0
  109. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/stop_controller.rs +0 -0
  110. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/substring.rs +0 -0
  111. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/tokenizer_json.rs +0 -0
  112. {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/tokenparser.rs +0 -0
  113. {llguidance-1.1.2 → llguidance-1.3.0}/plan.md +0 -0
  114. {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/__init__.py +0 -0
  115. {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/_grammar_from.py +0 -0
  116. {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/_struct_tag.py +0 -0
  117. {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/_tokenizer.py +0 -0
  118. {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/_util.py +0 -0
  119. {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/cli.py +0 -0
  120. {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/gbnf_to_lark.py +0 -0
  121. {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/hf.py +0 -0
  122. {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/llamacpp.py +0 -0
  123. {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/mlx.py +0 -0
  124. {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/py.typed +0 -0
  125. {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/tiktoken.py +0 -0
  126. {llguidance-1.1.2 → llguidance-1.3.0}/python/mypy.ini +0 -0
  127. {llguidance-1.1.2 → llguidance-1.3.0}/python/torch_tests/__init__.py +0 -0
  128. {llguidance-1.1.2 → llguidance-1.3.0}/python/torch_tests/test_bitmask.py +0 -0
  129. {llguidance-1.1.2 → llguidance-1.3.0}/python/torch_tests/test_hf.py +0 -0
  130. {llguidance-1.1.2 → llguidance-1.3.0}/python/torch_tests/test_llamacpp.py +0 -0
  131. {llguidance-1.1.2 → llguidance-1.3.0}/python/torch_tests/test_tiktoken.py +0 -0
  132. {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/src/lib.rs +0 -0
  133. {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/src/llamatokenizer.rs +0 -0
  134. {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/src/parserlimits.rs +0 -0
  135. {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/src/pyjson.rs +0 -0
  136. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/Cargo.toml +0 -0
  137. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/README.md +0 -0
  138. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/cli.sh +0 -0
  139. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/blog.sample.json +0 -0
  140. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/blog.schema.json +0 -0
  141. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/blog.schema.ll.json +0 -0
  142. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/README.md +0 -0
  143. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/arithmetic.gbnf +0 -0
  144. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/c.gbnf +0 -0
  145. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/chess.gbnf +0 -0
  146. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/english.gbnf +0 -0
  147. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/japanese.gbnf +0 -0
  148. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/json.gbnf +0 -0
  149. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/json_arr.gbnf +0 -0
  150. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/list.gbnf +0 -0
  151. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/vllm-sql.gbnf +0 -0
  152. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/lark.lark +0 -0
  153. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/rfc.lark +0 -0
  154. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/rfc.xml +0 -0
  155. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/ulysses.md +0 -0
  156. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/gtest.sh +0 -0
  157. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/lark.sh +0 -0
  158. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/run.sh +0 -0
  159. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/src/lib.rs +0 -0
  160. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/src/minimal.rs +0 -0
  161. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/src/sample_parser.rs +0 -0
  162. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_json_arrays.rs +0 -0
  163. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_json_enum_const.rs +0 -0
  164. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_json_objects.rs +0 -0
  165. {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_stop.rs +0 -0
  166. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/annotate_asm.js +0 -0
  167. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/bump.py +0 -0
  168. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/cbindgen.sh +0 -0
  169. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/checklinks.py +0 -0
  170. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/checklinks.sh +0 -0
  171. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/ci-publish.py +0 -0
  172. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/disasm.sh +0 -0
  173. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/gbnf_to_lark.py +0 -0
  174. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/gen-testcase.py +0 -0
  175. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/git-version.sh +0 -0
  176. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/install-deps.sh +0 -0
  177. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/jsonschema-stats.js +0 -0
  178. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/remote-guidance-test.sh +0 -0
  179. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/rust-size.js +0 -0
  180. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/rust_size.py +0 -0
  181. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/test-guidance.sh +0 -0
  182. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/tokenizer_test.py +0 -0
  183. {llguidance-1.1.2 → llguidance-1.3.0}/scripts/update-git.py +0 -0
  184. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/LICENSE +0 -0
  185. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/README.md +0 -0
  186. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/src/lib.rs +0 -0
  187. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/src/recognizer.rs +0 -0
  188. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/src/rng.rs +0 -0
  189. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/src/tokenv.rs +0 -0
  190. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/tests/test_svob.rs +0 -0
  191. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_hf_downloader/LICENSE +0 -0
  192. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_hf_downloader/src/lib.rs +0 -0
  193. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_hf_tokenizers/LICENSE +0 -0
  194. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_hf_tokenizers/src/lib.rs +0 -0
  195. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_tiktoken/LICENSE +0 -0
  196. {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_tiktoken/src/lib.rs +0 -0
@@ -0,0 +1,126 @@
1
+ name: Code Coverage
2
+ permissions:
3
+ contents: read
4
+
5
+
6
+ on:
7
+ pull_request:
8
+ push:
9
+ branches: [ "main" ]
10
+ workflow_dispatch:
11
+ inputs:
12
+ commit_id:
13
+ description: 'Branch or Commit ID (optional)'
14
+ required: false
15
+ type: string
16
+
17
+
18
+ env:
19
+ CARGO_TERM_COLOR: always
20
+ RUSTFLAGS: "-Cinstrument-coverage"
21
+ LLVM_PROFILE_FILE: "llg-%p-%m.profraw"
22
+
23
+
24
+ jobs:
25
+ code-cov-rust:
26
+ runs-on: ubuntu-latest
27
+
28
+ steps:
29
+ - name: Checkout repo at ${{ github.event_name == 'workflow_dispatch' && inputs.commit_id || github.sha }}
30
+ uses: actions/checkout@v4
31
+ with:
32
+ ref: ${{ github.event_name == 'workflow_dispatch' && inputs.commit_id || github.sha }}
33
+
34
+ - name: Update toolchain
35
+ run: rustup component add llvm-tools
36
+
37
+ - name: Install grcov
38
+ run: cargo install grcov
39
+
40
+ - name: Build everything
41
+ run: cargo build
42
+
43
+ - name: Run tests
44
+ run: cargo test
45
+
46
+ - name: Check environment
47
+ run: |
48
+ echo "CARGO_TERM_COLOR: $CARGO_TERM_COLOR"
49
+ echo "RUSTFLAGS: $RUSTFLAGS"
50
+ echo "LLVM_PROFILE_FILE: $LLVM_PROFILE_FILE"
51
+
52
+ - name: Generate coverage report
53
+ run: |
54
+ grcov . -s . --binary-path target/debug/ -t html --branch --ignore-not-existing -o target/debug/coverage/
55
+
56
+ - name: Check output
57
+ run: ls target/debug/coverage/
58
+
59
+ - uses: actions/upload-artifact@v4
60
+ with:
61
+ name: coverage-report-rust
62
+ path: target/debug/coverage/
63
+
64
+ code-cov-python:
65
+ runs-on: ubuntu-latest
66
+
67
+ steps:
68
+ - name: Checkout repo at ${{ github.event_name == 'workflow_dispatch' && inputs.commit_id || github.sha }}
69
+ uses: actions/checkout@v4
70
+ with:
71
+ ref: ${{ github.event_name == 'workflow_dispatch' && inputs.commit_id || github.sha }}
72
+
73
+ - name: Setup Python
74
+ uses: actions/setup-python@v5
75
+ with:
76
+ python-version: "3.11"
77
+
78
+ - name: Check environment
79
+ run: |
80
+ echo "CARGO_TERM_COLOR: $CARGO_TERM_COLOR"
81
+ echo "RUSTFLAGS: $RUSTFLAGS"
82
+ echo "LLVM_PROFILE_FILE: $LLVM_PROFILE_FILE"
83
+
84
+ - name: Update toolchain
85
+ run: rustup component add llvm-tools
86
+
87
+ - name: Install grcov
88
+ run: cargo install grcov
89
+
90
+ - name: Clone guidance
91
+ run: |
92
+ git clone -b main https://github.com/guidance-ai/guidance
93
+
94
+ - name: Install guidance
95
+ run: |
96
+ cd guidance
97
+ pip install .[all,test]
98
+
99
+ - name: Install local llguidance
100
+ run: |
101
+ pip uninstall -y llguidance || :
102
+ pip install -v -e .
103
+
104
+ - name: Verify llguidance being used
105
+ run: pip show llguidance
106
+
107
+ - name: Run tests
108
+ run: |
109
+ cd guidance
110
+ python -m pytest tests/unit
111
+
112
+ - name: See all outputs
113
+ run: ls -R
114
+
115
+ - name: Generate coverage report
116
+ run: |
117
+ grcov . -s . --binary-path . -t html --branch --ignore-not-existing -o target/debug/coverage/
118
+
119
+ - name: Check output
120
+ run: ls target/debug/coverage/
121
+
122
+ - uses: actions/upload-artifact@v4
123
+ with:
124
+ name: coverage-report-python
125
+ path: target/debug/coverage/
126
+
@@ -62,7 +62,7 @@ jobs:
62
62
  - uses: actions/checkout@v4
63
63
 
64
64
  - name: Set up Rust
65
- uses: dtolnay/rust-toolchain@1.80.0
65
+ uses: dtolnay/rust-toolchain@1.87.0
66
66
  with:
67
67
  components: clippy
68
68
 
@@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  If a release doesn't introduce any interesting changes (build fixes etc.), it's skipped.
6
6
 
7
+ #### [v1.3.0](https://github.com/guidance-ai/llguidance/compare/v1.2.0...v1.3.0) 2025-10-20
8
+
9
+ - change semantics of JSON separators (now regex patterns instead of text literals) [`#246`](https://github.com/guidance-ai/llguidance/pull/246)
10
+ - fix Inconsistent handling of the EOS token in `try_consume_tokens` [`#244`](https://github.com/guidance-ai/llguidance/pull/244)
11
+ - add option for initial skip of `%ignore` lexeme [`#235`](https://github.com/guidance-ai/llguidance/pull/235)
12
+ - bump MSRV to 1.87.0 [`#243`](https://github.com/guidance-ai/llguidance/pull/243)
13
+
14
+ #### [v1.2.0](https://github.com/guidance-ai/llguidance/compare/v1.1.2...v1.2.0) 2025-08-12
15
+
16
+ - support multithreaded compute bitmask for speculative decoding [`#225`](https://github.com/guidance-ai/llguidance/pull/225)
17
+ - thank you [@ZonePG](https://github.com/ZonePG)!
18
+ - `force_lexeme_end` -> `try_lexeme_end` in lark lexer when out of input [`#229`](https://github.com/guidance-ai/llguidance/pull/229); fixes [`#228`](https://github.com/guidance-ai/llguidance/issues/228)
19
+ - more JSON test coverage
20
+
7
21
  #### [v1.1.2](https://github.com/guidance-ai/llguidance/compare/v1.1.1...v1.1.2) 2025-08-08
8
22
 
9
23
  - add flag in ParserLimits to disable verbose errors [`#227`](https://github.com/guidance-ai/llguidance/pull/227)
@@ -1241,7 +1241,7 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
1241
1241
 
1242
1242
  [[package]]
1243
1243
  name = "llguidance"
1244
- version = "1.1.2"
1244
+ version = "1.3.0"
1245
1245
  dependencies = [
1246
1246
  "anyhow",
1247
1247
  "derivre",
@@ -1260,7 +1260,7 @@ dependencies = [
1260
1260
 
1261
1261
  [[package]]
1262
1262
  name = "llguidance_py"
1263
- version = "1.1.2"
1263
+ version = "1.3.0"
1264
1264
  dependencies = [
1265
1265
  "anyhow",
1266
1266
  "bytemuck",
@@ -2176,9 +2176,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
2176
2176
 
2177
2177
  [[package]]
2178
2178
  name = "slab"
2179
- version = "0.4.10"
2179
+ version = "0.4.11"
2180
2180
  source = "registry+https://github.com/rust-lang/crates.io-index"
2181
- checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
2181
+ checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
2182
2182
 
2183
2183
  [[package]]
2184
2184
  name = "smallvec"
@@ -2478,7 +2478,7 @@ dependencies = [
2478
2478
 
2479
2479
  [[package]]
2480
2480
  name = "toktrie"
2481
- version = "1.1.2"
2481
+ version = "1.3.0"
2482
2482
  dependencies = [
2483
2483
  "anyhow",
2484
2484
  "bytemuck",
@@ -2489,7 +2489,7 @@ dependencies = [
2489
2489
 
2490
2490
  [[package]]
2491
2491
  name = "toktrie_hf_downloader"
2492
- version = "1.1.2"
2492
+ version = "1.3.0"
2493
2493
  dependencies = [
2494
2494
  "anyhow",
2495
2495
  "hf-hub",
@@ -2500,7 +2500,7 @@ dependencies = [
2500
2500
 
2501
2501
  [[package]]
2502
2502
  name = "toktrie_hf_tokenizers"
2503
- version = "1.1.2"
2503
+ version = "1.3.0"
2504
2504
  dependencies = [
2505
2505
  "anyhow",
2506
2506
  "log",
@@ -2512,7 +2512,7 @@ dependencies = [
2512
2512
 
2513
2513
  [[package]]
2514
2514
  name = "toktrie_tiktoken"
2515
- version = "1.1.2"
2515
+ version = "1.3.0"
2516
2516
  dependencies = [
2517
2517
  "anyhow",
2518
2518
  "log",
@@ -21,6 +21,9 @@ default-members = [
21
21
  ]
22
22
  resolver = "2"
23
23
 
24
+ [workspace.package]
25
+ rust-version="1.87"
26
+
24
27
  [profile.release]
25
28
  debug = 1
26
29
  strip = "debuginfo"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llguidance
3
- Version: 1.1.2
3
+ Version: 1.3.0
4
4
  License-File: LICENSE
5
5
  Summary: Bindings for the Low-level Guidance (llguidance) Rust library for use within Guidance
6
6
  Author: Michal Moskal
@@ -76,8 +76,8 @@ You can modify your grammar easily to allow initial or trailing whitespace.
76
76
  You can set top-level `"x-guidance"` key to control this.
77
77
  Following keys are available inside of it:
78
78
 
79
- - `item_separator`, defaults to `":"`
80
- - `key_separator`, defaults to `","`
79
+ - `item_separator`, defaults to `","` - a regex pattern for the separator between array items or object properties
80
+ - `key_separator`, defaults to `":"` - a regex pattern for the separator between object keys and values
81
81
  - `whitespace_flexible`, defaults to `true`; set to `false` to enforce compact JSON representation
82
82
  - `whitespace_pattern`, optional string, overrides `whitespace_flexible`;
83
83
  `whitespace_flexible: true` is equivalent to `whitespace_pattern: r"[\x20\x0A\x0D\x09]+"`
@@ -100,6 +100,26 @@ For example:
100
100
  }
101
101
  ```
102
102
 
103
+ The separators are treated as regex patterns, allowing for flexible formatting:
104
+
105
+ ```json
106
+ {
107
+ "x-guidance": {
108
+ "item_separator": "\\s{0,2},\\s{0,2}",
109
+ "key_separator": "\\s{0,2}:\\s{0,2}",
110
+ "whitespace_flexible": false
111
+ },
112
+ "type": "object",
113
+ "properties": {
114
+ "a": { "type": "number" },
115
+ "b": { "type": "number" }
116
+ }
117
+ }
118
+ ```
119
+
120
+ This will match JSON like `{"a":1,"b":2}`, `{"a": 1, "b": 2}`, or `{"a" : 1 , "b":2}`,
121
+ but not `{"a":1, "b":2}` (too much whitespace after comma).
122
+
103
123
  The `"x-guidance"` key is only recognized at the top level of the schema.
104
124
 
105
125
 
@@ -318,7 +318,7 @@ MULT_NUM: %regex {
318
318
 
319
319
  Certain grammar options can be set by using `%llguidnace { ... }`,
320
320
  by passing it a JSON object with the options;
321
- see `LLGuidanceOptions` in [api.rs](../parser/src/api.rs#L24).
321
+ see `LLGuidanceOptions` in [api.rs](../parser/src/api.rs#L36).
322
322
  Example: `%llguidance { "no_forcing": true }`.
323
323
  It can be specified multiple times, with the options being merged.
324
324
 
@@ -1,10 +1,11 @@
1
1
  [package]
2
2
  name = "llguidance"
3
- version = "1.1.2"
3
+ version = "1.3.0"
4
4
  edition = "2021"
5
5
  license = "MIT"
6
6
  description = "Super-fast Structured Outputs"
7
7
  repository = "https://github.com/guidance-ai/llguidance"
8
+ rust-version.workspace = true
8
9
 
9
10
  [dependencies]
10
11
  toktrie = { workspace = true }
@@ -47,6 +47,13 @@ pub struct LLGuidanceOptions {
47
47
  /// This is very unlikely what you need.
48
48
  #[serde(default)]
49
49
  pub allow_invalid_utf8: bool,
50
+
51
+ /// If set, the grammar will allow the %ignore lexeme at the start of the grammar.
52
+ /// Otherwise, it will only be allowed after the first non-ignored lexeme.
53
+ /// This option (like the other options here) will apply to the entire grammar,
54
+ /// including nested sub-grammars.
55
+ #[serde(default)]
56
+ pub allow_initial_skip: bool,
50
57
  }
51
58
 
52
59
  impl LLGuidanceOptions {
@@ -57,6 +64,9 @@ impl LLGuidanceOptions {
57
64
  if other.allow_invalid_utf8 {
58
65
  self.allow_invalid_utf8 = true;
59
66
  }
67
+ if other.allow_initial_skip {
68
+ self.allow_initial_skip = true;
69
+ }
60
70
  }
61
71
  }
62
72
 
@@ -1322,7 +1322,7 @@ impl CGrammar {
1322
1322
  outp.rhs_elements.push(CSymIdx::NULL);
1323
1323
  outp.rhs_params.push(ParamExpr::Null);
1324
1324
  }
1325
- while outp.rhs_elements.len() % (1 << RULE_SHIFT) != 0 {
1325
+ while !outp.rhs_elements.len().is_multiple_of(1 << RULE_SHIFT) {
1326
1326
  outp.rhs_elements.push(CSymIdx::NULL);
1327
1327
  outp.rhs_params.push(ParamExpr::Null);
1328
1328
  }
@@ -132,7 +132,7 @@ impl XorShift {
132
132
  }
133
133
 
134
134
  pub fn one_in(&mut self, n: u32) -> bool {
135
- self.next() % n == 0
135
+ self.next().is_multiple_of(n)
136
136
  }
137
137
 
138
138
  pub fn next_alt(&mut self) -> u32 {
@@ -1611,7 +1611,10 @@ impl ParserState {
1611
1611
 
1612
1612
  let curr = self.lexer_state();
1613
1613
 
1614
- let res = if byte.is_none() {
1614
+ let res = if let Some(b) = byte {
1615
+ self.stats.definitive_bytes += 1;
1616
+ self.lexer_mut().advance(curr.lexer_state, b, true)
1617
+ } else {
1615
1618
  let lexeme = self.lexer_mut().force_lexeme_end(curr.lexer_state);
1616
1619
  if lexeme.is_error() {
1617
1620
  debug!(
@@ -1620,10 +1623,6 @@ impl ParserState {
1620
1623
  );
1621
1624
  }
1622
1625
  lexeme
1623
- } else {
1624
- self.stats.definitive_bytes += 1;
1625
- self.lexer_mut()
1626
- .advance(curr.lexer_state, byte.unwrap(), true)
1627
1626
  };
1628
1627
 
1629
1628
  if res.is_error() {
@@ -140,7 +140,7 @@ pub fn num_with_commas(x: usize) -> String {
140
140
 
141
141
  for (i, c) in s.chars().enumerate() {
142
142
  // Insert a comma once we've passed 'offset' and every 3 digits after that.
143
- if i != 0 && i >= offset && (i - offset) % 3 == 0 {
143
+ if i != 0 && i >= offset && (i - offset).is_multiple_of(3) {
144
144
  result.push(',');
145
145
  }
146
146
  result.push(c);
@@ -674,7 +674,7 @@ impl RegexVec {
674
674
  // if lst.len() == 0 {
675
675
  // return StateID::DEAD;
676
676
  // }
677
- assert!(lst.len() % 2 == 0);
677
+ assert!(lst.len().is_multiple_of(2));
678
678
  let id = StateID::new(self.rx_sets.insert(&lst));
679
679
  if id.as_usize() >= self.state_descs.len() {
680
680
  let state_desc = self.compute_state_desc(id);
@@ -233,6 +233,9 @@ impl GrammarBuilder {
233
233
  if options.no_forcing {
234
234
  self.regex.spec.no_forcing = true;
235
235
  }
236
+ if options.allow_initial_skip {
237
+ self.regex.spec.allow_initial_skip = true;
238
+ }
236
239
 
237
240
  // add root node
238
241
  self.curr_start_idx = self.new_node("start");
@@ -58,6 +58,8 @@ struct Compiler {
58
58
 
59
59
  any_cache: Option<NodeRef>,
60
60
  string_cache: Option<NodeRef>,
61
+ item_separator_cache: Option<NodeRef>,
62
+ key_separator_cache: Option<NodeRef>,
61
63
  }
62
64
 
63
65
  macro_rules! cache {
@@ -136,6 +138,8 @@ impl Compiler {
136
138
  pending_definitions: vec![],
137
139
  any_cache: None,
138
140
  string_cache: None,
141
+ item_separator_cache: None,
142
+ key_separator_cache: None,
139
143
  pattern_cache: PatternPropertyCache::default(),
140
144
  }
141
145
  }
@@ -331,6 +335,26 @@ impl Compiler {
331
335
  })
332
336
  }
333
337
 
338
+ fn item_separator(&mut self) -> Result<NodeRef> {
339
+ if let Some(node) = self.item_separator_cache {
340
+ return Ok(node);
341
+ }
342
+ let rx = self.builder.regex.regex(&self.options.item_separator)?;
343
+ let node = self.builder.lexeme(rx);
344
+ self.item_separator_cache = Some(node);
345
+ Ok(node)
346
+ }
347
+
348
+ fn key_separator(&mut self) -> Result<NodeRef> {
349
+ if let Some(node) = self.key_separator_cache {
350
+ return Ok(node);
351
+ }
352
+ let rx = self.builder.regex.regex(&self.options.key_separator)?;
353
+ let node = self.builder.lexeme(rx);
354
+ self.key_separator_cache = Some(node);
355
+ Ok(node)
356
+ }
357
+
334
358
  fn get_definition(&mut self, reference: &str) -> Result<NodeRef> {
335
359
  if let Some(definition) = self.definitions.get(reference) {
336
360
  return Ok(*definition);
@@ -380,7 +404,7 @@ impl Compiler {
380
404
  let mut unquoted_taken_names: Vec<String> = vec![];
381
405
  let mut items: Vec<(NodeRef, bool)> = vec![];
382
406
 
383
- let colon = self.builder.string(&self.options.key_separator);
407
+ let colon = self.key_separator()?;
384
408
 
385
409
  let mut num_required = 0;
386
410
  let mut num_optional = 0;
@@ -489,7 +513,7 @@ impl Compiler {
489
513
  let sel_options = options
490
514
  .iter()
491
515
  .map(|v| self.object_fields(v))
492
- .collect::<Vec<_>>();
516
+ .collect::<Result<Vec<_>>>()?;
493
517
  return Ok(self.builder.select(&sel_options));
494
518
  }
495
519
 
@@ -568,7 +592,7 @@ impl Compiler {
568
592
  if !pattern_options.is_empty() && max_properties != Some(0) {
569
593
  let pattern = self.builder.select(&pattern_options);
570
594
  let required = min_properties > 0;
571
- let seq = self.bounded_sequence(pattern, min_properties, max_properties);
595
+ let seq = self.bounded_sequence(pattern, min_properties, max_properties)?;
572
596
  items.push((seq, required));
573
597
  } else if min_properties > 0 {
574
598
  return Err(anyhow!(UnsatisfiableSchemaError {
@@ -578,14 +602,14 @@ impl Compiler {
578
602
  }));
579
603
  }
580
604
 
581
- Ok(self.object_fields(&items))
605
+ self.object_fields(&items)
582
606
  }
583
607
 
584
- fn object_fields(&mut self, items: &[(NodeRef, bool)]) -> NodeRef {
608
+ fn object_fields(&mut self, items: &[(NodeRef, bool)]) -> Result<NodeRef> {
585
609
  let opener = self.builder.string("{");
586
- let inner = self.ordered_sequence(items, false, &mut HashMap::default());
610
+ let inner = self.ordered_sequence(items, false, &mut HashMap::default())?;
587
611
  let closer = self.builder.string("}");
588
- self.builder.join(&[opener, inner, closer])
612
+ Ok(self.builder.join(&[opener, inner, closer]))
589
613
  }
590
614
 
591
615
  #[allow(clippy::type_complexity)]
@@ -594,22 +618,22 @@ impl Compiler {
594
618
  items: &'a [(NodeRef, bool)],
595
619
  prefixed: bool,
596
620
  cache: &mut HashMap<(&'a [(NodeRef, bool)], bool), NodeRef>,
597
- ) -> NodeRef {
621
+ ) -> Result<NodeRef> {
598
622
  // Cache to reduce number of nodes from O(n^2) to O(n)
599
623
  if let Some(node) = cache.get(&(items, prefixed)) {
600
- return *node;
624
+ return Ok(*node);
601
625
  }
602
626
  if items.is_empty() {
603
- return self.builder.string("");
627
+ return Ok(self.builder.string(""));
604
628
  }
605
- let comma = self.builder.string(&self.options.item_separator);
629
+ let comma = self.item_separator()?;
606
630
  let (item, required) = items[0];
607
631
  let rest = &items[1..];
608
632
 
609
633
  let node = match (prefixed, required) {
610
634
  (true, true) => {
611
635
  // If we know we have preceeding elements, we can safely just add a (',' + e)
612
- let rest_seq = self.ordered_sequence(rest, true, cache);
636
+ let rest_seq = self.ordered_sequence(rest, true, cache)?;
613
637
  self.builder.join(&[comma, item, rest_seq])
614
638
  }
615
639
  (true, false) => {
@@ -617,26 +641,26 @@ impl Compiler {
617
641
  // TODO optimization: if the rest is all optional, we can nest the rest in the optional
618
642
  let comma_item = self.builder.join(&[comma, item]);
619
643
  let optional_comma_item = self.builder.optional(comma_item);
620
- let rest_seq = self.ordered_sequence(rest, true, cache);
644
+ let rest_seq = self.ordered_sequence(rest, true, cache)?;
621
645
  self.builder.join(&[optional_comma_item, rest_seq])
622
646
  }
623
647
  (false, true) => {
624
648
  // No preceding elements, so we just add the element (no comma)
625
- let rest_seq = self.ordered_sequence(rest, true, cache);
649
+ let rest_seq = self.ordered_sequence(rest, true, cache)?;
626
650
  self.builder.join(&[item, rest_seq])
627
651
  }
628
652
  (false, false) => {
629
653
  // No preceding elements, but our element is optional. If we add the element, the remaining
630
654
  // will be prefixed, else they are not.
631
655
  // TODO: same nested optimization as above
632
- let prefixed_rest = self.ordered_sequence(rest, true, cache);
633
- let unprefixed_rest = self.ordered_sequence(rest, false, cache);
656
+ let prefixed_rest = self.ordered_sequence(rest, true, cache)?;
657
+ let unprefixed_rest = self.ordered_sequence(rest, false, cache)?;
634
658
  let opts = [self.builder.join(&[item, prefixed_rest]), unprefixed_rest];
635
659
  self.builder.select(&opts)
636
660
  }
637
661
  };
638
662
  cache.insert((items, prefixed), node);
639
- node
663
+ Ok(node)
640
664
  }
641
665
 
642
666
  fn bounded_sequence(
@@ -644,20 +668,20 @@ impl Compiler {
644
668
  item: NodeRef,
645
669
  min_elts: usize,
646
670
  max_elts: Option<usize>,
647
- ) -> NodeRef {
671
+ ) -> Result<NodeRef> {
648
672
  let min_elts = min_elts.saturating_sub(1);
649
673
  let max_elts = max_elts.map(|v| v.saturating_sub(1));
650
- let comma = self.builder.string(&self.options.item_separator);
674
+ let comma = self.item_separator()?;
651
675
  let item_comma = self.builder.join(&[item, comma]);
652
676
  let item_comma_rep = self.builder.repeat(item_comma, min_elts, max_elts);
653
- self.builder.join(&[item_comma_rep, item])
677
+ Ok(self.builder.join(&[item_comma_rep, item]))
654
678
  }
655
679
 
656
- fn sequence(&mut self, item: NodeRef) -> NodeRef {
657
- let comma = self.builder.string(&self.options.item_separator);
680
+ fn sequence(&mut self, item: NodeRef) -> Result<NodeRef> {
681
+ let comma = self.item_separator()?;
658
682
  let item_comma = self.builder.join(&[item, comma]);
659
683
  let item_comma_star = self.builder.zero_or_more(item_comma);
660
- self.builder.join(&[item_comma_star, item])
684
+ Ok(self.builder.join(&[item_comma_star, item]))
661
685
  }
662
686
 
663
687
  fn json_quote(&self, ast: RegexAst) -> RegexAst {
@@ -864,12 +888,12 @@ impl Compiler {
864
888
  if max_items.is_none() {
865
889
  if let Some(additional_item) = additional_item_grm {
866
890
  // Add an infinite tail of items
867
- optional_items.push(self.sequence(additional_item));
891
+ optional_items.push(self.sequence(additional_item)?);
868
892
  }
869
893
  }
870
894
 
871
895
  let mut grammars: Vec<NodeRef> = vec![self.builder.string("[")];
872
- let comma = self.builder.string(&self.options.item_separator);
896
+ let comma = self.item_separator()?;
873
897
 
874
898
  if !required_items.is_empty() {
875
899
  grammars.push(required_items[0]);
@@ -19,7 +19,7 @@ impl Decimal {
19
19
  // reduce to simplest form
20
20
  let mut coef = coef;
21
21
  let mut exp = exp;
22
- while exp > 0 && coef % 10 == 0 {
22
+ while exp > 0 && coef.is_multiple_of(10) {
23
23
  coef /= 10;
24
24
  exp -= 1;
25
25
  }
@@ -279,7 +279,7 @@ pub fn lex_lark(input: &str) -> Result<Vec<Lexeme>> {
279
279
  while idx <= input_bytes.len() {
280
280
  let mut b = b'\n';
281
281
  let res = if idx == input_bytes.len() {
282
- lexer.force_lexeme_end(state)
282
+ lexer.try_lexeme_end(state)
283
283
  } else {
284
284
  b = input_bytes[idx];
285
285
  lexer.advance(state, b, false)
@@ -120,11 +120,11 @@ impl Logger {
120
120
  std::mem::take(&mut self.buffer)
121
121
  }
122
122
 
123
- pub fn info_logger(&mut self) -> InfoLogger {
123
+ pub fn info_logger(&mut self) -> InfoLogger<'_> {
124
124
  InfoLogger { logger: self }
125
125
  }
126
126
 
127
- pub fn warning_logger(&mut self) -> WarningLogger {
127
+ pub fn warning_logger(&mut self) -> WarningLogger<'_> {
128
128
  WarningLogger { logger: self }
129
129
  }
130
130
  }
@@ -166,13 +166,12 @@ impl Matcher {
166
166
  self.with_inner(|inner| {
167
167
  for (idx, &t) in tokens.iter().enumerate() {
168
168
  if !inner.parser.validate_token(t)? {
169
- let _ = inner.parser.check_stop()?;
170
169
  return Ok(idx);
171
170
  }
172
171
  let bt = inner.parser.consume_token(t)?;
172
+ let _ = inner.parser.check_stop()?;
173
173
  ensure!(bt == 0, "unexpected backtracking");
174
174
  }
175
- let _ = inner.parser.check_stop()?;
176
175
  Ok(tokens.len())
177
176
  })
178
177
  }
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "llguidance"
3
- version = "1.1.2"
3
+ version = "1.3.0"
4
4
  description = "Bindings for the Low-level Guidance (llguidance) Rust library for use within Guidance"
5
5
  requires-python = ">=3.9"
6
6
  license = "MIT"