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)
/* sort by: | */
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
ByteOffset int Message string ( QuoteError) Error() string QuoteError : error
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 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 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 DplIn RedirOperator = 58 // <&
const DplOut RedirOperator = 59 // >&
const Eql BinAritOperator = 40 // ==
const ErrorUnset ParExpOperator = 72 // ?
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 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 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 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 // ^=