diff --git a/collector/benchmarks/issue-31157-compilation-time-ram-regression/.gitignore b/collector/benchmarks/issue-31157-compilation-time-ram-regression/.gitignore new file mode 100644 index 000000000..7b273b13f --- /dev/null +++ b/collector/benchmarks/issue-31157-compilation-time-ram-regression/.gitignore @@ -0,0 +1,2 @@ +*.lock +target/ diff --git a/collector/benchmarks/issue-31157-compilation-time-ram-regression/Cargo.toml b/collector/benchmarks/issue-31157-compilation-time-ram-regression/Cargo.toml new file mode 100644 index 000000000..47b8c629f --- /dev/null +++ b/collector/benchmarks/issue-31157-compilation-time-ram-regression/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "parser" +version = "0.1.0" +authors = ["White-Oak "] + +[dependencies] + +[dependencies.peruse] +git = "https://github.com/DanSimon/peruse.git" diff --git a/collector/benchmarks/issue-31157-compilation-time-ram-regression/makefile b/collector/benchmarks/issue-31157-compilation-time-ram-regression/makefile new file mode 100644 index 000000000..706431386 --- /dev/null +++ b/collector/benchmarks/issue-31157-compilation-time-ram-regression/makefile @@ -0,0 +1,6 @@ +.PHONY: all + +all: + $(CARGO) rustc $(CARGO_OPTS) -- $(CARGO_RUSTC_OPTS) +patches: + @echo '' diff --git a/collector/benchmarks/issue-31157-compilation-time-ram-regression/src/grammar.rs b/collector/benchmarks/issue-31157-compilation-time-ram-regression/src/grammar.rs new file mode 100644 index 000000000..7c56f81a7 --- /dev/null +++ b/collector/benchmarks/issue-31157-compilation-time-ram-regression/src/grammar.rs @@ -0,0 +1,70 @@ + +#[derive(Debug)] +#[derive(Clone)] +#[derive(PartialEq)] +pub enum AddOp { + Add, + Subtract, + Start, +} + +#[derive(Debug)] +#[derive(Clone)] +#[derive(PartialEq)] +pub enum MultOp { + Multiply, + Divide, + Modulo, + Start, +} + +#[derive(Clone)] +#[derive(Debug)] +#[derive(PartialEq)] +pub struct AddTerm(pub AddOp, pub Expr); + +#[derive(Clone)] +#[derive(Debug)] +#[derive(PartialEq)] +pub struct MultTerm(pub MultOp, pub Expr); + +#[derive(Debug)] +#[derive(Clone)] +#[derive(PartialEq)] +pub enum Expr { + Variable(String), + Num(i32), + AddSub(Vec), //a + b - c + d becomes [(+ a) (+ b) (- c) (+ d)] + MultDiv(Vec), +} + + +//for now this is it's own type and not a statement +#[derive(Debug)] +#[derive(Clone)] +#[derive(PartialEq)] +pub struct Block(pub Vec); + +#[derive(Debug)] +#[derive(Clone)] +#[derive(PartialEq)] +pub enum Statement { + Assign(String, Expr), + Output(Expr), + If(Expr, Comparator, Expr, Block, Option), + While(Expr, Comparator, Expr, Block), + Loop(Expr, Block), +} + +#[derive(Debug)] +#[derive(Clone)] +#[derive(Eq)] +#[derive(PartialEq)] +pub enum Comparator { + CEq, // == + CGt, // > + CLt, // < + CNeq, // != + CGeq, // >= + CLeq, // <= +} diff --git a/collector/benchmarks/issue-31157-compilation-time-ram-regression/src/grammar_lexer.rs b/collector/benchmarks/issue-31157-compilation-time-ram-regression/src/grammar_lexer.rs new file mode 100644 index 000000000..6a9061761 --- /dev/null +++ b/collector/benchmarks/issue-31157-compilation-time-ram-regression/src/grammar_lexer.rs @@ -0,0 +1,27 @@ +use grammar::*; + +#[derive(Debug)] +#[derive(Eq)] +#[derive(PartialEq)] +#[derive(Clone)] +pub enum Token { + Equals, + Ident(String), + Number(i32), + PlusSign, + MinusSign, + MultSign, + DivideSign, + ModuloSign, + OutputCmd, + NewLine, + OpenParen, + CloseParen, + OpenBrace, + CloseBrace, + IfKeyword, + ElseKeyword, + WhileKeyword, + LoopKeyword, + Cmp(Comparator), +} diff --git a/collector/benchmarks/issue-31157-compilation-time-ram-regression/src/lexer.rs b/collector/benchmarks/issue-31157-compilation-time-ram-regression/src/lexer.rs new file mode 100644 index 000000000..ef9425396 --- /dev/null +++ b/collector/benchmarks/issue-31157-compilation-time-ram-regression/src/lexer.rs @@ -0,0 +1,49 @@ +use peruse::string_parsers::*; +use peruse::parsers::*; + +use grammar_lexer::*; +use grammar::*; +use std::str::FromStr; + +//type Lexer = SliceParser; + + +pub fn token() -> Box>> { + + fn lt(s: &str, t: Token) -> RegexLiteralParser { + str_lit(&(String::from_str(r"^[ \t]*").unwrap() + s), t) + } + + let ident = capture(r"^[ \t]*([a-zA-Z]\w*)[ \t]*", |caps| Token::Ident(String::from_str(caps.at(1).unwrap()).unwrap())); + + let number = capture(r"^[ \t]*(\d+)[ \t]*", |caps| Token::Number(FromStr::from_str(caps.at(1).unwrap()).unwrap())); + + let lits = one_of(vec![ + lt("out", Token::OutputCmd), + lt("if", Token::IfKeyword), + lt("else", Token::ElseKeyword), + lt("while", Token::WhileKeyword), + lt("loop", Token::LoopKeyword), + lt(r"\r?\n\s*", Token::NewLine), + lt(r"\(\s*", Token::OpenParen), + lt(r"\)", Token::CloseParen), + lt(r"\}", Token::CloseBrace), + lt("==", Token::Cmp(Comparator::CEq)), + lt("!=", Token::Cmp(Comparator::CNeq)), + lt(">=", Token::Cmp(Comparator::CGeq)), + lt(r"\{\s*", Token::OpenBrace), + lt("<=", Token::Cmp(Comparator::CLeq)), + lt(">", Token::Cmp(Comparator::CGt)), + lt("<", Token::Cmp(Comparator::CLt)), + lt(r"\+", Token::PlusSign), + lt("-", Token::MinusSign), + lt("=", Token::Equals), + lt(r"\*", Token::MultSign), + lt("/", Token::DivideSign), + lt(r"%", Token::ModuloSign) + ]); + + let options = lits.or(number).or(ident).repeat(); + Box::new(options) + +} diff --git a/collector/benchmarks/issue-31157-compilation-time-ram-regression/src/lib.rs b/collector/benchmarks/issue-31157-compilation-time-ram-regression/src/lib.rs new file mode 100644 index 000000000..e69b44328 --- /dev/null +++ b/collector/benchmarks/issue-31157-compilation-time-ram-regression/src/lib.rs @@ -0,0 +1,13 @@ +extern crate peruse; + +pub mod grammar; +pub mod grammar_lexer; +pub mod lexer; +pub mod parser; + +#[cfg(test)] +mod test { + #[test] + fn it_works() { + } +} diff --git a/collector/benchmarks/issue-31157-compilation-time-ram-regression/src/parser.rs b/collector/benchmarks/issue-31157-compilation-time-ram-regression/src/parser.rs new file mode 100644 index 000000000..f51acc048 --- /dev/null +++ b/collector/benchmarks/issue-31157-compilation-time-ram-regression/src/parser.rs @@ -0,0 +1,143 @@ +use grammar::*; +use grammar_lexer::*; + +use peruse::slice_parsers::*; +use peruse::parsers::*; + +pub fn program() -> Box> { + + fn expression() -> Box> { + let simple_term = matcher(|token| match token { + Token::Ident(name) => Some(Expr::Variable(name)), + Token::Number(i) => Some(Expr::Num(i)), + _ => None + }); + + let paren_expr = || lit(Token::OpenParen).then_r(recursive(|| expression())).then_l(lit(Token::CloseParen)); + + let factor = paren_expr().or(simple_term); + + let multop = matcher(|token| match token { + Token::MultSign => Some(MultOp::Multiply), + Token::DivideSign => Some(MultOp::Divide), + Token::ModuloSign => Some(MultOp::Modulo), + _ => None + }); + + let addop = matcher(|token| match token { + Token::PlusSign => Some(AddOp::Add), + Token::MinusSign => Some(AddOp::Subtract), + _ => None + }); + + let mult = { + let p = factor.clone().then(multop.then(factor).repeat()).map(|(first, seq)| { + let mut ops = Vec::new(); + ops.push(MultTerm(MultOp::Start, first)); + for &(ref op, ref value) in seq.iter() { + ops.push(MultTerm(op.clone(), value.clone())); //maybe box the value instead + } + if ops.len() == 1 { + ops[0].1.clone() + } else{ + Expr::MultDiv(ops) + } + }); + boxed(p) + }; + + let plus = { + let p = mult.clone().then(addop.then(mult).repeat()).map(|(first, seq)| { + let mut ops = Vec::new(); + ops.push(AddTerm(AddOp::Start, first)); + for &(ref op, ref value) in seq.iter() { + ops.push(AddTerm(op.clone(), value.clone())); + } + if ops.len() == 1 { + ops[0].1.clone() + } else{ + Expr::AddSub(ops) + } + }); + boxed(p) + }; + + Box::new(plus) + } + + let assignment = { + let target = matcher(|token| match token { + Token::Ident(name) => Some(name), + _ => None + }); + boxed(target + .then_l(lit(Token::Equals)) + .then(recursive(|| expression())) + .map(|(target, expr)| Statement::Assign(target, expr))) + }; + + let comparator = || matcher(|token| match token { + Token::Cmp(cmp) => Some(cmp), + _ => None + }); + + fn code_block() -> Box> { + Box::new(lit(Token::OpenBrace) + .then_r(recursive(|| program())) + .then_l(lit(Token::CloseBrace))) + } + + fn if_stmt() -> Box> { + + let comparator = || matcher(|token| match token { + Token::Cmp(cmp) => Some(cmp), + _ => None + }); + + + let else_block = lit(Token::ElseKeyword) + .then_r( + recursive(if_stmt).map(|i| Block(vec![i])) + .or(boxed(recursive(|| code_block()))) + ); + + let p = lit(Token::IfKeyword) + .then_r(recursive(|| expression())) + .then(comparator()) + .then(recursive(expression)) + .then_l(lit(Token::OpenBrace)) + .then(recursive(program)) + .then_l(lit(Token::CloseBrace)) + .then(opt(else_block)) + .map(|((((l, cmp), r), block), else_opt)| Statement::If(l, cmp, r, block, else_opt)); + + Box::new(p) + }; + + let while_stmt = { + let p = lit(Token::WhileKeyword) + .then_r(recursive(expression)) + .then(comparator()) + .then(recursive(expression)) + .then_l(lit(Token::OpenBrace)) + .then(recursive(program)) + .then_l(lit(Token::CloseBrace)) + .map(|(((l, cmp), r), block)| Statement::While(l, cmp, r, block)); + boxed(p) + }; + + let loop_stmt = { + let p = lit(Token::LoopKeyword) + .then_r(recursive(expression)) + .then_l(lit(Token::OpenBrace)) + .then(recursive(program)) + .then_l(lit(Token::CloseBrace)) + .map(|(l, block)| Statement::Loop(l, block)); + boxed(p) + }; + let output = boxed(lit(Token::OutputCmd).then_r(recursive(|| expression())).map(|e| Statement::Output(e))); + + let statements = one_of(vec![assignment, output, boxed(recursive(|| if_stmt())), while_stmt, loop_stmt]).then_l(lit(Token::NewLine)).repeat(); + + Box::new(statements.map(|v| Block(v))) + }