github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/ast/position.go (about) 1 package ast 2 3 import ( 4 "fmt" 5 "path/filepath" 6 "strings" 7 8 "github.com/Konstantin8105/c4go/util" 9 ) 10 11 // Position is type of position in source code 12 type Position struct { 13 File string // The relative or absolute file path. 14 Line int // Start line 15 LineEnd int // End line 16 Column int // Start column 17 ColumnEnd int // End column 18 19 // This is the original string that was converted. This is used for 20 // debugging. We could derive this value from the other properties to save 21 // on a bit of memory, but let worry about that later. 22 StringValue string 23 } 24 25 // GetSimpleLocation - return a string like : "file:line" in 26 // according to position 27 // Example : " /tmp/1.c:200 " 28 func (p Position) GetSimpleLocation() (loc string) { 29 file := p.File 30 if f, err := filepath.Abs(p.File); err != nil { 31 file = f 32 } 33 return fmt.Sprintf(" %s:%d ", file, p.Line) 34 } 35 36 // NewPositionFromString create a Position from string line 37 func NewPositionFromString(s string) Position { 38 if strings.Contains(s, "<invalid sloc>") || s == "" { 39 return Position{} 40 } 41 42 re := util.GetRegex(`^col:(\d+)$`) 43 if groups := re.FindStringSubmatch(s); len(groups) > 0 { 44 return Position{ 45 StringValue: s, 46 Column: util.Atoi(groups[1]), 47 } 48 } 49 50 re = util.GetRegex(`^col:(\d+), col:(\d+)$`) 51 if groups := re.FindStringSubmatch(s); len(groups) > 0 { 52 return Position{ 53 StringValue: s, 54 Column: util.Atoi(groups[1]), 55 ColumnEnd: util.Atoi(groups[2]), 56 } 57 } 58 59 re = util.GetRegex(`^line:(\d+), line:(\d+)$`) 60 if groups := re.FindStringSubmatch(s); len(groups) > 0 { 61 return Position{ 62 StringValue: s, 63 Line: util.Atoi(groups[1]), 64 LineEnd: util.Atoi(groups[2]), 65 } 66 } 67 68 re = util.GetRegex(`^col:(\d+), line:(\d+)$`) 69 if groups := re.FindStringSubmatch(s); len(groups) > 0 { 70 return Position{ 71 StringValue: s, 72 Column: util.Atoi(groups[1]), 73 Line: util.Atoi(groups[2]), 74 } 75 } 76 77 re = util.GetRegex(`^line:(\d+):(\d+), line:(\d+):(\d+)$`) 78 if groups := re.FindStringSubmatch(s); len(groups) > 0 { 79 return Position{ 80 StringValue: s, 81 Line: util.Atoi(groups[1]), 82 Column: util.Atoi(groups[2]), 83 LineEnd: util.Atoi(groups[3]), 84 ColumnEnd: util.Atoi(groups[4]), 85 } 86 } 87 88 re = util.GetRegex(`^col:(\d+), line:(\d+):(\d+)$`) 89 if groups := re.FindStringSubmatch(s); len(groups) > 0 { 90 return Position{ 91 StringValue: s, 92 Column: util.Atoi(groups[1]), 93 LineEnd: util.Atoi(groups[2]), 94 ColumnEnd: util.Atoi(groups[3]), 95 } 96 } 97 98 re = util.GetRegex(`^line:(\d+):(\d+), col:(\d+)$`) 99 if groups := re.FindStringSubmatch(s); len(groups) > 0 { 100 return Position{ 101 StringValue: s, 102 Line: util.Atoi(groups[1]), 103 Column: util.Atoi(groups[2]), 104 ColumnEnd: util.Atoi(groups[3]), 105 } 106 } 107 108 re = util.GetRegex(`^line:(\d+):(\d+)$`) 109 if groups := re.FindStringSubmatch(s); len(groups) > 0 { 110 return Position{ 111 StringValue: s, 112 Line: util.Atoi(groups[1]), 113 Column: util.Atoi(groups[2]), 114 } 115 } 116 117 // This must be below all of the others. 118 re = util.GetRegex(`^((?:[a-zA-Z]\:)?[^:]+):(\d+):(\d+), col:(\d+)$`) 119 if groups := re.FindStringSubmatch(s); len(groups) > 0 { 120 return Position{ 121 StringValue: s, 122 File: groups[1], 123 Line: util.Atoi(groups[2]), 124 Column: util.Atoi(groups[3]), 125 ColumnEnd: util.Atoi(groups[4]), 126 } 127 } 128 129 re = util.GetRegex(`^((?:[a-zA-Z]\:)?[^:]+):(\d+):(\d+), line:(\d+):(\d+)$`) 130 if groups := re.FindStringSubmatch(s); len(groups) > 0 { 131 return Position{ 132 StringValue: s, 133 File: groups[1], 134 Line: util.Atoi(groups[2]), 135 Column: util.Atoi(groups[3]), 136 LineEnd: util.Atoi(groups[4]), 137 ColumnEnd: util.Atoi(groups[5]), 138 } 139 } 140 141 re = util.GetRegex(`^((?:[a-zA-Z]\:)?[^:]+):(\d+):(\d+)$`) 142 if groups := re.FindStringSubmatch(s); len(groups) > 0 { 143 return Position{ 144 StringValue: s, 145 File: groups[1], 146 Line: util.Atoi(groups[2]), 147 Column: util.Atoi(groups[3]), 148 } 149 } 150 151 re = util.GetRegex(`^((?:[a-zA-Z]\:)?[^:]+):(\d+):(\d+)$`) 152 if groups := re.FindStringSubmatch(s); len(groups) > 0 { 153 return Position{ 154 StringValue: s, 155 File: groups[1], 156 Line: util.Atoi(groups[2]), 157 Column: util.Atoi(groups[3]), 158 } 159 } 160 161 re = util.GetRegex(`^col:(\d+), ((?:[a-zA-Z]\:)?[^:]+):(\d+):(\d+)$`) 162 if groups := re.FindStringSubmatch(s); len(groups) > 0 { 163 return Position{ 164 StringValue: s, 165 Column: util.Atoi(groups[1]), 166 } 167 } 168 169 re = util.GetRegex(`^((?:[a-zA-Z]\:)?[^:]+):(\d+):(\d+), ((?:[a-zA-Z]\:)?[^:]+):(\d+):(\d+)$`) 170 if groups := re.FindStringSubmatch(s); len(groups) > 0 { 171 return Position{ 172 StringValue: s, 173 File: groups[1], 174 Line: util.Atoi(groups[2]), 175 Column: util.Atoi(groups[3]), 176 LineEnd: util.Atoi(groups[5]), 177 ColumnEnd: util.Atoi(groups[6]), 178 } 179 } 180 181 panic("unable to understand position '" + s + "'") 182 } 183 184 func mergePositions(p1, p2 Position) Position { 185 if p2.File != "" { 186 p1.File = p2.File 187 p1.Line = 0 188 p1.LineEnd = 0 189 p1.Column = 0 190 p1.ColumnEnd = 0 191 } 192 193 if p2.Line != 0 { 194 p1.Line = p2.Line 195 p1.LineEnd = 0 196 } 197 198 if p2.LineEnd != 0 { 199 p1.LineEnd = p2.LineEnd 200 } 201 202 if p2.Column != 0 { 203 p1.Column = p2.Column 204 p1.ColumnEnd = 0 205 } 206 207 if p2.ColumnEnd != 0 { 208 p1.ColumnEnd = p2.ColumnEnd 209 } 210 211 return p1 212 } 213 214 // PositionBuiltIn - default value for fix position 215 var PositionBuiltIn = "<built-in>" 216 217 // FixPositions is fix positions of Nodes 218 func FixPositions(nodes []Node) { 219 pos := Position{File: PositionBuiltIn} 220 fixPositions(nodes, pos) 221 } 222 223 func fixPositions(nodes []Node, pos Position) { 224 for _, node := range nodes { 225 if node != nil { 226 pos = mergePositions(pos, node.Position()) 227 setPosition(node, pos) 228 fixPositions(node.Children(), pos) 229 } 230 } 231 } 232 233 func setPosition(node Node, position Position) { 234 switch n := node.(type) { 235 case *AccessSpecDecl: 236 n.Pos = position 237 case *AlignedAttr: 238 n.Pos = position 239 case *AnnotateAttr: 240 n.Pos = position 241 case *AllocSizeAttr: 242 n.Pos = position 243 case *AlwaysInlineAttr: 244 n.Pos = position 245 case *ArraySubscriptExpr: 246 n.Pos = position 247 case *AsmLabelAttr: 248 n.Pos = position 249 case *AvailabilityAttr: 250 n.Pos = position 251 case *BuiltinAttr: 252 n.Pos = position 253 case *BinaryConditionalOperator: 254 n.Pos = position 255 case *BinaryOperator: 256 n.Pos = position 257 case *BlockCommandComment: 258 n.Pos = position 259 case *BreakStmt: 260 n.Pos = position 261 case *C11NoReturnAttr: 262 n.Pos = position 263 case *CallExpr: 264 n.Pos = position 265 case *CaseStmt: 266 n.Pos = position 267 case *CharacterLiteral: 268 n.Pos = position 269 case *CompoundStmt: 270 n.Pos = position 271 case *ConditionalOperator: 272 n.Pos = position 273 case *ConstAttr: 274 n.Pos = position 275 case *ConstantExpr: 276 n.Pos = position 277 case *ContinueStmt: 278 n.Pos = position 279 case *CompoundAssignOperator: 280 n.Pos = position 281 case *CompoundLiteralExpr: 282 n.Pos = position 283 case *CStyleCastExpr: 284 n.Pos = position 285 case *CXXConstructorDecl: 286 n.Pos = position 287 case *CXXConstructExpr: 288 n.Pos = position 289 case *CXXMethodDecl: 290 n.Pos = position 291 case *CXXMemberCallExpr: 292 n.Pos = position 293 case *CXXRecordDecl: 294 n.Pos = position 295 case *CXXThisExpr: 296 n.Pos = position 297 case *DeclRefExpr: 298 n.Pos = position 299 case *DeclStmt: 300 n.Pos = position 301 case *DefaultStmt: 302 n.Pos = position 303 case *DeprecatedAttr: 304 n.Pos = position 305 case *DisableTailCallsAttr: 306 n.Pos = position 307 case *DoStmt: 308 n.Pos = position 309 case *EmptyDecl: 310 n.Pos = position 311 case *EnableIfAttr: 312 n.Pos = position 313 case *EnumConstantDecl: 314 n.Pos = position 315 case *EnumDecl: 316 n.Pos = position 317 case *FieldDecl: 318 n.Pos = position 319 case *FloatingLiteral: 320 n.Pos = position 321 case *FormatAttr: 322 n.Pos = position 323 case *FormatArgAttr: 324 n.Pos = position 325 case *FullComment: 326 n.Pos = position 327 case *FunctionDecl: 328 n.Pos = position 329 case *ForStmt: 330 n.Pos = position 331 case *GenericSelectionExpr: 332 n.Pos = position 333 case *GCCAsmStmt: 334 n.Pos = position 335 case *HTMLStartTagComment: 336 n.Pos = position 337 case *HTMLEndTagComment: 338 n.Pos = position 339 case *GotoStmt: 340 n.Pos = position 341 case *IfStmt: 342 n.Pos = position 343 case *ImplicitCastExpr: 344 n.Pos = position 345 case *ImplicitValueInitExpr: 346 n.Pos = position 347 case *IndirectFieldDecl: 348 n.Pos = position 349 case *InitListExpr: 350 n.Pos = position 351 case *InlineCommandComment: 352 n.Pos = position 353 case *IntegerLiteral: 354 n.Pos = position 355 case *LabelStmt: 356 n.Pos = position 357 case *LinkageSpecDecl: 358 n.Pos = position 359 case *AllocAlignAttr: 360 n.Pos = position 361 case *MallocAttr: 362 n.Pos = position 363 case *MaxFieldAlignmentAttr: 364 n.Pos = position 365 case *MemberExpr: 366 n.Pos = position 367 case *ModeAttr: 368 n.Pos = position 369 case *NoAliasAttr: 370 n.Pos = position 371 case *NoInlineAttr: 372 n.Pos = position 373 case *NoThrowAttr: 374 n.Pos = position 375 case *NotTailCalledAttr: 376 n.Pos = position 377 case *NonNullAttr: 378 n.Pos = position 379 case *OffsetOfExpr: 380 n.Pos = position 381 case *OpaqueValueExpr: 382 n.Pos = position 383 case *OverloadableAttr: 384 n.Pos = position 385 case *PackedAttr: 386 n.Pos = position 387 case *ParagraphComment: 388 n.Pos = position 389 case *ParamCommandComment: 390 n.Pos = position 391 case *ParenExpr: 392 n.Pos = position 393 case *ParmVarDecl: 394 n.Pos = position 395 case *PredefinedExpr: 396 n.Pos = position 397 case *PureAttr: 398 n.Pos = position 399 case *RecordDecl: 400 n.Pos = position 401 case *RestrictAttr: 402 n.Pos = position 403 case *ReturnStmt: 404 n.Pos = position 405 case *ReturnsTwiceAttr: 406 n.Pos = position 407 case *SentinelAttr: 408 n.Pos = position 409 case *StmtExpr: 410 n.Pos = position 411 case *StaticAssertDecl: 412 n.Pos = position 413 case *StringLiteral: 414 n.Pos = position 415 case *SwitchStmt: 416 n.Pos = position 417 case *TextComment: 418 n.Pos = position 419 case *TransparentUnionAttr: 420 n.Pos = position 421 case *TypedefDecl: 422 n.Pos = position 423 case *UnaryExprOrTypeTraitExpr: 424 n.Pos = position 425 case *UnaryOperator: 426 n.Pos = position 427 case *UnusedAttr: 428 n.Pos = position 429 case *UsedAttr: 430 n.Pos = position 431 case *VAArgExpr: 432 n.Pos = position 433 case *VarDecl: 434 n.Pos = position 435 case *VerbatimBlockComment: 436 n.Pos = position 437 case *VerbatimBlockLineComment: 438 n.Pos = position 439 case *VerbatimLineComment: 440 n.Pos = position 441 case *VisibilityAttr: 442 n.Pos = position 443 case *WarnUnusedResultAttr: 444 n.Pos = position 445 case *WeakAttr: 446 n.Pos = position 447 case *WhileStmt: 448 n.Pos = position 449 case *TypedefType, *Typedef, *TranslationUnitDecl, *RecordType, *Record, 450 *QualType, *PointerType, *ParenType, *IncompleteArrayType, 451 *FunctionProtoType, *FunctionNoProtoType, *EnumType, *Enum, *ElaboratedType, 452 *ConstantArrayType, *BuiltinType, *ArrayFiller, *Field, 453 *DecayedType, *CXXRecord, *AttributedType: 454 // These do not have positions so they can be ignored. 455 default: 456 panic(fmt.Sprintf("unknown node type: %+#v", node)) 457 } 458 }