diff --git a/ast.go b/ast.go
deleted file mode 100644
index fa964eea9..000000000
--- a/ast.go
+++ /dev/null
@@ -1,163 +0,0 @@
-package main
-
-import (
- "bytes"
- "regexp"
- "strings"
-)
-
-type ExpressionRenderer interface {
- // TODO: The two arguments returned are the rendered Go and the C type.
- // This should be made into an appropriate type.
- Render() []string
-}
-
-type LineRenderer interface {
- RenderLine(out *bytes.Buffer, functionName string, indent int, returnType string)
-}
-
-func Parse(line string) interface{} {
- nodeName := strings.SplitN(line, " ", 2)[0]
- var node interface{}
-
- switch nodeName {
- case "AlwaysInlineAttr":
- node = parseAlwaysInlineAttr(line)
- case "ArraySubscriptExpr":
- node = parseArraySubscriptExpr(line)
- case "AsmLabelAttr":
- node = parseAsmLabelAttr(line)
- case "AvailabilityAttr":
- node = parseAvailabilityAttr(line)
- case "BinaryOperator":
- node = parseBinaryOperator(line)
- case "BreakStmt":
- node = parseBreakStmt(line)
- case "BuiltinType":
- node = parseBuiltinType(line)
- case "CallExpr":
- node = parseCallExpr(line)
- case "CharacterLiteral":
- node = parseCharacterLiteral(line)
- case "CompoundStmt":
- node = parseCompoundStmt(line)
- case "ConditionalOperator":
- node = parseConditionalOperator(line)
- case "ConstAttr":
- node = parseConstAttr(line)
- case "ConstantArrayType":
- node = parseConstantArrayType(line)
- case "CStyleCastExpr":
- node = parseCStyleCastExpr(line)
- case "DeclRefExpr":
- node = parseDeclRefExpr(line)
- case "DeclStmt":
- node = parseDeclStmt(line)
- case "DeprecatedAttr":
- node = parseDeprecatedAttr(line)
- case "ElaboratedType":
- node = parseElaboratedType(line)
- case "Enum":
- node = parseEnum(line)
- case "EnumConstantDecl":
- node = parseEnumConstantDecl(line)
- case "EnumDecl":
- node = parseEnumDecl(line)
- case "EnumType":
- node = parseEnumType(line)
- case "FieldDecl":
- node = parseFieldDecl(line)
- case "FloatingLiteral":
- node = parseFloatingLiteral(line)
- case "FormatAttr":
- node = parseFormatAttr(line)
- case "FunctionDecl":
- node = parseFunctionDecl(line)
- case "FunctionProtoType":
- node = parseFunctionProtoType(line)
- case "ForStmt":
- node = parseForStmt(line)
- case "IfStmt":
- node = parseIfStmt(line)
- case "ImplicitCastExpr":
- node = parseImplicitCastExpr(line)
- case "IntegerLiteral":
- node = parseIntegerLiteral(line)
- case "MallocAttr":
- node = parseMallocAttr(line)
- case "MemberExpr":
- node = parseMemberExpr(line)
- case "ModeAttr":
- node = parseModeAttr(line)
- case "NoThrowAttr":
- node = parseNoThrowAttr(line)
- case "NonNullAttr":
- node = parseNonNullAttr(line)
- case "ParenExpr":
- node = parseParenExpr(line)
- case "ParmVarDecl":
- node = parseParmVarDecl(line)
- case "PointerType":
- node = parsePointerType(line)
- case "PredefinedExpr":
- node = parsePredefinedExpr(line)
- case "QualType":
- node = parseQualType(line)
- case "Record":
- node = parseRecord(line)
- case "RecordDecl":
- node = parseRecordDecl(line)
- case "RecordType":
- node = parseRecordType(line)
- case "RestrictAttr":
- node = parseRestrictAttr(line)
- case "ReturnStmt":
- node = parseReturnStmt(line)
- case "StringLiteral":
- node = parseStringLiteral(line)
- case "TranslationUnitDecl":
- node = parseTranslationUnitDecl(line)
- case "Typedef":
- node = parseTypedef(line)
- case "TypedefDecl":
- node = parseTypedefDecl(line)
- case "TypedefType":
- node = parseTypedefType(line)
- case "UnaryOperator":
- node = parseUnaryOperator(line)
- case "VarDecl":
- node = parseVarDecl(line)
- case "WhileStmt":
- node = parseWhileStmt(line)
- case "NullStmt":
- node = nil
- default:
- panic("Unknown node type: '" + line + "'")
- }
-
- return node
-}
-
-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
[0-9a-fx]+) " +
- strings.Replace(strings.Replace(rx, "\n", "", -1), "\t", "", -1)
- re := regexp.MustCompile(fullRegexp)
-
- match := re.FindStringSubmatch(line)
- if len(match) == 0 {
- panic("could not match regexp '" + fullRegexp +
- "' with string '" + line + "'")
- }
-
- result := make(map[string]string)
- for i, name := range re.SubexpNames() {
- if i != 0 {
- result[name] = match[i]
- }
- }
-
- return result
-}
diff --git a/always_inline_attr.go b/ast/always_inline_attr.go
similarity index 79%
rename from always_inline_attr.go
rename to ast/always_inline_attr.go
index cde351b27..388e2714e 100644
--- a/always_inline_attr.go
+++ b/ast/always_inline_attr.go
@@ -1,4 +1,4 @@
-package main
+package ast
type AlwaysInlineAttr struct {
Address string
@@ -18,3 +18,7 @@ func parseAlwaysInlineAttr(line string) *AlwaysInlineAttr {
Children: []interface{}{},
}
}
+
+func (n *AlwaysInlineAttr) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/array_subscript_expr.go b/ast/array_subscript_expr.go
similarity index 61%
rename from array_subscript_expr.go
rename to ast/array_subscript_expr.go
index 1516aeb38..38ba5a38a 100644
--- a/array_subscript_expr.go
+++ b/ast/array_subscript_expr.go
@@ -1,4 +1,4 @@
-package main
+package ast
import "fmt"
@@ -7,7 +7,7 @@ type ArraySubscriptExpr struct {
Position string
Type string
Kind string
- Children []interface{}
+ Children []Node
}
func parseArraySubscriptExpr(line string) *ArraySubscriptExpr {
@@ -21,12 +21,14 @@ func parseArraySubscriptExpr(line string) *ArraySubscriptExpr {
Position: groups["position"],
Type: groups["type"],
Kind: groups["kind"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *ArraySubscriptExpr) Render() []string {
+func (n *ArraySubscriptExpr) render(ast *Ast) (string, string) {
children := n.Children
- return []string{fmt.Sprintf("%s[%s]", renderExpression(children[0])[0],
- renderExpression(children[1])[0]), "unknown1"}
+ expression, _ := renderExpression(ast, children[0])
+ index, _ := renderExpression(ast, children[1])
+ src := fmt.Sprintf("%s[%s]", expression, index)
+ return src, "unknown1"
}
diff --git a/asm_label_attr.go b/ast/asm_label_attr.go
similarity index 82%
rename from asm_label_attr.go
rename to ast/asm_label_attr.go
index ce50a59e5..b121f89f1 100644
--- a/asm_label_attr.go
+++ b/ast/asm_label_attr.go
@@ -1,4 +1,4 @@
-package main
+package ast
type AsmLabelAttr struct {
Address string
@@ -20,3 +20,7 @@ func parseAsmLabelAttr(line string) *AsmLabelAttr {
Children: []interface{}{},
}
}
+
+func (n *AsmLabelAttr) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/ast/ast.go b/ast/ast.go
new file mode 100644
index 000000000..3c99dd129
--- /dev/null
+++ b/ast/ast.go
@@ -0,0 +1,196 @@
+package ast
+
+import (
+ "regexp"
+ "strings"
+)
+
+type Ast struct {
+ imports []string
+
+ // for rendering go src
+ functionName string
+ indent int
+ returnType string
+}
+
+func NewAst() *Ast {
+ return &Ast{
+ imports: []string{"fmt"},
+ }
+}
+
+func (a *Ast) Imports() []string {
+ return a.imports
+}
+
+func (a *Ast) addImport(name string) {
+ for _, i := range a.imports {
+ if i == name {
+ // already imported
+ return
+ }
+ }
+
+ a.imports = append(a.imports, name)
+}
+
+func (a *Ast) importType(name string) string {
+ if strings.Index(name, ".") != -1 {
+ parts := strings.Split(name, ".")
+ a.addImport(strings.Join(parts[:len(parts)-1], "."))
+
+ parts2 := strings.Split(name, "/")
+ return parts2[len(parts2)-1]
+ }
+
+ return name
+}
+
+type Node interface {
+ render(ast *Ast) (string, string)
+}
+
+func Parse(line string) Node {
+
+ nodeName := strings.SplitN(line, " ", 2)[0]
+
+ switch nodeName {
+ case "AlwaysInlineAttr":
+ return parseAlwaysInlineAttr(line)
+ case "ArraySubscriptExpr":
+ return parseArraySubscriptExpr(line)
+ case "AsmLabelAttr":
+ return parseAsmLabelAttr(line)
+ case "AvailabilityAttr":
+ return parseAvailabilityAttr(line)
+ case "BinaryOperator":
+ return parseBinaryOperator(line)
+ case "BreakStmt":
+ return parseBreakStmt(line)
+ case "BuiltinType":
+ return parseBuiltinType(line)
+ case "CallExpr":
+ return parseCallExpr(line)
+ case "CharacterLiteral":
+ return parseCharacterLiteral(line)
+ case "CompoundStmt":
+ return parseCompoundStmt(line)
+ case "ConditionalOperator":
+ return parseConditionalOperator(line)
+ case "ConstAttr":
+ return parseConstAttr(line)
+ case "ConstantArrayType":
+ return parseConstantArrayType(line)
+ case "CStyleCastExpr":
+ return parseCStyleCastExpr(line)
+ case "DeclRefExpr":
+ return parseDeclRefExpr(line)
+ case "DeclStmt":
+ return parseDeclStmt(line)
+ case "DeprecatedAttr":
+ return parseDeprecatedAttr(line)
+ case "ElaboratedType":
+ return parseElaboratedType(line)
+ case "Enum":
+ return parseEnum(line)
+ case "EnumConstantDecl":
+ return parseEnumConstantDecl(line)
+ case "EnumDecl":
+ return parseEnumDecl(line)
+ case "EnumType":
+ return parseEnumType(line)
+ case "FieldDecl":
+ return parseFieldDecl(line)
+ case "FloatingLiteral":
+ return parseFloatingLiteral(line)
+ case "FormatAttr":
+ return parseFormatAttr(line)
+ case "FunctionDecl":
+ return parseFunctionDecl(line)
+ case "FunctionProtoType":
+ return parseFunctionProtoType(line)
+ case "ForStmt":
+ return parseForStmt(line)
+ case "IfStmt":
+ return parseIfStmt(line)
+ case "ImplicitCastExpr":
+ return parseImplicitCastExpr(line)
+ case "IntegerLiteral":
+ return parseIntegerLiteral(line)
+ case "MallocAttr":
+ return parseMallocAttr(line)
+ case "MemberExpr":
+ return parseMemberExpr(line)
+ case "ModeAttr":
+ return parseModeAttr(line)
+ case "NoThrowAttr":
+ return parseNoThrowAttr(line)
+ case "NonNullAttr":
+ return parseNonNullAttr(line)
+ case "ParenExpr":
+ return parseParenExpr(line)
+ case "ParmVarDecl":
+ return parseParmVarDecl(line)
+ case "PointerType":
+ return parsePointerType(line)
+ case "PredefinedExpr":
+ return parsePredefinedExpr(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 "StringLiteral":
+ return parseStringLiteral(line)
+ case "TranslationUnitDecl":
+ return parseTranslationUnitDecl(line)
+ case "Typedef":
+ return parseTypedef(line)
+ case "TypedefDecl":
+ return parseTypedefDecl(line)
+ case "TypedefType":
+ return parseTypedefType(line)
+ case "UnaryOperator":
+ return parseUnaryOperator(line)
+ case "VarDecl":
+ return parseVarDecl(line)
+ case "WhileStmt":
+ return parseWhileStmt(line)
+ case "NullStmt":
+ return nil
+ default:
+ panic("Unknown node type: '" + 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[0-9a-fx]+) " +
+ strings.Replace(strings.Replace(rx, "\n", "", -1), "\t", "", -1)
+ re := regexp.MustCompile(fullRegexp)
+
+ match := re.FindStringSubmatch(line)
+ if len(match) == 0 {
+ panic("could not match regexp '" + fullRegexp +
+ "' with string '" + line + "'")
+ }
+
+ result := make(map[string]string)
+ for i, name := range re.SubexpNames() {
+ if i != 0 {
+ result[name] = match[i]
+ }
+ }
+
+ return result
+}
diff --git a/ast_test.go b/ast/ast_test.go
similarity index 99%
rename from ast_test.go
rename to ast/ast_test.go
index 4a408c541..b59de617d 100644
--- a/ast_test.go
+++ b/ast/ast_test.go
@@ -1,4 +1,4 @@
-package main
+package ast
import (
"reflect"
diff --git a/availability_attr.go b/ast/availability_attr.go
similarity index 91%
rename from availability_attr.go
rename to ast/availability_attr.go
index 0b568cc12..0a7865fb9 100644
--- a/availability_attr.go
+++ b/ast/availability_attr.go
@@ -1,4 +1,4 @@
-package main
+package ast
type AvailabilityAttr struct {
Address string
@@ -39,3 +39,7 @@ func parseAvailabilityAttr(line string) *AvailabilityAttr {
Children: []interface{}{},
}
}
+
+func (n *AvailabilityAttr) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/binary_operator.go b/ast/binary_operator.go
similarity index 55%
rename from binary_operator.go
rename to ast/binary_operator.go
index 8ea831d3a..06ff2cc64 100644
--- a/binary_operator.go
+++ b/ast/binary_operator.go
@@ -1,4 +1,4 @@
-package main
+package ast
import "fmt"
@@ -7,7 +7,7 @@ type BinaryOperator struct {
Position string
Type string
Operator string
- Children []interface{}
+ Children []Node
}
func parseBinaryOperator(line string) *BinaryOperator {
@@ -21,30 +21,31 @@ func parseBinaryOperator(line string) *BinaryOperator {
Position: groups["position"],
Type: groups["type"],
Operator: groups["operator"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *BinaryOperator) Render() []string {
+func (n *BinaryOperator) render(ast *Ast) (string, string) {
operator := n.Operator
- left := renderExpression(n.Children[0])
- right := renderExpression(n.Children[1])
+ left, leftType := renderExpression(ast, n.Children[0])
+ right, rightType := renderExpression(ast, n.Children[1])
return_type := "bool"
if inStrings(operator, []string{"|", "&", "+", "-", "*", "/"}) {
// TODO: The left and right type might be different
- return_type = left[1]
+ return_type = leftType
}
if operator == "&&" {
- left[0] = cast(left[0], left[1], return_type)
- right[0] = cast(right[0], right[1], return_type)
+ left = cast(ast, left, leftType, return_type)
+ right = cast(ast, right, rightType, return_type)
}
- if (operator == "!=" || operator == "==") && right[0] == "(0)" {
- right[0] = "nil"
+ if (operator == "!=" || operator == "==") && right == "(0)" {
+ right = "nil"
}
- return []string{fmt.Sprintf("%s %s %s", left[0], operator, right[0]), return_type}
+ src := fmt.Sprintf("%s %s %s", left, operator, right)
+ return src, return_type
}
diff --git a/break_stmt.go b/ast/break_stmt.go
similarity index 78%
rename from break_stmt.go
rename to ast/break_stmt.go
index 78954dd17..426192e36 100644
--- a/break_stmt.go
+++ b/ast/break_stmt.go
@@ -1,4 +1,4 @@
-package main
+package ast
type BreakStmt struct {
Address string
@@ -19,6 +19,6 @@ func parseBreakStmt(line string) *BreakStmt {
}
}
-func (n *BreakStmt) Render() []string {
- return []string{"break", ""}
+func (n *BreakStmt) render(ast *Ast) (string, string) {
+ return "break", ""
}
diff --git a/builtin_type.go b/ast/builtin_type.go
similarity index 78%
rename from builtin_type.go
rename to ast/builtin_type.go
index 445076185..4f845aeac 100644
--- a/builtin_type.go
+++ b/ast/builtin_type.go
@@ -1,4 +1,4 @@
-package main
+package ast
type BuiltinType struct {
Address string
@@ -18,3 +18,7 @@ func parseBuiltinType(line string) *BuiltinType {
Children: []interface{}{},
}
}
+
+func (n *BuiltinType) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/c_style_cast_expr.go b/ast/c_style_cast_expr.go
similarity index 73%
rename from c_style_cast_expr.go
rename to ast/c_style_cast_expr.go
index d1994069d..8c10d30bf 100644
--- a/c_style_cast_expr.go
+++ b/ast/c_style_cast_expr.go
@@ -1,11 +1,11 @@
-package main
+package ast
type CStyleCastExpr struct {
Address string
Position string
Type string
Kind string
- Children []interface{}
+ Children []Node
}
func parseCStyleCastExpr(line string) *CStyleCastExpr {
@@ -19,11 +19,11 @@ func parseCStyleCastExpr(line string) *CStyleCastExpr {
Position: groups["position"],
Type: groups["type"],
Kind: groups["kind"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *CStyleCastExpr) Render() []string {
+func (n *CStyleCastExpr) render(ast *Ast) (string, string) {
children := n.Children
- return renderExpression(children[0])
+ return renderExpression(ast, children[0])
}
diff --git a/call_expr.go b/ast/call_expr.go
similarity index 66%
rename from call_expr.go
rename to ast/call_expr.go
index 7d80d5ac3..11fa33692 100644
--- a/call_expr.go
+++ b/ast/call_expr.go
@@ -1,4 +1,4 @@
-package main
+package ast
import (
"fmt"
@@ -9,7 +9,7 @@ type CallExpr struct {
Address string
Position string
Type string
- Children []interface{}
+ Children []Node
}
func parseCallExpr(line string) *CallExpr {
@@ -22,19 +22,19 @@ func parseCallExpr(line string) *CallExpr {
Address: groups["address"],
Position: groups["position"],
Type: groups["type"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *CallExpr) Render() []string {
+func (n *CallExpr) render(ast *Ast) (string, string) {
children := n.Children
- func_name := renderExpression(children[0])[0]
+ func_name, _ := renderExpression(ast, children[0])
func_def := getFunctionDefinition(func_name)
if func_def.Substitution != "" {
parts := strings.Split(func_def.Substitution, ".")
- addImport(strings.Join(parts[:len(parts)-1], "."))
+ ast.addImport(strings.Join(parts[:len(parts)-1], "."))
parts2 := strings.Split(func_def.Substitution, "/")
func_name = parts2[len(parts2)-1]
@@ -43,18 +43,18 @@ func (n *CallExpr) Render() []string {
args := []string{}
i := 0
for _, arg := range children[1:] {
- e := renderExpression(arg)
+ e, eType := renderExpression(ast, arg)
if i > len(func_def.ArgumentTypes)-1 {
// This means the argument is one of the varargs
// so we don't know what type it needs to be
// cast to.
- args = append(args, e[0])
+ args = append(args, e)
} else {
- args = append(args, cast(e[0], e[1], func_def.ArgumentTypes[i]))
+ args = append(args, cast(ast, e, eType, func_def.ArgumentTypes[i]))
}
- i += 1
+ i++
}
parts := []string{}
@@ -63,7 +63,6 @@ func (n *CallExpr) Render() []string {
parts = append(parts, v)
}
- return []string{
- fmt.Sprintf("%s(%s)", func_name, strings.Join(parts, ", ")),
- func_def.ReturnType}
+ src := fmt.Sprintf("%s(%s)", func_name, strings.Join(parts, ", "))
+ return src, func_def.ReturnType
}
diff --git a/cast.go b/ast/cast.go
similarity index 73%
rename from cast.go
rename to ast/cast.go
index 0e3e24986..bb21f942c 100644
--- a/cast.go
+++ b/ast/cast.go
@@ -1,10 +1,10 @@
-package main
+package ast
import "fmt"
-func cast(expr, fromType, toType string) string {
- fromType = resolveType(fromType)
- toType = resolveType(toType)
+func cast(ast *Ast, expr, fromType, toType string) string {
+ fromType = resolveType(ast, fromType)
+ toType = resolveType(ast, toType)
if fromType == toType {
return expr
@@ -27,6 +27,6 @@ func cast(expr, fromType, toType string) string {
return fmt.Sprintf("%s(%s)", toType, expr)
}
- addImport("github.com/elliotchance/c2go/noarch")
+ ast.addImport("github.com/elliotchance/c2go/noarch")
return fmt.Sprintf("noarch.%sTo%s(%s)", ucfirst(fromType), ucfirst(toType), expr)
}
diff --git a/character_literal.go b/ast/character_literal.go
similarity index 83%
rename from character_literal.go
rename to ast/character_literal.go
index 9d0897a3a..a5236c88c 100644
--- a/character_literal.go
+++ b/ast/character_literal.go
@@ -1,4 +1,4 @@
-package main
+package ast
type CharacterLiteral struct {
Address string
@@ -22,3 +22,7 @@ func parseCharacterLiteral(line string) *CharacterLiteral {
Children: []interface{}{},
}
}
+
+func (n *CharacterLiteral) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/common.go b/ast/common.go
similarity index 61%
rename from common.go
rename to ast/common.go
index 1108e2a5d..39231e2bc 100644
--- a/common.go
+++ b/ast/common.go
@@ -1,4 +1,4 @@
-package main
+package ast
import (
"bytes"
@@ -10,16 +10,17 @@ func printLine(out *bytes.Buffer, line string, indent int) {
out.WriteString(fmt.Sprintf("%s%s\n", strings.Repeat("\t", indent), line))
}
-func renderExpression(node interface{}) []string {
- if node == nil {
- return []string{"", "unknown54"}
- }
+func Render(ast *Ast, node Node) string {
+ src, _ := node.render(ast)
+ return src
+}
- if n, ok := node.(ExpressionRenderer); ok {
- return n.Render()
+func renderExpression(ast *Ast, node Node) (string, string) {
+ if node == nil {
+ return "", "unknown54"
}
- panic(fmt.Sprintf("renderExpression: %#v", node))
+ return node.render(ast)
}
func getFunctionParams(f *FunctionDecl) []*ParmVarDecl {
@@ -47,11 +48,11 @@ func getFunctionReturnType(f string) string {
return strings.TrimSpace(strings.Split(f, "(")[0])
}
-func Render(out *bytes.Buffer, node interface{}, functionName string, indent int, returnType string) {
- if n, ok := node.(LineRenderer); ok {
- n.RenderLine(out, functionName, indent, returnType)
- return
- }
+// func Render(out *bytes.Buffer, node interface{}, functionName string, indent int, returnType string) {
+// if n, ok := node.(LineRenderer); ok {
+// n.RenderLine(out, functionName, indent, returnType)
+// return
+// }
- printLine(out, renderExpression(node)[0], indent)
-}
+// printLine(out, renderExpression(node)[0], indent)
+// }
diff --git a/compound_stmt.go b/ast/compound_stmt.go
similarity index 63%
rename from compound_stmt.go
rename to ast/compound_stmt.go
index 067c9d5ab..09a872fa5 100644
--- a/compound_stmt.go
+++ b/ast/compound_stmt.go
@@ -1,11 +1,11 @@
-package main
+package ast
import "bytes"
type CompoundStmt struct {
Address string
Position string
- Children []interface{}
+ Children []Node
}
func parseCompoundStmt(line string) *CompoundStmt {
@@ -17,12 +17,21 @@ func parseCompoundStmt(line string) *CompoundStmt {
return &CompoundStmt{
Address: groups["address"],
Position: groups["position"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *CompoundStmt) RenderLine(out *bytes.Buffer, functionName string, indent int, returnType string) {
+func (n *CompoundStmt) render(ast *Ast) (string, string) {
+ out := bytes.NewBuffer([]byte{})
+
for _, c := range n.Children {
- Render(out, c, functionName, indent, returnType)
+ src, _ := renderExpression(ast, c)
+ printLine(out, src, ast.indent)
}
+
+ return out.String(), ""
+}
+
+func (n *CompoundStmt) RenderLine(out *bytes.Buffer, functionName string, indent int, returnType string) {
+
}
diff --git a/ast/conditional_operator.go b/ast/conditional_operator.go
new file mode 100644
index 000000000..1f31de5dd
--- /dev/null
+++ b/ast/conditional_operator.go
@@ -0,0 +1,34 @@
+package ast
+
+import "fmt"
+
+type ConditionalOperator struct {
+ Address string
+ Position string
+ Type string
+ Children []Node
+}
+
+func parseConditionalOperator(line string) *ConditionalOperator {
+ groups := groupsFromRegex(
+ `<(?P.*)> '(?P.*?)'`,
+ line,
+ )
+
+ return &ConditionalOperator{
+ Address: groups["address"],
+ Position: groups["position"],
+ Type: groups["type"],
+ Children: []Node{},
+ }
+}
+
+func (n *ConditionalOperator) render(ast *Ast) (string, string) {
+ a, _ := renderExpression(ast, n.Children[0])
+ b, _ := renderExpression(ast, n.Children[1])
+ c, _ := renderExpression(ast, n.Children[2])
+
+ ast.addImport("github.com/elliotchance/c2go/noarch")
+ src := fmt.Sprintf("noarch.Ternary(%s, func () interface{} { return %s }, func () interface{} { return %s })", a, b, c)
+ return src, n.Type
+}
diff --git a/const_attr.go b/ast/const_attr.go
similarity index 81%
rename from const_attr.go
rename to ast/const_attr.go
index 8e2fb3a22..09129ab40 100644
--- a/const_attr.go
+++ b/ast/const_attr.go
@@ -1,4 +1,4 @@
-package main
+package ast
type ConstAttr struct {
Address string
@@ -20,3 +20,7 @@ func parseConstAttr(line string) *ConstAttr {
Children: []interface{}{},
}
}
+
+func (n *ConstAttr) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/constant_array_type.go b/ast/constant_array_type.go
similarity index 72%
rename from constant_array_type.go
rename to ast/constant_array_type.go
index 4f8e6e4f3..24486af98 100644
--- a/constant_array_type.go
+++ b/ast/constant_array_type.go
@@ -1,10 +1,10 @@
-package main
+package ast
type ConstantArrayType struct {
Address string
Type string
Size int
- Children []interface{}
+ Children []Node
}
func parseConstantArrayType(line string) *ConstantArrayType {
@@ -17,6 +17,10 @@ func parseConstantArrayType(line string) *ConstantArrayType {
Address: groups["address"],
Type: groups["type"],
Size: atoi(groups["size"]),
- Children: []interface{}{},
+ Children: []Node{},
}
}
+
+func (n *ConstantArrayType) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/decl_ref_expr.go b/ast/decl_ref_expr.go
similarity index 86%
rename from decl_ref_expr.go
rename to ast/decl_ref_expr.go
index 3488f78a6..b99ace329 100644
--- a/decl_ref_expr.go
+++ b/ast/decl_ref_expr.go
@@ -1,4 +1,4 @@
-package main
+package ast
type DeclRefExpr struct {
Address string
@@ -38,16 +38,16 @@ func parseDeclRefExpr(line string) *DeclRefExpr {
}
}
-func (n *DeclRefExpr) Render() []string {
+func (n *DeclRefExpr) render(ast *Ast) (string, string) {
name := n.Name
if name == "argc" {
name = "len(os.Args)"
- addImport("os")
+ ast.addImport("os")
} else if name == "argv" {
name = "os.Args"
- addImport("os")
+ ast.addImport("os")
}
- return []string{name, n.Type}
+ return name, n.Type
}
diff --git a/decl_stmt.go b/ast/decl_stmt.go
similarity index 56%
rename from decl_stmt.go
rename to ast/decl_stmt.go
index 8fcac6fcf..b7e24fe0b 100644
--- a/decl_stmt.go
+++ b/ast/decl_stmt.go
@@ -1,11 +1,11 @@
-package main
+package ast
import "bytes"
type DeclStmt struct {
Address string
Position string
- Children []interface{}
+ Children []Node
}
func parseDeclStmt(line string) *DeclStmt {
@@ -17,12 +17,17 @@ func parseDeclStmt(line string) *DeclStmt {
return &DeclStmt{
Address: groups["address"],
Position: groups["position"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *DeclStmt) RenderLine(out *bytes.Buffer, functionName string, indent int, returnType string) {
+func (n *DeclStmt) render(ast *Ast) (string, string) {
+ out := bytes.NewBuffer([]byte{})
+
for _, child := range n.Children {
- printLine(out, renderExpression(child)[0], indent)
+ src, _ := renderExpression(ast, child)
+ printLine(out, src, ast.indent)
}
+
+ return out.String(), ""
}
diff --git a/deprecated_attr.go b/ast/deprecated_attr.go
similarity index 84%
rename from deprecated_attr.go
rename to ast/deprecated_attr.go
index c280a159f..70aafe0ab 100644
--- a/deprecated_attr.go
+++ b/ast/deprecated_attr.go
@@ -1,4 +1,4 @@
-package main
+package ast
type DeprecatedAttr struct {
Address string
@@ -22,3 +22,7 @@ func parseDeprecatedAttr(line string) *DeprecatedAttr {
Children: []interface{}{},
}
}
+
+func (n *DeprecatedAttr) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/elaborated_type.go b/ast/elaborated_type.go
similarity index 71%
rename from elaborated_type.go
rename to ast/elaborated_type.go
index 1d88f5dd7..58e623b08 100644
--- a/elaborated_type.go
+++ b/ast/elaborated_type.go
@@ -1,10 +1,10 @@
-package main
+package ast
type ElaboratedType struct {
Address string
Type string
Tags string
- Children []interface{}
+ Children []Node
}
func parseElaboratedType(line string) *ElaboratedType {
@@ -17,6 +17,10 @@ func parseElaboratedType(line string) *ElaboratedType {
Address: groups["address"],
Type: groups["type"],
Tags: groups["tags"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
+
+func (n *ElaboratedType) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/enum.go b/ast/enum.go
similarity index 77%
rename from enum.go
rename to ast/enum.go
index 48d5fbe81..a8917b8c9 100644
--- a/enum.go
+++ b/ast/enum.go
@@ -1,4 +1,4 @@
-package main
+package ast
type Enum struct {
Address string
@@ -18,3 +18,7 @@ func parseEnum(line string) *Enum {
Children: []interface{}{},
}
}
+
+func (n *Enum) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/enum_constant_decl.go b/ast/enum_constant_decl.go
similarity index 78%
rename from enum_constant_decl.go
rename to ast/enum_constant_decl.go
index fbcb9a1ec..dcdda7cd4 100644
--- a/enum_constant_decl.go
+++ b/ast/enum_constant_decl.go
@@ -1,4 +1,4 @@
-package main
+package ast
type EnumConstantDecl struct {
Address string
@@ -6,7 +6,7 @@ type EnumConstantDecl struct {
Position2 string
Name string
Type string
- Children []interface{}
+ Children []Node
}
func parseEnumConstantDecl(line string) *EnumConstantDecl {
@@ -24,6 +24,10 @@ func parseEnumConstantDecl(line string) *EnumConstantDecl {
Position2: groups["position2"],
Name: groups["name"],
Type: groups["type"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
+
+func (n *EnumConstantDecl) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/enum_decl.go b/ast/enum_decl.go
similarity index 76%
rename from enum_decl.go
rename to ast/enum_decl.go
index c0ef40a0b..e23fb5efc 100644
--- a/enum_decl.go
+++ b/ast/enum_decl.go
@@ -1,4 +1,4 @@
-package main
+package ast
import "strings"
@@ -7,7 +7,7 @@ type EnumDecl struct {
Position string
Position2 string
Name string
- Children []interface{}
+ Children []Node
}
func parseEnumDecl(line string) *EnumDecl {
@@ -21,10 +21,10 @@ func parseEnumDecl(line string) *EnumDecl {
Position: groups["position"],
Position2: groups["position2"],
Name: strings.TrimSpace(groups["name"]),
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *EnumDecl) Render() []string {
- return []string{"", ""}
+func (n *EnumDecl) render(ast *Ast) (string, string) {
+ return "", ""
}
diff --git a/enum_type.go b/ast/enum_type.go
similarity index 66%
rename from enum_type.go
rename to ast/enum_type.go
index 01c5fa8c7..194cc35e8 100644
--- a/enum_type.go
+++ b/ast/enum_type.go
@@ -1,9 +1,9 @@
-package main
+package ast
type EnumType struct {
Address string
Name string
- Children []interface{}
+ Children []Node
}
func parseEnumType(line string) *EnumType {
@@ -15,6 +15,10 @@ func parseEnumType(line string) *EnumType {
return &EnumType{
Address: groups["address"],
Name: groups["name"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
+
+func (n *EnumType) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/field_decl.go b/ast/field_decl.go
similarity index 79%
rename from field_decl.go
rename to ast/field_decl.go
index d8e40e343..4dc79ffc3 100644
--- a/field_decl.go
+++ b/ast/field_decl.go
@@ -1,4 +1,4 @@
-package main
+package ast
import (
"fmt"
@@ -12,7 +12,7 @@ type FieldDecl struct {
Name string
Type string
Referenced bool
- Children []interface{}
+ Children []Node
}
func parseFieldDecl(line string) *FieldDecl {
@@ -32,12 +32,12 @@ func parseFieldDecl(line string) *FieldDecl {
Name: strings.TrimSpace(groups["name"]),
Type: groups["type"],
Referenced: len(groups["referenced"]) > 0,
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *FieldDecl) Render() []string {
- fieldType := resolveType(n.Type)
+func (n *FieldDecl) render(ast *Ast) (string, string) {
+ fieldType := resolveType(ast, n.Type)
name := n.Name
//if name == "" {
@@ -53,7 +53,8 @@ func (n *FieldDecl) Render() []string {
// It may have a default value.
suffix := ""
if len(n.Children) > 0 {
- suffix = fmt.Sprintf(" = %s", renderExpression(n.Children[0])[0])
+ src, _ := renderExpression(ast, n.Children[0])
+ suffix = fmt.Sprintf(" = %s", src)
}
// NULL is a macro that one rendered looks like "(0)" we have to be
@@ -63,5 +64,6 @@ func (n *FieldDecl) Render() []string {
suffix = " = nil"
}
- return []string{fmt.Sprintf("%s %s%s", name, fieldType, suffix), "unknown3"}
+ src := fmt.Sprintf("%s %s%s", name, fieldType, suffix)
+ return src, "unknown3"
}
diff --git a/floating_literal.go b/ast/floating_literal.go
similarity index 80%
rename from floating_literal.go
rename to ast/floating_literal.go
index db3b95acf..59b31e0c8 100644
--- a/floating_literal.go
+++ b/ast/floating_literal.go
@@ -1,4 +1,4 @@
-package main
+package ast
import "fmt"
@@ -25,6 +25,6 @@ func parseFloatingLiteral(line string) *FloatingLiteral {
}
}
-func (n *FloatingLiteral) Render() []string {
- return []string{fmt.Sprintf("%f", n.Value), "double"}
+func (n *FloatingLiteral) render(ast *Ast) (string, string) {
+ return fmt.Sprintf("%f", n.Value), "double"
}
diff --git a/for_stmt.go b/ast/for_stmt.go
similarity index 69%
rename from for_stmt.go
rename to ast/for_stmt.go
index e5b266481..c8ca8618a 100644
--- a/for_stmt.go
+++ b/ast/for_stmt.go
@@ -1,4 +1,4 @@
-package main
+package ast
import (
"bytes"
@@ -8,7 +8,7 @@ import (
type ForStmt struct {
Address string
Position string
- Children []interface{}
+ Children []Node
}
func parseForStmt(line string) *ForStmt {
@@ -20,11 +20,13 @@ func parseForStmt(line string) *ForStmt {
return &ForStmt{
Address: groups["address"],
Position: groups["position"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *ForStmt) RenderLine(out *bytes.Buffer, functionName string, indent int, returnType string) {
+func (n *ForStmt) render(ast *Ast) (string, string) {
+ out := bytes.NewBuffer([]byte{})
+
children := n.Children
// There are always 5 children in a ForStmt, for example:
@@ -50,19 +52,20 @@ func (n *ForStmt) RenderLine(out *bytes.Buffer, functionName string, indent int,
panic("non-nil child 1 in ForStmt")
}
- init := renderExpression(children[0])[0]
- conditional := renderExpression(children[2])[0]
- step := renderExpression(children[3])[0]
- body := children[4]
+ init, _ := renderExpression(ast, children[0])
+ conditional, _ := renderExpression(ast, children[2])
+ step, _ := renderExpression(ast, children[3])
+ body, _ := renderExpression(ast, children[4])
if init == "" && conditional == "" && step == "" {
- printLine(out, "for {", indent)
+ printLine(out, "for {", ast.indent)
} else {
printLine(out, fmt.Sprintf("for %s; %s; %s {",
- init, conditional, step), indent)
+ init, conditional, step), ast.indent)
}
- Render(out, body, functionName, indent+1, returnType)
+ printLine(out, body, ast.indent+1)
+ printLine(out, "}", ast.indent)
- printLine(out, "}", indent)
+ return out.String(), ""
}
diff --git a/format_attr.go b/ast/format_attr.go
similarity index 89%
rename from format_attr.go
rename to ast/format_attr.go
index 5f9b8c6c2..220a21ef4 100644
--- a/format_attr.go
+++ b/ast/format_attr.go
@@ -1,4 +1,4 @@
-package main
+package ast
type FormatAttr struct {
Address string
@@ -33,3 +33,7 @@ func parseFormatAttr(line string) *FormatAttr {
Children: []interface{}{},
}
}
+
+func (n *FormatAttr) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/function_decl.go b/ast/function_decl.go
similarity index 65%
rename from function_decl.go
rename to ast/function_decl.go
index b66a821af..3f79e94b8 100644
--- a/function_decl.go
+++ b/ast/function_decl.go
@@ -1,4 +1,4 @@
-package main
+package ast
import (
"bytes"
@@ -16,7 +16,7 @@ type FunctionDecl struct {
IsExtern bool
IsImplicit bool
IsUsed bool
- Children []interface{}
+ Children []Node
}
func parseFunctionDecl(line string) *FunctionDecl {
@@ -47,54 +47,58 @@ func parseFunctionDecl(line string) *FunctionDecl {
IsExtern: len(groups["extern"]) > 0,
IsImplicit: len(groups["implicit"]) > 0,
IsUsed: len(groups["used"]) > 0,
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *FunctionDecl) RenderLine(out *bytes.Buffer, functionName string, indent int, returnType string) {
- functionName = strings.TrimSpace(n.Name)
+func (n *FunctionDecl) render(ast *Ast) (string, string) {
+ out := bytes.NewBuffer([]byte{})
- if functionName == "__istype" || functionName == "__isctype" ||
- functionName == "__wcwidth" || functionName == "__sputc" ||
- functionName == "__inline_signbitf" ||
- functionName == "__inline_signbitd" ||
- functionName == "__inline_signbitl" {
- return
+ ast.functionName = strings.TrimSpace(n.Name)
+
+ if ast.functionName == "__istype" ||
+ ast.functionName == "__isctype" ||
+ ast.functionName == "__wcwidth" ||
+ ast.functionName == "__sputc" ||
+ ast.functionName == "__inline_signbitf" ||
+ ast.functionName == "__inline_signbitd" ||
+ ast.functionName == "__inline_signbitl" {
+ return "", ""
}
- has_body := false
+ hasBody := false
if len(n.Children) > 0 {
for _, c := range n.Children {
if _, ok := c.(*CompoundStmt); ok {
- has_body = true
+ hasBody = true
}
}
}
args := []string{}
for _, a := range getFunctionParams(n) {
- args = append(args, fmt.Sprintf("%s %s", a.Name, resolveType(a.Type)))
+ args = append(args, fmt.Sprintf("%s %s", a.Name, resolveType(ast, a.Type)))
}
- if has_body {
+ if hasBody {
returnType := getFunctionReturnType(n.Type)
- if functionName == "main" {
- printLine(out, "func main() {", indent)
+ if ast.functionName == "main" {
+ printLine(out, "func main() {", ast.indent)
} else {
printLine(out, fmt.Sprintf("func %s(%s) %s {",
- functionName, strings.Join(args, ", "),
- resolveType(returnType)), indent)
+ ast.functionName, strings.Join(args, ", "),
+ resolveType(ast, returnType)), ast.indent)
}
for _, c := range n.Children {
if _, ok := c.(*CompoundStmt); ok {
- Render(out, c, functionName,
- indent+1, n.Type)
+ src, _ := renderExpression(ast, c)
+ printLine(out, src, ast.indent+1)
}
}
- printLine(out, "}\n", indent)
+ printLine(out, "}\n", ast.indent)
params := []string{}
for _, v := range getFunctionParams(n) {
@@ -107,4 +111,6 @@ func (n *FunctionDecl) RenderLine(out *bytes.Buffer, functionName string, indent
ArgumentTypes: params,
})
}
+
+ return out.String(), ""
}
diff --git a/function_definition.go b/ast/function_definition.go
similarity index 99%
rename from function_definition.go
rename to ast/function_definition.go
index 5cf0d56b5..a33598efc 100644
--- a/function_definition.go
+++ b/ast/function_definition.go
@@ -1,4 +1,4 @@
-package main
+package ast
import (
"regexp"
diff --git a/function_proto_type.go b/ast/function_proto_type.go
similarity index 72%
rename from function_proto_type.go
rename to ast/function_proto_type.go
index 79dc311ee..de70606f6 100644
--- a/function_proto_type.go
+++ b/ast/function_proto_type.go
@@ -1,10 +1,10 @@
-package main
+package ast
type FunctionProtoType struct {
Address string
Type string
Kind string
- Children []interface{}
+ Children []Node
}
func parseFunctionProtoType(line string) *FunctionProtoType {
@@ -17,6 +17,10 @@ func parseFunctionProtoType(line string) *FunctionProtoType {
Address: groups["address"],
Type: groups["type"],
Kind: groups["kind"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
+
+func (n *FunctionProtoType) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/if_stmt.go b/ast/if_stmt.go
similarity index 70%
rename from if_stmt.go
rename to ast/if_stmt.go
index 9a986038d..93e7a1bdf 100644
--- a/if_stmt.go
+++ b/ast/if_stmt.go
@@ -1,4 +1,4 @@
-package main
+package ast
import (
"bytes"
@@ -8,7 +8,7 @@ import (
type IfStmt struct {
Address string
Position string
- Children []interface{}
+ Children []Node
}
func parseIfStmt(line string) *IfStmt {
@@ -20,11 +20,12 @@ func parseIfStmt(line string) *IfStmt {
return &IfStmt{
Address: groups["address"],
Position: groups["position"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *IfStmt) RenderLine(out *bytes.Buffer, functionName string, indent int, returnType string) {
+func (n *IfStmt) render(ast *Ast) (string, string) {
+ out := bytes.NewBuffer([]byte{})
children := n.Children
// There is always 4 or 5 children in an IfStmt. For example:
@@ -64,19 +65,22 @@ func (n *IfStmt) RenderLine(out *bytes.Buffer, functionName string, indent int,
panic("non-nil child 0 in ForStmt")
}
- conditional := renderExpression(children[1])
+ conditional, conditionalType := renderExpression(ast, children[1])
// The condition in Go must always be a bool.
- boolCondition := cast(conditional[0], conditional[1], "bool")
+ boolCondition := cast(ast, conditional, conditionalType, "bool")
- printLine(out, fmt.Sprintf("if %s {", boolCondition), indent)
-
- Render(out, children[2], functionName, indent+1, returnType)
+ printLine(out, fmt.Sprintf("if %s {", boolCondition), ast.indent)
+ body, _ := renderExpression(ast, children[2])
+ printLine(out, body, ast.indent+1)
if children[3] != nil {
- printLine(out, "} else {", indent)
- Render(out, children[3], functionName, indent+1, returnType)
+ printLine(out, "} else {", ast.indent)
+ body, _ := renderExpression(ast, children[3])
+ printLine(out, body, ast.indent+1)
}
- printLine(out, "}", indent)
+ printLine(out, "}", ast.indent)
+
+ return out.String(), ""
}
diff --git a/implicit_cast_expr.go b/ast/implicit_cast_expr.go
similarity index 72%
rename from implicit_cast_expr.go
rename to ast/implicit_cast_expr.go
index a352f1898..1fdc6e725 100644
--- a/implicit_cast_expr.go
+++ b/ast/implicit_cast_expr.go
@@ -1,11 +1,11 @@
-package main
+package ast
type ImplicitCastExpr struct {
Address string
Position string
Type string
Kind string
- Children []interface{}
+ Children []Node
}
func parseImplicitCastExpr(line string) *ImplicitCastExpr {
@@ -19,10 +19,10 @@ func parseImplicitCastExpr(line string) *ImplicitCastExpr {
Position: groups["position"],
Type: groups["type"],
Kind: groups["kind"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *ImplicitCastExpr) Render() []string {
- return renderExpression(n.Children[0])
+func (n *ImplicitCastExpr) render(ast *Ast) (string, string) {
+ return renderExpression(ast, n.Children[0])
}
diff --git a/integer_literal.go b/ast/integer_literal.go
similarity index 82%
rename from integer_literal.go
rename to ast/integer_literal.go
index bee1d6c67..577630e2b 100644
--- a/integer_literal.go
+++ b/ast/integer_literal.go
@@ -1,4 +1,4 @@
-package main
+package ast
import "strconv"
@@ -25,12 +25,12 @@ func parseIntegerLiteral(line string) *IntegerLiteral {
}
}
-func (n *IntegerLiteral) Render() []string {
+func (n *IntegerLiteral) render(ast *Ast) (string, string) {
literal := n.Value
// FIXME
//if str(literal)[-1] == 'L':
// literal = '%s(%s)' % (resolveType('long'), literal[:-1])
- return []string{strconv.FormatInt(int64(literal), 10), "int"}
+ return strconv.FormatInt(int64(literal), 10), "int"
}
diff --git a/malloc_attr.go b/ast/malloc_attr.go
similarity index 78%
rename from malloc_attr.go
rename to ast/malloc_attr.go
index 0fa9a5998..b9a3afaa1 100644
--- a/malloc_attr.go
+++ b/ast/malloc_attr.go
@@ -1,4 +1,4 @@
-package main
+package ast
type MallocAttr struct {
Address string
@@ -18,3 +18,7 @@ func parseMallocAttr(line string) *MallocAttr {
Children: []interface{}{},
}
}
+
+func (n *MallocAttr) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/member_expr.go b/ast/member_expr.go
similarity index 62%
rename from member_expr.go
rename to ast/member_expr.go
index 85eafcf52..239d421b0 100644
--- a/member_expr.go
+++ b/ast/member_expr.go
@@ -1,4 +1,4 @@
-package main
+package ast
import "fmt"
@@ -9,7 +9,7 @@ type MemberExpr struct {
Lvalue bool
Name string
Address2 string
- Children []interface{}
+ Children []Node
}
func parseMemberExpr(line string) *MemberExpr {
@@ -29,23 +29,21 @@ func parseMemberExpr(line string) *MemberExpr {
Lvalue: true,
Name: groups["name"],
Address2: groups["address2"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *MemberExpr) Render() []string {
+func (n *MemberExpr) render(ast *Ast) (string, string) {
children := n.Children
- lhs := renderExpression(children[0])
- lhs_type := resolveType(lhs[1])
+ lhs, lhsType := renderExpression(ast, children[0])
+ lhsResolvedType := resolveType(ast, lhsType)
rhs := n.Name
- if inStrings(lhs_type, []string{"darwin.Float2", "darwin.Double2"}) {
+ if inStrings(lhsResolvedType, []string{"darwin.Float2", "darwin.Double2"}) {
rhs = getExportedName(rhs)
}
- return []string{
- fmt.Sprintf("%s.%s", lhs[0], rhs),
- children[0].(*DeclRefExpr).Type,
- }
+ src := fmt.Sprintf("%s.%s", lhs, rhs)
+ return src, children[0].(*DeclRefExpr).Type
}
diff --git a/mode_attr.go b/ast/mode_attr.go
similarity index 81%
rename from mode_attr.go
rename to ast/mode_attr.go
index 35183fe82..48ac36178 100644
--- a/mode_attr.go
+++ b/ast/mode_attr.go
@@ -1,4 +1,4 @@
-package main
+package ast
type ModeAttr struct {
Address string
@@ -20,3 +20,7 @@ func parseModeAttr(line string) *ModeAttr {
Children: []interface{}{},
}
}
+
+func (n *ModeAttr) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/no_throw_attr.go b/ast/no_throw_attr.go
similarity index 78%
rename from no_throw_attr.go
rename to ast/no_throw_attr.go
index 826838534..644035d0f 100644
--- a/no_throw_attr.go
+++ b/ast/no_throw_attr.go
@@ -1,4 +1,4 @@
-package main
+package ast
type NoThrowAttr struct {
Address string
@@ -18,3 +18,7 @@ func parseNoThrowAttr(line string) *NoThrowAttr {
Children: []interface{}{},
}
}
+
+func (n *NoThrowAttr) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/non_null_attr.go b/ast/non_null_attr.go
similarity index 78%
rename from non_null_attr.go
rename to ast/non_null_attr.go
index f5c7e8e37..2bfa9cfc0 100644
--- a/non_null_attr.go
+++ b/ast/non_null_attr.go
@@ -1,4 +1,4 @@
-package main
+package ast
type NonNullAttr struct {
Address string
@@ -18,3 +18,7 @@ func parseNonNullAttr(line string) *NonNullAttr {
Children: []interface{}{},
}
}
+
+func (n *NonNullAttr) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/paren_expr.go b/ast/paren_expr.go
similarity index 62%
rename from paren_expr.go
rename to ast/paren_expr.go
index 692464cc7..985653faa 100644
--- a/paren_expr.go
+++ b/ast/paren_expr.go
@@ -1,4 +1,4 @@
-package main
+package ast
import "fmt"
@@ -6,7 +6,7 @@ type ParenExpr struct {
Address string
Position string
Type string
- Children []interface{}
+ Children []Node
}
func parseParenExpr(line string) *ParenExpr {
@@ -19,11 +19,12 @@ func parseParenExpr(line string) *ParenExpr {
Address: groups["address"],
Position: groups["position"],
Type: groups["type"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *ParenExpr) Render() []string {
- a := renderExpression(n.Children[0])
- return []string{fmt.Sprintf("(%s)", a[0]), a[1]}
+func (n *ParenExpr) render(ast *Ast) (string, string) {
+ a, aType := renderExpression(ast, n.Children[0])
+ src := fmt.Sprintf("(%s)", a)
+ return src, aType
}
diff --git a/parm_var_decl.go b/ast/parm_var_decl.go
similarity index 87%
rename from parm_var_decl.go
rename to ast/parm_var_decl.go
index c30ddeee9..62b7e6f85 100644
--- a/parm_var_decl.go
+++ b/ast/parm_var_decl.go
@@ -1,4 +1,4 @@
-package main
+package ast
import "strings"
@@ -10,7 +10,7 @@ type ParmVarDecl struct {
Type string
Type2 string
IsUsed bool
- Children []interface{}
+ Children []Node
}
func parseParmVarDecl(line string) *ParmVarDecl {
@@ -42,6 +42,10 @@ func parseParmVarDecl(line string) *ParmVarDecl {
Type: groups["type"],
Type2: type2,
IsUsed: len(groups["used"]) > 0,
- Children: []interface{}{},
+ Children: []Node{},
}
}
+
+func (n *ParmVarDecl) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/pointer_type.go b/ast/pointer_type.go
similarity index 67%
rename from pointer_type.go
rename to ast/pointer_type.go
index f3d766825..f0c1e08b9 100644
--- a/pointer_type.go
+++ b/ast/pointer_type.go
@@ -1,9 +1,9 @@
-package main
+package ast
type PointerType struct {
Address string
Type string
- Children []interface{}
+ Children []Node
}
func parsePointerType(line string) *PointerType {
@@ -15,6 +15,10 @@ func parsePointerType(line string) *PointerType {
return &PointerType{
Address: groups["address"],
Type: groups["type"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
+
+func (n *PointerType) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/predefined_expr.go b/ast/predefined_expr.go
similarity index 71%
rename from predefined_expr.go
rename to ast/predefined_expr.go
index e993dbe4b..4e2752998 100644
--- a/predefined_expr.go
+++ b/ast/predefined_expr.go
@@ -1,4 +1,4 @@
-package main
+package ast
import "fmt"
@@ -8,7 +8,7 @@ type PredefinedExpr struct {
Type string
Name string
Lvalue bool
- Children []interface{}
+ Children []Node
}
func parsePredefinedExpr(line string) *PredefinedExpr {
@@ -23,19 +23,20 @@ func parsePredefinedExpr(line string) *PredefinedExpr {
Type: groups["type"],
Name: groups["name"],
Lvalue: true,
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *PredefinedExpr) Render() []string {
+func (n *PredefinedExpr) render(ast *Ast) (string, string) {
if n.Name == "__PRETTY_FUNCTION__" {
// FIXME
- return []string{"\"void print_number(int *)\"", "const char*"}
+ return "\"void print_number(int *)\"", "const char*"
}
if n.Name == "__func__" {
// FIXME
- return []string{fmt.Sprintf("\"%s\"", "print_number"), "const char*"}
+ src := fmt.Sprintf("\"%s\"", "print_number")
+ return src, "const char*"
}
panic(fmt.Sprintf("renderExpression: unknown PredefinedExpr: %s", n.Name))
diff --git a/qual_type.go b/ast/qual_type.go
similarity index 71%
rename from qual_type.go
rename to ast/qual_type.go
index 83aa205ff..4825bc7b1 100644
--- a/qual_type.go
+++ b/ast/qual_type.go
@@ -1,10 +1,10 @@
-package main
+package ast
type QualType struct {
Address string
Type string
Kind string
- Children []interface{}
+ Children []Node
}
func parseQualType(line string) *QualType {
@@ -17,6 +17,10 @@ func parseQualType(line string) *QualType {
Address: groups["address"],
Type: groups["type"],
Kind: groups["kind"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
+
+func (n *QualType) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/record.go b/ast/record.go
similarity index 77%
rename from record.go
rename to ast/record.go
index 32f520699..82d2a5682 100644
--- a/record.go
+++ b/ast/record.go
@@ -1,4 +1,4 @@
-package main
+package ast
type Record struct {
Address string
@@ -18,3 +18,7 @@ func parseRecord(line string) *Record {
Children: []interface{}{},
}
}
+
+func (n *Record) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/record_decl.go b/ast/record_decl.go
similarity index 74%
rename from record_decl.go
rename to ast/record_decl.go
index 54aaf74c8..cca71a502 100644
--- a/record_decl.go
+++ b/ast/record_decl.go
@@ -1,4 +1,4 @@
-package main
+package ast
import (
"bytes"
@@ -14,7 +14,7 @@ type RecordDecl struct {
Kind string
Name string
Definition bool
- Children []interface{}
+ Children []Node
}
func parseRecordDecl(line string) *RecordDecl {
@@ -46,28 +46,31 @@ func parseRecordDecl(line string) *RecordDecl {
Kind: groups["kind"],
Name: name,
Definition: definition,
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *RecordDecl) RenderLine(out *bytes.Buffer, functionName string, indent int, returnType string) {
+func (n *RecordDecl) render(ast *Ast) (string, string) {
+ out := bytes.NewBuffer([]byte{})
name := strings.TrimSpace(n.Name)
if name == "" || typeIsAlreadyDefined(name) {
- return
+ return "", ""
}
typeIsNowDefined(name)
if n.Kind == "union" {
- return
+ return "", ""
}
- printLine(out, fmt.Sprintf("type %s %s {", name, n.Kind), indent)
+ printLine(out, fmt.Sprintf("type %s %s {", name, n.Kind), ast.indent)
if len(n.Children) > 0 {
for _, c := range n.Children {
- Render(out, c, functionName, indent+1, "")
+ src, _ := renderExpression(ast, c)
+ printLine(out, src, ast.indent)
}
}
- printLine(out, "}\n", indent)
+ printLine(out, "}\n", ast.indent)
+ return out.String(), ""
}
diff --git a/record_type.go b/ast/record_type.go
similarity index 67%
rename from record_type.go
rename to ast/record_type.go
index 958edc858..6c633808e 100644
--- a/record_type.go
+++ b/ast/record_type.go
@@ -1,9 +1,9 @@
-package main
+package ast
type RecordType struct {
Address string
Type string
- Children []interface{}
+ Children []Node
}
func parseRecordType(line string) *RecordType {
@@ -15,6 +15,10 @@ func parseRecordType(line string) *RecordType {
return &RecordType{
Address: groups["address"],
Type: groups["type"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
+
+func (n *RecordType) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/resolve.go b/ast/resolve.go
similarity index 91%
rename from resolve.go
rename to ast/resolve.go
index d4ca87fab..0e6be1796 100644
--- a/resolve.go
+++ b/ast/resolve.go
@@ -1,4 +1,4 @@
-package main
+package ast
import (
"fmt"
@@ -74,13 +74,18 @@ func typeIsNowDefined(typeName string) {
TypesAlreadyDefined = append(TypesAlreadyDefined, typeName)
}
-func resolveType(s string) string {
+func resolveType(ast *Ast, s string) string {
+
// Remove any whitespace or attributes that are not relevant to Go.
s = strings.Replace(s, "const ", "", -1)
s = strings.Replace(s, "*__restrict", "*", -1)
s = strings.Replace(s, "*restrict", "*", -1)
s = strings.Trim(s, " \t\n\r")
+ if s == "char *[]" {
+ return "interface{}"
+ }
+
if s == "fpos_t" {
return "int"
}
@@ -89,14 +94,14 @@ func resolveType(s string) string {
// equivalent. For example float, int, etc.
for k, v := range simpleResolveTypes {
if k == s {
- return importType(v)
+ return ast.importType(v)
}
}
// If the type is already defined we can proceed with the same name.
for _, v := range TypesAlreadyDefined {
if v == s {
- return importType(s)
+ return ast.importType(s)
}
}
@@ -107,7 +112,7 @@ func resolveType(s string) string {
for _, v := range simpleResolveTypes {
if v == s {
- return "*" + importType(simpleResolveTypes[s])
+ return "*" + ast.importType(simpleResolveTypes[s])
}
}
@@ -117,7 +122,7 @@ func resolveType(s string) string {
for _, v := range simpleResolveTypes {
if v == s {
- return importType(simpleResolveTypes[s])
+ return ast.importType(simpleResolveTypes[s])
}
}
@@ -142,7 +147,7 @@ func resolveType(s string) string {
// It may be a pointer of a simple type. For example, float *, int *,
// etc.
if regexp.MustCompile("[\\w ]+\\*+$").MatchString(s) {
- return "*" + resolveType(strings.TrimSpace(s[:len(s)-2]))
+ return "*" + resolveType(ast, strings.TrimSpace(s[:len(s)-2]))
}
// Function pointers are not yet supported. In th mean time they will be
@@ -161,7 +166,7 @@ func resolveType(s string) string {
// It could be an array of fixed length.
search2 := regexp.MustCompile("([\\w ]+)\\[(\\d+)\\]").FindStringSubmatch(s)
if len(search2) > 0 {
- return fmt.Sprintf("[%s]%s", search2[2], resolveType(search2[1]))
+ return fmt.Sprintf("[%s]%s", search2[2], resolveType(ast, search2[1]))
}
panic(fmt.Sprintf("'%s'", s))
diff --git a/restrict_attr.go b/ast/restrict_attr.go
similarity index 81%
rename from restrict_attr.go
rename to ast/restrict_attr.go
index f827db1d5..3935a91d3 100644
--- a/restrict_attr.go
+++ b/ast/restrict_attr.go
@@ -1,4 +1,4 @@
-package main
+package ast
type RestrictAttr struct {
Address string
@@ -20,3 +20,7 @@ func parseRestrictAttr(line string) *RestrictAttr {
Children: []interface{}{},
}
}
+
+func (n *RestrictAttr) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/ast/return_stmt.go b/ast/return_stmt.go
new file mode 100644
index 000000000..824f772f2
--- /dev/null
+++ b/ast/return_stmt.go
@@ -0,0 +1,38 @@
+package ast
+
+import (
+ "bytes"
+)
+
+type ReturnStmt struct {
+ Address string
+ Position string
+ Children []Node
+}
+
+func parseReturnStmt(line string) *ReturnStmt {
+ groups := groupsFromRegex(
+ "<(?P.*)>",
+ line,
+ )
+
+ return &ReturnStmt{
+ Address: groups["address"],
+ Position: groups["position"],
+ Children: []Node{},
+ }
+}
+
+func (n *ReturnStmt) render(ast *Ast) (string, string) {
+ out := bytes.NewBuffer([]byte{})
+ r := "return"
+
+ if len(n.Children) > 0 && ast.functionName != "main" {
+ re, reType := renderExpression(ast, n.Children[0])
+ r = "return " + cast(ast, re, reType, "int")
+ }
+
+ printLine(out, r, ast.indent)
+
+ return out.String(), ""
+}
diff --git a/string_literal.go b/ast/string_literal.go
similarity index 75%
rename from string_literal.go
rename to ast/string_literal.go
index c831cec32..68f9e52be 100644
--- a/string_literal.go
+++ b/ast/string_literal.go
@@ -1,4 +1,4 @@
-package main
+package ast
import (
"fmt"
@@ -30,9 +30,7 @@ func parseStringLiteral(line string) *StringLiteral {
}
}
-func (n *StringLiteral) Render() []string {
- return []string{
- fmt.Sprintf("\"%s\"", strings.Replace(n.Value, "\n", "\\n", -1)),
- "const char *",
- }
+func (n *StringLiteral) render(ast *Ast) (string, string) {
+ src := fmt.Sprintf("\"%s\"", strings.Replace(n.Value, "\n", "\\n", -1))
+ return src, "const char *"
}
diff --git a/ast/translation_unit_decl.go b/ast/translation_unit_decl.go
new file mode 100644
index 000000000..2f54d01b7
--- /dev/null
+++ b/ast/translation_unit_decl.go
@@ -0,0 +1,29 @@
+package ast
+
+import (
+ "bytes"
+)
+
+type TranslationUnitDecl struct {
+ Address string
+ Children []Node
+}
+
+func parseTranslationUnitDecl(line string) *TranslationUnitDecl {
+ groups := groupsFromRegex("", line)
+
+ return &TranslationUnitDecl{
+ Address: groups["address"],
+ Children: []Node{},
+ }
+}
+
+func (n *TranslationUnitDecl) render(ast *Ast) (string, string) {
+ out := bytes.NewBuffer([]byte{})
+ for _, c := range n.Children {
+ src, _ := renderExpression(ast, c)
+ printLine(out, src, ast.indent)
+ }
+
+ return out.String(), ""
+}
diff --git a/typedef.go b/ast/typedef.go
similarity index 77%
rename from typedef.go
rename to ast/typedef.go
index 73e2471bc..c412c52dd 100644
--- a/typedef.go
+++ b/ast/typedef.go
@@ -1,4 +1,4 @@
-package main
+package ast
type Typedef struct {
Address string
@@ -18,3 +18,7 @@ func parseTypedef(line string) *Typedef {
Children: []interface{}{},
}
}
+
+func (n *Typedef) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/typedef_decl.go b/ast/typedef_decl.go
similarity index 76%
rename from typedef_decl.go
rename to ast/typedef_decl.go
index c1ffd9a46..fceba9317 100644
--- a/typedef_decl.go
+++ b/ast/typedef_decl.go
@@ -1,4 +1,4 @@
-package main
+package ast
import (
"bytes"
@@ -15,7 +15,7 @@ type TypedefDecl struct {
Type2 string
IsImplicit bool
IsReferenced bool
- Children []interface{}
+ Children []Node
}
func parseTypedefDecl(line string) *TypedefDecl {
@@ -44,14 +44,16 @@ func parseTypedefDecl(line string) *TypedefDecl {
Type2: type2,
IsImplicit: len(groups["implicit"]) > 0,
IsReferenced: len(groups["referenced"]) > 0,
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *TypedefDecl) RenderLine(out *bytes.Buffer, functionName string, indent int, returnType string) {
+func (n *TypedefDecl) render(ast *Ast) (string, string) {
+ out := bytes.NewBuffer([]byte{})
name := strings.TrimSpace(n.Name)
+
if typeIsAlreadyDefined(name) {
- return
+ return "", ""
}
typeIsNowDefined(name)
@@ -62,23 +64,25 @@ func (n *TypedefDecl) RenderLine(out *bytes.Buffer, functionName string, indent
// return
n.Type = strings.Replace(n.Type, "unsigned", "", -1)
- resolved_type := resolveType(n.Type)
+ resolvedType := resolveType(ast, n.Type)
if name == "__mbstate_t" {
- addImport("github.com/elliotchance/c2go/darwin")
- resolved_type = "darwin.C__mbstate_t"
+ ast.addImport("github.com/elliotchance/c2go/darwin")
+ resolvedType = "darwin.C__mbstate_t"
}
if name == "__darwin_ct_rune_t" {
- addImport("github.com/elliotchance/c2go/darwin")
- resolved_type = "darwin.C__darwin_ct_rune_t"
+ ast.addImport("github.com/elliotchance/c2go/darwin")
+ resolvedType = "darwin.C__darwin_ct_rune_t"
}
if name == "__builtin_va_list" || name == "__qaddr_t" || name == "definition" || name ==
"_IO_lock_t" || name == "va_list" || name == "fpos_t" || name == "__NSConstantString" || name ==
"__darwin_va_list" || name == "__fsid_t" || name == "_G_fpos_t" || name == "_G_fpos64_t" {
- return
+ return "", ""
}
- printLine(out, fmt.Sprintf("type %s %s\n", name, resolved_type), indent)
+ printLine(out, fmt.Sprintf("type %s %s\n", name, resolvedType), ast.indent)
+
+ return out.String(), ""
}
diff --git a/typedef_type.go b/ast/typedef_type.go
similarity index 71%
rename from typedef_type.go
rename to ast/typedef_type.go
index b061adec5..e97a4182f 100644
--- a/typedef_type.go
+++ b/ast/typedef_type.go
@@ -1,10 +1,10 @@
-package main
+package ast
type TypedefType struct {
Address string
Type string
Tags string
- Children []interface{}
+ Children []Node
}
func parseTypedefType(line string) *TypedefType {
@@ -17,6 +17,10 @@ func parseTypedefType(line string) *TypedefType {
Address: groups["address"],
Type: groups["type"],
Tags: groups["tags"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
+
+func (n *TypedefType) render(ast *Ast) (string, string) {
+ return "", ""
+}
diff --git a/unary_operator.go b/ast/unary_operator.go
similarity index 53%
rename from unary_operator.go
rename to ast/unary_operator.go
index e86b6ac29..3f6cb3078 100644
--- a/unary_operator.go
+++ b/ast/unary_operator.go
@@ -1,4 +1,4 @@
-package main
+package ast
import "fmt"
@@ -9,7 +9,7 @@ type UnaryOperator struct {
IsLvalue bool
IsPrefix bool
Operator string
- Children []interface{}
+ Children []Node
}
func parseUnaryOperator(line string) *UnaryOperator {
@@ -30,38 +30,38 @@ func parseUnaryOperator(line string) *UnaryOperator {
IsLvalue: len(groups["lvalue"]) > 0,
IsPrefix: len(groups["prefix"]) > 0,
Operator: groups["operator"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *UnaryOperator) Render() []string {
+func (n *UnaryOperator) render(ast *Ast) (string, string) {
operator := n.Operator
- expr := renderExpression(n.Children[0])
+ expr, exprType := renderExpression(ast, n.Children[0])
if operator == "!" {
- if expr[1] == "bool" {
- return []string{fmt.Sprintf("!(%s)", expr[0]), expr[1]}
+ if exprType == "bool" {
+ return fmt.Sprintf("!(%s)", expr), exprType
}
- addImport("github.com/elliotchance/c2go/noarch")
- return []string{fmt.Sprintf("%s(%s)", fmt.Sprintf("noarch.Not%s", ucfirst(expr[1])), expr[0]), expr[1]}
+ ast.addImport("github.com/elliotchance/c2go/noarch")
+ return fmt.Sprintf("%s(%s)", fmt.Sprintf("noarch.Not%s", ucfirst(exprType)), expr), exprType
}
if operator == "*" {
- if expr[1] == "const char *" {
- return []string{fmt.Sprintf("%s[0]", expr[0]), "char"}
+ if exprType == "const char *" {
+ return fmt.Sprintf("%s[0]", expr), "char"
}
- return []string{fmt.Sprintf("*%s", expr[0]), "int"}
+ return fmt.Sprintf("*%s", expr), "int"
}
if operator == "++" {
- return []string{fmt.Sprintf("%s += 1", expr[0]), expr[1]}
+ return fmt.Sprintf("%s += 1", expr), exprType
}
if operator == "~" {
operator = "^"
}
- return []string{fmt.Sprintf("%s%s", operator, expr[0]), expr[1]}
+ return fmt.Sprintf("%s%s", operator, expr), exprType
}
diff --git a/util.go b/ast/util.go
similarity index 98%
rename from util.go
rename to ast/util.go
index d7148f543..1af1e304b 100644
--- a/util.go
+++ b/ast/util.go
@@ -1,4 +1,4 @@
-package main
+package ast
import (
"strconv"
diff --git a/var_decl.go b/ast/var_decl.go
similarity index 67%
rename from var_decl.go
rename to ast/var_decl.go
index 92bfabec2..3cbc35b90 100644
--- a/var_decl.go
+++ b/ast/var_decl.go
@@ -1,7 +1,6 @@
-package main
+package ast
import (
- "bytes"
"fmt"
"strings"
)
@@ -16,7 +15,7 @@ type VarDecl struct {
IsExtern bool
IsUsed bool
IsCInit bool
- Children []interface{}
+ Children []Node
}
func parseVarDecl(line string) *VarDecl {
@@ -46,14 +45,25 @@ func parseVarDecl(line string) *VarDecl {
IsExtern: len(groups["extern"]) > 0,
IsUsed: len(groups["used"]) > 0,
IsCInit: len(groups["cinit"]) > 0,
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *VarDecl) Render() []string {
- theType := resolveType(n.Type)
+func (n *VarDecl) render(ast *Ast) (string, string) {
+ theType := resolveType(ast, n.Type)
name := n.Name
+ // FIXME: These names dont seem to work when testing more than 1 file
+ if name == "_LIB_VERSION" ||
+ name == "_IO_2_1_stdin_" ||
+ name == "_IO_2_1_stdout_" ||
+ name == "_IO_2_1_stderr_" ||
+ name == "stdin" ||
+ name == "stdout" ||
+ name == "stderr" {
+ return "", ""
+ }
+
// Go does not allow the name of a variable to be called "type".
// For the moment I will rename this to avoid the error.
if name == "type" {
@@ -63,15 +73,13 @@ func (n *VarDecl) Render() []string {
suffix := ""
if len(n.Children) > 0 {
children := n.Children
- suffix = fmt.Sprintf(" = %s", renderExpression(children[0])[0])
+ src, _ := renderExpression(ast, children[0])
+ suffix = fmt.Sprintf(" = %s", src)
}
if suffix == " = (0)" {
suffix = " = nil"
}
- return []string{fmt.Sprintf("var %s %s%s", name, theType, suffix), "unknown3"}
-}
-
-func (n *VarDecl) RenderLine(out *bytes.Buffer, functionName string, indent int, returnType string) {
+ return fmt.Sprintf("var %s %s%s", name, theType, suffix), "unknown3"
}
diff --git a/while_stmt.go b/ast/while_stmt.go
similarity index 51%
rename from while_stmt.go
rename to ast/while_stmt.go
index 86e5a676b..a9728252f 100644
--- a/while_stmt.go
+++ b/ast/while_stmt.go
@@ -1,4 +1,4 @@
-package main
+package ast
import (
"bytes"
@@ -8,7 +8,7 @@ import (
type WhileStmt struct {
Address string
Position string
- Children []interface{}
+ Children []Node
}
func parseWhileStmt(line string) *WhileStmt {
@@ -20,20 +20,23 @@ func parseWhileStmt(line string) *WhileStmt {
return &WhileStmt{
Address: groups["address"],
Position: groups["position"],
- Children: []interface{}{},
+ Children: []Node{},
}
}
-func (n *WhileStmt) RenderLine(out *bytes.Buffer, functionName string, indent int, returnType string) {
+func (n *WhileStmt) render(ast *Ast) (string, string) {
+ out := bytes.NewBuffer([]byte{})
// TODO: The first child of a WhileStmt appears to always be null.
// Are there any cases where it is used?
children := n.Children[1:]
- e := renderExpression(children[0])
- printLine(out, fmt.Sprintf("for %s {", cast(e[0], e[1], "bool")), indent)
+ e, eType := renderExpression(ast, children[0])
+ printLine(out, fmt.Sprintf("for %s {", cast(ast, e, eType, "bool")), ast.indent)
- // FIXME: Does this do anything?
- Render(out, children[1], functionName, indent+1, returnType)
+ body, _ := renderExpression(ast, children[1])
+ printLine(out, body, ast.indent+1)
- printLine(out, "}", indent)
+ printLine(out, "}", ast.indent)
+
+ return out.String(), ""
}
diff --git a/conditional_operator.go b/conditional_operator.go
deleted file mode 100644
index a552a3c83..000000000
--- a/conditional_operator.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package main
-
-import "fmt"
-
-type ConditionalOperator struct {
- Address string
- Position string
- Type string
- Children []interface{}
-}
-
-func parseConditionalOperator(line string) *ConditionalOperator {
- groups := groupsFromRegex(
- `<(?P.*)> '(?P.*?)'`,
- line,
- )
-
- return &ConditionalOperator{
- Address: groups["address"],
- Position: groups["position"],
- Type: groups["type"],
- Children: []interface{}{},
- }
-}
-
-func (n *ConditionalOperator) Render() []string {
- a := renderExpression(n.Children[0])[0]
- b := renderExpression(n.Children[1])[0]
- c := renderExpression(n.Children[2])[0]
-
- addImport("github.com/elliotchance/c2go/noarch")
- return []string{
- fmt.Sprintf("noarch.Ternary(%s, func () interface{} { return %s }, func () interface{} { return %s })", a, b, c),
- n.Type,
- }
-}
diff --git a/import.go b/import.go
deleted file mode 100644
index 86c3121e8..000000000
--- a/import.go
+++ /dev/null
@@ -1,35 +0,0 @@
-package main
-
-import "strings"
-
-var Imports []string
-
-func init() {
- initImports()
-}
-
-func addImport(importName string) {
- for _, i := range Imports {
- if i == importName {
- return
- }
- }
-
- Imports = append(Imports, importName)
-}
-
-func importType(typeName string) string {
- if strings.Index(typeName, ".") != -1 {
- parts := strings.Split(typeName, ".")
- addImport(strings.Join(parts[:len(parts)-1], "."))
-
- parts2 := strings.Split(typeName, "/")
- return parts2[len(parts2)-1]
- }
-
- return typeName
-}
-
-func initImports() {
- Imports = []string{"fmt"}
-}
diff --git a/main.go b/main.go
index e0c663081..f8daf398b 100644
--- a/main.go
+++ b/main.go
@@ -1,7 +1,6 @@
package main
import (
- "bytes"
"flag"
"fmt"
"io/ioutil"
@@ -10,6 +9,10 @@ import (
"reflect"
"regexp"
"strings"
+
+ "go/format"
+
+ "github.com/bongo227/c2go/ast"
)
var (
@@ -39,7 +42,7 @@ func convertLinesToNodes(lines []string) []interface{} {
}
offset := len(indentAndType[1])
- node := Parse(line[offset:])
+ node := ast.Parse(line[offset:])
indentLevel := len(indentAndType[1]) / 2
nodes = append(nodes, []interface{}{indentLevel, node})
@@ -49,9 +52,9 @@ func convertLinesToNodes(lines []string) []interface{} {
}
// buildTree convert an array of nodes, each prefixed with a depth into a tree.
-func buildTree(nodes []interface{}, depth int) []interface{} {
+func buildTree(nodes []interface{}, depth int) []ast.Node {
if len(nodes) == 0 {
- return []interface{}{}
+ return []ast.Node{}
}
// Split the list into sections, treat each section as a a tree with its own root.
@@ -64,7 +67,7 @@ func buildTree(nodes []interface{}, depth int) []interface{} {
}
}
- results := []interface{}{}
+ results := []ast.Node{}
for _, section := range sections {
slice := []interface{}{}
for _, n := range section {
@@ -74,15 +77,17 @@ func buildTree(nodes []interface{}, depth int) []interface{} {
}
children := buildTree(slice, depth+1)
- result := section[0].([]interface{})[1]
+ if result, ok := section[0].([]interface{})[1].(ast.Node); ok {
+ if len(children) > 0 {
+ c := reflect.ValueOf(result).Elem().FieldByName("Children")
+ slice := reflect.AppendSlice(c, reflect.ValueOf(children))
+ c.Set(slice)
+ }
- if len(children) > 0 {
- c := reflect.ValueOf(result).Elem().FieldByName("Children")
- slice := reflect.AppendSlice(c, reflect.ValueOf(children))
- c.Set(slice)
+ results = append(results, result)
+ } else {
+ results = append(results, nil)
}
-
- results = append(results, result)
}
return results
@@ -161,21 +166,25 @@ func Start(args []string) string {
// 3. Parse C and output Go
//parts := strings.Split(cFilePath, "/")
//go_file_path := fmt.Sprintf("%s.go", parts[len(parts) - 1][:len(parts) - 2])
- go_out := bytes.NewBuffer([]byte{})
- Render(go_out, tree[0], "", 0, "")
+ // Render(go_out, tree[0], "", 0, "")
+ astTree := ast.NewAst()
+ goOut := ast.Render(astTree, tree[0].(ast.Node))
+
+ // Format the code
+ goOutFmt, err := format.Source([]byte(goOut))
+ if err != nil {
+ panic(err)
+ }
// Put together the whole file
all := "package main\n\nimport (\n"
- for _, importName := range Imports {
+ for _, importName := range astTree.Imports() {
all += fmt.Sprintf("\t\"%s\"\n", importName)
}
- all += ")\n\n" + go_out.String()
-
- // Reset the imports
- initImports()
+ all += ")\n\n" + string(goOutFmt)
return all
}
diff --git a/main_test.go b/main_test.go
index 986b7c173..35f8e83aa 100644
--- a/main_test.go
+++ b/main_test.go
@@ -54,10 +54,11 @@ func TestIntegrationScripts(t *testing.T) {
// Compile Go
goSrc := Start([]string{file})
+ // fmt.Println(goSrc)
ioutil.WriteFile("build/main.go", []byte(goSrc), os.ModePerm)
- err = exec.Command("go", "build", "-o", goPath, "build/main.go").Run()
+ buildErr, err := exec.Command("go", "build", "-o", goPath, "build/main.go").CombinedOutput()
if err != nil {
- t.Fatal(err)
+ t.Fatal(string(buildErr), err)
}
// Run Go program
diff --git a/return_stmt.go b/return_stmt.go
deleted file mode 100644
index e193b5c73..000000000
--- a/return_stmt.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package main
-
-import "bytes"
-
-type ReturnStmt struct {
- Address string
- Position string
- Children []interface{}
-}
-
-func parseReturnStmt(line string) *ReturnStmt {
- groups := groupsFromRegex(
- "<(?P.*)>",
- line,
- )
-
- return &ReturnStmt{
- Address: groups["address"],
- Position: groups["position"],
- Children: []interface{}{},
- }
-}
-
-func (n *ReturnStmt) RenderLine(out *bytes.Buffer, functionName string, indent int, returnType string) {
- r := "return"
-
- if len(n.Children) > 0 && functionName != "main" {
- re := renderExpression(n.Children[0])
- r = "return " + cast(re[0], re[1], "int")
- }
-
- printLine(out, r, indent)
-}
diff --git a/translation_unit_decl.go b/translation_unit_decl.go
deleted file mode 100644
index 4b860b123..000000000
--- a/translation_unit_decl.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package main
-
-import "bytes"
-
-type TranslationUnitDecl struct {
- Address string
- Children []interface{}
-}
-
-func parseTranslationUnitDecl(line string) *TranslationUnitDecl {
- groups := groupsFromRegex("", line)
-
- return &TranslationUnitDecl{
- Address: groups["address"],
- Children: []interface{}{},
- }
-}
-
-func (n *TranslationUnitDecl) RenderLine(out *bytes.Buffer, functionName string, indent int, returnType string) {
- for _, c := range n.Children {
- Render(out, c, functionName, indent, returnType)
- }
-}