utterance 0.1.1

A parser library for creating readable, natural-language-inspired domain-specific languages.
Documentation
use utterance::lexer::Lexer;
use utterance::lexer::Punctuation;
use utterance::lexer::SpecialChar;
use utterance::lexer::Symbol;
use utterance::parser::Parser;
use utterance::parser::expectation::{NumberKind, StatementKind};
use utterance::parser::graph::GraphBuilder;
use utterance::parser::tree::ParseTree;
use utterance::parser::tree::ParseTreeFactory;
use utterance::parser::tree::noop_fn;

#[derive(Clone, Default, Debug)]
struct NoopContext;

#[test]
pub(crate) fn cyclic_base_tree() {
    let mut graph = GraphBuilder::<NoopContext>::new();
    let tree_factory = ParseTreeFactory::<NoopContext>::new();

    let end_tree = ParseTree::new(
        tree_factory.clone(),
        StatementKind::NewLineOrEnd,
        vec![],
        noop_fn,
    );
    let right_bracket_tree = ParseTree::new(
        tree_factory.clone(),
        StatementKind::Symbol(Symbol::SpecialChar(SpecialChar::RightBracket)),
        vec![end_tree],
        noop_fn,
    );

    let right_bracket_node = graph.add_tree(&right_bracket_tree);
    let number_node = graph.add_node(StatementKind::Number(NumberKind::Float), noop_fn);
    let comma_node = graph.add_node(
        StatementKind::Symbol(Symbol::Punctuation(Punctuation::Comma)),
        noop_fn,
    );

    graph.add_child(comma_node, number_node);
    graph.add_child(number_node, comma_node);
    graph.add_child(number_node, right_bracket_node);

    let repetition_tree = graph.build_from(tree_factory.clone(), number_node);
    let mut tree = ParseTree::new(
        tree_factory.clone(),
        StatementKind::Symbol(Symbol::SpecialChar(SpecialChar::LeftBracket)),
        vec![right_bracket_tree],
        noop_fn,
    );

    tree.push_child_ref(repetition_tree);

    let success = [
        "[]",
        "[1]",
        "[-1.55]",
        "[1, 1.0, -5]",
        "[1, 2, 3, 4, 5]",
        "[1, 1, 1, 1, 1, 1]",
    ];
    let deep = format!(
        "[{}]",
        (0..10000).map(|_| "1").collect::<Vec<_>>().join(", ")
    );
    let failures = [
        "[", "]", "15]", "[15, ]", "[15],", "[,15]", "[1,,2]", "[1 2]",
    ];

    let lexer = Lexer::<1>::new("");
    let mut parser = Parser::<NoopContext, 1, 1>::new(lexer, tree);

    for input in success {
        parser.update_input(input);
        let res = parser.parse();

        assert!(
            res.is_ok(),
            "expected success for {:?}, got: {:?}",
            input,
            res.unwrap_err()
        );
    }

    for input in failures {
        parser.update_input(input);
        let res = parser.parse();

        assert!(
            res.is_err(),
            "expected failure for {:?}, but parsing succeeded",
            input
        );
    }

    parser.update_input(&deep);
    let res = parser.parse();

    assert!(
        res.is_ok(),
        "expected success for deep cyclic parse, got: {:?}",
        res.unwrap_err()
    );
}