Added implicative multiplication, like 2pi
This commit is contained in:
parent
73823cbbce
commit
6ac025850d
11
src/main.rs
11
src/main.rs
@ -9,8 +9,6 @@ pub enum Operator {
|
|||||||
Divide,
|
Divide,
|
||||||
Modulo,
|
Modulo,
|
||||||
Caret,
|
Caret,
|
||||||
// Percent,
|
|
||||||
// Factorial,
|
|
||||||
LeftParen, // lexer only
|
LeftParen, // lexer only
|
||||||
RightParen, // lexer only
|
RightParen, // lexer only
|
||||||
}
|
}
|
||||||
@ -84,20 +82,22 @@ fn main() {
|
|||||||
match lexer::lex(s) {
|
match lexer::lex(s) {
|
||||||
Ok(tokens) => {
|
Ok(tokens) => {
|
||||||
let lex_time = Instant::now().duration_since(lex_start).as_nanos() as f32;
|
let lex_time = Instant::now().duration_since(lex_start).as_nanos() as f32;
|
||||||
// println!("Lexed TokenVector: {:?}", tokens);
|
|
||||||
|
|
||||||
let parse_start = Instant::now();
|
let parse_start = Instant::now();
|
||||||
match parser::parse(&tokens) {
|
match parser::parse(&tokens) {
|
||||||
Ok(ast) => {
|
Ok(ast) => {
|
||||||
let parse_time = Instant::now().duration_since(parse_start).as_nanos() as f32;
|
let parse_time = Instant::now().duration_since(parse_start).as_nanos() as f32;
|
||||||
// println!("Parsed AstNode: {:#?}", ast);
|
|
||||||
|
|
||||||
let eval_start = Instant::now();
|
let eval_start = Instant::now();
|
||||||
match evaluator::evaluate(&ast) {
|
match evaluator::evaluate(&ast) {
|
||||||
Ok(answer) => {
|
Ok(answer) => {
|
||||||
let eval_time = Instant::now().duration_since(eval_start).as_nanos() as f32;
|
let eval_time = Instant::now().duration_since(eval_start).as_nanos() as f32;
|
||||||
println!("Evaluated answer: {:#?}", answer);
|
|
||||||
|
|
||||||
|
println!("Lexed TokenVector: {:?}", tokens);
|
||||||
|
println!("Parsed AstNode: {:#?}", ast);
|
||||||
|
|
||||||
|
println!("Evaluated value: {} {:?}", answer.value, answer.unit);
|
||||||
|
|
||||||
println!("\u{23f1} {:.3}ms lexing", lex_time/1000.0/1000.0);
|
println!("\u{23f1} {:.3}ms lexing", lex_time/1000.0/1000.0);
|
||||||
println!("\u{23f1} {:.3}ms parsing", parse_time/1000.0/1000.0);
|
println!("\u{23f1} {:.3}ms parsing", parse_time/1000.0/1000.0);
|
||||||
println!("\u{23f1} {:.3}ms evaluation", eval_time/1000.0/1000.0);
|
println!("\u{23f1} {:.3}ms evaluation", eval_time/1000.0/1000.0);
|
||||||
@ -108,6 +108,7 @@ fn main() {
|
|||||||
},
|
},
|
||||||
Err(e) => println!("Parsing error: {}", e),
|
Err(e) => println!("Parsing error: {}", e),
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
Err(e) => println!("Lexing error: {}", e),
|
Err(e) => println!("Lexing error: {}", e),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -77,6 +77,7 @@ fn parse_level_2(tokens: &TokenVector, pos: usize) -> Result<(AstNode, usize), S
|
|||||||
// level 3 precedence: *, /, modulo
|
// level 3 precedence: *, /, modulo
|
||||||
fn parse_level_3(tokens: &TokenVector, pos: usize) -> Result<(AstNode, usize), String> {
|
fn parse_level_3(tokens: &TokenVector, pos: usize) -> Result<(AstNode, usize), String> {
|
||||||
let (mut node, mut pos) = parse_level_4(tokens, pos)?;
|
let (mut node, mut pos) = parse_level_4(tokens, pos)?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let token = tokens.get(pos);
|
let token = tokens.get(pos);
|
||||||
match token {
|
match token {
|
||||||
@ -88,6 +89,84 @@ fn parse_level_3(tokens: &TokenVector, pos: usize) -> Result<(AstNode, usize), S
|
|||||||
node = new_node;
|
node = new_node;
|
||||||
pos = next_pos;
|
pos = next_pos;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Below is implicative multiplication, for example '2pi'. Constants and
|
||||||
|
// such will only end up here if they were unable to be parsed as part of
|
||||||
|
// other operators.
|
||||||
|
// Note that this match statement matches an AstNode token, but the
|
||||||
|
// matches nested inside check the TokenVector. That's why we for example
|
||||||
|
// match a FunctionIdentifier, and inside that, a RightParen.
|
||||||
|
|
||||||
|
// pi2, )2
|
||||||
|
Some(&Token::Number(_)) => {
|
||||||
|
let last_token = tokens.get(pos - 1);
|
||||||
|
match last_token {
|
||||||
|
Some(&Token::Constant(_)) | Some(&Token::Operator(RightParen)) => {
|
||||||
|
let (right_node, next_pos) = parse_level_4(tokens, pos)?;
|
||||||
|
let mut new_node = AstNode::new(Token::Operator(Multiply));
|
||||||
|
new_node.children.push(node);
|
||||||
|
new_node.children.push(right_node);
|
||||||
|
node = new_node;
|
||||||
|
pos = next_pos;
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
return Ok((node, pos));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 2pi, )pi
|
||||||
|
Some(&Token::Constant(_)) => {
|
||||||
|
let last_token = tokens.get(pos - 1);
|
||||||
|
match last_token {
|
||||||
|
Some(&Token::Number(_)) | Some(&Token::Operator(RightParen)) => {
|
||||||
|
let (right_node, next_pos) = parse_level_4(tokens, pos)?;
|
||||||
|
let mut new_node = AstNode::new(Token::Operator(Multiply));
|
||||||
|
new_node.children.push(node);
|
||||||
|
new_node.children.push(right_node);
|
||||||
|
node = new_node;
|
||||||
|
pos = next_pos;
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
return Ok((node, pos));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 2log(1), )log(1)
|
||||||
|
Some(&Token::FunctionIdentifier(_)) => {
|
||||||
|
let last_token = tokens.get(pos - 1);
|
||||||
|
match last_token {
|
||||||
|
Some(&Token::Number(_)) | Some(&Token::Operator(RightParen)) => {
|
||||||
|
let (right_node, next_pos) = parse_level_4(tokens, pos)?;
|
||||||
|
let mut new_node = AstNode::new(Token::Operator(Multiply));
|
||||||
|
new_node.children.push(node);
|
||||||
|
new_node.children.push(right_node);
|
||||||
|
node = new_node;
|
||||||
|
pos = next_pos;
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
return Ok((node, pos));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 2(3), pi(3), )(3)
|
||||||
|
Some(&Token::Operator(LeftParen)) => {
|
||||||
|
let last_token = tokens.get(pos - 1);
|
||||||
|
println!("{:?}", token);
|
||||||
|
println!("{:?}", last_token);
|
||||||
|
match last_token {
|
||||||
|
Some(&Token::Number(_)) | Some(&Token::Constant(_)) | Some(&Token::Operator(RightParen)) => {
|
||||||
|
let (right_node, next_pos) = parse_level_4(tokens, pos)?;
|
||||||
|
let mut new_node = AstNode::new(Token::Operator(Multiply));
|
||||||
|
new_node.children.push(node);
|
||||||
|
new_node.children.push(right_node);
|
||||||
|
node = new_node;
|
||||||
|
pos = next_pos;
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
return Ok((node, pos));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Ok((node, pos));
|
return Ok((node, pos));
|
||||||
},
|
},
|
||||||
@ -121,10 +200,10 @@ fn parse_level_5(tokens: &TokenVector, pos: usize) -> Result<(AstNode, usize), S
|
|||||||
// Here we parse the negative unary operator. If the current token
|
// Here we parse the negative unary operator. If the current token
|
||||||
// is a minus, we wrap the right_node inside a Negative AstNode.
|
// is a minus, we wrap the right_node inside a Negative AstNode.
|
||||||
//
|
//
|
||||||
// Why doesn't this parse 4-5? First, we will first get a 4.
|
// Why doesn't this parse 4-5? First, we will first get a 4. In which case,
|
||||||
// In which case, we just return the result of parse_level_6(), which will
|
// we just return the result of parse_level_6(), which will include the pos
|
||||||
// include the pos of +. This will then go down to level 2 and be parsed as
|
// of +. This will then go down to level 2 and be parsed as a normal minus
|
||||||
// a normal minus operator.
|
// operator.
|
||||||
// The difference is that in other levels, we parse higher priorities
|
// The difference is that in other levels, we parse higher priorities
|
||||||
// immediately, while in this one we instead check if the current token
|
// immediately, while in this one we instead check if the current token
|
||||||
// is a minus, and if not, we then return the higher priority as normal.
|
// is a minus, and if not, we then return the higher priority as normal.
|
||||||
@ -215,9 +294,9 @@ fn parse_level_7(tokens: &TokenVector, pos: usize) -> Result<(AstNode, usize), S
|
|||||||
Token::Operator(LeftParen) => {
|
Token::Operator(LeftParen) => {
|
||||||
parse_level_1(tokens, pos + 1).and_then(|(node, next_pos)| {
|
parse_level_1(tokens, pos + 1).and_then(|(node, next_pos)| {
|
||||||
if let Some(&Token::Operator(RightParen)) = tokens.get(next_pos) {
|
if let Some(&Token::Operator(RightParen)) = tokens.get(next_pos) {
|
||||||
let mut paren = AstNode::new(Token::Paren);
|
let mut paren_node = AstNode::new(Token::Paren);
|
||||||
paren.children.push(node);
|
paren_node.children.push(node);
|
||||||
Ok((paren, next_pos + 1))
|
Ok((paren_node, next_pos + 1))
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Expected closing paren at {} but found {:?}", next_pos, tokens.get(next_pos)))
|
Err(format!("Expected closing paren at {} but found {:?}", next_pos, tokens.get(next_pos)))
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user