github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+incompatible/cmds/core/elvish/eval/args_walker.go (about) 1 package eval 2 3 import "github.com/u-root/u-root/cmds/core/elvish/parse" 4 5 type errorpfer interface { 6 errorpf(begin, end int, fmt string, args ...interface{}) 7 } 8 9 // argsWalker is used by builtin special forms to implement argument parsing. 10 type argsWalker struct { 11 cp errorpfer 12 form *parse.Form 13 idx int 14 } 15 16 func (cp *compiler) walkArgs(f *parse.Form) *argsWalker { 17 return &argsWalker{cp, f, 0} 18 } 19 20 func (aw *argsWalker) more() bool { 21 return aw.idx < len(aw.form.Args) 22 } 23 24 func (aw *argsWalker) peek() *parse.Compound { 25 if !aw.more() { 26 aw.cp.errorpf(aw.form.End(), aw.form.End(), "need more arguments") 27 } 28 return aw.form.Args[aw.idx] 29 } 30 31 func (aw *argsWalker) next() *parse.Compound { 32 n := aw.peek() 33 aw.idx++ 34 return n 35 } 36 37 // nextIs returns whether the next argument's source matches the given text. It 38 // also consumes the argument if it is. 39 func (aw *argsWalker) nextIs(text string) bool { 40 if aw.more() && aw.form.Args[aw.idx].SourceText() == text { 41 aw.idx++ 42 return true 43 } 44 return false 45 } 46 47 // nextMustLambda fetches the next argument, raising an error if it is not a 48 // lambda. 49 func (aw *argsWalker) nextMustLambda() *parse.Primary { 50 n := aw.next() 51 if len(n.Indexings) != 1 { 52 aw.cp.errorpf(n.Begin(), n.End(), "must be lambda") 53 } 54 if len(n.Indexings[0].Indicies) != 0 { 55 aw.cp.errorpf(n.Begin(), n.End(), "must be lambda") 56 } 57 pn := n.Indexings[0].Head 58 if pn.Type != parse.Lambda { 59 aw.cp.errorpf(n.Begin(), n.End(), "must be lambda") 60 } 61 return pn 62 } 63 64 func (aw *argsWalker) nextMustLambdaIfAfter(leader string) *parse.Primary { 65 if aw.nextIs(leader) { 66 return aw.nextMustLambda() 67 } 68 return nil 69 } 70 71 func (aw *argsWalker) mustEnd() { 72 if aw.more() { 73 aw.cp.errorpf(aw.form.Args[aw.idx].Begin(), aw.form.End(), "too many arguments") 74 } 75 }