nswrap/types/cparser.go

398 lines
9.8 KiB
Go

package types
// A parser to recognize type names in C/Objective-C
import (
"regexp"
)
var TypeName func(s string, n *Node) (string, *Node)
func init() {
instancename := regexp.MustCompile("instancename")
instancetype := regexp.MustCompile("instancetype")
cacheable := func(s string) bool {
return !instancetype.MatchString(s) && !instancename.MatchString(s)
}
//memoize the TypeName function for performance
cache := map[string]*Node{}
TypeName = func(s string, n *Node) (string, *Node) {
if n2, ok := cache[s]; ok {
return "", n2
}
s2, n2 := _TypeName(s, n)
if s2 == "" && cacheable(s) {
cache[s] = n2
}
return s2, n2
}
//for debug purposes, the following line can be uncommented, which will
//memoization memoization
//TypeName = _TypeName
}
func MethodSignature(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("MethodSignature"), Seq(
Parenthesized(TypeName),
Identifier,
Opt(MethodParameterList),
Opt(Word("NS_RETURNS_INNER_POINTER")),
))(s, n)
}
func MethodParameterList(s string, n *Node) (string, *Node) {
return Seq(
FirstMethodParameter,
ZeroOrMore(MethodParameter),
)(s, n)
}
func FirstMethodParameter(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("MethodParameter"), Seq(
Lit(":"),
Parenthesized(TypeName),
Identifier,
))(s, n)
}
func MethodParameter(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("MethodParameter"), Seq(
Identifier,
Lit(":"),
Parenthesized(TypeName),
Identifier,
))(s, n)
}
func _TypeName(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("TypeName"), Seq(
Opt(APIAvailable),
Opt(APIUnavailable),
Opt(SwiftUnavailable),
Opt(APIDeprecated),
Opt(APIDeprecatedWithReplacement),
Opt(NSAvailable),
Opt(NSAvailableMac),
Opt(NSDeprecated),
Opt(DispatchReturns),
Opt(ReturnsInnerPointer),
SpecifierQualifierList,
Opt(AbstractDeclarator),
))(s, n)
}
func AbstractDeclarator(s string, n *Node) (string, *Node) {
return OneOf(Seq(
Opt(Pointer),
OneOrMore(DirectAbstractDeclarator)),
Pointer,
Block,
)(s, n)
}
func ParenAbstractDeclarator(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("Parenthesized"),
Parenthesized(AbstractDeclarator),
)(s, n)
}
func ArrayDeclarator(s string, n *Node) (string, *Node) {
return OneOf(
ChildOf(NewNode("Array"),
Bracketed(Opt(TypeQualifierList))),
// NOTE: Parser does not allow arbitrary 'length' expressions
ChildOf(NewNode("Array"),
Bracketed(Seq(
Opt(TypeQualifierList),
NodeNamed("Length", Regexp(`[\d]+|\*`))))),
ChildOf(NewNode("Array"),
Bracketed(Seq(
Word("static"),
Opt(TypeQualifierList),
NodeNamed("Length", Regexp(`[\d]+`))))),
ChildOf(NewNode("Array"),
Bracketed(Seq(
Opt(TypeQualifierList),
Word("static"),
NodeNamed("Length", Regexp(`[\d]+`))))),
)(s, n)
}
func FunctionDeclarator(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("Function"), Seq(
Parenthesized(Opt(ParameterList)),
ZeroOrMore(Attribute),
))(s, n)
}
func Attribute(s string, n *Node) (string, *Node) {
return Seq(
Word("__attribute__"),
ChildOf(NewNode("parens"), Parenthesized(Parenthesized(
Attr,
))),
)(s, n)
}
func Attr(s string, n *Node) (string, *Node) {
return NodeNamed("Attribute", OneOf(
Word("noreturn"),
))(s, n)
}
func DirectAbstractDeclarator(s string, n *Node) (string, *Node) {
return OneOf(
ParenAbstractDeclarator,
ArrayDeclarator,
FunctionDeclarator,
)(s, n)
}
func ParameterList(s string, n *Node) (string, *Node) {
return Seq(
Opt(OneOrMore(Seq(ParameterDeclaration, Lit(",")))),
ParameterDeclaration,
)(s, n)
}
func ParameterDeclaration(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("ParameterDeclaration"), OneOf(
NodeNamed("Ellipsis", Lit("...")),
Seq(DeclarationSpecifiers, Declarator),
Seq(DeclarationSpecifiers, Opt(AbstractDeclarator)),
))(s, n)
}
func DeclarationSpecifiers(s string, n *Node) (string, *Node) {
return OneOf(
Seq(StorageClassSpecifier, Opt(DeclarationSpecifiers)),
Seq(TypeSpecifier, Opt(DeclarationSpecifiers)),
Seq(StructOrUnionSpecifier, Opt(DeclarationSpecifiers)),
Seq(TypeQualifier, Opt(DeclarationSpecifiers)),
Seq(TypedefName, Opt(DeclarationSpecifiers)),
// Seq(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 ChildOf(NewNode("Declarator"),
Seq(ZeroOrMore(Pointer), DirectDeclarator))(s, n)
}
func DirectDeclarator(s string, n *Node) (string, *Node) {
return 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 Seq(
NodeNamed("Pointer", Lit("*")),
Opt(TypeQualifierList),
Opt(NullableAnnotation),
Opt(Pointer),
)(s, n)
}
//FIXME: not sure how correct this is...
func Block(s string, n *Node) (string, *Node) {
return Seq(
NodeNamed("Block", Lit("^")),
Opt(NullableAnnotation),
)(s, n)
}
func TypeQualifierList(s string, n *Node) (string, *Node) {
return OneOrMore(TypeQualifier)(s, n)
}
func SpecifierQualifierList(s string, n *Node) (string, *Node) {
return NodeNamed("SpecifierQualifierList",
OneOf(
Seq(TypeSpecifier, Opt(SpecifierQualifierList)),
Seq(StructOrUnionSpecifier, Opt(SpecifierQualifierList)),
Seq(TypedefName, Opt(SpecifierQualifierList)),
Seq(TypeQualifier, Opt(SpecifierQualifierList)),
),
)(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"),
EnumSpecifier,
))(s, n)
}
func TypeQualifier(s string, n *Node) (string, *Node) {
return NodeNamed("TypeQualifier", OneOf(
Word("const"),
Word("restrict"),
Word("volatile"),
Word("__restrict"),
))(s, n)
}
func APIAvailable(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("APIAvailable"), Seq(
Word("API_AVAILABLE"),
Parenthesized(NodeNamed("Version",Regexp(`\w+\(\d+(\.\d+(\.\d+)?)?\)`))),
))(s, n)
}
func APIUnavailable(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("APIUnavailable"), Seq(
Word("API_UNAVAILABLE"),
Parenthesized(NodeNamed("Version",Regexp(`[^)]*`))),
))(s, n)
}
func APIDeprecated(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("APIDeprecated"), Seq(
NodeNamed("APIDeprecated",Regexp(`API_DEPRECATED`)),
Parenthesized(Seq(
NodeNamed("Message",Regexp(`"[^"]*"`)),
Lit(","),
NodeNamed("Version",Regexp(`\w+\(\d+(\.\d+)?,\s*((\d+(\.\d+)?)|(API_TO_BE_DEPRECATED))\)`)),
)),
))(s, n)
}
func APIDeprecatedWithReplacement(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("APIDeprecated"), Seq(
NodeNamed("APIDeprecated",Regexp(`API_DEPRECATED_WITH_REPLACEMENT`)),
Parenthesized(Seq(
NodeNamed("Message",Regexp(`"[^"]*"`)),
Lit(","),
NodeNamed("Version",Regexp(`\w+\(\d+(\.\d+)?,\s*((\d+(\.\d+)?)|(API_TO_BE_DEPRECATED))\)`)),
)),
))(s, n)
}
func SwiftUnavailable(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("SwiftUnavailable"), Seq(
Word("NS_SWIFT_UNAVAILABLE"),
Parenthesized(NodeNamed("Message",Regexp(`[^)]*`))),
))(s, n)
}
func NSAvailable(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("NSAvailable"), Seq(
Word("NS_AVAILABLE"),
Parenthesized(NodeNamed("Versions",Regexp(`\d+_\d+(,\s*\d+_\d+)?`))),
))(s, n)
}
func NSAvailableMac(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("NSAvailableMac"), Seq(
Word("NS_AVAILABLE_MAC"),
Parenthesized(NodeNamed("Versions",Regexp(`\d+_\d+(,\s*\d+_\d+)?`))),
))(s, n)
}
func NSDeprecated(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("NSDeprecated"), Seq(
Word("NS_DEPRECATED"),
Parenthesized(NodeNamed("Versions",Regexp(`\d+_\d+(,\s*\d+_\d+(,\s*\d+_\d+(,\s*\d+_\d+)?)?)?`))),
))(s, n)
}
func DispatchReturns(s string, n *Node) (string, *Node) {
return NodeNamed("DispatchReturns",Regexp("DISPATCH_[A-Z_]+"))(s, n)
}
func ReturnsInnerPointer(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("ReturnsInnerPointer"),
Word("NS_RETURNS_INNER_POINTER"),
)(s, n)
}
func StructOrUnionSpecifier(s string, n *Node) (string, *Node) {
return 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 EnumSpecifier(s string, n *Node) (string, *Node) {
return Nest(
NodeNamed("Enum", Word("enum")), Identifier)(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 ChildOf(NewNode("GenericList"), Seq(
Generic,
ZeroOrMore(Seq(Lit(","), Generic)),
))(s, n)
}
func BareTypedefName(s string, n *Node) (string, *Node) {
return NodeNamed("TypedefName", Identifier)(s, n)
}
func TypedefName(s string, n *Node) (string, *Node) {
return Seq(
Opt(NodeNamed("KindQualifier", Lit("__kindof"))),
BareTypedefName,
Opt(AngBracketed(GenericList)),
Opt(NullableAnnotation),
)(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
}