Implement repeat loops
This commit is contained in:
parent
745920b139
commit
877f85ef78
48
ast.go
48
ast.go
@ -100,24 +100,48 @@ func executeCmd(cmd *Command) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if cmd.RptLoops != nil {
|
||||||
|
// For each repeat loop
|
||||||
|
for _, RptLoop := range cmd.RptLoops {
|
||||||
|
for i:=0;i<*RptLoop.Times;i++ {
|
||||||
|
if RptLoop.IndexVar != nil {
|
||||||
|
Vars[*RptLoop.IndexVar] = i
|
||||||
|
}
|
||||||
|
for _, InnerCmd := range RptLoop.InnerCmds {
|
||||||
|
// Execute command recursively
|
||||||
|
err := executeCmd(InnerCmd)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%s: %s", InnerCmd.Pos, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command stores any commands encountered while parsing a script
|
// Command stores any commands encountered while parsing a script
|
||||||
type Command struct {
|
type Command struct {
|
||||||
Pos lexer.Position
|
Pos lexer.Position
|
||||||
Tokens []lexer.Token
|
Tokens []lexer.Token
|
||||||
Vars []*Var `( @@`
|
Vars []*Var `( @@`
|
||||||
Ifs []*If `| @@`
|
Ifs []*If `| @@`
|
||||||
Calls []*FuncCall `| @@)`
|
RptLoops []*RptLoop`| @@`
|
||||||
|
Calls []*FuncCall `| @@)`
|
||||||
}
|
}
|
||||||
|
|
||||||
// If stores any if statements encountered while parsing a script
|
// If stores any if statements encountered while parsing a script
|
||||||
type If struct {
|
type If struct {
|
||||||
Pos lexer.Position
|
Pos lexer.Position
|
||||||
Condition *Value `"if" @@ "{"`
|
Condition *Value `"if" @@ "{"`
|
||||||
InnerCmds []*Command `@@*"}"`
|
InnerCmds []*Command `@@* "}"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RptLoop struct {
|
||||||
|
Pos lexer.Position
|
||||||
|
Times *int `"repeat" @Number "times" "{"`
|
||||||
|
IndexVar *string `(@Ident "in")?`
|
||||||
|
InnerCmds []*Command `@@* "}"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FuncCall stores any function calls encountered while parsing a script
|
// FuncCall stores any function calls encountered while parsing a script
|
||||||
@ -143,13 +167,13 @@ type Var struct {
|
|||||||
|
|
||||||
// Value stores any literal values encountered while parsing a script
|
// Value stores any literal values encountered while parsing a script
|
||||||
type Value struct {
|
type Value struct {
|
||||||
Pos lexer.Position
|
Pos lexer.Position
|
||||||
String *string ` @String`
|
String *string ` @String`
|
||||||
Number *float64 `| @Number`
|
Number *float64 `| @Number`
|
||||||
Bool *Bool `| @("true" | "false")`
|
Bool *Bool `| @("true" | "false")`
|
||||||
SubCmd *FuncCall `| "(" @@ ")"`
|
SubCmd *FuncCall `| "(" @@ ")"`
|
||||||
VarVal *string `| "$" @Ident`
|
VarVal *string `| "$" @Ident`
|
||||||
Expr *Expression `| "{" @@ "}"`
|
Expr *Expression `| "{" @@ "}"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bool stores boolean values encountered while parsing a script.
|
// Bool stores boolean values encountered while parsing a script.
|
||||||
|
@ -81,3 +81,11 @@ func doShellScript(args map[string]interface{}) (interface{}, error) {
|
|||||||
return nil, errors.New("script not provided")
|
return nil, errors.New("script not provided")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toString(args map[string]interface{}) (interface{}, error) {
|
||||||
|
val, ok := args[""]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("no value provided")
|
||||||
|
}
|
||||||
|
return fmt.Sprint(val), nil
|
||||||
|
}
|
4
lexer.go
4
lexer.go
@ -10,8 +10,8 @@ var scptLexer = lexer.Must(stateful.NewSimple([]stateful.Rule{
|
|||||||
{"Ident", `[a-zA-Z]\w*`, nil},
|
{"Ident", `[a-zA-Z]\w*`, nil},
|
||||||
{"String", `"[^"]*"`, nil},
|
{"String", `"[^"]*"`, nil},
|
||||||
{"Number", `(?:\d*\.)?\d+`, nil},
|
{"Number", `(?:\d*\.)?\d+`, nil},
|
||||||
{"Punct", `[-[!@#$&()_{}\|:;"',.?/]|]`, nil},
|
{"Punct", `[-[!@$&()_{}\|:;"',.?/]|]`, nil},
|
||||||
{"Whitespace", `[ \t\r\n]+`, nil},
|
{"Whitespace", `[ \t\r\n]+`, nil},
|
||||||
{"Comment", `#[^\n]+`, nil},
|
{"Comment", `#[^\n]+`, nil},
|
||||||
{"Operator", `(>=|<=|>|<|==|!=)|[-+*/^%]`, nil},
|
{"Operator", `(>=|<=|>|<|==|!=)|[-+*/^%]`, nil},
|
||||||
}))
|
}))
|
||||||
|
3
scpt.go
3
scpt.go
@ -36,6 +36,7 @@ type FuncMap map[string]func(map[string]interface{}) (interface{}, error)
|
|||||||
var Funcs = FuncMap{
|
var Funcs = FuncMap{
|
||||||
"display-dialog": displayDialog,
|
"display-dialog": displayDialog,
|
||||||
"do-shell-script": doShellScript,
|
"do-shell-script": doShellScript,
|
||||||
|
"string": toString,
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddFuncs adds all functions from the provided FuncMap into
|
// AddFuncs adds all functions from the provided FuncMap into
|
||||||
@ -63,7 +64,7 @@ func Parse(r io.Reader) (*AST, error) {
|
|||||||
&AST{},
|
&AST{},
|
||||||
participle.Lexer(scptLexer),
|
participle.Lexer(scptLexer),
|
||||||
participle.Elide("Whitespace", "Comment"),
|
participle.Elide("Whitespace", "Comment"),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user