Skip to content

Commit

Permalink
Merge branch 'master' of qq:fefit/fet
Browse files Browse the repository at this point in the history
  • Loading branch information
ganmin committed Apr 27, 2020
2 parents 38e7ad7 + fa3b125 commit 99b4c01
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 67 deletions.
8 changes: 7 additions & 1 deletion fet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func TestCompile(t *testing.T) {
assert.Nil(t, err)
assert.Equal(t, output, strings.TrimSpace(result))
}
//
// test for syntax
helloFet := "hello fet!"
helloFetChars := strings.Split(helloFet, "")
t.Run("Test Smarty mode compile", func(t *testing.T) {
Expand All @@ -41,5 +41,11 @@ func TestCompile(t *testing.T) {
assertOutputToBe(t, "slice.tpl", map[string][]string{
"Result": helloFetChars,
}, "hello")
assertOutputToBe(t, "plus.tpl", nil, "5,5,5,5")
assertOutputToBe(t, "minus.tpl", nil, "0,0,0,0")
assertOutputToBe(t, "multiple.tpl", nil, "24,24,24,24")
assertOutputToBe(t, "divide.tpl", nil, "8,8,8,8")
assertOutputToBe(t, "minmax.tpl", nil, "1,2")
assertOutputToBe(t, "mod.tpl", nil, "1.15")
})
}
19 changes: 6 additions & 13 deletions lib/expression/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,6 @@ func typeOf(token Any) string {
return string(rns[total+1:])
}

func isBracket(token AnyToken) bool {
switch token.(type) {
case *LeftBracketToken, *RightBracketToken, *LeftSquareBracketToken, *RightSquareBracketToken:
return true
default:
return false
}
}

func getNoSpaceTokens(tokens []AnyToken, num int) (isPrevSpace bool, result []AnyToken) {
isTwo := num == 2
if num != 1 && !isTwo {
Expand Down Expand Up @@ -761,7 +752,11 @@ func (number *NumberToken) ToNumber() float64 {
cur, _ := strconv.ParseInt(values, number.Base, 64)
num = float64(cur)
} else {
num, _ = strconv.ParseFloat(values, 10)
if logics["IsFloat"] {
num, _ = strconv.ParseFloat(values+"."+string(number.Dicimals), 10)
} else {
num, _ = strconv.ParseFloat(values, 10)
}
if number.Power != nil {
power = number.Power.ToNumber()
}
Expand Down Expand Up @@ -1113,14 +1108,12 @@ func (parser *Parser) Add(s rune) error {
parser.Current = retryToken
// next must has a space
if token, ok := retryToken.(*OperatorToken); ok {
var validNext ValidateNextFn
validNext = func(t AnyToken) error {
parser.NextMustBe = func(t AnyToken) error {
if _, isSpace := t.(*SpaceToken); isSpace {
return nil
}
return fmt.Errorf("the keyword operator '%s' must have a right space", token.Keyword)
}
parser.NextMustBe = validNext
parser.NextValids++
}
}
Expand Down
7 changes: 1 addition & 6 deletions lib/expression/expression_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,7 @@ func TestTokenize(t *testing.T) {
assertErrorTokenize(t, "_")
assertErrorTokenize(t, "1a")
assertErrorTokenize(t, "1_")
assertErrorTokenize(t, "$a")
// wrong identifier
assertErrorTokenize(t, "_")
assertErrorTokenize(t, "1a")
assertErrorTokenize(t, "1_")
assertErrorTokenize(t, "$a")
assertErrorTokenize(t, ".a")
// wrong operators
assertErrorTokenize(t, ">=1")
assertErrorTokenize(t, `1 >= "a"`)
Expand Down
104 changes: 57 additions & 47 deletions lib/funcs/funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type CaptureData struct {
func (lc *LoopChan) init() {
lc.Chan = make(chan int, 1)
lc.Loop = -1
lc.Next()
_, _ = lc.Next()
}
func (lc *LoopChan) Close() (string, error) {
lc.Loop = -1
Expand Down Expand Up @@ -60,44 +60,53 @@ func Inject() template.FuncMap {
injects["INJECT_PLUS"] = generateNumberFunc(func(a, b interface{}) interface{} {
if a, b, err := toIntNumbers(a, b); err == nil {
return a + b
} else if a, b, err := toFloatNumbers(a, b); err == nil {
}
if a, b, err := toFloatNumbers(a, b); err == nil {
return a + b
} else {
panic(makeHaltInfo("plus(+)", err))
}
return haltNumberErr("+")
}, true)
injects["INJECT_MINUS"] = generateNumberFunc(func(a, b interface{}) interface{} {
if a, b, err := toIntNumbers(a, b); err == nil {
return a - b
} else if a, b, err := toFloatNumbers(a, b); err == nil {
}
if a, b, err := toFloatNumbers(a, b); err == nil {
return a - b
} else {
panic(makeHaltInfo("minus(-)", err))
}
return haltNumberErr("-")
}, true)
injects["INJECT_MULTIPLE"] = generateNumberFunc(func(a, b interface{}) interface{} {
if a, b, err := toIntNumbers(a, b); err == nil {
return a * b
} else if a, b, err := toFloatNumbers(a, b); err == nil {
}
if a, b, err := toFloatNumbers(a, b); err == nil {
return a * b
} else {
panic(makeHaltInfo("multiple(*)", err))
}
return haltNumberErr("*")
}, true)
injects["INJECT_DIVIDE"] = generateNumberFunc(func(a, b interface{}) interface{} {
if a, b, err := toFloatNumbers(a, b); err == nil {
return a / b
} else {
panic(makeHaltInfo("divide(/)", err))
}
return haltNumberErr("/")
}, false)
injects["INJECT_MOD"] = generateNumberFunc(func(a, b interface{}) interface{} {
if a, b, err := toFloatNumbers(a, b); err == nil {
return math.Mod(a, b)
} else {
panic(makeHaltInfo("mod(%)", err))
}
return haltNumberErr("%")
}, false)
injects["INJECT_POWER"] = generateNumberFunc(func(a, b interface{}) interface{} {
if a, b, err := toFloatNumbers(a, b); err == nil {
return math.Pow(a, b)
} else {
panic(makeHaltInfo("power(**)", err))
}
return haltNumberErr("**")
}, false)
injects["INJECT_BITAND"] = generateIntFunc(func(a, b int64) int64 {
return a & b
Expand Down Expand Up @@ -134,27 +143,31 @@ func Helpers() template.FuncMap {
return a
}
return b
} else if a, b, err := toFloatNumbers(a, b); err == nil {
}
if a, b, err := toFloatNumbers(a, b); err == nil {
if a < b {
return a
}
return b
} else {
panic(makeHaltInfo("min", err))
}
return fmt.Errorf("wrong arguments for 'min' method")
}, true)
helpers["max"] = generateNumberFunc(func(a, b interface{}) interface{} {
if a, b, err := toIntNumbers(a, b); err == nil {
if a > b {
return a
}
return b
} else if a, b, err := toFloatNumbers(a, b); err == nil {
}
if a, b, err := toFloatNumbers(a, b); err == nil {
if a > b {
return a
}
return b
} else {
panic(makeHaltInfo("max", err))
}
return fmt.Errorf("wrong arguments for 'min' method")
}, true)
// format
helpers["number_format"] = numberFormat
Expand Down Expand Up @@ -261,15 +274,6 @@ func toFloatOrString(target interface{}) (interface{}, error) {
return toFloat(target)
}
}
func isNumber(target interface{}) bool {
switch target.(type) {
case int, float64, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32:
return true
case complex64, complex128:
// ignore complex
}
return false
}

func trim(args ...interface{}) string {
argsNum := len(args)
Expand Down Expand Up @@ -323,10 +327,8 @@ func toFloatNumbers(a, b interface{}) (float64, float64, error) {
return 0.0, 0.0, err
}

func haltNumberErr(operator string) error {
err := fmt.Errorf("the operands of the '%s' operator are not numbers", operator)
panic(err.Error())
return err
func makeHaltInfo(name string, err error) string {
return fmt.Sprintf("'%s' method params error:%s", name, err.Error())
}

func generateNumberFunc(fn OperatorNumberFn, allowInt bool) (res ResultNumberFn) {
Expand Down Expand Up @@ -500,28 +502,36 @@ func truncate(content string, length int) string {
return string(cont[:length]) + suffix
}

func makeRange(start, end float64, args ...interface{}) []float64 {
func makeRange(s, e interface{}, args ...interface{}) []float64 {
step := 1.0
if len(args) == 1 {
if curStep, ok := args[0].(float64); ok && curStep != 0.0 {
step = curStep
if start, err := toFloat(s); err != nil {
panic(makeHaltInfo("mrange", err))
} else {
if end, err := toFloat(e); err != nil {
panic(makeHaltInfo("mrange", err))
} else {
if len(args) == 1 {
if curStep, ok := args[0].(float64); ok && curStep != 0.0 {
step = curStep
}
}
result := []float64{
start,
}
total := math.Floor((end - start) / step)
needLast := true
if start+total*step == end {
needLast = false
}
for i := 1.0; i <= total; i++ {
result = append(result, start+step*i)
}
if needLast {
result = append(result, end)
}
return result
}
}
result := []float64{
start,
}
total := math.Floor((end - start) / step)
needLast := true
if start+total*step == end {
needLast = false
}
for i := 1.0; i <= total; i++ {
result = append(result, start+step*i)
}
if needLast {
result = append(result, end)
}
return result
}

func capture(data interface{}, variables ...interface{}) CaptureData {
Expand Down Expand Up @@ -683,7 +693,7 @@ func empty(target interface{}, args ...interface{}) bool {
case float64, float32:
return v == 0.0
case bool:
return v == false
return !v
case nil:
return true
}
Expand Down
5 changes: 5 additions & 0 deletions tests/smarty/templates/divide.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{%$a = 24 %}
{%$b = 24%}
{%$c = 24.0%}
{%$d = 24.0%}
{%$a / 3%},{%$b / 3.0%},{%$c / 3.0%},{%$d / 3%}
3 changes: 3 additions & 0 deletions tests/smarty/templates/minmax.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{%$a = 1%}
{%$b = 2.0%}
{%min($a, $b)%},{%max($a, $b)%}
5 changes: 5 additions & 0 deletions tests/smarty/templates/minus.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{%$a = 1 %}
{%$b = 2%}
{%$c = 3.0%}
{%$d = 4.0%}
{%$a - 1%},{%$b - 2.0%},{%$c - 3.0%},{%$d - 4%}
3 changes: 3 additions & 0 deletions tests/smarty/templates/mod.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{%$a = 3.15%}
{%$b = 2%}
{%$a % $b%}
5 changes: 5 additions & 0 deletions tests/smarty/templates/multiple.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{%$a = 1 %}
{%$b = 2%}
{%$c = 3.0%}
{%$d = 4.0%}
{%$a * 24%},{%$b * 12.0%},{%$c * 8.0%},{%$d * 6%}
5 changes: 5 additions & 0 deletions tests/smarty/templates/plus.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{%$a = 1 %}
{%$b = 2%}
{%$c = 3.0%}
{%$d = 4.0%}
{%$a + 4%},{%$b + 3.0%},{%$c + 2.0%},{%$d + 1%}

0 comments on commit 99b4c01

Please sign in to comment.