Skip to content

Commit

Permalink
parser: support new :: constant declaration syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Fedotov authored and feds01 committed Sep 23, 2024
1 parent 2c50b44 commit e1fc042
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 17 deletions.
53 changes: 42 additions & 11 deletions compiler/hash-parser/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,7 @@ impl<'s> AstGen<'s> {
// pattern which is then followed by a `:` to denote that this is a
// declaration.
if self.begins_pat() {
let pat = self.parse_singular_pat()?;
self.parse_token(TokenKind::Colon)?;
let decl = self.parse_declaration(pat)?;

let decl = self.parse_declaration()?;
let expr = self.node_with_joined_span(Expr::Declaration(decl), start);
let semi = maybe_eat_semi(self);
return Ok(Some((semi, expr)));
Expand Down Expand Up @@ -580,19 +577,53 @@ impl<'s> AstGen<'s> {
/// ```text
/// some_var: f64 = ...;
/// ^^^^^^^^ ^^^ ^^^─────┐
/// pattern type the right hand-side expr
/// pattern annotation the right hand-side expr
/// ```
pub(crate) fn parse_declaration(&mut self, pat: AstNode<Pat>) -> ParseResult<Declaration> {
// Attempt to parse an optional type...
pub(crate) fn parse_declaration(&mut self) -> ParseResult<Declaration> {
let pat = self.parse_singular_pat()?;
let mut is_constant = false;

// Figure out if this declaration has an annotation or not...
let ty = match self.peek_kind() {
Some(TokenKind::Eq) => None,
_ => Some(self.parse_ty()?),
Some(TokenKind::Access) => {
self.skip_fast(TokenKind::Access); // `::`
is_constant = true;
None
}
_ => {
self.parse_token(TokenKind::Colon)?; // `:`

if self.peek_kind() == Some(TokenKind::Eq) {
self.skip_fast(TokenKind::Eq); // `=`
None
} else {
Some(self.parse_ty()?)
}
}
};

// Now parse the initialiser...
self.parse_token(TokenKind::Eq)?;
if !is_constant && ty.is_some() {
match self.peek_kind() {
Some(TokenKind::Eq) => {
self.skip_fast(TokenKind::Eq); // `=`
}
Some(TokenKind::Colon) => {
self.skip_fast(TokenKind::Colon); // `=`
is_constant = true;
}
tok => {
return self.err(
ParseErrorKind::UnExpected,
ExpectedItem::Colon | ExpectedItem::Eq,
tok,
)
}
}
}

let value = self.parse_expr_with_precedence(0)?;
Ok(Declaration { pat, ty, value })
Ok(Declaration { pat, ty, value, is_constant })
}

/// Given a initial left-hand side expression, attempt to parse a
Expand Down
14 changes: 8 additions & 6 deletions compiler/hash-parser/src/parser/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,9 +554,11 @@ impl<'s> AstGen<'s> {
}

fn peek_pat(&self) -> bool {
macro_rules! peek_colon(
// This is a macro that is used to simplify the lookahead for the pattern
// boundary, which can either be a `:` or a `::` token.
macro_rules! peek_pat_boundary(
() => {
matches!(self.peek_kind(), Some(TokenKind::Colon))
matches!(self.peek_kind(), Some(TokenKind::Colon | TokenKind::Access))
}
);

Expand All @@ -575,7 +577,7 @@ impl<'s> AstGen<'s> {
&& kind.is_range_lit()
{
self.skip_fast(kind);
peek_colon!()
peek_pat_boundary!()
} else {
false
}
Expand All @@ -587,12 +589,12 @@ impl<'s> AstGen<'s> {
// Other general literal patterns.
Some(kind) if kind.is_lit() => {
self.skip_fast(kind);
peek_colon!()
peek_pat_boundary!()
}
// Module, Array, Tuple patterns.
Some(TokenKind::Tree(_, _)) => {
self.skip_token();
peek_colon!()
peek_pat_boundary!()
}
// Identifier or constructor pattern.
Some(ident @ TokenKind::Ident(_)) => {
Expand Down Expand Up @@ -620,7 +622,7 @@ impl<'s> AstGen<'s> {
}
}

peek_colon!()
peek_pat_boundary!()
}
// This is the case for a bind that has a visibility modifier at the beginning. In
// this scenario, it can be followed by a `mut` modifier and then a identifier or
Expand Down

0 comments on commit e1fc042

Please sign in to comment.