nswrap/types/cparser.go
2019-06-13 16:47:36 -04:00

297 lines
6.9 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),
))(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(
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"),
Parenthesized(Opt(ParameterList)),
)(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 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
}