Compare commits
2 Commits
b76481bbf2
...
fe9ab9ebd2
Author | SHA1 | Date | |
---|---|---|---|
fe9ab9ebd2 | |||
7198749063 |
@ -182,7 +182,7 @@ a=1; b=2; c=3; a+b+c // returns 6
|
||||
=== [blue]`but` operator
|
||||
[blue]`but` is an infixed operator. Its operands can be any type of expression. It evaluates the left expression first, then the right expression. The value of the right expression is the final result. Examples: [blue]`5 but 2` returns 2, [blue]`x=2*3 but x-1` returns 5.
|
||||
|
||||
[blue]`but` is very similar to [blue]`;`. The only difference is that [blue]`;` can't be used inside parenthesis [blue]`;(` and [blue]`)`.
|
||||
[blue]`but` is very similar to [blue]`;`. The only difference is that [blue]`;` can't be used inside parenthesis [blue]`(` and [blue]`)`.
|
||||
|
||||
=== Assignment operator [blue]`=`
|
||||
The assignment operator [blue]`=` is used to define variable in the evaluation context or to change their value (see _ExprContext_).
|
||||
|
61
operator-dot.go
Normal file
61
operator-dot.go
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||
// All rights reserved.
|
||||
|
||||
// operator-dot.go
|
||||
package expr
|
||||
|
||||
// -------- dot term
|
||||
func newDotTerm(tk *Token) (inst *term) {
|
||||
return &term{
|
||||
tk: *tk,
|
||||
children: make([]*term, 0, 2),
|
||||
position: posInfix,
|
||||
priority: priDot,
|
||||
evalFunc: evalDot,
|
||||
}
|
||||
}
|
||||
|
||||
func evalDot(ctx ExprContext, self *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
indexTerm := self.children[1]
|
||||
if !isInteger(rightValue) {
|
||||
err = indexTerm.Errorf("index expression must be integer, got %T", rightValue)
|
||||
return
|
||||
}
|
||||
|
||||
index64, _ := rightValue.(int64)
|
||||
index := int(index64)
|
||||
|
||||
if isList(leftValue) {
|
||||
list, _ := leftValue.([]any)
|
||||
if index >= 0 && index < len(list) {
|
||||
v = list[index]
|
||||
} else if index >= -len(list) {
|
||||
v = list[len(list)+index]
|
||||
} else {
|
||||
err = indexTerm.Errorf("index %v out of bounds", index)
|
||||
}
|
||||
} else if isString(leftValue) {
|
||||
s, _ := leftValue.(string)
|
||||
if index >= 0 && index < len(s) {
|
||||
v = string(s[index])
|
||||
} else if index >= -len(s) {
|
||||
v = string(s[len(s)+index])
|
||||
} else {
|
||||
err = indexTerm.Errorf("index %v out of bounds", index)
|
||||
}
|
||||
} else {
|
||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// init
|
||||
func init() {
|
||||
registerTermConstructor(SymDot, newDotTerm)
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
// operator-insert.go
|
||||
package expr
|
||||
|
||||
|
||||
//-------- insert term
|
||||
|
||||
func newInsertTerm(tk *Token) (inst *term) {
|
||||
@ -12,7 +11,7 @@ func newInsertTerm(tk *Token) (inst *term) {
|
||||
tk: *tk,
|
||||
children: make([]*term, 0, 2),
|
||||
position: posInfix,
|
||||
priority: priSign,
|
||||
priority: priAssign,
|
||||
evalFunc: evalInsert,
|
||||
}
|
||||
}
|
||||
@ -22,7 +21,7 @@ func newAppendTerm(tk *Token) (inst *term) {
|
||||
tk: *tk,
|
||||
children: make([]*term, 0, 2),
|
||||
position: posInfix,
|
||||
priority: priSign,
|
||||
priority: priAssign,
|
||||
evalFunc: evalAppend,
|
||||
}
|
||||
}
|
||||
@ -38,7 +37,7 @@ func evalInsert(ctx ExprContext, self *term) (v any, err error) {
|
||||
list, _ := rightValue.([]any)
|
||||
v = append([]any{leftValue}, list...)
|
||||
} else {
|
||||
err = self.errIncompatibleType(rightValue)
|
||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -54,7 +53,7 @@ func evalAppend(ctx ExprContext, self *term) (v any, err error) {
|
||||
list, _ := leftValue.([]any)
|
||||
v = append(list, rightValue)
|
||||
} else {
|
||||
err = self.errIncompatibleType(leftValue)
|
||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -152,9 +152,10 @@ func (self *scanner) fetchNextToken() (tk *Token) {
|
||||
case ';':
|
||||
tk = self.makeToken(SymSemiColon, ch)
|
||||
case '.':
|
||||
if next, _ := self.peek(); next >= '0' && next <= '9' {
|
||||
tk = self.parseNumber(ch)
|
||||
} else if next == '/' {
|
||||
//if next, _ := self.peek(); next >= '0' && next <= '9' {
|
||||
// tk = self.parseNumber(ch)
|
||||
//} else if next == '/' {
|
||||
if next, _ := self.peek(); next == '/' {
|
||||
tk = self.moveOn(SymDotSlash, ch, next)
|
||||
} else {
|
||||
tk = self.makeToken(SymDot, ch)
|
||||
|
3
term.go
3
term.go
@ -24,6 +24,7 @@ const (
|
||||
priSign
|
||||
priFact
|
||||
priCoalesce
|
||||
priDot
|
||||
priValue
|
||||
)
|
||||
|
||||
@ -166,7 +167,7 @@ func (self *term) checkOperands() (err error) {
|
||||
switch self.position {
|
||||
case posInfix:
|
||||
if self.children == nil || len(self.children) != 2 || self.anyChildrenNil() {
|
||||
err = self.tk.Errorf("infix operator %q requires two not nil operands, got %d", self.source(), self.getChildrenCount())
|
||||
err = self.tk.Errorf("infix operator %q requires two non-nil operands, got %d", self.source(), self.getChildrenCount())
|
||||
}
|
||||
case posPrefix:
|
||||
if self.children == nil || len(self.children) != 1 || self.children[0] == nil {
|
||||
|
Loading…
Reference in New Issue
Block a user