398 lines
9.8 KiB
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
|
|
}
|