{ package bootcommand } Input <- expr:Expr EOF { return expr, nil } Expr <- l:( Wait / CharToggle / Special / Literal)+ { return l, nil } Wait = ExprStart "wait" duration:( Duration / Integer )? ExprEnd { var d time.Duration switch t := duration.(type) { case time.Duration: d = t case int64: d = time.Duration(t) * time.Second default: d = time.Second } return &waitExpression{d}, nil } CharToggle = ExprStart lit:(Literal) t:(On / Off) ExprEnd { return &literal{lit.(*literal).s, t.(KeyAction)}, nil } Special = ExprStart s:(SpecialKey) t:(On / Off)? ExprEnd { l := strings.ToLower(string(s.([]byte))) if t == nil { return &specialExpression{l, KeyPress}, nil } return &specialExpression{l, t.(KeyAction)}, nil } Number = '-'? Integer ( '.' Digit+ )? { return string(c.text), nil } Integer = '0' / NonZeroDigit Digit* { return strconv.ParseInt(string(c.text), 10, 64) } Duration = ( Number TimeUnit )+ { return time.ParseDuration(string(c.text)) } On = "on"i { return KeyOn, nil } Off = "off"i { return KeyOff, nil } Literal = . { r, _ := utf8.DecodeRune(c.text) return &literal{r, KeyPress}, nil } ExprEnd = ">" ExprStart = "<" SpecialKey = "bs"i / "del"i / "enter"i / "esc"i / "f10"i / "f11"i / "f12"i / "f1"i / "f2"i / "f3"i / "f4"i / "f5"i / "f6"i / "f7"i / "f8"i / "f9"i / "return"i / "tab"i / "up"i / "down"i / "spacebar"i / "insert"i / "home"i / "end"i / "pageUp"i / "pageDown"i / "leftAlt"i / "leftCtrl"i / "leftShift"i / "rightAlt"i / "rightCtrl"i / "rightShift"i / "leftSuper"i / "rightSuper"i / "left"i / "right"i NonZeroDigit = [1-9] Digit = [0-9] TimeUnit = ("ns" / "us" / "µs" / "ms" / "s" / "m" / "h") _ "whitespace" <- [ \n\t\r]* EOF <- !.