2019-04-18 09:38:46 -04:00
|
|
|
package types
|
|
|
|
|
2019-04-29 10:37:43 -04:00
|
|
|
/* Parsers for recognizing type names in C/Objective-C
|
|
|
|
|
|
|
|
type-name:
|
|
|
|
specifier-qualifier-list abstract-declarator<opt>
|
|
|
|
abstract-declarator:
|
|
|
|
pointer
|
|
|
|
pointer<opt> direct-abstract-declarator
|
|
|
|
direct-abstract-declarator:
|
|
|
|
( abstract-declarator )
|
|
|
|
direct-abstract-declarator<opt> [ type-qualifier-list<opt> assignment-expression<opt> ]
|
|
|
|
direct-abstract-declarator<opt> [ static type-qualifier-list<opt> assignment-expression ]
|
|
|
|
direct-abstract-declarator<opt> [ type-qualifier-list static assignment-expression ]
|
|
|
|
direct-abstract-declarator<opt> [ * ]
|
|
|
|
direct-abstract-declarator<opt> ( parameter-type-list<opt> )
|
|
|
|
pointer:
|
|
|
|
* type-qualifier-list<opt>
|
|
|
|
* type-qualifier-list<opt> pointer
|
|
|
|
parameter-type-list:
|
|
|
|
parameter-list
|
|
|
|
parameter-list , ...
|
|
|
|
parameter-list:
|
|
|
|
parameter-declaration
|
|
|
|
parameter-list , parameter-declaration
|
|
|
|
parameter-declaration:
|
|
|
|
declaration-specifiers declarator
|
|
|
|
declaration-specifiers abstract-declarator<opt>
|
|
|
|
type-qualifier-list:
|
|
|
|
type-qualifier
|
|
|
|
type-qualifier-list type-qualifier
|
|
|
|
specifier-qualifier-list:
|
|
|
|
type-specifier specifier-qualifier-list<opt>
|
|
|
|
type-qualifier specifier-qualifier-list<opt>
|
|
|
|
type-specifier:
|
|
|
|
void
|
|
|
|
char
|
|
|
|
short
|
|
|
|
int
|
|
|
|
long
|
|
|
|
float
|
|
|
|
double
|
|
|
|
signed
|
|
|
|
unsigned
|
|
|
|
_Bool
|
|
|
|
_Complex
|
|
|
|
struct-or-union-specifier
|
|
|
|
enum-specifier
|
|
|
|
typedef-name
|
|
|
|
type-qualifier:
|
|
|
|
const
|
|
|
|
restrict
|
|
|
|
volatile
|
|
|
|
struct-or-union-specifier:
|
|
|
|
// DON'T DO struct-or-union identifier<opt> { struct-declaration-list }
|
|
|
|
struct-or-union identifier
|
|
|
|
struct-or-union:
|
|
|
|
struct
|
|
|
|
union
|
|
|
|
struct-declaration-list:
|
|
|
|
struct-declaration
|
|
|
|
struct-declaration-list struct-declaration
|
|
|
|
struct-declaration:
|
|
|
|
specifier-qualifier-list struct-declarator-list ;
|
|
|
|
struct-declarator-list:
|
|
|
|
struct-declarator
|
|
|
|
struct-declarator-list , struct-declarator
|
|
|
|
struct-declarator:
|
|
|
|
declarator
|
|
|
|
declarator<opt>: constant-expression
|
|
|
|
identifier:
|
|
|
|
identifier-non-digit
|
|
|
|
identifier identifier-nondigit
|
|
|
|
identifier digit
|
|
|
|
identifier-nondigit:
|
|
|
|
nondigit
|
|
|
|
universal-character-name
|
|
|
|
nondigit:
|
|
|
|
_ [a-zA-Z]
|
|
|
|
digit:
|
|
|
|
[0-9]
|
|
|
|
*/
|
2019-04-18 09:38:46 -04:00
|
|
|
|
2019-05-03 13:14:30 -04:00
|
|
|
import (
|
|
|
|
"regexp"
|
|
|
|
)
|
|
|
|
|
2019-04-18 14:40:02 -04:00
|
|
|
var TypeName func(s string, n *Node) (string, *Node)
|
|
|
|
|
|
|
|
func init() {
|
2019-05-03 13:14:30 -04:00
|
|
|
instancename := regexp.MustCompile("instancename")
|
|
|
|
instancetype := regexp.MustCompile("instancetype")
|
|
|
|
cacheable := func(s string) bool {
|
|
|
|
return !instancetype.MatchString(s) && !instancename.MatchString(s)
|
|
|
|
}
|
|
|
|
|
2019-04-18 14:40:02 -04:00
|
|
|
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)
|
2019-05-03 13:14:30 -04:00
|
|
|
if s2 == "" && cacheable(s) {
|
2019-04-18 14:40:02 -04:00
|
|
|
cache[s] = n2
|
|
|
|
}
|
|
|
|
return s2,n2
|
|
|
|
}
|
2019-05-03 13:14:30 -04:00
|
|
|
//TypeName = _TypeName
|
2019-04-18 14:40:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func _TypeName(s string, n *Node) (string, *Node) {
|
2019-04-18 11:22:53 -04:00
|
|
|
return ChildOf(NewNode("TypeName"),Seq(
|
2019-04-18 09:38:46 -04:00
|
|
|
SpecifierQualifierList,
|
|
|
|
Opt(AbstractDeclarator),
|
|
|
|
))(s,n)
|
|
|
|
}
|
|
|
|
|
|
|
|
func AbstractDeclarator(s string, n *Node) (string, *Node) {
|
2019-04-18 11:22:53 -04:00
|
|
|
return OneOf(Seq(
|
2019-04-18 09:38:46 -04:00
|
|
|
Opt(Pointer),
|
2019-04-18 11:22:53 -04:00
|
|
|
OneOrMore(DirectAbstractDeclarator)),
|
2019-04-18 09:38:46 -04:00
|
|
|
Pointer,
|
2019-05-01 10:58:29 -04:00
|
|
|
//Id,
|
2019-04-26 14:08:43 -04:00
|
|
|
Block,
|
2019-04-18 09:38:46 -04:00
|
|
|
)(s,n)
|
|
|
|
}
|
|
|
|
|
2019-04-18 11:22:53 -04:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2019-04-18 09:38:46 -04:00
|
|
|
func DirectAbstractDeclarator(s string, n *Node) (string, *Node) {
|
|
|
|
return OneOf(
|
2019-04-18 11:22:53 -04:00
|
|
|
ParenAbstractDeclarator,
|
|
|
|
ArrayDeclarator,
|
|
|
|
FunctionDeclarator,
|
2019-04-18 09:38:46 -04:00
|
|
|
)(s,n)
|
|
|
|
}
|
|
|
|
|
|
|
|
func ParameterList(s string, n *Node) (string, *Node) {
|
2019-04-18 11:22:53 -04:00
|
|
|
return Seq(
|
|
|
|
Opt(OneOrMore(Seq(ParameterDeclaration,Lit(",")))),
|
2019-04-18 10:21:03 -04:00
|
|
|
ParameterDeclaration,
|
2019-04-18 09:38:46 -04:00
|
|
|
)(s,n)
|
|
|
|
}
|
|
|
|
|
|
|
|
func ParameterDeclaration(s string, n *Node) (string, *Node) {
|
|
|
|
return ChildOf(NewNode("ParameterDeclaration"),OneOf(
|
|
|
|
NodeNamed("Ellipsis",Lit("...")),
|
2019-04-18 11:22:53 -04:00
|
|
|
Seq(DeclarationSpecifiers,Declarator),
|
|
|
|
Seq(DeclarationSpecifiers,Opt(AbstractDeclarator)),
|
2019-04-18 09:38:46 -04:00
|
|
|
))(s,n)
|
|
|
|
}
|
|
|
|
|
|
|
|
func DeclarationSpecifiers(s string, n *Node) (string, *Node) {
|
|
|
|
return OneOf(
|
2019-04-18 11:22:53 -04:00
|
|
|
Seq(StorageClassSpecifier,Opt(DeclarationSpecifiers)),
|
|
|
|
Seq(TypeSpecifier,Opt(DeclarationSpecifiers)),
|
|
|
|
Seq(StructOrUnionSpecifier,Opt(DeclarationSpecifiers)),
|
|
|
|
Seq(TypeQualifier,Opt(DeclarationSpecifiers)),
|
|
|
|
Seq(TypedefName,Opt(DeclarationSpecifiers)),
|
|
|
|
// Seq(FunctionSpecifier,Opt(DeclarationSpecifiers)),
|
2019-04-18 09:38:46 -04:00
|
|
|
)(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) {
|
2019-04-18 10:21:03 -04:00
|
|
|
return ChildOf(NewNode("Declarator"),
|
2019-04-18 11:22:53 -04:00
|
|
|
Seq(ZeroOrMore(Pointer), DirectDeclarator))(s,n)
|
2019-04-18 09:38:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func DirectDeclarator(s string, n *Node) (string, *Node) {
|
2019-04-18 14:04:01 -04:00
|
|
|
return OneOf(
|
2019-04-18 09:38:46 -04:00
|
|
|
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)
|
|
|
|
}
|
2019-04-26 14:08:43 -04:00
|
|
|
|
2019-04-26 22:44:30 -04:00
|
|
|
func Id(s string, n *Node) (string, *Node) {
|
|
|
|
return Seq(
|
|
|
|
NodeNamed("Id",Lit("id")),
|
|
|
|
Opt(TypeQualifierList),
|
|
|
|
Opt(NullableAnnotation),
|
|
|
|
)(s,n)
|
|
|
|
}
|
|
|
|
|
2019-04-18 09:38:46 -04:00
|
|
|
func Pointer(s string, n *Node) (string, *Node) {
|
2019-04-18 11:22:53 -04:00
|
|
|
return Seq(
|
2019-04-18 09:38:46 -04:00
|
|
|
NodeNamed("Pointer",Lit("*")),
|
|
|
|
Opt(TypeQualifierList),
|
|
|
|
Opt(NullableAnnotation),
|
|
|
|
Opt(Pointer),
|
|
|
|
)(s,n)
|
|
|
|
}
|
|
|
|
|
2019-04-26 14:08:43 -04:00
|
|
|
//FIXME: not sure how correct this is...
|
|
|
|
func Block(s string, n *Node) (string, *Node) {
|
|
|
|
return Seq(
|
|
|
|
NodeNamed("Block",Lit("^")),
|
|
|
|
Opt(NullableAnnotation),
|
|
|
|
)(s,n)
|
|
|
|
}
|
|
|
|
|
2019-04-18 09:38:46 -04:00
|
|
|
func TypeQualifierList(s string, n *Node) (string, *Node) {
|
2019-04-18 11:22:53 -04:00
|
|
|
return OneOrMore(TypeQualifier)(s,n)
|
2019-04-18 09:38:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func SpecifierQualifierList(s string, n *Node) (string, *Node) {
|
|
|
|
return NodeNamed("SpecifierQualifierList",
|
|
|
|
OneOf(
|
2019-04-18 11:22:53 -04:00
|
|
|
Seq(TypeSpecifier,Opt(SpecifierQualifierList)),
|
|
|
|
Seq(StructOrUnionSpecifier,Opt(SpecifierQualifierList)),
|
|
|
|
Seq(TypedefName,Opt(SpecifierQualifierList)),
|
|
|
|
Seq(TypeQualifier,Opt(SpecifierQualifierList)),
|
2019-04-18 09:38:46 -04:00
|
|
|
),
|
|
|
|
)(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,
|
2019-04-29 13:31:13 -04:00
|
|
|
EnumSpecifier,
|
2019-04-18 09:38:46 -04:00
|
|
|
//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) {
|
2019-04-29 13:31:13 -04:00
|
|
|
return OneOf(
|
2019-04-18 11:22:53 -04:00
|
|
|
// Seq(StructOrUnion,Opt(Identifier),StructDeclarationList),
|
|
|
|
Nest(StructOrUnion,Identifier),
|
2019-04-29 13:31:13 -04:00
|
|
|
)(s,n)
|
2019-04-18 09:38:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func StructOrUnion(s string, n *Node) (string, *Node) {
|
|
|
|
return OneOf(
|
|
|
|
NodeNamed("Struct",Word("struct")),
|
|
|
|
NodeNamed("Union",Word("union")))(s,n)
|
|
|
|
}
|
|
|
|
|
2019-04-29 13:31:13 -04:00
|
|
|
func EnumSpecifier(s string, n *Node) (string, *Node) {
|
|
|
|
return Nest(
|
|
|
|
NodeNamed("Enum",Word("enum")),Identifier)(s,n)
|
|
|
|
}
|
|
|
|
|
2019-04-18 09:38:46 -04:00
|
|
|
func Generic(s string, n *Node) (string, *Node) {
|
|
|
|
return NodeNamed("Generic",TypeName)(s,n)
|
|
|
|
}
|
|
|
|
|
|
|
|
func GenericList(s string, n *Node) (string, *Node) {
|
2019-04-18 14:04:01 -04:00
|
|
|
return ChildOf(NewNode("GenericList"),Seq(
|
2019-04-18 09:38:46 -04:00
|
|
|
Generic,
|
2019-04-18 14:04:01 -04:00
|
|
|
ZeroOrMore(Seq(Lit(","),Generic)),
|
|
|
|
))(s,n)
|
2019-04-18 09:38:46 -04:00
|
|
|
}
|
|
|
|
|
2019-04-18 11:22:53 -04:00
|
|
|
func BareTypedefName(s string, n *Node) (string, *Node) {
|
|
|
|
return NodeNamed("TypedefName",Identifier)(s,n)
|
|
|
|
}
|
|
|
|
|
2019-04-18 09:38:46 -04:00
|
|
|
func TypedefName(s string, n *Node) (string, *Node) {
|
2019-05-03 13:14:30 -04:00
|
|
|
return Seq(
|
2019-05-06 13:21:36 -04:00
|
|
|
Opt(NodeNamed("KindQualifier",Lit("__kindof"))),
|
2019-04-18 11:22:53 -04:00
|
|
|
BareTypedefName,
|
2019-05-03 13:14:30 -04:00
|
|
|
Opt(AngBracketed(GenericList)),
|
|
|
|
Opt(NullableAnnotation),
|
2019-04-18 11:22:53 -04:00
|
|
|
)(s,n)
|
2019-04-18 09:38:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|