Clean up code and add support for multiple operations in expression
This commit is contained in:
parent
a95d054189
commit
291b7a906c
33
ast.go
33
ast.go
@ -1,6 +1,7 @@
|
||||
package scpt
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/alecthomas/participle/lexer"
|
||||
)
|
||||
@ -40,7 +41,7 @@ func (ast *AST) Execute() error {
|
||||
Vars[Var.Key] = val
|
||||
}
|
||||
}
|
||||
// If parsing function calls
|
||||
// If parsing function calls
|
||||
} else if cmd.Calls != nil {
|
||||
// For each function call
|
||||
for _, Call := range cmd.Calls {
|
||||
@ -50,6 +51,21 @@ func (ast *AST) Execute() error {
|
||||
return fmt.Errorf("%s: %s", Call.Pos, err)
|
||||
}
|
||||
}
|
||||
} else if cmd.Ifs != nil {
|
||||
for _, If := range cmd.Ifs {
|
||||
condVal, err := callIfFunc(ParseValue(If.Condition))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
condBool, ok := condVal.(bool)
|
||||
if !ok {
|
||||
return errors.New("condition must be a boolean")
|
||||
}
|
||||
if condBool {
|
||||
_, err := CallFunction(If.Action)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -59,9 +75,16 @@ func (ast *AST) Execute() error {
|
||||
type Command struct {
|
||||
Pos lexer.Position
|
||||
Vars []*Var `( @@`
|
||||
Ifs []*If `| @@`
|
||||
Calls []*FuncCall `| @@ )`
|
||||
}
|
||||
|
||||
type If struct {
|
||||
Pos lexer.Position
|
||||
Condition *Value `"if" @@`
|
||||
Action *FuncCall `"then" @@`
|
||||
}
|
||||
|
||||
// FuncCall stores any function calls encountered while parsing a script
|
||||
type FuncCall struct {
|
||||
Pos lexer.Position
|
||||
@ -110,8 +133,12 @@ func (b *Bool) Capture(values []string) error {
|
||||
// Expression stores any expressions encountered while parsing a
|
||||
// script for later evaluation
|
||||
type Expression struct {
|
||||
Pos lexer.Position
|
||||
Left *Value `@@`
|
||||
Pos lexer.Position
|
||||
Left *Value `@@`
|
||||
RightSegs []*ExprRightSeg `@@*`
|
||||
}
|
||||
|
||||
type ExprRightSeg struct {
|
||||
Op string `@( ">" | ">" "=" | "<" | "<" "=" | "!" "=" | "=" "=" | "+" | "-" | "*" | "/" | "^" | "%")`
|
||||
Right *Value `@@`
|
||||
}
|
||||
|
2
go.mod
2
go.mod
@ -6,6 +6,4 @@ require (
|
||||
github.com/alecthomas/participle v0.7.1
|
||||
github.com/antonmedv/expr v1.8.9
|
||||
github.com/gen2brain/dlgs v0.0.0-20210222160047-2f436553172f
|
||||
github.com/gopherjs/gopherjs v0.0.0-20210202160940-bed99a852dfe // indirect
|
||||
github.com/rs/zerolog v1.20.0
|
||||
)
|
||||
|
50
scpt.go
50
scpt.go
@ -67,8 +67,8 @@ func ParseValue(val *Value) (interface{}, error) {
|
||||
// Return unquoted string
|
||||
return strings.Trim(*val.String, `"`), nil
|
||||
} else if val.Bool != nil {
|
||||
// Return dereferenced boolean
|
||||
return *val.Bool, nil
|
||||
// Return dereferenced Bool converted to bool
|
||||
return bool(*val.Bool), nil
|
||||
} else if val.Float != nil {
|
||||
// Return dereferenced float
|
||||
return *val.Float, nil
|
||||
@ -83,22 +83,32 @@ func ParseValue(val *Value) (interface{}, error) {
|
||||
return Vars[*val.VarVal], nil
|
||||
} else if val.Expr != nil {
|
||||
// Parse value of left side of expression
|
||||
left, _ := ParseValue(val.Expr.Left)
|
||||
left, _ := callIfFunc(ParseValue(val.Expr.Left))
|
||||
// If value is string, requote
|
||||
if isStr(left) {
|
||||
left = requoteStr(left.(string))
|
||||
}
|
||||
// Parse value of right side of expression
|
||||
right, _ := ParseValue(val.Expr.Right)
|
||||
// If value is string, requote
|
||||
if isStr(right) {
|
||||
right = requoteStr(right.(string))
|
||||
// Create new nil string
|
||||
var right string
|
||||
// For every right segment
|
||||
for _, segment := range val.Expr.RightSegs {
|
||||
// Parse value of right segment, calling it if it is a function
|
||||
rVal, _ := callIfFunc(ParseValue(segment.Right))
|
||||
// If value is string, requote
|
||||
if isStr(rVal) {
|
||||
rVal = requoteStr(rVal.(string))
|
||||
}
|
||||
// Append right segment to right string
|
||||
right = right + fmt.Sprintf(
|
||||
" %s %v",
|
||||
segment.Op,
|
||||
rVal,
|
||||
)
|
||||
}
|
||||
// Create string expression from halves and operator
|
||||
// Create string expression from segments and operator
|
||||
exp := fmt.Sprintf(
|
||||
"%v %s %v",
|
||||
"%v %s",
|
||||
left,
|
||||
val.Expr.Op,
|
||||
right,
|
||||
)
|
||||
// Compile string expression
|
||||
@ -132,6 +142,20 @@ func isStr(i interface{}) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Call val if it is a function, otherwise pass through return values
|
||||
func callIfFunc(val interface{}, err error) (interface{}, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If val is a pointer to a FuncCall
|
||||
if IsFuncCall(val) {
|
||||
// Pass through return values of function call
|
||||
return CallFunction(val.(*FuncCall))
|
||||
}
|
||||
// Return given value
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// UnwrapArgs takes a slice of Arg structs and returns a map
|
||||
// storing the argument name and its value. If the argument has
|
||||
// no name, its key will be an empty string
|
||||
@ -164,8 +188,8 @@ func UnwrapArgs(args []*Arg) (map[string]interface{}, error) {
|
||||
|
||||
// IsFuncCall checks if val is a FuncCall struct
|
||||
func IsFuncCall(val interface{}) bool {
|
||||
// If type of val contains .FuncCall, return true
|
||||
if strings.Contains(reflect.TypeOf(val).String(), ".FuncCall") {
|
||||
// If type of val is a pointer to FuncCall, return true
|
||||
if reflect.TypeOf(val) == reflect.TypeOf(&FuncCall{}) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -1,6 +1,7 @@
|
||||
set y to (display-dialog "Hello" with title 12 with type "yesno")
|
||||
display-dialog "Goodbye" with title 21 with type "error"
|
||||
do-shell-script "notify-send Test Notification"
|
||||
print (display-dialog {"Test " + "2"} with title 30 with type "entry" with default "text")
|
||||
do-shell-script {"echo " + (display-dialog {"Test " + "2"} with title 30 with type "entry" with default "text")}
|
||||
set x to $y
|
||||
print { 3+4 }
|
||||
if {3 == 4} then display-dialog "What? Why is 3 equal to 4?" with title "What?!" with type "info"
|
||||
if {3 == 3} then display-dialog "3 is equal to 3!" with title "New Discovery" with type "info"
|
Loading…
Reference in New Issue
Block a user