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 }