Compare commits

..

No commits in common. "ab06702e5e38655e0298134c4bde818ceb814a25" and "315f5b22d32084abd99b76e92c8afaabae4e56d8" have entirely different histories.

9 changed files with 25 additions and 165 deletions

12
ast.go
View File

@ -45,19 +45,19 @@ func (expr *ast) String() string {
func (expr *ast) addTokens(tokens ...*Token) (err error) {
for _, tk := range tokens {
if _, err = expr.addToken(tk); err != nil {
if err = expr.addToken(tk); err != nil {
break
}
}
return
}
// func (expr *ast) addToken(tk *Token) (err error) {
// _, err = expr.addToken2(tk)
// return
// }
func (expr *ast) addToken(tk *Token) (err error) {
_, err = expr.addToken2(tk)
return
}
func (expr *ast) addToken(tk *Token) (t *term, err error) {
func (expr *ast) addToken2(tk *Token) (t *term, err error) {
if t = newTerm(tk); t != nil {
err = expr.addTerm(t)
} else {

View File

@ -35,39 +35,7 @@ func evalPostInc(ctx ExprContext, opTerm *term) (v any, err error) {
return
}
// -------- post decrement term
func newPostDecTerm(tk *Token) *term {
return &term{
tk: *tk,
parent: nil,
children: make([]*term, 0, 1),
position: posPostfix,
priority: priIncDec,
evalFunc: evalPostDec,
}
}
func evalPostDec(ctx ExprContext, opTerm *term) (v any, err error) {
var childValue any
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
return
}
/* if it, ok := childValue.(Iterator); ok {
v, err = it.Next()
} else */if IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable {
v = childValue
i, _ := childValue.(int64)
ctx.SetVar(opTerm.children[0].source(), i-1)
} else {
err = opTerm.errIncompatibleType(childValue)
}
return
}
// init
func init() {
registerTermConstructor(SymDoublePlus, newPostIncTerm)
registerTermConstructor(SymDoubleMinus, newPostDecTerm)
}

View File

@ -19,8 +19,7 @@ func NewParser() (p *parser) {
}
func (parser *parser) Next(scanner *scanner) (tk *Token) {
for tk = scanner.Next(); tk.IsSymbol(SymComment); tk = scanner.Next() {
}
for tk=scanner.Next(); tk.IsSymbol(SymComment); tk=scanner.Next() {}
return
}
@ -305,7 +304,7 @@ func addSelectorCase(selectorTerm, caseTerm *term) {
func (parser *parser) parseSelector(scanner *scanner, tree *ast, allowVarRef bool) (selectorTerm *term, err error) {
var caseTerm *term
tk := scanner.makeToken(SymSelector, '?')
if selectorTerm, err = tree.addToken(tk); err != nil {
if selectorTerm, err = tree.addToken2(tk); err != nil {
return
}
@ -343,14 +342,13 @@ func (parser *parser) parseGeneral(scanner *scanner, allowForest bool, allowVarR
var selectorTerm *term = nil
var currentTerm *term = nil
var tk *Token
tree = NewAst()
firstToken := true
// lastSym := SymUnknown
for tk = parser.Next(scanner); err == nil && tk != nil && !tk.IsTerm(termSymbols); /*&& !areSymbolsOutOfCtx(tk, selectorTerm, SymColon, SymDoubleColon)*/ tk = parser.Next(scanner) {
// if tk.Sym == SymComment {
// continue
// }
if tk.Sym == SymComment {
continue
}
if tk.Sym == SymSemiColon {
if allowForest {
@ -416,7 +414,7 @@ func (parser *parser) parseGeneral(scanner *scanner, allowForest bool, allowVarR
}
case SymEqual:
// if err = checkPrevSymbol(lastSym, SymIdentifier, tk); err == nil {
currentTerm, err = tree.addToken(tk)
currentTerm, err = tree.addToken2(tk)
// }
case SymFuncDef:
var funcDefTerm *term
@ -434,7 +432,7 @@ func (parser *parser) parseGeneral(scanner *scanner, allowForest bool, allowVarR
if tk.source[0] == '@' && !allowVarRef {
err = tk.Errorf("variable references are not allowed in top level expressions: %q", tk.source)
} else {
currentTerm, err = tree.addToken(tk)
currentTerm, err = tree.addToken2(tk)
}
case SymQuestion:
if selectorTerm, err = parser.parseSelector(scanner, tree, allowVarRef); err == nil {
@ -451,16 +449,14 @@ func (parser *parser) parseGeneral(scanner *scanner, allowForest bool, allowVarR
}
}
} else {
currentTerm, err = tree.addToken(tk)
currentTerm, err = tree.addToken2(tk)
}
if tk.IsSymbol(SymColon) {
// Colon outside a selector term acts like a separator
firstToken = true
}
case SymPlusEqual, SymMinusEqual, SymStarEqual:
currentTerm, err = parser.expandOpAssign(scanner, tree, tk, allowVarRef)
default:
currentTerm, err = tree.addToken(tk)
currentTerm, err = tree.addToken2(tk)
}
if currentTerm != nil && currentTerm.tk.Sym != SymSelector && currentTerm.parent != nil && currentTerm.parent.tk.Sym != SymSelector {
@ -469,7 +465,6 @@ func (parser *parser) parseGeneral(scanner *scanner, allowForest bool, allowVarR
}
// lastSym = tk.Sym
}
if err == nil {
err = tk.Error()
}
@ -482,49 +477,3 @@ func (parser *parser) parseGeneral(scanner *scanner, allowForest bool, allowVarR
// }
// return
// }
func (parser *parser) expandOpAssign(scanner * scanner, tree *ast, tk *Token, allowVarRef bool) (t *term, err error) {
var opSym Symbol
var opString string
if tree.root != nil {
switch tk.Sym {
case SymPlusEqual:
opString = "+"
opSym = SymPlus
case SymMinusEqual:
opString = "-"
opSym = SymMinus
case SymStarEqual:
opString = "*"
opSym = SymStar
default:
err = tk.Errorf("unsopported operator %q", tk.source)
return
}
leftExpr := tree.root.Clone()
leftExpr.setParent(nil)
if t, err = tree.addToken(NewToken(tk.row, tk.col, SymEqual, "=")); err == nil {
t = leftExpr
if err = tree.addTerm(leftExpr); err == nil {
if t, err = tree.addToken(NewToken(tk.row, tk.col, opSym, opString)); err == nil {
var subTree *ast
if subTree, err = parser.parseGeneral(scanner, false, allowVarRef, SymSemiColon, SymClosedRound, SymClosedBrace, SymClosedSquare); err == nil {
if scanner.Previous().IsOneOfA(SymSemiColon, SymClosedRound, SymClosedBrace, SymClosedSquare) {
if err = scanner.UnreadToken(); err != nil {
return
}
}
subTree.root.priority = priValue
err = tree.addTerm(newExprTerm(subTree.root))
t = subTree.root
}
}
}
}
} else {
err = tk.Errorf("left operand of %q must be a variable or a variable expression", tk)
}
return
}

View File

@ -16,7 +16,6 @@ import (
type scanner struct {
current *Token
prev *Token
stage *Token
stream *bufio.Reader
row int
column int
@ -75,16 +74,6 @@ func (scanner *scanner) unreadChar() (err error) {
return
}
func (scanner *scanner) UnreadToken() (err error) {
if scanner.stage == nil {
scanner.stage = scanner.current
scanner.current = scanner.prev
} else {
err = fmt.Errorf("staging already present, currently one level only of staging is allowed")
}
return
}
func (scanner *scanner) lastPos() (r, c int) {
if scanner.prev != nil {
r = scanner.prev.row
@ -100,12 +89,7 @@ func (scanner *scanner) Previous() *Token {
func (scanner *scanner) Next() (tk *Token) {
scanner.prev = scanner.current
tk = scanner.current
if scanner.stage != nil {
scanner.current = scanner.stage
scanner.stage = nil
} else {
scanner.current = scanner.fetchNextToken()
}
scanner.current = scanner.fetchNextToken()
return tk
}
@ -140,8 +124,6 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
tk = scanner.moveOn(SymDoubleStar, ch, next)
// } else if next == '/' {
// tk = self.moveOn(SymClosedComment, ch, next)
} else if next, _ = scanner.peek(); next == '=' {
tk = scanner.moveOn(SymStarEqual, ch, next)
} else {
tk = scanner.makeToken(SymStar, ch)
}
@ -287,11 +269,11 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
tk = scanner.makeToken(SymDollar, ch)
}
case '(':
// if next, _ := scanner.peek(); next == ')' {
// tk = scanner.moveOn(SymOpenClosedRound, ch, next)
// } else {
tk = scanner.makeToken(SymOpenRound, ch)
// }
// if next, _ := scanner.peek(); next == ')' {
// tk = scanner.moveOn(SymOpenClosedRound, ch, next)
// } else {
tk = scanner.makeToken(SymOpenRound, ch)
// }
case ')':
tk = scanner.makeToken(SymClosedRound, ch)
case '[':
@ -458,7 +440,7 @@ func (scanner *scanner) parseNumber(firstCh byte) (tk *Token) {
tk = scanner.makeErrorToken(err)
} else {
var value any
err = scanner.sync(err) // TODO: Check this function
err = scanner.sync(err) // TODO: Check this function
txt := sb.String()
if sym == SymFloat {
value, err = strconv.ParseFloat(txt, 64)

View File

@ -68,7 +68,6 @@ const (
SymDoubleDollar // 57: '$$'
SymDoubleDot // 58: '..'
SymTripleDot // 59: '...'
SymStarEqual // 60: '*='
SymChangeSign
SymUnchangeSign
SymIdentifier

View File

@ -47,7 +47,7 @@ func TestAddUnknownTokens(t *testing.T) {
wantErr := errors.New(`unexpected token "%"`)
tree := NewAst()
if _, gotErr := tree.addToken(tk0); gotErr != nil && gotErr.Error() != wantErr.Error() {
if gotErr := tree.addToken(tk0); gotErr != nil && gotErr.Error() != wantErr.Error() {
t.Errorf("err: got <%v>, want <%v>", gotErr, wantErr)
}
}

View File

@ -17,18 +17,7 @@ func TestExpr(t *testing.T) {
/* 3 */ {`builtin "os.file"; f=fileOpen("test-file.txt"); line=fileReadText(f); fileClose(f); line`, "uno", nil},
/* 4 */ {`mynot=func(v){int(v)?{true}::{false}}; mynot(0)`, true, nil},
/* 5 */ {`1 ? {1} : [1+0] {3*(1+1)}`, int64(6), nil},
/* 6 */ {`a=3; a+=1`, int64(4), nil},
/* 7 */ {`a=3; a-=1`, int64(2), nil},
/* 8 */ {`a=3; a*=2`, int64(6), nil},
/* 9 */ {`v=[10,20,30]; v[0]+=1; v[0]`, int64(11), nil},
/* 10 */ {`r={"a":10}; r["a"]+=1; r["a"]`, int64(11), nil},
/* 11 */ {`a=3; a/=2`, nil, `[1:8] left operand of "=" must be a variable or a collection's item`},
/* 12 */ {`*=2`, nil, `[1:2] left operand of "*=" must be a variable or a variable expression`},
/* 13 */ {`a=3; a*=2+1; a`, int64(9), nil},
/* 14 */ {`a=3; (a*=2)+1; a`, int64(6), nil},
/* 15 */ {`a=3; a*=2)+1; a`, nil, `[1:11] unexpected token ")"`},
/* 16 */ {`v=[2]; a=1; v[a-=1]=5; v[0]`, int64(5), nil},
/* 17 */ {`
/* 6 */ {`
ds={
"init":func(@end){@current=0 but true},
//"current":func(){current},
@ -43,6 +32,6 @@ func TestExpr(t *testing.T) {
}
// t.Setenv("EXPR_PATH", ".")
//runTestSuiteSpec(t, section, inputs, 9)
//runTestSuiteSpec(t, section, inputs, 6)
runTestSuite(t, section, inputs)
}

19
term.go
View File

@ -53,25 +53,6 @@ type term struct {
evalFunc evalFuncType
}
func (s *term) Clone() (d *term) {
var children []*term
if s.children != nil {
children = make([]*term, len(s.children))
for i, c := range s.children {
children[i] = c.Clone()
}
}
d = &term{
tk: *s.tk.Clone(),
parent: s.parent,
children: children,
position: s.position,
priority: s.priority,
evalFunc: s.evalFunc,
}
return
}
func (term *term) String() string {
var sb strings.Builder
term.toString(&sb)

View File

@ -51,10 +51,6 @@ func NewErrorToken(row, col int, err error) *Token {
return NewValueToken(row, col, SymError, fmt.Sprintf("[%d:%d]", row, col), err)
}
func (tk *Token) Clone() (c *Token) {
return NewValueToken(tk.row, tk.col, tk.Sym, tk.source, tk.Value)
}
func (tk *Token) IsEos() bool {
return tk.Sym == SymEos
}
@ -71,10 +67,6 @@ func (tk *Token) IsOneOf(termSymbols []Symbol) bool {
return termSymbols != nil && slices.Index(termSymbols, tk.Sym) >= 0
}
func (tk *Token) IsOneOfA(termSymbols ...Symbol) bool {
return slices.Index(termSymbols, tk.Sym) >= 0
}
func (tk *Token) IsSymbol(sym Symbol) bool {
return tk.Sym == sym
}