Merge pull request #21 from djmattyg007/more_operators_in_lexer
Further improvements to operator parsing in lexer
This commit is contained in:
commit
2ccee2ccd2
@ -1,9 +1,12 @@
|
|||||||
## Next
|
## Next
|
||||||
- Add operator words `plus`, `minus` and `times`
|
- Add operator words `plus`, `minus` and `times`
|
||||||
|
- Add operator phrases `multiplied by` and `divided by`
|
||||||
|
- Add operator symbol `÷`
|
||||||
- Disallow named number followed by smaller named number (like 1 million thousand)
|
- Disallow named number followed by smaller named number (like 1 million thousand)
|
||||||
- Fix/improve parsing of multi-word units
|
- Fix/improve parsing of multi-word units
|
||||||
- Fix light second parsed as light year
|
- Fix light second parsed as light year
|
||||||
- Fix `Ω` lexing
|
- Fix `Ω` lexing
|
||||||
|
- Fix lexing of rpm units
|
||||||
|
|
||||||
## 1.6.0 - 2021 Jul 3
|
## 1.6.0 - 2021 Jul 3
|
||||||
- Add support for non-US "metre" and "litre" spellings
|
- Add support for non-US "metre" and "litre" spellings
|
||||||
|
|||||||
46
src/lexer.rs
46
src/lexer.rs
@ -7,7 +7,7 @@ use crate::UnaryOperator::{Percent, Factorial};
|
|||||||
use crate::TextOperator::{Of, To};
|
use crate::TextOperator::{Of, To};
|
||||||
use crate::NamedNumber::*;
|
use crate::NamedNumber::*;
|
||||||
use crate::Constant::{E, Pi};
|
use crate::Constant::{E, Pi};
|
||||||
use crate::LexerKeyword::{In, PercentChar, Per, Mercury, Hg, PoundForce, Force, DoubleQuotes};
|
use crate::LexerKeyword::{In, PercentChar, Per, Mercury, Hg, PoundForce, Force, DoubleQuotes, Revolution};
|
||||||
use crate::FunctionIdentifier::{Cbrt, Ceil, Cos, Exp, Abs, Floor, Ln, Log, Round, Sin, Sqrt, Tan};
|
use crate::FunctionIdentifier::{Cbrt, Ceil, Cos, Exp, Abs, Floor, Ln, Log, Round, Sin, Sqrt, Tan};
|
||||||
use crate::units::Unit;
|
use crate::units::Unit;
|
||||||
use crate::units::Unit::*;
|
use crate::units::Unit::*;
|
||||||
@ -121,7 +121,7 @@ fn parse_token(c: &str, lexer: &mut Lexer) -> Result<(), String> {
|
|||||||
"+" => tokens.push(Token::Operator(Plus)),
|
"+" => tokens.push(Token::Operator(Plus)),
|
||||||
"-" => tokens.push(Token::Operator(Minus)),
|
"-" => tokens.push(Token::Operator(Minus)),
|
||||||
"*" => tokens.push(Token::Operator(Multiply)),
|
"*" => tokens.push(Token::Operator(Multiply)),
|
||||||
"/" => tokens.push(Token::Operator(Divide)),
|
"/" | "÷" => tokens.push(Token::Operator(Divide)),
|
||||||
"%" => tokens.push(Token::LexerKeyword(PercentChar)),
|
"%" => tokens.push(Token::LexerKeyword(PercentChar)),
|
||||||
"^" => tokens.push(Token::Operator(Caret)),
|
"^" => tokens.push(Token::Operator(Caret)),
|
||||||
"!" => tokens.push(Token::UnaryOperator(Factorial)),
|
"!" => tokens.push(Token::UnaryOperator(Factorial)),
|
||||||
@ -186,6 +186,18 @@ fn parse_word(word: &str, lexer: &mut Lexer) -> Result<(), String> {
|
|||||||
"plus" => Token::Operator(Plus),
|
"plus" => Token::Operator(Plus),
|
||||||
"minus" => Token::Operator(Minus),
|
"minus" => Token::Operator(Minus),
|
||||||
"times" => Token::Operator(Multiply),
|
"times" => Token::Operator(Multiply),
|
||||||
|
"multiplied" => {
|
||||||
|
match read_word("", lexer).as_str() {
|
||||||
|
"by" => Token::Operator(Multiply),
|
||||||
|
string => return Err(format!("Invalid string: {}", string)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"divided" => {
|
||||||
|
match read_word("", lexer).as_str() {
|
||||||
|
"by" => Token::Operator(Divide),
|
||||||
|
string => return Err(format!("Invalid string: {}", string)),
|
||||||
|
}
|
||||||
|
},
|
||||||
"mod" => Token::Operator(Modulo),
|
"mod" => Token::Operator(Modulo),
|
||||||
|
|
||||||
"sqrt" => Token::FunctionIdentifier(Sqrt),
|
"sqrt" => Token::FunctionIdentifier(Sqrt),
|
||||||
@ -565,7 +577,8 @@ fn parse_word(word: &str, lexer: &mut Lexer) -> Result<(), String> {
|
|||||||
"ghz" | "gigahertz" => Token::Unit(Gigahertz),
|
"ghz" | "gigahertz" => Token::Unit(Gigahertz),
|
||||||
"thz" | "terahertz" => Token::Unit(Terahertz),
|
"thz" | "terahertz" => Token::Unit(Terahertz),
|
||||||
"phz" | "petahertz" => Token::Unit(Petahertz),
|
"phz" | "petahertz" => Token::Unit(Petahertz),
|
||||||
"rpm" | "r/min" | "rev/min" => Token::Unit(RevolutionsPerMinute),
|
"rpm" => Token::Unit(RevolutionsPerMinute),
|
||||||
|
"r" | "rev" | "revolution" | "revolutions" => Token::LexerKeyword(Revolution),
|
||||||
|
|
||||||
"kph" | "kmh" => Token::Unit(KilometersPerHour),
|
"kph" | "kmh" => Token::Unit(KilometersPerHour),
|
||||||
"mps" => Token::Unit(MetersPerSecond),
|
"mps" => Token::Unit(MetersPerSecond),
|
||||||
@ -753,6 +766,10 @@ pub fn lex(input: &str, remove_trailing_operator: bool, default_degree: Unit) ->
|
|||||||
(Token::Unit(Inch), Token::TextOperator(Of), Token::LexerKeyword(Mercury)) => {
|
(Token::Unit(Inch), Token::TextOperator(Of), Token::LexerKeyword(Mercury)) => {
|
||||||
tokens[token_index-2] = Token::Unit(InchOfMercury);
|
tokens[token_index-2] = Token::Unit(InchOfMercury);
|
||||||
},
|
},
|
||||||
|
// revolutions per minute
|
||||||
|
(Token::LexerKeyword(Revolution), Token::LexerKeyword(Per), Token::Unit(Minute)) => {
|
||||||
|
tokens[token_index-2] = Token::Unit(RevolutionsPerMinute);
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
replaced = false;
|
replaced = false;
|
||||||
},
|
},
|
||||||
@ -927,15 +944,15 @@ mod tests {
|
|||||||
run_lex("20 lbf", vec![numtok!(20), Token::LexerKeyword(PoundForce)]);
|
run_lex("20 lbf", vec![numtok!(20), Token::LexerKeyword(PoundForce)]);
|
||||||
run_lex("60 hz", vec![numtok!(60), Token::Unit(Hertz)]);
|
run_lex("60 hz", vec![numtok!(60), Token::Unit(Hertz)]);
|
||||||
run_lex("1100 rpm", vec![numtok!(1100), Token::Unit(RevolutionsPerMinute)]);
|
run_lex("1100 rpm", vec![numtok!(1100), Token::Unit(RevolutionsPerMinute)]);
|
||||||
// run_lex("1150 revolutions per minute", vec![numtok!(1150), Token::Unit(RevolutionsPerMinute)]);
|
run_lex("1150 revolutions per minute", vec![numtok!(1150), Token::Unit(RevolutionsPerMinute)]);
|
||||||
// run_lex("1 revolution per min", vec![numtok!(1), Token::Unit(RevolutionsPerMinute)]);
|
run_lex("1 revolution per min", vec![numtok!(1), Token::Unit(RevolutionsPerMinute)]);
|
||||||
// run_lex("4 revolution / mins", vec![numtok!(4), Token::Unit(RevolutionsPerMinute)]);
|
run_lex("4 revolution / mins", vec![numtok!(4), Token::Unit(RevolutionsPerMinute)]);
|
||||||
// run_lex("1250 r / min", vec![numtok!(1250), Token::Unit(RevolutionsPerMinute)]);
|
run_lex("1250 r / min", vec![numtok!(1250), Token::Unit(RevolutionsPerMinute)]);
|
||||||
// run_lex("1300 rev / min", vec![numtok!(1300), Token::Unit(RevolutionsPerMinute)]);
|
run_lex("1300 rev / min", vec![numtok!(1300), Token::Unit(RevolutionsPerMinute)]);
|
||||||
// run_lex("1350 rev / minute", vec![numtok!(1350), Token::Unit(RevolutionsPerMinute)]);
|
run_lex("1350 rev / minute", vec![numtok!(1350), Token::Unit(RevolutionsPerMinute)]);
|
||||||
// run_lex("1250 r per min", vec![numtok!(1250), Token::Unit(RevolutionsPerMinute)]);
|
run_lex("1250 r per min", vec![numtok!(1250), Token::Unit(RevolutionsPerMinute)]);
|
||||||
// run_lex("1300 rev per min", vec![numtok!(1300), Token::Unit(RevolutionsPerMinute)]);
|
run_lex("1300 rev per min", vec![numtok!(1300), Token::Unit(RevolutionsPerMinute)]);
|
||||||
// run_lex("1350 rev per minute", vec![numtok!(1350), Token::Unit(RevolutionsPerMinute)]);
|
run_lex("1350 rev per minute", vec![numtok!(1350), Token::Unit(RevolutionsPerMinute)]);
|
||||||
run_lex("100 kph", vec![numtok!(100), Token::Unit(KilometersPerHour)]);
|
run_lex("100 kph", vec![numtok!(100), Token::Unit(KilometersPerHour)]);
|
||||||
run_lex("100 kmh", vec![numtok!(100), Token::Unit(KilometersPerHour)]);
|
run_lex("100 kmh", vec![numtok!(100), Token::Unit(KilometersPerHour)]);
|
||||||
run_lex("100 kilometers per hour", vec![numtok!(100), Token::Unit(KilometersPerHour)]);
|
run_lex("100 kilometers per hour", vec![numtok!(100), Token::Unit(KilometersPerHour)]);
|
||||||
@ -965,10 +982,11 @@ mod tests {
|
|||||||
run_lex("12 minus 4", vec![numtok!(12), Token::Operator(Minus), numtok!(4)]);
|
run_lex("12 minus 4", vec![numtok!(12), Token::Operator(Minus), numtok!(4)]);
|
||||||
run_lex("50.5 * 2", vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)]);
|
run_lex("50.5 * 2", vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)]);
|
||||||
run_lex("50.5 times 2", vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)]);
|
run_lex("50.5 times 2", vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)]);
|
||||||
// run_lex("50.5 multiplied by 2", vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)]);
|
run_lex("50.5 multiplied by 2", vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)]);
|
||||||
run_lex("6 / 3", vec![numtok!(6), Token::Operator(Divide), numtok!(3)]);
|
run_lex("6 / 3", vec![numtok!(6), Token::Operator(Divide), numtok!(3)]);
|
||||||
run_lex("50 / 10", vec![numtok!(50), Token::Operator(Divide), numtok!(10)]);
|
run_lex("50 / 10", vec![numtok!(50), Token::Operator(Divide), numtok!(10)]);
|
||||||
// run_lex("6 divided by 3", vec![numtok!(6), Token::Operator(Divide), numtok!(3)]);
|
run_lex("52 ÷ 12", vec![numtok!(52), Token::Operator(Divide), numtok!(12)]);
|
||||||
|
run_lex("6 divided by 3", vec![numtok!(6), Token::Operator(Divide), numtok!(3)]);
|
||||||
run_lex("7 mod 5", vec![numtok!(7), Token::Operator(Modulo), numtok!(5)]);
|
run_lex("7 mod 5", vec![numtok!(7), Token::Operator(Modulo), numtok!(5)]);
|
||||||
|
|
||||||
run_lex("(2 + 3) * 4", vec![Token::Operator(LeftParen), numtok!(2), Token::Operator(Plus), numtok!(3), Token::Operator(RightParen), Token::Operator(Multiply), numtok!(4)]);
|
run_lex("(2 + 3) * 4", vec![Token::Operator(LeftParen), numtok!(2), Token::Operator(Plus), numtok!(3), Token::Operator(RightParen), Token::Operator(Multiply), numtok!(4)]);
|
||||||
|
|||||||
@ -175,6 +175,7 @@ pub enum LexerKeyword {
|
|||||||
Hg,
|
Hg,
|
||||||
PoundForce,
|
PoundForce,
|
||||||
Force,
|
Force,
|
||||||
|
Revolution,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user