package syntax
Import Path
mvdan.cc/sh/v3/syntax (on go.dev)
Dependency Relation
imports 11 packages, and imported by one package
Involved Source Files
braces.go
Package syntax implements parsing and formatting of shell programs.
It supports POSIX Shell, Bash, and mksh.
lexer.go
nodes.go
parser.go
parser_arithm.go
printer.go
quote.go
quotestate_string.go
simplify.go
token_string.go
tokens.go
walk.go
Code Examples
package main
import (
"os"
"strings"
"mvdan.cc/sh/v3/syntax"
)
func main() {
r := strings.NewReader("{ foo; bar; }")
f, err := syntax.NewParser().Parse(r, "")
if err != nil {
return
}
syntax.NewPrinter().Print(os.Stdout, f)
}
package main
import (
"fmt"
"os"
"strings"
"mvdan.cc/sh/v3/syntax"
)
func main() {
r := strings.NewReader("echo foo; if x; then y; fi; foo | bar")
f, err := syntax.NewParser().Parse(r, "")
if err != nil {
return
}
printer := syntax.NewPrinter()
for i, stmt := range f.Stmts {
fmt.Printf("Cmd %d: %-20T - ", i, stmt.Cmd)
printer.Print(os.Stdout, stmt.Cmd)
fmt.Println()
}
}
package main
import (
"os"
"strings"
"mvdan.cc/sh/v3/syntax"
)
func main() {
in := strings.NewReader(`echo 'foo'`)
f, err := syntax.NewParser().Parse(in, "")
if err != nil {
return
}
syntax.DebugPrint(os.Stdout, f)
}
package main
import (
"fmt"
"os"
"strings"
"mvdan.cc/sh/v3/syntax"
)
func main() {
src := "for ((i = 0; i < 5; i++)); do echo $i >f; done"
// LangBash is the default
r := strings.NewReader(src)
f, err := syntax.NewParser().Parse(r, "")
fmt.Println(err)
// Parser errors with LangPOSIX
r = strings.NewReader(src)
_, err = syntax.NewParser(syntax.Variant(syntax.LangPOSIX)).Parse(r, "")
fmt.Println(err)
syntax.NewPrinter().Print(os.Stdout, f)
syntax.NewPrinter(syntax.SpaceRedirects(true)).Print(os.Stdout, f)
}
package main
import (
"fmt"
"mvdan.cc/sh/v3/syntax"
)
func main() {
for _, s := range []string{
"foo",
"bar $baz",
`"won't"`,
"~/home",
"#1304",
"name=value",
"for",
"glob-*",
"invalid-\xe2'",
"nonprint-\x0b\x1b",
} {
// We assume Bash syntax here.
// For general shell syntax quoting, use syntax.LangPOSIX.
quoted, err := syntax.Quote(s, syntax.LangBash)
if err != nil {
fmt.Printf("%q cannot be quoted: %v\n", s, err)
} else {
fmt.Printf("Quote(%17q): %s\n", s, quoted)
}
}
}
package main
import (
"os"
"strings"
"mvdan.cc/sh/v3/syntax"
)
func main() {
in := strings.NewReader(`echo $foo "and $bar"`)
f, err := syntax.NewParser().Parse(in, "")
if err != nil {
return
}
syntax.Walk(f, func(node syntax.Node) bool {
switch x := node.(type) {
case *syntax.ParamExp:
x.Param.Value = strings.ToUpper(x.Param.Value)
}
return true
})
syntax.NewPrinter().Print(os.Stdout, f)
}
package main
import (
"fmt"
"os"
"strings"
"mvdan.cc/sh/v3/syntax"
)
func main() {
r := strings.NewReader("echo foo${bar}'baz'")
f, err := syntax.NewParser().Parse(r, "")
if err != nil {
return
}
printer := syntax.NewPrinter()
args := f.Stmts[0].Cmd.(*syntax.CallExpr).Args
for i, word := range args {
fmt.Printf("Word number %d:\n", i)
for _, part := range word.Parts {
fmt.Printf("%-20T - ", part)
printer.Print(os.Stdout, part)
fmt.Println()
}
fmt.Println()
}
}
Package-Level Type Names (total 71)
ArithmCmd represents an arithmetic command.
This node will only appear in LangBash and LangMirBSDKorn.
Left Pos
Right Pos
// mksh's ((# expr))
X ArithmExpr
(*ArithmCmd) End() Pos
(*ArithmCmd) Pos() Pos
*ArithmCmd : Command
*ArithmCmd : Node
ArithmExp represents an arithmetic expansion.
// deprecated $[expr] form
Left Pos
Right Pos
// mksh's $((# expr))
X ArithmExpr
(*ArithmExp) End() Pos
(*ArithmExp) Pos() Pos
*ArithmExp : Node
*ArithmExp : WordPart
ArithmExpr represents all nodes that form arithmetic expressions.
These are *BinaryArithm, *UnaryArithm, *ParenArithm, and *Word.
End returns the position of the character immediately after the node.
If the character is a newline, the line number won't cross into the
next line. Comments are ignored, except if the node is a *File.
Pos returns the position of the first character of the node. Comments
are ignored, except if the node is a *File.
*BinaryArithm
*ParenArithm
*UnaryArithm
*Word
ArithmExpr : Node
func (*Parser).Arithmetic(r io.Reader) (ArithmExpr, error)
ArrayElem represents a Bash array element.
Index can be nil; for example, declare -a x=(value).
Value can be nil; for example, declare -A x=([index]=).
Finally, neither can be nil; for example, declare -A x=([index]=value)
Comments []Comment
Index ArithmExpr
Value *Word
(*ArrayElem) End() Pos
(*ArrayElem) Pos() Pos
*ArrayElem : Node
ArrayExpr represents a Bash array expression.
This node will only appear with LangBash.
Elems []*ArrayElem
Last []Comment
Lparen Pos
Rparen Pos
(*ArrayExpr) End() Pos
(*ArrayExpr) Pos() Pos
*ArrayExpr : Node
Assign represents an assignment to a variable.
Here and elsewhere, Index can mean either an index expression into an indexed
array, or a string key into an associative array.
If Index is non-nil, the value will be a word and not an array as nested
arrays are not allowed.
If Naked is true and Name is nil, the assignment is part of a DeclClause and
the argument (in the Value field) will be evaluated at run-time. This
includes parameter expansions, which may expand to assignments or options.
// +=
// =(arr)
// [i], ["k"]
// without '='
// must be a valid name
// =val
(*Assign) End() Pos
(*Assign) Pos() Pos
*Assign : Node
( BinAritOperator) String() string
BinAritOperator : expvar.Var
BinAritOperator : fmt.Stringer
const Add
const AddAssgn
const And
const AndArit
const AndAssgn
const Assgn
const Comma
const Eql
const Geq
const Gtr
const Leq
const Lss
const Mul
const MulAssgn
const Neq
const Or
const OrArit
const OrAssgn
const Pow
const Quo
const QuoAssgn
const Rem
const RemAssgn
const Shl
const ShlAssgn
const Shr
const ShrAssgn
const Sub
const SubAssgn
const TernColon
const TernQuest
const Xor
const XorAssgn
BinaryArithm represents a binary arithmetic expression.
If Op is any assign operator, X will be a word with a single *Lit whose value
is a valid name.
Ternary operators like "a ? b : c" are fit into this structure. Thus, if
Op==TernQuest, Y will be a *BinaryArithm with Op==TernColon. Op can only be
TernColon in that scenario.
Op BinAritOperator
OpPos Pos
X ArithmExpr
Y ArithmExpr
(*BinaryArithm) End() Pos
(*BinaryArithm) Pos() Pos
*BinaryArithm : ArithmExpr
*BinaryArithm : Node
BinaryCmd represents a binary expression between two statements.
Op BinCmdOperator
OpPos Pos
X *Stmt
Y *Stmt
(*BinaryCmd) End() Pos
(*BinaryCmd) Pos() Pos
*BinaryCmd : Command
*BinaryCmd : Node
BinaryTest represents a binary test expression.
Op BinTestOperator
OpPos Pos
X TestExpr
Y TestExpr
(*BinaryTest) End() Pos
(*BinaryTest) Pos() Pos
*BinaryTest : Node
*BinaryTest : TestExpr
( BinCmdOperator) String() string
BinCmdOperator : expvar.Var
BinCmdOperator : fmt.Stringer
const AndStmt
const OrStmt
const Pipe
const PipeAll
( BinTestOperator) String() string
BinTestOperator : expvar.Var
BinTestOperator : fmt.Stringer
const AndTest
const OrTest
const TsAfter
const TsBefore
const TsDevIno
const TsEql
const TsGeq
const TsGtr
const TsLeq
const TsLss
const TsMatch
const TsMatchShort
const TsNeq
const TsNewer
const TsNoMatch
const TsOlder
const TsReMatch
Block represents a series of commands that should be executed in a nested
scope. It is essentially a list of statements within curly braces.
Last []Comment
Lbrace Pos
Rbrace Pos
Stmts []*Stmt
(*Block) End() Pos
(*Block) Pos() Pos
*Block : Command
*Block : Node
BraceExp represents a Bash brace expression, such as "{a,f}" or "{1..10}".
This node will only appear as a result of SplitBraces.
Elems []*Word
// {x..y[..incr]} instead of {x,y[,...]}
(*BraceExp) End() Pos
(*BraceExp) Pos() Pos
*BraceExp : Node
*BraceExp : WordPart
CallExpr represents a command execution or function call, otherwise known as
a "simple command".
If Args is empty, Assigns apply to the shell environment. Otherwise, they are
variables that cannot be arrays and which only apply to the call.
Args []*Word
// a=x b=y args
(*CallExpr) End() Pos
(*CallExpr) Pos() Pos
*CallExpr : Command
*CallExpr : Node
CaseClause represents a case (switch) clause.
// deprecated mksh form with braces instead of in/esac
Case Pos
Esac Pos
In Pos
Items []*CaseItem
Last []Comment
Word *Word
(*CaseClause) End() Pos
(*CaseClause) Pos() Pos
*CaseClause : Command
*CaseClause : Node
CaseItem represents a pattern list (case) within a CaseClause.
Comments []Comment
Last []Comment
Op CaseOperator
// unset if it was finished by "esac"
Patterns []*Word
Stmts []*Stmt
(*CaseItem) End() Pos
(*CaseItem) Pos() Pos
*CaseItem : Node
( CaseOperator) String() string
CaseOperator : expvar.Var
CaseOperator : fmt.Stringer
const Break
const Fallthrough
const Resume
const ResumeKorn
CmdSubst represents a command substitution.
// deprecated `foo`
Last []Comment
Left Pos
// mksh's ${|foo;}
Right Pos
Stmts []*Stmt
// mksh's ${ foo;}
(*CmdSubst) End() Pos
(*CmdSubst) Pos() Pos
*CmdSubst : Node
*CmdSubst : WordPart
Command represents all nodes that are simple or compound commands, including
function declarations.
These are *CallExpr, *IfClause, *WhileClause, *ForClause, *CaseClause,
*Block, *Subshell, *BinaryCmd, *FuncDecl, *ArithmCmd, *TestClause,
*DeclClause, *LetClause, *TimeClause, and *CoprocClause.
End returns the position of the character immediately after the node.
If the character is a newline, the line number won't cross into the
next line. Comments are ignored, except if the node is a *File.
Pos returns the position of the first character of the node. Comments
are ignored, except if the node is a *File.
*ArithmCmd
*BinaryCmd
*Block
*CallExpr
*CaseClause
*CoprocClause
*DeclClause
*ForClause
*FuncDecl
*IfClause
*LetClause
*Subshell
*TestClause
*TestDecl
*TimeClause
*WhileClause
Command : Node
Comment represents a single comment on a single line.
Hash Pos
Text string
(*Comment) End() Pos
(*Comment) Pos() Pos
*Comment : Node
CoprocClause represents a Bash coproc clause.
This node will only appear with LangBash.
Coproc Pos
Name *Word
Stmt *Stmt
(*CoprocClause) End() Pos
(*CoprocClause) Pos() Pos
*CoprocClause : Command
*CoprocClause : Node
CStyleLoop represents the behavior of a for clause similar to the C
language.
This node will only appear with LangBash.
Init, Cond, Post can each be nil, if the for loop construct omits it.
Init, Cond, Post can each be nil, if the for loop construct omits it.
Lparen Pos
Init, Cond, Post can each be nil, if the for loop construct omits it.
Rparen Pos
(*CStyleLoop) End() Pos
(*CStyleLoop) Pos() Pos
*CStyleLoop : Loop
*CStyleLoop : Node
DblQuoted represents a list of nodes within double quotes.
// $""
Left Pos
Parts []WordPart
Right Pos
(*DblQuoted) End() Pos
(*DblQuoted) Pos() Pos
*DblQuoted : Node
*DblQuoted : WordPart
DeclClause represents a Bash declare clause.
Args can contain a mix of regular and naked assignments. The naked
assignments can represent either options or variable names.
This node will only appear with LangBash.
Args []*Assign
Variant is one of "declare", "local", "export", "readonly",
"typeset", or "nameref".
(*DeclClause) End() Pos
(*DeclClause) Pos() Pos
*DeclClause : Command
*DeclClause : Node
Expansion represents string manipulation in a ParamExp other than those
covered by Replace.
Op ParExpOperator
Word *Word
ExtGlob represents a Bash extended globbing expression. Note that these are
parsed independently of whether shopt has been called or not.
This node will only appear in LangBash and LangMirBSDKorn.
Op GlobOperator
OpPos Pos
Pattern *Lit
(*ExtGlob) End() Pos
(*ExtGlob) Pos() Pos
*ExtGlob : Node
*ExtGlob : WordPart
File represents a shell source file.
Last []Comment
Name string
Stmts []*Stmt
(*File) End() Pos
(*File) Pos() Pos
*File : Node
func (*Parser).Parse(r io.Reader, name string) (*File, error)
ForClause represents a for or a select clause. The latter is only present in
Bash.
// deprecated form with { } instead of do/done
Do []*Stmt
DoLast []Comment
DoPos Pos
DonePos Pos
ForPos Pos
Loop Loop
Select bool
(*ForClause) End() Pos
(*ForClause) Pos() Pos
*ForClause : Command
*ForClause : Node
FuncDecl represents the declaration of a function.
Body *Stmt
Name *Lit
// with () parentheses, only meaningful with RsrvWord=true
Position Pos
// non-posix "function f" style
(*FuncDecl) End() Pos
(*FuncDecl) Pos() Pos
*FuncDecl : Command
*FuncDecl : Node
( GlobOperator) String() string
GlobOperator : expvar.Var
GlobOperator : fmt.Stringer
const GlobExcept
const GlobOne
const GlobOneOrMore
const GlobZeroOrMore
const GlobZeroOrOne
IfClause represents an if statement.
Cond []*Stmt
CondLast []Comment
// if non-nil, an "elif" or an "else"
// position of "fi", shared with .Else if non-nil
// comments on the first "elif", "else", or "fi"
// position of the starting "if", "elif", or "else" token
Then []*Stmt
ThenLast []Comment
// position of "then", empty if this is an "else"
(*IfClause) End() Pos
(*IfClause) Pos() Pos
*IfClause : Command
*IfClause : Node
LangError is returned when the parser encounters code that is only valid in
other shell language variants. The error includes what feature is not present
in the current language variant, and what languages support it.
Feature string
Filename string
Langs []LangVariant
Pos Pos
( LangError) Error() string
LangError : error
LangVariant describes a shell language variant to use when tokenizing and
parsing shell code. The zero value is LangBash.
(*LangVariant) Set(s string) error
( LangVariant) String() string
LangVariant : expvar.Var
*LangVariant : flag.Value
LangVariant : fmt.Stringer
func Quote(s string, lang LangVariant) (string, error)
func Variant(l LangVariant) ParserOption
const LangAuto
const LangBash
const LangBats
const LangMirBSDKorn
const LangPOSIX
LetClause represents a Bash let clause.
This node will only appear in LangBash and LangMirBSDKorn.
Exprs []ArithmExpr
Let Pos
(*LetClause) End() Pos
(*LetClause) Pos() Pos
*LetClause : Command
*LetClause : Node
Lit represents a string literal.
Note that a parsed string literal may not appear as-is in the original source
code, as it is possible to split literals by escaping newlines. The splitting
is lost, but the end position is not.
Value string
ValueEnd Pos
ValuePos Pos
(*Lit) End() Pos
(*Lit) Pos() Pos
*Lit : Node
*Lit : WordPart
Loop holds either *WordIter or *CStyleLoop.
End returns the position of the character immediately after the node.
If the character is a newline, the line number won't cross into the
next line. Comments are ignored, except if the node is a *File.
Pos returns the position of the first character of the node. Comments
are ignored, except if the node is a *File.
*CStyleLoop
*WordIter
Loop : Node
Node represents a syntax tree node.
End returns the position of the character immediately after the node.
If the character is a newline, the line number won't cross into the
next line. Comments are ignored, except if the node is a *File.
Pos returns the position of the first character of the node. Comments
are ignored, except if the node is a *File.
*ArithmCmd
*ArithmExp
ArithmExpr (interface)
*ArrayElem
*ArrayExpr
*Assign
*BinaryArithm
*BinaryCmd
*BinaryTest
*Block
*BraceExp
*CallExpr
*CaseClause
*CaseItem
*CmdSubst
Command (interface)
*Comment
*CoprocClause
*CStyleLoop
*DblQuoted
*DeclClause
*ExtGlob
*File
*ForClause
*FuncDecl
*IfClause
*LetClause
*Lit
Loop (interface)
*ParamExp
*ParenArithm
*ParenTest
*ProcSubst
*Redirect
*SglQuoted
*Stmt
*Subshell
*TestClause
*TestDecl
TestExpr (interface)
*TimeClause
*UnaryArithm
*UnaryTest
*WhileClause
*Word
*WordIter
WordPart (interface)
func DebugPrint(w io.Writer, node Node) error
func Simplify(n Node) bool
func Walk(node Node, f func(Node) bool)
func (*Printer).Print(w io.Writer, node Node) error
ParamExp represents a parameter expansion.
Dollar Pos
// ${!a}
// ${a:-b}, ${a#b}, etc
// ${a[i]}, ${a["k"]}
// ${#a}
// ${!prefix*} or ${!prefix@}
Param *Lit
Rbrace Pos
// ${a/x/y}
// $a instead of ${a}
// ${a:x:y}
// ${%a}
(*ParamExp) End() Pos
(*ParamExp) Pos() Pos
*ParamExp : Node
*ParamExp : WordPart
ParenArithm represents an arithmetic expression within parentheses.
Lparen Pos
Rparen Pos
X ArithmExpr
(*ParenArithm) End() Pos
(*ParenArithm) Pos() Pos
*ParenArithm : ArithmExpr
*ParenArithm : Node
ParenTest represents a test expression within parentheses.
Lparen Pos
Rparen Pos
X TestExpr
(*ParenTest) End() Pos
(*ParenTest) Pos() Pos
*ParenTest : Node
*ParenTest : TestExpr
( ParExpOperator) String() string
ParExpOperator : expvar.Var
ParExpOperator : fmt.Stringer
const AlternateUnset
const AlternateUnsetOrNull
const AssignUnset
const AssignUnsetOrNull
const DefaultUnset
const DefaultUnsetOrNull
const ErrorUnset
const ErrorUnsetOrNull
const LowerAll
const LowerFirst
const OtherParamOps
const RemLargePrefix
const RemLargeSuffix
const RemSmallPrefix
const RemSmallSuffix
const UpperAll
const UpperFirst
( ParNamesOperator) String() string
ParNamesOperator : expvar.Var
ParNamesOperator : fmt.Stringer
const NamesPrefix
const NamesPrefixWords
ParseError represents an error found when parsing a source file, from which
the parser cannot recover.
Filename string
Incomplete bool
Pos Pos
Text string
( ParseError) Error() string
ParseError : error
Parser holds the internal state of the parsing mechanism of a
program.
Arithmetic parses a single arithmetic expression. That is, as if the input
were within the $(( and )) tokens.
Document parses a single here-document word. That is, it parses the input as
if they were lines following a <<EOF redirection.
In practice, this is the same as parsing the input as if it were within
double quotes, but without having to escape all double quote characters.
Similarly, the here-document word parsed here cannot be ended by any
delimiter other than reaching the end of the input.
Incomplete reports whether the parser is waiting to read more bytes because
it needs to finish properly parsing a statement.
It is only safe to call while the parser is blocked on a read. For an example
use case, see [Parser.Interactive].
Interactive implements what is necessary to parse statements in an
interactive shell. The parser will call the given function under two
circumstances outlined below.
If a line containing any number of statements is parsed, the function will be
called with said statements.
If a line ending in an incomplete statement is parsed, the function will be
called with any fully parsed statements, and [Parser.Incomplete] will return true.
One can imagine a simple interactive shell implementation as follows:
fmt.Fprintf(os.Stdout, "$ ")
parser.Interactive(os.Stdin, func(stmts []*syntax.Stmt) bool {
if parser.Incomplete() {
fmt.Fprintf(os.Stdout, "> ")
return true
}
run(stmts)
fmt.Fprintf(os.Stdout, "$ ")
return true
}
If the callback function returns false, parsing is stopped and the function
is not called again.
Parse reads and parses a shell program with an optional name. It
returns the parsed program if no issues were encountered. Otherwise,
an error is returned. Reads from r are buffered.
Parse can be called more than once, but not concurrently. That is, a
Parser can be reused once it is done working.
Stmts reads and parses statements one at a time, calling a function
each time one is parsed. If the function returns false, parsing is
stopped and the function is not called again.
Words reads and parses words one at a time, calling a function each time one
is parsed. If the function returns false, parsing is stopped and the function
is not called again.
Newlines are skipped, meaning that multi-line input will work fine. If the
parser encounters a token that isn't a word, such as a semicolon, an error
will be returned.
Note that the lexer doesn't currently tokenize spaces, so it may need to read
a non-space byte such as a newline or a letter before finishing the parsing
of a word. This will be fixed in the future.
func NewParser(options ...ParserOption) *Parser
ParserOption is a function which can be passed to NewParser
to alter its behavior. To apply option to existing Parser
call it directly, for example KeepComments(true)(parser).
func KeepComments(enabled bool) ParserOption
func StopAt(word string) ParserOption
func Variant(l LangVariant) ParserOption
func NewParser(options ...ParserOption) *Parser
Pos is a position within a shell source file.
After reports whether the position p is after p2. It is a more expressive
version of p.Offset() > p2.Offset().
Col returns the column number of the position, starting at 1. It counts in
bytes.
Col is protected against overflows; if an input line has too many columns,
extra columns will have a column number of 0, rendered as "?" by [Pos.String].
IsValid reports whether the position contains useful position information.
Some positions returned via [Parse] may be invalid: for example, [Stmt.Semicolon]
will only be valid if a statement contained a closing token such as ';'.
Line returns the line number of the position, starting at 1.
Line is protected against overflows; if an input has too many lines, extra
lines will have a line number of 0, rendered as "?" by [Pos.String].
Offset returns the byte offset of the position in the original source file.
Byte offsets start at 0.
Note that Offset is not protected against overflows;
if an input is larger than 4GiB, the offset will wrap around to 0.
( Pos) String() string
Pos : database/sql/driver.Validator
Pos : expvar.Var
Pos : fmt.Stringer
func NewPos(offset, line, column uint) Pos
func (*ArithmCmd).End() Pos
func (*ArithmCmd).Pos() Pos
func (*ArithmExp).End() Pos
func (*ArithmExp).Pos() Pos
func ArithmExpr.End() Pos
func ArithmExpr.Pos() Pos
func (*ArrayElem).End() Pos
func (*ArrayElem).Pos() Pos
func (*ArrayExpr).End() Pos
func (*ArrayExpr).Pos() Pos
func (*Assign).End() Pos
func (*Assign).Pos() Pos
func (*BinaryArithm).End() Pos
func (*BinaryArithm).Pos() Pos
func (*BinaryCmd).End() Pos
func (*BinaryCmd).Pos() Pos
func (*BinaryTest).End() Pos
func (*BinaryTest).Pos() Pos
func (*Block).End() Pos
func (*Block).Pos() Pos
func (*BraceExp).End() Pos
func (*BraceExp).Pos() Pos
func (*CallExpr).End() Pos
func (*CallExpr).Pos() Pos
func (*CaseClause).End() Pos
func (*CaseClause).Pos() Pos
func (*CaseItem).End() Pos
func (*CaseItem).Pos() Pos
func (*CmdSubst).End() Pos
func (*CmdSubst).Pos() Pos
func Command.End() Pos
func Command.Pos() Pos
func (*Comment).End() Pos
func (*Comment).Pos() Pos
func (*CoprocClause).End() Pos
func (*CoprocClause).Pos() Pos
func (*CStyleLoop).End() Pos
func (*CStyleLoop).Pos() Pos
func (*DblQuoted).End() Pos
func (*DblQuoted).Pos() Pos
func (*DeclClause).End() Pos
func (*DeclClause).Pos() Pos
func (*ExtGlob).End() Pos
func (*ExtGlob).Pos() Pos
func (*File).End() Pos
func (*File).Pos() Pos
func (*ForClause).End() Pos
func (*ForClause).Pos() Pos
func (*FuncDecl).End() Pos
func (*FuncDecl).Pos() Pos
func (*IfClause).End() Pos
func (*IfClause).Pos() Pos
func (*LetClause).End() Pos
func (*LetClause).Pos() Pos
func (*Lit).End() Pos
func (*Lit).Pos() Pos
func Loop.End() Pos
func Loop.Pos() Pos
func Node.End() Pos
func Node.Pos() Pos
func (*ParamExp).End() Pos
func (*ParamExp).Pos() Pos
func (*ParenArithm).End() Pos
func (*ParenArithm).Pos() Pos
func (*ParenTest).End() Pos
func (*ParenTest).Pos() Pos
func (*ProcSubst).End() Pos
func (*ProcSubst).Pos() Pos
func (*Redirect).End() Pos
func (*Redirect).Pos() Pos
func (*SglQuoted).End() Pos
func (*SglQuoted).Pos() Pos
func (*Stmt).End() Pos
func (*Stmt).Pos() Pos
func (*Subshell).End() Pos
func (*Subshell).Pos() Pos
func (*TestClause).End() Pos
func (*TestClause).Pos() Pos
func (*TestDecl).End() Pos
func (*TestDecl).Pos() Pos
func TestExpr.End() Pos
func TestExpr.Pos() Pos
func (*TimeClause).End() Pos
func (*TimeClause).Pos() Pos
func (*UnaryArithm).End() Pos
func (*UnaryArithm).Pos() Pos
func (*UnaryTest).End() Pos
func (*UnaryTest).Pos() Pos
func (*WhileClause).End() Pos
func (*WhileClause).Pos() Pos
func (*Word).End() Pos
func (*Word).Pos() Pos
func (*WordIter).End() Pos
func (*WordIter).Pos() Pos
func WordPart.End() Pos
func WordPart.Pos() Pos
func Pos.After(p2 Pos) bool
Printer holds the internal state of the printing mechanism of a
program.
( Printer) Flush() error
Print "pretty-prints" the given syntax tree node to the given writer. Writes
to w are buffered.
The node types supported at the moment are *File, *Stmt, *Word, *Assign, any
Command node, and any WordPart node. A trailing newline will only be printed
when a *File is used.
( Printer) Reset(io.Writer)
( Printer) Write([]byte) (int, error)
( Printer) WriteByte(byte) error
( Printer) WriteString(string) (int, error)
Printer : github.com/apache/thrift/lib/go/thrift.Flusher
Printer : github.com/miekg/dns.Writer
Printer : github.com/quic-go/quic-go/quicvarint.Writer
Printer : gorm.io/gorm/clause.Writer
Printer : internal/bisect.Writer
Printer : io.ByteWriter
Printer : io.StringWriter
Printer : io.Writer
func NewPrinter(opts ...PrinterOption) *Printer
PrinterOption is a function which can be passed to NewPrinter
to alter its behavior. To apply option to existing Printer
call it directly, for example KeepPadding(true)(printer).
func BinaryNextLine(enabled bool) PrinterOption
func FunctionNextLine(enabled bool) PrinterOption
func Indent(spaces uint) PrinterOption
func KeepPadding(enabled bool) PrinterOption
func Minify(enabled bool) PrinterOption
func SingleLine(enabled bool) PrinterOption
func SpaceRedirects(enabled bool) PrinterOption
func SwitchCaseIndent(enabled bool) PrinterOption
func NewPrinter(opts ...PrinterOption) *Printer
( ProcOperator) String() string
ProcOperator : expvar.Var
ProcOperator : fmt.Stringer
const CmdIn
const CmdOut
ProcSubst represents a Bash process substitution.
This node will only appear with LangBash.
Last []Comment
Op ProcOperator
OpPos Pos
Rparen Pos
Stmts []*Stmt
(*ProcSubst) End() Pos
(*ProcSubst) Pos() Pos
*ProcSubst : Node
*ProcSubst : WordPart
Redirect represents an input/output redirection.
// here-document body
// fd>, or {varname}> in Bash
Op RedirOperator
OpPos Pos
// >word
(*Redirect) End() Pos
(*Redirect) Pos() Pos
*Redirect : Node
( RedirOperator) String() string
RedirOperator : expvar.Var
RedirOperator : fmt.Stringer
const AppAll
const AppOut
const ClbOut
const DashHdoc
const DplIn
const DplOut
const Hdoc
const RdrAll
const RdrIn
const RdrInOut
const RdrOut
const WordHdoc
Replace represents a search and replace expression inside a ParamExp.
All bool
Orig *Word
With *Word
SglQuoted represents a string within single quotes.
// $''
Left Pos
Right Pos
Value string
(*SglQuoted) End() Pos
(*SglQuoted) Pos() Pos
*SglQuoted : Node
*SglQuoted : WordPart
Slice represents a character slicing expression inside a ParamExp.
This node will only appear in LangBash and LangMirBSDKorn.
Length ArithmExpr
Offset ArithmExpr
Stmt represents a statement, also known as a "complete command". It is
compromised of a command and other components that may come before or after
it.
// stmt &
Cmd Command
Comments []Comment
// mksh's |&
// ! stmt
Position Pos
// stmt >a <b
// position of ';', '&', or '|&', if any
(*Stmt) End() Pos
(*Stmt) Pos() Pos
*Stmt : Node
Subshell represents a series of commands that should be executed in a nested
shell environment.
Last []Comment
Lparen Pos
Rparen Pos
Stmts []*Stmt
(*Subshell) End() Pos
(*Subshell) Pos() Pos
*Subshell : Command
*Subshell : Node
TestClause represents a Bash extended test clause.
This node will only appear in LangBash and LangMirBSDKorn.
Left Pos
Right Pos
X TestExpr
(*TestClause) End() Pos
(*TestClause) Pos() Pos
*TestClause : Command
*TestClause : Node
TestDecl represents the declaration of a Bats test function.
Body *Stmt
Description *Word
Position Pos
(*TestDecl) End() Pos
(*TestDecl) Pos() Pos
*TestDecl : Command
*TestDecl : Node
TestExpr represents all nodes that form test expressions.
These are *BinaryTest, *UnaryTest, *ParenTest, and *Word.
End returns the position of the character immediately after the node.
If the character is a newline, the line number won't cross into the
next line. Comments are ignored, except if the node is a *File.
Pos returns the position of the first character of the node. Comments
are ignored, except if the node is a *File.
*BinaryTest
*ParenTest
*UnaryTest
*Word
TestExpr : Node
TimeClause represents a Bash time clause. PosixFormat corresponds to the -p
flag.
This node will only appear in LangBash and LangMirBSDKorn.
PosixFormat bool
Stmt *Stmt
Time Pos
(*TimeClause) End() Pos
(*TimeClause) Pos() Pos
*TimeClause : Command
*TimeClause : Node
( UnAritOperator) String() string
UnAritOperator : expvar.Var
UnAritOperator : fmt.Stringer
const BitNegation
const Dec
const Inc
const Minus
const Not
const Plus
UnaryArithm represents an unary arithmetic expression. The unary operator
may come before or after the sub-expression.
If Op is Inc or Dec, X will be a word with a single *Lit whose value is a
valid name.
Op UnAritOperator
OpPos Pos
Post bool
X ArithmExpr
(*UnaryArithm) End() Pos
(*UnaryArithm) Pos() Pos
*UnaryArithm : ArithmExpr
*UnaryArithm : Node
UnaryTest represents a unary test expression. The unary operator may come
before or after the sub-expression.
Op UnTestOperator
OpPos Pos
X TestExpr
(*UnaryTest) End() Pos
(*UnaryTest) Pos() Pos
*UnaryTest : Node
*UnaryTest : TestExpr
( UnTestOperator) String() string
UnTestOperator : expvar.Var
UnTestOperator : fmt.Stringer
const TsBlckSp
const TsCharSp
const TsDirect
const TsEmpStr
const TsExec
const TsExists
const TsFdTerm
const TsGIDSet
const TsGrpOwn
const TsModif
const TsNempStr
const TsNmPipe
const TsNoEmpty
const TsNot
const TsOptSet
const TsRead
const TsRefVar
const TsRegFile
const TsSmbLink
const TsSocket
const TsSticky
const TsUIDSet
const TsUsrOwn
const TsVarSet
const TsWrite
WhileClause represents a while or an until clause.
Cond []*Stmt
CondLast []Comment
Do []*Stmt
DoLast []Comment
DoPos Pos
DonePos Pos
Until bool
WhilePos Pos
(*WhileClause) End() Pos
(*WhileClause) Pos() Pos
*WhileClause : Command
*WhileClause : Node
Word represents a shell word, containing one or more word parts contiguous to
each other. The word is delimited by word boundaries, such as spaces,
newlines, semicolons, or parentheses.
Parts []WordPart
(*Word) End() Pos
Lit returns the word as a literal value, if the word consists of *Lit nodes
only. An empty string is returned otherwise. Words with multiple literals,
which can appear in some edge cases, are handled properly.
For example, the word "foo" will return "foo", but the word "foo${bar}" will
return "".
(*Word) Pos() Pos
*Word : ArithmExpr
*Word : Node
*Word : TestExpr
func (*Parser).Document(r io.Reader) (*Word, error)
func SplitBraces(word *Word) bool
WordIter represents the iteration of a variable over a series of words in a
for clause. If InPos is an invalid position, the "in" token was missing, so
the iteration is over the shell's positional parameters.
// position of "in"
Items []*Word
Name *Lit
(*WordIter) End() Pos
(*WordIter) Pos() Pos
*WordIter : Loop
*WordIter : Node
WordPart represents all nodes that can form part of a word.
These are *Lit, *SglQuoted, *DblQuoted, *ParamExp, *CmdSubst, *ArithmExp,
*ProcSubst, and *ExtGlob.
End returns the position of the character immediately after the node.
If the character is a newline, the line number won't cross into the
next line. Comments are ignored, except if the node is a *File.
Pos returns the position of the first character of the node. Comments
are ignored, except if the node is a *File.
*ArithmExp
*BraceExp
*CmdSubst
*DblQuoted
*ExtGlob
*Lit
*ParamExp
*ProcSubst
*SglQuoted
WordPart : Node
Package-Level Functions (total 22)
BinaryNextLine will make binary operators appear on the next line
when a binary command, such as a pipe, spans multiple lines. A
backslash will be used.
DebugPrint prints the provided syntax tree, spanning multiple lines and with
indentation. Can be useful to investigate the content of a syntax tree.
FunctionNextLine will place a function's opening braces on the next line.
Indent sets the number of spaces used for indentation. If set to 0,
tabs will be used instead.
IsIncomplete reports whether a Parser error could have been avoided with
extra input bytes. For example, if an [io.EOF] was encountered while there was
an unclosed quote or parenthesis.
IsKeyword returns true if the given word is part of the language keywords.
KeepComments makes the parser parse comments and attach them to
nodes, as opposed to discarding them.
KeepPadding will keep most nodes and tokens in the same column that
they were in the original source. This allows the user to decide how
to align and pad their code with spaces.
Note that this feature is best-effort and will only keep the
alignment stable, so it may need some human help the first time it is
run.
Minify will print programs in a way to save the most bytes possible.
For example, indentation and comments are skipped, and extra
whitespace is avoided when possible.
NewParser allocates a new Parser and applies any number of options.
NewPos creates a position with the given offset, line, and column.
Note that Pos uses a limited number of bits to store these numbers.
If line or column overflow their allocated space, they are replaced with 0.
NewPrinter allocates a new Printer and applies any number of options.
Quote returns a quoted version of the input string,
so that the quoted version is expanded or interpreted
as the original string in the given language variant.
Quoting is necessary when using arbitrary literal strings
as words in a shell script or command.
Without quoting, one can run into syntax errors,
as well as the possibility of running unintended code.
An error is returned when a string cannot be quoted for a variant.
For instance, POSIX lacks escape sequences for non-printable characters,
and no language variant can represent a string containing null bytes.
In such cases, the returned error type will be *QuoteError.
The quoting strategy is chosen on a best-effort basis,
to minimize the amount of extra bytes necessary.
Some strings do not require any quoting and are returned unchanged.
Those strings can be directly surrounded in single quotes as well.
Simplify modifies a node to remove redundant pieces of syntax, and returns
whether any changes were made.
The changes currently applied are:
Remove clearly useless parentheses $(( (expr) ))
Remove dollars from vars in exprs (($var))
Remove duplicate subshells $( (stmts) )
Remove redundant quotes [[ "$var" == str ]]
Merge negations with unary operators [[ ! -n $var ]]
Use single quotes to shorten literals "\$foo"
SingleLine will attempt to print programs in one line. For example, lists of
commands or nested blocks do not use newlines in this mode. Note that some
newlines must still appear, such as those following comments or around
here-documents.
Print's trailing newline when given a *File is not affected by this option.
SpaceRedirects will put a space after most redirection operators. The
exceptions are '>&', '<&', '>(', and '<('.
SplitBraces parses brace expansions within a word's literal parts. If any
valid brace expansions are found, they are replaced with BraceExp nodes, and
the function returns true. Otherwise, the word is left untouched and the
function returns false.
For example, a literal word "foo{bar,baz}" will result in a word containing
the literal "foo", and a brace expansion with the elements "bar" and "baz".
It does not return an error; malformed brace expansions are simply skipped.
For example, the literal word "a{b" is left unchanged.
StopAt configures the lexer to stop at an arbitrary word, treating it
as if it were the end of the input. It can contain any characters
except whitespace, and cannot be over four bytes in size.
This can be useful to embed shell code within another language, as
one can use a special word to mark the delimiters between the two.
As a word, it will only apply when following whitespace or a
separating token. For example, StopAt("$$") will act on the inputs
"foo $$" and "foo;$$", but not on "foo '$$'".
The match is done by prefix, so the example above will also act on
"foo $$bar".
SwitchCaseIndent will make switch cases be indented. As such, switch
case bodies will be two levels deeper than the switch itself.
ValidName returns whether val is a valid name as per the POSIX spec.
Variant changes the shell language variant that the parser will
accept.
The passed language variant must be one of the constant values defined in
this package.
Walk traverses a syntax tree in depth-first order: It starts by calling
f(node); node must not be nil. If f returns true, Walk invokes f
recursively for each of the non-nil children of node, followed by
f(nil).
Package-Level Constants (total 132)
const Add BinAritOperator = 68 // + const AddAssgn BinAritOperator = 44 // += const AlternateUnset ParExpOperator = 68 // + const AlternateUnsetOrNull ParExpOperator = 69 // :+ const And BinAritOperator = 9 // & const AndArit BinAritOperator = 10 // && const AndAssgn BinAritOperator = 49 // &= const AndStmt BinCmdOperator = 10 // && const AndTest BinTestOperator = 10 // && const AppAll RedirOperator = 65 // &>> const AppOut RedirOperator = 55 // >> const Assgn BinAritOperator = 74 // = const AssignUnset ParExpOperator = 74 // = const AssignUnsetOrNull ParExpOperator = 75 // := const BitNegation UnAritOperator = 35 // ~ const Break CaseOperator = 30 // ;; const ClbOut RedirOperator = 60 // >| const CmdIn ProcOperator = 66 // <( const CmdOut ProcOperator = 67 // >( const Comma BinAritOperator = 82 // , const DashHdoc RedirOperator = 62 // <<- const Dec UnAritOperator = 37 // -- const DefaultUnset ParExpOperator = 70 // - const DefaultUnsetOrNull ParExpOperator = 71 // :- const DplIn RedirOperator = 58 // <& const DplOut RedirOperator = 59 // >& const Eql BinAritOperator = 40 // == const ErrorUnset ParExpOperator = 72 // ? const ErrorUnsetOrNull ParExpOperator = 73 // :? const Fallthrough CaseOperator = 31 // ;& const Geq BinAritOperator = 43 // >= const GlobExcept GlobOperator = 126 // !( const GlobOne GlobOperator = 125 // @( const GlobOneOrMore GlobOperator = 124 // +( const GlobZeroOrMore GlobOperator = 123 // *( const GlobZeroOrOne GlobOperator = 122 // ?( const Gtr BinAritOperator = 54 // > const Hdoc RedirOperator = 61 // << const Inc UnAritOperator = 36 // ++
LangAuto corresponds to automatic language detection,
commonly used by end-user applications like shfmt,
which can guess a file's language variant given its filename or shebang.
At this time, the Parser does not support LangAuto.
LangBash corresponds to the GNU Bash language, as described in its
manual at https://www.gnu.org/software/bash/manual/bash.html.
We currently follow Bash version 5.1.
Its string representation is "bash".
LangBats corresponds to the Bash Automated Testing System language,
as described at https://github.com/bats-core/bats-core. Note that
it's just a small extension of the Bash language.
Its string representation is "bats".
LangMirBSDKorn corresponds to the MirBSD Korn Shell, also known as
mksh, as described at http://www.mirbsd.org/htman/i386/man1/mksh.htm.
Note that it shares some features with Bash, due to the the shared
ancestry that is ksh.
We currently follow mksh version 59.
Its string representation is "mksh".
LangPOSIX corresponds to the POSIX Shell language, as described at
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html.
Its string representation is "posix" or "sh".
const Leq BinAritOperator = 42 // <= const LowerAll ParExpOperator = 83 // ,, const LowerFirst ParExpOperator = 82 // , const Lss BinAritOperator = 56 // < const Minus UnAritOperator = 70 // - const Mul BinAritOperator = 38 // * const MulAssgn BinAritOperator = 46 // *= const NamesPrefix ParNamesOperator = 38 // * const NamesPrefixWords ParNamesOperator = 84 // @ const Neq BinAritOperator = 41 // != const Not UnAritOperator = 34 // ! const Or BinAritOperator = 12 // | const OrArit BinAritOperator = 11 // || const OrAssgn BinAritOperator = 50 // |= const OrStmt BinCmdOperator = 11 // || const OrTest BinTestOperator = 11 // || const OtherParamOps ParExpOperator = 84 // @ const Pipe BinCmdOperator = 12 // | const PipeAll BinCmdOperator = 13 // |& const Plus UnAritOperator = 68 // + const Pow BinAritOperator = 39 // ** const Quo BinAritOperator = 85 // / const QuoAssgn BinAritOperator = 47 // /= const RdrAll RedirOperator = 64 // &> const RdrIn RedirOperator = 56 // < const RdrInOut RedirOperator = 57 // <> const RdrOut RedirOperator = 54 // > const Rem BinAritOperator = 76 // % const RemAssgn BinAritOperator = 48 // %= const RemLargePrefix ParExpOperator = 79 // ## const RemLargeSuffix ParExpOperator = 77 // %% const RemSmallPrefix ParExpOperator = 78 // # const RemSmallSuffix ParExpOperator = 76 // % const Resume CaseOperator = 32 // ;;& const ResumeKorn CaseOperator = 33 // ;| const Shl BinAritOperator = 61 // << const ShlAssgn BinAritOperator = 52 // <<= const Shr BinAritOperator = 55 // >> const ShrAssgn BinAritOperator = 53 // >>= const Sub BinAritOperator = 70 // - const SubAssgn BinAritOperator = 45 // -= const TernColon BinAritOperator = 87 // : const TernQuest BinAritOperator = 72 // ? const TsAfter BinTestOperator = 54 // > const TsBefore BinTestOperator = 56 // < const TsBlckSp UnTestOperator = 92 // -b const TsCharSp UnTestOperator = 91 // -c const TsDevIno BinTestOperator = 115 // -ef const TsDirect UnTestOperator = 90 // -d const TsEmpStr UnTestOperator = 107 // -z const TsEql BinTestOperator = 116 // -eq const TsExec UnTestOperator = 104 // -x const TsExists UnTestOperator = 88 // -e const TsFdTerm UnTestOperator = 106 // -t const TsGeq BinTestOperator = 119 // -ge const TsGIDSet UnTestOperator = 97 // -g const TsGrpOwn UnTestOperator = 99 // -G const TsGtr BinTestOperator = 121 // -gt const TsLeq BinTestOperator = 118 // -le const TsLss BinTestOperator = 120 // -lt const TsMatch BinTestOperator = 40 // == const TsMatchShort BinTestOperator = 74 // = const TsModif UnTestOperator = 101 // -N const TsNempStr UnTestOperator = 108 // -n const TsNeq BinTestOperator = 117 // -ne const TsNewer BinTestOperator = 113 // -nt const TsNmPipe UnTestOperator = 93 // -p const TsNoEmpty UnTestOperator = 105 // -s const TsNoMatch BinTestOperator = 41 // != const TsNot UnTestOperator = 34 // ! const TsOlder BinTestOperator = 114 // -ot const TsOptSet UnTestOperator = 109 // -o const TsRead UnTestOperator = 102 // -r const TsRefVar UnTestOperator = 111 // -R const TsRegFile UnTestOperator = 89 // -f const TsReMatch BinTestOperator = 112 // =~ const TsSmbLink UnTestOperator = 95 // -L const TsSocket UnTestOperator = 94 // -S const TsSticky UnTestOperator = 96 // -k const TsUIDSet UnTestOperator = 98 // -u const TsUsrOwn UnTestOperator = 100 // -O const TsVarSet UnTestOperator = 110 // -v const TsWrite UnTestOperator = 103 // -w const UpperAll ParExpOperator = 81 // ^^ const UpperFirst ParExpOperator = 80 // ^ const WordHdoc RedirOperator = 63 // <<< const Xor BinAritOperator = 80 // ^ const XorAssgn BinAritOperator = 51 // ^=![]() |
The pages are generated with Golds v0.8.2. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |