conlang: Add constructor expression for structs!

grammar:
- Add new rules `PathLike`, `Structor`, `Fielder`
- Replace Path with PathLike in Primary expressions

cl-ast:
- Add nodes for Structor and Fielder

cl-parser:
- Add branch to path-expression parsing
- Parse Structor bodies

interpret:
- Add TODO
This commit is contained in:
2024-04-20 15:02:16 -05:00
parent efd442bbfa
commit 5341631781
9 changed files with 129 additions and 5 deletions

View File

@@ -91,6 +91,8 @@ pub enum Parsing {
Unary,
UnaryKind,
Index,
Structor,
Fielder,
Call,
Member,
PathExpr,
@@ -190,6 +192,8 @@ impl Display for Parsing {
Parsing::Unary => "a unary expression",
Parsing::UnaryKind => "a unary operator",
Parsing::Index => "an indexing expression",
Parsing::Structor => "a struct constructor expression",
Parsing::Fielder => "a struct field expression",
Parsing::Call => "a call expression",
Parsing::Member => "a member access expression",
Parsing::PathExpr => "a path",

View File

@@ -820,7 +820,7 @@ impl<'t> Parser<'t> {
// Prefix expressions
let mut head = match self.peek_kind(Parsing::Unary)? {
literal_like!() => self.literal()?.into(),
path_like!() => self.path()?.into(),
path_like!() => self.exprkind_pathlike()?,
TokenKind::Punct(Punct::Amp | Punct::AmpAmp) => self.addrof()?.into(),
TokenKind::Punct(Punct::LCurly) => self.block()?.into(),
TokenKind::Punct(Punct::LBrack) => self.exprkind_arraylike()?,
@@ -912,6 +912,38 @@ impl<'t> Parser<'t> {
Ok(head)
}
/// Parses an expression beginning with a [Path] (i.e. [Path] or [Structor])
pub fn exprkind_pathlike(&mut self) -> PResult<ExprKind> {
let head = self.path()?;
Ok(match self.match_op(Punct::Colon, Parsing::PathExpr) {
Ok(_) => ExprKind::Structor(self.structor_body(head)?),
Err(_) => ExprKind::Path(head),
})
}
/// [Structor]Body = `{` ([Fielder] `,`)* [Fielder]? `}`
pub fn structor_body(&mut self, to: Path) -> PResult<Structor> {
let init = delim(
sep(Self::fielder, Punct::Comma, CURLIES.1, Parsing::Structor),
CURLIES,
Parsing::Structor,
)(self)?;
Ok(Structor { to, init })
}
/// [Fielder] = [Identifier] (`:` [Expr])?
pub fn fielder(&mut self) -> PResult<Fielder> {
const PARSING: Parsing = Parsing::Fielder;
Ok(Fielder {
name: self.identifier()?,
init: match self.match_op(Punct::Colon, PARSING) {
Ok(_) => Some(Box::new(self.expr()?)),
Err(_) => None,
},
})
}
/// [Array] = '[' ([Expr] ',')* [Expr]? ']'
///
/// Array and ArrayRef are ambiguous until the second token,