Initial commit.

This commit is contained in:
Greg 2019-04-09 11:52:21 -04:00
commit 6a9c5c2811
230 changed files with 10509 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
clast
ast.txt

47
ast/aligned_attr.go Normal file
View File

@ -0,0 +1,47 @@
package ast
// AlignedAttr is a type of attribute that is optionally attached to a variable
// or struct field definition.
type AlignedAttr struct {
Addr Address
Pos Position
IsAligned bool
ChildNodes []Node
}
func parseAlignedAttr(line string) *AlignedAttr {
groups := groupsFromRegex(
"<(?P<position>.*)>(?P<aligned> aligned)?",
line,
)
return &AlignedAttr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
IsAligned: len(groups["aligned"]) > 0,
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *AlignedAttr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *AlignedAttr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *AlignedAttr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *AlignedAttr) Position() Position {
return n.Pos
}

24
ast/aligned_attr_test.go Normal file
View File

@ -0,0 +1,24 @@
package ast
import (
"testing"
)
func TestAlignedAttr(t *testing.T) {
nodes := map[string]Node{
`0x7f8a1d8ccfd0 <col:47, col:57> aligned`: &AlignedAttr{
Addr: 0x7f8a1d8ccfd0,
Pos: NewPositionFromString("col:47, col:57"),
IsAligned: true,
ChildNodes: []Node{},
},
`0x2c8ba10 <col:42>`: &AlignedAttr{
Addr: 0x2c8ba10,
Pos: NewPositionFromString("col:42"),
IsAligned: false,
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

57
ast/alloc_size_attr.go Normal file
View File

@ -0,0 +1,57 @@
package ast
import (
"strings"
"github.com/elliotchance/c2go/util"
)
// AllocSizeAttr is a type of attribute that is optionally attached to a variable
// or struct field definition.
type AllocSizeAttr struct {
Addr Address
Pos Position
Inherited bool
A int
B int
ChildNodes []Node
}
func parseAllocSizeAttr(line string) *AllocSizeAttr {
groups := groupsFromRegex(
`<(?P<position>.*)>(?P<inherited> Inherited)?(?P<a> \d+)(?P<b> \d+)?`,
line,
)
return &AllocSizeAttr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Inherited: len(groups["inherited"]) > 0,
A: util.Atoi(strings.TrimSpace(groups["a"])),
B: util.Atoi(strings.TrimSpace(groups["b"])),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *AllocSizeAttr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *AllocSizeAttr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *AllocSizeAttr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *AllocSizeAttr) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,27 @@
package ast
import (
"testing"
)
func TestAllocSizeAttr(t *testing.T) {
nodes := map[string]Node{
`0x7f8e390a5d38 <col:100, col:114> 1 2`: &AllocSizeAttr{
Addr: 0x7f8e390a5d38,
Pos: NewPositionFromString("col:100, col:114"),
A: 1,
B: 2,
ChildNodes: []Node{},
},
`0x7fbd1a167f48 </usr/include/stdlib.h:342:37> Inherited 1 0`: &AllocSizeAttr{
Addr: 0x7fbd1a167f48,
Pos: NewPositionFromString("/usr/include/stdlib.h:342:37"),
Inherited: true,
A: 1,
B: 0,
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

45
ast/always_inline_attr.go Normal file
View File

@ -0,0 +1,45 @@
package ast
// AlwaysInlineAttr is a type of attribute that is optionally attached to a
// variable or struct field definition.
type AlwaysInlineAttr struct {
Addr Address
Pos Position
ChildNodes []Node
}
func parseAlwaysInlineAttr(line string) *AlwaysInlineAttr {
groups := groupsFromRegex(
"<(?P<position>.*)> always_inline",
line,
)
return &AlwaysInlineAttr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *AlwaysInlineAttr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *AlwaysInlineAttr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *AlwaysInlineAttr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *AlwaysInlineAttr) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,17 @@
package ast
import (
"testing"
)
func TestAlwaysInlineAttr(t *testing.T) {
nodes := map[string]Node{
`0x7fce780f5018 </usr/include/sys/cdefs.h:313:68> always_inline`: &AlwaysInlineAttr{
Addr: 0x7fce780f5018,
Pos: NewPositionFromString("/usr/include/sys/cdefs.h:313:68"),
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

36
ast/array_filler.go Normal file
View File

@ -0,0 +1,36 @@
package ast
// ArrayFiller is type of array filler
type ArrayFiller struct {
ChildNodes []Node
}
func parseArrayFiller(line string) *ArrayFiller {
return &ArrayFiller{
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *ArrayFiller) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. For an ArrayFilter this will
// always be zero. See the documentation for the Address type for more
// information.
func (n *ArrayFiller) Address() Address {
return 0
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *ArrayFiller) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *ArrayFiller) Position() Position {
return Position{}
}

20
ast/array_filler_test.go Normal file
View File

@ -0,0 +1,20 @@
package ast
import (
"reflect"
"testing"
"github.com/elliotchance/c2go/util"
)
func TestArrayFiller(t *testing.T) {
expected := &ArrayFiller{
ChildNodes: []Node{},
}
actual := Parse(`array filler`)
if !reflect.DeepEqual(expected, actual) {
t.Errorf("%s", util.ShowDiff(formatMultiLine(expected),
formatMultiLine(actual)))
}
}

View File

@ -0,0 +1,54 @@
package ast
// ArraySubscriptExpr is expression.
type ArraySubscriptExpr struct {
Addr Address
Pos Position
Type string
Type2 string
IsLvalue bool
IsVectorComponent bool
ChildNodes []Node
}
func parseArraySubscriptExpr(line string) *ArraySubscriptExpr {
groups := groupsFromRegex(
`<(?P<position>.*)> '(?P<type>.*?)'(:'(?P<type2>.*?)')?
(?P<lvalue> lvalue)?
(?P<vcomp> vectorcomponent)?`,
line,
)
return &ArraySubscriptExpr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Type: groups["type"],
Type2: groups["type2"],
IsLvalue: len(groups["lvalue"]) > 0,
IsVectorComponent: len(groups["vcomp"]) > 0,
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *ArraySubscriptExpr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *ArraySubscriptExpr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *ArraySubscriptExpr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *ArraySubscriptExpr) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,36 @@
package ast
import (
"testing"
)
func TestArraySubscriptExpr(t *testing.T) {
nodes := map[string]Node{
`0x7fe35b85d180 <col:63, col:69> 'char *' lvalue`: &ArraySubscriptExpr{
Addr: 0x7fe35b85d180,
Pos: NewPositionFromString("col:63, col:69"),
Type: "char *",
Type2: "",
IsLvalue: true,
ChildNodes: []Node{},
},
`0x2416660 <col:2, col:5> 'u32':'unsigned int' lvalue`: &ArraySubscriptExpr{
Addr: 0x2416660,
Pos: NewPositionFromString("col:2, col:5"),
Type: "u32",
Type2: "unsigned int",
IsLvalue: true,
ChildNodes: []Node{},
},
`0x3f147c0 <col:39, col:55> 'extCoord':'extCoord' lvalue`: &ArraySubscriptExpr{
Addr: 0x3f147c0,
Pos: NewPositionFromString("col:39, col:55"),
Type: "extCoord",
Type2: "extCoord",
IsLvalue: true,
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

50
ast/asm_label_attr.go Normal file
View File

@ -0,0 +1,50 @@
package ast
// AsmLabelAttr is a type of attribute for assembler label
type AsmLabelAttr struct {
Addr Address
Pos Position
Inherited bool
FunctionName string
ChildNodes []Node
}
func parseAsmLabelAttr(line string) *AsmLabelAttr {
groups := groupsFromRegex(
`<(?P<position>.*)>
(?P<inherited> Inherited)?
"(?P<function>.+)"`,
line,
)
return &AsmLabelAttr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Inherited: len(groups["inherited"]) > 0,
FunctionName: groups["function"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *AsmLabelAttr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *AsmLabelAttr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *AsmLabelAttr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *AsmLabelAttr) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,26 @@
package ast
import (
"testing"
)
func TestAsmLabelAttr(t *testing.T) {
nodes := map[string]Node{
`0x7ff26d8224e8 </usr/include/sys/cdefs.h:569:36> "_fopen"`: &AsmLabelAttr{
Addr: 0x7ff26d8224e8,
Pos: NewPositionFromString("/usr/include/sys/cdefs.h:569:36"),
Inherited: false,
FunctionName: "_fopen",
ChildNodes: []Node{},
},
`0x7fd55a169318 </usr/include/stdio.h:325:47> Inherited "_popen"`: &AsmLabelAttr{
Addr: 0x7fd55a169318,
Pos: NewPositionFromString("/usr/include/stdio.h:325:47"),
Inherited: true,
FunctionName: "_popen",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

323
ast/ast.go Normal file
View File

@ -0,0 +1,323 @@
// Package ast parses the clang AST output into AST structures.
package ast
import (
"strconv"
"strings"
"github.com/elliotchance/c2go/util"
)
// Node represents any node in the AST.
type Node interface {
Address() Address
Children() []Node
AddChild(node Node)
Position() Position
}
// Address contains the memory address (originally outputted as a hexadecimal
// string) from the clang AST. The address are not predictable between run and
// are only useful for identifying nodes in a single AST.
//
// The Address is used like a primary key when storing the tree as a flat
// structure.
type Address uint64
// ParseAddress returns the integer representation of the hexadecimal address
// (like 0x7f8a1d8ccfd0). If the address cannot be parsed, 0 is returned.
func ParseAddress(address string) Address {
addr, _ := strconv.ParseUint(address, 0, 64)
return Address(addr)
}
// Parse takes the coloured output of the clang AST command and returns a root
// node for the AST.
func Parse(fullline string) Node {
line := fullline
// This is a special case. I'm not sure if it's a bug in the clang AST
// dumper. It should have children.
if line == "array filler" {
return parseArrayFiller(line)
}
parts := strings.SplitN(line, " ", 2)
nodeName := parts[0]
if nodeName == "super" || nodeName == "getter" { // special ObjC case
parts = strings.SplitN(parts[1], " ", 2)
nodeName += " " + parts[0]
}
// skip node name
if len(parts) > 1 {
line = parts[1]
}
switch nodeName {
case "AlignedAttr":
return parseAlignedAttr(line)
case "AllocSizeAttr":
return parseAllocSizeAttr(line)
case "AlwaysInlineAttr":
return parseAlwaysInlineAttr(line)
case "ArraySubscriptExpr":
return parseArraySubscriptExpr(line)
case "AsmLabelAttr":
return parseAsmLabelAttr(line)
case "AttributedType":
return parseAttributedType(line)
case "AvailabilityAttr":
return parseAvailabilityAttr(line)
case "BinaryOperator":
return parseBinaryOperator(line)
case "BlockCommandComment":
return parseBlockCommandComment(line)
case "BlockPointerType":
return parseBlockPointerType(line)
case "BreakStmt":
return parseBreakStmt(line)
case "BuiltinType":
return parseBuiltinType(line)
case "CallExpr":
return parseCallExpr(line)
case "CaseStmt":
return parseCaseStmt(line)
case "CharacterLiteral":
return parseCharacterLiteral(line)
case "CompoundLiteralExpr":
return parseCompoundLiteralExpr(line)
case "CompoundStmt":
return parseCompoundStmt(line)
case "ConditionalOperator":
return parseConditionalOperator(line)
case "ConstAttr":
return parseConstAttr(line)
case "ConstantArrayType":
return parseConstantArrayType(line)
case "ContinueStmt":
return parseContinueStmt(line)
case "CompoundAssignOperator":
return parseCompoundAssignOperator(line)
case "CStyleCastExpr":
return parseCStyleCastExpr(line)
case "DeclRefExpr":
return parseDeclRefExpr(line)
case "DeclStmt":
return parseDeclStmt(line)
case "DefaultStmt":
return parseDefaultStmt(line)
case "DeprecatedAttr":
return parseDeprecatedAttr(line)
case "DisableTailCallsAttr":
return parseDisableTailCallsAttr(line)
case "DoStmt":
return parseDoStmt(line)
case "ElaboratedType":
return parseElaboratedType(line)
case "EmptyDecl":
return parseEmptyDecl(line)
case "Enum":
return parseEnum(line)
case "EnumConstantDecl":
return parseEnumConstantDecl(line)
case "EnumDecl":
return parseEnumDecl(line)
case "EnumType":
return parseEnumType(line)
case "Field":
return parseField(line)
case "FieldDecl":
return parseFieldDecl(line)
case "FloatingLiteral":
return parseFloatingLiteral(line)
case "FormatAttr":
return parseFormatAttr(line)
case "FormatArgAttr":
return parseFormatArgAttr(line)
case "FunctionDecl":
return parseFunctionDecl(line)
case "FullComment":
return parseFullComment(line)
case "FunctionProtoType":
return parseFunctionProtoType(line)
case "ForStmt":
return parseForStmt(line)
case "HTMLStartTagComment":
return parseHTMLStartTagComment(line)
case "HTMLEndTagComment":
return parseHTMLEndTagComment(line)
case "GCCAsmStmt":
return parseGCCAsmStmt(line)
case "GotoStmt":
return parseGotoStmt(line)
case "IfStmt":
return parseIfStmt(line)
case "ImplicitCastExpr":
return parseImplicitCastExpr(line)
case "ImplicitValueInitExpr":
return parseImplicitValueInitExpr(line)
case "IncompleteArrayType":
return parseIncompleteArrayType(line)
case "IndirectFieldDecl":
return parseIndirectFieldDecl(line)
case "InitListExpr":
return parseInitListExpr(line)
case "InlineCommandComment":
return parseInlineCommandComment(line)
case "IntegerLiteral":
return parseIntegerLiteral(line)
case "LabelStmt":
return parseLabelStmt(line)
case "MallocAttr":
return parseMallocAttr(line)
case "MaxFieldAlignmentAttr":
return parseMaxFieldAlignmentAttr(line)
case "MemberExpr":
return parseMemberExpr(line)
case "ModeAttr":
return parseModeAttr(line)
case "NoInlineAttr":
return parseNoInlineAttr(line)
case "NoThrowAttr":
return parseNoThrowAttr(line)
case "NonNullAttr":
return parseNonNullAttr(line)
case "NotTailCalledAttr":
return parseNotTailCalledAttr(line)
case "ObjCInterface":
return parseObjCInterface(line)
case "ObjCInterfaceType":
return parseObjCInterfaceType(line)
case "super ObjCInterface":
return parseObjCInterface(line)
case "ObjCInterfaceDecl":
return parseObjCInterfaceDecl(line)
case "getter ObjCMethod":
return parseObjCMethod(line)
case "ObjCMethod":
return parseObjCMethod(line)
case "ObjCMethodDecl":
return parseObjCMethodDecl(line)
case "ObjCObjectType":
return parseObjCObjectType(line)
case "ObjCObjectPointerType":
return parseObjCObjectPointerType(line)
case "ObjCProtocol":
return parseObjCProtocol(line)
case "OffsetOfExpr":
return parseOffsetOfExpr(line)
case "PackedAttr":
return parsePackedAttr(line)
case "ParagraphComment":
return parseParagraphComment(line)
case "ParamCommandComment":
return parseParamCommandComment(line)
case "ParenExpr":
return parseParenExpr(line)
case "ParenType":
return parseParenType(line)
case "ParmVarDecl":
return parseParmVarDecl(line)
case "PointerType":
return parsePointerType(line)
case "DecayedType":
return parseDecayedType(line)
case "PredefinedExpr":
return parsePredefinedExpr(line)
case "PureAttr":
return parsePureAttr(line)
case "QualType":
return parseQualType(line)
case "Record":
return parseRecord(line)
case "RecordDecl":
return parseRecordDecl(line)
case "RecordType":
return parseRecordType(line)
case "RestrictAttr":
return parseRestrictAttr(line)
case "ReturnStmt":
return parseReturnStmt(line)
case "ReturnsTwiceAttr":
return parseReturnsTwiceAttr(line)
case "SentinelAttr":
return parseSentinelAttr(line)
case "StmtExpr":
return parseStmtExpr(line)
case "StringLiteral":
return parseStringLiteral(line)
case "SwitchStmt":
return parseSwitchStmt(line)
case "TextComment":
return parseTextComment(line)
case "TranslationUnitDecl":
return parseTranslationUnitDecl(line)
case "TransparentUnionAttr":
return parseTransparentUnionAttr(line)
case "Typedef":
return parseTypedef(line)
case "TypedefDecl":
return parseTypedefDecl(line)
case "TypedefType":
return parseTypedefType(line)
case "UnaryExprOrTypeTraitExpr":
return parseUnaryExprOrTypeTraitExpr(line)
case "UnaryOperator":
return parseUnaryOperator(line)
case "UnusedAttr":
return parseUnusedAttr(line)
case "VAArgExpr":
return parseVAArgExpr(line)
case "VarDecl":
return parseVarDecl(line)
case "VectorType":
return parseVectorType(line)
case "VerbatimBlockComment":
return parseVerbatimBlockComment(line)
case "VerbatimBlockLineComment":
return parseVerbatimBlockLineComment(line)
case "VerbatimLineComment":
return parseVerbatimLineComment(line)
case "VisibilityAttr":
return parseVisibilityAttr(line)
case "WarnUnusedResultAttr":
return parseWarnUnusedResultAttr(line)
case "WeakAttr":
return parseWeakAttr(line)
case "WhileStmt":
return parseWhileStmt(line)
case "NullStmt":
return nil
case "...": // FIXME for variadic functions
return nil
default:
return parseUnknown(nodeName,line)
}
}
func groupsFromRegex(rx, line string) map[string]string {
// We remove tabs and newlines from the regex. This is purely cosmetic,
// as the regex input can be quite long and it's nice for the caller to
// be able to format it in a more readable way.
fullRegexp := "^(?P<address>[0-9a-fx]+) " +
strings.Replace(strings.Replace(rx, "\n", "", -1), "\t", "", -1)
rx = fullRegexp + "[\\s]*$"
re := util.GetRegex(rx)
match := re.FindStringSubmatch(line)
if len(match) == 0 {
panic("could not match regexp with string\n" + rx + "\n" + line + "\n")
}
result := make(map[string]string)
for i, name := range re.SubexpNames() {
if i != 0 {
result[name] = match[i]
}
}
return result
}

70
ast/ast_test.go Normal file
View File

@ -0,0 +1,70 @@
package ast
import (
"fmt"
"reflect"
"strings"
"testing"
"github.com/elliotchance/c2go/util"
)
func formatMultiLine(o interface{}) string {
s := fmt.Sprintf("%#v", o)
s = strings.Replace(s, "{", "{\n", -1)
s = strings.Replace(s, ", ", "\n", -1)
return s
}
func runNodeTests(t *testing.T, tests map[string]Node) {
i := 1
for line, expected := range tests {
testName := fmt.Sprintf("Example%d", i)
i++
t.Run(testName, func(t *testing.T) {
// Append the name of the struct onto the front. This would make the
// complete line it would normally be parsing.
name := reflect.TypeOf(expected).Elem().Name()
actual := Parse(name + " " + line)
if !reflect.DeepEqual(expected, actual) {
t.Errorf("%s", util.ShowDiff(formatMultiLine(expected),
formatMultiLine(actual)))
}
})
}
}
func TestPrint(t *testing.T) {
cond := &ConditionalOperator{}
cond.AddChild(&ImplicitCastExpr{})
cond.AddChild(&ImplicitCastExpr{})
s := Atos(cond)
if len(s) == 0 {
t.Fatalf("Cannot convert AST tree : %#v", cond)
}
lines := strings.Split(s, "\n")
var amount int
for _, l := range lines {
if strings.Contains(l, "ImplicitCastExpr") {
amount++
}
}
if amount != 2 {
t.Error("Not correct design of output")
}
}
var lines = []string{
// c2go ast sqlite3.c | head -5000 | sed 's/^[ |`-]*//' | sed 's/<<<NULL>>>/NullStmt/g' | gawk 'length > 0 {print "`" $0 "`,"}'
}
func BenchmarkParse(b *testing.B) {
for n := 0; n < b.N; n++ {
for _, line := range lines {
Parse(line)
}
}
}

47
ast/attributed_type.go Normal file
View File

@ -0,0 +1,47 @@
package ast
// AttributedType is attributed type
type AttributedType struct {
Addr Address
Type string
Sugar bool
ChildNodes []Node
}
func parseAttributedType(line string) *AttributedType {
groups := groupsFromRegex(
`'(?P<type>.*)'
(?P<sugar> sugar)?`,
line,
)
return &AttributedType{
Addr: ParseAddress(groups["address"]),
Type: groups["type"],
Sugar: len(groups["sugar"])>0,
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *AttributedType) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *AttributedType) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *AttributedType) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *AttributedType) Position() Position {
return Position{}
}

69
ast/availability_attr.go Normal file
View File

@ -0,0 +1,69 @@
package ast
// AvailabilityAttr is a type of attribute that is optionally attached to a variable
// or struct field definition.
type AvailabilityAttr struct {
Addr Address
Pos Position
OS string
Version string
Unknown1 string
Unknown2 string
IsUnavailable bool
Message1 string
Message2 string
IsInherited bool
ChildNodes []Node
}
func parseAvailabilityAttr(line string) *AvailabilityAttr {
groups := groupsFromRegex(
`<(?P<position>.*)>
(?P<inherited> Inherited)?
(?P<os>\w+)
(?P<version>[\d_.]+)
(?P<unknown1>[\d_.]+)
(?P<unknown2>[\d_.]+)
(?P<unavalable> Unavailable)?
"(?P<message1>.*?)"
(?P<message2> ".*?")?`,
line,
)
return &AvailabilityAttr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
OS: groups["os"],
Version: groups["version"],
Unknown1: groups["unknown1"],
Unknown2: groups["unknown2"],
IsUnavailable: len(groups["unavalable"]) > 0,
Message1: removeQuotes(groups["message1"]),
Message2: removeQuotes(groups["message2"]),
IsInherited: len(groups["inherited"]) > 0,
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *AvailabilityAttr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *AvailabilityAttr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *AvailabilityAttr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *AvailabilityAttr) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,116 @@
package ast
import (
"testing"
)
func TestAvailabilityAttr(t *testing.T) {
nodes := map[string]Node{
`0x7fc5ff8e5d18 </usr/include/AvailabilityInternal.h:21697:88, col:124> macos 10.10 0 0 "" ""`: &AvailabilityAttr{
Addr: 0x7fc5ff8e5d18,
Pos: NewPositionFromString("/usr/include/AvailabilityInternal.h:21697:88, col:124"),
OS: "macos",
Version: "10.10",
Unknown1: 0,
Unknown2: 0,
IsUnavailable: false,
Message1: "",
Message2: "",
IsInherited: false,
ChildNodes: []Node{},
},
`0x7fc5ff8e60d0 </usr/include/Availability.h:215:81, col:115> watchos 3.0 0 0 "" ""`: &AvailabilityAttr{
Addr: 0x7fc5ff8e60d0,
Pos: NewPositionFromString("/usr/include/Availability.h:215:81, col:115"),
OS: "watchos",
Version: "3.0",
Unknown1: 0,
Unknown2: 0,
IsUnavailable: false,
Message1: "",
Message2: "",
IsInherited: false,
ChildNodes: []Node{},
},
`0x7fc5ff8e6170 <col:81, col:115> tvos 10.0 0 0 "" ""`: &AvailabilityAttr{
Addr: 0x7fc5ff8e6170,
Pos: NewPositionFromString("col:81, col:115"),
OS: "tvos",
Version: "10.0",
Unknown1: 0,
Unknown2: 0,
IsUnavailable: false,
Message1: "",
Message2: "",
IsInherited: false,
ChildNodes: []Node{},
},
`0x7fc5ff8e61d8 <col:81, col:115> ios 10.0 0 0 "" ""`: &AvailabilityAttr{
Addr: 0x7fc5ff8e61d8,
Pos: NewPositionFromString("col:81, col:115"),
OS: "ios",
Version: "10.0",
Unknown1: 0,
Unknown2: 0,
IsUnavailable: false,
Message1: "",
Message2: "",
IsInherited: false,
ChildNodes: []Node{},
},
`0x7fc5ff8f0e18 </usr/include/sys/cdefs.h:275:50, col:99> swift 0 0 0 Unavailable "Use snprintf instead." ""`: &AvailabilityAttr{
Addr: 0x7fc5ff8f0e18,
Pos: NewPositionFromString("/usr/include/sys/cdefs.h:275:50, col:99"),
OS: "swift",
Version: "0",
Unknown1: 0,
Unknown2: 0,
IsUnavailable: true,
Message1: "Use snprintf instead.",
Message2: "",
IsInherited: false,
ChildNodes: []Node{},
},
`0x7fc5ff8f1988 <line:275:50, col:99> swift 0 0 0 Unavailable "Use mkstemp(3) instead." ""`: &AvailabilityAttr{
Addr: 0x7fc5ff8f1988,
Pos: NewPositionFromString("line:275:50, col:99"),
OS: "swift",
Version: "0",
Unknown1: 0,
Unknown2: 0,
IsUnavailable: true,
Message1: "Use mkstemp(3) instead.",
Message2: "",
IsInherited: false,
ChildNodes: []Node{},
},
`0x104035438 </usr/include/AvailabilityInternal.h:14571:88, col:124> macosx 10.10 0 0 ""`: &AvailabilityAttr{
Addr: 0x104035438,
Pos: NewPositionFromString("/usr/include/AvailabilityInternal.h:14571:88, col:124"),
OS: "macosx",
Version: "10.10",
Unknown1: 0,
Unknown2: 0,
IsUnavailable: false,
Message1: "",
Message2: "",
IsInherited: false,
ChildNodes: []Node{},
},
`0x7f9bd588b1a8 </usr/include/gethostuuid.h:39:65, col:100> Inherited macos 10.5 0 0 "" ""`: &AvailabilityAttr{
Addr: 0x7f9bd588b1a8,
Pos: NewPositionFromString("/usr/include/gethostuuid.h:39:65, col:100"),
OS: "macos",
Version: "10.5",
Unknown1: 0,
Unknown2: 0,
IsUnavailable: false,
Message1: "",
Message2: "",
IsInherited: true,
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

50
ast/binary_operator.go Normal file
View File

@ -0,0 +1,50 @@
package ast
// BinaryOperator is type of binary operator
type BinaryOperator struct {
Addr Address
Pos Position
Type string
Type2 string
Operator string
ChildNodes []Node
}
func parseBinaryOperator(line string) *BinaryOperator {
groups := groupsFromRegex(
"<(?P<position>.*)> '(?P<type1>.*?)'(:'(?P<type2>.*?)')? '(?P<operator>.*?)'",
line,
)
return &BinaryOperator{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Type: groups["type1"],
Type2: groups["type2"],
Operator: groups["operator"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *BinaryOperator) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *BinaryOperator) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *BinaryOperator) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *BinaryOperator) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,27 @@
package ast
import (
"testing"
)
func TestBinaryOperator(t *testing.T) {
nodes := map[string]Node{
`0x7fca2d8070e0 <col:11, col:23> 'unsigned char' '='`: &BinaryOperator{
Addr: 0x7fca2d8070e0,
Pos: NewPositionFromString("col:11, col:23"),
Type: "unsigned char",
Operator: "=",
ChildNodes: []Node{},
},
`0x1ff95b8 <line:78:2, col:7> 'T_ENUM':'T_ENUM' '='`: &BinaryOperator{
Addr: 0x1ff95b8,
Pos: NewPositionFromString("line:78:2, col:7"),
Type: "T_ENUM",
Type2: "T_ENUM",
Operator: "=",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

View File

@ -0,0 +1,46 @@
package ast
// BlockCommandComment is a type of comment
type BlockCommandComment struct {
Addr Address
Pos Position
Name string
ChildNodes []Node
}
func parseBlockCommandComment(line string) *BlockCommandComment {
groups := groupsFromRegex(
`<(?P<position>.*)> Name="(?P<name>.*)"`,
line,
)
return &BlockCommandComment{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Name: groups["name"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *BlockCommandComment) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *BlockCommandComment) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *BlockCommandComment) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *BlockCommandComment) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,18 @@
package ast
import (
"testing"
)
func TestBlockCommandComment(t *testing.T) {
nodes := map[string]Node{
`0x1069fae60 <col:4, line:163:57> Name="abstract"`: &BlockCommandComment{
Addr: 0x1069fae60,
Pos: NewPositionFromString("col:4, line:163:57"),
Name: "abstract",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

44
ast/block_pointer_type.go Normal file
View File

@ -0,0 +1,44 @@
package ast
// BlockPointerType is block pointer type
type BlockPointerType struct {
Addr Address
Type string
ChildNodes []Node
}
func parseBlockPointerType(line string) *BlockPointerType {
groups := groupsFromRegex(
"'(?P<type>.*)'",
line,
)
return &BlockPointerType{
Addr: ParseAddress(groups["address"]),
Type: groups["type"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *BlockPointerType) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *BlockPointerType) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *BlockPointerType) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *BlockPointerType) Position() Position {
return Position{}
}

44
ast/break_stmt.go Normal file
View File

@ -0,0 +1,44 @@
package ast
// BreakStmt is node represent 'break'
type BreakStmt struct {
Addr Address
Pos Position
ChildNodes []Node
}
func parseBreakStmt(line string) *BreakStmt {
groups := groupsFromRegex(
"<(?P<position>.*)>",
line,
)
return &BreakStmt{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *BreakStmt) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *BreakStmt) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *BreakStmt) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *BreakStmt) Position() Position {
return n.Pos
}

17
ast/break_stmt_test.go Normal file
View File

@ -0,0 +1,17 @@
package ast
import (
"testing"
)
func TestBreakStmt(t *testing.T) {
nodes := map[string]Node{
`0x7fca2d8070e0 <col:11, col:23>`: &BreakStmt{
Addr: 0x7fca2d8070e0,
Pos: NewPositionFromString("col:11, col:23"),
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

44
ast/builtin_type.go Normal file
View File

@ -0,0 +1,44 @@
package ast
// BuiltinType is builtin type
type BuiltinType struct {
Addr Address
Type string
ChildNodes []Node
}
func parseBuiltinType(line string) *BuiltinType {
groups := groupsFromRegex(
"'(?P<type>.*?)'",
line,
)
return &BuiltinType{
Addr: ParseAddress(groups["address"]),
Type: groups["type"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *BuiltinType) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *BuiltinType) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *BuiltinType) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *BuiltinType) Position() Position {
return Position{}
}

22
ast/builtin_type_test.go Normal file
View File

@ -0,0 +1,22 @@
package ast
import (
"testing"
)
func TestBuiltinType(t *testing.T) {
nodes := map[string]Node{
`0x7f8a43023f40 '__int128'`: &BuiltinType{
Addr: 0x7f8a43023f40,
Type: "__int128",
ChildNodes: []Node{},
},
`0x7f8a43023ea0 'unsigned long long'`: &BuiltinType{
Addr: 0x7f8a43023ea0,
Type: "unsigned long long",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

56
ast/c_style_cast_expr.go Normal file
View File

@ -0,0 +1,56 @@
package ast
// CStyleCastExpr is expression.
type CStyleCastExpr struct {
Addr Address
Pos Position
Type string
Type2 string
Kind string
ChildNodes []Node
}
// CStyleCastExprNullToPointer - string of kind NullToPointer
var CStyleCastExprNullToPointer = "NullToPointer"
// CStyleCastExprToVoid - string of kind ToVoid
var CStyleCastExprToVoid = "ToVoid"
func parseCStyleCastExpr(line string) *CStyleCastExpr {
groups := groupsFromRegex(
"<(?P<position>.*)> '(?P<type1>.*?)'(:'(?P<type2>.*?)')? <(?P<kind>.*)>",
line,
)
return &CStyleCastExpr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Type: groups["type1"],
Type2: groups["type2"],
Kind: groups["kind"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *CStyleCastExpr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *CStyleCastExpr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *CStyleCastExpr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *CStyleCastExpr) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,27 @@
package ast
import (
"testing"
)
func TestCStyleCastExpr(t *testing.T) {
nodes := map[string]Node{
`0x7fddc18fb2e0 <col:50, col:56> 'char' <IntegralCast>`: &CStyleCastExpr{
Addr: 0x7fddc18fb2e0,
Pos: NewPositionFromString("col:50, col:56"),
Type: "char",
Kind: "IntegralCast",
ChildNodes: []Node{},
},
`0x2781518 <col:7, col:17> 'T_ENUM':'T_ENUM' <IntegralCast>`: &CStyleCastExpr{
Addr: 0x2781518,
Pos: NewPositionFromString("col:7, col:17"),
Type: "T_ENUM",
Type2: "T_ENUM",
Kind: "IntegralCast",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

46
ast/call_expr.go Normal file
View File

@ -0,0 +1,46 @@
package ast
// CallExpr is expression.
type CallExpr struct {
Addr Address
Pos Position
Type string
ChildNodes []Node
}
func parseCallExpr(line string) *CallExpr {
groups := groupsFromRegex(
"<(?P<position>.*)> '(?P<type>.*?)'",
line,
)
return &CallExpr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Type: groups["type"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *CallExpr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *CallExpr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *CallExpr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *CallExpr) Position() Position {
return n.Pos
}

24
ast/call_expr_test.go Normal file
View File

@ -0,0 +1,24 @@
package ast
import (
"testing"
)
func TestCallExpr(t *testing.T) {
nodes := map[string]Node{
`0x7f9bf3033240 <col:11, col:25> 'int'`: &CallExpr{
Addr: 0x7f9bf3033240,
Pos: NewPositionFromString("col:11, col:25"),
Type: "int",
ChildNodes: []Node{},
},
`0x7f9bf3035c20 <line:7:4, col:64> 'int'`: &CallExpr{
Addr: 0x7f9bf3035c20,
Pos: NewPositionFromString("line:7:4, col:64"),
Type: "int",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

41
ast/case_stmt.go Normal file
View File

@ -0,0 +1,41 @@
package ast
// CaseStmt is node represent 'case'
type CaseStmt struct {
Addr Address
Pos Position
ChildNodes []Node
}
func parseCaseStmt(line string) *CaseStmt {
groups := groupsFromRegex(`<(?P<position>.*)>`, line)
return &CaseStmt{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *CaseStmt) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *CaseStmt) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *CaseStmt) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *CaseStmt) Position() Position {
return n.Pos
}

17
ast/case_stmt_test.go Normal file
View File

@ -0,0 +1,17 @@
package ast
import (
"testing"
)
func TestCaseStmt(t *testing.T) {
nodes := map[string]Node{
`0x7fc8b5094688 <line:11:5, line:12:21>`: &CaseStmt{
Addr: 0x7fc8b5094688,
Pos: NewPositionFromString("line:11:5, line:12:21"),
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

52
ast/character_literal.go Normal file
View File

@ -0,0 +1,52 @@
package ast
import (
"github.com/elliotchance/c2go/util"
)
// CharacterLiteral is type of character literal
type CharacterLiteral struct {
Addr Address
Pos Position
Type string
Value int
ChildNodes []Node
}
func parseCharacterLiteral(line string) *CharacterLiteral {
groups := groupsFromRegex(
"<(?P<position>.*)> '(?P<type>.*?)' (?P<value>\\d+)",
line,
)
return &CharacterLiteral{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Type: groups["type"],
Value: util.Atoi(groups["value"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *CharacterLiteral) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *CharacterLiteral) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *CharacterLiteral) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *CharacterLiteral) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,19 @@
package ast
import (
"testing"
)
func TestCharacterLiteral(t *testing.T) {
nodes := map[string]Node{
`0x7f980b858308 <col:62> 'int' 10`: &CharacterLiteral{
Addr: 0x7f980b858308,
Pos: NewPositionFromString("col:62"),
Type: "int",
Value: 10,
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

View File

@ -0,0 +1,56 @@
package ast
// CompoundAssignOperator is type of compound assign operator
type CompoundAssignOperator struct {
Addr Address
Pos Position
Type string
Opcode string
ComputationLHSType string
ComputationResultType string
ChildNodes []Node
}
func parseCompoundAssignOperator(line string) *CompoundAssignOperator {
groups := groupsFromRegex(
`<(?P<position>.*)>
'(?P<type>.+?)'
'(?P<opcode>.+?)'
ComputeLHSTy='(?P<clhstype>.+?)'
ComputeResultTy='(?P<crestype>.+?)'`,
line,
)
return &CompoundAssignOperator{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Type: groups["type"],
Opcode: groups["opcode"],
ComputationLHSType: groups["clhstype"],
ComputationResultType: groups["crestype"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *CompoundAssignOperator) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *CompoundAssignOperator) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *CompoundAssignOperator) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *CompoundAssignOperator) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,21 @@
package ast
import (
"testing"
)
func TestCompoundAssignOperator(t *testing.T) {
nodes := map[string]Node{
`0x2dc5758 <line:5:2, col:7> 'int' '+=' ComputeLHSTy='int' ComputeResultTy='int'`: &CompoundAssignOperator{
Addr: 0x2dc5758,
Pos: NewPositionFromString("line:5:2, col:7"),
Type: "int",
Opcode: "+=",
ComputationLHSType: "int",
ComputationResultType: "int",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

View File

@ -0,0 +1,48 @@
package ast
// CompoundLiteralExpr C99 6.5.2.5
type CompoundLiteralExpr struct {
Addr Address
Pos Position
Type1 string
Type2 string
ChildNodes []Node
}
func parseCompoundLiteralExpr(line string) *CompoundLiteralExpr {
groups := groupsFromRegex(
`<(?P<position>.*)> '(?P<type1>.*?)'(:'(?P<type2>.*?)')? lvalue`,
line,
)
return &CompoundLiteralExpr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Type1: groups["type1"],
Type2: groups["type2"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *CompoundLiteralExpr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *CompoundLiteralExpr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *CompoundLiteralExpr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *CompoundLiteralExpr) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,19 @@
package ast
import (
"testing"
)
func TestCompoundLiteralExpr(t *testing.T) {
nodes := map[string]Node{
`0x5575acce81f0 <col:21, col:40> 'struct node':'struct node' lvalue`: &CompoundLiteralExpr{
Addr: 0x5575acce81f0,
Pos: NewPositionFromString("col:21, col:40"),
Type1: "struct node",
Type2: "struct node",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

48
ast/compound_stmt.go Normal file
View File

@ -0,0 +1,48 @@
package ast
// CompoundStmt is node represents a compound of nodes
type CompoundStmt struct {
Addr Address
Pos Position
ChildNodes []Node
// TODO: remove this
BelongsToSwitch bool
}
func parseCompoundStmt(line string) *CompoundStmt {
groups := groupsFromRegex(
"<(?P<position>.*)>",
line,
)
return &CompoundStmt{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
ChildNodes: []Node{},
BelongsToSwitch: false,
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *CompoundStmt) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *CompoundStmt) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *CompoundStmt) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *CompoundStmt) Position() Position {
return n.Pos
}

22
ast/compound_stmt_test.go Normal file
View File

@ -0,0 +1,22 @@
package ast
import (
"testing"
)
func TestCompoundStmt(t *testing.T) {
nodes := map[string]Node{
`0x7fbd0f014f18 <col:54, line:358:1>`: &CompoundStmt{
Addr: 0x7fbd0f014f18,
Pos: NewPositionFromString("col:54, line:358:1"),
ChildNodes: []Node{},
},
`0x7fbd0f8360b8 <line:4:1, line:13:1>`: &CompoundStmt{
Addr: 0x7fbd0f8360b8,
Pos: NewPositionFromString("line:4:1, line:13:1"),
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

View File

@ -0,0 +1,46 @@
package ast
// ConditionalOperator is type of condition operator
type ConditionalOperator struct {
Addr Address
Pos Position
Type string
ChildNodes []Node
}
func parseConditionalOperator(line string) *ConditionalOperator {
groups := groupsFromRegex(
`<(?P<position>.*)> '(?P<type>.*?)'`,
line,
)
return &ConditionalOperator{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Type: groups["type"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *ConditionalOperator) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *ConditionalOperator) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *ConditionalOperator) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *ConditionalOperator) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,18 @@
package ast
import (
"testing"
)
func TestConditionalOperator(t *testing.T) {
nodes := map[string]Node{
`0x7fc6ae0bc678 <col:6, col:89> 'void'`: &ConditionalOperator{
Addr: 0x7fc6ae0bc678,
Pos: NewPositionFromString("col:6, col:89"),
Type: "void",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

47
ast/const_attr.go Normal file
View File

@ -0,0 +1,47 @@
package ast
// ConstAttr is a type of attribute that is optionally attached to a variable
// or struct field definition.
type ConstAttr struct {
Addr Address
Pos Position
Tags string
ChildNodes []Node
}
func parseConstAttr(line string) *ConstAttr {
groups := groupsFromRegex(
"<(?P<position>.*)>(?P<tags>.*)",
line,
)
return &ConstAttr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Tags: groups["tags"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *ConstAttr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *ConstAttr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *ConstAttr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *ConstAttr) Position() Position {
return n.Pos
}

18
ast/const_attr_test.go Normal file
View File

@ -0,0 +1,18 @@
package ast
import (
"testing"
)
func TestConstAttr(t *testing.T) {
nodes := map[string]Node{
`0x7fa3b88bbb38 <line:4:1, line:13:1>foo`: &ConstAttr{
Addr: 0x7fa3b88bbb38,
Pos: NewPositionFromString("line:4:1, line:13:1"),
Tags: "foo",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

View File

@ -0,0 +1,50 @@
package ast
import (
"github.com/elliotchance/c2go/util"
)
// ConstantArrayType is constant array type
type ConstantArrayType struct {
Addr Address
Type string
Size int
ChildNodes []Node
}
func parseConstantArrayType(line string) *ConstantArrayType {
groups := groupsFromRegex(
"'(?P<type>.*)' (?P<size>\\d+)",
line,
)
return &ConstantArrayType{
Addr: ParseAddress(groups["address"]),
Type: groups["type"],
Size: util.Atoi(groups["size"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *ConstantArrayType) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *ConstantArrayType) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *ConstantArrayType) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *ConstantArrayType) Position() Position {
return Position{}
}

View File

@ -0,0 +1,24 @@
package ast
import (
"testing"
)
func TestConstantArrayType(t *testing.T) {
nodes := map[string]Node{
`0x7f94ad016a40 'struct __va_list_tag [1]' 1 `: &ConstantArrayType{
Addr: 0x7f94ad016a40,
Type: "struct __va_list_tag [1]",
Size: 1,
ChildNodes: []Node{},
},
`0x7f8c5f059d20 'char [37]' 37 `: &ConstantArrayType{
Addr: 0x7f8c5f059d20,
Type: "char [37]",
Size: 37,
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

44
ast/continue_stmt.go Normal file
View File

@ -0,0 +1,44 @@
package ast
// ContinueStmt is node represent 'continue'
type ContinueStmt struct {
Addr Address
Pos Position
ChildNodes []Node
}
func parseContinueStmt(line string) *ContinueStmt {
groups := groupsFromRegex(
"<(?P<position>.*)>",
line,
)
return &ContinueStmt{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *ContinueStmt) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *ContinueStmt) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *ContinueStmt) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *ContinueStmt) Position() Position {
return n.Pos
}

17
ast/continue_stmt_test.go Normal file
View File

@ -0,0 +1,17 @@
package ast
import (
"testing"
)
func TestContinueStmt(t *testing.T) {
nodes := map[string]Node{
`0x1e044e0 <col:20>`: &ContinueStmt{
Addr: 0x1e044e0,
Pos: NewPositionFromString("col:20"),
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

44
ast/decayed_type.go Normal file
View File

@ -0,0 +1,44 @@
package ast
// DecayedType is pointer type
type DecayedType struct {
Addr Address
Type string
ChildNodes []Node
}
func parseDecayedType(line string) *DecayedType {
groups := groupsFromRegex(
"'(?P<type>.*)' sugar",
line,
)
return &DecayedType{
Addr: ParseAddress(groups["address"]),
Type: groups["type"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *DecayedType) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *DecayedType) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *DecayedType) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *DecayedType) Position() Position {
return Position{}
}

17
ast/decayed_type_test.go Normal file
View File

@ -0,0 +1,17 @@
package ast
import (
"testing"
)
func TestDecayedType(t *testing.T) {
nodes := map[string]Node{
`0x7f1234567890 'struct __va_list_tag *' sugar`: &DecayedType{
Addr: 0x7f1234567890,
Type: "struct __va_list_tag *",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

71
ast/decl_ref_expr.go Normal file
View File

@ -0,0 +1,71 @@
package ast
// DeclRefExpr is expression.
type DeclRefExpr struct {
Addr Address
Pos Position
Type string
Type1 string
Lvalue bool
For string
Address2 string
Name string
Type2 string
Type3 string
ChildNodes []Node
}
func parseDeclRefExpr(line string) *DeclRefExpr {
groups := groupsFromRegex(
`<(?P<position>.*)>
'(?P<type>.*?)'(:'(?P<type1>.*?)')?
.*?
(?P<lvalue> lvalue)?
(?P<for>\w+)
(?P<address2>[0-9a-fx]+)
'(?P<name>.*?)'
'(?P<type2>.*?)'(:'(?P<type3>.*?)')?
`,
line,
)
return &DeclRefExpr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Type: groups["type"],
Type1: groups["type1"],
Lvalue: len(groups["lvalue"]) > 0,
For: groups["for"],
Address2: groups["address2"],
Name: groups["name"],
Type2: groups["type2"],
Type3: groups["type3"],
ChildNodes: []Node{},
}
}
// FunctionDeclRefExpr - value of DeclRefExpr.For for function
var FunctionDeclRefExpr = "Function"
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *DeclRefExpr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *DeclRefExpr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *DeclRefExpr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *DeclRefExpr) Position() Position {
return n.Pos
}

77
ast/decl_ref_expr_test.go Normal file
View File

@ -0,0 +1,77 @@
package ast
import (
"testing"
)
func TestDeclRefExpr(t *testing.T) {
nodes := map[string]Node{
`0x7fc972064460 <col:8> 'FILE *' lvalue ParmVar 0x7fc9720642d0 '_p' 'FILE *'`: &DeclRefExpr{
Addr: 0x7fc972064460,
Pos: NewPositionFromString("col:8"),
Type: "FILE *",
Type1: "",
Lvalue: true,
For: "ParmVar",
Address2: "0x7fc9720642d0",
Name: "_p",
Type2: "FILE *",
Type3: "",
ChildNodes: []Node{},
},
`0x7fc97206a958 <col:11> 'int (int, FILE *)' Function 0x7fc972064198 '__swbuf' 'int (int, FILE *)'`: &DeclRefExpr{
Addr: 0x7fc97206a958,
Pos: NewPositionFromString("col:11"),
Type: "int (int, FILE *)",
Type1: "",
Lvalue: false,
For: "Function",
Address2: "0x7fc972064198",
Name: "__swbuf",
Type2: "int (int, FILE *)",
Type3: "",
ChildNodes: []Node{},
},
`0x7fa36680f170 <col:19> 'struct programming':'struct programming' lvalue Var 0x7fa36680dc20 'variable' 'struct programming':'struct programming'`: &DeclRefExpr{
Addr: 0x7fa36680f170,
Pos: NewPositionFromString("col:19"),
Type: "struct programming",
Type1: "struct programming",
Lvalue: true,
For: "Var",
Address2: "0x7fa36680dc20",
Name: "variable",
Type2: "struct programming",
Type3: "struct programming",
ChildNodes: []Node{},
},
`0x35cb438 <col:13> 'int' EnumConstant 0x35ca300 'Jan' 'int'`: &DeclRefExpr{
Addr: 0x35cb438,
Pos: NewPositionFromString("col:13"),
Type: "int",
Type1: "",
Lvalue: false,
For: "EnumConstant",
Address2: "0x35ca300",
Name: "Jan",
Type2: "int",
Type3: "",
ChildNodes: []Node{},
},
`0x1ff8770 <col:33> 'T_ENUM':'T_ENUM' lvalue Var 0x1ff8600 'cc' 'T_ENUM':'T_ENUM'`: &DeclRefExpr{
Addr: 0x1ff8770,
Pos: NewPositionFromString("col:33"),
Type: "T_ENUM",
Type1: "T_ENUM",
Lvalue: true,
For: "Var",
Address2: "0x1ff8600",
Name: "cc",
Type2: "T_ENUM",
Type3: "T_ENUM",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

44
ast/decl_stmt.go Normal file
View File

@ -0,0 +1,44 @@
package ast
// DeclStmt is node represents a declaration in a statement list.
type DeclStmt struct {
Addr Address
Pos Position
ChildNodes []Node
}
func parseDeclStmt(line string) *DeclStmt {
groups := groupsFromRegex(
"<(?P<position>.*)>",
line,
)
return &DeclStmt{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *DeclStmt) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *DeclStmt) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *DeclStmt) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *DeclStmt) Position() Position {
return n.Pos
}

17
ast/decl_stmt_test.go Normal file
View File

@ -0,0 +1,17 @@
package ast
import (
"testing"
)
func TestDeclStmt(t *testing.T) {
nodes := map[string]Node{
`0x7fb791846e80 <line:11:4, col:31>`: &DeclStmt{
Addr: 0x7fb791846e80,
Pos: NewPositionFromString("line:11:4, col:31"),
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

41
ast/default_stmt.go Normal file
View File

@ -0,0 +1,41 @@
package ast
// DefaultStmt is node represent 'default'
type DefaultStmt struct {
Addr Address
Pos Position
ChildNodes []Node
}
func parseDefaultStmt(line string) *DefaultStmt {
groups := groupsFromRegex(`<(?P<position>.*)>`, line)
return &DefaultStmt{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *DefaultStmt) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *DefaultStmt) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *DefaultStmt) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *DefaultStmt) Position() Position {
return n.Pos
}

17
ast/default_stmt_test.go Normal file
View File

@ -0,0 +1,17 @@
package ast
import (
"testing"
)
func TestDefaultStmt(t *testing.T) {
nodes := map[string]Node{
`0x7f951308bfb0 <line:17:5, line:18:34>`: &DefaultStmt{
Addr: 0x7f951308bfb0,
Pos: NewPositionFromString("line:17:5, line:18:34"),
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

51
ast/deprecated_attr.go Normal file
View File

@ -0,0 +1,51 @@
package ast
// DeprecatedAttr is a type of attribute that is optionally attached to a variable
// or struct field definition.
type DeprecatedAttr struct {
Addr Address
Pos Position
Message1 string
Message2 string
IsInherited bool
ChildNodes []Node
}
func parseDeprecatedAttr(line string) *DeprecatedAttr {
groups := groupsFromRegex(
`<(?P<position>.*)>(?P<inherited> Inherited)? "(?P<message1>.*?)"(?P<message2> ".*?")?`,
line,
)
return &DeprecatedAttr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Message1: removeQuotes(groups["message1"]),
Message2: removeQuotes(groups["message2"]),
IsInherited: len(groups["inherited"]) > 0,
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *DeprecatedAttr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *DeprecatedAttr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *DeprecatedAttr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *DeprecatedAttr) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,36 @@
package ast
import (
"testing"
)
func TestDeprecatedAttr(t *testing.T) {
nodes := map[string]Node{
`0x7fec4b0ab9c0 <line:180:48, col:63> "This function is provided for compatibility reasons only. Due to security concerns inherent in the design of tempnam(3), it is highly recommended that you use mkstemp(3) instead." ""`: &DeprecatedAttr{
Addr: 0x7fec4b0ab9c0,
Pos: NewPositionFromString("line:180:48, col:63"),
Message1: "This function is provided for compatibility reasons only. Due to security concerns inherent in the design of tempnam(3), it is highly recommended that you use mkstemp(3) instead.",
Message2: "",
IsInherited: false,
ChildNodes: []Node{},
},
`0xb75d00 <line:1107:12> "This function or variable may be unsafe. Consider using _snwprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details." ""`: &DeprecatedAttr{
Addr: 0xb75d00,
Pos: NewPositionFromString("line:1107:12"),
Message1: "This function or variable may be unsafe. Consider using _snwprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.",
Message2: "",
IsInherited: false,
ChildNodes: []Node{},
},
`0xb75d00 <line:1107:12> Inherited "This function or variable may be unsafe. Consider using _snwprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details." ""`: &DeprecatedAttr{
Addr: 0xb75d00,
Pos: NewPositionFromString("line:1107:12"),
Message1: "This function or variable may be unsafe. Consider using _snwprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.",
Message2: "",
IsInherited: true,
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

View File

@ -0,0 +1,45 @@
package ast
// DisableTailCallsAttr is a type of attribute that is optionally attached to a variable
// or struct field definition.
type DisableTailCallsAttr struct {
Addr Address
Pos Position
ChildNodes []Node
}
func parseDisableTailCallsAttr(line string) *DisableTailCallsAttr {
groups := groupsFromRegex(
"<(?P<position>.*)>",
line,
)
return &DisableTailCallsAttr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *DisableTailCallsAttr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *DisableTailCallsAttr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *DisableTailCallsAttr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *DisableTailCallsAttr) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,17 @@
package ast
import (
"testing"
)
func TestDisableTailCallsAttr(t *testing.T) {
nodes := map[string]Node{
`0x7fc8fa094558 <col:107> `: &DisableTailCallsAttr{
Addr: 0x7fc8fa094558,
Pos: NewPositionFromString("col:107"),
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

44
ast/do_stmt.go Normal file
View File

@ -0,0 +1,44 @@
package ast
// DoStmt is node represent 'do'
type DoStmt struct {
Addr Address
Pos Position
ChildNodes []Node
}
func parseDoStmt(line string) *DoStmt {
groups := groupsFromRegex(
"<(?P<position>.*)>",
line,
)
return &DoStmt{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *DoStmt) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *DoStmt) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *DoStmt) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *DoStmt) Position() Position {
return n.Pos
}

17
ast/do_stmt_test.go Normal file
View File

@ -0,0 +1,17 @@
package ast
import (
"testing"
)
func TestDoStmt(t *testing.T) {
nodes := map[string]Node{
`0x7ff36d0a0938 <line:11:5, line:14:23>`: &DoStmt{
Addr: 0x7ff36d0a0938,
Pos: NewPositionFromString("line:11:5, line:14:23"),
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

46
ast/elaborated_type.go Normal file
View File

@ -0,0 +1,46 @@
package ast
// ElaboratedType is elaborated type
type ElaboratedType struct {
Addr Address
Type string
Tags string
ChildNodes []Node
}
func parseElaboratedType(line string) *ElaboratedType {
groups := groupsFromRegex(
"'(?P<type>.*?)' (?P<tags>.+)",
line,
)
return &ElaboratedType{
Addr: ParseAddress(groups["address"]),
Type: groups["type"],
Tags: groups["tags"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *ElaboratedType) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *ElaboratedType) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *ElaboratedType) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *ElaboratedType) Position() Position {
return Position{}
}

View File

@ -0,0 +1,18 @@
package ast
import (
"testing"
)
func TestElaboratedType(t *testing.T) {
nodes := map[string]Node{
`0x7f873686c120 'union __mbstate_t' sugar`: &ElaboratedType{
Addr: 0x7f873686c120,
Type: "union __mbstate_t",
Tags: "sugar",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

47
ast/empty_decl.go Normal file
View File

@ -0,0 +1,47 @@
package ast
// EmptyDecl - element of AST
type EmptyDecl struct {
Addr Address
Pos Position
Position2 Position
ChildNodes []Node
}
func parseEmptyDecl(line string) *EmptyDecl {
groups := groupsFromRegex(
`<(?P<position>.*)>
( (?P<position2>.*))?`,
line,
)
return &EmptyDecl{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Position2: NewPositionFromString(groups["position2"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *EmptyDecl) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *EmptyDecl) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *EmptyDecl) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *EmptyDecl) Position() Position {
return n.Pos
}

18
ast/empty_decl_test.go Normal file
View File

@ -0,0 +1,18 @@
package ast
import (
"testing"
)
func TestEmptyDecl(t *testing.T) {
nodes := map[string]Node{
`0x480bec8 <col:13> col:13`: &EmptyDecl{
Addr: 0x480bec8,
Pos: NewPositionFromString("col:13"),
Position2: NewPositionFromString("col:13"),
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

44
ast/enum.go Normal file
View File

@ -0,0 +1,44 @@
package ast
// Enum struct
type Enum struct {
Addr Address
Name string
ChildNodes []Node
}
func parseEnum(line string) *Enum {
groups := groupsFromRegex(
"'(?P<name>.*?)'",
line,
)
return &Enum{
Addr: ParseAddress(groups["address"]),
Name: groups["name"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *Enum) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *Enum) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *Enum) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *Enum) Position() Position {
return Position{}
}

56
ast/enum_constant_decl.go Normal file
View File

@ -0,0 +1,56 @@
package ast
// EnumConstantDecl is node represents a enum constant declaration.
type EnumConstantDecl struct {
Addr Address
Pos Position
Position2 string
Referenced bool
Name string
Type string
ChildNodes []Node
}
func parseEnumConstantDecl(line string) *EnumConstantDecl {
groups := groupsFromRegex(
`<(?P<position>.*)>
( (?P<position2>[^ ]+))?
( (?P<referenced>referenced))?
(?P<name>.+)
'(?P<type>.+?)'`,
line,
)
return &EnumConstantDecl{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Position2: groups["position2"],
Referenced: len(groups["referenced"]) > 0,
Name: groups["name"],
Type: groups["type"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *EnumConstantDecl) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *EnumConstantDecl) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *EnumConstantDecl) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *EnumConstantDecl) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,30 @@
package ast
import (
"testing"
)
func TestEnumConstantDecl(t *testing.T) {
nodes := map[string]Node{
`0x1660db0 <line:185:3> __codecvt_noconv 'int'`: &EnumConstantDecl{
Addr: 0x1660db0,
Pos: NewPositionFromString("line:185:3"),
Position2: "",
Referenced: false,
Name: "__codecvt_noconv",
Type: "int",
ChildNodes: []Node{},
},
`0x3c77ba8 <line:59:3, col:65> col:3 referenced _ISalnum 'int'`: &EnumConstantDecl{
Addr: 0x3c77ba8,
Pos: NewPositionFromString("line:59:3, col:65"),
Position2: "col:3",
Referenced: true,
Name: "_ISalnum",
Type: "int",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

52
ast/enum_decl.go Normal file
View File

@ -0,0 +1,52 @@
package ast
import (
"strings"
)
// EnumDecl is node represents a enum declaration.
type EnumDecl struct {
Addr Address
Pos Position
Position2 string
Name string
ChildNodes []Node
}
func parseEnumDecl(line string) *EnumDecl {
groups := groupsFromRegex(
`(?:prev (?P<prev>0x[0-9a-f]+) )?<(?P<position>.*)>(?P<position2> .+:\d+)?(?P<name>.*)`,
line,
)
return &EnumDecl{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Position2: groups["position2"],
Name: strings.TrimSpace(groups["name"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *EnumDecl) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *EnumDecl) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *EnumDecl) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *EnumDecl) Position() Position {
return n.Pos
}

26
ast/enum_decl_test.go Normal file
View File

@ -0,0 +1,26 @@
package ast
import (
"testing"
)
func TestEnumDecl(t *testing.T) {
nodes := map[string]Node{
`0x22a6c80 <line:180:1, line:186:1> __codecvt_result`: &EnumDecl{
Addr: 0x22a6c80,
Pos: NewPositionFromString("line:180:1, line:186:1"),
Position2: "",
Name: "__codecvt_result",
ChildNodes: []Node{},
},
`0x32fb5a0 <enum.c:3:1, col:45> col:6 week`: &EnumDecl{
Addr: 0x32fb5a0,
Pos: NewPositionFromString("enum.c:3:1, col:45"),
Position2: " col:6",
Name: "week",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

17
ast/enum_test.go Normal file
View File

@ -0,0 +1,17 @@
package ast
import (
"testing"
)
func TestEnum(t *testing.T) {
nodes := map[string]Node{
`0x7f980b858308 'foo'`: &Enum{
Addr: 0x7f980b858308,
Name: "foo",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

44
ast/enum_type.go Normal file
View File

@ -0,0 +1,44 @@
package ast
// EnumType is enum type
type EnumType struct {
Addr Address
Name string
ChildNodes []Node
}
func parseEnumType(line string) *EnumType {
groups := groupsFromRegex(
"'(?P<name>.*?)'",
line,
)
return &EnumType{
Addr: ParseAddress(groups["address"]),
Name: groups["name"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *EnumType) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *EnumType) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *EnumType) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *EnumType) Position() Position {
return Position{}
}

17
ast/enum_type_test.go Normal file
View File

@ -0,0 +1,17 @@
package ast
import (
"testing"
)
func TestEnumType(t *testing.T) {
nodes := map[string]Node{
`0x7f980b858309 'foo'`: &EnumType{
Addr: 0x7f980b858309,
Name: "foo",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

46
ast/field.go Normal file
View File

@ -0,0 +1,46 @@
package ast
// Field struct
type Field struct {
Addr Address
String1 string
String2 string
ChildNodes []Node
}
func parseField(line string) *Field {
groups := groupsFromRegex(
`'(?P<string1>.*?)' '(?P<string2>.*?)'`,
line,
)
return &Field{
Addr: ParseAddress(groups["address"]),
String1: groups["string1"],
String2: groups["string2"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *Field) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *Field) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *Field) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *Field) Position() Position {
return Position{}
}

67
ast/field_decl.go Normal file
View File

@ -0,0 +1,67 @@
package ast
import (
"strings"
)
// FieldDecl is node represents a field declaration.
type FieldDecl struct {
Addr Address
Pos Position
Position2 string
Name string
Type string
Type2 string
Implicit bool
Referenced bool
ChildNodes []Node
}
func parseFieldDecl(line string) *FieldDecl {
groups := groupsFromRegex(
`<(?P<position>.*)>
(?P<position2> col:\d+| line:\d+:\d+)?
(?P<implicit> implicit)?
(?P<referenced> referenced)?
(?P<name> \w+?)?
'(?P<type>.+?)'
(:'(?P<type2>.*?)')?
`,
line,
)
return &FieldDecl{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Position2: strings.TrimSpace(groups["position2"]),
Name: strings.TrimSpace(groups["name"]),
Type: groups["type"],
Type2: groups["type2"],
Implicit: len(groups["implicit"]) > 0,
Referenced: len(groups["referenced"]) > 0,
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *FieldDecl) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *FieldDecl) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *FieldDecl) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *FieldDecl) Position() Position {
return n.Pos
}

122
ast/field_decl_test.go Normal file
View File

@ -0,0 +1,122 @@
package ast
import (
"testing"
)
func TestFieldDecl(t *testing.T) {
nodes := map[string]Node{
`0x7fef510c4848 <line:141:2, col:6> col:6 _ur 'int'`: &FieldDecl{
Addr: 0x7fef510c4848,
Pos: NewPositionFromString("line:141:2, col:6"),
Position2: "col:6",
Name: "_ur",
Type: "int",
Type2: "",
Implicit: false,
Referenced: false,
ChildNodes: []Node{},
},
`0x7fef510c46f8 <line:139:2, col:16> col:16 _ub 'struct __sbuf':'struct __sbuf'`: &FieldDecl{
Addr: 0x7fef510c46f8,
Pos: NewPositionFromString("line:139:2, col:16"),
Position2: "col:16",
Name: "_ub",
Type: "struct __sbuf",
Type2: "struct __sbuf",
Implicit: false,
Referenced: false,
ChildNodes: []Node{},
},
`0x7fef510c3fe0 <line:134:2, col:19> col:19 _read 'int (* _Nullable)(void *, char *, int)':'int (*)(void *, char *, int)'`: &FieldDecl{
Addr: 0x7fef510c3fe0,
Pos: NewPositionFromString("line:134:2, col:19"),
Position2: "col:19",
Name: "_read",
Type: "int (* _Nullable)(void *, char *, int)",
Type2: "int (*)(void *, char *, int)",
Implicit: false,
Referenced: false,
ChildNodes: []Node{},
},
`0x7fef51073a60 <line:105:2, col:40> col:40 __cleanup_stack 'struct __darwin_pthread_handler_rec *'`: &FieldDecl{
Addr: 0x7fef51073a60,
Pos: NewPositionFromString("line:105:2, col:40"),
Position2: "col:40",
Name: "__cleanup_stack",
Type: "struct __darwin_pthread_handler_rec *",
Type2: "",
Implicit: false,
Referenced: false,
ChildNodes: []Node{},
},
`0x7fef510738e8 <line:100:2, col:43> col:7 __opaque 'char [16]'`: &FieldDecl{
Addr: 0x7fef510738e8,
Pos: NewPositionFromString("line:100:2, col:43"),
Position2: "col:7",
Name: "__opaque",
Type: "char [16]",
Type2: "",
Implicit: false,
Referenced: false,
ChildNodes: []Node{},
},
`0x7fe9f5072268 <line:129:2, col:6> col:6 referenced _lbfsize 'int'`: &FieldDecl{
Addr: 0x7fe9f5072268,
Pos: NewPositionFromString("line:129:2, col:6"),
Position2: "col:6",
Name: "_lbfsize",
Type: "int",
Type2: "",
Implicit: false,
Referenced: true,
ChildNodes: []Node{},
},
`0x7f9bc9083d00 <line:91:5, line:97:8> line:91:5 'unsigned short'`: &FieldDecl{
Addr: 0x7f9bc9083d00,
Pos: NewPositionFromString("line:91:5, line:97:8"),
Position2: "line:91:5",
Name: "",
Type: "unsigned short",
Type2: "",
Implicit: false,
Referenced: false,
ChildNodes: []Node{},
},
`0x30363a0 <col:18, col:29> __val 'int [2]'`: &FieldDecl{
Addr: 0x30363a0,
Pos: NewPositionFromString("col:18, col:29"),
Position2: "",
Name: "__val",
Type: "int [2]",
Type2: "",
Implicit: false,
Referenced: false,
ChildNodes: []Node{},
},
`0x17aeac0 <line:3:9> col:9 implicit referenced 'struct vec3d_t::(anonymous at main.c:3:9)'`: &FieldDecl{
Addr: 0x17aeac0,
Pos: NewPositionFromString("line:3:9"),
Position2: "col:9",
Name: "",
Type: "struct vec3d_t::(anonymous at main.c:3:9)",
Type2: "",
Implicit: true,
Referenced: true,
ChildNodes: []Node{},
},
`0x56498bf52160 <line:269:5, col:21> col:21 type 'enum __pid_type':'enum __pid_type'`: &FieldDecl{
Addr: 0x56498bf52160,
Pos: NewPositionFromString("line:269:5, col:21"),
Position2: "col:21",
Name: "type",
Type: "enum __pid_type",
Type2: "enum __pid_type",
Implicit: false,
Referenced: false,
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

18
ast/field_test.go Normal file
View File

@ -0,0 +1,18 @@
package ast
import (
"testing"
)
func TestField(t *testing.T) {
nodes := map[string]Node{
`0x44159a0 '' 'union sigcontext::(anonymous at /usr/include/x86_64-linux-gnu/bits/sigcontext.h:165:17)'`: &Field{
Addr: 0x44159a0,
String1: "",
String2: "union sigcontext::(anonymous at /usr/include/x86_64-linux-gnu/bits/sigcontext.h:165:17)",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

114
ast/floating_literal.go Normal file
View File

@ -0,0 +1,114 @@
package ast
import (
"errors"
"fmt"
"reflect"
"github.com/elliotchance/c2go/cc"
)
// FloatingLiteral is type of float literal
type FloatingLiteral struct {
Addr Address
Pos Position
Type string
Value float64
ChildNodes []Node
}
func parseFloatingLiteral(line string) *FloatingLiteral {
groups := groupsFromRegex(
"<(?P<position>.*)> '(?P<type>.*?)' (?P<value>.+)",
line,
)
return &FloatingLiteral{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Type: groups["type"],
Value: atof(groups["value"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *FloatingLiteral) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *FloatingLiteral) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *FloatingLiteral) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *FloatingLiteral) Position() Position {
return n.Pos
}
// FloatingLiteralError represents one instance of an error where the exact
// floating point value of a FloatingLiteral could not be determined from the
// original source. See RepairFloatingLiteralsFromSource for a full explanation.
type FloatingLiteralError struct {
Node *FloatingLiteral
Err error
}
// RepairFloatingLiteralsFromSource finds the exact values of floating literals
// by reading their values directly from the preprocessed source.
//
// The clang AST only serializes floating point values in scientific notation
// with 7 significant digits. This is not enough when dealing with precise
// numbers.
//
// The only solution is to read the original floating literal from the source
// code. We can do this by using the positional information on the node.
//
// If the floating literal cannot be resolved for any reason the original value
// will remain. This function will return all errors encountered.
func RepairFloatingLiteralsFromSource(rootNode Node, preprocessedFile string) []FloatingLiteralError {
errs := []FloatingLiteralError{}
floatingLiteralNodes :=
GetAllNodesOfType(rootNode, reflect.TypeOf((*FloatingLiteral)(nil)))
for _, node := range floatingLiteralNodes {
fNode := node.(*FloatingLiteral)
// Use the node position to retrieve the original line from the
// preprocessed source.
pos := node.Position()
line, err :=
cc.GetLineFromPreprocessedFile(preprocessedFile, pos.File, pos.Line)
// If there was a problem reading the line we should raise a warning and
// use the value we have. Hopefully that will be an accurate enough
// representation.
if err != nil {
errs = append(errs, FloatingLiteralError{
Node: fNode,
Err: err,
})
}
// Extract the exact value from the line.
if pos.Column-1 >= len(line) {
errs = append(errs, FloatingLiteralError{
Node: fNode,
Err: errors.New("cannot get exact value exact value"),
})
} else {
fmt.Sscan(line[pos.Column-1:], &fNode.Value)
}
}
return errs
}

View File

@ -0,0 +1,26 @@
package ast
import (
"testing"
)
func TestFloatingLiteral(t *testing.T) {
nodes := map[string]Node{
`0x7febe106f5e8 <col:24> 'double' 1.230000e+00`: &FloatingLiteral{
Addr: 0x7febe106f5e8,
Pos: NewPositionFromString("col:24"),
Type: "double",
Value: 1.23,
ChildNodes: []Node{},
},
`0x21c65b8 <col:41> 'double' 2.718282e+00`: &FloatingLiteral{
Addr: 0x21c65b8,
Pos: NewPositionFromString("col:41"),
Type: "double",
Value: 2.718282e+00,
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

44
ast/for_stmt.go Normal file
View File

@ -0,0 +1,44 @@
package ast
// ForStmt is node represent 'for'
type ForStmt struct {
Addr Address
Pos Position
ChildNodes []Node
}
func parseForStmt(line string) *ForStmt {
groups := groupsFromRegex(
"<(?P<position>.*)>",
line,
)
return &ForStmt{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *ForStmt) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *ForStmt) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *ForStmt) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *ForStmt) Position() Position {
return n.Pos
}

17
ast/for_stmt_test.go Normal file
View File

@ -0,0 +1,17 @@
package ast
import (
"testing"
)
func TestForStmt(t *testing.T) {
nodes := map[string]Node{
`0x7f961e018848 <line:9:4, line:10:70>`: &ForStmt{
Addr: 0x7f961e018848,
Pos: NewPositionFromString("line:9:4, line:10:70"),
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

48
ast/format_arg_attr.go Normal file
View File

@ -0,0 +1,48 @@
package ast
// FormatArgAttr is a type of attribute that is optionally attached to a
// function definition.
type FormatArgAttr struct {
Addr Address
Pos Position
Arg string
ChildNodes []Node
}
func parseFormatArgAttr(line string) *FormatArgAttr {
groups := groupsFromRegex(
`<(?P<position>.*)>
*(?P<arg>\d+)`,
line,
)
return &FormatArgAttr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Arg: groups["arg"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *FormatArgAttr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *FormatArgAttr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *FormatArgAttr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *FormatArgAttr) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,18 @@
package ast
import (
"testing"
)
func TestFormatArgAttr(t *testing.T) {
nodes := map[string]Node{
`0x7f1234567890 <col:47, col:57> 1`: &FormatArgAttr{
Addr: 0x7f1234567890,
Pos: NewPositionFromString("col:47, col:57"),
Arg: "1",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

64
ast/format_attr.go Normal file
View File

@ -0,0 +1,64 @@
package ast
import (
"github.com/elliotchance/c2go/util"
)
// FormatAttr is a type of attribute that is optionally attached to a variable
// or struct field definition.
type FormatAttr struct {
Addr Address
Pos Position
Implicit bool
Inherited bool
FunctionName string
Unknown1 int
Unknown2 int
ChildNodes []Node
}
func parseFormatAttr(line string) *FormatAttr {
groups := groupsFromRegex(
`<(?P<position>.*)>
(?P<implicit> Implicit)?
(?P<inherited> Inherited)?
(?P<function>\w+)
(?P<unknown1>\d+)
(?P<unknown2>\d+)`,
line,
)
return &FormatAttr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Implicit: len(groups["implicit"]) > 0,
Inherited: len(groups["inherited"]) > 0,
FunctionName: groups["function"],
Unknown1: util.Atoi(groups["unknown1"]),
Unknown2: util.Atoi(groups["unknown2"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *FormatAttr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *FormatAttr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *FormatAttr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *FormatAttr) Position() Position {
return n.Pos
}

42
ast/format_attr_test.go Normal file
View File

@ -0,0 +1,42 @@
package ast
import (
"testing"
)
func TestFormatAttr(t *testing.T) {
nodes := map[string]Node{
`0x7fcc8d8ecee8 <col:6> Implicit printf 2 3`: &FormatAttr{
Addr: 0x7fcc8d8ecee8,
Pos: NewPositionFromString("col:6"),
Implicit: true,
Inherited: false,
FunctionName: "printf",
Unknown1: 2,
Unknown2: 3,
ChildNodes: []Node{},
},
`0x7fcc8d8ecff8 </usr/include/sys/cdefs.h:351:18, col:61> printf 2 3`: &FormatAttr{
Addr: 0x7fcc8d8ecff8,
Pos: NewPositionFromString("/usr/include/sys/cdefs.h:351:18, col:61"),
Implicit: false,
Inherited: false,
FunctionName: "printf",
Unknown1: 2,
Unknown2: 3,
ChildNodes: []Node{},
},
`0x273b4d0 <line:357:12> Inherited printf 2 3`: &FormatAttr{
Addr: 0x273b4d0,
Pos: NewPositionFromString("line:357:12"),
Implicit: false,
Inherited: true,
FunctionName: "printf",
Unknown1: 2,
Unknown2: 3,
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

44
ast/full_comment.go Normal file
View File

@ -0,0 +1,44 @@
package ast
// FullComment is a type of comment
type FullComment struct {
Addr Address
Pos Position
ChildNodes []Node
}
func parseFullComment(line string) *FullComment {
groups := groupsFromRegex(
`<(?P<position>.*)>`,
line,
)
return &FullComment{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *FullComment) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *FullComment) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *FullComment) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *FullComment) Position() Position {
return n.Pos
}

17
ast/full_comment_test.go Normal file
View File

@ -0,0 +1,17 @@
package ast
import (
"testing"
)
func TestFullComment(t *testing.T) {
nodes := map[string]Node{
`0x3860920 <line:10176:4, line:10180:45>`: &FullComment{
Addr: 0x3860920,
Pos: NewPositionFromString("line:10176:4, line:10180:45"),
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

85
ast/function_decl.go Normal file
View File

@ -0,0 +1,85 @@
package ast
import (
"strings"
)
// FunctionDecl is node represents a function declaration.
type FunctionDecl struct {
Addr Address
Pos Position
Prev string
Parent string
Position2 string
Name string
Type string
Type2 string
IsExtern bool
IsImplicit bool
IsUsed bool
IsReferenced bool
IsStatic bool
IsInline bool
ChildNodes []Node
}
func parseFunctionDecl(line string) *FunctionDecl {
groups := groupsFromRegex(
`(?:parent (?P<parent>0x[0-9a-f]+) )?
(?:prev (?P<prev>0x[0-9a-f]+) )?
<(?P<position1>.*?)>
(?P<position2> <scratch space>[^ ]+| [^ ]+)?
(?P<implicit> implicit)?
(?P<used> used)?
(?P<referenced> referenced)?
(?P<name>[_\w]+)
'(?P<type>.*?)'
(:'(?P<type2>.*?)')?
(?P<extern> extern)?
(?P<static> static)?
(?P<inline> inline)?
`,
line,
)
return &FunctionDecl{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position1"]),
Parent: groups["parent"],
Prev: groups["prev"],
Position2: strings.TrimSpace(groups["position2"]),
Name: groups["name"],
Type: groups["type"],
Type2: groups["type2"],
IsExtern: len(groups["extern"]) > 0,
IsImplicit: len(groups["implicit"]) > 0,
IsUsed: len(groups["used"]) > 0,
IsReferenced: len(groups["referenced"]) > 0,
IsStatic: len(groups["static"]) > 0,
IsInline: len(groups["inline"]) > 0,
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *FunctionDecl) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *FunctionDecl) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *FunctionDecl) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *FunctionDecl) Position() Position {
return n.Pos
}

222
ast/function_decl_test.go Normal file
View File

@ -0,0 +1,222 @@
package ast
import (
"testing"
)
func TestFunctionDecl(t *testing.T) {
nodes := map[string]Node{
`0x7fb5a90e60d0 <line:231:1, col:22> col:7 clearerr 'void (FILE *)'`: &FunctionDecl{
Addr: 0x7fb5a90e60d0,
Pos: NewPositionFromString("line:231:1, col:22"),
Prev: "",
Position2: "col:7",
Name: "clearerr",
Type: "void (FILE *)",
Type2: "",
IsExtern: false,
IsImplicit: false,
IsUsed: false,
IsReferenced: false,
IsStatic: false,
IsInline: false,
ChildNodes: []Node{},
},
`0x7fb5a90e2a50 </usr/include/sys/stdio.h:39:1, /usr/include/AvailabilityInternal.h:21697:126> /usr/include/sys/stdio.h:39:5 renameat 'int (int, const char *, int, const char *)'`: &FunctionDecl{
Addr: 0x7fb5a90e2a50,
Pos: NewPositionFromString("/usr/include/sys/stdio.h:39:1, /usr/include/AvailabilityInternal.h:21697:126"),
Prev: "",
Position2: "/usr/include/sys/stdio.h:39:5",
Name: "renameat",
Type: "int (int, const char *, int, const char *)",
Type2: "",
IsExtern: false,
IsImplicit: false,
IsUsed: false,
IsReferenced: false,
IsStatic: false,
IsInline: false,
ChildNodes: []Node{},
},
`0x7fb5a90e9b70 </usr/include/stdio.h:244:6> col:6 implicit fprintf 'int (FILE *, const char *, ...)' extern`: &FunctionDecl{
Addr: 0x7fb5a90e9b70,
Pos: NewPositionFromString("/usr/include/stdio.h:244:6"),
Prev: "",
Position2: "col:6",
Name: "fprintf",
Type: "int (FILE *, const char *, ...)",
Type2: "",
IsExtern: true,
IsImplicit: true,
IsUsed: false,
IsReferenced: false,
IsStatic: false,
IsInline: false,
ChildNodes: []Node{},
},
`0x7fb5a90e9d40 prev 0x7fb5a90e9b70 <col:1, /usr/include/sys/cdefs.h:351:63> /usr/include/stdio.h:244:6 fprintf 'int (FILE *, const char *, ...)'`: &FunctionDecl{
Addr: 0x7fb5a90e9d40,
Pos: NewPositionFromString("col:1, /usr/include/sys/cdefs.h:351:63"),
Prev: "0x7fb5a90e9b70",
Position2: "/usr/include/stdio.h:244:6",
Name: "fprintf",
Type: "int (FILE *, const char *, ...)",
Type2: "",
IsExtern: false,
IsImplicit: false,
IsUsed: false,
IsReferenced: false,
IsStatic: false,
IsInline: false,
ChildNodes: []Node{},
},
`0x7fb5a90ec210 <line:259:6> col:6 implicit used printf 'int (const char *, ...)' extern`: &FunctionDecl{
Addr: 0x7fb5a90ec210,
Pos: NewPositionFromString("line:259:6"),
Prev: "",
Position2: "col:6",
Name: "printf",
Type: "int (const char *, ...)",
Type2: "",
IsExtern: true,
IsImplicit: true,
IsUsed: true,
IsReferenced: false,
IsStatic: false,
IsInline: false,
ChildNodes: []Node{},
},
`0x2ae30d8 </usr/include/math.h:65:3, /usr/include/x86_64-linux-gnu/sys/cdefs.h:57:54> <scratch space>:17:1 __acos 'double (double)' extern`: &FunctionDecl{
Addr: 0x2ae30d8,
Pos: NewPositionFromString("/usr/include/math.h:65:3, /usr/include/x86_64-linux-gnu/sys/cdefs.h:57:54"),
Prev: "",
Position2: "<scratch space>:17:1",
Name: "__acos",
Type: "double (double)",
Type2: "",
IsExtern: true,
IsImplicit: false,
IsUsed: false,
IsReferenced: false,
IsStatic: false,
IsInline: false,
ChildNodes: []Node{},
},
`0x7fc595071500 <line:26:1, line:69:1> line:26:5 referenced main 'int (int, char **)'`: &FunctionDecl{
Addr: 0x7fc595071500,
Pos: NewPositionFromString("line:26:1, line:69:1"),
Prev: "",
Position2: "line:26:5",
Name: "main",
Type: "int (int, char **)",
Type2: "",
IsExtern: false,
IsImplicit: false,
IsUsed: false,
IsReferenced: true,
IsStatic: false,
IsInline: false,
ChildNodes: []Node{},
},
`0x55973a008cb0 <line:93619:1, line:93630:1> line:93619:12 used exprIsConst 'int (Expr *, int, int)' static`: &FunctionDecl{
Addr: 0x55973a008cb0,
Pos: NewPositionFromString("line:93619:1, line:93630:1"),
Prev: "",
Position2: "line:93619:12",
Name: "exprIsConst",
Type: "int (Expr *, int, int)",
Type2: "",
IsExtern: false,
IsImplicit: false,
IsUsed: true,
IsReferenced: false,
IsStatic: true,
IsInline: false,
ChildNodes: []Node{},
},
`0x563ade547cb8 <safe_math.h:13:1, line:25:1> line:14:2 safe_unary_minus_func_int8_t_s 'int8_t (int8_t)':'int8_t (int8_t)' static`: &FunctionDecl{
Addr: 0x563ade547cb8,
Pos: NewPositionFromString("safe_math.h:13:1, line:25:1"),
Prev: "",
Position2: "line:14:2",
Name: "safe_unary_minus_func_int8_t_s",
Type: "int8_t (int8_t)",
Type2: "int8_t (int8_t)",
IsExtern: false,
IsImplicit: false,
IsUsed: false,
IsReferenced: false,
IsStatic: true,
IsInline: false,
ChildNodes: []Node{},
},
`0x556cac571be0 <tests/asm.c:9:1, line:13:1> line:9:26 sqlite3Hwtime1 'unsigned long (void)' inline`: &FunctionDecl{
Addr: 0x556cac571be0,
Pos: NewPositionFromString("tests/asm.c:9:1, line:13:1"),
Prev: "",
Position2: "line:9:26",
Name: "sqlite3Hwtime1",
Type: "unsigned long (void)",
Type2: "",
IsExtern: false,
IsImplicit: false,
IsUsed: false,
IsReferenced: false,
IsStatic: false,
IsInline: true,
ChildNodes: []Node{},
},
`0x21c3da0 <line:8201:1, line:8786:1> line:8201:25 used insertvertex 'enum insertvertexresult (struct mesh *, struct behavior *, vertex, struct otri *, struct osub *, int, int)'`: &FunctionDecl{
Addr: 0x21c3da0,
Pos: NewPositionFromString("line:8201:1, line:8786:1"),
Prev: "",
Position2: "line:8201:25",
Name: "insertvertex",
Type: "enum insertvertexresult (struct mesh *, struct behavior *, vertex, struct otri *, struct osub *, int, int)",
Type2: "",
IsExtern: false,
IsImplicit: false,
IsUsed: true,
IsReferenced: false,
IsStatic: false,
IsInline: false,
ChildNodes: []Node{},
},
`0x30bdba8 parent 0x304fbb0 <col:3, col:38> col:30 used getinfo 'enum countries ()'`: &FunctionDecl{
Addr: 0x30bdba8,
Pos: NewPositionFromString("col:3, col:38"),
Prev: "",
Parent: "0x304fbb0",
Position2: "col:30",
Name: "getinfo",
Type: "enum countries ()",
Type2: "",
IsExtern: false,
IsImplicit: false,
IsUsed: true,
IsReferenced: false,
IsStatic: false,
IsInline: false,
ChildNodes: []Node{},
},
`0x353d3b8 parent 0x31e9ba0 prev 0x33b0810 <col:2, col:30> col:22 used dmatrix 'double **(long, long, long, long)'`: &FunctionDecl{
Addr: 0x353d3b8,
Pos: NewPositionFromString("col:2, col:30"),
Prev: "0x33b0810",
Parent: "0x31e9ba0",
Position2: "col:22",
Name: "dmatrix",
Type: "double **(long, long, long, long)",
Type2: "",
IsExtern: false,
IsImplicit: false,
IsUsed: true,
IsReferenced: false,
IsStatic: false,
IsInline: false,
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

View File

@ -0,0 +1,46 @@
package ast
// FunctionProtoType is function proto type
type FunctionProtoType struct {
Addr Address
Type string
Kind string
ChildNodes []Node
}
func parseFunctionProtoType(line string) *FunctionProtoType {
groups := groupsFromRegex(
"'(?P<type>.*?)' (?P<kind>.*)",
line,
)
return &FunctionProtoType{
Addr: ParseAddress(groups["address"]),
Type: groups["type"],
Kind: groups["kind"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *FunctionProtoType) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *FunctionProtoType) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *FunctionProtoType) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *FunctionProtoType) Position() Position {
return Position{}
}

View File

@ -0,0 +1,18 @@
package ast
import (
"testing"
)
func TestFunctionProtoType(t *testing.T) {
nodes := map[string]Node{
`0x7fa3b88bbb30 'struct _opaque_pthread_t *' foo`: &FunctionProtoType{
Addr: 0x7fa3b88bbb30,
Type: "struct _opaque_pthread_t *",
Kind: "foo",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

44
ast/gcc_asm_stmt.go Normal file
View File

@ -0,0 +1,44 @@
package ast
// GCCAsmStmt is node represent gcc assembler
type GCCAsmStmt struct {
Addr Address
Pos Position
ChildNodes []Node
}
func parseGCCAsmStmt(line string) *GCCAsmStmt {
groups := groupsFromRegex(
"<(?P<position>.*)>",
line,
)
return &GCCAsmStmt{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *GCCAsmStmt) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *GCCAsmStmt) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *GCCAsmStmt) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *GCCAsmStmt) Position() Position {
return n.Pos
}

17
ast/gcc_asm_stmt_test.go Normal file
View File

@ -0,0 +1,17 @@
package ast
import (
"testing"
)
func TestGCCAsmStmtStmt(t *testing.T) {
nodes := map[string]Node{
`0x7fad830c9e38 <line:13:5, col:57>`: &GCCAsmStmt{
Addr: 0x7fad830c9e38,
Pos: NewPositionFromString("line:13:5, col:57"),
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

48
ast/go_stmt.go Normal file
View File

@ -0,0 +1,48 @@
package ast
// GotoStmt is node represent 'goto'
type GotoStmt struct {
Addr Address
Pos Position
Name string
Position2 string
ChildNodes []Node
}
func parseGotoStmt(line string) *GotoStmt {
groups := groupsFromRegex(
"<(?P<position>.*)> '(?P<name>.*)' (?P<position2>.*)",
line,
)
return &GotoStmt{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Name: groups["name"],
Position2: groups["position2"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *GotoStmt) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *GotoStmt) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *GotoStmt) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *GotoStmt) Position() Position {
return n.Pos
}

19
ast/go_stmt_test.go Normal file
View File

@ -0,0 +1,19 @@
package ast
import (
"testing"
)
func TestGotoStmt(t *testing.T) {
nodes := map[string]Node{
`0x7fb9cc1994d8 <line:18893:9, col:14> 'end_getDigits' 0x7fb9cc199490`: &GotoStmt{
Addr: 0x7fb9cc1994d8,
Pos: NewPositionFromString("line:18893:9, col:14"),
Name: "end_getDigits",
Position2: "0x7fb9cc199490",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

View File

@ -0,0 +1,46 @@
package ast
// HTMLEndTagComment is a type of comment
type HTMLEndTagComment struct {
Addr Address
Pos Position
Name string
ChildNodes []Node
}
func parseHTMLEndTagComment(line string) *HTMLEndTagComment {
groups := groupsFromRegex(
`<(?P<position>.*)> Name="(?P<name>.*)"`,
line,
)
return &HTMLEndTagComment{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Name: groups["name"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *HTMLEndTagComment) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *HTMLEndTagComment) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *HTMLEndTagComment) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *HTMLEndTagComment) Position() Position {
return n.Pos
}

View File

@ -0,0 +1,18 @@
package ast
import (
"testing"
)
func TestHTMLEndTagComment(t *testing.T) {
nodes := map[string]Node{
`0x4259670 <col:27, col:30> Name="i"`: &HTMLEndTagComment{
Addr: 0x4259670,
Pos: NewPositionFromString("col:27, col:30"),
Name: "i",
ChildNodes: []Node{},
},
}
runNodeTests(t, nodes)
}

View File

@ -0,0 +1,46 @@
package ast
// HTMLStartTagComment is a type of comment
type HTMLStartTagComment struct {
Addr Address
Pos Position
Name string
ChildNodes []Node
}
func parseHTMLStartTagComment(line string) *HTMLStartTagComment {
groups := groupsFromRegex(
`<(?P<position>.*)> Name="(?P<name>.*)"`,
line,
)
return &HTMLStartTagComment{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Name: groups["name"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *HTMLStartTagComment) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *HTMLStartTagComment) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *HTMLStartTagComment) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *HTMLStartTagComment) Position() Position {
return n.Pos
}

Some files were not shown because too many files have changed in this diff Show More