From 323d82a7f235f78d56e26677c7ba54470caea08e Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Thu, 12 Oct 2023 17:08:24 +0200 Subject: parser: implement 'for' statement --- parser/parse.go | 54 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) (limited to 'parser/parse.go') diff --git a/parser/parse.go b/parser/parse.go index 5f0b643..901ac7d 100644 --- a/parser/parse.go +++ b/parser/parse.go @@ -102,6 +102,8 @@ func (p *Parser) ParseStmt(in Tokens) (out Tokens, err error) { return nil, nil } switch t := in[0]; t.Id { + case lang.For: + return p.ParseFor(in) case lang.Func: return p.ParseFunc(in) case lang.If: @@ -113,6 +115,53 @@ func (p *Parser) ParseStmt(in Tokens) (out Tokens, err error) { } } +func (p *Parser) ParseFor(in Tokens) (out Tokens, err error) { + // TODO: detect invalid code. + fc := strconv.Itoa(p.labelCount[p.scope+p.fname]) + prefix := p.fname + "_for" + fc + p.labelCount[p.scope+p.fname]++ + var init, cond, post, body Tokens + pre := in[1 : len(in)-1].Split(lang.Semicolon) + switch len(pre) { + case 1: + cond = pre[0] + case 3: + init, cond, post = pre[0], pre[1], pre[2] + default: + return nil, fmt.Errorf("invalild for statement") + } + p.pushScope("for" + fc) + defer p.popScope() + if len(init) > 0 { + if init, err = p.ParseStmt(init); err != nil { + return nil, err + } + out = init + } + out = append(out, scanner.Token{Id: lang.Label, Str: prefix + "b"}) + if len(cond) > 0 { + if cond, err = p.ParseExpr(cond); err != nil { + return nil, err + } + out = append(out, cond...) + out = append(out, scanner.Token{Id: lang.JumpFalse, Str: "JumpFalse " + prefix + "e"}) + } + if body, err = p.Parse(in[len(in)-1].Block()); err != nil { + return nil, err + } + out = append(out, body...) + if len(post) > 0 { + if post, err = p.ParseStmt(post); err != nil { + return nil, err + } + out = append(out, post...) + } + out = append(out, + scanner.Token{Id: lang.Goto, Str: "goto " + prefix + "b"}, + scanner.Token{Id: lang.Label, Str: prefix + "e"}) + return out, err +} + func (p *Parser) ParseFunc(in Tokens) (out Tokens, err error) { // TODO: handle anonymous functions (no function name) // TODO: handle receiver (methods) @@ -182,13 +231,11 @@ func (p *Parser) ParseIf(in Tokens) (out Tokens, err error) { if err != nil { return nil, err } - //pre := append(Tokens{{Id: lang.Label, Str: prefix + "_b" + ssc}}, blockout...) if sc > 0 { pre = append(pre, scanner.Token{Id: lang.Goto, Str: "goto " + prefix + "_e0"}) } pre = append(pre, scanner.Token{Id: lang.Label, Str: prefix + "_e" + ssc}) out = append(pre, out...) - i-- ifp := in[:i].LastIndex(lang.If) @@ -198,7 +245,6 @@ func (p *Parser) ParseIf(in Tokens) (out Tokens, err error) { ssc = strconv.Itoa(sc) continue } - pre = Tokens{} var init, cond Tokens initcond := in[ifp+1 : i+1] @@ -227,8 +273,6 @@ func (p *Parser) ParseIf(in Tokens) (out Tokens, err error) { sc++ ssc = strconv.Itoa(sc) } - log.Println("prefix:", prefix) - log.Println("if tokens:", out) return out, err } -- cgit v1.2.3