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)
|
v, err = bitwiseAnd(opTerm, leftValue, rightValue)
|
||||||
case SymVertBarEqual:
|
case SymVertBarEqual:
|
||||||
v, err = bitwiseOr(opTerm, leftValue, rightValue)
|
v, err = bitwiseOr(opTerm, leftValue, rightValue)
|
||||||
|
case SymCaretEqual:
|
||||||
|
v, err = bitwiseXor(opTerm, leftValue, rightValue)
|
||||||
case SymDoubleLessEqual:
|
case SymDoubleLessEqual:
|
||||||
v, err = bitLeftShift(opTerm, leftValue, rightValue)
|
v, err = bitLeftShift(opTerm, leftValue, rightValue)
|
||||||
case SymDoubleGreaterEqual:
|
case SymDoubleGreaterEqual:
|
||||||
@ -214,4 +216,5 @@ func init() {
|
|||||||
registerTermConstructor(SymDoubleGreaterEqual, newOpAssignTerm)
|
registerTermConstructor(SymDoubleGreaterEqual, newOpAssignTerm)
|
||||||
registerTermConstructor(SymAmpersandEqual, newOpAssignTerm)
|
registerTermConstructor(SymAmpersandEqual, newOpAssignTerm)
|
||||||
registerTermConstructor(SymVertBarEqual, newOpAssignTerm)
|
registerTermConstructor(SymVertBarEqual, newOpAssignTerm)
|
||||||
|
registerTermConstructor(SymCaretEqual, newOpAssignTerm)
|
||||||
}
|
}
|
||||||
|
@ -107,9 +107,48 @@ func evalBitwiseOr(ctx ExprContext, opTerm *term) (v any, err error) {
|
|||||||
return
|
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
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymTilde, newBitwiseNotTerm)
|
registerTermConstructor(SymTilde, newBitwiseNotTerm)
|
||||||
registerTermConstructor(SymAmpersand, newBitwiseAndTerm)
|
registerTermConstructor(SymAmpersand, newBitwiseAndTerm)
|
||||||
registerTermConstructor(SymVertBar, newBitwiseOrTerm)
|
registerTermConstructor(SymVertBar, newBitwiseOrTerm)
|
||||||
|
registerTermConstructor(SymCaret, newBitwiseXorTerm)
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ func newIterValueTerm(tk *Token) (inst *term) {
|
|||||||
tk: *tk,
|
tk: *tk,
|
||||||
children: make([]*term, 0, 1),
|
children: make([]*term, 0, 1),
|
||||||
position: posPrefix,
|
position: posPrefix,
|
||||||
priority: priIterValue,
|
priority: priDereference,
|
||||||
evalFunc: evalIterValue,
|
evalFunc: evalIterValue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,6 +33,6 @@ func evalIterValue(ctx ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
// registerTermConstructor(SymOpenClosedRound, newIterValueTerm)
|
// registerTermConstructor(SymOpenClosedRound, newIterValueTerm)
|
||||||
registerTermConstructor(SymCaret, 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
|
tk.Sym = SymChangeSign
|
||||||
} else if tk.Sym == SymPlus {
|
} else if tk.Sym == SymPlus {
|
||||||
tk.Sym = SymUnchangeSign
|
tk.Sym = SymUnchangeSign
|
||||||
|
} else if tk.IsSymbol(SymStar) {
|
||||||
|
tk.SetSymbol(SymDereference)
|
||||||
} else if tk.IsSymbol(SymExclamation) {
|
} 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
|
break
|
||||||
}
|
}
|
||||||
firstToken = false
|
firstToken = false
|
||||||
@ -481,7 +483,7 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
|
|||||||
currentTerm = mapTerm
|
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)
|
currentTerm, err = tree.addToken(tk)
|
||||||
firstToken = true
|
firstToken = true
|
||||||
case SymFuncDef:
|
case SymFuncDef:
|
||||||
@ -518,14 +520,11 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if hasFlag(ctx, allowIndex) {
|
|
||||||
// tk.Sym = SymRange
|
|
||||||
// }
|
|
||||||
currentTerm, err = tree.addToken(tk)
|
currentTerm, err = tree.addToken(tk)
|
||||||
}
|
if tk.IsOneOfA(SymColon, SymRange) {
|
||||||
if tk.IsOneOfA(SymColon, SymRange) {
|
// Colon outside a selector term acts like a separator
|
||||||
// Colon outside a selector term acts like a separator
|
firstToken = true
|
||||||
firstToken = true
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
currentTerm, err = tree.addToken(tk)
|
currentTerm, err = tree.addToken(tk)
|
||||||
|
@ -177,7 +177,11 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
case ',':
|
case ',':
|
||||||
tk = scanner.makeToken(SymComma, ch)
|
tk = scanner.makeToken(SymComma, ch)
|
||||||
case '^':
|
case '^':
|
||||||
tk = scanner.makeToken(SymCaret, ch)
|
if next, _ := scanner.peek(); next == '=' {
|
||||||
|
tk = scanner.moveOn(SymCaretEqual, ch, next)
|
||||||
|
} else {
|
||||||
|
tk = scanner.makeToken(SymCaret, ch)
|
||||||
|
}
|
||||||
case ':':
|
case ':':
|
||||||
if next, _ := scanner.peek(); next == ':' {
|
if next, _ := scanner.peek(); next == ':' {
|
||||||
tk = scanner.moveOn(SymDoubleColon, ch, next)
|
tk = scanner.moveOn(SymDoubleColon, ch, next)
|
||||||
|
@ -100,8 +100,9 @@ func init() {
|
|||||||
SymDoubleGreaterEqual: {">>=", symClassOperator, posInfix}, // 64: '>>='
|
SymDoubleGreaterEqual: {">>=", symClassOperator, posInfix}, // 64: '>>='
|
||||||
SymAmpersandEqual: {"&=", symClassOperator, posInfix}, // 65: '&='
|
SymAmpersandEqual: {"&=", symClassOperator, posInfix}, // 65: '&='
|
||||||
SymVertBarEqual: {"|=", symClassOperator, posInfix}, // 65: '|='
|
SymVertBarEqual: {"|=", symClassOperator, posInfix}, // 65: '|='
|
||||||
SymPlusGreater: {"+>", symClassOperator, posInfix}, // 66: '+>'
|
SymCaretEqual: {"^=", symClassOperator, posInfix}, // 66: '^='
|
||||||
SymLessPlus: {"<+", symClassOperator, posInfix}, // 67: '<+'
|
SymPlusGreater: {"+>", symClassOperator, posInfix}, // 67: '+>'
|
||||||
|
SymLessPlus: {"<+", symClassOperator, posInfix}, // 68: '<+'
|
||||||
// SymChangeSign
|
// SymChangeSign
|
||||||
// SymUnchangeSign
|
// SymUnchangeSign
|
||||||
// SymIdentifier
|
// SymIdentifier
|
||||||
|
@ -75,10 +75,12 @@ const (
|
|||||||
SymDoubleGreaterEqual // 64: '>>='
|
SymDoubleGreaterEqual // 64: '>>='
|
||||||
SymAmpersandEqual // 65: '&='
|
SymAmpersandEqual // 65: '&='
|
||||||
SymVertBarEqual // 65: '|='
|
SymVertBarEqual // 65: '|='
|
||||||
SymPlusGreater // 66: '+>'
|
SymCaretEqual // 66: '^='
|
||||||
SymLessPlus // 67: '<+'
|
SymPlusGreater // 67: '+>'
|
||||||
|
SymLessPlus // 68: '<+'
|
||||||
SymChangeSign
|
SymChangeSign
|
||||||
SymUnchangeSign
|
SymUnchangeSign
|
||||||
|
SymDereference
|
||||||
SymIdentifier
|
SymIdentifier
|
||||||
SymBool
|
SymBool
|
||||||
SymInteger
|
SymInteger
|
||||||
|
@ -9,10 +9,10 @@ import "testing"
|
|||||||
func TestIteratorParser(t *testing.T) {
|
func TestIteratorParser(t *testing.T) {
|
||||||
section := "Iterator"
|
section := "Iterator"
|
||||||
inputs := []inputType{
|
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},
|
/* 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},
|
/* 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},
|
/* 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},
|
/* 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},
|
/* 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},
|
/* 15 */ {`0o10`, int64(8), nil},
|
||||||
/* 16 */ {`0b10`, int64(2), nil},
|
/* 16 */ {`0b10`, int64(2), nil},
|
||||||
/* 17 */ {`~true`, nil, `[1:2] prefix/postfix operator "~" do not support operand 'true' [bool]`},
|
/* 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", ".")
|
// t.Setenv("EXPR_PATH", ".")
|
||||||
|
@ -142,6 +142,6 @@ func TestGeneralParser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// t.Setenv("EXPR_PATH", ".")
|
// t.Setenv("EXPR_PATH", ".")
|
||||||
//runTestSuiteSpec(t, section, inputs, 130)
|
// runTestSuiteSpec(t, section, inputs, 114)
|
||||||
runTestSuite(t, section, inputs)
|
runTestSuite(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user