Add type parsing infrastructure.
This commit is contained in:
parent
0b0b73c6bd
commit
e7270e95cf
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,4 +4,3 @@ ast.txt
|
|||
simple
|
||||
complex
|
||||
program
|
||||
types
|
||||
|
|
291
types/combinators.go
Normal file
291
types/combinators.go
Normal file
|
@ -0,0 +1,291 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var (
|
||||
whitespace *regexp.Regexp
|
||||
wordchars *regexp.Regexp
|
||||
reservedwords *regexp.Regexp
|
||||
)
|
||||
|
||||
func init() {
|
||||
whitespace = regexp.MustCompile(" *")
|
||||
wordchars = regexp.MustCompile(`[_0-9a-zA-Z]`)
|
||||
reservedwords = regexp.MustCompile("^(void|char|short|int|long|float|double|signed|unsigned|_Bool|_Complex|const|restrict|volatile|struct|union|enum)$")
|
||||
}
|
||||
|
||||
func dbg(f string, xs ...interface{}) {
|
||||
if Debug {
|
||||
fmt.Printf(f,xs...)
|
||||
}
|
||||
}
|
||||
|
||||
type Parser func(string, *Node) (string, *Node)
|
||||
|
||||
// Adders
|
||||
|
||||
//Child takes a parser and adds its output node (if non-nil) to the tree.
|
||||
//FIXME -- broken?
|
||||
func Child(p Parser) Parser {
|
||||
return func(s string, n *Node) (string, *Node) {
|
||||
dbg("Child(%s %p)\n",n.Kind,n)
|
||||
s2,n2 := p(s,n)
|
||||
if n2 == nil {
|
||||
return s,nil
|
||||
}
|
||||
if n2 != n {
|
||||
dbg("Child(%p): AddChild()\n",p)
|
||||
n.AddChild(n2)
|
||||
}
|
||||
return s2,n
|
||||
}
|
||||
}
|
||||
|
||||
//ChildOf takes a node and adds results of a parser to it as a child
|
||||
func ChildOf(ret *Node, p Parser) Parser {
|
||||
return func(s string, n *Node) (string, *Node) {
|
||||
dbg("ChildOf(%s %p) %s %p\n",ret.Kind,ret,n.Kind,n)
|
||||
s2,n2 := p(s,ret)
|
||||
if n2 == nil {
|
||||
return s,nil
|
||||
}
|
||||
if n2 == ret {
|
||||
dbg("ChildOf(ret = %p) n2 = %p. WHAT\n",ret,n2)
|
||||
ret.Children = n2.Children
|
||||
} else {
|
||||
dbg("ChildOf(ret = %p) AddChild()\n",ret)
|
||||
ret.AddChild(n2)
|
||||
}
|
||||
return s2,ret
|
||||
}
|
||||
}
|
||||
|
||||
//Children takes a parser returns a parser that adds the children of its
|
||||
//output node to the tree. If multiple parsers are passed in, they are
|
||||
//passed to Seq(...)
|
||||
func Children(ps ...Parser) Parser {
|
||||
if len(ps) > 1 {
|
||||
return Children(Seq(ps...))
|
||||
}
|
||||
p := ps[0]
|
||||
return func(s string, n *Node) (string, *Node) {
|
||||
dbg("Children(%s %p)\n",n.Kind,n)
|
||||
s2,n2 := p(s,n)
|
||||
if n2 == nil {
|
||||
return s,nil
|
||||
}
|
||||
for _,c := range n2.Children {
|
||||
dbg("Children(%s %p) AddChild() from %p\n",n.Kind,n,n2)
|
||||
if c != n {
|
||||
n.AddChild(c)
|
||||
}
|
||||
}
|
||||
return s2,n
|
||||
}
|
||||
}
|
||||
|
||||
//ChildrenOf takes a node and adds the children of a parser's output node
|
||||
//to it as its children.
|
||||
func ChildrenOf(ret *Node, p Parser) Parser {
|
||||
return func(s string, n *Node) (string, *Node) {
|
||||
dbg("ChildrenOf(%s %p) %s %p\n",ret.Kind,ret,n.Kind,n)
|
||||
return Children(p)(s,ret)
|
||||
}
|
||||
}
|
||||
|
||||
func NodeNamed(k string, p Parser) Parser {
|
||||
return func(s string, n *Node) (string, *Node) {
|
||||
s2,n2 := p(s,n)
|
||||
if n2 != nil {
|
||||
n2.Kind = k
|
||||
}
|
||||
return s2,n2
|
||||
}
|
||||
}
|
||||
|
||||
// Combinators
|
||||
|
||||
//Id is the identity parser
|
||||
func Id(s string, n *Node) (string, *Node) {
|
||||
return s,n
|
||||
}
|
||||
|
||||
//Opt optionally runs a Parser, returning the input node if it fails
|
||||
func Opt(p Parser) Parser {
|
||||
return func(s string, n *Node) (string, *Node) {
|
||||
s2,n2 := p(s,n)
|
||||
if n2 == nil {
|
||||
return s,n
|
||||
}
|
||||
return s2,n2
|
||||
}
|
||||
}
|
||||
|
||||
//OneOf picks the first matching parser and returns its result
|
||||
func OneOf(ps ...Parser) Parser {
|
||||
dbg("OneOf(%p)\n",ps)
|
||||
return func(s string, n *Node) (string, *Node) {
|
||||
for _,p := range ps {
|
||||
s2,n2 := p(s,n)
|
||||
if n2 != nil {
|
||||
return s2,n2
|
||||
}
|
||||
}
|
||||
return s,nil
|
||||
}
|
||||
}
|
||||
|
||||
//Doesn't work? May have side effects that do not get unwound.
|
||||
func Longest(ps ...Parser) Parser {
|
||||
dbg("Longest(%p)\n",ps)
|
||||
return func(s string, n *Node) (string, *Node) {
|
||||
ss := make([]string,len(ps))
|
||||
ns := make([]*Node,len(ps))
|
||||
//An arbitrarily large number so I don't have to import "math"
|
||||
minrem := 10000
|
||||
mini := 0
|
||||
for i,p := range ps {
|
||||
ss[i],ns[i] = p(s,n)
|
||||
if ns[i] != nil && len(ss[i]) < minrem {
|
||||
minrem = len(ss[i])
|
||||
mini = i
|
||||
}
|
||||
}
|
||||
if minrem < 10000 {
|
||||
return ss[mini],ns[mini]
|
||||
}
|
||||
return s,nil
|
||||
}
|
||||
}
|
||||
|
||||
//Seq applies parsers in sequence, adding results as children to the input
|
||||
//node. Returns nil and the input string unless the entire sequence succeeds
|
||||
func Seq(ps ...Parser) Parser {
|
||||
dbg("Seq(%p)\n",ps)
|
||||
return func(s string, n *Node) (string, *Node) {
|
||||
ret := NewNode("Seq")
|
||||
s2, n2 := s,n
|
||||
for _,p := range ps {
|
||||
s2, n2 = p(s2,ret)
|
||||
if n2 == nil {
|
||||
return s,nil
|
||||
}
|
||||
if n2 != ret {
|
||||
dbg("Seq(%p): AddChild()\n",ps)
|
||||
ret.AddChild(n2)
|
||||
}
|
||||
}
|
||||
return s2,ret
|
||||
}
|
||||
}
|
||||
func SeqC(ps ...Parser) Parser {
|
||||
return Children(Seq(ps...))
|
||||
}
|
||||
|
||||
//Like Seq but subsequent children are nested inside their earlier siblings.
|
||||
func Nest(ps ...Parser) Parser {
|
||||
dbg("Nest(%p)\n",ps)
|
||||
return func(s string, n *Node) (string, *Node) {
|
||||
s2,n2 := Seq(ps...)(s,n)
|
||||
if n2 == nil {
|
||||
return s,nil
|
||||
}
|
||||
ret := NewNode("Nest")
|
||||
n3 := ret
|
||||
for _,c := range n2.Children {
|
||||
n3.AddChild(c)
|
||||
n3 = c
|
||||
}
|
||||
return s2,ret
|
||||
}
|
||||
}
|
||||
|
||||
//ZeroOrMore returns a sequence of zero or more nodes
|
||||
func ZeroOrMore(p Parser) Parser {
|
||||
return func(s string, n *Node) (string, *Node) {
|
||||
ret := NewNode("ZeroOrMore")
|
||||
dbg("ZeroOrMore(%s %p) ret = %p\n",n.Kind,n,ret)
|
||||
var s2 string
|
||||
var n2 *Node
|
||||
for s2,n2 = p(s,n); n2 != nil; s2,n2 = p(s2,n) {
|
||||
dbg("ZeroOrMore(%p): AddChild()\n",p)
|
||||
ret.AddChild(n2)
|
||||
}
|
||||
if len(ret.Children) > 0 {
|
||||
return s2,ret
|
||||
}
|
||||
return s,n
|
||||
}
|
||||
}
|
||||
|
||||
func OneOrMore(p Parser) Parser {
|
||||
return Seq(p,Children(ZeroOrMore(p)))
|
||||
}
|
||||
|
||||
func Parenthesized(p Parser) Parser {
|
||||
return Children(Seq(Lit("("),p,Lit(")")))
|
||||
}
|
||||
|
||||
func Bracketed(p Parser) Parser {
|
||||
return Seq(Lit("["),p,Lit("]"))
|
||||
}
|
||||
|
||||
func AngBracketed(p Parser) Parser {
|
||||
return Children(Seq(Lit("<"),p,Lit(">")))
|
||||
}
|
||||
|
||||
func CurlyBracketed(p Parser) Parser {
|
||||
return Children(Seq(Lit("{"),p,Lit("}")))
|
||||
}
|
||||
|
||||
// Recognizers
|
||||
|
||||
func Word(f string) Parser {
|
||||
return Lit(f,true)
|
||||
}
|
||||
|
||||
func Lit(f string, ws ...bool) Parser {
|
||||
word := false
|
||||
if len(ws) > 0 {
|
||||
word = ws[0]
|
||||
}
|
||||
lenf := len(f)
|
||||
return func(s string, n *Node) (string, *Node) {
|
||||
ret := NewNode("Lit",f)
|
||||
dbg("Lit(%p) %s ret = %p\n",n,f,ret)
|
||||
if len(s) < lenf {
|
||||
return s,nil
|
||||
}
|
||||
if f == s[:lenf] && !(word && len(s) > lenf && wordchars.Match([]byte{s[lenf]})) {
|
||||
adv := lenf
|
||||
if loc := whitespace.FindStringIndex(s[lenf:]); loc != nil {
|
||||
adv += loc[1]
|
||||
}
|
||||
return s[adv:],ret
|
||||
}
|
||||
return s,nil
|
||||
}
|
||||
}
|
||||
|
||||
func Regexp(f string) Parser {
|
||||
f = "^" + f
|
||||
r := regexp.MustCompile(f)
|
||||
return func(s string, n *Node) (string, *Node) {
|
||||
dbg("Regexp(%p) %s\n",n,f)
|
||||
if loc := r.FindStringIndex(s); loc != nil {
|
||||
lenf := loc[1]
|
||||
adv := lenf
|
||||
if loc := whitespace.FindStringIndex(s[lenf:]); loc != nil {
|
||||
adv += loc[1]
|
||||
}
|
||||
ret := NewNode("Regexp",s[:lenf])
|
||||
dbg("Regexp(%p): ret = %p (%s)\n",n,ret,s[:lenf])
|
||||
return s[adv:],ret
|
||||
}
|
||||
return s,nil
|
||||
}
|
||||
}
|
||||
|
208
types/ctypes.go
Normal file
208
types/ctypes.go
Normal file
|
@ -0,0 +1,208 @@
|
|||
package types
|
||||
|
||||
// Parsers for recognizing type names in C/Objective-C
|
||||
|
||||
func TypeName(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("TypeName",Seq(
|
||||
SpecifierQualifierList,
|
||||
Opt(AbstractDeclarator),
|
||||
))(s,n)
|
||||
}
|
||||
|
||||
func AbstractDeclarator(s string, n *Node) (string, *Node) {
|
||||
return OneOf(SeqC(
|
||||
Opt(Pointer),
|
||||
Children(OneOrMore(DirectAbstractDeclarator))),
|
||||
Pointer,
|
||||
)(s,n)
|
||||
}
|
||||
|
||||
func DirectAbstractDeclarator(s string, n *Node) (string, *Node) {
|
||||
return OneOf(
|
||||
ChildOf(NewNode("Parenthesized"),Parenthesized(AbstractDeclarator)),
|
||||
NodeNamed("Array",Bracketed(Opt(TypeQualifierList))),
|
||||
NodeNamed("Array",Bracketed(SeqC(Opt(TypeQualifierList),NodeNamed("Length",Regexp(`[\d]+|\*`))))), // NOTE: Does not allow arbitrary expressions
|
||||
NodeNamed("Array",Bracketed(SeqC(Word("static"),Opt(TypeQualifierList),NodeNamed("Length",Regexp(`[\d]+`))))), // NOTE: Does not allow arbitrary expressions
|
||||
NodeNamed("Array",Bracketed(SeqC(Opt(TypeQualifierList),Word("static"),NodeNamed("Length",Regexp(`[\d]+`))))), // NOTE: Does not allow arbitrary expressions
|
||||
ChildOf(NewNode("Function"),Parenthesized(Opt(ParameterList))),
|
||||
)(s,n)
|
||||
}
|
||||
|
||||
func ParameterList(s string, n *Node) (string, *Node) {
|
||||
return SeqC(
|
||||
Opt(Children(OneOrMore(SeqC(ParameterDeclaration,Lit(","))))),
|
||||
ParameterDeclaration,
|
||||
)(s,n)
|
||||
}
|
||||
|
||||
func ParameterDeclaration(s string, n *Node) (string, *Node) {
|
||||
return ChildOf(NewNode("ParameterDeclaration"),OneOf(
|
||||
NodeNamed("Ellipsis",Lit("...")),
|
||||
SeqC(DeclarationSpecifiers,Declarator),
|
||||
SeqC(DeclarationSpecifiers,Opt(AbstractDeclarator)),
|
||||
))(s,n)
|
||||
}
|
||||
|
||||
func DeclarationSpecifiers(s string, n *Node) (string, *Node) {
|
||||
return OneOf(
|
||||
SeqC(StorageClassSpecifier,Opt(DeclarationSpecifiers)),
|
||||
SeqC(TypeSpecifier,Opt(DeclarationSpecifiers)),
|
||||
SeqC(TypeQualifier,Opt(DeclarationSpecifiers)),
|
||||
SeqC(Identifier,Opt(DeclarationSpecifiers)),
|
||||
// SeqC(FunctionSpecifier,Opt(DeclarationSpecifiers)),
|
||||
)(s,n)
|
||||
}
|
||||
|
||||
func StorageClassSpecifier(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("StorageClassSpecifier",OneOf(
|
||||
Word("typedef"),
|
||||
Word("extern"),
|
||||
Word("static"),
|
||||
Word("auto"),
|
||||
Word("register"),
|
||||
))(s,n)
|
||||
}
|
||||
|
||||
func Declarator(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("Declarator",
|
||||
Seq(ZeroOrMore(Pointer), DirectDeclarator))(s,n)
|
||||
}
|
||||
|
||||
func DirectDeclarator(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("DirectDeclarator",
|
||||
OneOf(
|
||||
Identifier,
|
||||
Parenthesized(Declarator),
|
||||
// INCOMPLETE
|
||||
),
|
||||
)(s,n)
|
||||
}
|
||||
|
||||
func NullableAnnotation(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("NullableAnnotation",OneOf(
|
||||
Word("_Nullable"),
|
||||
Word("_Nonnull"),
|
||||
Word("_Null_unspecified"),
|
||||
))(s,n)
|
||||
}
|
||||
func Pointer(s string, n *Node) (string, *Node) {
|
||||
return SeqC(
|
||||
NodeNamed("Pointer",Lit("*")),
|
||||
Opt(TypeQualifierList),
|
||||
Opt(NullableAnnotation),
|
||||
Opt(Pointer),
|
||||
)(s,n)
|
||||
}
|
||||
|
||||
func TypeQualifierList(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("TypeQualifierList",
|
||||
Children((OneOrMore(TypeQualifier))),
|
||||
)(s,n)
|
||||
}
|
||||
|
||||
func SpecifierQualifierList(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("SpecifierQualifierList",
|
||||
OneOf(
|
||||
SeqC(TypeSpecifier,Opt(SpecifierQualifierList)),
|
||||
SeqC(StructOrUnionSpecifier,Opt(SpecifierQualifierList)),
|
||||
SeqC(TypedefName,Opt(SpecifierQualifierList)),
|
||||
SeqC(TypeQualifier,Opt(SpecifierQualifierList)),
|
||||
),
|
||||
)(s,n)
|
||||
// OneOrMore(OneOf(TypeQualifier,TypeSpecifier)))(s,n)
|
||||
}
|
||||
|
||||
func TypeSpecifier(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("TypeSpecifier",OneOf(
|
||||
Word("void"),
|
||||
Word("char"),
|
||||
Word("short"),
|
||||
Word("int"),
|
||||
Word("long"),
|
||||
Word("float"),
|
||||
Word("double"),
|
||||
Word("signed"),
|
||||
Word("unsigned"),
|
||||
Word("_Bool"),
|
||||
Word("_Complex"),
|
||||
//StructOrUnionSpecifier,
|
||||
//EnumSpecifier,
|
||||
//TypedefName,
|
||||
))(s,n)
|
||||
}
|
||||
|
||||
func TypeQualifier(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("TypeQualifier",OneOf(
|
||||
Word("const"),
|
||||
Word("restrict"),
|
||||
Word("volatile"),
|
||||
))(s,n)
|
||||
}
|
||||
|
||||
func StructOrUnionSpecifier(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("StructOrUnionSpecifier",Children(OneOf(
|
||||
Seq(StructOrUnion,Opt(Identifier),StructDeclarationList),
|
||||
Nest(StructOrUnion,Identifier),
|
||||
)))(s,n)
|
||||
}
|
||||
|
||||
func StructOrUnion(s string, n *Node) (string, *Node) {
|
||||
return OneOf(
|
||||
NodeNamed("Struct",Word("struct")),
|
||||
NodeNamed("Union",Word("union")))(s,n)
|
||||
}
|
||||
|
||||
func StructDeclarationList(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("StructDeclarationList",OneOrMore(StructDeclaration))(s,n)
|
||||
}
|
||||
|
||||
func StructDeclaration(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("StructDeclaration",Seq(
|
||||
SpecifierQualifierList,
|
||||
StructDeclaratorList,
|
||||
Lit(";"),
|
||||
))(s,n)
|
||||
}
|
||||
|
||||
func StructDeclaratorList(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("StructDeclaratorList",Seq(
|
||||
Opt(OneOrMore(Seq(StructDeclarator,Lit(",")))),
|
||||
StructDeclarator,
|
||||
))(s,n)
|
||||
}
|
||||
|
||||
func StructDeclarator(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("StructDeclarator",Declarator)(s,n)
|
||||
}
|
||||
|
||||
func Generic(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("Generic",TypeName)(s,n)
|
||||
}
|
||||
|
||||
func GenericList(s string, n *Node) (string, *Node) {
|
||||
return OneOf(
|
||||
SeqC(Generic,Lit(","),GenericList),
|
||||
Generic,
|
||||
)(s,n)
|
||||
}
|
||||
|
||||
func TypedefName(s string, n *Node) (string, *Node) {
|
||||
return NodeNamed("TypedefName",OneOf(
|
||||
SeqC(NodeNamed("TypedefName",Identifier),AngBracketed(GenericList)),
|
||||
Identifier,
|
||||
))(s,n)
|
||||
}
|
||||
|
||||
func Identifier(s string, n *Node) (string, *Node) {
|
||||
s2,n2 := NodeNamed("Identifier",
|
||||
Regexp(`[_a-zA-Z][_0-9a-zA-Z]*`))(s,n)
|
||||
if n2 == nil {
|
||||
return s,nil
|
||||
}
|
||||
if reservedwords.MatchString(n2.Content) {
|
||||
dbg("Identifier '%s' contains reserved word\n",n2.Content)
|
||||
return s,nil
|
||||
}
|
||||
return s2,n2
|
||||
}
|
||||
|
76
types/main.go
Normal file
76
types/main.go
Normal file
|
@ -0,0 +1,76 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
Debug bool = false
|
||||
)
|
||||
|
||||
func Parse(s string) *Node {
|
||||
_, n2 := TypeName(s,NewNode("AST"))
|
||||
return n2
|
||||
}
|
||||
|
||||
//Evaluate a node to determine if it is a pointer or array
|
||||
func (n *Node) isAbstract(k string) bool {
|
||||
if n.stripAbstract(k) == nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
//Strip one level of pointer or array indirection from a node
|
||||
func (n *Node) stripAbstract(k string) *Node {
|
||||
i := len(n.Children) - 1
|
||||
if i < 1 {
|
||||
return nil
|
||||
}
|
||||
ret := NewNode(n.Kind)
|
||||
cs := n.Children[:]
|
||||
|
||||
fmt.Printf("stripAbstract(): i = %d\n",i)
|
||||
//Scan backwords skipping NullableAnnotation tags
|
||||
for ;i > 0 && cs[i].Kind == "NullableAnnotation"; i-- { }
|
||||
|
||||
if cs[i].Kind == k {
|
||||
fmt.Printf("stripAbstract(): last node is %s\n",k)
|
||||
ret.Children = cs[:i]
|
||||
return ret
|
||||
}
|
||||
if i > 1 && cs[i-1].Kind == "Parenthesized" {
|
||||
j := len(cs[i-1].Children) - 1
|
||||
//Scan backwards skipping TypeQualifier tags
|
||||
for ;j > 0 && cs[i-1].Children[j].Kind == "TypeQualifier"; j-- { }
|
||||
if cs[i-1].Children[j].Kind != k {
|
||||
return nil
|
||||
}
|
||||
if j == 0 { // strip Parenthesized tag
|
||||
cs[i-1] = cs[i]
|
||||
ret.Children = cs[:i]
|
||||
return ret
|
||||
}
|
||||
// strip last child from Parenthesized tag
|
||||
cs[i-1].Children = cs[i-1].Children[:j]
|
||||
ret.Children = cs
|
||||
return ret
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//PointsTo, when called on a pointer node returns a node describing the type
|
||||
//pointed to. Otherwise returns nil when called on non-pointer types.
|
||||
func (n *Node) PointsTo() *Node {
|
||||
fmt.Printf("PointsTo()\n")
|
||||
return n.stripAbstract("Pointer")
|
||||
}
|
||||
|
||||
//ArrayOf, when called on an array node returns a node describing the type
|
||||
//of the elements of the array. Otherwise returns nil when called on
|
||||
//non-array types.
|
||||
func (n *Node) ArrayOf() *Node {
|
||||
fmt.Printf("ArrayOf()\n")
|
||||
return n.stripAbstract("Array")
|
||||
}
|
||||
|
69
types/node.go
Normal file
69
types/node.go
Normal file
|
@ -0,0 +1,69 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Type definition and basic functions for Nodes
|
||||
|
||||
type Node struct {
|
||||
Kind, Content string
|
||||
Children []*Node
|
||||
}
|
||||
|
||||
func NewNode(k string,cs ...string) *Node {
|
||||
c := ""
|
||||
if len(cs) > 0 {
|
||||
c = cs[0]
|
||||
}
|
||||
ret := &Node{ Kind: k, Content: c, Children: []*Node{} }
|
||||
dbg("NewNode(%p) %s\n",ret,ret.Kind)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (n *Node) String(ls ...int) string {
|
||||
if n == nil {
|
||||
return ""
|
||||
}
|
||||
var ret strings.Builder
|
||||
level := 0
|
||||
if len(ls) > 0 {
|
||||
level = ls[0]
|
||||
if level > 100 {
|
||||
fmt.Println("(*Node)String(): Recursion too deep")
|
||||
os.Exit(-1)
|
||||
}
|
||||
}
|
||||
prefix := strings.Repeat("-",level)
|
||||
ret.WriteString(fmt.Sprintf("%s<%s> %p '%s'\n",prefix, n.Kind, n, n.Content))
|
||||
for _,c := range n.Children {
|
||||
ret.WriteString(c.String(level+1))
|
||||
}
|
||||
return ret.String()
|
||||
}
|
||||
|
||||
func (n *Node) AddChild(c *Node) *Node {
|
||||
erp := func(s string) {
|
||||
dbg("(%p)AddChild(%p): %s\n",n,c,s)
|
||||
os.Exit(-1)
|
||||
}
|
||||
if n == nil { erp("Called on nil node") }
|
||||
if c == nil { erp("Child is nil") }
|
||||
if n == c { erp("Node cannot be its own child") }
|
||||
|
||||
// Skip literals
|
||||
if c.Kind == "Lit" { return n }
|
||||
|
||||
// Do we already have this child? (FIXME: Not needed?)
|
||||
for _,d := range n.Children {
|
||||
if c == d {
|
||||
return n
|
||||
}
|
||||
}
|
||||
dbg("(%p)AddChild(%p)\n",n,c)
|
||||
n.Children = append(n.Children,c)
|
||||
return n
|
||||
}
|
||||
|
15
wrap/main.go
15
wrap/main.go
|
@ -65,11 +65,16 @@ var builtinTypes map[string]string = map[string]string{
|
|||
"complex double": "C.complexdouble",
|
||||
}*/
|
||||
|
||||
func (w *Wrapper) AddType(t,class string) {
|
||||
func (w *Wrapper) AddType(t1,t2,class string) {
|
||||
fmt.Printf("Type: %s\n",t1)
|
||||
t := typeOrType2(t1,t2)
|
||||
if _,ok := builtinTypes[t]; ok {
|
||||
return
|
||||
}
|
||||
nt, err := goType(t,class)
|
||||
if Debug {
|
||||
fmt.Printf("AddType(): (%s) (%s) -> %s\n",t1,t2,nt)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -264,7 +269,7 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
|||
Properties: map[string]Property{},
|
||||
Methods: map[string]Method{},
|
||||
}
|
||||
w.AddType(name,name)
|
||||
w.AddType(name,"",name)
|
||||
}
|
||||
var avail bool
|
||||
for _,c := range ns {
|
||||
|
@ -278,7 +283,7 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
|||
}
|
||||
//_,avail = w.GetParms(x,name) // TODO
|
||||
//if avail {
|
||||
w.AddType(typeOrType2(x.Type,x.Type2),name)
|
||||
w.AddType(x.Type,x.Type2,name)
|
||||
i.Properties[p.Name] = p
|
||||
//}
|
||||
case *ast.ObjCMethodDecl:
|
||||
|
@ -292,7 +297,7 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
|||
}
|
||||
m.Parameters, avail = w.GetParms(x,name)
|
||||
if avail {
|
||||
w.AddType(typeOrType2(x.Type,x.Type2),name)
|
||||
w.AddType(x.Type,x.Type2,name)
|
||||
i.Methods[m.Name] = m
|
||||
}
|
||||
case *ast.ObjCProtocol:
|
||||
|
@ -346,6 +351,7 @@ func (w *Wrapper) GetParms(n *ast.ObjCMethodDecl,class string) ([]Parameter,bool
|
|||
if Debug { fmt.Printf("GetParms(): ast.Unknown: %s\n",x.Name) }
|
||||
}
|
||||
}
|
||||
// check that the method is available for this OS and not deprecated
|
||||
a := func() bool {
|
||||
if len(avail) == 0 {
|
||||
return true
|
||||
|
@ -360,6 +366,7 @@ func (w *Wrapper) GetParms(n *ast.ObjCMethodDecl,class string) ([]Parameter,bool
|
|||
if !a {
|
||||
return nil, false
|
||||
}
|
||||
// check that we found the right number of parameters
|
||||
if len(ret) != len(n.Parameters) {
|
||||
fmt.Printf("Error in method declaration %s: Wrong number of ParmVarDecl children: %d parameters but %d ParmVarDecl children\n",n.Name,len(n.Parameters),len(ret))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user