Skip to content

Commit

Permalink
Allow parsing a function without parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
asterite committed Sep 13, 2024
1 parent 9bf2dcb commit c616de7
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 21 deletions.
2 changes: 2 additions & 0 deletions compiler/noirc_frontend/src/parser/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub enum ParserErrorReason {
ExpectedLeftBracketOrWhereOrLeftBraceOrArrowAfterImplType,
#[error("expected <, where or {{ after trait impl for type")]
ExpectedLeftBracketOrWhereOrLeftBraceOrArrowAfterTraitImplForType,
#[error("expected ( or < after function name")]
ExpectedLeftParenOrLeftBracketAfterFunctionName,
#[error("Expected a ; separating these two statements")]
MissingSeparatingSemi,
#[error("constrain keyword is deprecated")]
Expand Down
78 changes: 57 additions & 21 deletions compiler/noirc_frontend/src/parser/parser/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,30 +48,66 @@ pub(super) fn function_definition(allow_self: bool) -> impl NoirParser<NoirFunct
.then_ignore(keyword(Keyword::Fn))
.then(ident())
.then(generics())
.then(parenthesized(function_parameters(allow_self)))
.then(function_return_type())
.then(where_clause())
.then(body_or_error)
.validate(|(((args, ret), where_clause), (body, body_span)), span, emit| {
let ((((attributes, modifiers), name), generics), parameters) = args;
.then(
parenthesized(function_parameters(allow_self))
.then(function_return_type())
.then(where_clause())
.then(body_or_error)
// Allow parsing just `fn foo` for recovery and LSP autocompletion
.or_not(),
)
.validate(|args, span, emit| {
let (
(((attributes, (is_unconstrained, visibility, is_comptime)), name), generics),
params_and_others,
) = args;

// Validate collected attributes, filtering them into function and secondary variants
let attributes = validate_attributes(attributes, span, emit);
FunctionDefinition {
span: body_span,
name,
attributes,
is_unconstrained: modifiers.0,
visibility: modifiers.1,
is_comptime: modifiers.2,
generics,
parameters,
body,
where_clause,
return_type: ret.1,
return_visibility: ret.0,
}
.into()

let function_definition = if let Some(params_and_others) = params_and_others {
let (
((parameters, (return_visibility, return_type)), where_clause),
(body, body_span),
) = params_and_others;

FunctionDefinition {
span: body_span,
name,
attributes,
is_unconstrained,
visibility,
is_comptime,
generics,
parameters,
body,
where_clause,
return_type,
return_visibility,
}
} else {
emit(ParserError::with_reason(
ParserErrorReason::ExpectedLeftParenOrLeftBracketAfterFunctionName,
span,
));

let empty_span = Span::from(span.end()..span.end());
FunctionDefinition {
span: empty_span,
name,
attributes,
is_unconstrained,
visibility,
is_comptime,
generics,
parameters: Vec::new(),
body: BlockExpression { statements: vec![] },
where_clause: Vec::new(),
return_type: FunctionReturnType::Default(empty_span),
return_visibility: Visibility::Private,
}
};
function_definition.into()
})
}

Expand Down

0 comments on commit c616de7

Please sign in to comment.