github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/lang/expressions/statement.go (about)

     1  package expressions
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/lmorg/murex/lang/expressions/noglob"
     7  	"github.com/lmorg/murex/utils/lists"
     8  )
     9  
    10  type StatementT struct {
    11  	command    []rune
    12  	parameters [][]rune
    13  	paramTemp  []rune
    14  	namedPipes []string
    15  	cast       []rune
    16  
    17  	// parser states
    18  	canHaveZeroLenStr bool // to get around $VARS being empty or unset
    19  	possibleGlob      bool // to signal to NextParameter of a possible glob
    20  	asStatement       bool // force murex to parse expression as statement
    21  	ignoreCrLf        bool // allow '\' to escape a new line
    22  	validFunction     bool // allow function(parameters...) in statement
    23  }
    24  
    25  func (st *StatementT) String() string {
    26  	if st == nil {
    27  		return "<nil>"
    28  	}
    29  	return string(st.command)
    30  }
    31  
    32  func (st *StatementT) Parameters() []string {
    33  	if st == nil {
    34  		return nil
    35  	}
    36  
    37  	params := make([]string, len(st.parameters))
    38  
    39  	for i := range st.parameters {
    40  		params[i] = string(st.parameters[i])
    41  	}
    42  
    43  	return params
    44  }
    45  
    46  func (tree *ParserT) nextParameter() error {
    47  	st := tree.statement
    48  
    49  	switch {
    50  
    51  	case len(st.command) == 0:
    52  		// no command yet so this must be a command
    53  		st.command = st.paramTemp
    54  		st.possibleGlob = false
    55  		st.validFunction = true
    56  
    57  	case st.possibleGlob:
    58  		// glob
    59  		st.possibleGlob = false
    60  		st.canHaveZeroLenStr = false
    61  		st.validFunction = true
    62  
    63  		if !tree.ExpandGlob() || lists.Match(noglob.GetNoGlobCmds(), st.String()) {
    64  			st.parameters = append(st.parameters, st.paramTemp)
    65  			break
    66  		}
    67  		v, err := tree.parseGlob(st.paramTemp)
    68  		if err != nil {
    69  			return err
    70  		}
    71  		if v == nil {
    72  			st.parameters = append(st.parameters, st.paramTemp)
    73  			break
    74  		}
    75  		for i := range v {
    76  			st.parameters = append(st.parameters, []rune(v[i]))
    77  		}
    78  
    79  	case st.canHaveZeroLenStr:
    80  		// variable, possibly zero length
    81  		st.parameters = append(st.parameters, st.paramTemp)
    82  		st.canHaveZeroLenStr = false
    83  		st.validFunction = true
    84  
    85  	case len(st.paramTemp) == 0:
    86  		// just empty space. Nothing to do
    87  		return nil
    88  
    89  	default:
    90  		// just a regular old parameter
    91  		st.parameters = append(st.parameters, st.paramTemp)
    92  		st.validFunction = true
    93  	}
    94  
    95  	st.paramTemp = []rune{}
    96  	return nil
    97  }
    98  
    99  func (st *StatementT) validate() error {
   100  	switch {
   101  
   102  	case len(st.command) == 0:
   103  		return errors.New("no command specified (empty command property)")
   104  
   105  	case st.command[0] == '$':
   106  		return errors.New("commands cannot begin with '$'. Please quote or escape this character")
   107  
   108  	case st.command[0] == '@' && len(st.command) > 1 && st.command[1] != '[':
   109  		return errors.New("commands cannot begin with '@'. Please quote or escape this character")
   110  
   111  	case st.command[0] == '%':
   112  		return errors.New("commands cannot begin with '%'. Please quote or escape this character")
   113  
   114  	default:
   115  		return nil
   116  	}
   117  }