Added lexing of energy and speed units

This commit is contained in:
Kasper 2020-01-11 04:31:30 +01:00
parent 0d90173d7a
commit 0758611dfb
4 changed files with 66 additions and 5 deletions

View File

@ -314,5 +314,8 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
} }
} }
}, },
_ => {
Err(format!("Unexpected token {:?}", token))
}
} }
} }

View File

@ -100,6 +100,8 @@ pub fn lex(input: &str) -> Result<TokenVector, String> {
"cos" => tokens.push(Token::FunctionIdentifier(Cos)), "cos" => tokens.push(Token::FunctionIdentifier(Cos)),
"tan" => tokens.push(Token::FunctionIdentifier(Tan)), "tan" => tokens.push(Token::FunctionIdentifier(Tan)),
"per" => tokens.push(Token::Per),
"ns" | "nanosec" | "nanosecs" | "nanosecond" | "nanoseconds" => tokens.push(Token::Unit(Nanosecond)), "ns" | "nanosec" | "nanosecs" | "nanosecond" | "nanoseconds" => tokens.push(Token::Unit(Nanosecond)),
"μs" | "microsec" | "microsecs" | "microsecond" | "microseconds" => tokens.push(Token::Unit(Microsecond)), "μs" | "microsec" | "microsecs" | "microsecond" | "microseconds" => tokens.push(Token::Unit(Microsecond)),
"ms" | "millisec" | "millisecs" | "millisecond" | "milliseconds" => tokens.push(Token::Unit(Millisecond)), "ms" | "millisec" | "millisecs" | "millisecond" | "milliseconds" => tokens.push(Token::Unit(Millisecond)),
@ -109,7 +111,6 @@ pub fn lex(input: &str) -> Result<TokenVector, String> {
"day" | "days" => tokens.push(Token::Unit(Day)), "day" | "days" => tokens.push(Token::Unit(Day)),
"wk" | "wks" | "week" | "weeks" => tokens.push(Token::Unit(Week)), "wk" | "wks" | "week" | "weeks" => tokens.push(Token::Unit(Week)),
"mo" | "mos" | "month" | "months" => tokens.push(Token::Unit(Month)), "mo" | "mos" | "month" | "months" => tokens.push(Token::Unit(Month)),
"q" | "quater" | "quaters" => tokens.push(Token::Unit(Month)), "q" | "quater" | "quaters" => tokens.push(Token::Unit(Month)),
"yr" | "yrs" | "year" | "years" => tokens.push(Token::Unit(Year)), "yr" | "yrs" | "year" | "years" => tokens.push(Token::Unit(Year)),
"decade" | "decades" => tokens.push(Token::Unit(Decade)), "decade" | "decades" => tokens.push(Token::Unit(Decade)),
@ -210,6 +211,28 @@ pub fn lex(input: &str) -> Result<TokenVector, String> {
"zib" | "zebibyte" | "zebibytes" => tokens.push(Token::Unit(Zebibyte)), "zib" | "zebibyte" | "zebibytes" => tokens.push(Token::Unit(Zebibyte)),
"yib" | "yobibyte" | "yobibytes" => tokens.push(Token::Unit(Yobibyte)), "yib" | "yobibyte" | "yobibytes" => tokens.push(Token::Unit(Yobibyte)),
"millijoule" | "millijoules" => tokens.push(Token::Unit(Millijoule)),
"j"| "joule" | "joules" => tokens.push(Token::Unit(Joule)),
"kj" | "kilojoule" | "kilojoules" => tokens.push(Token::Unit(Kilojoule)),
"mj" | "megajoule" | "megajoules" => tokens.push(Token::Unit(Megajoule)),
"gj" | "gigajoule" | "gigajoules" => tokens.push(Token::Unit(Gigajoule)),
"tj" | "terajoule" | "terajoules" => tokens.push(Token::Unit(Terajoule)),
"cal" | "calorie" | "calories" => tokens.push(Token::Unit(Calorie)),
"kcal" | "kilocalorie" | "kilocalories" => tokens.push(Token::Unit(KiloCalorie)),
"btu" | "british thermal unit" | "british thermal units" => tokens.push(Token::Unit(BritishThermalUnit)),
"wh" | "watt hour" | "watt hours" => tokens.push(Token::Unit(WattHour)),
"kwh" | "kilowatt hour" | "kilowatt hours" => tokens.push(Token::Unit(KilowattHour)),
"mwh" | "megawatt hour" | "megawatt hours" => tokens.push(Token::Unit(MegawattHour)),
"gwh" | "gigawatt hour" | "gigawatt hours" => tokens.push(Token::Unit(GigawattHour)),
"twh" | "terawatt hour" | "terawatt hours" => tokens.push(Token::Unit(TerawattHour)),
"pwh" | "petawatt hour" | "petawatt hours" => tokens.push(Token::Unit(PetawattHour)),
"kph" | "kmh" => tokens.push(Token::Unit(KilometersPerHour)),
"mps" => tokens.push(Token::Unit(MetersPerSecond)),
"mph" => tokens.push(Token::Unit(MilesPerHour)),
"fps" => tokens.push(Token::Unit(FeetPerSecond)),
"kn" | "kt" | "knot" | "knots" => tokens.push(Token::Unit(Knot)),
"k" | "kelvin" | "kelvins" => tokens.push(Token::Unit(Kelvin)), "k" | "kelvin" | "kelvins" => tokens.push(Token::Unit(Kelvin)),
"c" | "celcius" => tokens.push(Token::Unit(Celcius)), "c" | "celcius" => tokens.push(Token::Unit(Celcius)),
"f" | "fahrenheit" | "fahrenheits" => tokens.push(Token::Unit(Fahrenheit)), "f" | "fahrenheit" | "fahrenheits" => tokens.push(Token::Unit(Fahrenheit)),
@ -273,9 +296,9 @@ pub fn lex(input: &str) -> Result<TokenVector, String> {
} }
} }
// the lexer parses percentages as modulo, so here modulos become percentages
let mut token_index = 0; let mut token_index = 0;
for _i in 1..tokens.len() { for _i in 1..tokens.len() {
// the lexer parses percentages as modulo, so here modulos become percentages
match tokens[token_index] { match tokens[token_index] {
Token::Operator(Modulo) => { Token::Operator(Modulo) => {
match &tokens[token_index + 1] { match &tokens[token_index + 1] {
@ -302,7 +325,41 @@ pub fn lex(input: &str) -> Result<TokenVector, String> {
_ => {}, _ => {},
} }
token_index += 1; token_index += 1;
// parse units like km per h
if token_index >= 2 {
let token1 = &tokens[token_index-2];
let token2 = match &tokens[token_index-1] {
// treat km/h the same as km per h
Token::Operator(Divide) => &Token::Per,
_ => &tokens[token_index-1],
};
let token3 = &tokens[token_index];
let mut replaced = true;
match (token1, token2, token3) {
(Token::Unit(Kilometer), Token::Per, Token::Unit(Hour)) => {
tokens[token_index-2] = Token::Unit(KilometersPerHour);
},
(Token::Unit(Mile), Token::Per, Token::Unit(Hour)) => {
tokens[token_index-2] = Token::Unit(MilesPerHour);
},
(Token::Unit(Meter), Token::Per, Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(MetersPerSecond);
},
(Token::Unit(Foot), Token::Per, Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(FeetPerSecond);
},
_ => {
replaced = false;
},
} }
if replaced {
tokens.remove(token_index);
tokens.remove(token_index-1);
token_index -= 2;
}
}
}
println!("XKXK {:?}", tokens);
Ok(tokens) Ok(tokens)
} }

View File

@ -60,6 +60,7 @@ pub enum Token {
FunctionIdentifier(FunctionIdentifier), FunctionIdentifier(FunctionIdentifier),
Constant(Constant), Constant(Constant),
Paren, // parser only Paren, // parser only
Per, // lexer only
TextOperator(TextOperator), TextOperator(TextOperator),
Negative, // parser only Negative, // parser only
Unit(units::Unit), Unit(units::Unit),

View File

@ -160,9 +160,9 @@ create_units!(
Megajoule: (Energy, d128!(1000000)), Megajoule: (Energy, d128!(1000000)),
Gigajoule: (Energy, d128!(1000000000)), Gigajoule: (Energy, d128!(1000000000)),
Terajoule: (Energy, d128!(1000000000000)), Terajoule: (Energy, d128!(1000000000000)),
Calorie: (Energy, d128!(4.1868)), // "IT" type Calorie: (Energy, d128!(4.1868)),
KiloCalorie: (Energy, d128!(4186.8)), // "IT" type KiloCalorie: (Energy, d128!(4186.8)),
BritishThermalUnit: (Energy, d128!(1055.05585262)), // "IT" type, might not be 100% accurate BritishThermalUnit: (Energy, d128!(1055.05585262)),
WattHour: (Energy, d128!(3600)), WattHour: (Energy, d128!(3600)),
KilowattHour: (Energy, d128!(3600000)), KilowattHour: (Energy, d128!(3600000)),
MegawattHour: (Energy, d128!(3600000000)), MegawattHour: (Energy, d128!(3600000000)),