How do compilers parse complex data types names like function pointers. The type has to be somehow put into the AST or it has to be processed during parsing. What are the pros and cons of different methods of parsing complex data types? What methods are most commonly used? These are the ways I could think of:

  • Do type checking in the parser.
  • Use an intermediate structure to represent types in parser.
  • Get every token that is part of the type name and parse it during type checking.

1 Answer 1


This somewhat differs between languages, but mostly solution #2: the parser handles the structure of type names, without handling their semantics.

Type names generally follow a grammar that can be handled by the parser. Then, the AST would contain a sub-tree representing the type syntax. The type checker might later transform this into a different form to facilitate equality checking, e.g. by resolving type aliases. While function pointers might have special syntax, the type checker can treat them equivalently to a parametrized type. E.g. the C function pointer type int (*)() might be handled equivalently to a C++ template invocation _FunctionPointer<int>, and might even be transformed by the parser to such a more generic form. Once fully evaluated, the type may be given a unique name via name mangling.

Unfortunately, the correct parsing of some programming languages depends on whether an identifier is a type or a value. If that is the case, parsing and type checking has to be interleaved. The parser would consume the smallest chunk of input that can be processed independently, then hand if off to the part of the compiler that handles semantics, e.g. the type checker. The type checker in turn updates a dictionary that maps identifiers to their kind, allowing the parser to continue.

  • 1
    In some sense, it is really as simple as: the parser does the parsing, the typer does the typing, the type inferencer does the type inferencing, and the type checker does the type checking. Even in compilers for languages like C++, these separate responsibilities are typically separated into separate phases of the compiler, it's just that instead of a nice linear flow of one phase after another, you have phases "calling ahead" or "calling back" to other phases. Commented Dec 12, 2021 at 13:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.