wip: struct, enum

This commit is contained in:
2025-10-04 14:30:33 +08:00
parent 582f22eb33
commit 7ac0070589

View File

@@ -63,8 +63,16 @@ enum Expr {
enum TopLevel { enum TopLevel {
TopLetDecl(id~ : String, type_~ : Type?, expr~ : Expr) TopLetDecl(id~ : String, type_~ : Type?, expr~ : Expr)
TopFn(Function) TopFn(Function)
Struct(Struct) Struct(
Enum(Enum) id~ : String,
user_defined_type~ : Type?,
fields~ : Array[(String, Type)]
)
Enum(
id~ : String,
user_defined_type~ : Type?,
variants~ : Array[(String, Array[Type])]
)
} }
///| ///|
@@ -118,6 +126,91 @@ fn parse_type(
} }
} }
///|
fn parse_struct(
tokens : ArrayView[Token],
) -> (TopLevel, ArrayView[Token]) raise ParseError {
guard tokens is [Struct, UpperIdentifier(id), .. rest] else {
raise ParseError("Expected 'struct' followed by struct name")
}
let (user_defined_type, rest) = if rest
is [LBracket, UpperIdentifier(type_), RBracket, .. r] {
(Some(UserDefined(type_)), r)
} else {
(None, rest)
}
guard rest is [LCurlyBracket, .. rest] else {
raise ParseError("Expected '{' after struct name")
}
let fields = []
loop rest {
[RCurlyBracket, .. r] => (Struct(id~, user_defined_type~, fields~), r)
[UpperIdentifier(field_name) | LowerIdentifier(field_name), Colon, .. r] => {
let (field_type, r) = parse_type(r)
fields.push((field_name, field_type))
match r {
[Semicolon, .. r] => continue r
[RCurlyBracket, ..] => continue r
_ => raise ParseError("Expected ';' or '}' after struct field")
}
}
_ => raise ParseError("Unexpected token in struct field list")
}
}
///|
fn parse_enum(
tokens : ArrayView[Token],
) -> (TopLevel, ArrayView[Token]) raise ParseError {
guard tokens is [Enum, UpperIdentifier(id), .. rest] else {
raise ParseError("Expected 'enum' followed by enum name")
}
let (user_defined_type, rest) = if rest
is [LBracket, UpperIdentifier(type_), RBracket, .. r] {
(Some(UserDefined(type_)), r)
} else {
(None, rest)
}
guard rest is [LCurlyBracket, .. rest] else {
raise ParseError("Expected '{' after enum name")
}
let variants = []
loop rest {
[RCurlyBracket, .. r] => (Enum(id~, user_defined_type~, variants~), r)
[UpperIdentifier(variant_name), .. r] => {
let variant_types = []
if r is [LParen, .. r] {
loop r {
[RParen, ..] => break
r => {
let (variant_type, r) = parse_type(r)
variant_types.push(variant_type)
match r {
[Comma, RParen, ..] =>
raise ParseError(
"Trailing comma in enum variant type list is not allowed",
)
[Comma, .. r] => continue r
[RParen, ..] => break
_ =>
raise ParseError(
"Expected ',' or ')' in enum variant type list",
)
}
}
}
}
variants.push((variant_name, variant_types))
match r {
[Semicolon, .. r] => continue r
[RCurlyBracket, ..] => continue r
_ => raise ParseError("Expected ';' or '}' after enum variant")
}
}
_ => raise ParseError("Unexpected token in enum variant list")
}
}
///| ///|
pub fn parse_program(tokens : Array[Token]) -> Program raise ParseError { pub fn parse_program(tokens : Array[Token]) -> Program raise ParseError {
let program = [] let program = []
@@ -131,18 +224,26 @@ pub fn parse_program(tokens : Array[Token]) -> Program raise ParseError {
) )
} }
let (expr, rest) = parse_expr(rest) let (expr, rest) = parse_expr(rest)
program.push(TopLetDecl(id, type_, expr)) program.push(TopLetDecl(id~, type_=Some(type_), expr~))
continue rest continue rest
} }
[Let, LowerIdentifier(id) | UpperIdentifier(id), Assign, .. rest] => { [Let, LowerIdentifier(id) | UpperIdentifier(id), Assign, .. rest] => {
let (expr, rest) = parse_expr(rest) let (expr, rest) = parse_expr(rest)
program.push(TopLetDecl(id, None, expr)) program.push(TopLetDecl(id~, type_=None, expr~))
continue rest continue rest
} }
[Fn, LowerIdentifier("main"), ..] => ... [Fn, LowerIdentifier("main"), ..] => ...
[Fn, ..] => ... [Fn, ..] => ...
[Struct, ..] => ... [Struct, ..] as tokens => {
[Enum, ..] => ... let (struct_, rest) = parse_struct(tokens)
program.push(struct_)
continue rest
}
[Enum, ..] as tokens => {
let (enum_, rest) = parse_enum(tokens)
program.push(enum_)
continue rest
}
_ => raise ParseError("Unexpected token at top level") _ => raise ParseError("Unexpected token at top level")
} }
} }