From d79973cb9df8660fe89810507557f5ba86256f30 Mon Sep 17 00:00:00 2001 From: Mel Date: Wed, 27 Jul 2022 22:53:35 +0000 Subject: Parse type declaration statements --- pkg/lang/parser/stmts.go | 126 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 117 insertions(+), 9 deletions(-) (limited to 'pkg/lang/parser/stmts.go') diff --git a/pkg/lang/parser/stmts.go b/pkg/lang/parser/stmts.go index 7d10e61..a0bba28 100644 --- a/pkg/lang/parser/stmts.go +++ b/pkg/lang/parser/stmts.go @@ -54,11 +54,15 @@ func (p *Parser) parseFnDeclStmt() (ast.Stmt, error) { return ast.Stmt{}, err } - params, err := p.parseFnParams() + hasThis, params, err := p.parseFnParams() if err != nil { return ast.Stmt{}, err } + if hasThis { + return ast.Stmt{}, fmt.Errorf("function cannot have 'this' as a parameter") + } + block, err := p.parseBlock() if err != nil { return ast.Stmt{}, err @@ -75,20 +79,36 @@ func (p *Parser) parseFnDeclStmt() (ast.Stmt, error) { }, nil } -func (p *Parser) parseFnParams() ([]ast.IdentNode, error) { - // FnParams = "(" ( IDENT ("," IDENT)* )? ")" +func (p *Parser) parseFnParams() (bool, []ast.IdentNode, error) { + // FnParams = "(" ( (IDENT | "this") ("," IDENT)* )? ")" if _, err := p.expect(token.LParen); err != nil { - return nil, err + return false, nil, err } + hasThis := false params := []ast.IdentNode{} if p.peek().Kind != token.RParen { for { + if p.peek().Kind == token.KwThis { + hasThis = true + if _, err := p.expect(token.KwThis); err != nil { + return false, nil, err + } + + if p.peek().Kind != token.Comma { + break + } else { + if _, err := p.expect(token.Comma); err != nil { + return false, nil, err + } + } + } + param, err := p.parseIdent() if err != nil { - return nil, err + return false, nil, err } params = append(params, param) @@ -98,20 +118,108 @@ func (p *Parser) parseFnParams() ([]ast.IdentNode, error) { } if _, err := p.expect(token.Comma); err != nil { - return nil, err + return false, nil, err } } } if _, err := p.expect(token.RParen); err != nil { - return nil, err + return false, nil, err } - return params, nil + return hasThis, params, nil } func (p *Parser) parseTypeDeclStmt() (ast.Stmt, error) { - panic("not implemented") + // TypeDeclStmt = "type" IDENT "{" (FnDeclStmt)* "}" + + typeTok, err := p.expect(token.KwType) + if err != nil { + return ast.Stmt{}, err + } + + name, err := p.parseIdent() + if err != nil { + return ast.Stmt{}, err + } + + if _, err := p.expect(token.LBrace); err != nil { + return ast.Stmt{}, err + } + + if err := p.parseStmtEnd(); err != nil { + return ast.Stmt{}, err + } + + methods := make([]ast.TypeMethodNode, 0) + + for p.peek().Kind != token.RBrace { + node, err := p.parseTypeMethodNode() + if err != nil { + return ast.Stmt{}, err + } + + methods = append(methods, node) + + if err := p.parseStmtEnd(); err != nil { + return ast.Stmt{}, err + } + } + + if _, err := p.expect(token.RBrace); err != nil { + return ast.Stmt{}, err + } + + return ast.Stmt{ + At: typeTok.At, + Kind: ast.StmtKindTypeDecl, + Value: ast.StmtTypeDecl{ + Name: name, + Methods: methods, + }, + }, nil + +} + +func (p *Parser) parseTypeMethodNode() (ast.TypeMethodNode, error) { + var err error + + startTok := p.peek() + isConstructor := false + name := ast.IdentNode{} + + if p.peek().Kind == token.KwFn { + startTok, err = p.expect(token.KwFn) + if err != nil { + return ast.TypeMethodNode{}, err + } + + name, err = p.parseIdent() + if err != nil { + return ast.TypeMethodNode{}, err + } + } else { + isConstructor = true + } + + hasThis, params, err := p.parseFnParams() + if err != nil { + return ast.TypeMethodNode{}, err + } + + block, err := p.parseBlock() + if err != nil { + return ast.TypeMethodNode{}, err + } + + return ast.TypeMethodNode{ + At: startTok.At, + HasThis: hasThis, + IsConstructor: isConstructor, + Name: name, + Args: params, + Body: block, + }, nil } func (p *Parser) parseVarDeclStmt() (ast.Stmt, error) { -- cgit 1.4.1