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.
- llguidance-1.3.0/.github/workflows/code-coverage.yml +126 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/.github/workflows/rust.yml +1 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/CHANGELOG.md +14 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/Cargo.lock +8 -8
- {llguidance-1.1.2 → llguidance-1.3.0}/Cargo.toml +3 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/PKG-INFO +1 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/docs/json_schema.md +22 -2
- {llguidance-1.1.2 → llguidance-1.3.0}/docs/syntax.md +1 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/Cargo.toml +2 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/api.rs +10 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/grammar.rs +1 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/parser.rs +5 -6
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/perf.rs +1 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/regexvec.rs +1 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/grammar_builder.rs +3 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/compiler.rs +49 -25
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/numeric.rs +1 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lark/lexer.rs +1 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/logging.rs +2 -2
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/matcher.rs +1 -2
- {llguidance-1.1.2 → llguidance-1.3.0}/pyproject.toml +1 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/_lib.pyi +34 -3
- {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/numpy.py +14 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/torch.py +11 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/torch_tests/test_matcher.py +149 -2
- {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/Cargo.toml +2 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/src/llinterpreter.rs +2 -2
- {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/src/llmatcher.rs +113 -4
- {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/src/py.rs +3 -11
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/common_lark_utils/mod.rs +7 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_json_primitives.rs +13 -7
- llguidance-1.3.0/sample_parser/tests/test_json_schema_combinations.rs +372 -0
- llguidance-1.3.0/sample_parser/tests/test_json_string_format.rs +141 -0
- llguidance-1.3.0/sample_parser/tests/test_json_x_guidance.rs +81 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_lark.rs +16 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_ll.rs +9 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_raw_parser.rs +26 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/Cargo.toml +2 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/src/bytes.rs +1 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/src/svob.rs +1 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/src/toktree.rs +1 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_hf_downloader/Cargo.toml +2 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_hf_tokenizers/Cargo.toml +2 -1
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_tiktoken/Cargo.toml +2 -1
- llguidance-1.1.2/.github/workflows/code-coverage.yml +0 -62
- llguidance-1.1.2/sample_parser/tests/test_json_schema_combinations.rs +0 -154
- {llguidance-1.1.2 → llguidance-1.3.0}/.github/workflows/wheels.yml +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/.gitignore +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/CODE_OF_CONDUCT.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/LICENSE +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/README.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/SECURITY.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/SUPPORT.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/c_sample/Makefile +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/c_sample/README.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/c_sample/c_sample.cpp +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/docs/de_recursing.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/docs/fast_forward.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/docs/mask_plot.png +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/docs/optimizations.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/docs/parametric.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/docs/special_tokens.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/docs/toktrie.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/Cargo.toml +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/expected_maskbench.json +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/jstats.sh +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/scripts/split-stats.sh +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/scripts/split_plot.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/src/json_stats.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/src/lib.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/json_stats/src/stats.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/LICENSE +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/README.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/build.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/cbindgen.toml +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/grammars/character.json +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/grammars/json.json +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/llguidance.h +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/constraint.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/from_guidance.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/lexer.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/lexerspec.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/mod.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/earley/slicer.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/factory.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/ffi.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/ffi_par.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/hashcons.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/README.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/context_ref.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/context_simple/context.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/context_simple/draft.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/context_simple/mod.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/formats.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/mod.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/schema.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json/shared_context.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/json_validation.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lark/README.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lark/ast.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lark/common.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lark/compiler.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lark/mod.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lark/parser.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/lib.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/output.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/panic_utils.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/regex_rewrite.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/stop_controller.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/substring.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/tokenizer_json.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/parser/src/tokenparser.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/plan.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/__init__.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/_grammar_from.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/_struct_tag.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/_tokenizer.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/_util.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/cli.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/gbnf_to_lark.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/hf.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/llamacpp.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/mlx.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/py.typed +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/llguidance/tiktoken.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/mypy.ini +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/torch_tests/__init__.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/torch_tests/test_bitmask.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/torch_tests/test_hf.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/torch_tests/test_llamacpp.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python/torch_tests/test_tiktoken.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/src/lib.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/src/llamatokenizer.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/src/parserlimits.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/python_ext/src/pyjson.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/Cargo.toml +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/README.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/cli.sh +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/blog.sample.json +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/blog.schema.json +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/blog.schema.ll.json +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/README.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/arithmetic.gbnf +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/c.gbnf +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/chess.gbnf +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/english.gbnf +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/japanese.gbnf +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/json.gbnf +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/json_arr.gbnf +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/list.gbnf +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/from-llama.cpp/vllm-sql.gbnf +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/lark.lark +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/rfc.lark +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/rfc.xml +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/data/ulysses.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/gtest.sh +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/lark.sh +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/run.sh +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/src/lib.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/src/minimal.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/src/sample_parser.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_json_arrays.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_json_enum_const.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_json_objects.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/sample_parser/tests/test_stop.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/annotate_asm.js +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/bump.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/cbindgen.sh +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/checklinks.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/checklinks.sh +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/ci-publish.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/disasm.sh +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/gbnf_to_lark.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/gen-testcase.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/git-version.sh +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/install-deps.sh +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/jsonschema-stats.js +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/remote-guidance-test.sh +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/rust-size.js +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/rust_size.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/test-guidance.sh +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/tokenizer_test.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/scripts/update-git.py +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/LICENSE +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/README.md +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/src/lib.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/src/recognizer.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/src/rng.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/src/tokenv.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie/tests/test_svob.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_hf_downloader/LICENSE +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_hf_downloader/src/lib.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_hf_tokenizers/LICENSE +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_hf_tokenizers/src/lib.rs +0 -0
- {llguidance-1.1.2 → llguidance-1.3.0}/toktrie_tiktoken/LICENSE +0 -0
- {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
|
+
|
|
@@ -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.
|
|
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.
|
|
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.
|
|
2179
|
+
version = "0.4.11"
|
|
2180
2180
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2181
|
-
checksum = "
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
2515
|
+
version = "1.3.0"
|
|
2516
2516
|
dependencies = [
|
|
2517
2517
|
"anyhow",
|
|
2518
2518
|
"log",
|
|
@@ -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#
|
|
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.
|
|
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()
|
|
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()
|
|
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
|
|
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)
|
|
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()
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
896
|
+
let comma = self.item_separator()?;
|
|
873
897
|
|
|
874
898
|
if !required_items.is_empty() {
|
|
875
899
|
grammars.push(required_items[0]);
|
|
@@ -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.
|
|
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
|
}
|