diff options
| author | Marc Vertes <mvertes@free.fr> | 2023-11-03 19:05:14 +0100 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2023-11-03 19:05:14 +0100 |
| commit | 6e2349e875e77d8af8b7d6f00f718db6813b40c1 (patch) | |
| tree | 74b476bc508264378fcb11bc7849658d76955f68 /parser/parse.go | |
| parent | 20d331813cf05f42961f0f6df531c2880f753a07 (diff) | |
feat: add support for control flow operators in expressions
Logical operators `&&` (and), `||` (or) are now parsed in expressions.
The control flow tokens (labels, conditional jumps) are added
accordingly.
Diffstat (limited to 'parser/parse.go')
| -rw-r--r-- | parser/parse.go | 110 |
1 files changed, 0 insertions, 110 deletions
diff --git a/parser/parse.go b/parser/parse.go index 757468c..fb8ae2c 100644 --- a/parser/parse.go +++ b/parser/parse.go @@ -441,116 +441,6 @@ func (p *Parser) ParseReturn(in Tokens) (out Tokens, err error) { return out, err } -func (p *Parser) ParseExpr(in Tokens) (out Tokens, err error) { - log.Println("ParseExpr in:", in) - var ops Tokens - var vl int - // - // Process tokens from last to first, the goal is to reorder the tokens in - // a stack machine processing order, so it can be directly interpreted. - // - for i := len(in) - 1; i >= 0; i-- { - t := in[i] - // temporary assumptions: binary operators, returning 1 value - switch t.Id { - case lang.Ident: - // resolve symbol if not a selector rhs. - // TODO: test for selector expr. - _, sc, ok := p.getSym(t.Str, p.scope) - if ok && sc != "" { - t.Str = sc + "/" + t.Str - } - out = append(out, t) - vl++ - case lang.Int, lang.String: - out = append(out, t) - vl++ - case lang.Define, lang.Add, lang.Sub, lang.Assign, lang.Equal, lang.Greater, lang.Less, lang.Mul: - // TODO: handle operator precedence to swap operators / operands if necessary - if vl < 2 { - ops = append(ops, t) - break - } - case lang.ParenBlock: - // If the previous token is an arithmetic, logic or assign operator then - // this parenthesis block is an enclosed expr, otherwise a call expr. - if i == 0 || in[i-1].Id.IsOperator() { - out = append(out, t) - vl++ - break - } - // The call expression can be a function call, a conversion, - // a type assersion (including for type switch) - // func call: push args and func address then call - out = append(out, t) - vl++ - if t2 := in[i-1]; t2.Id == lang.Ident { - if s, sc, ok := p.getSym(t2.Str, p.scope); ok { - log.Println("callExpr:", t2.Str, p.scope, s, ok, sc) - if s.kind == symValue { - // Store the number of input parameters in the token Beg field. - ops = append(ops, scanner.Token{Str: "callX", Id: lang.CallX, Pos: t.Pos, Beg: p.numItems(t.Block(), lang.Comma)}) - break - } - } - } - ops = append(ops, scanner.Token{Str: "call", Id: lang.Call, Pos: t.Pos}) - } - if lops, lout := len(ops), len(out); lops > 0 && vl > lops { - op := ops[lops-1] - ops = ops[:lops-1] - // Reorder tokens according to operator precedence rules. - if p.precedence(out[lout-2]) > p.precedence(op) { - op, out[lout-1], out[lout-2] = out[lout-2], op, out[lout-1] - if p.precedence(out[lout-3]) > p.precedence(out[lout-1]) { - out[lout-1], out[lout-2], out[lout-3] = out[lout-3], out[lout-1], out[lout-2] - } - } - out = append(out, op) - vl-- - } - } - out = append(out, ops...) // TODO: verify that ops should be added in this order. - - log.Println("ParseExpr out:", out, "vl:", vl, "ops:", ops) - // The tokens are now properly ordered, process nested blocks. - for i := len(out) - 1; i >= 0; i-- { - t := out[i] - var toks Tokens - switch t.Id { - case lang.ParenBlock, lang.BracketBlock: - if toks, err = p.ParseExprStr(t.Block()); err != nil { - return out, err - } - default: - continue - } - - // replace block token by its parsed result. - log.Println("toks:", toks) - out2 := append(Tokens{}, out[:i]...) - out2 = append(out2, toks...) - out = append(out2, out[i+1:]...) - } - log.Println("Final out:", out) - return out, err -} - -func (p *Parser) ParseExprStr(s string) (tokens Tokens, err error) { - if tokens, err = p.Scan(s, false); err != nil { - return - } - var result Tokens - for _, sub := range tokens.Split(lang.Comma) { - toks, err := p.ParseExpr(sub) - if err != nil { - return result, err - } - result = append(toks, result...) - } - return result, err -} - func (p *Parser) numItems(s string, sep lang.TokenId) int { tokens, err := p.Scan(s, false) if err != nil { |
