Syntaktiset esikäsittelijät otettiin käyttöön Lisp-kieliperheessä. Niiden tehtävänä on muuntaa syntaksipuita useiden käyttäjän määrittelemien sääntöjen mukaisesti. Joissakin ohjelmointikielissä säännöt kirjoitetaan samalla kielellä kuin ohjelma (käännösaikainen heijastus). Näin on Lispissä ja OCamlissa. Jotkin muut kielet luottavat täysin ulkoiseen kieleen muunnosten määrittelyssä, kuten XML:n XSLT-esiprosessori tai sen staattisesti tyypitetty vastine CDuce.
Syntaktisia esiprosessoreita käytetään tyypillisesti mukauttamaan kielen syntaksia, laajentamaan kieltä lisäämällä uusia primitiivejä tai sulauttamaan aluespesifinen ohjelmointikieli (DSL, Domain Specific Programming Language) yleiskäyttöisen kielen sisään.
Syntaksin mukauttaminenEdit
Hyvä esimerkki syntaksin mukauttamisesta on kahden eri syntaksin olemassaolo Objective Caml -ohjelmointikielessä. Ohjelmat voidaan kirjoittaa välinpitämättömästi käyttäen ”normaalia syntaksia” tai ”tarkistettua syntaksia”, ja ne voidaan pyydettäessä kaunistella jommallakummalla syntaksilla.
Viisinkertaisesti monet OCaml-kielellä kirjoitetut ohjelmat muokkaavat kielen syntaksia lisäämällä siihen uusia operaattoreita.
Kielen laajentaminenMuokkaa
Parhaat esimerkit kielen laajentamisesta makrojen avulla löytyvät Lisp-kieliperheestä. Vaikka kielet itsessään ovat yksinkertaisia dynaamisesti tyypitettyjä funktionaalisia ytimiä, Scheme- tai Common Lisp -standardijakelut mahdollistavat imperatiivisen tai oliopohjaisen ohjelmoinnin sekä staattisen tyypityksen. Lähes kaikki nämä ominaisuudet on toteutettu syntaktisella esikäsittelyllä, vaikka on syytä huomata, että Lispissä kääntäjä hoitaa kääntämisen ”makrojen laajentamisvaiheen”. Tätä voidaan silti pitää eräänlaisena esikäsittelynä, koska se tapahtuu ennen kääntämisen muita vaiheita.
Kielen erikoistuminenEdit
Yksi Lisp-kieliperheen epätavallisista piirteistä on mahdollisuus käyttää makroja sisäisen DSL:n luomiseen. Tyypillisesti suuressa Lisp-pohjaisessa projektissa moduuli saatetaan kirjoittaa useilla tällaisilla minikielillä, joista yksi ehkä käyttää SQL-pohjaista Lisp-murretta, toinen on kirjoitettu graafisiin käyttöliittymiin tai pretty-printingiin erikoistuneella murteella jne. Common Lispin standardikirjastossa on esimerkkinä tästä syntaktisen abstraktion tasosta LOOP-makro, joka toteuttaa Algolin kaltaisen minikielen monimutkaisen iteroinnin kuvaamiseen, mutta mahdollistaa silti Lispin standardioperaattoreiden käytön.
MetaOCaml-esiprosessori/-kieli tarjoaa samanlaisia ominaisuuksia ulkoisille DSL:ille. Tämä esiprosessori ottaa kielen semantiikan kuvauksen (eli tulkin) ja yhdistämällä käännöksen aikaista tulkintaa ja koodin tuottamista tekee määritelmästä kääntäjän OCaml-ohjelmointikielelle – ja tästä kielestä joko tavukoodiksi tai natiivikoodiksi.