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.
This commit is contained in:
parent
e43823740f
commit
eccb0c4dc9
@ -183,6 +183,14 @@ func evalOpAssign(ctx ExprContext, opTerm *term) (v any, err error) {
|
|||||||
v, err = divValues(opTerm, leftValue, rightValue)
|
v, err = divValues(opTerm, leftValue, rightValue)
|
||||||
case SymPercEqual:
|
case SymPercEqual:
|
||||||
v, err = remainderValues(opTerm, leftValue, rightValue)
|
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:
|
default:
|
||||||
err = opTerm.Errorf("unsupported assign operator %q", opTerm.source())
|
err = opTerm.Errorf("unsupported assign operator %q", opTerm.source())
|
||||||
}
|
}
|
||||||
@ -201,4 +209,9 @@ func init() {
|
|||||||
registerTermConstructor(SymMinusEqual, newOpAssignTerm)
|
registerTermConstructor(SymMinusEqual, newOpAssignTerm)
|
||||||
registerTermConstructor(SymStarEqual, newOpAssignTerm)
|
registerTermConstructor(SymStarEqual, newOpAssignTerm)
|
||||||
registerTermConstructor(SymSlashEqual, newOpAssignTerm)
|
registerTermConstructor(SymSlashEqual, newOpAssignTerm)
|
||||||
|
registerTermConstructor(SymPercEqual, newOpAssignTerm)
|
||||||
|
registerTermConstructor(SymDoubleLessEqual, newOpAssignTerm)
|
||||||
|
registerTermConstructor(SymDoubleGreaterEqual, newOpAssignTerm)
|
||||||
|
registerTermConstructor(SymAmpersandEqual, newOpAssignTerm)
|
||||||
|
registerTermConstructor(SymVertBarEqual, newOpAssignTerm)
|
||||||
}
|
}
|
||||||
|
@ -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)
|
|
||||||
}
|
|
115
operator-bitwise.go
Normal file
115
operator-bitwise.go
Normal file
@ -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)
|
||||||
|
}
|
@ -4,7 +4,7 @@
|
|||||||
// operator-shift.go
|
// operator-shift.go
|
||||||
package expr
|
package expr
|
||||||
|
|
||||||
//-------- shift term
|
//-------- bit right shift term
|
||||||
|
|
||||||
func newRightShiftTerm(tk *Token) (inst *term) {
|
func newRightShiftTerm(tk *Token) (inst *term) {
|
||||||
return &term{
|
return &term{
|
||||||
@ -16,13 +16,7 @@ func newRightShiftTerm(tk *Token) (inst *term) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func evalRightShift(ctx ExprContext, opTerm *term) (v any, err error) {
|
func bitRightShift(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||||
var leftValue, rightValue any
|
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if IsInteger(leftValue) && IsInteger(rightValue) {
|
if IsInteger(leftValue) && IsInteger(rightValue) {
|
||||||
leftInt := leftValue.(int64)
|
leftInt := leftValue.(int64)
|
||||||
rightInt := rightValue.(int64)
|
rightInt := rightValue.(int64)
|
||||||
@ -33,6 +27,17 @@ func evalRightShift(ctx ExprContext, opTerm *term) (v any, err error) {
|
|||||||
return
|
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) {
|
func newLeftShiftTerm(tk *Token) (inst *term) {
|
||||||
return &term{
|
return &term{
|
||||||
tk: *tk,
|
tk: *tk,
|
||||||
@ -43,13 +48,7 @@ func newLeftShiftTerm(tk *Token) (inst *term) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func evalLeftShift(ctx ExprContext, opTerm *term) (v any, err error) {
|
func bitLeftShift(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||||
var leftValue, rightValue any
|
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if IsInteger(leftValue) && IsInteger(rightValue) {
|
if IsInteger(leftValue) && IsInteger(rightValue) {
|
||||||
leftInt := leftValue.(int64)
|
leftInt := leftValue.(int64)
|
||||||
rightInt := rightValue.(int64)
|
rightInt := rightValue.(int64)
|
||||||
@ -60,23 +59,16 @@ func evalLeftShift(ctx ExprContext, opTerm *term) (v any, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// func evalAssignAppend(ctx ExprContext, self *term) (v any, err error) {
|
func evalLeftShift(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||||
// var leftValue, rightValue any
|
var leftValue, rightValue any
|
||||||
|
|
||||||
// if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if IsList(leftValue) {
|
v, err = bitLeftShift(opTerm, leftValue, rightValue)
|
||||||
// list, _ := leftValue.(*ListType)
|
return
|
||||||
// newList := append(*list, rightValue)
|
}
|
||||||
// v = &newList
|
|
||||||
// if
|
|
||||||
// } else {
|
|
||||||
// err = self.errIncompatibleTypes(leftValue, rightValue)
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
|
37
scanner.go
37
scanner.go
@ -169,6 +169,8 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
case '|':
|
case '|':
|
||||||
if next, _ := scanner.peek(); next == '|' {
|
if next, _ := scanner.peek(); next == '|' {
|
||||||
tk = scanner.moveOn(SymDoubleVertBar, ch, next)
|
tk = scanner.moveOn(SymDoubleVertBar, ch, next)
|
||||||
|
} else if next, _ = scanner.peek(); next == '=' {
|
||||||
|
tk = scanner.moveOn(SymVertBarEqual, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymVertBar, ch)
|
tk = scanner.makeToken(SymVertBar, ch)
|
||||||
}
|
}
|
||||||
@ -234,11 +236,17 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
case '&':
|
case '&':
|
||||||
if next, _ := scanner.peek(); next == '&' {
|
if next, _ := scanner.peek(); next == '&' {
|
||||||
tk = scanner.moveOn(SymDoubleAmpersand, ch, next)
|
tk = scanner.moveOn(SymDoubleAmpersand, ch, next)
|
||||||
|
} else if next, _ = scanner.peek(); next == '=' {
|
||||||
|
tk = scanner.moveOn(SymAmpersandEqual, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymAmpersand, ch)
|
tk = scanner.makeToken(SymAmpersand, ch)
|
||||||
}
|
}
|
||||||
case '%':
|
case '%':
|
||||||
tk = scanner.makeToken(SymPercent, ch)
|
if next, _ := scanner.peek(); next == '=' {
|
||||||
|
tk = scanner.moveOn(SymPercEqual, ch, next)
|
||||||
|
} else {
|
||||||
|
tk = scanner.makeToken(SymPercent, ch)
|
||||||
|
}
|
||||||
case '#':
|
case '#':
|
||||||
tk = scanner.makeToken(SymHash, ch)
|
tk = scanner.makeToken(SymHash, ch)
|
||||||
case '@':
|
case '@':
|
||||||
@ -267,7 +275,14 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
if next, _ := scanner.peek(); next == '=' {
|
if next, _ := scanner.peek(); next == '=' {
|
||||||
tk = scanner.moveOn(SymLessOrEqual, ch, next)
|
tk = scanner.moveOn(SymLessOrEqual, ch, next)
|
||||||
} else if 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 == '>' {
|
} else if next == '>' {
|
||||||
tk = scanner.moveOn(SymLessGreater, ch, next)
|
tk = scanner.moveOn(SymLessGreater, ch, next)
|
||||||
} else if next == '+' {
|
} else if next == '+' {
|
||||||
@ -279,7 +294,14 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
if next, _ := scanner.peek(); next == '=' {
|
if next, _ := scanner.peek(); next == '=' {
|
||||||
tk = scanner.moveOn(SymGreaterOrEqual, ch, next)
|
tk = scanner.moveOn(SymGreaterOrEqual, ch, next)
|
||||||
} else if 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 {
|
} else {
|
||||||
tk = scanner.makeToken(SymGreater, ch)
|
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) {
|
func (scanner *scanner) moveOn(sym Symbol, chars ...byte) (tk *Token) {
|
||||||
tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), string(chars))
|
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()
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
136
symbol-map.go
136
symbol-map.go
@ -31,72 +31,76 @@ type symbolSpec struct {
|
|||||||
func init() {
|
func init() {
|
||||||
|
|
||||||
symbolMap = map[Symbol]symbolSpec{
|
symbolMap = map[Symbol]symbolSpec{
|
||||||
SymUnknown: {"<unknown>", symClassOther}, // -1: Unknown symbol
|
SymUnknown: {"<unknown>", symClassOther}, // -1: Unknown symbol
|
||||||
SymNone: {"<null>", symClassOther}, // 0: Null value for variable of type symbol
|
SymNone: {"<null>", symClassOther}, // 0: Null value for variable of type symbol
|
||||||
SymError: {"<error>", symClassOther}, // 1: Error reading from stream
|
SymError: {"<error>", symClassOther}, // 1: Error reading from stream
|
||||||
SymEos: {"<eos>", symClassOther}, // 2: End of stream
|
SymEos: {"<eos>", symClassOther}, // 2: End of stream
|
||||||
SymMinus: {"-", symClassOperator}, // 3: '-'
|
SymMinus: {"-", symClassOperator}, // 3: '-'
|
||||||
SymMinusEqual: {"-=", symClassOperator}, // 4: '-='
|
SymMinusEqual: {"-=", symClassOperator}, // 4: '-='
|
||||||
SymDoubleMinus: {"--", symClassOperator}, // 5: '--'
|
SymDoubleMinus: {"--", symClassOperator}, // 5: '--'
|
||||||
SymPlus: {"+", symClassOperator}, // 6: '+'
|
SymPlus: {"+", symClassOperator}, // 6: '+'
|
||||||
SymPlusEqual: {"+=", symClassOperator}, // 7: '+='
|
SymPlusEqual: {"+=", symClassOperator}, // 7: '+='
|
||||||
SymDoublePlus: {"++", symClassOperator}, // 8: '++'
|
SymDoublePlus: {"++", symClassOperator}, // 8: '++'
|
||||||
SymStar: {"*", symClassOperator}, // 9: '*'
|
SymStar: {"*", symClassOperator}, // 9: '*'
|
||||||
SymDoubleStar: {"**", symClassOperator}, // 10: '**'
|
SymDoubleStar: {"**", symClassOperator}, // 10: '**'
|
||||||
SymSlash: {"/", symClassOperator}, // 11: '/'
|
SymSlash: {"/", symClassOperator}, // 11: '/'
|
||||||
SymBackSlash: {"\\", symClassOperator}, // 12: '\'
|
SymBackSlash: {"\\", symClassOperator}, // 12: '\'
|
||||||
SymVertBar: {"|", symClassOperator}, // 13: '|'
|
SymVertBar: {"|", symClassOperator}, // 13: '|'
|
||||||
SymDoubleVertBar: {"||", symClassOperator}, // 14: '||'
|
SymDoubleVertBar: {"||", symClassOperator}, // 14: '||'
|
||||||
SymComma: {",", symClassOperator}, // 15: ','
|
SymComma: {",", symClassOperator}, // 15: ','
|
||||||
SymColon: {":", symClassOperator}, // 16: ':'
|
SymColon: {":", symClassOperator}, // 16: ':'
|
||||||
SymSemiColon: {";", symClassOperator}, // 17: ';'
|
SymSemiColon: {";", symClassOperator}, // 17: ';'
|
||||||
SymDot: {".", symClassOperator}, // 18: '.'
|
SymDot: {".", symClassOperator}, // 18: '.'
|
||||||
SymDotSlash: {"./", symClassOperator}, // 19: './'
|
SymDotSlash: {"./", symClassOperator}, // 19: './'
|
||||||
SymQuote: {"'", symClassDelimiter}, // 20: '\''
|
SymQuote: {"'", symClassDelimiter}, // 20: '\''
|
||||||
SymDoubleQuote: {"\"", symClassDelimiter}, // 21: '"'
|
SymDoubleQuote: {"\"", symClassDelimiter}, // 21: '"'
|
||||||
SymBackTick: {"`", symClassOperator}, // 22: '`'
|
SymBackTick: {"`", symClassOperator}, // 22: '`'
|
||||||
SymExclamation: {"!", symClassPostOp}, // 23: '!'
|
SymExclamation: {"!", symClassPostOp}, // 23: '!'
|
||||||
SymQuestion: {"?", symClassOperator}, // 24: '?'
|
SymQuestion: {"?", symClassOperator}, // 24: '?'
|
||||||
SymAmpersand: {"&", symClassOperator}, // 25: '&'
|
SymAmpersand: {"&", symClassOperator}, // 25: '&'
|
||||||
SymDoubleAmpersand: {"&&", symClassOperator}, // 26: '&&'
|
SymDoubleAmpersand: {"&&", symClassOperator}, // 26: '&&'
|
||||||
SymPercent: {"%", symClassOperator}, // 27: '%'
|
SymPercent: {"%", symClassOperator}, // 27: '%'
|
||||||
SymAt: {"@", symClassOperator}, // 28: '@'
|
SymAt: {"@", symClassOperator}, // 28: '@'
|
||||||
SymUndescore: {"_", symClassOperator}, // 29: '_'
|
SymUndescore: {"_", symClassOperator}, // 29: '_'
|
||||||
SymEqual: {"=", symClassOperator}, // 30: '='
|
SymEqual: {"=", symClassOperator}, // 30: '='
|
||||||
SymDoubleEqual: {"==", symClassOperator}, // 31: '=='
|
SymDoubleEqual: {"==", symClassOperator}, // 31: '=='
|
||||||
SymLess: {"<", symClassOperator}, // 32: '<'
|
SymLess: {"<", symClassOperator}, // 32: '<'
|
||||||
SymLessOrEqual: {"<=", symClassOperator}, // 33: '<='
|
SymLessOrEqual: {"<=", symClassOperator}, // 33: '<='
|
||||||
SymGreater: {">", symClassOperator}, // 34: '>'
|
SymGreater: {">", symClassOperator}, // 34: '>'
|
||||||
SymGreaterOrEqual: {">=", symClassOperator}, // 35: '>='
|
SymGreaterOrEqual: {">=", symClassOperator}, // 35: '>='
|
||||||
SymLessGreater: {"<>", symClassOperator}, // 36: '<>'
|
SymLessGreater: {"<>", symClassOperator}, // 36: '<>'
|
||||||
SymNotEqual: {"!=", symClassOperator}, // 37: '!='
|
SymNotEqual: {"!=", symClassOperator}, // 37: '!='
|
||||||
SymDollar: {"$", symClassOperator}, // 38: '$'
|
SymDollar: {"$", symClassOperator}, // 38: '$'
|
||||||
SymHash: {"#", symClassOperator}, // 39: '#'
|
SymHash: {"#", symClassOperator}, // 39: '#'
|
||||||
SymOpenRound: {"(", symClassParenthesis}, // 40: '('
|
SymOpenRound: {"(", symClassParenthesis}, // 40: '('
|
||||||
SymClosedRound: {")", symClassParenthesis}, // 41: ')'
|
SymClosedRound: {")", symClassParenthesis}, // 41: ')'
|
||||||
SymOpenSquare: {"[", symClassParenthesis}, // 42: '['
|
SymOpenSquare: {"[", symClassParenthesis}, // 42: '['
|
||||||
SymClosedSquare: {"]", symClassParenthesis}, // 43: ']'
|
SymClosedSquare: {"]", symClassParenthesis}, // 43: ']'
|
||||||
SymOpenBrace: {"{", symClassParenthesis}, // 44: '{'
|
SymOpenBrace: {"{", symClassParenthesis}, // 44: '{'
|
||||||
SymClosedBrace: {"}", symClassParenthesis}, // 45: '}'
|
SymClosedBrace: {"}", symClassParenthesis}, // 45: '}'
|
||||||
SymTilde: {"~", symClassOperator}, // 46: '~'
|
SymTilde: {"~", symClassOperator}, // 46: '~'
|
||||||
SymDoubleQuestion: {"??", symClassOperator}, // 47: '??'
|
SymDoubleQuestion: {"??", symClassOperator}, // 47: '??'
|
||||||
SymQuestionEqual: {"?=", symClassOperator}, // 48: '?='
|
SymQuestionEqual: {"?=", symClassOperator}, // 48: '?='
|
||||||
SymQuestionExclam: {"?!", symClassOperator}, // 49: '?!'
|
SymQuestionExclam: {"?!", symClassOperator}, // 49: '?!'
|
||||||
SymDoubleAt: {"@@", symClassOperator}, // 50: '@@'
|
SymDoubleAt: {"@@", symClassOperator}, // 50: '@@'
|
||||||
SymDoubleColon: {"::", symClassOperator}, // 51: '::'
|
SymDoubleColon: {"::", symClassOperator}, // 51: '::'
|
||||||
SymDoubleGreater: {">>", symClassOperator}, // 52: '>>'
|
SymDoubleGreater: {">>", symClassOperator}, // 52: '>>'
|
||||||
SymDoubleLess: {"<<", symClassOperator}, // 53: '<<'
|
SymDoubleLess: {"<<", symClassOperator}, // 53: '<<'
|
||||||
SymCaret: {"^", symClassOperator}, // 54: '^'
|
SymCaret: {"^", symClassOperator}, // 54: '^'
|
||||||
SymDollarRound: {"$(", symClassOperator}, // 55: '$('
|
SymDollarRound: {"$(", symClassOperator}, // 55: '$('
|
||||||
SymOpenClosedRound: {"()", symClassPostOp}, // 56: '()'
|
SymOpenClosedRound: {"()", symClassPostOp}, // 56: '()'
|
||||||
SymDoubleDollar: {"$$", symClassOperator}, // 57: '$$'
|
SymDoubleDollar: {"$$", symClassOperator}, // 57: '$$'
|
||||||
SymDoubleDot: {"..", symClassOperator}, // 58: '..'
|
SymDoubleDot: {"..", symClassOperator}, // 58: '..'
|
||||||
SymTripleDot: {"...", symClassOperator}, // 59: '...'
|
SymTripleDot: {"...", symClassOperator}, // 59: '...'
|
||||||
SymStarEqual: {"*=", symClassOperator}, // 60: '*='
|
SymStarEqual: {"*=", symClassOperator}, // 60: '*='
|
||||||
SymSlashEqual: {"/=", symClassOperator}, // 61: '/='
|
SymSlashEqual: {"/=", symClassOperator}, // 61: '/='
|
||||||
SymPercEqual: {"%=", symClassOperator}, // 62: '%='
|
SymPercEqual: {"%=", symClassOperator}, // 62: '%='
|
||||||
SymPlusGreater: {"+>", symClassOperator}, // 63: '+>'
|
SymDoubleLessEqual: {"<<=", symClassOperator}, // 63: '<<='
|
||||||
SymLessPlus: {"<+", symClassOperator}, // 64: '<+'
|
SymDoubleGreaterEqual: {">>=", symClassOperator}, // 64: '>>='
|
||||||
|
SymAmpersandEqual: {"&=", symClassOperator}, // 65: '&='
|
||||||
|
SymVertBarEqual: {"|=", symClassOperator}, // 65: '|='
|
||||||
|
SymPlusGreater: {"+>", symClassOperator}, // 66: '+>'
|
||||||
|
SymLessPlus: {"<+", symClassOperator}, // 67: '<+'
|
||||||
// SymChangeSign
|
// SymChangeSign
|
||||||
// SymUnchangeSign
|
// SymUnchangeSign
|
||||||
// SymIdentifier
|
// SymIdentifier
|
||||||
|
136
symbol.go
136
symbol.go
@ -7,72 +7,76 @@ package expr
|
|||||||
type Symbol int16
|
type Symbol int16
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SymUnknown Symbol = iota - 1 // -1: Unknown symbol
|
SymUnknown Symbol = iota - 1 // -1: Unknown symbol
|
||||||
SymNone // 0: Null value for variable of type symbol
|
SymNone // 0: Null value for variable of type symbol
|
||||||
SymError // 1: Error reading from stream
|
SymError // 1: Error reading from stream
|
||||||
SymEos // 2: End of stream
|
SymEos // 2: End of stream
|
||||||
SymMinus // 3: '-'
|
SymMinus // 3: '-'
|
||||||
SymMinusEqual // 4: '-='
|
SymMinusEqual // 4: '-='
|
||||||
SymDoubleMinus // 5: '--'
|
SymDoubleMinus // 5: '--'
|
||||||
SymPlus // 6: '+'
|
SymPlus // 6: '+'
|
||||||
SymPlusEqual // 7: '+='
|
SymPlusEqual // 7: '+='
|
||||||
SymDoublePlus // 8: '++'
|
SymDoublePlus // 8: '++'
|
||||||
SymStar // 9: '*'
|
SymStar // 9: '*'
|
||||||
SymDoubleStar // 10: '**'
|
SymDoubleStar // 10: '**'
|
||||||
SymSlash // 11: '/'
|
SymSlash // 11: '/'
|
||||||
SymBackSlash // 12: '\'
|
SymBackSlash // 12: '\'
|
||||||
SymVertBar // 13: '|'
|
SymVertBar // 13: '|'
|
||||||
SymDoubleVertBar // 14: '||'
|
SymDoubleVertBar // 14: '||'
|
||||||
SymComma // 15: ','
|
SymComma // 15: ','
|
||||||
SymColon // 16: ':'
|
SymColon // 16: ':'
|
||||||
SymSemiColon // 17: ';'
|
SymSemiColon // 17: ';'
|
||||||
SymDot // 18: '.'
|
SymDot // 18: '.'
|
||||||
SymDotSlash // 19: './'
|
SymDotSlash // 19: './'
|
||||||
SymQuote // 20: '\''
|
SymQuote // 20: '\''
|
||||||
SymDoubleQuote // 21: '"'
|
SymDoubleQuote // 21: '"'
|
||||||
SymBackTick // 22: '`'
|
SymBackTick // 22: '`'
|
||||||
SymExclamation // 23: '!'
|
SymExclamation // 23: '!'
|
||||||
SymQuestion // 24: '?'
|
SymQuestion // 24: '?'
|
||||||
SymAmpersand // 25: '&'
|
SymAmpersand // 25: '&'
|
||||||
SymDoubleAmpersand // 26: '&&'
|
SymDoubleAmpersand // 26: '&&'
|
||||||
SymPercent // 27: '%'
|
SymPercent // 27: '%'
|
||||||
SymAt // 28: '@'
|
SymAt // 28: '@'
|
||||||
SymUndescore // 29: '_'
|
SymUndescore // 29: '_'
|
||||||
SymEqual // 30: '='
|
SymEqual // 30: '='
|
||||||
SymDoubleEqual // 31: '=='
|
SymDoubleEqual // 31: '=='
|
||||||
SymLess // 32: '<'
|
SymLess // 32: '<'
|
||||||
SymLessOrEqual // 33: '<='
|
SymLessOrEqual // 33: '<='
|
||||||
SymGreater // 34: '>'
|
SymGreater // 34: '>'
|
||||||
SymGreaterOrEqual // 35: '>='
|
SymGreaterOrEqual // 35: '>='
|
||||||
SymLessGreater // 36: '<>'
|
SymLessGreater // 36: '<>'
|
||||||
SymNotEqual // 37: '!='
|
SymNotEqual // 37: '!='
|
||||||
SymDollar // 38: '$'
|
SymDollar // 38: '$'
|
||||||
SymHash // 39: '#'
|
SymHash // 39: '#'
|
||||||
SymOpenRound // 40: '('
|
SymOpenRound // 40: '('
|
||||||
SymClosedRound // 41: ')'
|
SymClosedRound // 41: ')'
|
||||||
SymOpenSquare // 42: '['
|
SymOpenSquare // 42: '['
|
||||||
SymClosedSquare // 43: ']'
|
SymClosedSquare // 43: ']'
|
||||||
SymOpenBrace // 44: '{'
|
SymOpenBrace // 44: '{'
|
||||||
SymClosedBrace // 45: '}'
|
SymClosedBrace // 45: '}'
|
||||||
SymTilde // 46: '~'
|
SymTilde // 46: '~'
|
||||||
SymDoubleQuestion // 47: '??'
|
SymDoubleQuestion // 47: '??'
|
||||||
SymQuestionEqual // 48: '?='
|
SymQuestionEqual // 48: '?='
|
||||||
SymQuestionExclam // 49: '?!'
|
SymQuestionExclam // 49: '?!'
|
||||||
SymDoubleAt // 50: '@@'
|
SymDoubleAt // 50: '@@'
|
||||||
SymDoubleColon // 51: '::'
|
SymDoubleColon // 51: '::'
|
||||||
SymDoubleGreater // 52: '>>'
|
SymDoubleGreater // 52: '>>'
|
||||||
SymDoubleLess // 53: '<<'
|
SymDoubleLess // 53: '<<'
|
||||||
SymCaret // 54: '^'
|
SymCaret // 54: '^'
|
||||||
SymDollarRound // 55: '$('
|
SymDollarRound // 55: '$('
|
||||||
SymOpenClosedRound // 56: '()'
|
SymOpenClosedRound // 56: '()'
|
||||||
SymDoubleDollar // 57: '$$'
|
SymDoubleDollar // 57: '$$'
|
||||||
SymDoubleDot // 58: '..'
|
SymDoubleDot // 58: '..'
|
||||||
SymTripleDot // 59: '...'
|
SymTripleDot // 59: '...'
|
||||||
SymStarEqual // 60: '*='
|
SymStarEqual // 60: '*='
|
||||||
SymSlashEqual // 61: '/='
|
SymSlashEqual // 61: '/='
|
||||||
SymPercEqual // 62: '%='
|
SymPercEqual // 62: '%='
|
||||||
SymPlusGreater // 63: '+>'
|
SymDoubleLessEqual // 63: '<<='
|
||||||
SymLessPlus // 64: '<+'
|
SymDoubleGreaterEqual // 64: '>>='
|
||||||
|
SymAmpersandEqual // 65: '&='
|
||||||
|
SymVertBarEqual // 65: '|='
|
||||||
|
SymPlusGreater // 66: '+>'
|
||||||
|
SymLessPlus // 67: '<+'
|
||||||
SymChangeSign
|
SymChangeSign
|
||||||
SymUnchangeSign
|
SymUnchangeSign
|
||||||
SymIdentifier
|
SymIdentifier
|
||||||
|
@ -38,9 +38,9 @@ func TestListParser(t *testing.T) {
|
|||||||
/* 24 */ {`["a","b","c","d"][1]`, "b", nil},
|
/* 24 */ {`["a","b","c","d"][1]`, "b", nil},
|
||||||
/* 25 */ {`["a","b","c","d"][1,1]`, nil, `[1:19] one index only is allowed`},
|
/* 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},
|
/* 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},
|
/* 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},
|
/* 30 */ {`2 >> 3;`, int64(0), nil},
|
||||||
/* 31 */ {`a=[1,2]; a<+3`, newListA(int64(1), int64(2), int64(3)), 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},
|
/* 32 */ {`a=[1,2]; 5+>a`, newListA(int64(5), int64(1), int64(2)), nil},
|
||||||
|
@ -14,10 +14,24 @@ func TestOperator(t *testing.T) {
|
|||||||
/* 1 */ {`a=1; unset "a"; a`, nil, `undefined variable or function "a"`},
|
/* 1 */ {`a=1; unset "a"; a`, nil, `undefined variable or function "a"`},
|
||||||
/* 2 */ {`a=1; unset ["a", "b"]`, int64(1), nil},
|
/* 2 */ {`a=1; unset ["a", "b"]`, int64(1), nil},
|
||||||
/* 3 */ {`f=func(){3}; unset "f()"`, 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", ".")
|
// t.Setenv("EXPR_PATH", ".")
|
||||||
|
|
||||||
//runTestSuiteSpec(t, section, inputs, 3)
|
// runTestSuiteSpec(t, section, inputs, 4)
|
||||||
runTestSuite(t, section, inputs)
|
runTestSuite(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestStringsParser(t *testing.T) {
|
func TestStringsParser(t *testing.T) {
|
||||||
|
section := "String"
|
||||||
inputs := []inputType{
|
inputs := []inputType{
|
||||||
/* 1 */ {`"uno" + "due"`, `unodue`, nil},
|
/* 1 */ {`"uno" + "due"`, `unodue`, nil},
|
||||||
/* 2 */ {`"uno" + 2`, `uno2`, nil},
|
/* 2 */ {`"uno" + 2`, `uno2`, nil},
|
||||||
@ -22,6 +23,6 @@ func TestStringsParser(t *testing.T) {
|
|||||||
/* 10 */ {`"AF3B0Dz" / 0`, nil, "[1:12] division by zero"},
|
/* 10 */ {`"AF3B0Dz" / 0`, nil, "[1:12] division by zero"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// runTestSuiteSpec(t, "String", inputs, 8)
|
// runTestSuiteSpec(t, section, inputs, 8)
|
||||||
runTestSuite(t, "String", inputs)
|
runTestSuite(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user