Initial commit.
This commit is contained in:
commit
6a9c5c2811
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
clast
|
||||
ast.txt
|
||||
|
47
ast/aligned_attr.go
Normal file
47
ast/aligned_attr.go
Normal 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
24
ast/aligned_attr_test.go
Normal 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
57
ast/alloc_size_attr.go
Normal 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
|
||||
}
|
27
ast/alloc_size_attr_test.go
Normal file
27
ast/alloc_size_attr_test.go
Normal 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
45
ast/always_inline_attr.go
Normal 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
|
||||
}
|
17
ast/always_inline_attr_test.go
Normal file
17
ast/always_inline_attr_test.go
Normal 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
36
ast/array_filler.go
Normal 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
20
ast/array_filler_test.go
Normal 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)))
|
||||
}
|
||||
}
|
54
ast/array_subscript_expr.go
Normal file
54
ast/array_subscript_expr.go
Normal 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
|
||||
}
|
36
ast/array_subscript_expr_test.go
Normal file
36
ast/array_subscript_expr_test.go
Normal 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
50
ast/asm_label_attr.go
Normal 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
|
||||
}
|
26
ast/asm_label_attr_test.go
Normal file
26
ast/asm_label_attr_test.go
Normal 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
323
ast/ast.go
Normal 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
70
ast/ast_test.go
Normal 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
47
ast/attributed_type.go
Normal 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
69
ast/availability_attr.go
Normal 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
|
||||
}
|
116
ast/availability_attr_test.go
Normal file
116
ast/availability_attr_test.go
Normal 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
50
ast/binary_operator.go
Normal 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
|
||||
}
|
27
ast/binary_operator_test.go
Normal file
27
ast/binary_operator_test.go
Normal 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)
|
||||
}
|
46
ast/block_command_comment.go
Normal file
46
ast/block_command_comment.go
Normal 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
|
||||
}
|
18
ast/block_command_comment_test.go
Normal file
18
ast/block_command_comment_test.go
Normal 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
44
ast/block_pointer_type.go
Normal 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
44
ast/break_stmt.go
Normal 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
17
ast/break_stmt_test.go
Normal 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
44
ast/builtin_type.go
Normal 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
22
ast/builtin_type_test.go
Normal 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
56
ast/c_style_cast_expr.go
Normal 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
|
||||
}
|
27
ast/c_style_cast_expr_test.go
Normal file
27
ast/c_style_cast_expr_test.go
Normal 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
46
ast/call_expr.go
Normal 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
24
ast/call_expr_test.go
Normal 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
41
ast/case_stmt.go
Normal 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
17
ast/case_stmt_test.go
Normal 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
52
ast/character_literal.go
Normal 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
|
||||
}
|
19
ast/character_literal_test.go
Normal file
19
ast/character_literal_test.go
Normal 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)
|
||||
}
|
56
ast/compound_assign_operator.go
Normal file
56
ast/compound_assign_operator.go
Normal 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
|
||||
}
|
21
ast/compound_assign_operator_test.go
Normal file
21
ast/compound_assign_operator_test.go
Normal 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)
|
||||
}
|
48
ast/compound_literal_expr.go
Normal file
48
ast/compound_literal_expr.go
Normal 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
|
||||
}
|
19
ast/compound_literal_expr_test.go
Normal file
19
ast/compound_literal_expr_test.go
Normal 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
48
ast/compound_stmt.go
Normal 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
22
ast/compound_stmt_test.go
Normal 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)
|
||||
}
|
46
ast/conditional_operator.go
Normal file
46
ast/conditional_operator.go
Normal 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
|
||||
}
|
18
ast/conditional_operator_test.go
Normal file
18
ast/conditional_operator_test.go
Normal 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
47
ast/const_attr.go
Normal 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
18
ast/const_attr_test.go
Normal 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)
|
||||
}
|
50
ast/constant_array_type.go
Normal file
50
ast/constant_array_type.go
Normal 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{}
|
||||
}
|
24
ast/constant_array_type_test.go
Normal file
24
ast/constant_array_type_test.go
Normal 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
44
ast/continue_stmt.go
Normal 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
17
ast/continue_stmt_test.go
Normal 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
44
ast/decayed_type.go
Normal 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
17
ast/decayed_type_test.go
Normal 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
71
ast/decl_ref_expr.go
Normal 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
77
ast/decl_ref_expr_test.go
Normal 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
44
ast/decl_stmt.go
Normal 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
17
ast/decl_stmt_test.go
Normal 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
41
ast/default_stmt.go
Normal 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
17
ast/default_stmt_test.go
Normal 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
51
ast/deprecated_attr.go
Normal 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
|
||||
}
|
36
ast/deprecated_attr_test.go
Normal file
36
ast/deprecated_attr_test.go
Normal 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)
|
||||
}
|
45
ast/disable_tail_calls_attr.go
Normal file
45
ast/disable_tail_calls_attr.go
Normal 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
|
||||
}
|
17
ast/disable_tail_calls_attr_test.go
Normal file
17
ast/disable_tail_calls_attr_test.go
Normal 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
44
ast/do_stmt.go
Normal 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
17
ast/do_stmt_test.go
Normal 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
46
ast/elaborated_type.go
Normal 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{}
|
||||
}
|
18
ast/elaborated_type_test.go
Normal file
18
ast/elaborated_type_test.go
Normal 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
47
ast/empty_decl.go
Normal 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
18
ast/empty_decl_test.go
Normal 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
44
ast/enum.go
Normal 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
56
ast/enum_constant_decl.go
Normal 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
|
||||
}
|
30
ast/enum_constant_decl_test.go
Normal file
30
ast/enum_constant_decl_test.go
Normal 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
52
ast/enum_decl.go
Normal 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
26
ast/enum_decl_test.go
Normal 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
17
ast/enum_test.go
Normal 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
44
ast/enum_type.go
Normal 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
17
ast/enum_type_test.go
Normal 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
46
ast/field.go
Normal 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
67
ast/field_decl.go
Normal 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
122
ast/field_decl_test.go
Normal 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
18
ast/field_test.go
Normal 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
114
ast/floating_literal.go
Normal 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
|
||||
}
|
26
ast/floating_literal_test.go
Normal file
26
ast/floating_literal_test.go
Normal 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
44
ast/for_stmt.go
Normal 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
17
ast/for_stmt_test.go
Normal 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
48
ast/format_arg_attr.go
Normal 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
|
||||
}
|
18
ast/format_arg_attr_test.go
Normal file
18
ast/format_arg_attr_test.go
Normal 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
64
ast/format_attr.go
Normal 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
42
ast/format_attr_test.go
Normal 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
44
ast/full_comment.go
Normal 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
17
ast/full_comment_test.go
Normal 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
85
ast/function_decl.go
Normal 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
222
ast/function_decl_test.go
Normal 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)
|
||||
}
|
46
ast/function_proto_type.go
Normal file
46
ast/function_proto_type.go
Normal 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{}
|
||||
}
|
18
ast/function_proto_type_test.go
Normal file
18
ast/function_proto_type_test.go
Normal 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
44
ast/gcc_asm_stmt.go
Normal 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
17
ast/gcc_asm_stmt_test.go
Normal 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
48
ast/go_stmt.go
Normal 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
19
ast/go_stmt_test.go
Normal 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)
|
||||
}
|
46
ast/html_end_tag_comment.go
Normal file
46
ast/html_end_tag_comment.go
Normal 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
|
||||
}
|
18
ast/html_end_tag_comment_test.go
Normal file
18
ast/html_end_tag_comment_test.go
Normal 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)
|
||||
}
|
46
ast/html_start_tag_comment.go
Normal file
46
ast/html_start_tag_comment.go
Normal 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
Loading…
Reference in New Issue
Block a user