Skip to content
This repository was archived by the owner on Dec 27, 2022. It is now read-only.

[RFC?] Weighted Choices #4

@felix91gr

Description

@felix91gr

I propose a "Weighted Choices" helper function. Sometimes, when one has a highly-recursive grammar, a naïve approach to generating strings would turn into Stack Overflow panics instead of the desired behavior. That's because when we write a grammar, we're implicitly favoring shorter strings in our mind. One could think about it this way: "certainly, a function comprised of 20 nested scopes and 1000 lines of code should never exist".

And that statement is true, but implicit in our reasoning. I propose a helper function for giving different priorities to different choices in a disyuntive (choice!) production. It would be used like this:

    let term = choice_weighted_multi(
        recursive_rules.clone(),
        vec![
            ("paren_expr".to_string(), 1),
            ("ids".to_string(), 100),
            ("ints".to_string(), 100),
            ]
        );

The name of the generators are on the left hand side of the tuples, and their "weights" on the right side.

This is how I've implemented the function, if you know of a better way please let me know:

type NameAndWeight = (String, u8);

fn choice_weighted_multi(rule_index: Arc<RwLock<Rules>>, names_and_weights: Vec<NameAndWeight> ) -> impl Generator
{
    let mut rules_in_generator: Vec<Box<Generator>> = Vec::new();

    for (name, weight) in names_and_weights.iter() {
        
        for _i in 0..*weight {
            rules_in_generator.push(
                Box::new(rule(name.clone(), rule_index.clone()))
            );
        }
    }

    choice(rules_in_generator)
}

Thanks to this approach, I'm now fuzzing my parser of Tiny-C. Before, it would run into stackoverflow 8 times out of 10. Now, I can run 5 million different generation steps without a problem :D

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions