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  }