Skip to content
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

new: parse short match correctly #32

Merged
merged 2 commits into from
Jan 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 20 additions & 33 deletions src/parser/internal/expression/control_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,37 @@ use crate::tree::expression::control_flow::MatchExpression;
use crate::tree::utils::CommaSeparated;

pub fn match_expression(state: &mut State) -> ParseResult<MatchExpression> {
let r#match = utils::skip_keyword(state, TokenKind::Match)?;

let expression = if state.iterator.current().kind == TokenKind::LeftBrace {
None
} else {
Some(Box::new(expression::create(state)?))
};

Ok(MatchExpression {
comments: state.iterator.comments(),
r#match: utils::skip_keyword(state, TokenKind::Match)?,
expression: Box::new(expression::create(state)?),
r#match,
expression,
body: MatchBodyExpression {
left_brace: utils::skip_left_brace(state)?,
arms: {
let mut items = Vec::new();
let mut commas = Vec::new();
let mut default_arm = None;

while state.iterator.current().kind != TokenKind::RightBrace {
let current = state.iterator.current();
let (condition, default) = if current.kind == TokenKind::Default {
(
MatchArmConditionExpression::Default(utils::skip_keyword(
state,
TokenKind::Default,
)?),
true,
)
let condition = if current.kind == TokenKind::Default {
MatchArmConditionExpression::Default(utils::skip_keyword(
state,
TokenKind::Default,
)?)
} else {
(
MatchArmConditionExpression::Expressions(utils::comma_separated(
state,
&expression::create,
TokenKind::DoubleArrow,
)?),
false,
)
MatchArmConditionExpression::Expressions(utils::comma_separated(
state,
&expression::create,
TokenKind::DoubleArrow,
)?)
};

let arm = MatchArmExpression {
Expand All @@ -48,20 +49,6 @@ pub fn match_expression(state: &mut State) -> ParseResult<MatchExpression> {
expression: expression::create(state)?,
};

if default {
if let Some(default_arm) = &default_arm {
crate::parser_report!(
state,
match_expression_cannot_have_multiple_default_arms(
default_arm,
&arm,
)
);
} else {
default_arm = Some(arm.clone());
}
}

items.push(arm);

let current = state.iterator.current();
Expand Down
39 changes: 0 additions & 39 deletions src/parser/issue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,25 +347,6 @@ pub enum ParserIssueCode {
/// - Remove the modifier
ModifierCannotBeUsedOnInterfaceConstant = 22,

/// Match expression cannot have multiple default arms ( code = 23 )
///
/// Example:
///
/// ```ara
/// function foo(string $input): string {
/// match $input {
/// "foo" => "bar",
/// default => "baz",
/// default => "qux",
/// }
/// }
/// ```
///
/// Possible solution(s):
///
/// - Remove one of the default arms
MatchExpressionCannotHaveMultipleDefaultArms = 23,

/// Promoted property cannot be variadic ( code = 24 )
///
/// Example:
Expand Down Expand Up @@ -919,26 +900,6 @@ pub(crate) fn modifier_cannot_be_used_on_interface_constant(
.with_note("only the `final`, and `public` modifiers can be used on an interface constant.")
}

pub(crate) fn match_expression_cannot_have_multiple_default_arms(
state: &ParserState,
first: &dyn Node,
second: &dyn Node,
) -> Issue {
let origin = state.source.name();

Issue::error(
ParserIssueCode::MatchExpressionCannotHaveMultipleDefaultArms,
"match expression cannot have multiple default arms",
)
.with_source(origin, second.initial_position(), second.final_position())
.with_annotation(Annotation::primary(
origin,
first.initial_position(),
first.final_position(),
))
.with_note("a match expression can only have one default arm")
}

pub(crate) fn promoted_property_cannot_be_variadic(
state: &ParserState,
class_name: Option<&Identifier>,
Expand Down
8 changes: 6 additions & 2 deletions src/tree/expression/control_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::tree::Node;
pub struct MatchExpression {
pub comments: CommentGroup,
pub r#match: Keyword,
pub expression: Box<Expression>,
pub expression: Option<Box<Expression>>,
pub body: MatchBodyExpression,
}

Expand Down Expand Up @@ -54,7 +54,11 @@ impl Node for MatchExpression {
}

fn children(&self) -> Vec<&dyn Node> {
vec![&self.r#match, self.expression.as_ref(), &self.body]
let mut children: Vec<&dyn Node> = vec![&self.r#match, &self.body];
if let Some(expression) = &self.expression {
children.push(expression.as_ref());
}
children
}

fn get_description(&self) -> String {
Expand Down
40 changes: 22 additions & 18 deletions tests/samples/0070/tree.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1388,11 +1388,13 @@ DefinitionTree {
value: "match",
position: 669,
},
expression: Variable(
Variable {
position: 675,
name: "$a",
},
expression: Some(
Variable(
Variable {
position: 675,
name: "$a",
},
),
),
body: MatchBodyExpression {
left_brace: 678,
Expand Down Expand Up @@ -1524,20 +1526,22 @@ DefinitionTree {
value: "match",
position: 751,
},
expression: Parenthesized(
ParenthesizedExpression {
comments: CommentGroup {
comments: [],
},
left_parenthesis: 757,
expression: Variable(
Variable {
position: 758,
name: "$a",
expression: Some(
Parenthesized(
ParenthesizedExpression {
comments: CommentGroup {
comments: [],
},
),
right_parenthesis: 760,
},
left_parenthesis: 757,
expression: Variable(
Variable {
position: 758,
name: "$a",
},
),
right_parenthesis: 760,
},
),
),
body: MatchBodyExpression {
left_brace: 762,
Expand Down
9 changes: 9 additions & 0 deletions tests/samples/0106/code.ara
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
function bar(): void {
$c = match {
$a == $b => 'a is equal to b',
$a > $b => 'a is greater than b',
$a < $b => 'a is less than b',
default => 'a and b are not comparable',
default => 'a and b are not comparable', // The analyzer should warn about this
};
}
Loading