Documentation
¶
Overview ¶
Package syntax implements parsing and formatting of shell programs. It supports POSIX Shell, Bash, and mksh.
Example ¶
package main
import (
"os"
"strings"
"github.com/ewhauser/gbash/internal/shell/syntax"
)
func main() {
r := strings.NewReader("{ foo; bar; }")
f, err := syntax.NewParser().Parse(r, "")
if err != nil {
return
}
syntax.NewPrinter().Print(os.Stdout, f)
}
Output: { foo bar }
Index ¶
- Constants
- func ArithmExprString(expr ArithmExpr) string
- func DebugPrint(w io.Writer, node Node) error
- func IsIncomplete(err error) bool
- func IsKeyword(word string) bool
- func Quote(s string, lang LangVariant) (string, error)
- func Simplify(n Node) bool
- func ValidName(val string) bool
- func Walk(node Node, f func(Node) bool)
- type AliasExpansion
- type AliasResolver
- type AliasSpec
- type ArithmCmd
- type ArithmExp
- type ArithmExpr
- type ArrayElem
- type ArrayElemKind
- type ArrayExpr
- type ArrayExprMode
- type Assign
- type BinAritOperator
- type BinCmdOperator
- type BinTestOperator
- type BinaryArithm
- type BinaryCmd
- type BinaryTest
- type Block
- type BraceExp
- type CStyleLoop
- type CallExpr
- type CaseClause
- type CaseItem
- type CaseOperator
- type CmdSubst
- type Command
- type Comment
- type CondBinary
- type CondExpr
- type CondParen
- type CondPattern
- type CondRegex
- type CondUnary
- type CondVarRef
- type CondWord
- type CoprocClause
- type DblQuoted
- type DeclAssign
- type DeclClause
- type DeclDynamicWord
- type DeclFlag
- type DeclName
- type DeclOperand
- type Expansion
- type ExtGlob
- type File
- type FlagsArithm
- type ForClause
- type FuncDecl
- type GlobOperator
- type HeredocDelim
- type IfClause
- type LangError
- type LangVariant
- type LetClause
- type Lit
- type Loop
- type Node
- type ParExpOperator
- type ParNamesOperator
- type ParamExp
- type ParenArithm
- type ParenTest
- type ParseError
- type Parser
- func (p *Parser) Arithmetic(r io.Reader) (ArithmExpr, error)
- func (p *Parser) DeclOperand(r io.Reader) (DeclOperand, error)
- func (p *Parser) DeclOperandField(r io.Reader) (DeclOperand, error)
- func (p *Parser) Document(r io.Reader) (*Word, error)
- func (p *Parser) Incomplete() bool
- func (p *Parser) Interactive(r io.Reader, fn func([]*Stmt) bool) errordeprecated
- func (p *Parser) InteractiveSeq(r io.Reader) iter.Seq2[[]*Stmt, error]
- func (p *Parser) Parse(r io.Reader, name string) (*File, error)
- func (p *Parser) Stmts(r io.Reader, fn func(*Stmt) bool) errordeprecated
- func (p *Parser) StmtsSeq(r io.Reader) iter.Seq2[*Stmt, error]
- func (p *Parser) VarRef(r io.Reader) (*VarRef, error)
- func (p *Parser) Words(r io.Reader, fn func(*Word) bool) errordeprecated
- func (p *Parser) WordsSeq(r io.Reader) iter.Seq2[*Word, error]
- type ParserOption
- func ExpandAliases(resolver AliasResolver) ParserOption
- func KeepComments(enabled bool) ParserOption
- func LegacyBashCompat(enabled bool) ParserOption
- func ParseExtGlob(enabled bool) ParserOption
- func RecoverErrors(maximum int) ParserOption
- func StopAt(word string) ParserOption
- func Variant(l LangVariant) ParserOption
- type Pattern
- type PatternAny
- type PatternCharClass
- type PatternPart
- type PatternSingle
- type Pos
- type Printer
- type PrinterOption
- func BinaryNextLine(enabled bool) PrinterOption
- func FunctionNextLine(enabled bool) PrinterOption
- func Indent(spaces uint) PrinterOption
- func KeepPadding(enabled bool) PrinterOptiondeprecated
- func Minify(enabled bool) PrinterOption
- func SingleLine(enabled bool) PrinterOption
- func SpaceRedirects(enabled bool) PrinterOption
- func SwitchCaseIndent(enabled bool) PrinterOption
- type ProcOperator
- type ProcSubst
- type QuoteError
- type RedirOperator
- type Redirect
- type Replace
- type ReplaceAnchor
- type SglQuoted
- type Slice
- type Stmt
- type Subscript
- type SubscriptKind
- type SubscriptMode
- type Subshell
- type TestClause
- type TestDecl
- type TestExpr
- type TimeClause
- type UnAritOperator
- type UnTestOperator
- type UnaryArithm
- type UnaryTest
- type VarRef
- type VarRefContext
- type WhileClause
- type Word
- type WordIter
- type WordPart
Examples ¶
Constants ¶
const ( RdrOut = RedirOperator(rdrOut) + iota // > AppOut // >> RdrIn // < RdrInOut // <> DplIn // <& DplOut // >& RdrClob // >| AppClob // >>| with [LangZsh] Hdoc // << DashHdoc // <<- WordHdoc // <<< RdrAll // &> RdrAllClob // &>| with [LangZsh] AppAll // &>> AppAllClob // &>>| with [LangZsh] // Deprecated: use [RdrClob] // //go:fix inline ClbOut = RdrClob )
const ( CmdIn = ProcOperator(cmdIn) + iota // <( CmdInTemp // =( CmdOut // >( )
const ( GlobZeroOrOne = GlobOperator(globQuest) + iota // ?( GlobZeroOrMore // *( GlobOneOrMore // +( GlobOne // @( GlobExcept // !( )
const ( AndStmt = BinCmdOperator(andAnd) + iota // && OrStmt // || Pipe // | PipeAll // |& )
const ( Break = CaseOperator(dblSemicolon) + iota // ;; Fallthrough // ;& Resume // ;;& ResumeKorn // ;| )
const ( NamesPrefix = ParNamesOperator(star) // * NamesPrefixWords = ParNamesOperator(at) // @ )
const ( AlternateUnset = ParExpOperator(plus) + iota // + AlternateUnsetOrNull // :+ DefaultUnset // - DefaultUnsetOrNull // :- ErrorUnset // ? ErrorUnsetOrNull // :? AssignUnset // = AssignUnsetOrNull // := RemSmallSuffix // % RemLargeSuffix // %% RemSmallPrefix // # RemLargePrefix // ## MatchEmpty // :# with [LangZsh] ArrayExclude // :| with [LangZsh] ArrayIntersect // :* with [LangZsh] UpperFirst // ^ UpperAll // ^^ LowerFirst // , LowerAll // ,, OtherParamOps // @ )
const ( Not = UnAritOperator(exclMark) + iota // ! BitNegation // ~ Inc // ++ Dec // -- Plus = UnAritOperator(plus) // + Minus = UnAritOperator(minus) // - )
const ( Add = BinAritOperator(plus) // + Sub = BinAritOperator(minus) // - Mul = BinAritOperator(star) // * Quo = BinAritOperator(slash) // / Rem = BinAritOperator(perc) // % Pow = BinAritOperator(power) // ** Eql = BinAritOperator(equal) // == Gtr = BinAritOperator(rdrOut) // > Lss = BinAritOperator(rdrIn) // < Neq = BinAritOperator(nequal) // != Leq = BinAritOperator(lequal) // <= Geq = BinAritOperator(gequal) // >= And = BinAritOperator(and) // & Or = BinAritOperator(or) // | Xor = BinAritOperator(caret) // ^ Shr = BinAritOperator(appOut) // >> Shl = BinAritOperator(hdoc) // << AndArit = BinAritOperator(andAnd) // && OrArit = BinAritOperator(orOr) // || XorBool = BinAritOperator(dblCaret) // ^^ Comma = BinAritOperator(comma) // , TernQuest = BinAritOperator(quest) // ? TernColon = BinAritOperator(colon) // : Assgn = BinAritOperator(assgn) // = AddAssgn = BinAritOperator(addAssgn) // += SubAssgn = BinAritOperator(subAssgn) // -= MulAssgn = BinAritOperator(mulAssgn) // *= QuoAssgn = BinAritOperator(quoAssgn) // /= RemAssgn = BinAritOperator(remAssgn) // %= AndAssgn = BinAritOperator(andAssgn) // &= OrAssgn = BinAritOperator(orAssgn) // |= XorAssgn = BinAritOperator(xorAssgn) // ^= ShlAssgn = BinAritOperator(shlAssgn) // <<= ShrAssgn = BinAritOperator(shrAssgn) // >>= AndBoolAssgn = BinAritOperator(andBoolAssgn) // &&= OrBoolAssgn = BinAritOperator(orBoolAssgn) // ||= XorBoolAssgn = BinAritOperator(xorBoolAssgn) // ^^= PowAssgn = BinAritOperator(powAssgn) // **= )
const ( TsExists = UnTestOperator(tsExists) + iota // -e TsRegFile // -f TsDirect // -d TsCharSp // -c TsBlckSp // -b TsNmPipe // -p TsSocket // -S TsSmbLink // -L TsSticky // -k TsGIDSet // -g TsUIDSet // -u TsGrpOwn // -G TsUsrOwn // -O TsModif // -N TsRead // -r TsWrite // -w TsExec // -x TsNoEmpty // -s TsFdTerm // -t TsEmpStr // -z TsNempStr // -n TsOptSet // -o TsVarSet // -v TsRefVar // -R TsNot = UnTestOperator(exclMark) // ! TsParen = UnTestOperator(leftParen) // ( )
const ( TsReMatch = BinTestOperator(tsReMatch) + iota // =~ TsNewer // -nt TsOlder // -ot TsDevIno // -ef TsEql // -eq TsNeq // -ne TsLeq // -le TsGeq // -ge TsLss // -lt TsGtr // -gt AndTest = BinTestOperator(andAnd) // && OrTest = BinTestOperator(orOr) // || TsMatchShort = BinTestOperator(assgn) // = TsMatch = BinTestOperator(equal) // == TsNoMatch = BinTestOperator(nequal) // != TsBefore = BinTestOperator(rdrIn) // < TsAfter = BinTestOperator(rdrOut) // > )
Variables ¶
This section is empty.
Functions ¶
func ArithmExprString ¶
func ArithmExprString(expr ArithmExpr) string
ArithmExprString returns the compact shell source form of an arithmetic expression.
func DebugPrint ¶
DebugPrint prints the provided syntax tree, spanning multiple lines and with indentation. Can be useful to investigate the content of a syntax tree.
Example ¶
package main
import (
"os"
"strings"
"github.com/ewhauser/gbash/internal/shell/syntax"
)
func main() {
in := strings.NewReader(`echo 'foo'`)
f, err := syntax.NewParser().Parse(in, "")
if err != nil {
return
}
syntax.DebugPrint(os.Stdout, f)
}
Output: *syntax.File { . Name: "" . Stmts: []*syntax.Stmt (len = 1) { . . 0: *syntax.Stmt { . . . Comments: []syntax.Comment (len = 0) {} . . . Cmd: *syntax.CallExpr { . . . . Assigns: []*syntax.Assign (len = 0) {} . . . . Args: []*syntax.Word (len = 2) { . . . . . 0: *syntax.Word { . . . . . . Parts: []syntax.WordPart (len = 1) { . . . . . . . 0: *syntax.Lit { . . . . . . . . ValuePos: 1:1 . . . . . . . . ValueEnd: 1:5 . . . . . . . . Value: "echo" . . . . . . . } . . . . . . } . . . . . . AliasExpansions: []*syntax.AliasExpansion (len = 0) {} . . . . . } . . . . . 1: *syntax.Word { . . . . . . Parts: []syntax.WordPart (len = 1) { . . . . . . . 0: *syntax.SglQuoted { . . . . . . . . Left: 1:6 . . . . . . . . Right: 1:10 . . . . . . . . Dollar: false . . . . . . . . Value: "foo" . . . . . . . } . . . . . . } . . . . . . AliasExpansions: []*syntax.AliasExpansion (len = 0) {} . . . . . } . . . . } . . . } . . . Position: 1:1 . . . Semicolon: 0:0 . . . Negated: false . . . Background: false . . . Coprocess: false . . . Disown: false . . . Redirs: []*syntax.Redirect (len = 0) {} . . } . } . Last: []syntax.Comment (len = 0) {} . AliasExpansions: []*syntax.AliasExpansion (len = 0) {} }
func IsIncomplete ¶
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.
func IsKeyword ¶
IsKeyword returns true if the given word is a language keyword in POSIX Shell or Bash.
func Quote ¶
func Quote(s string, lang LangVariant) (string, error)
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.
Example ¶
package main
import (
"fmt"
"github.com/ewhauser/gbash/internal/shell/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)
}
}
}
Output: Quote( "foo"): foo Quote( "bar $baz"): 'bar $baz' Quote( "\"won't\""): "\"won't\"" Quote( "~/home"): '~/home' Quote( "#1304"): '#1304' Quote( "name=value"): 'name=value' Quote( "for"): 'for' Quote( "glob-*"): 'glob-*' Quote( "invalid-\xe2'"): $'invalid-\xe2\'' Quote("nonprint-\v\x1b"): $'nonprint-\v\x1b'
func Simplify ¶
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"
func Walk ¶
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).
Example ¶
package main
import (
"os"
"strings"
"github.com/ewhauser/gbash/internal/shell/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 node := node.(type) {
case *syntax.ParamExp:
node.Param.Value = strings.ToUpper(node.Param.Value)
}
return true
})
syntax.NewPrinter().Print(os.Stdout, f)
}
Output: echo $FOO "and $BAR"
Types ¶
type AliasExpansion ¶
AliasExpansion records one alias expansion applied while parsing.
type AliasResolver ¶
AliasResolver returns a raw alias replacement for an unquoted command word.
type AliasSpec ¶
type AliasSpec struct {
Value string
}
AliasSpec describes a shell alias value as raw shell source.
Value should preserve the exact alias replacement text, including any trailing blanks or newlines.
func (AliasSpec) EndsWithBlank ¶
EndsWithBlank reports whether the alias replacement should keep alias expansion enabled for the next shell word.
type ArithmCmd ¶
type ArithmCmd struct {
Left, Right Pos
Unsigned bool // mksh's ((# expr))
Source string
X ArithmExpr
}
ArithmCmd represents an arithmetic command.
This node will only appear with LangBash and LangMirBSDKorn.
type ArithmExp ¶
type ArithmExp struct {
Left, Right Pos
Bracket bool // deprecated $[expr] form
Unsigned bool // mksh's $((# expr))
Source string
X ArithmExpr
}
ArithmExp represents an arithmetic expansion.
type ArithmExpr ¶
type ArithmExpr interface {
Node
// contains filtered or unexported methods
}
ArithmExpr represents all nodes that form arithmetic expressions.
These are *BinaryArithm, *UnaryArithm, *ParenArithm, *FlagsArithm, and *Word.
type ArrayElem ¶
type ArrayElem struct {
Kind ArrayElemKind
Index *Subscript
Value *Word
Comments []Comment
}
ArrayElem represents a Bash array element.
Sequential elements have Kind ArrayElemSequential and a nil Index, for example `declare -a x=(value)`.
Keyed elements have a non-nil Index with Kind ArrayElemKeyed or ArrayElemKeyedAppend, for example `declare -A x=([index]=value)` or `declare -A x=([index]+=value)`.
Value can be nil for empty assignments such as `declare -A x=([index]=)` or `declare -A x=([index]+=)`.
type ArrayElemKind ¶
type ArrayElemKind uint8
const ( // ArrayElemSequential appends one or more sequential values without an // explicit [key]= prefix. ArrayElemSequential ArrayElemKind = iota // ArrayElemKeyed assigns a single value to an explicit [key]. ArrayElemKeyed // ArrayElemKeyedAppend appends a single value to an explicit [key]+= target. ArrayElemKeyedAppend )
type ArrayExpr ¶
type ArrayExpr struct {
Lparen, Rparen Pos
Mode ArrayExprMode
Elems []*ArrayElem
Last []Comment
}
ArrayExpr represents a Bash array expression.
This node will only appear with LangBash.
type ArrayExprMode ¶
type ArrayExprMode uint8
const ( // ArrayExprInherit leaves compound-assignment interpretation to the // surrounding context, such as a previous declare flag or existing variable // kind. ArrayExprInherit ArrayExprMode = iota // ArrayExprIndexed marks a compound assignment as an indexed array literal. ArrayExprIndexed // ArrayExprAssociative marks a compound assignment as an associative array // literal. ArrayExprAssociative )
type Assign ¶
type Assign struct {
Append bool // +=
Ref *VarRef
Value *Word // =val
Array *ArrayExpr // =(arr)
// contains filtered or unexported fields
}
Assign represents an assignment to a variable.
If [Assign.Ref]'s Index is non-nil, the value will be a word and not an array, as nested arrays are not allowed.
func (*Assign) LiteralizedValue ¶ added in v0.0.23
type BinAritOperator ¶
type BinAritOperator token
func (BinAritOperator) String ¶
func (o BinAritOperator) String() string
type BinCmdOperator ¶
type BinCmdOperator token
func (BinCmdOperator) String ¶
func (o BinCmdOperator) String() string
type BinTestOperator ¶
type BinTestOperator token
func (BinTestOperator) String ¶
func (o BinTestOperator) String() string
type BinaryArithm ¶
type BinaryArithm struct {
OpPos Pos
Op BinAritOperator
X, Y ArithmExpr
}
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]. TernColon does not appear in any other scenario.
func (*BinaryArithm) End ¶
func (b *BinaryArithm) End() Pos
func (*BinaryArithm) Pos ¶
func (b *BinaryArithm) Pos() Pos
type BinaryCmd ¶
type BinaryCmd struct {
OpPos Pos
Op BinCmdOperator
X, Y *Stmt
}
BinaryCmd represents a binary expression between two statements.
type BinaryTest ¶
type BinaryTest struct {
OpPos Pos
Op BinTestOperator
X, Y TestExpr
}
BinaryTest represents a binary test expression.
func (*BinaryTest) End ¶
func (b *BinaryTest) End() Pos
func (*BinaryTest) Pos ¶
func (b *BinaryTest) Pos() Pos
type Block ¶
Block represents a series of commands that should be executed in a nested scope. It is essentially a list of statements within curly braces.
type BraceExp ¶
type BraceExp struct {
Lbrace, Rbrace Pos
Sequence bool // {x..y[..incr]} instead of {x,y[,...]}
Elems []*Word
}
BraceExp represents a brace expression, such as "{a,f}" or "{1..10}".
This node will only appear with LangBash, LangBats, LangMirBSDKorn, and LangZsh.
type CStyleLoop ¶
type CStyleLoop struct {
Lparen, Rparen Pos
// Init, Cond, Post can each be nil, if the for loop construct omits it.
Init, Cond, Post ArithmExpr
}
CStyleLoop represents the behavior of a for clause similar to the C language.
This node will only appear with LangBash.
func (*CStyleLoop) End ¶
func (c *CStyleLoop) End() Pos
func (*CStyleLoop) Pos ¶
func (c *CStyleLoop) Pos() Pos
type CallExpr ¶
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.
type CaseClause ¶
type CaseClause struct {
Case, In, Esac Pos
Braces bool // deprecated mksh form with braces instead of in/esac
Word *Word
Items []*CaseItem
Last []Comment
}
CaseClause represents a case (switch) clause.
func (*CaseClause) End ¶
func (c *CaseClause) End() Pos
func (*CaseClause) Pos ¶
func (c *CaseClause) Pos() Pos
type CaseItem ¶
type CaseItem struct {
Op CaseOperator
OpPos Pos // unset if it was finished by "esac"
Comments []Comment
Patterns []*Pattern
Stmts []*Stmt
Last []Comment
}
CaseItem represents a pattern list (case) within a CaseClause.
type CaseOperator ¶
type CaseOperator token
func (CaseOperator) String ¶
func (o CaseOperator) String() string
type CmdSubst ¶
type CmdSubst struct {
Left, Right Pos
Stmts []*Stmt
Last []Comment
Backquotes bool // deprecated `foo`
TempFile bool // mksh's ${ foo;}
ReplyVar bool // mksh's ${|foo;}
}
CmdSubst represents a command substitution.
type Command ¶
type Command interface {
Node
// contains filtered or unexported methods
}
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.
Example ¶
package main
import (
"fmt"
"os"
"strings"
"github.com/ewhauser/gbash/internal/shell/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()
}
}
Output: Cmd 0: *syntax.CallExpr - echo foo Cmd 1: *syntax.IfClause - if x; then y; fi Cmd 2: *syntax.BinaryCmd - foo | bar
type CondBinary ¶
type CondBinary struct {
OpPos Pos
Op BinTestOperator
X, Y CondExpr
}
CondBinary represents a binary [[ ... ]] conditional expression.
func (*CondBinary) End ¶
func (b *CondBinary) End() Pos
func (*CondBinary) Pos ¶
func (b *CondBinary) Pos() Pos
type CondExpr ¶
type CondExpr interface {
Node
// contains filtered or unexported methods
}
CondExpr represents all nodes that form [[ ... ]] conditional expressions.
These are *CondBinary, *CondUnary, *CondParen, *CondWord, *CondVarRef, *CondPattern, and *CondRegex.
type CondPattern ¶
type CondPattern struct {
Pattern *Pattern
}
CondPattern wraps a pattern-matching operand for [[ == ]], [[ = ]], and [[ != ]].
func (*CondPattern) End ¶
func (p *CondPattern) End() Pos
func (*CondPattern) Pos ¶
func (p *CondPattern) Pos() Pos
type CondRegex ¶
type CondRegex struct {
Word *Word
}
CondRegex wraps a regular-expression operand for [[ =~ ]].
type CondUnary ¶
type CondUnary struct {
OpPos Pos
Op UnTestOperator
X CondExpr
}
CondUnary represents a unary [[ ... ]] conditional expression.
type CondVarRef ¶
type CondVarRef struct {
Ref *VarRef
}
CondVarRef wraps an exact variable reference operand for [[ -v ... ]] and [[ -R ... ]].
func (*CondVarRef) End ¶
func (r *CondVarRef) End() Pos
func (*CondVarRef) Pos ¶
func (r *CondVarRef) Pos() Pos
type CondWord ¶
type CondWord struct {
Word *Word
}
CondWord wraps a generic [[ ... ]] conditional word operand.
type CoprocClause ¶
CoprocClause represents a Bash coproc clause.
This node will only appear with LangBash.
func (*CoprocClause) End ¶
func (c *CoprocClause) End() Pos
func (*CoprocClause) Pos ¶
func (c *CoprocClause) Pos() Pos
type DeclAssign ¶
type DeclAssign struct {
Assign *Assign
}
DeclAssign is a declaration operand that carries a real assignment.
func (*DeclAssign) End ¶
func (d *DeclAssign) End() Pos
func (*DeclAssign) Pos ¶
func (d *DeclAssign) Pos() Pos
type DeclClause ¶
type DeclClause struct {
// Variant is one of "declare", "local", "export", "readonly",
// "typeset", or "nameref".
Variant *Lit
Operands []DeclOperand
}
DeclClause represents a Bash-style declaration clause.
func (*DeclClause) End ¶
func (d *DeclClause) End() Pos
func (*DeclClause) Pos ¶
func (d *DeclClause) Pos() Pos
type DeclDynamicWord ¶
type DeclDynamicWord struct {
Word *Word
}
DeclDynamicWord is a declaration operand whose runtime expansion can produce flags, names, or assignments.
func (*DeclDynamicWord) End ¶
func (d *DeclDynamicWord) End() Pos
func (*DeclDynamicWord) Pos ¶
func (d *DeclDynamicWord) Pos() Pos
type DeclFlag ¶
type DeclFlag struct {
Word *Word
}
DeclFlag is a literal option word in a declaration builtin, such as "-a" or "+n".
type DeclName ¶
type DeclName struct {
Ref *VarRef
}
DeclName is a bare declaration operand naming a variable or reference without assigning a value.
type DeclOperand ¶
type DeclOperand interface {
Node
// contains filtered or unexported methods
}
DeclOperand represents a typed operand to a Bash-style declaration builtin.
These are *DeclFlag, *DeclName, *DeclAssign, and *DeclDynamicWord.
type Expansion ¶
type Expansion struct {
Op ParExpOperator
Word *Word
Pattern *Pattern
}
Expansion represents string manipulation in a ParamExp other than those covered by Replace.
type ExtGlob ¶
type ExtGlob struct {
OpPos, Rparen Pos
Op GlobOperator
Patterns []*Pattern
}
ExtGlob represents a Bash extended globbing expression.
Whether these nodes are recognized is controlled by the parser's ParseExtGlob option. The gbash interpreter reparses input incrementally so `shopt -s extglob` can affect later chunks in the same script.
This node will only appear with LangBash and LangMirBSDKorn.
type File ¶
type File struct {
Name string
Stmts []*Stmt
Last []Comment
// AliasExpansions records alias substitutions applied while parsing this
// file. Entries are ordered by expansion time and point at the alias
// invocation site, not the alias definition site.
AliasExpansions []*AliasExpansion
}
File represents a shell source file.
type FlagsArithm ¶
type FlagsArithm struct {
Flags *Lit
X ArithmExpr
}
FlagsArithm represents zsh subscript flags attached to an arithmetic expression, such as ${array[(flags)expr]}.
This node will only appear with LangZsh.
func (*FlagsArithm) End ¶
func (z *FlagsArithm) End() Pos
func (*FlagsArithm) Pos ¶
func (z *FlagsArithm) Pos() Pos
type ForClause ¶
type ForClause struct {
ForPos, DoPos, DonePos Pos
Select bool
Braces bool // deprecated form with { } instead of do/done
Loop Loop
Do []*Stmt
DoLast []Comment
}
ForClause represents a for or a select clause. The latter is only present in Bash.
type FuncDecl ¶
type FuncDecl struct {
Position Pos
RsrvWord bool // non-posix "function f" style
Parens bool // with () parentheses, can only be false when RsrvWord==true
// Only one of these is set at a time.
// Neither is set when declaring an anonymous func with [LangZsh].
// TODO(v4): join these, even if it's mildly annoying to non-Zsh users.
Name *Lit
Names []*Lit // When declaring many func names with [LangZsh].
Body *Stmt
}
FuncDecl represents the declaration of a function.
type GlobOperator ¶
type GlobOperator token
func (GlobOperator) String ¶
func (o GlobOperator) String() string
type HeredocDelim ¶
type HeredocDelim struct {
Parts []WordPart
Value string // delimiter text after quote removal
Quoted bool // whether any quoting/escaping was present
BodyExpands bool // whether the heredoc body allows shell expansion
}
HeredocDelim represents a here-document delimiter and the parser metadata derived from it.
func (*HeredocDelim) End ¶
func (d *HeredocDelim) End() Pos
func (*HeredocDelim) Pos ¶
func (d *HeredocDelim) Pos() Pos
type IfClause ¶
type IfClause struct {
Position Pos // position of the starting "if", "elif", or "else" token
ThenPos Pos // position of "then", empty if this is an "else"
FiPos Pos // position of "fi", shared with .Else if non-nil
Cond []*Stmt
CondLast []Comment
Then []*Stmt
ThenLast []Comment
Else *IfClause // if non-nil, an "elif" or an "else"
Last []Comment // comments on the first "elif", "else", or "fi"
}
IfClause represents an if statement.
type LangError ¶
type LangError struct {
Filename string
Pos Pos
// Feature briefly describes which language feature caused the error.
Feature string
// Langs lists some of the language variants which support the feature.
Langs []LangVariant
// LangUsed is the language variant used which led to the error.
LangUsed LangVariant
}
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.
type LangVariant ¶
type LangVariant int
LangVariant describes a shell language variant to use when tokenizing and parsing shell code. The zero value is LangBash.
This type implements flag.Value so that it can be used as a CLI flag.
const ( // 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.2. // // Its string representation is "bash". LangBash LangVariant = 1 << iota // 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". LangPOSIX // 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 shared // ancestry that is ksh. // // We currently follow mksh version 59. // // Its string representation is "mksh". LangMirBSDKorn // 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". LangBats // LangZsh corresponds to the Z shell, as described at https://www.zsh.org/. // // Note that its support in the syntax package is experimental and // incomplete for now. See https://github.com/mvdan/sh/issues/120. // // We currently follow Zsh version 5.9. // // Its string representation is "zsh". LangZsh // 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, [Variant] does not support LangAuto. LangAuto )
func (*LangVariant) Set ¶
func (l *LangVariant) Set(s string) error
func (LangVariant) String ¶
func (l LangVariant) String() string
type LetClause ¶
type LetClause struct {
Let Pos
Exprs []ArithmExpr
}
LetClause represents a Bash let clause.
This node will only appear with LangBash and LangMirBSDKorn.
type Lit ¶
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.
type Loop ¶
type Loop interface {
Node
// contains filtered or unexported methods
}
Loop holds either *WordIter or *CStyleLoop.
type Node ¶
type Node interface {
// Pos returns the position of the first character of the node. Comments
// are ignored, except if the node is a [*File].
Pos() Pos
// 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].
End() Pos
}
Node represents a syntax tree node.
type ParExpOperator ¶
type ParExpOperator token
func (ParExpOperator) String ¶
func (o ParExpOperator) String() string
type ParNamesOperator ¶
type ParNamesOperator token
func (ParNamesOperator) String ¶
func (o ParNamesOperator) String() string
type ParamExp ¶
type ParamExp struct {
Dollar, Rbrace Pos
Short bool // $a instead of ${a}
Flags *Lit // ${(flags)a} with [LangZsh]
// Only one of these is set at a time.
// TODO(v4): perhaps use an Operator token here,
// given how we've grown the number of booleans
// TODO(v4): rename Excl to reflect its purpose
Excl bool // ${!a}
Length bool // ${#a}
Width bool // mksh's ${%a}
IsSet bool // ${+a} with [LangZsh]
// Only one of these is set at a time.
// TODO(v4): consider joining Param and NestedParam into a single field,
// even if that would be mildly annoying to non-Zsh users.
Param *Lit
// A nested parameter expression in the form of [*ParamExp] or [*CmdSubst],
// or either of those in a [*DblQuoted]. Only possible with [LangZsh].
NestedParam WordPart
Index *Subscript // ${a[i]}, ${a["k"]}, ${a[@]}, or a ${a[i,j]} slice with [LangZsh]
// Invalid preserves the original source for expansions that bash accepts
// syntactically but rejects later as a bad substitution.
Invalid string
// Only one of these is set at a time.
// TODO(v4): consider joining these in a single "expansion" field/type,
// because it should be impossible for multiple to be set at once,
// and a flat structure like this takes up more space.
Modifiers []*Lit // ${a:h2} with [LangZsh]
Slice *Slice // ${a:x:y}
Repl *Replace // ${a/x/y}
Names ParNamesOperator // ${!prefix*} or ${!prefix@}
Exp *Expansion // ${a:-b}, ${a#b}, etc
}
ParamExp represents a parameter expansion.
type ParenArithm ¶
type ParenArithm struct {
Lparen, Rparen Pos
X ArithmExpr
}
ParenArithm represents an arithmetic expression within parentheses.
func (*ParenArithm) End ¶
func (p *ParenArithm) End() Pos
func (*ParenArithm) Pos ¶
func (p *ParenArithm) Pos() Pos
type ParseError ¶
type ParseError struct {
Filename string
Pos Pos
Text string
Incomplete bool
// SecondaryText is an optional second diagnostic line that BashError emits
// before the source snippet. Bash uses this for some syntax errors like
// "syntax error near ...".
SecondaryText string
SecondaryPos Pos
// SourceLine is the content of the source line where the error occurred.
// When set, BashError includes it as a second diagnostic line.
SourceLine string
// SourceLinePos optionally overrides the line number used for SourceLine.
SourceLinePos Pos
// contains filtered or unexported fields
}
ParseError represents an error found when parsing a source file, from which the parser cannot recover.
func (ParseError) BashError ¶
func (e ParseError) BashError() string
BashError returns the error message formatted like bash does.
func (ParseError) Error ¶
func (e ParseError) Error() string
func (ParseError) WantsSourceLine ¶ added in v0.0.23
func (e ParseError) WantsSourceLine() bool
type Parser ¶
type Parser struct {
// contains filtered or unexported fields
}
Parser holds the internal state of the parsing mechanism of a program.
func NewParser ¶
func NewParser(options ...ParserOption) *Parser
NewParser allocates a new Parser and applies any number of options.
Example (Options) ¶
package main
import (
"fmt"
"os"
"strings"
"github.com/ewhauser/gbash/internal/shell/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)
}
Output: <nil> 1:5: c-style fors are a bash/zsh feature; tried parsing as posix for ((i = 0; i < 5; i++)); do echo $i >f; done for ((i = 0; i < 5; i++)); do echo $i > f; done
func (*Parser) Arithmetic ¶
func (p *Parser) Arithmetic(r io.Reader) (ArithmExpr, error)
Arithmetic parses a single arithmetic expression. That is, as if the input were within the $(( and )) tokens.
func (*Parser) DeclOperand ¶
func (p *Parser) DeclOperand(r io.Reader) (DeclOperand, error)
DeclOperand parses a single Bash-style declaration operand, such as "-a", "foo", "foo=bar", or `assoc["k"]=value`.
func (*Parser) DeclOperandField ¶
func (p *Parser) DeclOperandField(r io.Reader) (DeclOperand, error)
DeclOperandField parses a runtime-expanded Bash-style declaration operand.
Unlike Parser.DeclOperand, scalar assignment values are kept as literal text after the assignment operator, and array element values are reparsed structurally without re-enabling expansion syntax inside those values.
func (*Parser) Document ¶
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.
func (*Parser) Incomplete ¶
Incomplete reports whether the parser needs more input bytes to finish properly parsing a statement or word.
It is only safe to call while the parser is blocked on a read. For an example use case, see Parser.Interactive.
func (*Parser) Interactive
deprecated
Interactive is a pre-iterators API which now wraps Parser.InteractiveSeq.
Deprecated: use Parser.InteractiveSeq.
func (*Parser) InteractiveSeq ¶
InteractiveSeq 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.
func (*Parser) Parse ¶
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.
func (*Parser) Stmts
deprecated
Stmts is a pre-iterators API which now wraps Parser.StmtsSeq.
Deprecated: use Parser.StmtsSeq.
func (*Parser) VarRef ¶
VarRef parses a single shell variable reference, such as "foo", "a[1]", or `assoc["k"]`.
func (*Parser) Words
deprecated
Words is a pre-iterators API which now wraps Parser.WordsSeq.
Deprecated: use Parser.WordsSeq.
func (*Parser) WordsSeq ¶
WordsSeq reads and parses a sequence of words alongside any error encountered.
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.
type ParserOption ¶
type ParserOption func(*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 ExpandAliases ¶
func ExpandAliases(resolver AliasResolver) ParserOption
ExpandAliases configures parse-time alias expansion for unquoted command words.
func KeepComments ¶
func KeepComments(enabled bool) ParserOption
KeepComments makes the parser parse comments and attach them to nodes, as opposed to discarding them.
func LegacyBashCompat ¶ added in v0.0.22
func LegacyBashCompat(enabled bool) ParserOption
LegacyBashCompat enables parser diagnostics that match the older bash behavior used by the in-shell `bash` builtin conformance path.
func ParseExtGlob ¶ added in v0.0.23
func ParseExtGlob(enabled bool) ParserOption
ParseExtGlob controls whether the parser should recognize Bash extended glob operators like `@(foo)` and `!(bar)` as dedicated syntax nodes.
func RecoverErrors ¶
func RecoverErrors(maximum int) ParserOption
RecoverErrors allows the parser to skip up to a maximum number of errors in the given input on a best-effort basis. This can be useful to tab-complete an interactive shell prompt, or when providing diagnostics on slightly incomplete shell source.
Currently, this only helps with mandatory tokens from the shell grammar which are not present in the input. They result in position fields or nodes whose position report Pos.IsRecovered as true.
For example, given the input
(foo |
the result will contain two recovered positions; first, the pipe requires a statement to follow, and as Stmt.Pos reports, the entire node is recovered. Second, the subshell needs to be closed, so [Subshell.Rparen] is recovered.
func StopAt ¶
func StopAt(word string) ParserOption
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".
func Variant ¶
func Variant(l LangVariant) ParserOption
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.
type Pattern ¶
type Pattern struct {
Start, EndPos Pos
Parts []PatternPart
}
Pattern represents a shell pattern shared by extglobs, case arms, [[ == ]], and parameter pattern operators.
type PatternAny ¶
type PatternAny struct {
Asterisk Pos
}
PatternAny represents an unquoted `*` wildcard in a shell pattern.
func (*PatternAny) End ¶
func (p *PatternAny) End() Pos
func (*PatternAny) Pos ¶
func (p *PatternAny) Pos() Pos
type PatternCharClass ¶
PatternCharClass represents a bracket expression such as `[abc]` or `[[:digit:]]` in a shell pattern.
func (*PatternCharClass) End ¶
func (p *PatternCharClass) End() Pos
func (*PatternCharClass) Pos ¶
func (p *PatternCharClass) Pos() Pos
type PatternPart ¶
type PatternPart interface {
Node
// contains filtered or unexported methods
}
PatternPart represents all nodes that can form part of a shell pattern.
These are *Lit, *SglQuoted, *DblQuoted, *ParamExp, *CmdSubst, *ArithmExp, *ProcSubst, *PatternAny, *PatternSingle, *PatternCharClass, and *ExtGlob.
type PatternSingle ¶
type PatternSingle struct {
Question Pos
}
PatternSingle represents an unquoted `?` wildcard in a shell pattern.
func (*PatternSingle) End ¶
func (p *PatternSingle) End() Pos
func (*PatternSingle) Pos ¶
func (p *PatternSingle) Pos() Pos
type Pos ¶
type Pos struct {
// contains filtered or unexported fields
}
Pos is a position within a shell source file.
func NewPos ¶
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.
func (Pos) After ¶
After reports whether the position p is after p2. It is a more expressive version of p.Offset() > p2.Offset(). It always returns false if p is an invalid position.
func (Pos) Col ¶
Col returns the column number of the position, starting at 1. It counts in bytes. Invalid positions always report the column number 0.
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.
func (Pos) IsRecovered ¶
IsRecovered reports whether the position that the token or node belongs to was missing in the original input and recovered via RecoverErrors.
func (Pos) IsValid ¶
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 ';'.
Recovered positions, as reported by Pos.IsRecovered, are not considered valid given that they don't contain position information.
func (Pos) Line ¶
Line returns the line number of the position, starting at 1. Invalid positions always report the line number 0.
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.
func (Pos) Offset ¶
Offset returns the byte offset of the position in the original source file. Byte offsets start at 0. Invalid positions always report the offset 0.
Offset has basic protection against overflows; if an input is too large, offset numbers will stop increasing past a very large number.
type Printer ¶
type Printer struct {
// contains filtered or unexported fields
}
Printer holds the internal state of the printing mechanism of a program.
func NewPrinter ¶
func NewPrinter(opts ...PrinterOption) *Printer
NewPrinter allocates a new Printer and applies any number of options.
func (*Printer) Print ¶
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, *HeredocDelim, *Assign, any Command node, any ArithmExpr node, and any WordPart node. A trailing newline will only be printed when a *File is used.
type PrinterOption ¶
type PrinterOption func(*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 ¶
func BinaryNextLine(enabled bool) PrinterOption
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.
func FunctionNextLine ¶
func FunctionNextLine(enabled bool) PrinterOption
FunctionNextLine will place a function's opening braces on the next line.
func Indent ¶
func Indent(spaces uint) PrinterOption
Indent sets the number of spaces used for indentation. If set to 0, tabs will be used instead.
func KeepPadding
deprecated
func KeepPadding(enabled bool) PrinterOption
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.
Deprecated: this formatting option is flawed and buggy, and often does not result in what the user wants when the code gets complex enough. The next major version, v4, will remove this feature entirely. See: https://github.com/mvdan/sh/issues/658
func Minify ¶
func Minify(enabled bool) PrinterOption
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.
func SingleLine ¶
func SingleLine(enabled bool) PrinterOption
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.
func SpaceRedirects ¶
func SpaceRedirects(enabled bool) PrinterOption
SpaceRedirects will put a space after most redirection operators. The exceptions are '>&', '<&', '>(', and '<('.
func SwitchCaseIndent ¶
func SwitchCaseIndent(enabled bool) PrinterOption
SwitchCaseIndent will make switch cases be indented. As such, switch case bodies will be two levels deeper than the switch itself.
type ProcOperator ¶
type ProcOperator token
func (ProcOperator) String ¶
func (o ProcOperator) String() string
type ProcSubst ¶
type ProcSubst struct {
OpPos, Rparen Pos
Op ProcOperator
Stmts []*Stmt
Last []Comment
}
ProcSubst represents a Bash process substitution.
This node will only appear with LangBash.
type QuoteError ¶
func (QuoteError) Error ¶
func (e QuoteError) Error() string
type RedirOperator ¶
type RedirOperator token
func (RedirOperator) String ¶
func (o RedirOperator) String() string
type Redirect ¶
type Redirect struct {
OpPos Pos
Op RedirOperator
N *Lit // fd>, or {varname}> in Bash
Word *Word // >word
HdocDelim *HeredocDelim // <<EOF delimiter metadata
Hdoc *Word // here-document body
}
Redirect represents an input/output redirection.
type Replace ¶
type Replace struct {
Anchor ReplaceAnchor
All bool
Orig *Pattern
With *Word
}
Replace represents a search and replace expression inside a ParamExp.
type ReplaceAnchor ¶ added in v0.0.23
type ReplaceAnchor uint8
const ( ReplaceAnchorNone ReplaceAnchor = iota ReplaceAnchorPrefix ReplaceAnchorSuffix )
type Slice ¶
type Slice struct {
// MissingOffset distinguishes `${param:}` from `${param: }`.
// Both would otherwise look like an empty arithmetic word.
MissingOffset bool
Offset, Length ArithmExpr
}
Slice represents a character slicing expression inside a ParamExp.
This node will only appear with LangBash and LangMirBSDKorn. LangZsh uses a BinaryArithm with Comma in [ParamExp.Index.Expr] instead.
type Stmt ¶
type Stmt struct {
Comments []Comment
Cmd Command
Position Pos
Semicolon Pos // position of ';', '&', or '|&', if any
Negated bool // ! stmt
Background bool // stmt &
Coprocess bool // mksh's |&
Disown bool // zsh's &| or &!
Redirs []*Redirect // stmt >a <b
}
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.
type Subscript ¶
type Subscript struct {
Left, Right Pos
Kind SubscriptKind
Mode SubscriptMode
Expr ArithmExpr
// contains filtered or unexported fields
}
Subscript represents a bracketed shell subscript, such as [i], [$key], [@], or [*].
Expr can still be a string-like word or a zsh-specific expression such as a comma slice. The [Kind] field distinguishes the all-elements selectors from generic expression subscripts without forcing runtime consumers to reparse [@] or [*] from a generic word. [Mode] records whether a generic expression subscript should be interpreted with indexed-array arithmetic or associative-array string-key semantics; zero means the parser did not know yet and later resolution must decide.
func CloneSubscript ¶ added in v0.0.23
func (*Subscript) AllElements ¶
type SubscriptKind ¶
type SubscriptKind uint8
const ( SubscriptExpr SubscriptKind = iota SubscriptAt SubscriptStar )
type SubscriptMode ¶
type SubscriptMode uint8
const ( SubscriptAuto SubscriptMode = iota SubscriptIndexed SubscriptAssociative )
type Subshell ¶
Subshell represents a series of commands that should be executed in a nested shell environment.
type TestClause ¶
TestClause represents a Bash extended test clause.
This node will only appear with LangBash and LangMirBSDKorn.
func (*TestClause) End ¶
func (t *TestClause) End() Pos
func (*TestClause) Pos ¶
func (t *TestClause) Pos() Pos
type TestExpr ¶
type TestExpr interface {
Node
// contains filtered or unexported methods
}
TestExpr represents all nodes that form test expressions.
These are *BinaryTest, *UnaryTest, *ParenTest, and *Word.
type TimeClause ¶
TimeClause represents a Bash time clause. PosixFormat corresponds to the -p flag.
This node will only appear with LangBash and LangMirBSDKorn.
func (*TimeClause) End ¶
func (c *TimeClause) End() Pos
func (*TimeClause) Pos ¶
func (c *TimeClause) Pos() Pos
type UnAritOperator ¶
type UnAritOperator token
func (UnAritOperator) String ¶
func (o UnAritOperator) String() string
type UnTestOperator ¶
type UnTestOperator token
func (UnTestOperator) String ¶
func (o UnTestOperator) String() string
type UnaryArithm ¶
type UnaryArithm struct {
OpPos Pos
Op UnAritOperator
Post bool
X ArithmExpr
}
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.
func (*UnaryArithm) End ¶
func (u *UnaryArithm) End() Pos
func (*UnaryArithm) Pos ¶
func (u *UnaryArithm) Pos() Pos
type UnaryTest ¶
type UnaryTest struct {
OpPos Pos
Op UnTestOperator
X TestExpr
}
UnaryTest represents a unary test expression. The unary operator may come before or after the sub-expression.
type VarRef ¶
type VarRef struct {
Name *Lit // must be a valid name
Index *Subscript // [i], ["k"], [@], [*]
Context VarRefContext // default or -v-specific interpretation rules
// contains filtered or unexported fields
}
VarRef represents a reference to a shell variable, optionally with an array index or associative-array key.
func CloneVarRef ¶ added in v0.0.23
type VarRefContext ¶
type VarRefContext uint8
const ( VarRefDefault VarRefContext = iota VarRefVarSet )
type WhileClause ¶
type WhileClause struct {
WhilePos, DoPos, DonePos Pos
Until bool
Cond []*Stmt
CondLast []Comment
Do []*Stmt
DoLast []Comment
}
WhileClause represents a while or an until clause.
func (*WhileClause) End ¶
func (w *WhileClause) End() Pos
func (*WhileClause) Pos ¶
func (w *WhileClause) Pos() Pos
type Word ¶
type Word struct {
Parts []WordPart
// AliasExpansions preserves the alias-expansion chain that produced this
// word, if any. The chain is ordered from the outermost alias expansion to
// the innermost recursive expansion.
AliasExpansions []*AliasExpansion
}
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.
Example ¶
package main
import (
"fmt"
"os"
"strings"
"github.com/ewhauser/gbash/internal/shell/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()
}
}
Output: Word number 0: *syntax.Lit - echo Word number 1: *syntax.Lit - foo *syntax.ParamExp - ${bar} *syntax.SglQuoted - 'baz'
type WordIter ¶
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.
type WordPart ¶
type WordPart interface {
Node
// contains filtered or unexported methods
}
WordPart represents all nodes that can form part of a word.
These are *Lit, *SglQuoted, *DblQuoted, *ParamExp, *CmdSubst, *ArithmExp, *ProcSubst, *ExtGlob, and *BraceExp.