[fine] WIP: Classes

This commit is contained in:
John Doty 2024-01-20 08:56:53 -08:00
parent e6c96fde38
commit 0ee89bf26b
7 changed files with 370 additions and 59 deletions

View file

@ -125,8 +125,10 @@ pub enum TreeKind {
BinaryExpression,
Block,
CallExpression,
ClassDecl,
ConditionalExpression,
ExpressionStatement,
FieldDecl,
File,
ForStatement,
FunctionDecl,
@ -145,6 +147,9 @@ pub enum TreeKind {
TypeParameter,
TypeParameterList,
UnaryExpression,
FieldList,
NewObjectExpression,
FieldValue,
}
pub struct Tree<'a> {
@ -183,14 +188,17 @@ impl<'a> Tree<'a> {
})
}
pub fn children_of_kind<'b>(
&'b self,
s: &'b SyntaxTree,
kind: TreeKind,
) -> impl Iterator<Item = TreeRef> + 'b {
self.child_trees()
.filter_map(move |t| if s[t].kind == kind { Some(t) } else { None })
}
pub fn child_of_kind(&self, s: &SyntaxTree, kind: TreeKind) -> Option<TreeRef> {
self.children
.iter()
.filter_map(|c| match c {
Child::Tree(t) => Some(*t),
_ => None,
})
.find(|c| s[*c].kind == kind)
self.children_of_kind(&s, kind).next()
}
pub fn child_tree_of_kind<'b>(
@ -400,6 +408,10 @@ impl<'a> CParser<'a> {
self.error(error);
}
fn expect_start(&mut self, kind: TokenKind) {
assert!(self.eat(kind));
}
fn advance_with_error<T>(&mut self, error: T) -> MarkClosed
where
T: Into<String>,
@ -498,6 +510,7 @@ fn file(p: &mut CParser) {
while !p.eof() {
match p.peek() {
TokenKind::Fun => function(p),
TokenKind::Class => class(p),
_ => statement(p),
}
}
@ -505,10 +518,9 @@ fn file(p: &mut CParser) {
}
fn function(p: &mut CParser) {
assert!(p.at(TokenKind::Fun));
let m = p.start();
p.expect(TokenKind::Fun, "expected a function to start with 'fun'");
p.expect_start(TokenKind::Fun);
p.expect(TokenKind::Identifier, "expected a function name");
if p.at(TokenKind::LeftParen) {
param_list(p);
@ -523,11 +535,40 @@ fn function(p: &mut CParser) {
p.end(m, TreeKind::FunctionDecl);
}
fn param_list(p: &mut CParser) {
assert!(p.at(TokenKind::LeftParen));
fn class(p: &mut CParser) {
let m = p.start();
p.expect(TokenKind::LeftParen, "expect '(' to start a parameter list");
p.expect_start(TokenKind::Class);
p.expect(TokenKind::Identifier, "expected a class name");
if p.eat(TokenKind::LeftBrace) {
while !p.at(TokenKind::RightBrace) && !p.eof() {
field_decl(p);
}
}
p.expect(TokenKind::RightBrace, "expected a class to end with a '}'");
p.end(m, TreeKind::ClassDecl);
}
fn field_decl(p: &mut CParser) {
let m = p.start();
p.expect(TokenKind::Identifier, "expected a field name");
if p.eat(TokenKind::Colon) {
type_expr(p);
}
p.expect(
TokenKind::Semicolon,
"expect a ';' after field declarations",
);
p.end(m, TreeKind::FieldDecl);
}
fn param_list(p: &mut CParser) {
let m = p.start();
p.expect_start(TokenKind::LeftParen);
while !p.at(TokenKind::RightParen) && !p.eof() {
if p.at(TokenKind::Identifier) {
parameter(p);
@ -541,12 +582,9 @@ fn param_list(p: &mut CParser) {
}
fn parameter(p: &mut CParser) {
assert!(p.at(TokenKind::Identifier));
let m = p.start();
p.expect(
TokenKind::Identifier,
"expected an identifier for a parameter name",
);
p.expect_start(TokenKind::Identifier);
if p.eat(TokenKind::Colon) {
type_expr(p);
}
@ -558,13 +596,9 @@ fn parameter(p: &mut CParser) {
}
fn return_type(p: &mut CParser) {
assert!(p.at(TokenKind::Arrow));
let m = p.start();
p.expect(
TokenKind::Arrow,
"function return type starts with an arrow",
);
p.expect_start(TokenKind::Arrow);
type_expr(p);
p.end(m, TreeKind::ReturnType);
@ -584,10 +618,9 @@ fn type_expr(p: &mut CParser) {
}
fn type_parameter_list(p: &mut CParser) {
assert!(p.at(TokenKind::Less));
let m = p.start();
p.expect(TokenKind::Less, "expected < to start type parameter list");
p.expect_start(TokenKind::Less);
while !p.at(TokenKind::Greater) && !p.eof() {
if p.at(TokenKind::Identifier) {
type_parameter(p);
@ -613,10 +646,9 @@ fn type_parameter(p: &mut CParser) {
}
fn block(p: &mut CParser) {
assert!(p.at(TokenKind::LeftBrace));
let m = p.start();
p.expect(TokenKind::LeftBrace, "expect '{' to start a block");
p.expect_start(TokenKind::LeftBrace);
while !p.at(TokenKind::RightBrace) && !p.eof() {
statement(p);
}
@ -650,10 +682,9 @@ fn statement_if(p: &mut CParser) {
}
fn statement_let(p: &mut CParser) {
assert!(p.at(TokenKind::Let));
let m = p.start();
p.expect(TokenKind::Let, "expect 'let' to start a let statement");
p.expect_start(TokenKind::Let);
p.expect(TokenKind::Identifier, "expected a name for the variable");
p.expect(TokenKind::Equal, "expected a '=' after the variable name");
expression(p);
@ -665,13 +696,9 @@ fn statement_let(p: &mut CParser) {
}
fn statement_return(p: &mut CParser) {
assert!(p.at(TokenKind::Return));
let m = p.start();
p.expect(
TokenKind::Return,
"expect 'return' to start a return statement",
);
p.expect_start(TokenKind::Return);
expression(p);
if !p.at(TokenKind::RightBrace) {
p.expect(TokenKind::Semicolon, "expect ';' to end a return statement");
@ -681,10 +708,9 @@ fn statement_return(p: &mut CParser) {
}
fn statement_for(p: &mut CParser) {
assert!(p.at(TokenKind::For));
let m = p.start();
p.expect(TokenKind::For, "expect a for to start a for loop");
p.expect_start(TokenKind::For);
p.expect(
TokenKind::Identifier,
"expected an identifier for the loop variable",
@ -771,13 +797,9 @@ fn expression_with_power(p: &mut CParser, minimum_power: u8) {
}
fn argument_list(p: &mut CParser) {
assert!(p.at(TokenKind::LeftParen));
let m = p.start();
p.expect(
TokenKind::LeftParen,
"expect an argument list to start with '('",
);
p.expect_start(TokenKind::LeftParen);
while !p.at(TokenKind::RightParen) && !p.eof() {
argument(p);
}
@ -818,6 +840,8 @@ fn prefix_expression(p: &mut CParser) -> MarkClosed {
TokenKind::LeftBracket => list_constructor(p),
TokenKind::New => object_constructor(p),
_ => p.advance_with_error("expected an expression"),
}
}
@ -829,10 +853,9 @@ fn literal(p: &mut CParser) -> MarkClosed {
}
fn grouping(p: &mut CParser) -> MarkClosed {
assert!(p.at(TokenKind::LeftParen));
let m = p.start();
p.expect(TokenKind::LeftParen, "expected '(' to start grouping");
p.expect_start(TokenKind::LeftParen);
expression(p);
p.expect(TokenKind::RightParen, "unmatched parentheses in expression");
@ -849,10 +872,9 @@ fn unary(p: &mut CParser) -> MarkClosed {
}
fn conditional(p: &mut CParser) -> MarkClosed {
assert!(p.at(TokenKind::If));
let m = p.start();
p.expect(TokenKind::If, "expected conditional to start with 'if'");
p.expect_start(TokenKind::If);
expression(p);
block(p);
if p.eat(TokenKind::Else) {
@ -877,13 +899,9 @@ fn identifier(p: &mut CParser) -> MarkClosed {
}
fn list_constructor(p: &mut CParser) -> MarkClosed {
assert!(p.at(TokenKind::LeftBracket));
let m = p.start();
p.expect(
TokenKind::LeftBracket,
"expect a list constructor to start with [",
);
p.expect_start(TokenKind::LeftBracket);
while !p.at(TokenKind::RightBracket) && !p.eof() {
list_constructor_element(p);
}
@ -909,6 +927,49 @@ fn list_constructor_element(p: &mut CParser) {
p.end(m, TreeKind::ListConstructorElement);
}
fn object_constructor(p: &mut CParser) -> MarkClosed {
let m = p.start();
p.expect_start(TokenKind::New);
type_expr(p);
if p.at(TokenKind::LeftBrace) {
field_list(p);
} else {
p.error("expected a '{' to start the field list after the class type");
}
p.end(m, TreeKind::NewObjectExpression)
}
fn field_list(p: &mut CParser) {
let m = p.start();
p.expect_start(TokenKind::LeftBrace);
while !p.at(TokenKind::RightBrace) && !p.eof() {
field_value(p);
}
p.expect(
TokenKind::RightBrace,
"expected the field list to end with '}'",
);
p.end(m, TreeKind::FieldList);
}
fn field_value(p: &mut CParser) {
let m = p.start();
p.expect(TokenKind::Identifier, "expected a field name");
if p.eat(TokenKind::Colon) {
expression(p);
}
if !p.at(TokenKind::RightBrace) {
p.expect(TokenKind::Comma, "expect a ',' between fields");
}
p.end(m, TreeKind::FieldValue);
}
#[cfg(test)]
mod tests {
use super::*;