diff options
| author | Marc Vertes <mvertes@free.fr> | 2026-01-06 19:02:29 +0100 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2026-01-06 19:02:29 +0100 |
| commit | bffc031ea83c7176aac3d3828de0060c6630140c (patch) | |
| tree | 32e30f3bec94884936c2cfc2d53d3ae496e13d61 /scanner | |
| parent | f07fc0178831432b68f1b9bd6c96b257aa2e9abe (diff) | |
fix: correct and simplify parsing of expressions.
The expressions were parsed from right to left, and it was incorrect and
cumbersome. Now they are processed from left to right, with a simpler
and correct handling of precedence rules.
The vm function call syntax has been changed to set the function
before the input arguments on the stack, as to follow the declaring
order in languages.
Diffstat (limited to 'scanner')
| -rw-r--r-- | scanner/scan.go | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/scanner/scan.go b/scanner/scan.go index edd8b1c..cb1549e 100644 --- a/scanner/scan.go +++ b/scanner/scan.go @@ -46,8 +46,10 @@ func (t *Token) Name() string { func (t *Token) String() string { s := t.Tok.String() if t.Tok.IsLiteral() || t.Tok.IsBlock() || t.Tok == lang.Ident || t.Tok == lang.Comment || - t.Tok == lang.Period || t.Tok == lang.Label || t.Tok == lang.Goto { + t.Tok == lang.Period || t.Tok == lang.Label || t.Tok == lang.Goto || t.Tok == lang.JumpSetFalse || t.Tok == lang.JumpSetTrue || t.Tok == lang.JumpFalse || t.Tok == lang.Colon || t.Tok == lang.Composite { s += strconv.Quote(t.Str) + } else if t.Tok == lang.Call { + s += "(" + strconv.Itoa(t.Beg) + ")" } return s } @@ -119,8 +121,8 @@ func (sc *Scanner) Scan(src string, semiEOF bool) (tokens []Token, err error) { if len(tokens) > 0 && t.Str == "\n" { // Check for automatic semi-colon insertion after newline. last := tokens[len(tokens)-1] - if last.Tok.IsKeyword() && sc.TokenProps[last.Str].SkipSemi || - last.Tok.IsOperator() && !sc.TokenProps[last.Str].SkipSemi { + if last.Tok.IsKeyword() && sc.TokenProps[last.Tok].SkipSemi || + last.Tok.IsOperator() && !sc.TokenProps[last.Tok].SkipSemi { skip = true } else { t.Tok = lang.Semicolon @@ -142,8 +144,8 @@ func (sc *Scanner) Scan(src string, semiEOF bool) (tokens []Token, err error) { if last.Str == ";" { return tokens, nil } - if last.Tok == lang.Ident && sc.TokenProps[last.Str].SkipSemi || - last.Tok.IsOperator() && !sc.TokenProps[last.Str].SkipSemi { + if last.Tok == lang.Ident && sc.TokenProps[last.Tok].SkipSemi || + last.Tok.IsOperator() && !sc.TokenProps[last.Tok].SkipSemi { return tokens, nil } tokens = append(tokens, Token{Tok: lang.Semicolon, Str: ";"}) @@ -179,7 +181,7 @@ func (sc *Scanner) Next(src string) (tok Token, err error) { return Token{}, nil case sc.isGroupSep(r): // TODO: handle group separators. - return Token{Tok: sc.TokenProps[string(r)].Token, Pos: p + i, Str: string(r)}, nil + return Token{Tok: sc.Tokens[string(r)], Pos: p + i, Str: string(r)}, nil case sc.isLineSep(r): return Token{Pos: p + i, Str: "\n"}, nil case sc.isStr(r): @@ -194,12 +196,12 @@ func (sc *Scanner) Next(src string) (tok Token, err error) { err = ErrBlock } tok := Token{Pos: p + i, Str: b, Beg: 1, End: 1} - tok.Tok = sc.TokenProps[tok.Name()].Token + tok.Tok = sc.Tokens[tok.Name()] return tok, err case sc.isOp(r): op, isOp := sc.getOp(src[i:]) if isOp { - t := sc.TokenProps[op].Token + t := sc.Tokens[op] if t == lang.Illegal { err = fmt.Errorf("%w: %s", ErrIllegal, op) } @@ -218,7 +220,7 @@ func (sc *Scanner) Next(src string) (tok Token, err error) { default: t, isDefined := sc.getToken(src[i:]) if isDefined { - ident := sc.TokenProps[t].Token + ident := sc.Tokens[t] if ident == lang.Illegal { ident = lang.Ident } |
