mirror of
https://github.com/go-task/task.git
synced 2025-03-03 14:52:13 +02:00
Update vendor of github.com/mvdan/sh
This commit is contained in:
parent
bb84b067c5
commit
86e0496555
12
vendor/github.com/mvdan/sh/interp/arith.go
generated
vendored
12
vendor/github.com/mvdan/sh/interp/arith.go
generated
vendored
@ -11,8 +11,8 @@ import (
|
|||||||
|
|
||||||
func (r *Runner) arithm(expr syntax.ArithmExpr) int {
|
func (r *Runner) arithm(expr syntax.ArithmExpr) int {
|
||||||
switch x := expr.(type) {
|
switch x := expr.(type) {
|
||||||
case *syntax.Word:
|
case *syntax.Lit:
|
||||||
str := r.loneWord(x)
|
str := x.Value
|
||||||
// recursively fetch vars
|
// recursively fetch vars
|
||||||
for {
|
for {
|
||||||
val := r.getVar(str)
|
val := r.getVar(str)
|
||||||
@ -23,12 +23,14 @@ func (r *Runner) arithm(expr syntax.ArithmExpr) int {
|
|||||||
}
|
}
|
||||||
// default to 0
|
// default to 0
|
||||||
return atoi(str)
|
return atoi(str)
|
||||||
|
case *syntax.ParamExp:
|
||||||
|
return atoi(r.paramExp(x))
|
||||||
case *syntax.ParenArithm:
|
case *syntax.ParenArithm:
|
||||||
return r.arithm(x.X)
|
return r.arithm(x.X)
|
||||||
case *syntax.UnaryArithm:
|
case *syntax.UnaryArithm:
|
||||||
switch x.Op {
|
switch x.Op {
|
||||||
case syntax.Inc, syntax.Dec:
|
case syntax.Inc, syntax.Dec:
|
||||||
name := x.X.(*syntax.Word).Parts[0].(*syntax.Lit).Value
|
name := x.X.(*syntax.Lit).Value
|
||||||
old := atoi(r.getVar(name))
|
old := atoi(r.getVar(name))
|
||||||
val := old
|
val := old
|
||||||
if x.Op == syntax.Inc {
|
if x.Op == syntax.Inc {
|
||||||
@ -81,7 +83,7 @@ func atoi(s string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Runner) assgnArit(b *syntax.BinaryArithm) int {
|
func (r *Runner) assgnArit(b *syntax.BinaryArithm) int {
|
||||||
name := b.X.(*syntax.Word).Parts[0].(*syntax.Lit).Value
|
name := b.X.(*syntax.Lit).Value
|
||||||
val := atoi(r.getVar(name))
|
val := atoi(r.getVar(name))
|
||||||
arg := r.arithm(b.Y)
|
arg := r.arithm(b.Y)
|
||||||
switch b.Op {
|
switch b.Op {
|
||||||
@ -105,7 +107,7 @@ func (r *Runner) assgnArit(b *syntax.BinaryArithm) int {
|
|||||||
val ^= arg
|
val ^= arg
|
||||||
case syntax.ShlAssgn:
|
case syntax.ShlAssgn:
|
||||||
val <<= uint(arg)
|
val <<= uint(arg)
|
||||||
default: // syntax.ShrAssgn
|
case syntax.ShrAssgn:
|
||||||
val >>= uint(arg)
|
val >>= uint(arg)
|
||||||
}
|
}
|
||||||
r.setVar(name, strconv.Itoa(val))
|
r.setVar(name, strconv.Itoa(val))
|
||||||
|
44
vendor/github.com/mvdan/sh/interp/builtin.go
generated
vendored
44
vendor/github.com/mvdan/sh/interp/builtin.go
generated
vendored
@ -5,13 +5,26 @@ package interp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/mvdan/sh/syntax"
|
"github.com/mvdan/sh/syntax"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *Runner) builtin(pos syntax.Pos, name string, args []string) bool {
|
func isBuiltin(name string) bool {
|
||||||
|
switch name {
|
||||||
|
case "true", ":", "false", "exit", "set", "shift", "unset",
|
||||||
|
"echo", "printf", "break", "continue", "pwd", "cd",
|
||||||
|
"wait", "builtin", "trap", "type", "source", "command",
|
||||||
|
"pushd", "popd", "umask", "alias", "unalias", "fg", "bg",
|
||||||
|
"getopts":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runner) builtin(pos syntax.Pos, name string, args []string) {
|
||||||
exit := 0
|
exit := 0
|
||||||
switch name {
|
switch name {
|
||||||
case "true", ":":
|
case "true", ":":
|
||||||
@ -46,6 +59,7 @@ func (r *Runner) builtin(pos syntax.Pos, name string, args []string) bool {
|
|||||||
default:
|
default:
|
||||||
r.errf("usage: shift [n]\n")
|
r.errf("usage: shift [n]\n")
|
||||||
exit = 2
|
exit = 2
|
||||||
|
break
|
||||||
}
|
}
|
||||||
if len(r.args) < n {
|
if len(r.args) < n {
|
||||||
n = len(r.args)
|
n = len(r.args)
|
||||||
@ -160,20 +174,28 @@ func (r *Runner) builtin(pos syntax.Pos, name string, args []string) bool {
|
|||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// TODO: pos
|
if !isBuiltin(args[0]) {
|
||||||
if !r.builtin(0, args[0], args[1:]) {
|
|
||||||
exit = 1
|
exit = 1
|
||||||
|
break
|
||||||
}
|
}
|
||||||
case "trap", "type", "source", "command", "pushd", "popd",
|
// TODO: pos
|
||||||
|
r.builtin(0, args[0], args[1:])
|
||||||
|
case "type":
|
||||||
|
for _, arg := range args {
|
||||||
|
if isBuiltin(arg) {
|
||||||
|
r.outf("%s is a shell builtin\n", arg)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if path, err := exec.LookPath(arg); err == nil {
|
||||||
|
r.outf("%s is %s\n", arg, path)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
exit = 1
|
||||||
|
r.errf("type: %s: not found\n", arg)
|
||||||
|
}
|
||||||
|
case "trap", "source", "command", "pushd", "popd",
|
||||||
"umask", "alias", "unalias", "fg", "bg", "getopts":
|
"umask", "alias", "unalias", "fg", "bg", "getopts":
|
||||||
r.errf("unhandled builtin: %s", name)
|
r.errf("unhandled builtin: %s", name)
|
||||||
// TODO(mvdan): we rely on the binary versions of these, we
|
|
||||||
// should eventually implement them as builtins like Bash for
|
|
||||||
// portability
|
|
||||||
// case "[", "test":
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
r.exit = exit
|
r.exit = exit
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
27
vendor/github.com/mvdan/sh/interp/interp.go
generated
vendored
27
vendor/github.com/mvdan/sh/interp/interp.go
generated
vendored
@ -98,12 +98,10 @@ func (r *Runner) varInd(v varValue, e syntax.ArithmExpr) string {
|
|||||||
}
|
}
|
||||||
case []string:
|
case []string:
|
||||||
// TODO: @ between double quotes
|
// TODO: @ between double quotes
|
||||||
if w, ok := e.(*syntax.Word); ok {
|
if lit, ok := e.(*syntax.Lit); ok {
|
||||||
if lit, ok := w.Parts[0].(*syntax.Lit); ok {
|
switch lit.Value {
|
||||||
switch lit.Value {
|
case "@", "*":
|
||||||
case "@", "*":
|
return strings.Join(x, " ")
|
||||||
return strings.Join(x, " ")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i := r.arithm(e)
|
i := r.arithm(e)
|
||||||
@ -373,6 +371,7 @@ func (r *Runner) cmd(cm syntax.Command) {
|
|||||||
r.stmts(x.ThenStmts)
|
r.stmts(x.ThenStmts)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
r.exit = 0
|
||||||
for _, el := range x.Elifs {
|
for _, el := range x.Elifs {
|
||||||
r.stmts(el.CondStmts)
|
r.stmts(el.CondStmts)
|
||||||
if r.exit == 0 {
|
if r.exit == 0 {
|
||||||
@ -381,9 +380,6 @@ func (r *Runner) cmd(cm syntax.Command) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.stmts(x.ElseStmts)
|
r.stmts(x.ElseStmts)
|
||||||
if len(x.Elifs)+len(x.ElseStmts) == 0 {
|
|
||||||
r.exit = 0
|
|
||||||
}
|
|
||||||
case *syntax.WhileClause:
|
case *syntax.WhileClause:
|
||||||
for r.err == nil {
|
for r.err == nil {
|
||||||
r.stmts(x.CondStmts)
|
r.stmts(x.CondStmts)
|
||||||
@ -559,10 +555,16 @@ func (r *Runner) wordParts(wps []syntax.WordPart, quoted bool) []string {
|
|||||||
curBuf.WriteString(field)
|
curBuf.WriteString(field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, wp := range wps {
|
for i, wp := range wps {
|
||||||
switch x := wp.(type) {
|
switch x := wp.(type) {
|
||||||
case *syntax.Lit:
|
case *syntax.Lit:
|
||||||
curBuf.WriteString(x.Value)
|
s := x.Value
|
||||||
|
if i > 0 || len(s) == 0 || s[0] != '~' {
|
||||||
|
} else if len(s) < 2 || s[1] == '/' {
|
||||||
|
// TODO: ~someuser
|
||||||
|
s = r.getVar("HOME") + s[1:]
|
||||||
|
}
|
||||||
|
curBuf.WriteString(s)
|
||||||
case *syntax.SglQuoted:
|
case *syntax.SglQuoted:
|
||||||
curBuf.WriteString(x.Value)
|
curBuf.WriteString(x.Value)
|
||||||
case *syntax.DblQuoted:
|
case *syntax.DblQuoted:
|
||||||
@ -619,7 +621,8 @@ func (r *Runner) call(pos syntax.Pos, name string, args []string) {
|
|||||||
r.args = oldArgs
|
r.args = oldArgs
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if r.builtin(pos, name, args) {
|
if isBuiltin(name) {
|
||||||
|
r.builtin(pos, name, args)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cmd := exec.CommandContext(r.Context, name, args...)
|
cmd := exec.CommandContext(r.Context, name, args...)
|
||||||
|
4
vendor/github.com/mvdan/sh/interp/param.go
generated
vendored
4
vendor/github.com/mvdan/sh/interp/param.go
generated
vendored
@ -40,7 +40,7 @@ func (r *Runner) paramExp(pe *syntax.ParamExp) string {
|
|||||||
switch {
|
switch {
|
||||||
case pe.Length:
|
case pe.Length:
|
||||||
str = strconv.Itoa(utf8.RuneCountInString(str))
|
str = strconv.Itoa(utf8.RuneCountInString(str))
|
||||||
case pe.Excl:
|
case pe.Indirect:
|
||||||
val, set = r.lookupVar(str)
|
val, set = r.lookupVar(str)
|
||||||
str = varStr(val)
|
str = varStr(val)
|
||||||
}
|
}
|
||||||
@ -141,7 +141,7 @@ func (r *Runner) paramExp(pe *syntax.ParamExp) string {
|
|||||||
str = string(rs)
|
str = string(rs)
|
||||||
case syntax.LowerAll:
|
case syntax.LowerAll:
|
||||||
str = strings.ToLower(str)
|
str = strings.ToLower(str)
|
||||||
default: // syntax.OtherParamOps
|
case syntax.OtherParamOps:
|
||||||
switch arg {
|
switch arg {
|
||||||
case "Q":
|
case "Q":
|
||||||
str = strconv.Quote(str)
|
str = strconv.Quote(str)
|
||||||
|
4
vendor/github.com/mvdan/sh/interp/test.go
generated
vendored
4
vendor/github.com/mvdan/sh/interp/test.go
generated
vendored
@ -74,10 +74,10 @@ func (r *Runner) binTest(op syntax.BinTestOperator, x, y string) bool {
|
|||||||
return x != "" && y != ""
|
return x != "" && y != ""
|
||||||
case syntax.OrTest:
|
case syntax.OrTest:
|
||||||
return x != "" || y != ""
|
return x != "" || y != ""
|
||||||
case syntax.TsEqual:
|
case syntax.TsMatch:
|
||||||
m, _ := path.Match(y, x)
|
m, _ := path.Match(y, x)
|
||||||
return m
|
return m
|
||||||
case syntax.TsNequal:
|
case syntax.TsNoMatch:
|
||||||
m, _ := path.Match(y, x)
|
m, _ := path.Match(y, x)
|
||||||
return !m
|
return !m
|
||||||
case syntax.TsBefore:
|
case syntax.TsBefore:
|
||||||
|
6
vendor/github.com/mvdan/sh/syntax/canonical.sh
generated
vendored
6
vendor/github.com/mvdan/sh/syntax/canonical.sh
generated
vendored
@ -25,9 +25,9 @@ case $foo in
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
foo | bar
|
foo | bar
|
||||||
foo \
|
foo &&
|
||||||
&& $(bar) \
|
$(bar) &&
|
||||||
&& (more)
|
(more)
|
||||||
|
|
||||||
foo 2>&1
|
foo 2>&1
|
||||||
foo <<EOF
|
foo <<EOF
|
||||||
|
32
vendor/github.com/mvdan/sh/syntax/lexer.go
generated
vendored
32
vendor/github.com/mvdan/sh/syntax/lexer.go
generated
vendored
@ -732,15 +732,37 @@ loop:
|
|||||||
if p.quote&allArithmExpr != 0 {
|
if p.quote&allArithmExpr != 0 {
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
case ':', '=', '%', '?', '^', ',':
|
if p.quote == paramName && p.peekByte('(') {
|
||||||
|
tok = _Lit
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
case '?':
|
||||||
|
if p.quote == paramName && p.peekByte('(') {
|
||||||
|
tok = _Lit
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case ':', '=', '%', '^', ',':
|
||||||
if p.quote&allArithmExpr != 0 || p.quote&allParamReg != 0 {
|
if p.quote&allArithmExpr != 0 || p.quote&allParamReg != 0 {
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
case '#', '[', '@':
|
case '@':
|
||||||
|
if p.quote == paramName && p.peekByte('(') {
|
||||||
|
tok = _Lit
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case '#', '[':
|
||||||
if p.quote&allParamReg != 0 {
|
if p.quote&allParamReg != 0 {
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
case '+', '-':
|
case '+':
|
||||||
|
if p.quote == paramName && p.peekByte('(') {
|
||||||
|
tok = _Lit
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case '-':
|
||||||
switch p.quote {
|
switch p.quote {
|
||||||
case paramExpInd, paramExpLen, paramExpOff,
|
case paramExpInd, paramExpLen, paramExpOff,
|
||||||
paramExpExp, paramExpRepl, sglQuotes:
|
paramExpExp, paramExpRepl, sglQuotes:
|
||||||
@ -778,7 +800,7 @@ loop:
|
|||||||
p.discardLit(1)
|
p.discardLit(1)
|
||||||
if r = p.rune(); r == '\\' {
|
if r = p.rune(); r == '\\' {
|
||||||
p.discardLit(1)
|
p.discardLit(1)
|
||||||
r = p.rune()
|
p.rune()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -893,7 +915,7 @@ func (p *parser) hdocLitWord() *Word {
|
|||||||
r = p.rune()
|
r = p.rune()
|
||||||
}
|
}
|
||||||
l := p.lit(pos, val)
|
l := p.lit(pos, val)
|
||||||
return p.word(p.singleWps(l))
|
return p.word(p.wps(l))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) advanceLitRe(r rune) {
|
func (p *parser) advanceLitRe(r rune) {
|
||||||
|
53
vendor/github.com/mvdan/sh/syntax/nodes.go
generated
vendored
53
vendor/github.com/mvdan/sh/syntax/nodes.go
generated
vendored
@ -144,6 +144,10 @@ func (s *Stmt) End() Pos {
|
|||||||
|
|
||||||
// Command represents all nodes that are simple commands, which are
|
// Command represents all nodes that are simple commands, which are
|
||||||
// directly placed in a Stmt.
|
// directly placed in a Stmt.
|
||||||
|
//
|
||||||
|
// These are *CallExpr, *IfClause, *WhileClause, *UntilClause,
|
||||||
|
// *ForClause, *CaseClause, *Block, *Subshell, *BinaryCmd, *FuncDecl,
|
||||||
|
// *ArithmCmd, *TestClause, *DeclClause, *LetClause, and *CoprocClause.
|
||||||
type Command interface {
|
type Command interface {
|
||||||
Node
|
Node
|
||||||
commandNode()
|
commandNode()
|
||||||
@ -162,7 +166,6 @@ func (*FuncDecl) commandNode() {}
|
|||||||
func (*ArithmCmd) commandNode() {}
|
func (*ArithmCmd) commandNode() {}
|
||||||
func (*TestClause) commandNode() {}
|
func (*TestClause) commandNode() {}
|
||||||
func (*DeclClause) commandNode() {}
|
func (*DeclClause) commandNode() {}
|
||||||
func (*EvalClause) commandNode() {}
|
|
||||||
func (*LetClause) commandNode() {}
|
func (*LetClause) commandNode() {}
|
||||||
func (*CoprocClause) commandNode() {}
|
func (*CoprocClause) commandNode() {}
|
||||||
|
|
||||||
@ -280,7 +283,7 @@ type ForClause struct {
|
|||||||
func (f *ForClause) Pos() Pos { return f.For }
|
func (f *ForClause) Pos() Pos { return f.For }
|
||||||
func (f *ForClause) End() Pos { return f.Done + 4 }
|
func (f *ForClause) End() Pos { return f.Done + 4 }
|
||||||
|
|
||||||
// Loop represents all nodes that can be loops in a for clause.
|
// Loop holds either *WordIter or *CStyleLoop.
|
||||||
type Loop interface {
|
type Loop interface {
|
||||||
Node
|
Node
|
||||||
loopNode()
|
loopNode()
|
||||||
@ -342,6 +345,9 @@ func (w *Word) Pos() Pos { return w.Parts[0].Pos() }
|
|||||||
func (w *Word) End() Pos { return w.Parts[len(w.Parts)-1].End() }
|
func (w *Word) End() Pos { return w.Parts[len(w.Parts)-1].End() }
|
||||||
|
|
||||||
// WordPart represents all nodes that can form a word.
|
// WordPart represents all nodes that can form a word.
|
||||||
|
//
|
||||||
|
// These are *Lit, *SglQuoted, *DblQuoted, *ParamExp, *CmdSubst,
|
||||||
|
// *ArithmExp, *ProcSubst, *ArrayExpr, and *ExtGlob.
|
||||||
type WordPart interface {
|
type WordPart interface {
|
||||||
Node
|
Node
|
||||||
wordPartNode()
|
wordPartNode()
|
||||||
@ -414,7 +420,8 @@ func (c *CmdSubst) End() Pos { return c.Right + 1 }
|
|||||||
type ParamExp struct {
|
type ParamExp struct {
|
||||||
Dollar, Rbrace Pos
|
Dollar, Rbrace Pos
|
||||||
Short bool
|
Short bool
|
||||||
Length, Excl bool // TODO(mvdan): rename Excl in 2.0 (Indirect, etc)
|
Indirect bool
|
||||||
|
Length bool
|
||||||
Param *Lit
|
Param *Lit
|
||||||
Ind *Index
|
Ind *Index
|
||||||
Slice *Slice
|
Slice *Slice
|
||||||
@ -484,6 +491,9 @@ func (a *ArithmCmd) Pos() Pos { return a.Left }
|
|||||||
func (a *ArithmCmd) End() Pos { return a.Right + 2 }
|
func (a *ArithmCmd) End() Pos { return a.Right + 2 }
|
||||||
|
|
||||||
// ArithmExpr represents all nodes that form arithmetic expressions.
|
// ArithmExpr represents all nodes that form arithmetic expressions.
|
||||||
|
//
|
||||||
|
// These are *BinaryArithm, *UnaryArithm, *ParenArithm, *Lit, and
|
||||||
|
// *ParamExp.
|
||||||
type ArithmExpr interface {
|
type ArithmExpr interface {
|
||||||
Node
|
Node
|
||||||
arithmExprNode()
|
arithmExprNode()
|
||||||
@ -492,20 +502,18 @@ type ArithmExpr interface {
|
|||||||
func (*BinaryArithm) arithmExprNode() {}
|
func (*BinaryArithm) arithmExprNode() {}
|
||||||
func (*UnaryArithm) arithmExprNode() {}
|
func (*UnaryArithm) arithmExprNode() {}
|
||||||
func (*ParenArithm) arithmExprNode() {}
|
func (*ParenArithm) arithmExprNode() {}
|
||||||
func (*Word) arithmExprNode() {}
|
func (*Lit) arithmExprNode() {}
|
||||||
|
func (*ParamExp) arithmExprNode() {}
|
||||||
|
|
||||||
// BinaryArithm represents a binary expression between two arithmetic
|
// BinaryArithm represents a binary expression between two arithmetic
|
||||||
// expression.
|
// expression.
|
||||||
//
|
//
|
||||||
// If Op is any assign operator, X will be a *Word with a single *Lit
|
// If Op is any assign operator, X will be a *Lit whose value is a valid
|
||||||
// whose value is a valid name.
|
// name.
|
||||||
//
|
//
|
||||||
// Ternary operators like "a ? b : c" are fit into this structure. Thus,
|
// Ternary operators like "a ? b : c" are fit into this structure. Thus,
|
||||||
// if Op == Quest, Y will be a *BinaryArithm with Op == Colon. Op can
|
// if Op == Quest, Y will be a *BinaryArithm with Op == Colon. Op can
|
||||||
// only be Colon in that scenario.
|
// only be Colon in that scenario.
|
||||||
//
|
|
||||||
// TODO(mvdan): we probably want to split up assigns in 2.0 (X would be
|
|
||||||
// a *Lit) to simplify the rules here. Perhaps reuse the Assign type?
|
|
||||||
type BinaryArithm struct {
|
type BinaryArithm struct {
|
||||||
OpPos Pos
|
OpPos Pos
|
||||||
Op BinAritOperator
|
Op BinAritOperator
|
||||||
@ -518,11 +526,7 @@ func (b *BinaryArithm) End() Pos { return b.Y.End() }
|
|||||||
// UnaryArithm represents an unary expression over a node, either before
|
// UnaryArithm represents an unary expression over a node, either before
|
||||||
// or after it.
|
// or after it.
|
||||||
//
|
//
|
||||||
// If Op is Inc or Dec, X will be a *Word with a single *Lit whose value
|
// If Op is Inc or Dec, X will be a *Lit whose value is a valid name.
|
||||||
// is a valid name.
|
|
||||||
//
|
|
||||||
// TODO(mvdan): consider splitting up Inc/Dec like the assigns above in
|
|
||||||
// 2.0.
|
|
||||||
type UnaryArithm struct {
|
type UnaryArithm struct {
|
||||||
OpPos Pos
|
OpPos Pos
|
||||||
Op UnAritOperator
|
Op UnAritOperator
|
||||||
@ -584,6 +588,8 @@ func (t *TestClause) Pos() Pos { return t.Left }
|
|||||||
func (t *TestClause) End() Pos { return t.Right + 2 }
|
func (t *TestClause) End() Pos { return t.Right + 2 }
|
||||||
|
|
||||||
// TestExpr represents all nodes that form arithmetic expressions.
|
// TestExpr represents all nodes that form arithmetic expressions.
|
||||||
|
//
|
||||||
|
// These are *BinaryTest, *UnaryTest, *ParenTest, and *Word.
|
||||||
type TestExpr interface {
|
type TestExpr interface {
|
||||||
Node
|
Node
|
||||||
testExprNode()
|
testExprNode()
|
||||||
@ -681,25 +687,6 @@ type ProcSubst struct {
|
|||||||
func (s *ProcSubst) Pos() Pos { return s.OpPos }
|
func (s *ProcSubst) Pos() Pos { return s.OpPos }
|
||||||
func (s *ProcSubst) End() Pos { return s.Rparen + 1 }
|
func (s *ProcSubst) End() Pos { return s.Rparen + 1 }
|
||||||
|
|
||||||
// EvalClause represents a Bash eval clause.
|
|
||||||
//
|
|
||||||
// This node will never appear when in PosixConformant mode.
|
|
||||||
//
|
|
||||||
// TODO(mvdan): EvalClause is actually pointless, as any non-trivial use
|
|
||||||
// of eval will involve parsing the program at run-time. Remove in 2.0.
|
|
||||||
type EvalClause struct {
|
|
||||||
Eval Pos
|
|
||||||
Stmt *Stmt
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *EvalClause) Pos() Pos { return e.Eval }
|
|
||||||
func (e *EvalClause) End() Pos {
|
|
||||||
if e.Stmt != nil {
|
|
||||||
return e.Stmt.End()
|
|
||||||
}
|
|
||||||
return e.Eval + 4
|
|
||||||
}
|
|
||||||
|
|
||||||
// CoprocClause represents a Bash coproc clause.
|
// CoprocClause represents a Bash coproc clause.
|
||||||
//
|
//
|
||||||
// This node will never appear when in PosixConformant mode.
|
// This node will never appear when in PosixConformant mode.
|
||||||
|
182
vendor/github.com/mvdan/sh/syntax/parser.go
generated
vendored
182
vendor/github.com/mvdan/sh/syntax/parser.go
generated
vendored
@ -132,7 +132,7 @@ func (p *parser) word(parts []WordPart) *Word {
|
|||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) singleWps(wp WordPart) []WordPart {
|
func (p *parser) wps(wp WordPart) []WordPart {
|
||||||
if len(p.wpsBatch) == 0 {
|
if len(p.wpsBatch) == 0 {
|
||||||
p.wpsBatch = make([]WordPart, 64)
|
p.wpsBatch = make([]WordPart, 64)
|
||||||
}
|
}
|
||||||
@ -142,15 +142,6 @@ func (p *parser) singleWps(wp WordPart) []WordPart {
|
|||||||
return wps
|
return wps
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) wps() []WordPart {
|
|
||||||
if len(p.wpsBatch) < 4 {
|
|
||||||
p.wpsBatch = make([]WordPart, 64)
|
|
||||||
}
|
|
||||||
wps := p.wpsBatch[:0:4]
|
|
||||||
p.wpsBatch = p.wpsBatch[4:]
|
|
||||||
return wps
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *parser) stmt(pos Pos) *Stmt {
|
func (p *parser) stmt(pos Pos) *Stmt {
|
||||||
if len(p.stmtBatch) == 0 {
|
if len(p.stmtBatch) == 0 {
|
||||||
p.stmtBatch = make([]Stmt, 16)
|
p.stmtBatch = make([]Stmt, 16)
|
||||||
@ -204,6 +195,7 @@ const (
|
|||||||
arithmExprBrack
|
arithmExprBrack
|
||||||
testRegexp
|
testRegexp
|
||||||
switchCase
|
switchCase
|
||||||
|
paramName
|
||||||
paramExpName
|
paramExpName
|
||||||
paramExpInd
|
paramExpInd
|
||||||
paramExpOff
|
paramExpOff
|
||||||
@ -218,7 +210,7 @@ const (
|
|||||||
arithmExprBrack | allParamArith
|
arithmExprBrack | allParamArith
|
||||||
allRbrack = arithmExprBrack | paramExpInd
|
allRbrack = arithmExprBrack | paramExpInd
|
||||||
allParamArith = paramExpInd | paramExpOff | paramExpLen
|
allParamArith = paramExpInd | paramExpOff | paramExpLen
|
||||||
allParamReg = paramExpName | allParamArith
|
allParamReg = paramName | paramExpName | allParamArith
|
||||||
allParamExp = allParamReg | paramExpRepl | paramExpExp
|
allParamExp = allParamReg | paramExpRepl | paramExpExp
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -498,11 +490,6 @@ func (p *parser) invalidStmtStart() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) getWord() *Word {
|
func (p *parser) getWord() *Word {
|
||||||
if p.tok == _LitWord {
|
|
||||||
w := p.word(p.singleWps(p.lit(p.pos, p.val)))
|
|
||||||
p.next()
|
|
||||||
return w
|
|
||||||
}
|
|
||||||
if parts := p.wordParts(); len(parts) > 0 {
|
if parts := p.wordParts(); len(parts) > 0 {
|
||||||
return p.word(parts)
|
return p.word(parts)
|
||||||
}
|
}
|
||||||
@ -514,7 +501,7 @@ func (p *parser) getWordOrEmpty() *Word {
|
|||||||
if len(parts) == 0 {
|
if len(parts) == 0 {
|
||||||
l := p.lit(p.pos, "")
|
l := p.lit(p.pos, "")
|
||||||
l.ValueEnd = l.ValuePos // force Lit.Pos() == Lit.End()
|
l.ValueEnd = l.ValuePos // force Lit.Pos() == Lit.End()
|
||||||
return p.word(p.singleWps(l))
|
return p.word(p.wps(l))
|
||||||
}
|
}
|
||||||
return p.word(parts)
|
return p.word(parts)
|
||||||
}
|
}
|
||||||
@ -536,9 +523,10 @@ func (p *parser) wordParts() (wps []WordPart) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if wps == nil {
|
if wps == nil {
|
||||||
wps = p.wps()
|
wps = p.wps(n)
|
||||||
|
} else {
|
||||||
|
wps = append(wps, n)
|
||||||
}
|
}
|
||||||
wps = append(wps, n)
|
|
||||||
if p.spaced {
|
if p.spaced {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -607,11 +595,10 @@ func (p *parser) wordPart() WordPart {
|
|||||||
p.rune()
|
p.rune()
|
||||||
p.tok, p.val = _LitWord, string(r)
|
p.tok, p.val = _LitWord, string(r)
|
||||||
default:
|
default:
|
||||||
if p.quote&allRegTokens != 0 {
|
old := p.quote
|
||||||
p.advanceLitNone(r)
|
p.quote = paramName
|
||||||
} else {
|
p.advanceLitOther(r)
|
||||||
p.advanceLitOther(r)
|
p.quote = old
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pe.Param = p.getLit()
|
pe.Param = p.getLit()
|
||||||
return pe
|
return pe
|
||||||
@ -665,12 +652,7 @@ func (p *parser) wordPart() WordPart {
|
|||||||
old := p.quote
|
old := p.quote
|
||||||
p.quote = dblQuotes
|
p.quote = dblQuotes
|
||||||
p.next()
|
p.next()
|
||||||
if p.tok == _LitWord {
|
q.Parts = p.wordParts()
|
||||||
q.Parts = p.singleWps(p.lit(p.pos, p.val))
|
|
||||||
p.next()
|
|
||||||
} else {
|
|
||||||
q.Parts = p.wordParts()
|
|
||||||
}
|
|
||||||
p.quote = old
|
p.quote = old
|
||||||
if !p.got(dblQuote) {
|
if !p.got(dblQuote) {
|
||||||
p.quoteErr(q.Pos(), dblQuote)
|
p.quoteErr(q.Pos(), dblQuote)
|
||||||
@ -803,7 +785,7 @@ func (p *parser) arithmExpr(ftok token, fpos Pos, level int, compact, tern bool)
|
|||||||
}
|
}
|
||||||
case AddAssgn, SubAssgn, MulAssgn, QuoAssgn, RemAssgn, AndAssgn,
|
case AddAssgn, SubAssgn, MulAssgn, QuoAssgn, RemAssgn, AndAssgn,
|
||||||
OrAssgn, XorAssgn, ShlAssgn, ShrAssgn, Assgn:
|
OrAssgn, XorAssgn, ShlAssgn, ShrAssgn, Assgn:
|
||||||
if w, ok := b.X.(*Word); !ok || !p.wordIdent(w) {
|
if l, ok := b.X.(*Lit); !ok || !validIdent(l.Value, p.bash()) {
|
||||||
p.posErr(b.OpPos, "%s must follow a name", b.Op.String())
|
p.posErr(b.OpPos, "%s must follow a name", b.Op.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -822,14 +804,6 @@ func (p *parser) arithmExpr(ftok token, fpos Pos, level int, compact, tern bool)
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) wordIdent(w *Word) bool {
|
|
||||||
if len(w.Parts) != 1 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
lit, ok := w.Parts[0].(*Lit)
|
|
||||||
return ok && validIdent(lit.Value, p.bash())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *parser) arithmExprBase(compact bool) ArithmExpr {
|
func (p *parser) arithmExprBase(compact bool) ArithmExpr {
|
||||||
var x ArithmExpr
|
var x ArithmExpr
|
||||||
switch p.tok {
|
switch p.tok {
|
||||||
@ -843,7 +817,11 @@ func (p *parser) arithmExprBase(compact bool) ArithmExpr {
|
|||||||
case addAdd, subSub:
|
case addAdd, subSub:
|
||||||
ue := &UnaryArithm{OpPos: p.pos, Op: UnAritOperator(p.tok)}
|
ue := &UnaryArithm{OpPos: p.pos, Op: UnAritOperator(p.tok)}
|
||||||
p.next()
|
p.next()
|
||||||
ue.X = p.followWordTok(token(ue.Op), ue.OpPos)
|
if lit := p.getLit(); lit == nil {
|
||||||
|
p.followErr(ue.OpPos, token(ue.Op).String(), "a literal")
|
||||||
|
} else {
|
||||||
|
ue.X = lit
|
||||||
|
}
|
||||||
return ue
|
return ue
|
||||||
case leftParen:
|
case leftParen:
|
||||||
pe := &ParenArithm{Lparen: p.pos}
|
pe := &ParenArithm{Lparen: p.pos}
|
||||||
@ -864,23 +842,27 @@ func (p *parser) arithmExprBase(compact bool) ArithmExpr {
|
|||||||
p.followErrExp(ue.OpPos, ue.Op.String())
|
p.followErrExp(ue.OpPos, ue.Op.String())
|
||||||
}
|
}
|
||||||
x = ue
|
x = ue
|
||||||
|
case illegalTok, rightBrack, rightBrace, rightParen:
|
||||||
|
case _LitWord:
|
||||||
|
x = p.getLit()
|
||||||
|
case dollar, dollBrace:
|
||||||
|
x = p.wordPart().(*ParamExp)
|
||||||
case bckQuote:
|
case bckQuote:
|
||||||
if p.quote == arithmExprLet {
|
if p.quote == arithmExprLet {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
if w := p.getWord(); w != nil {
|
if arithmOpLevel(BinAritOperator(p.tok)) >= 0 {
|
||||||
// we want real nil, not (*Word)(nil) as that
|
break
|
||||||
// sets the type to non-nil and then x != nil
|
|
||||||
x = w
|
|
||||||
}
|
}
|
||||||
|
p.curErr("arithmetic expressions must consist of names and numbers")
|
||||||
}
|
}
|
||||||
if compact && p.spaced {
|
if compact && p.spaced {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
if p.tok == addAdd || p.tok == subSub {
|
if p.tok == addAdd || p.tok == subSub {
|
||||||
if w, ok := x.(*Word); !ok || !p.wordIdent(w) {
|
if l, ok := x.(*Lit); !ok || !validIdent(l.Value, p.bash()) {
|
||||||
p.curErr("%s must follow a name", p.tok.String())
|
p.curErr("%s must follow a name", p.tok.String())
|
||||||
}
|
}
|
||||||
u := &UnaryArithm{
|
u := &UnaryArithm{
|
||||||
@ -914,7 +896,7 @@ func (p *parser) paramExp() *ParamExp {
|
|||||||
}
|
}
|
||||||
case exclMark:
|
case exclMark:
|
||||||
if p.r != '}' {
|
if p.r != '}' {
|
||||||
pe.Excl = true
|
pe.Indirect = true
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1089,7 +1071,7 @@ func (p *parser) getAssign() *Assign {
|
|||||||
start := p.lit(p.pos+1, p.val[p.asPos+1:])
|
start := p.lit(p.pos+1, p.val[p.asPos+1:])
|
||||||
if start.Value != "" {
|
if start.Value != "" {
|
||||||
start.ValuePos += Pos(p.asPos)
|
start.ValuePos += Pos(p.asPos)
|
||||||
as.Value = p.word(p.singleWps(start))
|
as.Value = p.word(p.wps(start))
|
||||||
}
|
}
|
||||||
if p.next(); p.spaced {
|
if p.next(); p.spaced {
|
||||||
return as
|
return as
|
||||||
@ -1108,7 +1090,7 @@ func (p *parser) getAssign() *Assign {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ae.Rparen = p.matched(ae.Lparen, leftParen, rightParen)
|
ae.Rparen = p.matched(ae.Lparen, leftParen, rightParen)
|
||||||
as.Value = p.word(p.singleWps(ae))
|
as.Value = p.word(p.wps(ae))
|
||||||
} else if !p.newLine && !stopToken(p.tok) {
|
} else if !p.newLine && !stopToken(p.tok) {
|
||||||
if w := p.getWord(); w != nil {
|
if w := p.getWord(); w != nil {
|
||||||
if as.Value == nil {
|
if as.Value == nil {
|
||||||
@ -1227,55 +1209,66 @@ preLoop:
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func bashDeclareWord(s string) bool {
|
|
||||||
switch s {
|
|
||||||
case "declare", "local", "export", "readonly", "typeset", "nameref":
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *parser) gotStmtPipe(s *Stmt) *Stmt {
|
func (p *parser) gotStmtPipe(s *Stmt) *Stmt {
|
||||||
switch p.tok {
|
switch p.tok {
|
||||||
case leftParen:
|
|
||||||
s.Cmd = p.subshell()
|
|
||||||
case dblLeftParen:
|
|
||||||
s.Cmd = p.arithmExpCmd()
|
|
||||||
case _LitWord:
|
case _LitWord:
|
||||||
switch {
|
switch p.val {
|
||||||
case p.val == "}":
|
case "{":
|
||||||
p.curErr("%s can only be used to close a block", p.val)
|
|
||||||
case p.val == "{":
|
|
||||||
s.Cmd = p.block()
|
s.Cmd = p.block()
|
||||||
case p.val == "if":
|
case "if":
|
||||||
s.Cmd = p.ifClause()
|
s.Cmd = p.ifClause()
|
||||||
case p.val == "while":
|
case "while":
|
||||||
s.Cmd = p.whileClause()
|
s.Cmd = p.whileClause()
|
||||||
case p.val == "until":
|
case "until":
|
||||||
s.Cmd = p.untilClause()
|
s.Cmd = p.untilClause()
|
||||||
case p.val == "for":
|
case "for":
|
||||||
s.Cmd = p.forClause()
|
s.Cmd = p.forClause()
|
||||||
case p.val == "case":
|
case "case":
|
||||||
s.Cmd = p.caseClause()
|
s.Cmd = p.caseClause()
|
||||||
case p.bash() && p.val == "[[":
|
case "}":
|
||||||
s.Cmd = p.testClause()
|
p.curErr(`%s can only be used to close a block`, p.val)
|
||||||
case p.bash() && bashDeclareWord(p.val):
|
case "]]":
|
||||||
s.Cmd = p.declClause()
|
if !p.bash() {
|
||||||
case p.bash() && p.val == "eval":
|
break
|
||||||
s.Cmd = p.evalClause()
|
}
|
||||||
case p.bash() && p.val == "coproc":
|
p.curErr(`%s can only be used to close a test`, p.val)
|
||||||
s.Cmd = p.coprocClause()
|
case "then":
|
||||||
case p.bash() && p.val == "let":
|
p.curErr(`%q can only be used in an if`, p.val)
|
||||||
s.Cmd = p.letClause()
|
case "elif":
|
||||||
case p.bash() && p.val == "function":
|
p.curErr(`%q can only be used in an if`, p.val)
|
||||||
s.Cmd = p.bashFuncDecl()
|
case "fi":
|
||||||
|
p.curErr(`%q can only be used to end an if`, p.val)
|
||||||
|
case "do":
|
||||||
|
p.curErr(`%q can only be used in a loop`, p.val)
|
||||||
|
case "done":
|
||||||
|
p.curErr(`%q can only be used to end a loop`, p.val)
|
||||||
|
case "esac":
|
||||||
|
p.curErr(`%q can only be used to end a case`, p.val)
|
||||||
default:
|
default:
|
||||||
|
if !p.bash() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch p.val {
|
||||||
|
case "[[":
|
||||||
|
s.Cmd = p.testClause()
|
||||||
|
case "declare", "local", "export", "readonly",
|
||||||
|
"typeset", "nameref":
|
||||||
|
s.Cmd = p.declClause()
|
||||||
|
case "coproc":
|
||||||
|
s.Cmd = p.coprocClause()
|
||||||
|
case "let":
|
||||||
|
s.Cmd = p.letClause()
|
||||||
|
case "function":
|
||||||
|
s.Cmd = p.bashFuncDecl()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if s.Cmd == nil {
|
||||||
name := p.lit(p.pos, p.val)
|
name := p.lit(p.pos, p.val)
|
||||||
if p.next(); p.gotSameLine(leftParen) {
|
if p.next(); p.gotSameLine(leftParen) {
|
||||||
p.follow(name.ValuePos, "foo(", rightParen)
|
p.follow(name.ValuePos, "foo(", rightParen)
|
||||||
s.Cmd = p.funcDecl(name, name.ValuePos)
|
s.Cmd = p.funcDecl(name, name.ValuePos)
|
||||||
} else {
|
} else {
|
||||||
s.Cmd = p.callExpr(s, p.word(p.singleWps(name)))
|
s.Cmd = p.callExpr(s, p.word(p.wps(name)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case bckQuote:
|
case bckQuote:
|
||||||
@ -1291,6 +1284,10 @@ func (p *parser) gotStmtPipe(s *Stmt) *Stmt {
|
|||||||
p.posErr(w.Pos(), "invalid func name")
|
p.posErr(w.Pos(), "invalid func name")
|
||||||
}
|
}
|
||||||
s.Cmd = p.callExpr(s, w)
|
s.Cmd = p.callExpr(s, w)
|
||||||
|
case leftParen:
|
||||||
|
s.Cmd = p.subshell()
|
||||||
|
case dblLeftParen:
|
||||||
|
s.Cmd = p.arithmExpCmd()
|
||||||
}
|
}
|
||||||
for !p.newLine && p.peekRedir() {
|
for !p.newLine && p.peekRedir() {
|
||||||
p.doRedirect(s)
|
p.doRedirect(s)
|
||||||
@ -1625,24 +1622,15 @@ func (p *parser) declClause() *DeclClause {
|
|||||||
return ds
|
return ds
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) evalClause() *EvalClause {
|
|
||||||
ec := &EvalClause{Eval: p.pos}
|
|
||||||
p.next()
|
|
||||||
ec.Stmt, _ = p.getStmt(false, false)
|
|
||||||
return ec
|
|
||||||
}
|
|
||||||
|
|
||||||
func isBashCompoundCommand(tok token, val string) bool {
|
func isBashCompoundCommand(tok token, val string) bool {
|
||||||
switch tok {
|
switch tok {
|
||||||
case leftParen, dblLeftParen:
|
case leftParen, dblLeftParen:
|
||||||
return true
|
return true
|
||||||
case _LitWord:
|
case _LitWord:
|
||||||
switch val {
|
switch val {
|
||||||
case "{", "if", "while", "until", "for", "case", "[[", "eval",
|
case "{", "if", "while", "until", "for", "case", "[[",
|
||||||
"coproc", "let", "function":
|
"coproc", "let", "function", "declare", "local",
|
||||||
return true
|
"export", "readonly", "typeset", "nameref":
|
||||||
}
|
|
||||||
if bashDeclareWord(val) {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1668,12 +1656,12 @@ func (p *parser) coprocClause() *CoprocClause {
|
|||||||
}
|
}
|
||||||
// name was in fact the stmt
|
// name was in fact the stmt
|
||||||
cc.Stmt = p.stmt(cc.Name.ValuePos)
|
cc.Stmt = p.stmt(cc.Name.ValuePos)
|
||||||
cc.Stmt.Cmd = p.call(p.word(p.singleWps(cc.Name)))
|
cc.Stmt.Cmd = p.call(p.word(p.wps(cc.Name)))
|
||||||
cc.Name = nil
|
cc.Name = nil
|
||||||
} else if cc.Name != nil {
|
} else if cc.Name != nil {
|
||||||
if call, ok := cc.Stmt.Cmd.(*CallExpr); ok {
|
if call, ok := cc.Stmt.Cmd.(*CallExpr); ok {
|
||||||
// name was in fact the start of a call
|
// name was in fact the start of a call
|
||||||
call.Args = append([]*Word{p.word(p.singleWps(cc.Name))},
|
call.Args = append([]*Word{p.word(p.wps(cc.Name))},
|
||||||
call.Args...)
|
call.Args...)
|
||||||
cc.Name = nil
|
cc.Name = nil
|
||||||
}
|
}
|
||||||
@ -1726,7 +1714,7 @@ func (p *parser) callExpr(s *Stmt, w *Word) *CallExpr {
|
|||||||
return ce
|
return ce
|
||||||
case _LitWord:
|
case _LitWord:
|
||||||
ce.Args = append(ce.Args, p.word(
|
ce.Args = append(ce.Args, p.word(
|
||||||
p.singleWps(p.lit(p.pos, p.val)),
|
p.wps(p.lit(p.pos, p.val)),
|
||||||
))
|
))
|
||||||
p.next()
|
p.next()
|
||||||
case bckQuote:
|
case bckQuote:
|
||||||
|
151
vendor/github.com/mvdan/sh/syntax/printer.go
generated
vendored
151
vendor/github.com/mvdan/sh/syntax/printer.go
generated
vendored
@ -11,7 +11,14 @@ import (
|
|||||||
|
|
||||||
// PrintConfig controls how the printing of an AST node will behave.
|
// PrintConfig controls how the printing of an AST node will behave.
|
||||||
type PrintConfig struct {
|
type PrintConfig struct {
|
||||||
Spaces int // 0 (default) for tabs, >0 for number of spaces
|
// Spaces dictates the indentation style. The default value of 0
|
||||||
|
// uses tabs, and any positive value uses that number of spaces.
|
||||||
|
Spaces int
|
||||||
|
// BinaryNextLine makes binary operators (such as &&, || and |)
|
||||||
|
// be at the start of a line if the statement that follows them
|
||||||
|
// is on a separate line. This means that the operator will come
|
||||||
|
// after an escaped newline.
|
||||||
|
BinaryNextLine bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var printerFree = sync.Pool{
|
var printerFree = sync.Pool{
|
||||||
@ -310,52 +317,7 @@ func (p *printer) wordPart(wp WordPart) {
|
|||||||
p.nestedStmts(x.Stmts, x.Right)
|
p.nestedStmts(x.Stmts, x.Right)
|
||||||
p.sepTok(")", x.Right)
|
p.sepTok(")", x.Right)
|
||||||
case *ParamExp:
|
case *ParamExp:
|
||||||
if x.Short {
|
p.paramExp(x)
|
||||||
p.WriteByte('$')
|
|
||||||
p.WriteString(x.Param.Value)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
p.WriteString("${")
|
|
||||||
switch {
|
|
||||||
case x.Length:
|
|
||||||
p.WriteByte('#')
|
|
||||||
case x.Excl:
|
|
||||||
p.WriteByte('!')
|
|
||||||
}
|
|
||||||
if x.Param != nil {
|
|
||||||
p.WriteString(x.Param.Value)
|
|
||||||
}
|
|
||||||
if x.Ind != nil {
|
|
||||||
p.WriteByte('[')
|
|
||||||
p.arithmExpr(x.Ind.Expr, false)
|
|
||||||
p.WriteByte(']')
|
|
||||||
}
|
|
||||||
if x.Slice != nil {
|
|
||||||
p.WriteByte(':')
|
|
||||||
if un, ok := x.Slice.Offset.(*UnaryArithm); ok {
|
|
||||||
if un.Op == Plus || un.Op == Minus {
|
|
||||||
// to avoid :+ and :-
|
|
||||||
p.WriteByte(' ')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.arithmExpr(x.Slice.Offset, true)
|
|
||||||
if x.Slice.Length != nil {
|
|
||||||
p.WriteByte(':')
|
|
||||||
p.arithmExpr(x.Slice.Length, true)
|
|
||||||
}
|
|
||||||
} else if x.Repl != nil {
|
|
||||||
if x.Repl.All {
|
|
||||||
p.WriteByte('/')
|
|
||||||
}
|
|
||||||
p.WriteByte('/')
|
|
||||||
p.word(x.Repl.Orig)
|
|
||||||
p.WriteByte('/')
|
|
||||||
p.word(x.Repl.With)
|
|
||||||
} else if x.Exp != nil {
|
|
||||||
p.WriteString(x.Exp.Op.String())
|
|
||||||
p.word(x.Exp.Word)
|
|
||||||
}
|
|
||||||
p.WriteByte('}')
|
|
||||||
case *ArithmExp:
|
case *ArithmExp:
|
||||||
p.WriteString("$((")
|
p.WriteString("$((")
|
||||||
p.arithmExpr(x.X, false)
|
p.arithmExpr(x.X, false)
|
||||||
@ -381,6 +343,55 @@ func (p *printer) wordPart(wp WordPart) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *printer) paramExp(pe *ParamExp) {
|
||||||
|
if pe.Short {
|
||||||
|
p.WriteByte('$')
|
||||||
|
p.WriteString(pe.Param.Value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.WriteString("${")
|
||||||
|
switch {
|
||||||
|
case pe.Length:
|
||||||
|
p.WriteByte('#')
|
||||||
|
case pe.Indirect:
|
||||||
|
p.WriteByte('!')
|
||||||
|
}
|
||||||
|
if pe.Param != nil {
|
||||||
|
p.WriteString(pe.Param.Value)
|
||||||
|
}
|
||||||
|
if pe.Ind != nil {
|
||||||
|
p.WriteByte('[')
|
||||||
|
p.arithmExpr(pe.Ind.Expr, false)
|
||||||
|
p.WriteByte(']')
|
||||||
|
}
|
||||||
|
if pe.Slice != nil {
|
||||||
|
p.WriteByte(':')
|
||||||
|
if un, ok := pe.Slice.Offset.(*UnaryArithm); ok {
|
||||||
|
if un.Op == Plus || un.Op == Minus {
|
||||||
|
// to avoid :+ and :-
|
||||||
|
p.WriteByte(' ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.arithmExpr(pe.Slice.Offset, true)
|
||||||
|
if pe.Slice.Length != nil {
|
||||||
|
p.WriteByte(':')
|
||||||
|
p.arithmExpr(pe.Slice.Length, true)
|
||||||
|
}
|
||||||
|
} else if pe.Repl != nil {
|
||||||
|
if pe.Repl.All {
|
||||||
|
p.WriteByte('/')
|
||||||
|
}
|
||||||
|
p.WriteByte('/')
|
||||||
|
p.word(pe.Repl.Orig)
|
||||||
|
p.WriteByte('/')
|
||||||
|
p.word(pe.Repl.With)
|
||||||
|
} else if pe.Exp != nil {
|
||||||
|
p.WriteString(pe.Exp.Op.String())
|
||||||
|
p.word(pe.Exp.Word)
|
||||||
|
}
|
||||||
|
p.WriteByte('}')
|
||||||
|
}
|
||||||
|
|
||||||
func (p *printer) loop(loop Loop) {
|
func (p *printer) loop(loop Loop) {
|
||||||
switch x := loop.(type) {
|
switch x := loop.(type) {
|
||||||
case *WordIter:
|
case *WordIter:
|
||||||
@ -405,8 +416,10 @@ func (p *printer) loop(loop Loop) {
|
|||||||
|
|
||||||
func (p *printer) arithmExpr(expr ArithmExpr, compact bool) {
|
func (p *printer) arithmExpr(expr ArithmExpr, compact bool) {
|
||||||
switch x := expr.(type) {
|
switch x := expr.(type) {
|
||||||
case *Word:
|
case *Lit:
|
||||||
p.word(x)
|
p.WriteString(x.Value)
|
||||||
|
case *ParamExp:
|
||||||
|
p.paramExp(x)
|
||||||
case *BinaryArithm:
|
case *BinaryArithm:
|
||||||
if compact {
|
if compact {
|
||||||
p.arithmExpr(x.X, compact)
|
p.arithmExpr(x.X, compact)
|
||||||
@ -636,19 +649,28 @@ func (p *printer) command(cmd Command, redirs []*Redirect) (startRedirs int) {
|
|||||||
p.incLevel()
|
p.incLevel()
|
||||||
}
|
}
|
||||||
_, p.nestedBinary = x.Y.Cmd.(*BinaryCmd)
|
_, p.nestedBinary = x.Y.Cmd.(*BinaryCmd)
|
||||||
if len(p.pendingHdocs) == 0 && x.Y.Pos() > p.nline {
|
if p.BinaryNextLine {
|
||||||
p.bslashNewl()
|
if len(p.pendingHdocs) == 0 && x.Y.Pos() > p.nline {
|
||||||
p.indent()
|
p.bslashNewl()
|
||||||
}
|
p.indent()
|
||||||
p.spacedString(x.Op.String())
|
}
|
||||||
if p.anyCommentsBefore(x.Y.Pos()) {
|
p.spacedString(x.Op.String())
|
||||||
p.wantSpace = false
|
if p.anyCommentsBefore(x.Y.Pos()) {
|
||||||
p.WriteByte('\n')
|
p.wantSpace = false
|
||||||
p.indent()
|
p.WriteByte('\n')
|
||||||
p.incLines(p.comments[0].Pos())
|
p.indent()
|
||||||
p.commentsUpTo(x.Y.Pos())
|
p.incLines(p.comments[0].Pos())
|
||||||
p.WriteByte('\n')
|
p.commentsUpTo(x.Y.Pos())
|
||||||
p.indent()
|
p.WriteByte('\n')
|
||||||
|
p.indent()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.spacedString(x.Op.String())
|
||||||
|
if x.Y.Pos() > p.nline {
|
||||||
|
p.commentsUpTo(x.Y.Pos())
|
||||||
|
p.newline(0)
|
||||||
|
p.indent()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p.incLines(x.Y.Pos())
|
p.incLines(x.Y.Pos())
|
||||||
p.stmt(x.Y)
|
p.stmt(x.Y)
|
||||||
@ -723,11 +745,6 @@ func (p *printer) command(cmd Command, redirs []*Redirect) (startRedirs int) {
|
|||||||
p.word(w)
|
p.word(w)
|
||||||
}
|
}
|
||||||
p.assigns(x.Assigns)
|
p.assigns(x.Assigns)
|
||||||
case *EvalClause:
|
|
||||||
p.spacedString("eval")
|
|
||||||
if x.Stmt != nil {
|
|
||||||
p.stmt(x.Stmt)
|
|
||||||
}
|
|
||||||
case *CoprocClause:
|
case *CoprocClause:
|
||||||
p.spacedString("coproc")
|
p.spacedString("coproc")
|
||||||
if x.Name != nil {
|
if x.Name != nil {
|
||||||
|
16
vendor/github.com/mvdan/sh/syntax/tokens.go
generated
vendored
16
vendor/github.com/mvdan/sh/syntax/tokens.go
generated
vendored
@ -316,16 +316,12 @@ const (
|
|||||||
TsGeq
|
TsGeq
|
||||||
TsLss
|
TsLss
|
||||||
TsGtr
|
TsGtr
|
||||||
AndTest = BinTestOperator(andAnd)
|
AndTest = BinTestOperator(andAnd)
|
||||||
OrTest = BinTestOperator(orOr)
|
OrTest = BinTestOperator(orOr)
|
||||||
// TODO(mvdan): == and != are pattern matches; use more
|
TsMatch = BinTestOperator(equal)
|
||||||
// appropriate names like TsMatch and TsNoMatch in 2.0
|
TsNoMatch = BinTestOperator(nequal)
|
||||||
TsEqual = BinTestOperator(equal)
|
TsBefore = BinTestOperator(rdrIn)
|
||||||
TsNequal = BinTestOperator(nequal)
|
TsAfter = BinTestOperator(rdrOut)
|
||||||
TsBefore = BinTestOperator(rdrIn)
|
|
||||||
TsAfter = BinTestOperator(rdrOut)
|
|
||||||
// Deprecated: now parses as TsEqual
|
|
||||||
TsAssgn = BinTestOperator(assgn) // TODO(mvdan): remove in 2.0
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (o RedirOperator) String() string { return token(o).String() }
|
func (o RedirOperator) String() string { return token(o).String() }
|
||||||
|
4
vendor/github.com/mvdan/sh/syntax/walk.go
generated
vendored
4
vendor/github.com/mvdan/sh/syntax/walk.go
generated
vendored
@ -163,10 +163,6 @@ func Walk(node Node, f func(Node) bool) {
|
|||||||
Walk(x.Pattern, f)
|
Walk(x.Pattern, f)
|
||||||
case *ProcSubst:
|
case *ProcSubst:
|
||||||
walkStmts(x.Stmts, f)
|
walkStmts(x.Stmts, f)
|
||||||
case *EvalClause:
|
|
||||||
if x.Stmt != nil {
|
|
||||||
Walk(x.Stmt, f)
|
|
||||||
}
|
|
||||||
case *CoprocClause:
|
case *CoprocClause:
|
||||||
if x.Name != nil {
|
if x.Name != nil {
|
||||||
Walk(x.Name, f)
|
Walk(x.Name, f)
|
||||||
|
12
vendor/vendor.json
vendored
12
vendor/vendor.json
vendored
@ -51,16 +51,16 @@
|
|||||||
"revisionTime": "2017-01-24T11:57:57Z"
|
"revisionTime": "2017-01-24T11:57:57Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "1ZLAvHVYAS3kxaYI8OQiTBllqNU=",
|
"checksumSHA1": "ZjfvXVu+OyeRBysQ8uowAkPD/6o=",
|
||||||
"path": "github.com/mvdan/sh/interp",
|
"path": "github.com/mvdan/sh/interp",
|
||||||
"revision": "17e267b541e30baece16b7ddeae50822cc6a795f",
|
"revision": "faf782d3a498f50cfc6aa9071d04e6f1e82e8035",
|
||||||
"revisionTime": "2017-04-24T11:31:08Z"
|
"revisionTime": "2017-04-30T14:10:52Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "4/7joITdf4wl+uoV8zDXgYqy2aw=",
|
"checksumSHA1": "RIR7FOsCR78SmOJOUsclJe9lvxo=",
|
||||||
"path": "github.com/mvdan/sh/syntax",
|
"path": "github.com/mvdan/sh/syntax",
|
||||||
"revision": "17e267b541e30baece16b7ddeae50822cc6a795f",
|
"revision": "faf782d3a498f50cfc6aa9071d04e6f1e82e8035",
|
||||||
"revisionTime": "2017-04-24T11:31:08Z"
|
"revisionTime": "2017-04-30T14:10:52Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "HUXE+Nrcau8FSaVEvPYHMvDjxOE=",
|
"checksumSHA1": "HUXE+Nrcau8FSaVEvPYHMvDjxOE=",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user