diff options
| author | Marc Vertes <mvertes@free.fr> | 2026-01-21 19:26:42 +0100 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2026-01-21 19:26:42 +0100 |
| commit | c922c797204069f42a7abf88500c5708f68a8e43 (patch) | |
| tree | a0379dc6f6992f0ba077b028dfd4b031dd674d98 /parser/expr.go | |
| parent | ee9397bc031dc33e4f735b3331643bbf60a0d17a (diff) | |
feat: add support for range clause and iterators
- vm: added Pull, Next and Stop instructions, to implement iterators
- lang: add Range, Next and Stop tokens
- parser: handle range clause. Still naive and incomplete.
- comp: generate iterator instructions from range clause.
Work in progress. Only initial support for slices. Many more tests
and combinations needed, but the main pattern is there now.
Diffstat (limited to 'parser/expr.go')
| -rw-r--r-- | parser/expr.go | 52 |
1 files changed, 27 insertions, 25 deletions
diff --git a/parser/expr.go b/parser/expr.go index 1944827..149b5e2 100644 --- a/parser/expr.go +++ b/parser/expr.go @@ -17,9 +17,9 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { var ops Tokens var ctype string - popop := func() (t scanner.Token) { + popop := func() scanner.Token { l := len(ops) - 1 - t = ops[l] + t := ops[l] ops = ops[:l] if t.Tok.IsLogicalOp() { t.Tok = lang.Label // Implement conditional branching directly. @@ -27,6 +27,15 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { return t } + // addop adds an operator to the operator stack. + addop := func(t scanner.Token) { + // Operators on stack with a lower precedence are poped out and output first. + for len(ops) > 0 && p.precedence(t) < p.precedence(ops[len(ops)-1]) { + out = append(out, popop()) + } + ops = append(ops, t) + } + lin := len(in) for i := 0; i < lin; i++ { switch t := in[i]; t.Tok { @@ -47,18 +56,19 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { case lang.Period: // TODO: fail if next is not an ident. t.Str += in[i+1].Str // Hardwire selector argument. - for len(ops) > 0 && p.precedence(t) < p.precedence(ops[len(ops)-1]) { - out = append(out, popop()) - } - ops = append(ops, t) + addop(t) i++ // Skip over next ident. + case lang.Next: + out = append(out, t) + + case lang.Range: + ops = ops[:len(ops)-1] // Suppress previous assign or define. + addop(t) + case lang.Colon: t.Str = typeStr - for len(ops) > 0 && p.precedence(t) < p.precedence(ops[len(ops)-1]) { - out = append(out, popop()) - } - ops = append(ops, t) + addop(t) case lang.Add, lang.And, lang.Assign, lang.Define, lang.Equal, lang.Greater, lang.Less, lang.Mul, lang.Not, lang.Sub, lang.Shl, lang.Shr: if i == 0 || in[i-1].Tok.IsOperator() { @@ -66,30 +76,21 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { t.Tok = lang.UnaryOp[t.Tok] // FIXME: parsetype for composite if & or * } - for len(ops) > 0 && p.precedence(t) < p.precedence(ops[len(ops)-1]) { - out = append(out, popop()) - } - ops = append(ops, t) + addop(t) case lang.Land: - for len(ops) > 0 && p.precedence(t) < p.precedence(ops[len(ops)-1]) { - out = append(out, popop()) - } + addop(t) xp := strconv.Itoa(p.labelCount[p.scope]) p.labelCount[p.scope]++ out = append(out, scanner.Token{Tok: lang.JumpSetFalse, Str: p.scope + "x" + xp}) - t.Str = p.scope + "x" + xp - ops = append(ops, t) + ops[len(ops)-1].Str = p.scope + "x" + xp case lang.Lor: - for len(ops) > 0 && p.precedence(t) < p.precedence(ops[len(ops)-1]) { - out = append(out, popop()) - } + addop(t) xp := strconv.Itoa(p.labelCount[p.scope]) p.labelCount[p.scope]++ out = append(out, scanner.Token{Tok: lang.JumpSetTrue, Str: p.scope + "x" + xp}) - t.Str = p.scope + "x" + xp - ops = append(ops, t) + ops[len(ops)-1].Str = p.scope + "x" + xp case lang.Ident: s, sc, ok := p.Symbols.Get(t.Str, p.scope) @@ -145,7 +146,8 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { return out, err } ctype = typ.String() - p.Symbols.Add(symbol.UnsetAddr, ctype, vm.NewValue(typ), symbol.Type, typ, p.funcScope != "") + // p.Symbols.Add(symbol.UnsetAddr, ctype, vm.NewValue(typ), symbol.Type, typ, p.funcScope != "") + p.Symbols.Add(symbol.UnsetAddr, ctype, vm.NewValue(typ), symbol.Type, typ, false) out = append(out, scanner.Token{Tok: lang.Ident, Pos: t.Pos, Str: ctype}) i += n - 1 break |
