fix negative word binary expression (#549)
* fix negative word binary expression Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
@ -510,6 +510,8 @@ impl BinaryPart {
|
||||
let mut new_pipe_info = pipe_info.clone();
|
||||
new_pipe_info.is_in_pipe = false;
|
||||
|
||||
println!("BinaryPart::get_result: {:?}", self);
|
||||
|
||||
match self {
|
||||
BinaryPart::Literal(literal) => Ok(literal.into()),
|
||||
BinaryPart::Identifier(identifier) => {
|
||||
@ -521,11 +523,7 @@ impl BinaryPart {
|
||||
}
|
||||
BinaryPart::CallExpression(call_expression) => call_expression.execute(memory, &mut new_pipe_info, engine),
|
||||
BinaryPart::UnaryExpression(unary_expression) => {
|
||||
// Return an error this should not happen.
|
||||
Err(KclError::Semantic(KclErrorDetails {
|
||||
message: format!("UnaryExpression should not be a BinaryPart: {:?}", unary_expression),
|
||||
source_ranges: vec![unary_expression.into()],
|
||||
}))
|
||||
unary_expression.get_result(memory, &mut new_pipe_info, engine)
|
||||
}
|
||||
BinaryPart::MemberExpression(member_expression) => member_expression.get_result(memory),
|
||||
}
|
||||
|
||||
@ -1182,4 +1182,28 @@ show(thisBox)
|
||||
memory.root.get("thing").unwrap().get_json_value().unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_math_negative_variable_in_binary_expression() {
|
||||
let ast = r#"const sigmaAllow = 35000 // psi
|
||||
const width = 1 // inch
|
||||
|
||||
const p = 150 // lbs
|
||||
const distance = 6 // inches
|
||||
const FOS = 2
|
||||
|
||||
const leg1 = 5 // inches
|
||||
const leg2 = 8 // inches
|
||||
|
||||
const thickness_squared = distance * p * FOS * 6 / sigmaAllow
|
||||
const thickness = 0.56 // inches. App does not support square root function yet
|
||||
|
||||
const bracket = startSketchAt([0,0])
|
||||
|> line([0, leg1], %)
|
||||
|> line([leg2, 0], %)
|
||||
|> line([0, -thickness], %)
|
||||
|> line([-leg2 + thickness, 0], %)
|
||||
"#;
|
||||
parse_execute(ast).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,8 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
abstract_syntax_tree_types::{
|
||||
BinaryExpression, BinaryOperator, BinaryPart, CallExpression, Identifier, Literal, MemberExpression, ValueMeta,
|
||||
BinaryExpression, BinaryOperator, BinaryPart, CallExpression, Identifier, Literal, MemberExpression,
|
||||
UnaryExpression, ValueMeta,
|
||||
},
|
||||
errors::{KclError, KclErrorDetails},
|
||||
executor::SourceRange,
|
||||
@ -82,6 +83,7 @@ pub enum MathExpression {
|
||||
ExtendedBinaryExpression(Box<ExtendedBinaryExpression>),
|
||||
ParenthesisToken(Box<ParenthesisToken>),
|
||||
MemberExpression(Box<MemberExpression>),
|
||||
UnaryExpression(Box<UnaryExpression>),
|
||||
}
|
||||
|
||||
impl MathExpression {
|
||||
@ -94,6 +96,7 @@ impl MathExpression {
|
||||
MathExpression::ExtendedBinaryExpression(extended_binary_expression) => extended_binary_expression.start(),
|
||||
MathExpression::ParenthesisToken(parenthesis_token) => parenthesis_token.start(),
|
||||
MathExpression::MemberExpression(member_expression) => member_expression.start(),
|
||||
MathExpression::UnaryExpression(unary_expression) => unary_expression.start(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,6 +109,7 @@ impl MathExpression {
|
||||
MathExpression::ExtendedBinaryExpression(extended_binary_expression) => extended_binary_expression.end(),
|
||||
MathExpression::ParenthesisToken(parenthesis_token) => parenthesis_token.end(),
|
||||
MathExpression::MemberExpression(member_expression) => member_expression.end(),
|
||||
MathExpression::UnaryExpression(unary_expression) => unary_expression.end(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -208,7 +212,8 @@ impl ReversePolishNotation {
|
||||
if prevtoken.token_type == TokenType::Operator {
|
||||
// Get the next token and see if it is a number.
|
||||
if let Ok(nexttoken) = self.parser.get_token(1) {
|
||||
if nexttoken.token_type == TokenType::Number {
|
||||
if nexttoken.token_type == TokenType::Number || nexttoken.token_type == TokenType::Word
|
||||
{
|
||||
// We have a negative number/ word or string.
|
||||
// Change the value of the token to be the negative number/ word or string.
|
||||
let mut new_token = nexttoken.clone();
|
||||
@ -250,7 +255,7 @@ impl ReversePolishNotation {
|
||||
&& current_token.value == "-"
|
||||
{
|
||||
if let Ok(nexttoken) = self.parser.get_token(1) {
|
||||
if nexttoken.token_type == TokenType::Number {
|
||||
if nexttoken.token_type == TokenType::Number || nexttoken.token_type == TokenType::Word {
|
||||
// We have a negative number/ word or string.
|
||||
// Change the value of the token to be the negative number/ word or string.
|
||||
let mut new_token = nexttoken.clone();
|
||||
@ -435,11 +440,25 @@ impl ReversePolishNotation {
|
||||
);
|
||||
}
|
||||
let mut new_stack = stack;
|
||||
new_stack.push(MathExpression::Identifier(Box::new(Identifier {
|
||||
name: current_token.value.clone(),
|
||||
start: current_token.start,
|
||||
end: current_token.end,
|
||||
})));
|
||||
if current_token.value.starts_with('-') {
|
||||
let expression = UnaryExpression {
|
||||
start: current_token.start,
|
||||
end: current_token.end,
|
||||
operator: crate::abstract_syntax_tree_types::UnaryOperator::Neg,
|
||||
argument: BinaryPart::Identifier(Box::new(Identifier {
|
||||
name: current_token.value.trim_start_matches('-').to_string(),
|
||||
start: current_token.start + 1,
|
||||
end: current_token.end,
|
||||
})),
|
||||
};
|
||||
new_stack.push(MathExpression::UnaryExpression(Box::new(expression)));
|
||||
} else {
|
||||
new_stack.push(MathExpression::Identifier(Box::new(Identifier {
|
||||
name: current_token.value.clone(),
|
||||
start: current_token.start,
|
||||
end: current_token.end,
|
||||
})));
|
||||
}
|
||||
return self.build_tree(&reverse_polish_notation_tokens[1..], new_stack);
|
||||
}
|
||||
} else if current_token.token_type == TokenType::Brace && current_token.value == "(" {
|
||||
@ -571,6 +590,10 @@ impl ReversePolishNotation {
|
||||
BinaryPart::MemberExpression(member_expression.clone()),
|
||||
member_expression.start,
|
||||
),
|
||||
MathExpression::UnaryExpression(unary_expression) => (
|
||||
BinaryPart::UnaryExpression(unary_expression.clone()),
|
||||
unary_expression.start,
|
||||
),
|
||||
a => {
|
||||
return Err(KclError::InvalidExpression(KclErrorDetails {
|
||||
source_ranges: vec![current_token.into()],
|
||||
@ -605,6 +628,10 @@ impl ReversePolishNotation {
|
||||
BinaryPart::MemberExpression(member_expression.clone()),
|
||||
member_expression.end,
|
||||
),
|
||||
MathExpression::UnaryExpression(unary_expression) => (
|
||||
BinaryPart::UnaryExpression(unary_expression.clone()),
|
||||
unary_expression.end,
|
||||
),
|
||||
a => {
|
||||
return Err(KclError::InvalidExpression(KclErrorDetails {
|
||||
source_ranges: vec![current_token.into()],
|
||||
|
||||
@ -103,9 +103,9 @@ pub struct ParamsResult {
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
struct UnaryExpressionResult {
|
||||
expression: UnaryExpression,
|
||||
last_index: usize,
|
||||
pub struct UnaryExpressionResult {
|
||||
pub expression: UnaryExpression,
|
||||
pub last_index: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
@ -731,7 +731,9 @@ impl Parser {
|
||||
|
||||
let maybe_operator = self.next_meaningful_token(index, None)?;
|
||||
if let Some(maybe_operator_token) = maybe_operator.token {
|
||||
if maybe_operator_token.token_type == TokenType::Number {
|
||||
if maybe_operator_token.token_type == TokenType::Number
|
||||
|| maybe_operator_token.token_type == TokenType::Word
|
||||
{
|
||||
return self.find_end_of_binary_expression(maybe_operator.index);
|
||||
} else if maybe_operator_token.token_type != TokenType::Operator
|
||||
|| maybe_operator_token.value == PIPE_OPERATOR
|
||||
@ -1418,7 +1420,7 @@ impl Parser {
|
||||
self.make_params(next_brace_or_comma_token.index, _previous_params)
|
||||
}
|
||||
|
||||
fn make_unary_expression(&self, index: usize) -> Result<UnaryExpressionResult, KclError> {
|
||||
pub fn make_unary_expression(&self, index: usize) -> Result<UnaryExpressionResult, KclError> {
|
||||
let current_token = self.get_token(index)?;
|
||||
let next_token = self.next_meaningful_token(index, None)?;
|
||||
if next_token.token.is_none() {
|
||||
@ -2741,6 +2743,12 @@ show(mySk1)"#;
|
||||
let tokens = crate::tokeniser::lexer(code);
|
||||
let parser = Parser::new(tokens);
|
||||
let _end = parser.find_end_of_binary_expression(0).unwrap();
|
||||
// with call expression at the end of binary expression
|
||||
let code = "-legX + 2, ";
|
||||
let tokens = crate::tokeniser::lexer(code);
|
||||
let parser = Parser::new(tokens.clone());
|
||||
let end = parser.find_end_of_binary_expression(0).unwrap();
|
||||
assert_eq!(tokens[end].value, "2");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -3079,6 +3087,20 @@ const secondExtrude = startSketchAt([0,0])
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_negative_in_array_binary_expression() {
|
||||
let tokens = crate::tokeniser::lexer(
|
||||
r#"const leg1 = 5
|
||||
const thickness = 0.56
|
||||
|
||||
const bracket = [-leg2 + thickness, 0]
|
||||
"#,
|
||||
);
|
||||
let parser = Parser::new(tokens);
|
||||
let result = parser.ast();
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_nested_open_brackets() {
|
||||
let tokens = crate::tokeniser::lexer(
|
||||
|
||||
@ -720,4 +720,25 @@ mod tests {
|
||||
let semantic_types = TokenType::to_semantic_token_types().unwrap();
|
||||
assert!(!semantic_types.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lexer_negative_word() {
|
||||
assert_eq!(
|
||||
lexer("-legX"),
|
||||
vec![
|
||||
Token {
|
||||
token_type: TokenType::Operator,
|
||||
value: "-".to_string(),
|
||||
start: 0,
|
||||
end: 1,
|
||||
},
|
||||
Token {
|
||||
token_type: TokenType::Word,
|
||||
value: "legX".to_string(),
|
||||
start: 1,
|
||||
end: 5,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user