github.com/madlambda/nash@v0.2.2-0.20230113003044-f2284521680b/ast/node_args.go (about) 1 package ast 2 3 import ( 4 "fmt" 5 6 "github.com/madlambda/nash/scanner" 7 "github.com/madlambda/nash/token" 8 ) 9 10 // ArgFromToken is a helper to get an argument based on the lexer token 11 func ExprFromToken(val scanner.Token) (Expr, error) { 12 switch val.Type() { 13 case token.Arg: 14 return NewStringExpr(token.NewFileInfo(val.Line(), val.Column()), val.Value(), false), nil 15 case token.String: 16 return NewStringExpr(token.NewFileInfo(val.Line(), val.Column()), val.Value(), true), nil 17 case token.Variable: 18 return NewVarExpr(token.NewFileInfo(val.Line(), val.Column()), val.Value()), nil 19 } 20 21 return nil, fmt.Errorf("argFromToken doesn't support type %v", val) 22 } 23 24 // NewArgString creates a new string argument 25 func NewStringExpr(info token.FileInfo, value string, quoted bool) *StringExpr { 26 return &StringExpr{ 27 NodeType: NodeStringExpr, 28 FileInfo: info, 29 30 str: value, 31 quoted: quoted, 32 } 33 } 34 35 // Value returns the argument string value 36 func (s *StringExpr) Value() string { 37 return s.str 38 } 39 40 func (s *StringExpr) SetValue(a string) { 41 s.str = a 42 } 43 44 func (s *StringExpr) IsEqual(other Node) bool { 45 if !s.equal(s, other) { 46 return false 47 } 48 49 value, ok := other.(*StringExpr) 50 51 if !ok { 52 return false 53 } 54 55 if s.quoted != value.quoted { 56 return false 57 } 58 59 return s.str == value.str 60 } 61 62 func NewIntExpr(info token.FileInfo, val int) *IntExpr { 63 return &IntExpr{ 64 NodeType: NodeIntExpr, 65 FileInfo: info, 66 67 val: val, 68 } 69 } 70 71 func (i *IntExpr) Value() int { return i.val } 72 73 func (i *IntExpr) IsEqual(other Node) bool { 74 if !i.equal(i, other) { 75 return false 76 } 77 78 o, ok := other.(*IntExpr) 79 80 if !ok { 81 return false 82 } 83 84 return i.val == o.val 85 } 86 87 func NewListExpr(info token.FileInfo, values []Expr) *ListExpr { 88 return NewListVariadicExpr(info, values, false) 89 } 90 91 func NewListVariadicExpr(info token.FileInfo, values []Expr, variadic bool) *ListExpr { 92 return &ListExpr{ 93 NodeType: NodeListExpr, 94 FileInfo: info, 95 96 List: values, 97 IsVariadic: variadic, 98 } 99 } 100 101 // PushExpr push an expression to end of the list 102 func (l *ListExpr) PushExpr(a Expr) { 103 l.List = append(l.List, a) 104 } 105 106 func (l *ListExpr) IsEqual(other Node) bool { 107 if !l.equal(l, other) { 108 return false 109 } 110 111 o, ok := other.(*ListExpr) 112 113 if !ok { 114 return false 115 } 116 117 if len(l.List) != len(o.List) { 118 return false 119 } 120 121 for i, val := range l.List { 122 oval := o.List[i] 123 if !val.IsEqual(oval) { 124 debug("%v(%s) != %v(%s)", val, val.Type(), 125 oval, oval.Type()) 126 return false 127 } 128 } 129 130 return true 131 } 132 133 func NewConcatExpr(info token.FileInfo, parts []Expr) *ConcatExpr { 134 return &ConcatExpr{ 135 NodeType: NodeConcatExpr, 136 FileInfo: info, 137 138 concat: parts, 139 } 140 } 141 142 // PushExpr push an expression to end of the concat list 143 func (c *ConcatExpr) PushExpr(a Expr) { 144 c.concat = append(c.concat, a) 145 } 146 147 // SetConcatList set the concatenation parts 148 func (c *ConcatExpr) SetConcat(v []Expr) { 149 c.concat = v 150 } 151 152 func (c *ConcatExpr) List() []Expr { return c.concat } 153 154 func (c *ConcatExpr) IsEqual(other Node) bool { 155 if !c.equal(c, other) { 156 return false 157 } 158 159 o, ok := other.(*ConcatExpr) 160 161 if !ok { 162 return false 163 } 164 165 if len(c.concat) != len(o.concat) { 166 return false 167 } 168 169 for i := 0; i < len(c.concat); i++ { 170 if !c.concat[i].IsEqual(o.concat[i]) { 171 return false 172 } 173 } 174 175 return true 176 } 177 178 func NewVarExpr(info token.FileInfo, name string) *VarExpr { 179 return NewVarVariadicExpr(info, name, false) 180 } 181 182 func NewVarVariadicExpr(info token.FileInfo, name string, isVariadic bool) *VarExpr { 183 return &VarExpr{ 184 NodeType: NodeVarExpr, 185 FileInfo: info, 186 Name: name, 187 IsVariadic: isVariadic, 188 } 189 } 190 191 func (v *VarExpr) IsEqual(other Node) bool { 192 if !v.equal(v, other) { 193 return false 194 } 195 196 o, ok := other.(*VarExpr) 197 if !ok { 198 return false 199 } 200 201 return v.Name == o.Name && 202 v.IsVariadic == o.IsVariadic 203 } 204 205 func NewIndexExpr(info token.FileInfo, va *VarExpr, idx Expr) *IndexExpr { 206 return NewIndexVariadicExpr(info, va, idx, false) 207 } 208 209 func NewIndexVariadicExpr(info token.FileInfo, va *VarExpr, idx Expr, variadic bool) *IndexExpr { 210 return &IndexExpr{ 211 NodeType: NodeIndexExpr, 212 FileInfo: info, 213 214 Var: va, 215 Index: idx, 216 IsVariadic: variadic, 217 } 218 } 219 220 func (i *IndexExpr) IsEqual(other Node) bool { 221 if !i.equal(i, other) { 222 return false 223 } 224 225 o, ok := other.(*IndexExpr) 226 if !ok { 227 return false 228 } 229 230 return i.Var.IsEqual(o.Var) && 231 i.Index.IsEqual(o.Index) && 232 i.IsVariadic == o.IsVariadic 233 }