From eccb0c4dc9aeebc3a194cb0ded26f81286847a63 Mon Sep 17 00:00:00 2001 From: Celestino Amoroso Date: Sun, 29 Dec 2024 19:26:02 +0100 Subject: [PATCH] Added new special operators like &= and <<=. Also made a litle change to scanner function moveOn(): now it moves on the last char passed and only if there are more than one chars. --- operator-assign.go | 13 +++++ operator-binary.go | 104 --------------------------------- operator-bitwise.go | 115 +++++++++++++++++++++++++++++++++++++ operator-shift.go | 52 +++++++---------- scanner.go | 37 ++++++++++-- symbol-map.go | 136 +++++++++++++++++++++++--------------------- symbol.go | 136 +++++++++++++++++++++++--------------------- t_list_test.go | 4 +- t_operator_test.go | 16 +++++- t_strings_test.go | 5 +- term.go | 6 +- 11 files changed, 346 insertions(+), 278 deletions(-) delete mode 100644 operator-binary.go create mode 100644 operator-bitwise.go diff --git a/operator-assign.go b/operator-assign.go index 1a2bf18..c26e52c 100644 --- a/operator-assign.go +++ b/operator-assign.go @@ -183,6 +183,14 @@ func evalOpAssign(ctx ExprContext, opTerm *term) (v any, err error) { v, err = divValues(opTerm, leftValue, rightValue) case SymPercEqual: v, err = remainderValues(opTerm, leftValue, rightValue) + case SymAmpersandEqual: + v, err = bitwiseAnd(opTerm, leftValue, rightValue) + case SymVertBarEqual: + v, err = bitwiseOr(opTerm, leftValue, rightValue) + case SymDoubleLessEqual: + v, err = bitLeftShift(opTerm, leftValue, rightValue) + case SymDoubleGreaterEqual: + v, err = bitRightShift(opTerm, leftValue, rightValue) default: err = opTerm.Errorf("unsupported assign operator %q", opTerm.source()) } @@ -201,4 +209,9 @@ func init() { registerTermConstructor(SymMinusEqual, newOpAssignTerm) registerTermConstructor(SymStarEqual, newOpAssignTerm) registerTermConstructor(SymSlashEqual, newOpAssignTerm) + registerTermConstructor(SymPercEqual, newOpAssignTerm) + registerTermConstructor(SymDoubleLessEqual, newOpAssignTerm) + registerTermConstructor(SymDoubleGreaterEqual, newOpAssignTerm) + registerTermConstructor(SymAmpersandEqual, newOpAssignTerm) + registerTermConstructor(SymVertBarEqual, newOpAssignTerm) } diff --git a/operator-binary.go b/operator-binary.go deleted file mode 100644 index c3b43ab..0000000 --- a/operator-binary.go +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). -// All rights reserved. - -// operator-binary.go -package expr - -//-------- NOT term - -func newBinNotTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 1), - position: posPrefix, - priority: priBinNot, - evalFunc: evalBinaryNot, - } -} - -func evalBinaryNot(ctx ExprContext, opTerm *term) (v any, err error) { - var value any - - if value, err = opTerm.evalPrefix(ctx); err != nil { - return - } - - if IsInteger(value) { - i, _ := value.(int64) - v = ^i - } else { - err = opTerm.errIncompatibleType(value) - } - return -} - -//-------- Binary AND term - -func newBinAndTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priBinAnd, - evalFunc: evalBinaryAnd, - } -} - -func evalBinaryAnd(ctx ExprContext, self *term) (v any, err error) { - var leftValue, rightValue any - var leftInt, rightInt int64 - var lok, rok bool - - if leftValue, rightValue, err = self.evalInfix(ctx); err != nil { - return - } - - leftInt, lok = leftValue.(int64) - rightInt, rok = rightValue.(int64) - - if lok && rok { - v = leftInt & rightInt - } else { - err = self.errIncompatibleTypes(leftValue, rightValue) - } - return -} - -//-------- Binary OR term - -func newBinOrTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priBinOr, - evalFunc: evalBinaryOr, - } -} - -func evalBinaryOr(ctx ExprContext, self *term) (v any, err error) { - var leftValue, rightValue any - var leftInt, rightInt int64 - var lok, rok bool - - if leftValue, rightValue, err = self.evalInfix(ctx); err != nil { - return - } - - leftInt, lok = leftValue.(int64) - rightInt, rok = rightValue.(int64) - - if lok && rok { - v = leftInt | rightInt - } else { - err = self.errIncompatibleTypes(leftValue, rightValue) - } - return -} - -// init -func init() { - registerTermConstructor(SymTilde, newBinNotTerm) - registerTermConstructor(SymAmpersand, newBinAndTerm) - registerTermConstructor(SymVertBar, newBinOrTerm) -} diff --git a/operator-bitwise.go b/operator-bitwise.go new file mode 100644 index 0000000..745fbfb --- /dev/null +++ b/operator-bitwise.go @@ -0,0 +1,115 @@ +// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). +// All rights reserved. + +// operator-bitwise.go +package expr + +//-------- Bitwise NOT term + +func newBitwiseNotTerm(tk *Token) (inst *term) { + return &term{ + tk: *tk, + children: make([]*term, 0, 1), + position: posPrefix, + priority: priBitwiseNot, + evalFunc: evalBitwiseNot, + } +} + +func evalBitwiseNot(ctx ExprContext, opTerm *term) (v any, err error) { + var value any + + if value, err = opTerm.evalPrefix(ctx); err != nil { + return + } + + if IsInteger(value) { + i, _ := value.(int64) + v = ^i + } else { + err = opTerm.errIncompatibleType(value) + } + return +} + +//-------- Bitwise AND term + +func newBitwiseAndTerm(tk *Token) (inst *term) { + return &term{ + tk: *tk, + children: make([]*term, 0, 2), + position: posInfix, + priority: priBitwiseAnd, + evalFunc: evalBitwiseAnd, + } +} + +func bitwiseAnd(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 evalBitwiseAnd(ctx ExprContext, opTerm *term) (v any, err error) { + var leftValue, rightValue any + + if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + return + } + v, err = bitwiseAnd(opTerm, leftValue, rightValue) + return +} + +//-------- Bitwise OR term + +func newBitwiseOrTerm(tk *Token) (inst *term) { + return &term{ + tk: *tk, + children: make([]*term, 0, 2), + position: posInfix, + priority: priBitwiseOr, + evalFunc: evalBitwiseOr, + } +} + +func bitwiseOr(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 evalBitwiseOr(ctx ExprContext, opTerm *term) (v any, err error) { + var leftValue, rightValue any + + if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + return + } + + v, err = bitwiseOr(opTerm, leftValue, rightValue) + return +} + +// init +func init() { + registerTermConstructor(SymTilde, newBitwiseNotTerm) + registerTermConstructor(SymAmpersand, newBitwiseAndTerm) + registerTermConstructor(SymVertBar, newBitwiseOrTerm) +} diff --git a/operator-shift.go b/operator-shift.go index 992e083..7c1e9f7 100644 --- a/operator-shift.go +++ b/operator-shift.go @@ -4,7 +4,7 @@ // operator-shift.go package expr -//-------- shift term +//-------- bit right shift term func newRightShiftTerm(tk *Token) (inst *term) { return &term{ @@ -16,13 +16,7 @@ func newRightShiftTerm(tk *Token) (inst *term) { } } -func evalRightShift(ctx ExprContext, opTerm *term) (v any, err error) { - var leftValue, rightValue any - - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { - return - } - +func bitRightShift(opTerm *term, leftValue, rightValue any) (v any, err error) { if IsInteger(leftValue) && IsInteger(rightValue) { leftInt := leftValue.(int64) rightInt := rightValue.(int64) @@ -33,6 +27,17 @@ func evalRightShift(ctx ExprContext, opTerm *term) (v any, err error) { return } +func evalRightShift(ctx ExprContext, opTerm *term) (v any, err error) { + var leftValue, rightValue any + + if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + return + } + + v, err = bitRightShift(opTerm, leftValue, rightValue) + return +} + func newLeftShiftTerm(tk *Token) (inst *term) { return &term{ tk: *tk, @@ -43,13 +48,7 @@ func newLeftShiftTerm(tk *Token) (inst *term) { } } -func evalLeftShift(ctx ExprContext, opTerm *term) (v any, err error) { - var leftValue, rightValue any - - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { - return - } - +func bitLeftShift(opTerm *term, leftValue, rightValue any) (v any, err error) { if IsInteger(leftValue) && IsInteger(rightValue) { leftInt := leftValue.(int64) rightInt := rightValue.(int64) @@ -60,23 +59,16 @@ func evalLeftShift(ctx ExprContext, opTerm *term) (v any, err error) { return } -// func evalAssignAppend(ctx ExprContext, self *term) (v any, err error) { -// var leftValue, rightValue any +func evalLeftShift(ctx ExprContext, opTerm *term) (v any, err error) { + var leftValue, rightValue any -// if leftValue, rightValue, err = self.evalInfix(ctx); err != nil { -// return -// } + if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + return + } -// if IsList(leftValue) { -// list, _ := leftValue.(*ListType) -// newList := append(*list, rightValue) -// v = &newList -// if -// } else { -// err = self.errIncompatibleTypes(leftValue, rightValue) -// } -// return -// } + v, err = bitLeftShift(opTerm, leftValue, rightValue) + return +} // init func init() { diff --git a/scanner.go b/scanner.go index e9e52bf..362979a 100644 --- a/scanner.go +++ b/scanner.go @@ -169,6 +169,8 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { case '|': if next, _ := scanner.peek(); next == '|' { tk = scanner.moveOn(SymDoubleVertBar, ch, next) + } else if next, _ = scanner.peek(); next == '=' { + tk = scanner.moveOn(SymVertBarEqual, ch, next) } else { tk = scanner.makeToken(SymVertBar, ch) } @@ -234,11 +236,17 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { case '&': if next, _ := scanner.peek(); next == '&' { tk = scanner.moveOn(SymDoubleAmpersand, ch, next) + } else if next, _ = scanner.peek(); next == '=' { + tk = scanner.moveOn(SymAmpersandEqual, ch, next) } else { tk = scanner.makeToken(SymAmpersand, ch) } case '%': - tk = scanner.makeToken(SymPercent, ch) + if next, _ := scanner.peek(); next == '=' { + tk = scanner.moveOn(SymPercEqual, ch, next) + } else { + tk = scanner.makeToken(SymPercent, ch) + } case '#': tk = scanner.makeToken(SymHash, ch) case '@': @@ -267,7 +275,14 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { if next, _ := scanner.peek(); next == '=' { tk = scanner.moveOn(SymLessOrEqual, ch, next) } else if next == '<' { - tk = scanner.moveOn(SymDoubleLess, ch, next) + scanner.readChar() + next2, _ := scanner.readChar() + scanner.unreadChar() + if next2 == '=' { + tk = scanner.moveOn(SymDoubleLessEqual, ch, next, next2) + } else { + tk = scanner.accept(SymDoubleLess, ch, next) + } } else if next == '>' { tk = scanner.moveOn(SymLessGreater, ch, next) } else if next == '+' { @@ -279,7 +294,14 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { if next, _ := scanner.peek(); next == '=' { tk = scanner.moveOn(SymGreaterOrEqual, ch, next) } else if next == '>' { - tk = scanner.moveOn(SymDoubleGreater, ch, next) + scanner.readChar() + next2, _ := scanner.readChar() + scanner.unreadChar() + if next2 == '=' { + tk = scanner.moveOn(SymDoubleGreaterEqual, ch, next, next2) + } else { + tk = scanner.accept(SymDoubleGreater, ch, next) + } } else { tk = scanner.makeToken(SymGreater, ch) } @@ -634,9 +656,16 @@ func (scanner *scanner) translate(sym Symbol) Symbol { func (scanner *scanner) moveOn(sym Symbol, chars ...byte) (tk *Token) { tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), string(chars)) - for i := 1; i < len(chars); i++ { + // for i := 1; i < len(chars); i++ { + if len(chars) > 1 { scanner.readChar() } + // } + return +} + +func (scanner *scanner) accept(sym Symbol, chars ...byte) (tk *Token) { + tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), string(chars)) return } diff --git a/symbol-map.go b/symbol-map.go index 5ee8213..0f321f7 100644 --- a/symbol-map.go +++ b/symbol-map.go @@ -31,72 +31,76 @@ type symbolSpec struct { func init() { symbolMap = map[Symbol]symbolSpec{ - SymUnknown: {"", symClassOther}, // -1: Unknown symbol - SymNone: {"", symClassOther}, // 0: Null value for variable of type symbol - SymError: {"", symClassOther}, // 1: Error reading from stream - SymEos: {"", symClassOther}, // 2: End of stream - SymMinus: {"-", symClassOperator}, // 3: '-' - SymMinusEqual: {"-=", symClassOperator}, // 4: '-=' - SymDoubleMinus: {"--", symClassOperator}, // 5: '--' - SymPlus: {"+", symClassOperator}, // 6: '+' - SymPlusEqual: {"+=", symClassOperator}, // 7: '+=' - SymDoublePlus: {"++", symClassOperator}, // 8: '++' - SymStar: {"*", symClassOperator}, // 9: '*' - SymDoubleStar: {"**", symClassOperator}, // 10: '**' - SymSlash: {"/", symClassOperator}, // 11: '/' - SymBackSlash: {"\\", symClassOperator}, // 12: '\' - SymVertBar: {"|", symClassOperator}, // 13: '|' - SymDoubleVertBar: {"||", symClassOperator}, // 14: '||' - SymComma: {",", symClassOperator}, // 15: ',' - SymColon: {":", symClassOperator}, // 16: ':' - SymSemiColon: {";", symClassOperator}, // 17: ';' - SymDot: {".", symClassOperator}, // 18: '.' - SymDotSlash: {"./", symClassOperator}, // 19: './' - SymQuote: {"'", symClassDelimiter}, // 20: '\'' - SymDoubleQuote: {"\"", symClassDelimiter}, // 21: '"' - SymBackTick: {"`", symClassOperator}, // 22: '`' - SymExclamation: {"!", symClassPostOp}, // 23: '!' - SymQuestion: {"?", symClassOperator}, // 24: '?' - SymAmpersand: {"&", symClassOperator}, // 25: '&' - SymDoubleAmpersand: {"&&", symClassOperator}, // 26: '&&' - SymPercent: {"%", symClassOperator}, // 27: '%' - SymAt: {"@", symClassOperator}, // 28: '@' - SymUndescore: {"_", symClassOperator}, // 29: '_' - SymEqual: {"=", symClassOperator}, // 30: '=' - SymDoubleEqual: {"==", symClassOperator}, // 31: '==' - SymLess: {"<", symClassOperator}, // 32: '<' - SymLessOrEqual: {"<=", symClassOperator}, // 33: '<=' - SymGreater: {">", symClassOperator}, // 34: '>' - SymGreaterOrEqual: {">=", symClassOperator}, // 35: '>=' - SymLessGreater: {"<>", symClassOperator}, // 36: '<>' - SymNotEqual: {"!=", symClassOperator}, // 37: '!=' - SymDollar: {"$", symClassOperator}, // 38: '$' - SymHash: {"#", symClassOperator}, // 39: '#' - SymOpenRound: {"(", symClassParenthesis}, // 40: '(' - SymClosedRound: {")", symClassParenthesis}, // 41: ')' - SymOpenSquare: {"[", symClassParenthesis}, // 42: '[' - SymClosedSquare: {"]", symClassParenthesis}, // 43: ']' - SymOpenBrace: {"{", symClassParenthesis}, // 44: '{' - SymClosedBrace: {"}", symClassParenthesis}, // 45: '}' - SymTilde: {"~", symClassOperator}, // 46: '~' - SymDoubleQuestion: {"??", symClassOperator}, // 47: '??' - SymQuestionEqual: {"?=", symClassOperator}, // 48: '?=' - SymQuestionExclam: {"?!", symClassOperator}, // 49: '?!' - SymDoubleAt: {"@@", symClassOperator}, // 50: '@@' - SymDoubleColon: {"::", symClassOperator}, // 51: '::' - SymDoubleGreater: {">>", symClassOperator}, // 52: '>>' - SymDoubleLess: {"<<", symClassOperator}, // 53: '<<' - SymCaret: {"^", symClassOperator}, // 54: '^' - SymDollarRound: {"$(", symClassOperator}, // 55: '$(' - SymOpenClosedRound: {"()", symClassPostOp}, // 56: '()' - SymDoubleDollar: {"$$", symClassOperator}, // 57: '$$' - SymDoubleDot: {"..", symClassOperator}, // 58: '..' - SymTripleDot: {"...", symClassOperator}, // 59: '...' - SymStarEqual: {"*=", symClassOperator}, // 60: '*=' - SymSlashEqual: {"/=", symClassOperator}, // 61: '/=' - SymPercEqual: {"%=", symClassOperator}, // 62: '%=' - SymPlusGreater: {"+>", symClassOperator}, // 63: '+>' - SymLessPlus: {"<+", symClassOperator}, // 64: '<+' + SymUnknown: {"", symClassOther}, // -1: Unknown symbol + SymNone: {"", symClassOther}, // 0: Null value for variable of type symbol + SymError: {"", symClassOther}, // 1: Error reading from stream + SymEos: {"", symClassOther}, // 2: End of stream + SymMinus: {"-", symClassOperator}, // 3: '-' + SymMinusEqual: {"-=", symClassOperator}, // 4: '-=' + SymDoubleMinus: {"--", symClassOperator}, // 5: '--' + SymPlus: {"+", symClassOperator}, // 6: '+' + SymPlusEqual: {"+=", symClassOperator}, // 7: '+=' + SymDoublePlus: {"++", symClassOperator}, // 8: '++' + SymStar: {"*", symClassOperator}, // 9: '*' + SymDoubleStar: {"**", symClassOperator}, // 10: '**' + SymSlash: {"/", symClassOperator}, // 11: '/' + SymBackSlash: {"\\", symClassOperator}, // 12: '\' + SymVertBar: {"|", symClassOperator}, // 13: '|' + SymDoubleVertBar: {"||", symClassOperator}, // 14: '||' + SymComma: {",", symClassOperator}, // 15: ',' + SymColon: {":", symClassOperator}, // 16: ':' + SymSemiColon: {";", symClassOperator}, // 17: ';' + SymDot: {".", symClassOperator}, // 18: '.' + SymDotSlash: {"./", symClassOperator}, // 19: './' + SymQuote: {"'", symClassDelimiter}, // 20: '\'' + SymDoubleQuote: {"\"", symClassDelimiter}, // 21: '"' + SymBackTick: {"`", symClassOperator}, // 22: '`' + SymExclamation: {"!", symClassPostOp}, // 23: '!' + SymQuestion: {"?", symClassOperator}, // 24: '?' + SymAmpersand: {"&", symClassOperator}, // 25: '&' + SymDoubleAmpersand: {"&&", symClassOperator}, // 26: '&&' + SymPercent: {"%", symClassOperator}, // 27: '%' + SymAt: {"@", symClassOperator}, // 28: '@' + SymUndescore: {"_", symClassOperator}, // 29: '_' + SymEqual: {"=", symClassOperator}, // 30: '=' + SymDoubleEqual: {"==", symClassOperator}, // 31: '==' + SymLess: {"<", symClassOperator}, // 32: '<' + SymLessOrEqual: {"<=", symClassOperator}, // 33: '<=' + SymGreater: {">", symClassOperator}, // 34: '>' + SymGreaterOrEqual: {">=", symClassOperator}, // 35: '>=' + SymLessGreater: {"<>", symClassOperator}, // 36: '<>' + SymNotEqual: {"!=", symClassOperator}, // 37: '!=' + SymDollar: {"$", symClassOperator}, // 38: '$' + SymHash: {"#", symClassOperator}, // 39: '#' + SymOpenRound: {"(", symClassParenthesis}, // 40: '(' + SymClosedRound: {")", symClassParenthesis}, // 41: ')' + SymOpenSquare: {"[", symClassParenthesis}, // 42: '[' + SymClosedSquare: {"]", symClassParenthesis}, // 43: ']' + SymOpenBrace: {"{", symClassParenthesis}, // 44: '{' + SymClosedBrace: {"}", symClassParenthesis}, // 45: '}' + SymTilde: {"~", symClassOperator}, // 46: '~' + SymDoubleQuestion: {"??", symClassOperator}, // 47: '??' + SymQuestionEqual: {"?=", symClassOperator}, // 48: '?=' + SymQuestionExclam: {"?!", symClassOperator}, // 49: '?!' + SymDoubleAt: {"@@", symClassOperator}, // 50: '@@' + SymDoubleColon: {"::", symClassOperator}, // 51: '::' + SymDoubleGreater: {">>", symClassOperator}, // 52: '>>' + SymDoubleLess: {"<<", symClassOperator}, // 53: '<<' + SymCaret: {"^", symClassOperator}, // 54: '^' + SymDollarRound: {"$(", symClassOperator}, // 55: '$(' + SymOpenClosedRound: {"()", symClassPostOp}, // 56: '()' + SymDoubleDollar: {"$$", symClassOperator}, // 57: '$$' + SymDoubleDot: {"..", symClassOperator}, // 58: '..' + SymTripleDot: {"...", symClassOperator}, // 59: '...' + SymStarEqual: {"*=", symClassOperator}, // 60: '*=' + SymSlashEqual: {"/=", symClassOperator}, // 61: '/=' + SymPercEqual: {"%=", symClassOperator}, // 62: '%=' + SymDoubleLessEqual: {"<<=", symClassOperator}, // 63: '<<=' + SymDoubleGreaterEqual: {">>=", symClassOperator}, // 64: '>>=' + SymAmpersandEqual: {"&=", symClassOperator}, // 65: '&=' + SymVertBarEqual: {"|=", symClassOperator}, // 65: '|=' + SymPlusGreater: {"+>", symClassOperator}, // 66: '+>' + SymLessPlus: {"<+", symClassOperator}, // 67: '<+' // SymChangeSign // SymUnchangeSign // SymIdentifier diff --git a/symbol.go b/symbol.go index 88a62ba..f492969 100644 --- a/symbol.go +++ b/symbol.go @@ -7,72 +7,76 @@ package expr type Symbol int16 const ( - SymUnknown Symbol = iota - 1 // -1: Unknown symbol - SymNone // 0: Null value for variable of type symbol - SymError // 1: Error reading from stream - SymEos // 2: End of stream - SymMinus // 3: '-' - SymMinusEqual // 4: '-=' - SymDoubleMinus // 5: '--' - SymPlus // 6: '+' - SymPlusEqual // 7: '+=' - SymDoublePlus // 8: '++' - SymStar // 9: '*' - SymDoubleStar // 10: '**' - SymSlash // 11: '/' - SymBackSlash // 12: '\' - SymVertBar // 13: '|' - SymDoubleVertBar // 14: '||' - SymComma // 15: ',' - SymColon // 16: ':' - SymSemiColon // 17: ';' - SymDot // 18: '.' - SymDotSlash // 19: './' - SymQuote // 20: '\'' - SymDoubleQuote // 21: '"' - SymBackTick // 22: '`' - SymExclamation // 23: '!' - SymQuestion // 24: '?' - SymAmpersand // 25: '&' - SymDoubleAmpersand // 26: '&&' - SymPercent // 27: '%' - SymAt // 28: '@' - SymUndescore // 29: '_' - SymEqual // 30: '=' - SymDoubleEqual // 31: '==' - SymLess // 32: '<' - SymLessOrEqual // 33: '<=' - SymGreater // 34: '>' - SymGreaterOrEqual // 35: '>=' - SymLessGreater // 36: '<>' - SymNotEqual // 37: '!=' - SymDollar // 38: '$' - SymHash // 39: '#' - SymOpenRound // 40: '(' - SymClosedRound // 41: ')' - SymOpenSquare // 42: '[' - SymClosedSquare // 43: ']' - SymOpenBrace // 44: '{' - SymClosedBrace // 45: '}' - SymTilde // 46: '~' - SymDoubleQuestion // 47: '??' - SymQuestionEqual // 48: '?=' - SymQuestionExclam // 49: '?!' - SymDoubleAt // 50: '@@' - SymDoubleColon // 51: '::' - SymDoubleGreater // 52: '>>' - SymDoubleLess // 53: '<<' - SymCaret // 54: '^' - SymDollarRound // 55: '$(' - SymOpenClosedRound // 56: '()' - SymDoubleDollar // 57: '$$' - SymDoubleDot // 58: '..' - SymTripleDot // 59: '...' - SymStarEqual // 60: '*=' - SymSlashEqual // 61: '/=' - SymPercEqual // 62: '%=' - SymPlusGreater // 63: '+>' - SymLessPlus // 64: '<+' + SymUnknown Symbol = iota - 1 // -1: Unknown symbol + SymNone // 0: Null value for variable of type symbol + SymError // 1: Error reading from stream + SymEos // 2: End of stream + SymMinus // 3: '-' + SymMinusEqual // 4: '-=' + SymDoubleMinus // 5: '--' + SymPlus // 6: '+' + SymPlusEqual // 7: '+=' + SymDoublePlus // 8: '++' + SymStar // 9: '*' + SymDoubleStar // 10: '**' + SymSlash // 11: '/' + SymBackSlash // 12: '\' + SymVertBar // 13: '|' + SymDoubleVertBar // 14: '||' + SymComma // 15: ',' + SymColon // 16: ':' + SymSemiColon // 17: ';' + SymDot // 18: '.' + SymDotSlash // 19: './' + SymQuote // 20: '\'' + SymDoubleQuote // 21: '"' + SymBackTick // 22: '`' + SymExclamation // 23: '!' + SymQuestion // 24: '?' + SymAmpersand // 25: '&' + SymDoubleAmpersand // 26: '&&' + SymPercent // 27: '%' + SymAt // 28: '@' + SymUndescore // 29: '_' + SymEqual // 30: '=' + SymDoubleEqual // 31: '==' + SymLess // 32: '<' + SymLessOrEqual // 33: '<=' + SymGreater // 34: '>' + SymGreaterOrEqual // 35: '>=' + SymLessGreater // 36: '<>' + SymNotEqual // 37: '!=' + SymDollar // 38: '$' + SymHash // 39: '#' + SymOpenRound // 40: '(' + SymClosedRound // 41: ')' + SymOpenSquare // 42: '[' + SymClosedSquare // 43: ']' + SymOpenBrace // 44: '{' + SymClosedBrace // 45: '}' + SymTilde // 46: '~' + SymDoubleQuestion // 47: '??' + SymQuestionEqual // 48: '?=' + SymQuestionExclam // 49: '?!' + SymDoubleAt // 50: '@@' + SymDoubleColon // 51: '::' + SymDoubleGreater // 52: '>>' + SymDoubleLess // 53: '<<' + SymCaret // 54: '^' + SymDollarRound // 55: '$(' + SymOpenClosedRound // 56: '()' + SymDoubleDollar // 57: '$$' + SymDoubleDot // 58: '..' + SymTripleDot // 59: '...' + SymStarEqual // 60: '*=' + SymSlashEqual // 61: '/=' + SymPercEqual // 62: '%=' + SymDoubleLessEqual // 63: '<<=' + SymDoubleGreaterEqual // 64: '>>=' + SymAmpersandEqual // 65: '&=' + SymVertBarEqual // 65: '|=' + SymPlusGreater // 66: '+>' + SymLessPlus // 67: '<+' SymChangeSign SymUnchangeSign SymIdentifier diff --git a/t_list_test.go b/t_list_test.go index 13aea6c..a92ad37 100644 --- a/t_list_test.go +++ b/t_list_test.go @@ -38,9 +38,9 @@ func TestListParser(t *testing.T) { /* 24 */ {`["a","b","c","d"][1]`, "b", nil}, /* 25 */ {`["a","b","c","d"][1,1]`, nil, `[1:19] one index only is allowed`}, /* 26 */ {`[0,1,2,3,4][:]`, newListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil}, - /* 27 */ {`["a", "b", "c"] << ;`, nil, `[1:18] infix operator "<<" requires two non-nil operands, got 1`}, + /* 27 */ {`["a", "b", "c"] <+ ;`, nil, `[1:18] infix operator "<+" requires two non-nil operands, got 1`}, /* 28 */ {`2 << 3;`, int64(16), nil}, - /* 29 */ {`but >> ["a", "b", "c"]`, nil, `[1:6] infix operator ">>" requires two non-nil operands, got 0`}, + /* 29 */ {`but +> ["a", "b", "c"]`, nil, `[1:6] infix operator "+>" requires two non-nil operands, got 0`}, /* 30 */ {`2 >> 3;`, int64(0), nil}, /* 31 */ {`a=[1,2]; a<+3`, newListA(int64(1), int64(2), int64(3)), nil}, /* 32 */ {`a=[1,2]; 5+>a`, newListA(int64(5), int64(1), int64(2)), nil}, diff --git a/t_operator_test.go b/t_operator_test.go index 1ff894b..c2a83fc 100644 --- a/t_operator_test.go +++ b/t_operator_test.go @@ -14,10 +14,24 @@ func TestOperator(t *testing.T) { /* 1 */ {`a=1; unset "a"; a`, nil, `undefined variable or function "a"`}, /* 2 */ {`a=1; unset ["a", "b"]`, int64(1), nil}, /* 3 */ {`f=func(){3}; unset "f()"`, int64(1), nil}, + /* 4 */ {`a=1; a<<=1+0`, int64(2), nil}, + /* 5 */ {`a=2; a>>=1+0`, int64(1), nil}, + /* 6 */ {`1<<1`, int64(2), nil}, + /* 7 */ {`1>>1`, int64(0), nil}, + /* 8 */ {`1|2`, int64(3), nil}, + /* 9 */ {`a=1; a|=2`, int64(3), nil}, + /* 10 */ {`3&1`, int64(1), nil}, + /* 11 */ {`a=3; a&=1`, int64(1), nil}, + /* 12 */ {`~1`, int64(-2), nil}, + /* 13 */ {`0x10`, int64(16), nil}, + /* 14 */ {`0x1X`, nil, `[1:5] two adjacent operators: "1" and "X"`}, + /* 15 */ {`0o10`, int64(8), nil}, + /* 16 */ {`0b10`, int64(2), nil}, + /* 17 */ {`~true`, nil, `[1:2] prefix/postfix operator "~" do not support operand 'true' [bool]`}, } // t.Setenv("EXPR_PATH", ".") - //runTestSuiteSpec(t, section, inputs, 3) + // runTestSuiteSpec(t, section, inputs, 4) runTestSuite(t, section, inputs) } diff --git a/t_strings_test.go b/t_strings_test.go index 50a05f4..52042ec 100644 --- a/t_strings_test.go +++ b/t_strings_test.go @@ -9,6 +9,7 @@ import ( ) func TestStringsParser(t *testing.T) { + section := "String" inputs := []inputType{ /* 1 */ {`"uno" + "due"`, `unodue`, nil}, /* 2 */ {`"uno" + 2`, `uno2`, nil}, @@ -22,6 +23,6 @@ func TestStringsParser(t *testing.T) { /* 10 */ {`"AF3B0Dz" / 0`, nil, "[1:12] division by zero"}, } - // runTestSuiteSpec(t, "String", inputs, 8) - runTestSuite(t, "String", inputs) + // runTestSuiteSpec(t, section, inputs, 8) + runTestSuite(t, section, inputs) } diff --git a/term.go b/term.go index 4682a63..b3c91e4 100644 --- a/term.go +++ b/term.go @@ -20,9 +20,9 @@ const ( priAnd priNot priRelational - priBinOr - priBinAnd - priBinNot + priBitwiseOr + priBitwiseAnd + priBitwiseNot priSum priProduct priFraction