Skip to content

Commit

Permalink
split up lr1 constraint into exact and regular constraint
Browse files Browse the repository at this point in the history
  • Loading branch information
bastiscode committed Mar 7, 2024
1 parent 5938293 commit b9d23ff
Show file tree
Hide file tree
Showing 6 changed files with 646 additions and 224 deletions.
14 changes: 7 additions & 7 deletions src/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
use pyo3::types::{PyDict, PyList};
use text_utils_grammar::{
Constraint, LR1GrammarConstraint, LR1GrammarParser, LR1NextState, LR1Parse, LR1State,
Constraint, ExactLR1GrammarConstraint, LR1GrammarParser, LR1NextState, LR1Parse, LR1State,
RegularExpressionConstraint, RegularExpressionState,
};

Expand Down Expand Up @@ -114,19 +114,19 @@ impl RegexConstraint {
}

#[pyclass]
struct LR1Constraint {
inner: Arc<LR1GrammarConstraint>,
struct ExactLR1Constraint {
inner: Arc<ExactLR1GrammarConstraint>,
state: LR1State,
indices: Vec<usize>,
is_match: bool,
next_states: Vec<LR1NextState>,
}

#[pymethods]
impl LR1Constraint {
impl ExactLR1Constraint {
#[new]
fn new(grammar: &str, lexer: &str, continuations: Vec<Vec<u8>>) -> anyhow::Result<Self> {
let inner = LR1GrammarConstraint::new(grammar, lexer, continuations)
let inner = ExactLR1GrammarConstraint::new(grammar, lexer, continuations)
.map_err(|e| anyhow!("failed to create LR(1) grammar constraint: {}", e))?;
let state = inner.get_start_state();
let (indices, next_states) = inner.get_valid_continuations_with_state(&state);
Expand All @@ -146,7 +146,7 @@ impl LR1Constraint {
lexer_path: &str,
continuations: Vec<Vec<u8>>,
) -> anyhow::Result<Self> {
let inner = LR1GrammarConstraint::from_files(grammar_path, lexer_path, continuations)
let inner = ExactLR1GrammarConstraint::from_files(grammar_path, lexer_path, continuations)
.map_err(|e| {
anyhow!(
"failed to create LR(1) grammar constraint from files {} and {}: {}",
Expand Down Expand Up @@ -350,7 +350,7 @@ fn parse_into_py(
pub(super) fn add_submodule(py: Python, parent_module: &PyModule) -> PyResult<()> {
let m = PyModule::new(py, "grammar")?;
m.add_class::<RegexConstraint>()?;
m.add_class::<LR1Constraint>()?;
m.add_class::<ExactLR1Constraint>()?;
m.add_class::<LR1Parser>()?;
parent_module.add_submodule(m)?;

Expand Down
35 changes: 27 additions & 8 deletions text-utils-grammar/benches/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ use std::fs::{self, read_to_string};
use std::path::PathBuf;

use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
use text_utils_grammar::lr1::LR1GrammarConstraint;
use text_utils_grammar::{
utils::optimized_prefix_order, Constraint, LR1GrammarConstraint, LR1GrammarParser,
utils::optimized_prefix_order, Constraint, ExactLR1GrammarConstraint, LR1GrammarParser,
RegularExpressionConstraint,
};

Expand Down Expand Up @@ -117,30 +118,48 @@ fn bench_lr1_constraint(c: &mut Criterion) {
.to_str()
.unwrap()
.to_string();
let lr1_constraint = LR1GrammarConstraint::from_files(grammar, tokens, conts.clone()).unwrap();
let state = lr1_constraint.get_start_state();
let exact_lr_constraint =
ExactLR1GrammarConstraint::from_files(&grammar, &tokens, conts.clone()).unwrap();
let lr_constraint = LR1GrammarConstraint::from_files(grammar, tokens, conts.clone()).unwrap();
let state = exact_lr_constraint.get_start_state();
c.bench_function("exact_lr1_json_empty_get_valid_continuations", |b| {
b.iter(|| exact_lr_constraint.get_valid_continuations_with_state(&state))
});
let state = lr_constraint.get_start_state();
c.bench_function("lr1_json_empty_get_valid_continuations", |b| {
b.iter(|| lr1_constraint.get_valid_continuations_with_state(&state))
b.iter(|| lr_constraint.get_valid_continuations_with_state(&state))
});
let input = read_to_string(
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("grammars/json/examples/numbers.json"),
)
.unwrap();
let state = lr1_constraint
let state = exact_lr_constraint
.get_state(&input.as_bytes()[..input.len() / 2])
.unwrap();
c.bench_function("exact_lr1_json_numbers_get_valid_continuations", |b| {
b.iter(|| exact_lr_constraint.get_valid_continuations_with_state(&state))
});
let state = lr_constraint
.get_state(&input.as_bytes()[..input.len() / 2])
.unwrap();
c.bench_function("lr1_json_numbers_get_valid_continuations", |b| {
b.iter(|| lr1_constraint.get_valid_continuations_with_state(&state))
b.iter(|| lr_constraint.get_valid_continuations_with_state(&state))
});
let input = read_to_string(
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("grammars/json/examples/example1.json"),
)
.unwrap();
let state = lr1_constraint
let state = exact_lr_constraint
.get_state(&input.as_bytes()[..input.len() / 2])
.unwrap();
c.bench_function("exact_lr1_json_example1_get_valid_continuations", |b| {
b.iter(|| exact_lr_constraint.get_valid_continuations_with_state(&state))
});
let state = lr_constraint
.get_state(&input.as_bytes()[..input.len() / 2])
.unwrap();
c.bench_function("lr1_json_example1_get_valid_continuations", |b| {
b.iter(|| lr1_constraint.get_valid_continuations_with_state(&state))
b.iter(|| lr_constraint.get_valid_continuations_with_state(&state))
});
}

Expand Down
2 changes: 1 addition & 1 deletion text-utils-grammar/grammars/calc/examples/calc.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
(1+2)*3
()
5 changes: 4 additions & 1 deletion text-utils-grammar/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ pub mod utils;
pub use re::RegularExpressionConstraint;
pub use regex_automata::util::primitives::StateID as RegularExpressionState;

pub use lr1::{LR1GrammarConstraint, LR1GrammarParser, LR1NextState, LR1Parse, LR1State};
pub use lr1::{
ExactLR1GrammarConstraint, LR1GrammarConstraint, LR1GrammarParser, LR1NextState, LR1Parse,
LR1State,
};

pub trait Constraint {
type State;
Expand Down
Loading

0 comments on commit b9d23ff

Please sign in to comment.