Skip to content

Commit 0efc731

Browse files
committed
Add crate benchmark by White-Oak plus makefile
Various cleanups
1 parent 93dde42 commit 0efc731

File tree

8 files changed

+319
-0
lines changed

8 files changed

+319
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.lock
2+
target/
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "parser"
3+
version = "0.1.0"
4+
authors = ["White-Oak <[email protected]>"]
5+
6+
[dependencies]
7+
8+
[dependencies.peruse]
9+
git = "https://github.com/DanSimon/peruse.git"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.PHONY: all
2+
3+
all:
4+
$(CARGO) rustc $(CARGO_OPTS) -- $(CARGO_RUSTC_OPTS)
5+
patches:
6+
@echo ''
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
2+
#[derive(Debug)]
3+
#[derive(Clone)]
4+
#[derive(PartialEq)]
5+
pub enum AddOp {
6+
Add,
7+
Subtract,
8+
Start,
9+
}
10+
11+
#[derive(Debug)]
12+
#[derive(Clone)]
13+
#[derive(PartialEq)]
14+
pub enum MultOp {
15+
Multiply,
16+
Divide,
17+
Modulo,
18+
Start,
19+
}
20+
21+
#[derive(Clone)]
22+
#[derive(Debug)]
23+
#[derive(PartialEq)]
24+
pub struct AddTerm(pub AddOp, pub Expr);
25+
26+
#[derive(Clone)]
27+
#[derive(Debug)]
28+
#[derive(PartialEq)]
29+
pub struct MultTerm(pub MultOp, pub Expr);
30+
31+
#[derive(Debug)]
32+
#[derive(Clone)]
33+
#[derive(PartialEq)]
34+
pub enum Expr {
35+
Variable(String),
36+
Num(i32),
37+
AddSub(Vec<AddTerm>), //a + b - c + d becomes [(+ a) (+ b) (- c) (+ d)]
38+
MultDiv(Vec<MultTerm>),
39+
}
40+
41+
42+
//for now this is it's own type and not a statement
43+
#[derive(Debug)]
44+
#[derive(Clone)]
45+
#[derive(PartialEq)]
46+
pub struct Block(pub Vec<Statement>);
47+
48+
#[derive(Debug)]
49+
#[derive(Clone)]
50+
#[derive(PartialEq)]
51+
pub enum Statement {
52+
Assign(String, Expr),
53+
Output(Expr),
54+
If(Expr, Comparator, Expr, Block, Option<Block>),
55+
While(Expr, Comparator, Expr, Block),
56+
Loop(Expr, Block),
57+
}
58+
59+
#[derive(Debug)]
60+
#[derive(Clone)]
61+
#[derive(Eq)]
62+
#[derive(PartialEq)]
63+
pub enum Comparator {
64+
CEq, // ==
65+
CGt, // >
66+
CLt, // <
67+
CNeq, // !=
68+
CGeq, // >=
69+
CLeq, // <=
70+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use grammar::*;
2+
3+
#[derive(Debug)]
4+
#[derive(Eq)]
5+
#[derive(PartialEq)]
6+
#[derive(Clone)]
7+
pub enum Token {
8+
Equals,
9+
Ident(String),
10+
Number(i32),
11+
PlusSign,
12+
MinusSign,
13+
MultSign,
14+
DivideSign,
15+
ModuloSign,
16+
OutputCmd,
17+
NewLine,
18+
OpenParen,
19+
CloseParen,
20+
OpenBrace,
21+
CloseBrace,
22+
IfKeyword,
23+
ElseKeyword,
24+
WhileKeyword,
25+
LoopKeyword,
26+
Cmp(Comparator),
27+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use peruse::string_parsers::*;
2+
use peruse::parsers::*;
3+
4+
use grammar_lexer::*;
5+
use grammar::*;
6+
use std::str::FromStr;
7+
8+
//type Lexer = SliceParser<I=str, O=Token>;
9+
10+
11+
pub fn token() -> Box<Parser<I=str, O=Vec<Token>>> {
12+
13+
fn lt(s: &str, t: Token) -> RegexLiteralParser<Token> {
14+
str_lit(&(String::from_str(r"^[ \t]*").unwrap() + s), t)
15+
}
16+
17+
let ident = capture(r"^[ \t]*([a-zA-Z]\w*)[ \t]*", |caps| Token::Ident(String::from_str(caps.at(1).unwrap()).unwrap()));
18+
19+
let number = capture(r"^[ \t]*(\d+)[ \t]*", |caps| Token::Number(FromStr::from_str(caps.at(1).unwrap()).unwrap()));
20+
21+
let lits = one_of(vec![
22+
lt("out", Token::OutputCmd),
23+
lt("if", Token::IfKeyword),
24+
lt("else", Token::ElseKeyword),
25+
lt("while", Token::WhileKeyword),
26+
lt("loop", Token::LoopKeyword),
27+
lt(r"\r?\n\s*", Token::NewLine),
28+
lt(r"\(\s*", Token::OpenParen),
29+
lt(r"\)", Token::CloseParen),
30+
lt(r"\}", Token::CloseBrace),
31+
lt("==", Token::Cmp(Comparator::CEq)),
32+
lt("!=", Token::Cmp(Comparator::CNeq)),
33+
lt(">=", Token::Cmp(Comparator::CGeq)),
34+
lt(r"\{\s*", Token::OpenBrace),
35+
lt("<=", Token::Cmp(Comparator::CLeq)),
36+
lt(">", Token::Cmp(Comparator::CGt)),
37+
lt("<", Token::Cmp(Comparator::CLt)),
38+
lt(r"\+", Token::PlusSign),
39+
lt("-", Token::MinusSign),
40+
lt("=", Token::Equals),
41+
lt(r"\*", Token::MultSign),
42+
lt("/", Token::DivideSign),
43+
lt(r"%", Token::ModuloSign)
44+
]);
45+
46+
let options = lits.or(number).or(ident).repeat();
47+
Box::new(options)
48+
49+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
extern crate peruse;
2+
3+
pub mod grammar;
4+
pub mod grammar_lexer;
5+
pub mod lexer;
6+
pub mod parser;
7+
8+
#[cfg(test)]
9+
mod test {
10+
#[test]
11+
fn it_works() {
12+
}
13+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
use grammar::*;
2+
use grammar_lexer::*;
3+
4+
use peruse::slice_parsers::*;
5+
use peruse::parsers::*;
6+
7+
pub fn program() -> Box<Parser<I=[Token], O=Block>> {
8+
9+
fn expression() -> Box<Parser<I=[Token], O=Expr>> {
10+
let simple_term = matcher(|token| match token {
11+
Token::Ident(name) => Some(Expr::Variable(name)),
12+
Token::Number(i) => Some(Expr::Num(i)),
13+
_ => None
14+
});
15+
16+
let paren_expr = || lit(Token::OpenParen).then_r(recursive(|| expression())).then_l(lit(Token::CloseParen));
17+
18+
let factor = paren_expr().or(simple_term);
19+
20+
let multop = matcher(|token| match token {
21+
Token::MultSign => Some(MultOp::Multiply),
22+
Token::DivideSign => Some(MultOp::Divide),
23+
Token::ModuloSign => Some(MultOp::Modulo),
24+
_ => None
25+
});
26+
27+
let addop = matcher(|token| match token {
28+
Token::PlusSign => Some(AddOp::Add),
29+
Token::MinusSign => Some(AddOp::Subtract),
30+
_ => None
31+
});
32+
33+
let mult = {
34+
let p = factor.clone().then(multop.then(factor).repeat()).map(|(first, seq)| {
35+
let mut ops = Vec::new();
36+
ops.push(MultTerm(MultOp::Start, first));
37+
for &(ref op, ref value) in seq.iter() {
38+
ops.push(MultTerm(op.clone(), value.clone())); //maybe box the value instead
39+
}
40+
if ops.len() == 1 {
41+
ops[0].1.clone()
42+
} else{
43+
Expr::MultDiv(ops)
44+
}
45+
});
46+
boxed(p)
47+
};
48+
49+
let plus = {
50+
let p = mult.clone().then(addop.then(mult).repeat()).map(|(first, seq)| {
51+
let mut ops = Vec::new();
52+
ops.push(AddTerm(AddOp::Start, first));
53+
for &(ref op, ref value) in seq.iter() {
54+
ops.push(AddTerm(op.clone(), value.clone()));
55+
}
56+
if ops.len() == 1 {
57+
ops[0].1.clone()
58+
} else{
59+
Expr::AddSub(ops)
60+
}
61+
});
62+
boxed(p)
63+
};
64+
65+
Box::new(plus)
66+
}
67+
68+
let assignment = {
69+
let target = matcher(|token| match token {
70+
Token::Ident(name) => Some(name),
71+
_ => None
72+
});
73+
boxed(target
74+
.then_l(lit(Token::Equals))
75+
.then(recursive(|| expression()))
76+
.map(|(target, expr)| Statement::Assign(target, expr)))
77+
};
78+
79+
let comparator = || matcher(|token| match token {
80+
Token::Cmp(cmp) => Some(cmp),
81+
_ => None
82+
});
83+
84+
fn code_block() -> Box<Parser<I=[Token], O=Block>> {
85+
Box::new(lit(Token::OpenBrace)
86+
.then_r(recursive(|| program()))
87+
.then_l(lit(Token::CloseBrace)))
88+
}
89+
90+
fn if_stmt() -> Box<Parser<I=[Token], O=Statement>> {
91+
92+
let comparator = || matcher(|token| match token {
93+
Token::Cmp(cmp) => Some(cmp),
94+
_ => None
95+
});
96+
97+
98+
let else_block = lit(Token::ElseKeyword)
99+
.then_r(
100+
recursive(if_stmt).map(|i| Block(vec![i]))
101+
.or(boxed(recursive(|| code_block())))
102+
);
103+
104+
let p = lit(Token::IfKeyword)
105+
.then_r(recursive(|| expression()))
106+
.then(comparator())
107+
.then(recursive(expression))
108+
.then_l(lit(Token::OpenBrace))
109+
.then(recursive(program))
110+
.then_l(lit(Token::CloseBrace))
111+
.then(opt(else_block))
112+
.map(|((((l, cmp), r), block), else_opt)| Statement::If(l, cmp, r, block, else_opt));
113+
114+
Box::new(p)
115+
};
116+
117+
let while_stmt = {
118+
let p = lit(Token::WhileKeyword)
119+
.then_r(recursive(expression))
120+
.then(comparator())
121+
.then(recursive(expression))
122+
.then_l(lit(Token::OpenBrace))
123+
.then(recursive(program))
124+
.then_l(lit(Token::CloseBrace))
125+
.map(|(((l, cmp), r), block)| Statement::While(l, cmp, r, block));
126+
boxed(p)
127+
};
128+
129+
let loop_stmt = {
130+
let p = lit(Token::LoopKeyword)
131+
.then_r(recursive(expression))
132+
.then_l(lit(Token::OpenBrace))
133+
.then(recursive(program))
134+
.then_l(lit(Token::CloseBrace))
135+
.map(|(l, block)| Statement::Loop(l, block));
136+
boxed(p)
137+
};
138+
let output = boxed(lit(Token::OutputCmd).then_r(recursive(|| expression())).map(|e| Statement::Output(e)));
139+
140+
let statements = one_of(vec![assignment, output, boxed(recursive(|| if_stmt())), while_stmt, loop_stmt]).then_l(lit(Token::NewLine)).repeat();
141+
142+
Box::new(statements.map(|v| Block(v)))
143+
}

0 commit comments

Comments
 (0)