wip: struct, enum
This commit is contained in:
@@ -63,8 +63,16 @@ enum Expr {
|
||||
enum TopLevel {
|
||||
TopLetDecl(id~ : String, type_~ : Type?, expr~ : Expr)
|
||||
TopFn(Function)
|
||||
Struct(Struct)
|
||||
Enum(Enum)
|
||||
Struct(
|
||||
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 {
|
||||
let program = []
|
||||
@@ -131,18 +224,26 @@ pub fn parse_program(tokens : Array[Token]) -> Program raise ParseError {
|
||||
)
|
||||
}
|
||||
let (expr, rest) = parse_expr(rest)
|
||||
program.push(TopLetDecl(id, type_, expr))
|
||||
program.push(TopLetDecl(id~, type_=Some(type_), expr~))
|
||||
continue rest
|
||||
}
|
||||
[Let, LowerIdentifier(id) | UpperIdentifier(id), Assign, .. rest] => {
|
||||
let (expr, rest) = parse_expr(rest)
|
||||
program.push(TopLetDecl(id, None, expr))
|
||||
program.push(TopLetDecl(id~, type_=None, expr~))
|
||||
continue rest
|
||||
}
|
||||
[Fn, LowerIdentifier("main"), ..] => ...
|
||||
[Fn, ..] => ...
|
||||
[Struct, ..] => ...
|
||||
[Enum, ..] => ...
|
||||
[Struct, ..] as tokens => {
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user