La notion de préprocesseur syntaxique a été introduite avec le langage Lisp. Son rôle est de transformer des arbres de syntaxe en fonction de règles définies par l'utilisateur. Pour certains langages de programmation, ces règles sont écrites dans le même langage que le programme (introspection statique). C'est le cas de Lisp ou d'OCaml. Dans d'autres cas, il s'agit d'un langage externe entièrement, tel que XSLT pour XML, ou de sa contrepartie statiquement typée CDuce.
Les préprocesseurs syntaxiques sont typiquement utilisés pour personnaliser la syntaxe d'un langage, pour étendre un langage avec de nouvelles primitives ou pour transformer un langage de programmation généraliste en un langage spécialisé.
Un bon exemple de personnalisation de syntaxe est l'existence de deux syntaxes distinctes pour le langage OCaml. Un programme peut être écrit indifféremment à l'aide de la « syntaxe normale » ou de la « syntaxe révisée », et peut être réaffiché à la demande dans une syntaxe ou l'autre.
De même, un grand nombre de programmes écrits en OCaml personnalisent la syntaxe du langage pour lui ajouter de nouveaux opérateurs.
Le meilleur exemple d'extension d'un langage à l'aide de macros est Lisp. Alors que les langages de la famille, par eux-mêmes, ne sont que des noyaux fonctionnels minimalistes (moins de 10 instructions) et dynamiquement typés, la distribution standard de Scheme ou de Common Lisp permet la programmation impérative ou orientée objets, ou encore le typage statique. Toutes ces fonctionnalités sont implantées à l'aide du préprocesseur syntaxique.
De la même manière, la gestion d'expressions rationnelles ou la génération de code statiquement vérifiées et fortement typées peuvent être ajoutées à la syntaxe et la sémantique d'OCaml à l'aide de macros, de même que des fibres (ou coroutines, ou générateurs), des monades ou la manipulation transparente d'arbres XML.
Une fonctionnalité inhabituelle de Lisp est la possibilité d'utiliser des macros pour transformer le langage en un langage spécialisé. Typiquement, dans tout projet Lisp suffisamment large, une partie de l'effort est concentré sur l'adaptation du langage lui-même à la tâche visée, et la construction, par exemple, de dialectes pour SQL ou pour l'affichage ou l'interface graphique, etc. D'après des programmeurs Lisp expérimentés, cette fonctionnalité leur permet de diviser par 7 à 20 fois le temps et la longueur du code nécessaire pour achever un projet.
Le préprocesseur MetaOCaml fournit des fonctionnalités similaires pour la conception de langages spécialisés externes. Ce préprocesseur, à partir de la description de la sémantique d'un langage (i.e. un interpréteur), à l'aide d'interprétation durant la compilation et de génération de code, convertit cette description en un compilateur dans le langage Ocaml.