diff options
| author | Marc Vertes <mvertes@free.fr> | 2026-01-16 12:30:31 +0100 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2026-01-16 12:30:31 +0100 |
| commit | ee9397bc031dc33e4f735b3331643bbf60a0d17a (patch) | |
| tree | 42087d58e916904af3e70de6171e0f1c9c894d8f /parser | |
| parent | 31e3793202402fda21905027c18ebfa5c8d8c832 (diff) | |
feat: handle slice expressions
Diffstat (limited to 'parser')
| -rw-r--r-- | parser/expr.go | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/parser/expr.go b/parser/expr.go index 5a1c670..1944827 100644 --- a/parser/expr.go +++ b/parser/expr.go @@ -1,6 +1,7 @@ package parser import ( + "errors" "log" "strconv" @@ -105,7 +106,7 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { } case lang.ParenBlock: - toks, err := p.parseExprStr(t.Block(), typeStr) + toks, err := p.parseBlock(t, typeStr) if err != nil { return out, err } @@ -149,17 +150,20 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { i += n - 1 break } - toks, err := p.parseExprStr(t.Block(), typeStr) + toks, err := p.parseBlock(t, typeStr) if err != nil { return out, err } + if len(toks) == 0 { + break + } out = append(out, toks...) if i < len(in)-2 && in[i+1].Tok == lang.Assign { - // A bracket block followed by assign implies a MapAssing token, + // A bracket block followed by assign implies an IndexAssign token, // as assignement to a map element cannot be implemented through a normal Assign. - ops = append(ops, scanner.Token{Tok: lang.MapAssign, Pos: t.Pos}) + ops = append(ops, scanner.Token{Tok: lang.IndexAssign, Pos: t.Pos}) i++ - } else { + } else if toks[len(toks)-1].Tok != lang.Slice { ops = append(ops, scanner.Token{Tok: lang.Index, Pos: t.Pos}) } @@ -225,17 +229,44 @@ func (p *Parser) parseComposite(s, typ string) (Tokens, error) { return result, nil } -func (p *Parser) parseExprStr(s, typ string) (tokens Tokens, err error) { - if tokens, err = p.Scan(s, false); err != nil { +func (p *Parser) parseBlock(t scanner.Token, typ string) (result Tokens, err error) { + tokens, err := p.Scan(t.Block(), false) + if err != nil { return tokens, err } - var result Tokens + if tokens.Index(lang.Colon) >= 0 { + // Slice expression, a[low : high] or a[low : high : max] + for i, sub := range tokens.Split(lang.Colon) { + if i > 2 { + return nil, errors.New("expected ']', found ':'") + } + if len(sub) == 0 { + if i == 0 { + result = append(result, scanner.Token{Tok: lang.Int, Str: "0"}) + continue + } else if i == 2 { + return nil, errors.New("final index required in 3-index slice") + } + result = append(result, scanner.Token{Tok: lang.Len, Beg: 1}) + continue + } + toks, err := p.parseExpr(sub, typ) + if err != nil { + return result, err + } + result = append(result, toks...) + } + result = append(result, scanner.Token{Tok: lang.Slice, Pos: t.Pos}) + return result, err + } + for _, sub := range tokens.Split(lang.Comma) { toks, err := p.parseExpr(sub, typ) if err != nil { return result, err } + // Inverse sub list order (func call parameters) result = append(toks, result...) } |
