summaryrefslogtreecommitdiff
path: root/parser
diff options
context:
space:
mode:
authorMarc Vertes <mvertes@free.fr>2026-01-26 18:44:29 +0100
committerMarc Vertes <mvertes@free.fr>2026-01-26 18:44:29 +0100
commitaa5861917ac2543f85bf4cfefbb69cf501d4de41 (patch)
tree94122ea3167c295da822f03d075a085b4f87e9ea /parser
parentece8bdbc45afc3ea626db884ea3283d9a8395ae5 (diff)
fix: improve multi assignHEADmain
Do not consider assign operators in expression handling, they are part of statements. Isolate parsing of left hand side and right hand side in assignments.
Diffstat (limited to 'parser')
-rw-r--r--parser/expr.go15
-rw-r--r--parser/parse.go43
-rw-r--r--parser/tokens.go1
3 files changed, 40 insertions, 19 deletions
diff --git a/parser/expr.go b/parser/expr.go
index 1f15185..d49cfd5 100644
--- a/parser/expr.go
+++ b/parser/expr.go
@@ -62,14 +62,13 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) {
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
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:
+ case lang.Add, lang.And, lang.Equal, lang.Greater, lang.Less, lang.Mul, lang.Not, lang.Sub, lang.Shl, lang.Shr:
if i == 0 || in[i-1].Tok.IsOperator() {
// An operator preceded by an operator or no token is unary.
t.Tok = lang.UnaryOp[t.Tok]
@@ -100,10 +99,6 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) {
ctype = s.Type.String()
}
out = append(out, t)
- if i+1 < len(in) && in[i+1].Tok == lang.Define {
- // Ident is to be assigned next. Define it as a var.
- p.Symbols.Add(symbol.UnsetAddr, t.Str, vm.Value{}, symbol.Var, nil, false)
- }
case lang.ParenBlock:
toks, err := p.parseBlock(t, typeStr)
@@ -145,7 +140,6 @@ 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, false)
out = append(out, newIdent(ctype, t.Pos))
i += n - 1
@@ -159,12 +153,7 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) {
break
}
out = append(out, toks...)
- if i < len(in)-2 && in[i+1].Tok == lang.Assign {
- // 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, newIndexAssign(t.Pos))
- i++
- } else if toks[len(toks)-1].Tok != lang.Slice {
+ if toks[len(toks)-1].Tok != lang.Slice {
ops = append(ops, newIndex(t.Pos))
}
diff --git a/parser/parse.go b/parser/parse.go
index 18613f4..9c1fd13 100644
--- a/parser/parse.go
+++ b/parser/parse.go
@@ -163,11 +163,37 @@ func (p *Parser) parseStmt(in Tokens) (out Tokens, err error) {
func (p *Parser) parseAssign(in Tokens, aindex int) (out Tokens, err error) {
rhs := in[aindex+1:].Split(lang.Comma)
- if len(rhs) == 1 {
- return p.parseExpr(in, "")
- }
lhs := in[:aindex].Split(lang.Comma)
define := in[aindex].Tok == lang.Define
+ if len(rhs) == 1 {
+ for _, e := range lhs {
+ toks, err := p.parseExpr(e, "")
+ if err != nil {
+ return out, err
+ }
+ if define && len(e) == 1 && e[0].Tok == lang.Ident {
+ p.Symbols.Add(symbol.UnsetAddr, e[0].Str, vm.Value{}, symbol.Var, nil, false)
+ }
+ out = append(out, toks...)
+ }
+ toks, err := p.parseExpr(rhs[0], "")
+ if err != nil {
+ return out, err
+ }
+ if out[len(out)-1].Tok == lang.Index {
+ // Map elements cannot be assigned directly, but only through IndexAssign.
+ out = out[:len(out)-1]
+ out = append(out, toks...)
+ out = append(out, newToken(lang.IndexAssign, "", in[aindex].Pos))
+ } else {
+ out = append(out, toks...)
+ if out[len(out)-1].Tok != lang.Range {
+ out = append(out, newToken(in[aindex].Tok, "", in[aindex].Pos))
+ }
+ }
+ return out, err
+ }
+ // Multiple values in right hand side.
for i, e := range rhs {
toks, err := p.parseExpr(lhs[i], "")
if err != nil {
@@ -185,8 +211,15 @@ func (p *Parser) parseAssign(in Tokens, aindex int) (out Tokens, err error) {
if err != nil {
return out, err
}
- out = append(out, toks...)
- out = append(out, newToken(in[aindex].Tok, "", in[aindex].Pos))
+ if out[len(out)-1].Tok == lang.Index {
+ // Map elements cannot be assigned directly, but only through IndexAssign.
+ out = out[:len(out)-1]
+ out = append(out, toks...)
+ out = append(out, newToken(lang.IndexAssign, "", in[aindex].Pos))
+ } else {
+ out = append(out, toks...)
+ out = append(out, newToken(in[aindex].Tok, "", in[aindex].Pos))
+ }
}
return out, err
}
diff --git a/parser/tokens.go b/parser/tokens.go
index 7a241f3..9c4354d 100644
--- a/parser/tokens.go
+++ b/parser/tokens.go
@@ -88,7 +88,6 @@ func newReturn(pos int) Token { return newToken(lang.Ret
func newJumpSetFalse(label string, pos int) Token { return newToken(lang.JumpSetFalse, label, pos) }
func newJumpSetTrue(label string, pos int) Token { return newToken(lang.JumpSetTrue, label, pos) }
func newComposite(pos int) Token { return newToken(lang.Composite, "", pos) }
-func newIndexAssign(pos int) Token { return newToken(lang.IndexAssign, "", pos) }
func newIndex(pos int) Token { return newToken(lang.Index, "", pos) }
func newInt(i, pos int) Token { return newToken(lang.Int, strconv.Itoa(i), pos) }
func newColon(pos int) Token { return newToken(lang.Colon, "", pos) }