修复: byte/rune 长度混淆及错误位置丢失

This commit is contained in:
2026-04-01 10:43:16 +08:00
parent 1b5b6aff8f
commit 2f9d81dc17
8 changed files with 603 additions and 93 deletions

View File

@@ -127,7 +127,7 @@ func (p *ExprParser) parseUnary() (*Expr, error) {
func (p *ExprParser) parsePrimary() (*Expr, error) {
p.skipSpaces()
if p.pos >= len(p.input) {
return nil, fmt.Errorf("line %d, col %d: unexpected end of expression", p.line, p.col)
return nil, PosErrorf(p.line, p.col, "unexpected end of expression")
}
ch := p.input[p.pos]
@@ -152,12 +152,12 @@ func (p *ExprParser) parsePrimary() (*Expr, error) {
}
p.skipSpaces()
if p.pos >= len(p.input) || p.input[p.pos] != ')' {
return nil, fmt.Errorf("line %d, col %d: expected ')'", p.line, p.col)
return nil, PosErrorf(p.line, p.col, "expected ')'")
}
p.skip(1)
return expr, nil
}
return nil, fmt.Errorf("line %d, col %d: unexpected character %q", p.line, p.col, string(ch))
return nil, PosErrorf(p.line, p.col, "unexpected character %q", string(ch))
}
func (p *ExprParser) parseIdentOrKeyword() (*Expr, error) {
@@ -186,7 +186,7 @@ func (p *ExprParser) parseIdentOrKeyword() (*Expr, error) {
for p.pos < len(p.input) && p.input[p.pos] == '.' {
p.skip(1)
if p.pos >= len(p.input) || !isIdentStart(p.input[p.pos]) {
return nil, fmt.Errorf("line %d, col %d: expected identifier after '.'", p.line, p.col)
return nil, PosErrorf(p.line, p.col, "expected identifier after '.'")
}
segStart := p.pos
for p.pos < len(p.input) && isIdentPart(p.input[p.pos]) {
@@ -221,7 +221,7 @@ func (p *ExprParser) parseFuncCall(name string) (*Expr, error) {
}
p.skipSpaces()
if p.pos >= len(p.input) || p.input[p.pos] != ')' {
return nil, fmt.Errorf("line %d, col %d: expected ')' after function call", p.line, p.col)
return nil, PosErrorf(p.line, p.col, "expected ')' after function call")
}
p.skip(1)
return &Expr{Pos: Pos{Line: p.line, Col: p.col}, ExprType: ExprFuncCall, FuncName: name, FuncArgs: args}, nil
@@ -252,7 +252,7 @@ func (p *ExprParser) parseStringLit() (*Expr, error) {
p.pos++
}
if p.pos >= len(p.input) {
return nil, fmt.Errorf("line %d, col %d: unterminated string", p.line, p.col)
return nil, PosErrorf(p.line, p.col, "unterminated string")
}
p.skip(1)
return &Expr{Pos: Pos{Line: p.line, Col: p.col}, ExprType: ExprLiteral, Value: buf.String()}, nil
@@ -266,7 +266,7 @@ func (p *ExprParser) parseSingleQuoteStringLit() (*Expr, error) {
p.pos++
}
if p.pos >= len(p.input) {
return nil, fmt.Errorf("line %d, col %d: unterminated string", p.line, p.col)
return nil, PosErrorf(p.line, p.col, "unterminated string")
}
p.skip(1)
return &Expr{Pos: Pos{Line: p.line, Col: p.col}, ExprType: ExprLiteral, Value: buf.String()}, nil
@@ -292,13 +292,13 @@ func (p *ExprParser) parseNumberLit() (*Expr, error) {
if isFloat {
v, err := strconv.ParseFloat(text, 64)
if err != nil {
return nil, fmt.Errorf("line %d, col %d: invalid number %q", p.line, p.col, text)
return nil, PosErrorf(p.line, p.col, "invalid number %q", text)
}
return &Expr{Pos: Pos{Line: p.line, Col: p.col}, ExprType: ExprLiteral, Value: v}, nil
}
v, err := strconv.ParseInt(text, 10, 64)
if err != nil {
return nil, fmt.Errorf("line %d, col %d: invalid number %q", p.line, p.col, text)
return nil, PosErrorf(p.line, p.col, "invalid number %q", text)
}
return &Expr{Pos: Pos{Line: p.line, Col: p.col}, ExprType: ExprLiteral, Value: int(v)}, nil
}
@@ -359,7 +359,7 @@ func Eval(expr *Expr, ctx *Context) (any, error) {
case ExprFuncCall:
return evalFuncCall(expr, ctx)
default:
return nil, fmt.Errorf("line %d, col %d: unknown expression type", expr.Pos.Line, expr.Pos.Col)
return nil, PosErrorf(expr.Pos.Line, expr.Pos.Col, "unknown expression type")
}
}
@@ -372,7 +372,7 @@ func evalUnary(expr *Expr, ctx *Context) (any, error) {
case "!":
return !isTruthy(val), nil
default:
return nil, fmt.Errorf("line %d, col %d: unknown unary operator %q", expr.Pos.Line, expr.Pos.Col, expr.UnaryOp)
return nil, PosErrorf(expr.Pos.Line, expr.Pos.Col, "unknown unary operator %q", expr.UnaryOp)
}
}
@@ -421,14 +421,14 @@ func evalBinary(expr *Expr, ctx *Context) (any, error) {
case ">=":
return compareOrder(left, right, expr.Op)
default:
return nil, fmt.Errorf("line %d, col %d: unknown operator %q", expr.Pos.Line, expr.Pos.Col, expr.Op)
return nil, PosErrorf(expr.Pos.Line, expr.Pos.Col, "unknown operator %q", expr.Op)
}
}
func evalFuncCall(expr *Expr, ctx *Context) (any, error) {
fn, ok := LookupBuiltin(expr.FuncName)
if !ok {
return nil, fmt.Errorf("line %d, col %d: unknown function %q", expr.Pos.Line, expr.Pos.Col, expr.FuncName)
return nil, PosErrorf(expr.Pos.Line, expr.Pos.Col, "unknown function %q", expr.FuncName)
}
var args []any
for _, a := range expr.FuncArgs {
@@ -440,7 +440,7 @@ func evalFuncCall(expr *Expr, ctx *Context) (any, error) {
}
result, ok := fn(args)
if !ok {
return nil, fmt.Errorf("line %d, col %d: function %q call failed", expr.Pos.Line, expr.Pos.Col, expr.FuncName)
return nil, PosErrorf(expr.Pos.Line, expr.Pos.Col, "function %q call failed", expr.FuncName)
}
return result, nil
}