-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement parser for arithmetic expressions like a++
#155
base: main
Are you sure you want to change the base?
Changes from 4 commits
a844a71
a04b438
f38c5ae
beac261
2870dfb
15e78cc
5d19a48
d408118
d07ed7c
c6da08e
781b0b8
237ac4e
681725a
5ced079
44d8f1e
73a063d
30979c8
97d53c2
6c19d8c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1422,22 +1422,8 @@ fn parse_unary_arithmetic_expr(pair: Pair<Rule>) -> Result<ArithmeticPart> { | |
let first = inner.next().unwrap(); | ||
|
||
match first.as_rule() { | ||
Rule::unary_arithmetic_op => { | ||
let op = parse_unary_arithmetic_op(first)?; | ||
let operand = parse_arithmetic_expr(inner.next().unwrap())?; | ||
Ok(ArithmeticPart::UnaryArithmeticExpr { | ||
operator: op, | ||
operand: Box::new(operand), | ||
}) | ||
} | ||
Rule::post_arithmetic_op => { | ||
let operand = parse_arithmetic_expr(inner.next().unwrap())?; | ||
let op = parse_post_arithmetic_op(first)?; | ||
Ok(ArithmeticPart::PostArithmeticExpr { | ||
operand: Box::new(operand), | ||
operator: op, | ||
}) | ||
} | ||
Rule::unary_pre_arithmetic_expr => unary_pre_arithmetic_expr(first), | ||
Rule::unary_post_arithmetic_expr => unary_post_arithmetic_expr(first), | ||
_ => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this result in an error given that |
||
let operand = parse_arithmetic_expr(first)?; | ||
let op = parse_post_arithmetic_op(inner.next().unwrap())?; | ||
|
@@ -1449,26 +1435,100 @@ fn parse_unary_arithmetic_expr(pair: Pair<Rule>) -> Result<ArithmeticPart> { | |
} | ||
} | ||
|
||
fn parse_unary_arithmetic_op_type(pair: Pair<Rule>) -> Result<bool> { | ||
match pair.as_rule() { | ||
Rule::unary_arithmetic_op => Ok(true), | ||
Rule::post_arithmetic_op => Ok(false), | ||
_ => Err(miette!( | ||
"Unexpected rule in unary arithmetic operator: {:?}", | ||
pair.as_rule() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feels fairly hacky to return true of false for the type. Maybe you can try replacing this with match statement in |
||
)), | ||
} | ||
} | ||
|
||
fn unary_pre_arithmetic_expr(pair: Pair<Rule>) -> Result<ArithmeticPart> { | ||
let mut inner = pair.into_inner(); | ||
let first = inner.next().unwrap(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's better to replace unwraps with proper error handling. |
||
let second = inner.next().unwrap(); | ||
let operand = match second.as_rule() { | ||
Rule::parentheses_expr => { | ||
let inner = second.into_inner().next().unwrap(); | ||
let parts = parse_arithmetic_sequence(inner)?; | ||
Ok(ArithmeticPart::ParenthesesExpr(Box::new(Arithmetic { | ||
parts, | ||
}))) | ||
} | ||
Rule::VARIABLE => Ok(ArithmeticPart::Variable(second.as_str().to_string())), | ||
Rule::NUMBER => Ok(ArithmeticPart::Number(second.as_str().to_string())), | ||
_ => Err(miette!( | ||
"Unexpected rule in arithmetic expression: {:?}", | ||
second.as_rule() | ||
)), | ||
}?; | ||
|
||
if parse_unary_arithmetic_op_type(first.clone())? { | ||
let op = parse_unary_arithmetic_op(first)?; | ||
Ok(ArithmeticPart::UnaryArithmeticExpr { | ||
operator: (op), | ||
operand: (Box::new(operand)), | ||
}) | ||
} else { | ||
let op = parse_post_arithmetic_op(first)?; | ||
Ok(ArithmeticPart::PostArithmeticExpr { | ||
operator: (op), | ||
operand: (Box::new(operand)), | ||
}) | ||
} | ||
} | ||
|
||
fn unary_post_arithmetic_expr(pair: Pair<Rule>) -> Result<ArithmeticPart> { | ||
let mut inner = pair.into_inner(); | ||
let first = inner.next().unwrap(); | ||
let second = inner.next().unwrap(); | ||
let operand = match first.as_rule() { | ||
Rule::parentheses_expr => { | ||
let inner = first.into_inner().next().unwrap(); | ||
let parts = parse_arithmetic_sequence(inner)?; | ||
Ok(ArithmeticPart::ParenthesesExpr(Box::new(Arithmetic { | ||
parts, | ||
}))) | ||
} | ||
Rule::VARIABLE => Ok(ArithmeticPart::Variable(first.as_str().to_string())), | ||
Rule::NUMBER => Ok(ArithmeticPart::Number(first.as_str().to_string())), | ||
_ => Err(miette!( | ||
"Unexpected rule in arithmetic expression: {:?}", | ||
first.as_rule() | ||
)), | ||
}?; | ||
let op = parse_post_arithmetic_op(second)?; | ||
Ok(ArithmeticPart::PostArithmeticExpr { | ||
operator: (op), | ||
operand: (Box::new(operand)), | ||
}) | ||
} | ||
|
||
fn parse_unary_arithmetic_op(pair: Pair<Rule>) -> Result<UnaryArithmeticOp> { | ||
match pair.as_str() { | ||
"+" => Ok(UnaryArithmeticOp::Plus), | ||
"-" => Ok(UnaryArithmeticOp::Minus), | ||
"!" => Ok(UnaryArithmeticOp::LogicalNot), | ||
"~" => Ok(UnaryArithmeticOp::BitwiseNot), | ||
let first = pair.into_inner().next().unwrap(); | ||
match first.as_rule() { | ||
Rule::add => Ok(UnaryArithmeticOp::Plus), | ||
Rule::subtract => Ok(UnaryArithmeticOp::Minus), | ||
Rule::logical_not => Ok(UnaryArithmeticOp::LogicalNot), | ||
Rule::bitwise_not => Ok(UnaryArithmeticOp::BitwiseNot), | ||
_ => Err(miette!( | ||
"Invalid unary arithmetic operator: {}", | ||
pair.as_str() | ||
"Unexpected rule in unary arithmetic operator: {:?}", | ||
first.as_rule() | ||
)), | ||
} | ||
} | ||
|
||
fn parse_post_arithmetic_op(pair: Pair<Rule>) -> Result<PostArithmeticOp> { | ||
match pair.as_str() { | ||
"++" => Ok(PostArithmeticOp::Increment), | ||
"--" => Ok(PostArithmeticOp::Decrement), | ||
let first = pair.into_inner().next().unwrap(); | ||
match first.as_rule() { | ||
Rule::increment => Ok(PostArithmeticOp::Increment), | ||
Rule::decrement => Ok(PostArithmeticOp::Decrement), | ||
_ => Err(miette!( | ||
"Invalid post arithmetic operator: {}", | ||
pair.as_str() | ||
"Unexpected rule in post arithmetic operator: {:?}", | ||
first.as_rule() | ||
)), | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,5 @@ | ||
echo $((2 ** 3)) | ||
echo $((2 ** 3)) | ||
|
||
echo $((a++)) | ||
|
||
echo $((--a)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you change
unary_arithmetic_op
topre_arithmetic_op
for better clarity?