use crate::syntax::ast::{
BaseDimDecl, BindableVisibility, DeclKind, Declaration, DimDecl, UnitConstness, Visibility,
};
use crate::syntax::names::{DimName, UnitName};
use crate::syntax::token::Token;
use super::super::{ParseError, Parser};
impl Parser<'_> {
pub(super) fn parse_base_dimension_decl(
&mut self,
base_span: crate::syntax::span::Span,
) -> Result<Declaration, ParseError> {
let (_, _dim_span) = self.expect(Token::Dimension)?;
let name = self.parse_any_ident()?.into_spanned::<DimName>();
let (_, semi_span) = self.expect(Token::Semicolon)?;
let span = base_span.merge(semi_span);
Ok(Declaration {
attributes: vec![],
kind: DeclKind::BaseDimension(BaseDimDecl {
visibility: Visibility::Private,
name,
}),
span,
})
}
pub(super) fn parse_dimension_decl(&mut self) -> Result<Declaration, ParseError> {
let (_, start_span) = self.expect(Token::Dimension)?;
let name = self.parse_any_ident()?.into_spanned::<DimName>();
let definition = if self.lexer.peek() == Some(&Token::Eq) {
self.expect(Token::Eq)?;
Some(self.parse_dim_expr()?)
} else {
None
};
let (_, semi_span) = self.expect(Token::Semicolon)?;
let span = start_span.merge(semi_span);
Ok(Declaration {
attributes: vec![],
kind: DeclKind::Dimension(DimDecl {
visibility: BindableVisibility::Private,
name,
definition,
}),
span,
})
}
pub(super) fn parse_unit_decl(&mut self) -> Result<Declaration, ParseError> {
let (_, start_span) = self.expect(Token::Unit)?;
self.parse_unit_decl_inner(
start_span,
UnitConstness::Dynamic,
true,
)
}
pub(super) fn parse_const_unit(
&mut self,
const_span: crate::syntax::span::Span,
) -> Result<Declaration, ParseError> {
self.expect(Token::Unit)?;
self.parse_unit_decl_inner(
const_span,
UnitConstness::Const,
true,
)
}
pub(super) fn parse_base_unit_decl(
&mut self,
base_span: crate::syntax::span::Span,
) -> Result<Declaration, ParseError> {
self.expect(Token::Unit)?;
self.parse_unit_decl_inner(
base_span,
UnitConstness::Const,
false,
)
}
fn parse_unit_decl_inner(
&mut self,
start_span: crate::syntax::span::Span,
constness: UnitConstness,
require_definition: bool,
) -> Result<Declaration, ParseError> {
let name = self.parse_any_ident()?.into_spanned::<UnitName>();
self.expect(Token::Colon)?;
let dim_type = self.parse_dim_expr()?;
let definition = match self.lexer.peek() {
Some(Token::Eq) => {
self.lexer.next_token();
Some(self.parse_unit_def()?)
}
_ => None,
};
if require_definition && definition.is_none() {
let err_span = name.span;
return Err(self.unexpected_token(
"`=` followed by a unit definition (use `base unit` for a no-body declaration)",
";",
err_span,
));
}
let (_, semi_span) = self.expect(Token::Semicolon)?;
let span = start_span.merge(semi_span);
Ok(Declaration {
attributes: vec![],
kind: DeclKind::Unit(crate::syntax::ast::UnitDecl {
visibility: Visibility::Private,
constness,
name,
dim_type,
definition,
}),
span,
})
}
}