diff options
| author | Mel <einebeere@gmail.com> | 2022-07-27 22:53:35 +0000 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2022-07-27 22:53:35 +0000 |
| commit | d79973cb9df8660fe89810507557f5ba86256f30 (patch) | |
| tree | 201774dae1fa63e6b962e7be9aeea20c033bb5e3 /pkg/lang/parser/stmts.go | |
| parent | 4f23155ca7f8591cae0be6938610386513d24b7f (diff) | |
| download | jinx-d79973cb9df8660fe89810507557f5ba86256f30.tar.zst jinx-d79973cb9df8660fe89810507557f5ba86256f30.zip | |
Parse type declaration statements
Diffstat (limited to 'pkg/lang/parser/stmts.go')
| -rw-r--r-- | pkg/lang/parser/stmts.go | 126 |
1 files changed, 117 insertions, 9 deletions
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) { |
