New bitwise XOR operator specified by symbol ^ (caret). Iterator dereference is now done by prefixed * (star)
This commit is contained in:
parent
5ab6876ea1
commit
760c1ee6da
@ -187,6 +187,8 @@ func evalOpAssign(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
v, err = bitwiseAnd(opTerm, leftValue, rightValue)
|
||||
case SymVertBarEqual:
|
||||
v, err = bitwiseOr(opTerm, leftValue, rightValue)
|
||||
case SymCaretEqual:
|
||||
v, err = bitwiseXor(opTerm, leftValue, rightValue)
|
||||
case SymDoubleLessEqual:
|
||||
v, err = bitLeftShift(opTerm, leftValue, rightValue)
|
||||
case SymDoubleGreaterEqual:
|
||||
@ -214,4 +216,5 @@ func init() {
|
||||
registerTermConstructor(SymDoubleGreaterEqual, newOpAssignTerm)
|
||||
registerTermConstructor(SymAmpersandEqual, newOpAssignTerm)
|
||||
registerTermConstructor(SymVertBarEqual, newOpAssignTerm)
|
||||
registerTermConstructor(SymCaretEqual, newOpAssignTerm)
|
||||
}
|
||||
|
@ -107,9 +107,48 @@ func evalBitwiseOr(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//-------- Bitwise XOR term
|
||||
|
||||
func newBitwiseXorTerm(tk *Token) (inst *term) {
|
||||
return &term{
|
||||
tk: *tk,
|
||||
children: make([]*term, 0, 2),
|
||||
position: posInfix,
|
||||
priority: priBitwiseOr,
|
||||
evalFunc: evalBitwiseXor,
|
||||
}
|
||||
}
|
||||
|
||||
func bitwiseXor(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
var leftInt, rightInt int64
|
||||
var lok, rok bool
|
||||
|
||||
leftInt, lok = leftValue.(int64)
|
||||
rightInt, rok = rightValue.(int64)
|
||||
|
||||
if lok && rok {
|
||||
v = leftInt ^ rightInt
|
||||
} else {
|
||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func evalBitwiseXor(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
v, err = bitwiseXor(opTerm, leftValue, rightValue)
|
||||
return
|
||||
}
|
||||
|
||||
// init
|
||||
func init() {
|
||||
registerTermConstructor(SymTilde, newBitwiseNotTerm)
|
||||
registerTermConstructor(SymAmpersand, newBitwiseAndTerm)
|
||||
registerTermConstructor(SymVertBar, newBitwiseOrTerm)
|
||||
registerTermConstructor(SymCaret, newBitwiseXorTerm)
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ func newIterValueTerm(tk *Token) (inst *term) {
|
||||
tk: *tk,
|
||||
children: make([]*term, 0, 1),
|
||||
position: posPrefix,
|
||||
priority: priIterValue,
|
||||
priority: priDereference,
|
||||
evalFunc: evalIterValue,
|
||||
}
|
||||
}
|
||||
@ -33,6 +33,6 @@ func evalIterValue(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
|
||||
// init
|
||||
func init() {
|
||||
// registerTermConstructor(SymOpenClosedRound, newIterValueTerm)
|
||||
registerTermConstructor(SymCaret, newIterValueTerm)
|
||||
// registerTermConstructor(SymOpenClosedRound, newIterValueTerm)
|
||||
registerTermConstructor(SymDereference, newIterValueTerm)
|
||||
}
|
||||
|
17
parser.go
17
parser.go
@ -441,8 +441,10 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
|
||||
tk.Sym = SymChangeSign
|
||||
} else if tk.Sym == SymPlus {
|
||||
tk.Sym = SymUnchangeSign
|
||||
} else if tk.IsSymbol(SymStar) {
|
||||
tk.SetSymbol(SymDereference)
|
||||
} else if tk.IsSymbol(SymExclamation) {
|
||||
err = tk.Errorf("postfix opertor %q requires an operand on its left", tk)
|
||||
err = tk.Errorf("postfix opertor %q requires an operand on its left side", tk)
|
||||
break
|
||||
}
|
||||
firstToken = false
|
||||
@ -481,7 +483,7 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
|
||||
currentTerm = mapTerm
|
||||
}
|
||||
}
|
||||
case SymEqual, SymPlusEqual, SymMinusEqual, SymStarEqual, SymSlashEqual, SymPercEqual:
|
||||
case SymEqual, SymPlusEqual, SymMinusEqual, SymStarEqual, SymSlashEqual, SymPercEqual, SymAmpersandEqual, SymVertBarEqual, SymDoubleLessEqual, SymDoubleGreaterEqual, SymCaretEqual:
|
||||
currentTerm, err = tree.addToken(tk)
|
||||
firstToken = true
|
||||
case SymFuncDef:
|
||||
@ -518,14 +520,11 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// if hasFlag(ctx, allowIndex) {
|
||||
// tk.Sym = SymRange
|
||||
// }
|
||||
currentTerm, err = tree.addToken(tk)
|
||||
}
|
||||
if tk.IsOneOfA(SymColon, SymRange) {
|
||||
// Colon outside a selector term acts like a separator
|
||||
firstToken = true
|
||||
if tk.IsOneOfA(SymColon, SymRange) {
|
||||
// Colon outside a selector term acts like a separator
|
||||
firstToken = true
|
||||
}
|
||||
}
|
||||
default:
|
||||
currentTerm, err = tree.addToken(tk)
|
||||
|
@ -177,7 +177,11 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
||||
case ',':
|
||||
tk = scanner.makeToken(SymComma, ch)
|
||||
case '^':
|
||||
tk = scanner.makeToken(SymCaret, ch)
|
||||
if next, _ := scanner.peek(); next == '=' {
|
||||
tk = scanner.moveOn(SymCaretEqual, ch, next)
|
||||
} else {
|
||||
tk = scanner.makeToken(SymCaret, ch)
|
||||
}
|
||||
case ':':
|
||||
if next, _ := scanner.peek(); next == ':' {
|
||||
tk = scanner.moveOn(SymDoubleColon, ch, next)
|
||||
|
@ -100,8 +100,9 @@ func init() {
|
||||
SymDoubleGreaterEqual: {">>=", symClassOperator, posInfix}, // 64: '>>='
|
||||
SymAmpersandEqual: {"&=", symClassOperator, posInfix}, // 65: '&='
|
||||
SymVertBarEqual: {"|=", symClassOperator, posInfix}, // 65: '|='
|
||||
SymPlusGreater: {"+>", symClassOperator, posInfix}, // 66: '+>'
|
||||
SymLessPlus: {"<+", symClassOperator, posInfix}, // 67: '<+'
|
||||
SymCaretEqual: {"^=", symClassOperator, posInfix}, // 66: '^='
|
||||
SymPlusGreater: {"+>", symClassOperator, posInfix}, // 67: '+>'
|
||||
SymLessPlus: {"<+", symClassOperator, posInfix}, // 68: '<+'
|
||||
// SymChangeSign
|
||||
// SymUnchangeSign
|
||||
// SymIdentifier
|
||||
|
@ -75,10 +75,12 @@ const (
|
||||
SymDoubleGreaterEqual // 64: '>>='
|
||||
SymAmpersandEqual // 65: '&='
|
||||
SymVertBarEqual // 65: '|='
|
||||
SymPlusGreater // 66: '+>'
|
||||
SymLessPlus // 67: '<+'
|
||||
SymCaretEqual // 66: '^='
|
||||
SymPlusGreater // 67: '+>'
|
||||
SymLessPlus // 68: '<+'
|
||||
SymChangeSign
|
||||
SymUnchangeSign
|
||||
SymDereference
|
||||
SymIdentifier
|
||||
SymBool
|
||||
SymInteger
|
||||
|
@ -9,10 +9,10 @@ import "testing"
|
||||
func TestIteratorParser(t *testing.T) {
|
||||
section := "Iterator"
|
||||
inputs := []inputType{
|
||||
/* 1 */ {`include "test-resources/iterator.expr"; it=$(ds,3); ^it`, int64(0), nil},
|
||||
/* 1 */ {`include "test-resources/iterator.expr"; it=$(ds,3); *it`, int64(0), nil},
|
||||
/* 2 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++`, int64(1), nil},
|
||||
/* 3 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++; #it`, int64(3), nil},
|
||||
/* 4 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++; it.reset; ^it`, int64(0), nil},
|
||||
/* 4 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++; it.reset; *it`, int64(0), nil},
|
||||
/* 5 */ {`builtin "math.arith"; include "test-resources/iterator.expr"; it=$(ds,3); add(it)`, int64(6), nil},
|
||||
/* 6 */ {`builtin "math.arith"; include "test-resources/iterator.expr"; it=$(ds,3); mul(it)`, int64(0), nil},
|
||||
/* 7 */ {`builtin "math.arith"; include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); mul(it)`, int64(12000), nil},
|
||||
|
@ -28,6 +28,9 @@ func TestOperator(t *testing.T) {
|
||||
/* 15 */ {`0o10`, int64(8), nil},
|
||||
/* 16 */ {`0b10`, int64(2), nil},
|
||||
/* 17 */ {`~true`, nil, `[1:2] prefix/postfix operator "~" do not support operand 'true' [bool]`},
|
||||
/* 18 */ {`1^2`, int64(3), nil},
|
||||
/* 19 */ {`3^2`, int64(1), nil},
|
||||
/* 19 */ {`a=1; a^=2`, int64(3), nil},
|
||||
}
|
||||
|
||||
// t.Setenv("EXPR_PATH", ".")
|
||||
|
@ -142,6 +142,6 @@ func TestGeneralParser(t *testing.T) {
|
||||
}
|
||||
|
||||
// t.Setenv("EXPR_PATH", ".")
|
||||
//runTestSuiteSpec(t, section, inputs, 130)
|
||||
// runTestSuiteSpec(t, section, inputs, 114)
|
||||
runTestSuite(t, section, inputs)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user