From ad820abce5588b09ba7034f97de7eea71417ff5e Mon Sep 17 00:00:00 2001 From: Christopher Seven Phiri Date: Thu, 15 Aug 2024 12:28:18 +0200 Subject: [PATCH] can parse classes --- src/ast/class.go | 31 +++++++++++++++++++++++++++++++ src/parser/class.go | 24 ++++++++++++++++++++++++ src/parser/parser.go | 1 + src/parser/parser_test.go | 18 ++++++++++-------- src/token/token.go | 2 ++ 5 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 src/ast/class.go create mode 100644 src/parser/class.go diff --git a/src/ast/class.go b/src/ast/class.go new file mode 100644 index 0000000..b9d159d --- /dev/null +++ b/src/ast/class.go @@ -0,0 +1,31 @@ +package ast + +import ( + "bytes" + + "github.com/sevenreup/chewa/src/token" +) + +type ClassStatement struct { + Expression + Token token.Token + Name *Identifier + Super *Identifier + Body *BlockStatement +} + +func (class *ClassStatement) expressionNode() {} +func (class *ClassStatement) TokenLiteral() string { return class.Token.Literal } +func (class *ClassStatement) String() string { + var out bytes.Buffer + out.WriteString("ndondomeko ") + out.WriteString(class.Name.String()) + if class.Super != nil { + out.WriteString(" ndi ") + out.WriteString(class.Super.String()) + } + out.WriteString(" {\n") + out.WriteString(class.Body.String()) + out.WriteString("\n}") + return out.String() +} diff --git a/src/parser/class.go b/src/parser/class.go new file mode 100644 index 0000000..0cd09d9 --- /dev/null +++ b/src/parser/class.go @@ -0,0 +1,24 @@ +package parser + +import ( + "github.com/sevenreup/chewa/src/ast" + "github.com/sevenreup/chewa/src/token" +) + +func (p *Parser) classStatement() ast.Expression { + class := &ast.ClassStatement{Token: p.curToken} + + p.nextToken() + + class.Name = &ast.Identifier{Token: p.curToken, Value: p.curToken.Literal} + + // TODO: Implement inheritance + + if !p.expectPeek(token.OPENING_BRACE) { + return nil + } + + class.Body = p.parseBlockStatement() + + return class +} diff --git a/src/parser/parser.go b/src/parser/parser.go index 1b5142a..113491f 100644 --- a/src/parser/parser.go +++ b/src/parser/parser.go @@ -85,6 +85,7 @@ func New(l *lexer.Lexer) *Parser { p.registerPrefix(token.FOR, p.parseForExpression) p.registerPrefix(token.WHILE, p.parseWhileExpression) p.registerPrefix(token.FUNCTION, p.parseFunctionLiteral) + p.registerPrefix(token.CLASS, p.classStatement) p.registerPrefix(token.OPENING_BRACE, p.mapLiteral) p.registerPrefix(token.OPENING_PAREN, p.parseGroupedExpression) diff --git a/src/parser/parser_test.go b/src/parser/parser_test.go index 9eb340e..e1c5da0 100644 --- a/src/parser/parser_test.go +++ b/src/parser/parser_test.go @@ -1346,24 +1346,26 @@ func TestParsingHashLiteralsWithExpressions(t *testing.T) { func TestParsingClassExpressions(t *testing.T) { input := ` - kalasi Person { + kalasi Person { + nambala age = 5; }` l := lexer.New([]byte(input)) p := New(l) program := p.ParseProgram() checkParserErrors(t, p) - stmt := program.Statements[0].(*ast.ClassStatement) - if stmt.Name.Value != "Person" { - t.Fatalf("stmt.Name.Value not 'Person'. got=%q", stmt.Name.Value) + stmt := program.Statements[0].(*ast.ExpressionStatement) + classStatement := stmt.Expression.(*ast.ClassStatement) + if classStatement.Name.Value != "Person" { + t.Fatalf("stmt.Name.Value not 'Person'. got=%q", classStatement.Name.Value) } - if len(stmt.Body.Statements) != 1 { + if len(classStatement.Body.Statements) != 1 { t.Fatalf("stmt.Body.Statements does not contain 1 statements. got=%d\n", - len(stmt.Body.Statements)) + len(classStatement.Body.Statements)) } - bodyStmt, ok := stmt.Body.Statements[0].(*ast.VariableDeclarationStatement) + bodyStmt, ok := classStatement.Body.Statements[0].(*ast.VariableDeclarationStatement) if !ok { t.Fatalf("stmt.Body.Statements[0] is not ast.VariableDeclarationStatement. got=%T", - stmt.Body.Statements[0]) + classStatement.Body.Statements[0]) } if bodyStmt.Identifier.Value != "age" { t.Fatalf("bodyStmt.Identifier.Value not 'age'. got=%s", bodyStmt.Identifier.Value) diff --git a/src/token/token.go b/src/token/token.go index 3daaac0..0272162 100644 --- a/src/token/token.go +++ b/src/token/token.go @@ -63,6 +63,7 @@ const ( FOR = "FOR" WHILE = "WHILE" MAP = "MAP" + CLASS = "CLASS" ) type Position struct { @@ -89,6 +90,7 @@ var keywords = map[string]TokenType{ "za": FOR, "pamene": WHILE, "mgwirizano": MAP, + "kalasi": CLASS, } var variableTypes = map[TokenType]TokenType{