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,
|
||||
Modulo,
|
||||
Caret,
|
||||
// Percent,
|
||||
// Factorial,
|
||||
LeftParen, // lexer only
|
||||
RightParen, // lexer only
|
||||
}
|
||||
@ -84,20 +82,22 @@ fn main() {
|
||||
match lexer::lex(s) {
|
||||
Ok(tokens) => {
|
||||
let lex_time = Instant::now().duration_since(lex_start).as_nanos() as f32;
|
||||
// println!("Lexed TokenVector: {:?}", tokens);
|
||||
|
||||
let parse_start = Instant::now();
|
||||
match parser::parse(&tokens) {
|
||||
Ok(ast) => {
|
||||
let parse_time = Instant::now().duration_since(parse_start).as_nanos() as f32;
|
||||
// println!("Parsed AstNode: {:#?}", ast);
|
||||
|
||||
let eval_start = Instant::now();
|
||||
match evaluator::evaluate(&ast) {
|
||||
Ok(answer) => {
|
||||
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 parsing", parse_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!("Lexing error: {}", e),
|
||||
}
|
||||
|
||||
@ -77,6 +77,7 @@ fn parse_level_2(tokens: &TokenVector, pos: usize) -> Result<(AstNode, usize), S
|
||||
// level 3 precedence: *, /, modulo
|
||||
fn parse_level_3(tokens: &TokenVector, pos: usize) -> Result<(AstNode, usize), String> {
|
||||
let (mut node, mut pos) = parse_level_4(tokens, pos)?;
|
||||
|
||||
loop {
|
||||
let token = tokens.get(pos);
|
||||
match token {
|
||||
@ -88,6 +89,84 @@ fn parse_level_3(tokens: &TokenVector, pos: usize) -> Result<(AstNode, usize), S
|
||||
node = new_node;
|
||||
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));
|
||||
},
|
||||
@ -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
|
||||
// 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.
|
||||
// In which case, we just return the result of parse_level_6(), which will
|
||||
// include the pos of +. This will then go down to level 2 and be parsed as
|
||||
// a normal minus operator.
|
||||
// Why doesn't this parse 4-5? First, we will first get a 4. In which case,
|
||||
// we just return the result of parse_level_6(), which will include the pos
|
||||
// of +. This will then go down to level 2 and be parsed as a normal minus
|
||||
// operator.
|
||||
// The difference is that in other levels, we parse higher priorities
|
||||
// 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.
|
||||
@ -215,9 +294,9 @@ fn parse_level_7(tokens: &TokenVector, pos: usize) -> Result<(AstNode, usize), S
|
||||
Token::Operator(LeftParen) => {
|
||||
parse_level_1(tokens, pos + 1).and_then(|(node, next_pos)| {
|
||||
if let Some(&Token::Operator(RightParen)) = tokens.get(next_pos) {
|
||||
let mut paren = AstNode::new(Token::Paren);
|
||||
paren.children.push(node);
|
||||
Ok((paren, next_pos + 1))
|
||||
let mut paren_node = AstNode::new(Token::Paren);
|
||||
paren_node.children.push(node);
|
||||
Ok((paren_node, next_pos + 1))
|
||||
} else {
|
||||
Err(format!("Expected closing paren at {} but found {:?}", next_pos, tokens.get(next_pos)))
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user