github.com/bir3/gocompiler@v0.9.2202/src/cmd/compile/internal/syntax/positions.go (about) 1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This file implements helper functions for scope position computations. 6 7 package syntax 8 9 // StartPos returns the start position of n. 10 func StartPos(n Node) Pos { 11 // Cases for nodes which don't need a correction are commented out. 12 for m := n; ; { 13 switch n := m.(type) { 14 case nil: 15 panic("nil node") 16 17 // packages 18 case *File: 19 // file block starts at the beginning of the file 20 return MakePos(n.Pos().Base(), 1, 1) 21 22 // declarations 23 // case *ImportDecl: 24 // case *ConstDecl: 25 // case *TypeDecl: 26 // case *VarDecl: 27 // case *FuncDecl: 28 29 // expressions 30 // case *BadExpr: 31 // case *Name: 32 // case *BasicLit: 33 case *CompositeLit: 34 if n.Type != nil { 35 m = n.Type 36 continue 37 } 38 return n.Pos() 39 // case *KeyValueExpr: 40 // case *FuncLit: 41 // case *ParenExpr: 42 case *SelectorExpr: 43 m = n.X 44 case *IndexExpr: 45 m = n.X 46 // case *SliceExpr: 47 case *AssertExpr: 48 m = n.X 49 case *TypeSwitchGuard: 50 if n.Lhs != nil { 51 m = n.Lhs 52 continue 53 } 54 m = n.X 55 case *Operation: 56 if n.Y != nil { 57 m = n.X 58 continue 59 } 60 return n.Pos() 61 case *CallExpr: 62 m = n.Fun 63 case *ListExpr: 64 if len(n.ElemList) > 0 { 65 m = n.ElemList[0] 66 continue 67 } 68 return n.Pos() 69 // types 70 // case *ArrayType: 71 // case *SliceType: 72 // case *DotsType: 73 // case *StructType: 74 // case *Field: 75 // case *InterfaceType: 76 // case *FuncType: 77 // case *MapType: 78 // case *ChanType: 79 80 // statements 81 // case *EmptyStmt: 82 // case *LabeledStmt: 83 // case *BlockStmt: 84 // case *ExprStmt: 85 case *SendStmt: 86 m = n.Chan 87 // case *DeclStmt: 88 case *AssignStmt: 89 m = n.Lhs 90 // case *BranchStmt: 91 // case *CallStmt: 92 // case *ReturnStmt: 93 // case *IfStmt: 94 // case *ForStmt: 95 // case *SwitchStmt: 96 // case *SelectStmt: 97 98 // helper nodes 99 case *RangeClause: 100 if n.Lhs != nil { 101 m = n.Lhs 102 continue 103 } 104 m = n.X 105 // case *CaseClause: 106 // case *CommClause: 107 108 default: 109 return n.Pos() 110 } 111 } 112 } 113 114 // EndPos returns the approximate end position of n in the source. 115 // For some nodes (*Name, *BasicLit) it returns the position immediately 116 // following the node; for others (*BlockStmt, *SwitchStmt, etc.) it 117 // returns the position of the closing '}'; and for some (*ParenExpr) 118 // the returned position is the end position of the last enclosed 119 // expression. 120 // Thus, EndPos should not be used for exact demarcation of the 121 // end of a node in the source; it is mostly useful to determine 122 // scope ranges where there is some leeway. 123 func EndPos(n Node) Pos { 124 for m := n; ; { 125 switch n := m.(type) { 126 case nil: 127 panic("nil node") 128 129 // packages 130 case *File: 131 return n.EOF 132 133 // declarations 134 case *ImportDecl: 135 m = n.Path 136 case *ConstDecl: 137 if n.Values != nil { 138 m = n.Values 139 continue 140 } 141 if n.Type != nil { 142 m = n.Type 143 continue 144 } 145 if l := len(n.NameList); l > 0 { 146 m = n.NameList[l-1] 147 continue 148 } 149 return n.Pos() 150 case *TypeDecl: 151 m = n.Type 152 case *VarDecl: 153 if n.Values != nil { 154 m = n.Values 155 continue 156 } 157 if n.Type != nil { 158 m = n.Type 159 continue 160 } 161 if l := len(n.NameList); l > 0 { 162 m = n.NameList[l-1] 163 continue 164 } 165 return n.Pos() 166 case *FuncDecl: 167 if n.Body != nil { 168 m = n.Body 169 continue 170 } 171 m = n.Type 172 173 // expressions 174 case *BadExpr: 175 return n.Pos() 176 case *Name: 177 p := n.Pos() 178 return MakePos(p.Base(), p.Line(), p.Col()+uint(len(n.Value))) 179 case *BasicLit: 180 p := n.Pos() 181 return MakePos(p.Base(), p.Line(), p.Col()+uint(len(n.Value))) 182 case *CompositeLit: 183 return n.Rbrace 184 case *KeyValueExpr: 185 m = n.Value 186 case *FuncLit: 187 m = n.Body 188 case *ParenExpr: 189 m = n.X 190 case *SelectorExpr: 191 m = n.Sel 192 case *IndexExpr: 193 m = n.Index 194 case *SliceExpr: 195 for i := len(n.Index) - 1; i >= 0; i-- { 196 if x := n.Index[i]; x != nil { 197 m = x 198 continue 199 } 200 } 201 m = n.X 202 case *AssertExpr: 203 m = n.Type 204 case *TypeSwitchGuard: 205 m = n.X 206 case *Operation: 207 if n.Y != nil { 208 m = n.Y 209 continue 210 } 211 m = n.X 212 case *CallExpr: 213 if l := lastExpr(n.ArgList); l != nil { 214 m = l 215 continue 216 } 217 m = n.Fun 218 case *ListExpr: 219 if l := lastExpr(n.ElemList); l != nil { 220 m = l 221 continue 222 } 223 return n.Pos() 224 225 // types 226 case *ArrayType: 227 m = n.Elem 228 case *SliceType: 229 m = n.Elem 230 case *DotsType: 231 m = n.Elem 232 case *StructType: 233 if l := lastField(n.FieldList); l != nil { 234 m = l 235 continue 236 } 237 return n.Pos() 238 // TODO(gri) need to take TagList into account 239 case *Field: 240 if n.Type != nil { 241 m = n.Type 242 continue 243 } 244 m = n.Name 245 case *InterfaceType: 246 if l := lastField(n.MethodList); l != nil { 247 m = l 248 continue 249 } 250 return n.Pos() 251 case *FuncType: 252 if l := lastField(n.ResultList); l != nil { 253 m = l 254 continue 255 } 256 if l := lastField(n.ParamList); l != nil { 257 m = l 258 continue 259 } 260 return n.Pos() 261 case *MapType: 262 m = n.Value 263 case *ChanType: 264 m = n.Elem 265 266 // statements 267 case *EmptyStmt: 268 return n.Pos() 269 case *LabeledStmt: 270 m = n.Stmt 271 case *BlockStmt: 272 return n.Rbrace 273 case *ExprStmt: 274 m = n.X 275 case *SendStmt: 276 m = n.Value 277 case *DeclStmt: 278 if l := lastDecl(n.DeclList); l != nil { 279 m = l 280 continue 281 } 282 return n.Pos() 283 case *AssignStmt: 284 m = n.Rhs 285 if m == nil { 286 p := EndPos(n.Lhs) 287 return MakePos(p.Base(), p.Line(), p.Col()+2) 288 } 289 case *BranchStmt: 290 if n.Label != nil { 291 m = n.Label 292 continue 293 } 294 return n.Pos() 295 case *CallStmt: 296 m = n.Call 297 case *ReturnStmt: 298 if n.Results != nil { 299 m = n.Results 300 continue 301 } 302 return n.Pos() 303 case *IfStmt: 304 if n.Else != nil { 305 m = n.Else 306 continue 307 } 308 m = n.Then 309 case *ForStmt: 310 m = n.Body 311 case *SwitchStmt: 312 return n.Rbrace 313 case *SelectStmt: 314 return n.Rbrace 315 316 // helper nodes 317 case *RangeClause: 318 m = n.X 319 case *CaseClause: 320 if l := lastStmt(n.Body); l != nil { 321 m = l 322 continue 323 } 324 return n.Colon 325 case *CommClause: 326 if l := lastStmt(n.Body); l != nil { 327 m = l 328 continue 329 } 330 return n.Colon 331 332 default: 333 return n.Pos() 334 } 335 } 336 } 337 338 func lastDecl(list []Decl) Decl { 339 if l := len(list); l > 0 { 340 return list[l-1] 341 } 342 return nil 343 } 344 345 func lastExpr(list []Expr) Expr { 346 if l := len(list); l > 0 { 347 return list[l-1] 348 } 349 return nil 350 } 351 352 func lastStmt(list []Stmt) Stmt { 353 if l := len(list); l > 0 { 354 return list[l-1] 355 } 356 return nil 357 } 358 359 func lastField(list []*Field) *Field { 360 if l := len(list); l > 0 { 361 return list[l-1] 362 } 363 return nil 364 }